h264_reader/nal/sei/
buffering_period.rs1use 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 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}