Skip to content

Commit

Permalink
codec/h26x: remove generic parameter for data
Browse files Browse the repository at this point in the history
The data member does not need to be owned - it can simply be borrowed
as a slice. Change that type to remove a generic argument (and introduce
a lifetime), which simplifies the code a bit.
  • Loading branch information
Gnurou committed Oct 3, 2023
1 parent 23746f7 commit d61e3ee
Show file tree
Hide file tree
Showing 13 changed files with 75 additions and 90 deletions.
4 changes: 2 additions & 2 deletions examples/ccdec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,7 @@ fn main() {
let display = libva::Display::open().expect("failed to open libva display");
let (mut decoder, frame_iter) = match args.input_format {
EncodedFormat::H264 => {
let frame_iter = Box::new(NalIterator::<H264Nalu<_>>::new(&input).map(Cow::Borrowed))
let frame_iter = Box::new(NalIterator::<H264Nalu>::new(&input).map(Cow::Borrowed))
as Box<dyn Iterator<Item = Cow<[u8]>>>;

let decoder = Box::new(StatelessDecoder::<H264, _>::new_vaapi(
Expand Down Expand Up @@ -369,7 +369,7 @@ fn main() {
(decoder, frame_iter)
}
EncodedFormat::H265 => {
let frame_iter = Box::new(NalIterator::<H265Nalu<_>>::new(&input).map(Cow::Borrowed))
let frame_iter = Box::new(NalIterator::<H265Nalu>::new(&input).map(Cow::Borrowed))
as Box<dyn Iterator<Item = Cow<[u8]>>>;

let decoder = Box::new(StatelessDecoder::<H265, _>::new_vaapi(
Expand Down
35 changes: 15 additions & 20 deletions src/codec/h264/nalu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,29 +18,28 @@ pub trait Header: Sized {
}

#[derive(Debug)]
pub struct Nalu<T, U> {
pub struct Nalu<'a, U> {
header: U,
/// The mapping that backs this NALU. Possibly shared with the other NALUs
/// in the Access Unit.
data: T,
data: &'a [u8],

size: usize,
offset: usize,
sc_offset: usize,
}

impl<T, U> Nalu<T, U>
impl<'a, U> Nalu<'a, U>
where
T: AsRef<[u8]> + Clone,
U: Debug + Header,
{
/// Find the next Annex B encoded NAL unit.
pub fn next(cursor: &mut Cursor<T>) -> anyhow::Result<Nalu<T, U>> {
pub fn next(cursor: &mut Cursor<&'a [u8]>) -> anyhow::Result<Nalu<'a, U>> {
let bitstream = cursor.clone().into_inner();
let pos = usize::try_from(cursor.position())?;

// Find the start code for this NALU
let current_nalu_offset = match Nalu::<T, U>::find_start_code(cursor, pos) {
let current_nalu_offset = match Nalu::<'a, U>::find_start_code(cursor, pos) {
Some(offset) => offset,
None => return Err(anyhow!("No NAL found")),
};
Expand All @@ -49,7 +48,7 @@ where

// If the preceding byte is 00, then we actually have a four byte SC,
// i.e. 00 00 00 01 Where the first 00 is the "zero_byte()"
if start_code_offset > 0 && cursor.get_ref().as_ref()[start_code_offset - 1] == 00 {
if start_code_offset > 0 && cursor.get_ref()[start_code_offset - 1] == 00 {
start_code_offset -= 1;
}

Expand All @@ -62,14 +61,12 @@ where
let hdr = U::parse(cursor)?;

// Find the start of the subsequent NALU.
let mut next_nalu_offset = match Nalu::<T, U>::find_start_code(cursor, nalu_offset) {
let mut next_nalu_offset = match Nalu::<'a, U>::find_start_code(cursor, nalu_offset) {
Some(offset) => offset,
None => cursor.chunk().len(), // Whatever data is left must be part of the current NALU
};

while next_nalu_offset > 0
&& cursor.get_ref().as_ref()[nalu_offset + next_nalu_offset - 1] == 00
{
while next_nalu_offset > 0 && cursor.get_ref()[nalu_offset + next_nalu_offset - 1] == 00 {
// Discard trailing_zero_8bits
next_nalu_offset -= 1;
}
Expand All @@ -91,14 +88,13 @@ where
}
}

impl<T, U> Nalu<T, U>
impl<'a, U> Nalu<'a, U>
where
T: AsRef<[u8]>,
U: Debug,
{
fn find_start_code(data: &mut Cursor<T>, offset: usize) -> Option<usize> {
fn find_start_code(data: &mut Cursor<&'a [u8]>, offset: usize) -> Option<usize> {
// discard all zeroes until the start code pattern is found
data.get_ref().as_ref()[offset..]
data.get_ref()[offset..]
.windows(3)
.position(|window| window == [0x00, 0x00, 0x01])
}
Expand All @@ -109,8 +105,8 @@ where
}

/// Get a reference to the nalu's data.
pub fn data(&self) -> &T {
&self.data
pub fn data(&self) -> &'a [u8] {
self.data
}

/// Get a reference to the nalu's size.
Expand All @@ -129,9 +125,8 @@ where
}
}

impl<T: AsRef<[u8]>, U> AsRef<[u8]> for Nalu<T, U> {
impl<'a, U> AsRef<[u8]> for Nalu<'a, U> {
fn as_ref(&self) -> &[u8] {
let data = self.data.as_ref();
&data[self.offset..self.offset + self.size]
&self.data[self.offset..self.offset + self.size]
}
}
22 changes: 11 additions & 11 deletions src/codec/h264/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use crate::codec::h264::nalu::Header;
use crate::codec::h264::nalu_reader::NaluReader;
use crate::codec::h264::picture::Field;

pub type Nalu<T> = nalu::Nalu<T, NaluHeader>;
pub type Nalu<'a> = nalu::Nalu<'a, NaluHeader>;

const DEFAULT_4X4_INTRA: [u8; 16] = [
6, 13, 13, 20, 20, 20, 28, 28, 28, 28, 32, 32, 32, 37, 37, 42,
Expand Down Expand Up @@ -409,21 +409,21 @@ impl SliceHeader {

/// A H264 slice. An integer number of macroblocks or macroblock pairs ordered
/// consecutively in the raster scan within a particular slice group
pub struct Slice<T> {
pub struct Slice<'a> {
/// The slice header.
header: SliceHeader,
/// The NAL unit backing this slice.
nalu: Nalu<T>,
nalu: Nalu<'a>,
}

impl<T> Slice<T> {
impl<'a> Slice<'a> {
/// Get a reference to the slice's header.
pub fn header(&self) -> &SliceHeader {
&self.header
}

/// Get a reference to the slice's nalu.
pub fn nalu(&self) -> &Nalu<T> {
pub fn nalu(&self) -> &Nalu<'a> {
&self.nalu
}
}
Expand Down Expand Up @@ -1787,7 +1787,7 @@ impl Parser {
/// Parse a SPS and add it to the list of active SPSes.
///
/// Returns a reference to the new SPS.
pub fn parse_sps<T: AsRef<[u8]>>(&mut self, nalu: &Nalu<T>) -> anyhow::Result<&Rc<Sps>> {
pub fn parse_sps(&mut self, nalu: &Nalu) -> anyhow::Result<&Rc<Sps>> {
if !matches!(nalu.header().type_, NaluType::Sps) {
return Err(anyhow!(
"Invalid NALU type, expected {:?}, got {:?}",
Expand Down Expand Up @@ -1956,7 +1956,7 @@ impl Parser {
Ok(self.get_sps(key).unwrap())
}

pub fn parse_pps<T: AsRef<[u8]>>(&mut self, nalu: &Nalu<T>) -> anyhow::Result<&Pps> {
pub fn parse_pps(&mut self, nalu: &Nalu) -> anyhow::Result<&Pps> {
if !matches!(nalu.header().type_, NaluType::Pps) {
return Err(anyhow!(
"Invalid NALU type, expected {:?}, got {:?}",
Expand Down Expand Up @@ -2215,9 +2215,9 @@ impl Parser {
Ok(())
}

fn parse_dec_ref_pic_marking<U: AsRef<[u8]>>(
fn parse_dec_ref_pic_marking(
r: &mut NaluReader,
nalu: &Nalu<U>,
nalu: &Nalu,
header: &mut SliceHeader,
) -> anyhow::Result<()> {
let rpm = &mut header.dec_ref_pic_marking;
Expand Down Expand Up @@ -2263,7 +2263,7 @@ impl Parser {
Ok(())
}

pub fn parse_slice_header<T: AsRef<[u8]>>(&self, nalu: Nalu<T>) -> anyhow::Result<Slice<T>> {
pub fn parse_slice_header<'a>(&self, nalu: Nalu<'a>) -> anyhow::Result<Slice<'a>> {
if !matches!(
nalu.header().type_,
NaluType::Slice
Expand Down Expand Up @@ -2838,7 +2838,7 @@ mod tests {
0x00, 0x00, 0x01, 0x07, 0x00, 0x00, 0x0a, 0xfb, 0xb0, 0x32, 0xc0, 0xca, 0x80,
];

let mut cursor = Cursor::new(invalid_sps);
let mut cursor = Cursor::new(invalid_sps.as_ref());
let mut parser = Parser::default();

while let Ok(nalu) = Nalu::next(&mut cursor) {
Expand Down
2 changes: 1 addition & 1 deletion src/codec/h264/picture.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ impl PictureData {
}
}

pub fn new_from_slice(slice: &Slice<&[u8]>, sps: &Sps, timestamp: u64) -> Self {
pub fn new_from_slice(slice: &Slice, sps: &Sps, timestamp: u64) -> Self {
let hdr = slice.header();
let nalu_hdr = slice.nalu().header();

Expand Down
46 changes: 20 additions & 26 deletions src/codec/h265/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ impl Header for NaluHeader {
}
}

pub type Nalu<T> = nalu::Nalu<T, NaluHeader>;
pub type Nalu<'a> = nalu::Nalu<'a, NaluHeader>;

/// H265 levels as defined by table A.8.
/// `general_level_idc` and `sub_layer_level_idc[ OpTid ]` shall be set equal to a
Expand Down Expand Up @@ -2970,21 +2970,21 @@ impl Default for SliceHeader {

/// A H265 slice. An integer number of macroblocks or macroblock pairs ordered
/// consecutively in the raster scan within a particular slice group
pub struct Slice<T> {
pub struct Slice<'a> {
/// The slice header.
header: SliceHeader,
/// The NAL unit backing this slice.
nalu: Nalu<T>,
nalu: Nalu<'a>,
}

impl<T> Slice<T> {
impl<'a> Slice<'a> {
/// Get a reference to the slice's header.
pub fn header(&self) -> &SliceHeader {
&self.header
}

/// Get a reference to the slice's nalu.
pub fn nalu(&self) -> &Nalu<T> {
pub fn nalu(&self) -> &Nalu {
&self.nalu
}

Expand Down Expand Up @@ -3666,7 +3666,7 @@ pub struct Parser {

impl Parser {
/// Parse a VPS NALU.
pub fn parse_vps<T: AsRef<[u8]>>(&mut self, nalu: &Nalu<T>) -> anyhow::Result<&Vps> {
pub fn parse_vps(&mut self, nalu: &Nalu) -> anyhow::Result<&Vps> {
if !matches!(nalu.header().type_, NaluType::VpsNut) {
return Err(anyhow!(
"Invalid NALU type, expected {:?}, got {:?}",
Expand Down Expand Up @@ -4535,7 +4535,7 @@ impl Parser {
}

/// Parse a SPS NALU.
pub fn parse_sps<T: AsRef<[u8]>>(&mut self, nalu: &Nalu<T>) -> anyhow::Result<&Sps> {
pub fn parse_sps(&mut self, nalu: &Nalu) -> anyhow::Result<&Sps> {
if !matches!(nalu.header().type_, NaluType::SpsNut) {
return Err(anyhow!(
"Invalid NALU type, expected {:?}, got {:?}",
Expand Down Expand Up @@ -4832,7 +4832,7 @@ impl Parser {
}

/// Parse a PPS NALU.
pub fn parse_pps<T: AsRef<[u8]>>(&mut self, nalu: &Nalu<T>) -> anyhow::Result<&Pps> {
pub fn parse_pps(&mut self, nalu: &Nalu) -> anyhow::Result<&Pps> {
if !matches!(nalu.header().type_, NaluType::PpsNut) {
return Err(anyhow!(
"Invalid NALU type, expected {:?}, got {:?}",
Expand Down Expand Up @@ -5155,10 +5155,7 @@ impl Parser {
}

/// Parses a slice header from a slice NALU.
pub fn parse_slice_header<T: AsRef<[u8]>>(
&mut self,
nalu: Nalu<T>,
) -> anyhow::Result<Slice<T>> {
pub fn parse_slice_header<'a>(&mut self, nalu: Nalu<'a>) -> anyhow::Result<Slice<'a>> {
if !matches!(
nalu.header().type_,
NaluType::TrailN
Expand Down Expand Up @@ -5611,10 +5608,7 @@ mod tests {
const STREAM_TEST_25_FPS_SLICE_1: &[u8] =
include_bytes!("test_data/test-25fps-h265-slice-data-1.bin");

fn dispatch_parse_call(
parser: &mut Parser,
nalu: Nalu<&[u8], NaluHeader>,
) -> anyhow::Result<()> {
fn dispatch_parse_call(parser: &mut Parser, nalu: Nalu<NaluHeader>) -> anyhow::Result<()> {
match nalu.header().type_ {
NaluType::TrailN
| NaluType::TrailR
Expand Down Expand Up @@ -5652,9 +5646,9 @@ mod tests {
bitstream: &[u8],
nalu_type: NaluType,
mut nskip: i32,
) -> Option<Nalu<&[u8], NaluHeader>> {
) -> Option<Nalu<NaluHeader>> {
let mut cursor = Cursor::new(bitstream);
while let Ok(nalu) = Nalu::<_, NaluHeader>::next(&mut cursor) {
while let Ok(nalu) = Nalu::<NaluHeader>::next(&mut cursor) {
if nalu.header().type_ == nalu_type {
if nskip == 0 {
return Some(nalu);
Expand All @@ -5672,23 +5666,23 @@ mod tests {
fn parse_nalus_from_stream_file() {
let mut cursor = Cursor::new(STREAM_BEAR);
let mut num_nalus = 0;
while Nalu::<_, NaluHeader>::next(&mut cursor).is_ok() {
while Nalu::<NaluHeader>::next(&mut cursor).is_ok() {
num_nalus += 1;
}

assert_eq!(num_nalus, STREAM_BEAR_NUM_NALUS);

let mut cursor = Cursor::new(STREAM_BBB);
let mut num_nalus = 0;
while Nalu::<_, NaluHeader>::next(&mut cursor).is_ok() {
while Nalu::<NaluHeader>::next(&mut cursor).is_ok() {
num_nalus += 1;
}

assert_eq!(num_nalus, STREAM_BBB_NUM_NALUS);

let mut cursor = Cursor::new(STREAM_TEST25FPS);
let mut num_nalus = 0;
while Nalu::<_, NaluHeader>::next(&mut cursor).is_ok() {
while Nalu::<NaluHeader>::next(&mut cursor).is_ok() {
num_nalus += 1;
}

Expand All @@ -5702,21 +5696,21 @@ mod tests {
let mut cursor = Cursor::new(STREAM_BBB);
let mut parser = Parser::default();

while let Ok(nalu) = Nalu::<_, NaluHeader>::next(&mut cursor) {
while let Ok(nalu) = Nalu::<NaluHeader>::next(&mut cursor) {
dispatch_parse_call(&mut parser, nalu).unwrap();
}

let mut cursor = Cursor::new(STREAM_BEAR);
let mut parser = Parser::default();

while let Ok(nalu) = Nalu::<_, NaluHeader>::next(&mut cursor) {
while let Ok(nalu) = Nalu::<NaluHeader>::next(&mut cursor) {
dispatch_parse_call(&mut parser, nalu).unwrap();
}

let mut cursor = Cursor::new(STREAM_TEST25FPS);
let mut parser = Parser::default();

while let Ok(nalu) = Nalu::<_, NaluHeader>::next(&mut cursor) {
while let Ok(nalu) = Nalu::<NaluHeader>::next(&mut cursor) {
dispatch_parse_call(&mut parser, nalu).unwrap();
}
}
Expand All @@ -5727,7 +5721,7 @@ mod tests {
let mut cursor = Cursor::new(STREAM_BEAR);
let mut parser = Parser::default();

let vps_nalu = Nalu::<_, NaluHeader>::next(&mut cursor).unwrap();
let vps_nalu = Nalu::<NaluHeader>::next(&mut cursor).unwrap();
let vps = parser.parse_vps(&vps_nalu).unwrap();

assert!(vps.base_layer_internal_flag);
Expand Down Expand Up @@ -5924,7 +5918,7 @@ mod tests {
let mut cursor = Cursor::new(STREAM_TEST25FPS);
let mut parser = Parser::default();

let vps_nalu = Nalu::<_, NaluHeader>::next(&mut cursor).unwrap();
let vps_nalu = Nalu::<NaluHeader>::next(&mut cursor).unwrap();
let vps = parser.parse_vps(&vps_nalu).unwrap();
assert!(vps.base_layer_internal_flag);
assert!(vps.base_layer_available_flag);
Expand Down
2 changes: 1 addition & 1 deletion src/codec/h265/picture.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ impl PictureData {
/// This will also call the picture order count process (clause 8.3.1) to
/// correctly initialize the POC values.
pub fn new_from_slice(
slice: &Slice<&[u8]>,
slice: &Slice,
pps: &Pps,
first_picture_in_bitstream: bool,
first_picture_after_eos: bool,
Expand Down
Loading

0 comments on commit d61e3ee

Please sign in to comment.