Skip to content

Commit 11dde34

Browse files
committed
Add support for parsing access_unit_delimiter_rbsp()
1 parent 9237745 commit 11dde34

File tree

5 files changed

+132
-1
lines changed

5 files changed

+132
-1
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
* Add `Profile::CavlcIntra444` (profile_idc 44) and `Profile::MFCHigh` (profile_idc 134) enum variants.
1414
* Parse AvcC extension fields (`chroma_format`, `bit_depth_luma_minus8`, `bit_depth_chroma_minus8`, SPS extension NAL units) for High profile and above.
1515
* Add `slice_group_change_cycle`, `slice_alpha_c0_offset_div2` and `slice_beta_offset_div2 to `SliceHeader`
16+
* Parse `access_unit_delimiter_rbsp()` (NAL type 9) via new `aud::AccessUnitDelimiter`.
1617
* Parse `seq_parameter_set_extension_rbsp()` (NAL type 13) via new `sps_extension::SeqParameterSetExtension`.
1718
* Parse `subset_seq_parameter_set_rbsp()` (NAL type 15) via new `subset_sps::SubsetSps`, including SVC extension (profiles 83/86) and MVC extension (profiles 118/128/134).
1819
* Add `Context::put_subset_seq_param_set()`, `Context::subset_sps_by_id()`, and `Context::subset_sps()` for managing subset SPS state.

examples/dump.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use h264_reader::annexb::AnnexBReader;
2+
use h264_reader::nal::aud::AccessUnitDelimiter;
23
use h264_reader::nal::pps::PicParameterSet;
34
use h264_reader::nal::sei::buffering_period::BufferingPeriod;
45
use h264_reader::nal::sei::pic_timing::PicTiming;
@@ -128,6 +129,12 @@ fn main() {
128129
}
129130
}
130131
}
132+
UnitType::AccessUnitDelimiter => {
133+
match AccessUnitDelimiter::from_bits(nal.rbsp_bits()) {
134+
Ok(aud) => println!("{:#?}", aud),
135+
Err(e) => println!("AUD error: {:?}", e),
136+
}
137+
}
131138
UnitType::SeqParameterSetExtension => {
132139
hex_dump(&nal);
133140
match SeqParameterSetExtension::from_bits(nal.rbsp_bits()) {

fuzz/fuzz_targets/fuzz_target_1.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
use libfuzzer_sys::fuzz_target;
33
use h264_reader::annexb::AnnexBReader;
44
use h264_reader::Context;
5-
use h264_reader::nal::{Nal, RefNal, UnitType, pps, slice, sei, sps, sps_extension, subset_sps};
5+
use h264_reader::nal::{Nal, RefNal, UnitType, aud, pps, slice, sei, sps, sps_extension, subset_sps};
66
use h264_reader::push::NalInterest;
77

88
fuzz_target!(|data: &[u8]| {
@@ -45,6 +45,9 @@ fuzz_target!(|data: &[u8]| {
4545
UnitType::SliceLayerWithoutPartitioningIdr | UnitType::SliceLayerWithoutPartitioningNonIdr => {
4646
let _ = slice::SliceHeader::from_bits(&ctx, &mut nal.rbsp_bits(), hdr);
4747
},
48+
UnitType::AccessUnitDelimiter => {
49+
let _ = aud::AccessUnitDelimiter::from_bits(nal.rbsp_bits());
50+
},
4851
UnitType::SeqParameterSetExtension => {
4952
let _ = sps_extension::SeqParameterSetExtension::from_bits(nal.rbsp_bits());
5053
},

src/nal/aud.rs

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
//! Parser for `access_unit_delimiter_rbsp()` (NAL type 9, spec 7.3.2.4).
2+
3+
use crate::rbsp::BitRead;
4+
use std::fmt;
5+
6+
/// Indicates which slice types may be present in the primary coded picture
7+
/// of the access unit (Table 7-5).
8+
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
9+
pub enum PrimaryPicType {
10+
/// I slices only
11+
I = 0,
12+
/// I, P slices
13+
IP = 1,
14+
/// I, P, B slices
15+
IPB = 2,
16+
/// SI slices only
17+
SI = 3,
18+
/// SI, SP slices
19+
SISP = 4,
20+
/// I, SI slices
21+
ISI = 5,
22+
/// I, SI, P, SP slices
23+
ISIPSP = 6,
24+
/// I, SI, P, SP, B slices
25+
ISIPSPB = 7,
26+
}
27+
28+
/// Error returned when a `primary_pic_type` value is out of range.
29+
#[derive(Debug)]
30+
pub struct PrimaryPicTypeError(pub u8);
31+
32+
impl fmt::Display for PrimaryPicTypeError {
33+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
34+
write!(f, "invalid primary_pic_type value: {}", self.0)
35+
}
36+
}
37+
38+
impl PrimaryPicType {
39+
pub fn from_id(id: u8) -> Result<PrimaryPicType, PrimaryPicTypeError> {
40+
match id {
41+
0 => Ok(PrimaryPicType::I),
42+
1 => Ok(PrimaryPicType::IP),
43+
2 => Ok(PrimaryPicType::IPB),
44+
3 => Ok(PrimaryPicType::SI),
45+
4 => Ok(PrimaryPicType::SISP),
46+
5 => Ok(PrimaryPicType::ISI),
47+
6 => Ok(PrimaryPicType::ISIPSP),
48+
7 => Ok(PrimaryPicType::ISIPSPB),
49+
_ => Err(PrimaryPicTypeError(id)),
50+
}
51+
}
52+
53+
pub fn id(self) -> u8 {
54+
self as u8
55+
}
56+
}
57+
58+
/// Parsed `access_unit_delimiter_rbsp()` (NAL unit type 9).
59+
#[derive(Clone, Debug, PartialEq, Eq)]
60+
pub struct AccessUnitDelimiter {
61+
pub primary_pic_type: PrimaryPicType,
62+
}
63+
64+
impl AccessUnitDelimiter {
65+
pub fn from_bits<R: BitRead>(mut r: R) -> Result<AccessUnitDelimiter, AudError> {
66+
let val: u8 = r.read(3, "primary_pic_type")?;
67+
let primary_pic_type =
68+
PrimaryPicType::from_id(val).map_err(AudError::InvalidPrimaryPicType)?;
69+
r.finish_rbsp()?;
70+
Ok(AccessUnitDelimiter { primary_pic_type })
71+
}
72+
}
73+
74+
/// Error type for AUD parsing.
75+
#[derive(Debug)]
76+
pub enum AudError {
77+
InvalidPrimaryPicType(PrimaryPicTypeError),
78+
RbspError(crate::rbsp::BitReaderError),
79+
}
80+
81+
impl From<crate::rbsp::BitReaderError> for AudError {
82+
fn from(e: crate::rbsp::BitReaderError) -> Self {
83+
AudError::RbspError(e)
84+
}
85+
}
86+
87+
impl fmt::Display for AudError {
88+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
89+
match self {
90+
AudError::InvalidPrimaryPicType(e) => write!(f, "{}", e),
91+
AudError::RbspError(e) => write!(f, "{:?}", e),
92+
}
93+
}
94+
}
95+
96+
#[cfg(test)]
97+
mod test {
98+
use super::*;
99+
use crate::rbsp::BitReader;
100+
101+
#[test]
102+
fn parse_all_pic_types() {
103+
for id in 0u8..=7 {
104+
// primary_pic_type(3 bits) + rbsp_stop_one_bit(1) + padding(4 zeros)
105+
let byte = (id << 5) | 0x10;
106+
let data = [byte];
107+
let aud = AccessUnitDelimiter::from_bits(BitReader::new(&data[..])).unwrap();
108+
assert_eq!(aud.primary_pic_type.id(), id);
109+
}
110+
}
111+
112+
#[test]
113+
fn parse_ipb() {
114+
// primary_pic_type=2 (IPB): 010 1 0000 = 0x50
115+
let data = [0x50u8];
116+
let aud = AccessUnitDelimiter::from_bits(BitReader::new(&data[..])).unwrap();
117+
assert_eq!(aud.primary_pic_type, PrimaryPicType::IPB);
118+
}
119+
}

src/nal/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
//! [`RbspDecoder`](../rbsp/struct.RbspDecoder.html)), where it has been encoded with
55
//! 'emulation prevention bytes'.
66
7+
pub mod aud;
78
pub mod pps;
89
pub mod sei;
910
pub mod slice;

0 commit comments

Comments
 (0)