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(length, "initial_cpb_removal_delay")?,
40 initial_cpb_removal_delay_offset: r.read(length, "initial_cpb_removal_delay_offset")?,
41 });
42 }
43 Ok(res)
44}
45
46#[derive(Debug, Eq, PartialEq)]
47pub struct BufferingPeriod {
48 nal_hrd_bp: Option<Vec<InitialCpbRemoval>>,
49 vcl_hrd_bp: Option<Vec<InitialCpbRemoval>>,
50}
51impl BufferingPeriod {
52 pub fn read(
53 ctx: &Context,
54 msg: &SeiMessage<'_>,
55 ) -> Result<BufferingPeriod, BufferingPeriodError> {
56 assert_eq!(msg.payload_type, HeaderType::BufferingPeriod);
57 let mut r = crate::rbsp::BitReader::new(msg.payload);
58 let seq_parameter_set_id =
59 sps::SeqParamSetId::from_u32(r.read_ue("seq_parameter_set_id")?)?;
60 let sps = ctx
61 .sps_by_id(seq_parameter_set_id)
62 .ok_or_else(|| BufferingPeriodError::UndefinedSeqParamSetId(seq_parameter_set_id))?;
63 let vui = sps.vui_parameters.as_ref();
64 let mut read = |p: &sps::HrdParameters| {
65 read_cpb_removal_delay_list(
66 &mut r,
67 p.cpb_specs.len(),
68 u32::from(p.initial_cpb_removal_delay_length_minus1) + 1,
69 )
70 };
71 let nal_hrd_bp = vui
72 .and_then(|v| v.nal_hrd_parameters.as_ref())
73 .map(&mut read)
74 .transpose()?;
75 let vcl_hrd_bp = vui
76 .and_then(|v| v.vcl_hrd_parameters.as_ref())
77 .map(&mut read)
78 .transpose()?;
79 r.finish_sei_payload()?;
80 Ok(BufferingPeriod {
81 nal_hrd_bp,
82 vcl_hrd_bp,
83 })
84 }
85}
86
87#[cfg(test)]
88mod test {
89 use hex_literal::hex;
90
91 use crate::rbsp;
92
93 use super::*;
94
95 #[test]
96 fn parse() {
97 let mut ctx = Context::default();
100 let sps_rbsp = hex!(
101 "
102 4d 60 15 8d 8d 28 58 9d 08 00 00 0f a0 00 07 53
103 07 00 00 00 92 7c 00 00 12 4f 80 fb dc 18 00 00
104 0f 42 40 00 07 a1 20 7d ee 07 c6 0c 62 60
105 "
106 );
107 ctx.put_seq_param_set(
108 sps::SeqParameterSet::from_bits(rbsp::BitReader::new(&sps_rbsp[..])).unwrap(),
109 );
110
111 let msg = SeiMessage {
112 payload_type: HeaderType::BufferingPeriod,
113 payload: &hex!("d7 e4 00 00 57 e4 00 00 40")[..],
114 };
115 assert_eq!(
116 BufferingPeriod::read(&ctx, &msg).unwrap(),
117 BufferingPeriod {
118 nal_hrd_bp: Some(vec![InitialCpbRemoval {
119 initial_cpb_removal_delay: 45_000,
120 initial_cpb_removal_delay_offset: 0,
121 },]),
122 vcl_hrd_bp: Some(vec![InitialCpbRemoval {
123 initial_cpb_removal_delay: 45_000,
124 initial_cpb_removal_delay_offset: 0,
125 },]),
126 }
127 );
128 }
129}