Skip to main content

h264_reader/nal/sei/
buffering_period.rs

1use super::SeiMessage;
2use crate::nal::sei::HeaderType;
3use crate::nal::sps;
4use crate::rbsp::BitRead;
5use crate::rbsp::BitReaderError;
6use crate::Context;
7
8#[derive(Debug)]
9pub enum BufferingPeriodError {
10    ReaderError(BitReaderError),
11    UndefinedSeqParamSetId(sps::SeqParamSetId),
12    InvalidSeqParamSetId(sps::SeqParamSetIdError),
13}
14impl From<BitReaderError> for BufferingPeriodError {
15    fn from(e: BitReaderError) -> Self {
16        BufferingPeriodError::ReaderError(e)
17    }
18}
19impl From<sps::SeqParamSetIdError> for BufferingPeriodError {
20    fn from(e: sps::SeqParamSetIdError) -> Self {
21        BufferingPeriodError::InvalidSeqParamSetId(e)
22    }
23}
24
25#[derive(Debug, Eq, PartialEq)]
26struct InitialCpbRemoval {
27    initial_cpb_removal_delay: u32,
28    initial_cpb_removal_delay_offset: u32,
29}
30
31fn read_cpb_removal_delay_list<R: BitRead>(
32    r: &mut R,
33    count: usize,
34    length: u32,
35) -> Result<Vec<InitialCpbRemoval>, BitReaderError> {
36    let mut res = vec![];
37    for _ in 0..count {
38        res.push(InitialCpbRemoval {
39            initial_cpb_removal_delay: r.read_var(length, "initial_cpb_removal_delay")?,
40            initial_cpb_removal_delay_offset: r
41                .read_var(length, "initial_cpb_removal_delay_offset")?,
42        });
43    }
44    Ok(res)
45}
46
47#[derive(Debug, Eq, PartialEq)]
48pub struct BufferingPeriod {
49    nal_hrd_bp: Option<Vec<InitialCpbRemoval>>,
50    vcl_hrd_bp: Option<Vec<InitialCpbRemoval>>,
51}
52impl BufferingPeriod {
53    pub fn read(
54        ctx: &Context,
55        msg: &SeiMessage<'_>,
56    ) -> Result<BufferingPeriod, BufferingPeriodError> {
57        assert_eq!(msg.payload_type, HeaderType::BufferingPeriod);
58        let mut r = crate::rbsp::BitReader::new(msg.payload);
59        let seq_parameter_set_id =
60            sps::SeqParamSetId::from_u32(r.read_ue("seq_parameter_set_id")?)?;
61        let sps = ctx
62            .sps_by_id(seq_parameter_set_id)
63            .ok_or_else(|| BufferingPeriodError::UndefinedSeqParamSetId(seq_parameter_set_id))?;
64        let vui = sps.vui_parameters.as_ref();
65        let mut read = |p: &sps::HrdParameters| {
66            read_cpb_removal_delay_list(
67                &mut r,
68                p.cpb_specs.len(),
69                u32::from(p.initial_cpb_removal_delay_length_minus1) + 1,
70            )
71        };
72        let nal_hrd_bp = vui
73            .and_then(|v| v.nal_hrd_parameters.as_ref())
74            .map(&mut read)
75            .transpose()?;
76        let vcl_hrd_bp = vui
77            .and_then(|v| v.vcl_hrd_parameters.as_ref())
78            .map(&mut read)
79            .transpose()?;
80        r.finish_sei_payload()?;
81        Ok(BufferingPeriod {
82            nal_hrd_bp,
83            vcl_hrd_bp,
84        })
85    }
86}
87
88#[cfg(test)]
89mod test {
90    use hex_literal::hex;
91
92    use crate::rbsp;
93
94    use super::*;
95
96    #[test]
97    fn parse() {
98        // https://standards.iso.org/ittf/PubliclyAvailableStandards/ISO_IEC_14496-4_2004_Amd_6_2005_Bitstreams/
99        // This example taken from CVSEFDFT3_Sony_E.zip.
100        let mut ctx = Context::default();
101        let sps_rbsp = hex!(
102            "
103            4d 60 15 8d 8d 28 58 9d 08 00 00 0f a0 00 07 53
104            07 00 00 00 92 7c 00 00 12 4f 80 fb dc 18 00 00
105            0f 42 40 00 07 a1 20 7d ee 07 c6 0c 62 60
106        "
107        );
108        ctx.put_seq_param_set(
109            sps::SeqParameterSet::from_bits(rbsp::BitReader::new(&sps_rbsp[..])).unwrap(),
110        );
111
112        let msg = SeiMessage {
113            payload_type: HeaderType::BufferingPeriod,
114            payload: &hex!("d7 e4 00 00 57 e4 00 00 40")[..],
115        };
116        assert_eq!(
117            BufferingPeriod::read(&ctx, &msg).unwrap(),
118            BufferingPeriod {
119                nal_hrd_bp: Some(vec![InitialCpbRemoval {
120                    initial_cpb_removal_delay: 45_000,
121                    initial_cpb_removal_delay_offset: 0,
122                },]),
123                vcl_hrd_bp: Some(vec![InitialCpbRemoval {
124                    initial_cpb_removal_delay: 45_000,
125                    initial_cpb_removal_delay_offset: 0,
126                },]),
127            }
128        );
129    }
130}