scuffle_h265/sps/vui_parameters/
hrd_parameters.rs

1use std::io;
2
3use byteorder::ReadBytesExt;
4use scuffle_bytes_util::BitReader;
5use scuffle_expgolomb::BitReaderExpGolombExt;
6
7use crate::range_check::range_check;
8
9/// HRD parameters.
10///
11/// `hrd_parameters(commonInfPresentFlag, maxNumSubLayersMinus1)`
12///
13/// - ISO/IEC 23008-2 - E.2.2
14/// - ISO/IEC 23008-2 - E.3.2
15#[derive(Debug, Clone, PartialEq)]
16pub struct HrdParameters {
17    /// HRD parameters information unrelated to sub-layers.
18    pub common_inf: CommonInf,
19    /// Sub-layer HRD parameters.
20    pub sub_layers: Vec<HrdParametersSubLayer>,
21}
22
23impl HrdParameters {
24    pub(crate) fn parse<R: io::Read>(
25        bit_reader: &mut BitReader<R>,
26        common_inf_present_flag: bool,
27        max_num_sub_layers_minus1: u8,
28    ) -> io::Result<Self> {
29        let mut common_inf = CommonInf::default();
30
31        let mut nal_hrd_parameters_present_flag = false;
32        let mut vcl_hrd_parameters_present_flag = false;
33
34        if common_inf_present_flag {
35            nal_hrd_parameters_present_flag = bit_reader.read_bit()?;
36            vcl_hrd_parameters_present_flag = bit_reader.read_bit()?;
37
38            if nal_hrd_parameters_present_flag || vcl_hrd_parameters_present_flag {
39                let sub_pic_hrd_params_present_flag = bit_reader.read_bit()?;
40                if sub_pic_hrd_params_present_flag {
41                    let tick_divisor_minus2 = bit_reader.read_u8()?;
42                    let du_cpb_removal_delay_increment_length_minus1 = bit_reader.read_bits(5)? as u8;
43                    let sub_pic_cpb_params_in_pic_timing_sei_flag = bit_reader.read_bit()?;
44                    let dpb_output_delay_du_length_minus1 = bit_reader.read_bits(5)? as u8;
45
46                    common_inf.sub_pic_hrd_params = Some(SubPicHrdParams {
47                        tick_divisor_minus2,
48                        du_cpb_removal_delay_increment_length_minus1,
49                        sub_pic_cpb_params_in_pic_timing_sei_flag,
50                        dpb_output_delay_du_length_minus1,
51                        cpb_size_du_scale: 0, // replaced below
52                    });
53                }
54
55                common_inf.bit_rate_scale = Some(bit_reader.read_bits(4)? as u8);
56                common_inf.cpb_size_scale = Some(bit_reader.read_bits(4)? as u8);
57
58                if sub_pic_hrd_params_present_flag {
59                    let cpb_size_du_scale = bit_reader.read_bits(4)? as u8;
60
61                    // set the cpb_size_du_scale in sub_pic_hrd_params
62                    if let Some(ref mut sub_pic_hrd_params) = common_inf.sub_pic_hrd_params {
63                        sub_pic_hrd_params.cpb_size_du_scale = cpb_size_du_scale;
64                    }
65                }
66
67                common_inf.initial_cpb_removal_delay_length_minus1 = bit_reader.read_bits(5)? as u8;
68                common_inf.au_cpb_removal_delay_length_minus1 = bit_reader.read_bits(5)? as u8;
69                common_inf.dpb_output_delay_length_minus1 = bit_reader.read_bits(5)? as u8;
70            }
71        }
72
73        let mut sub_layers = Vec::with_capacity(max_num_sub_layers_minus1 as usize + 1);
74
75        for _ in 0..=max_num_sub_layers_minus1 {
76            sub_layers.push(HrdParametersSubLayer::parse(
77                bit_reader,
78                common_inf.sub_pic_hrd_params.is_some(),
79                nal_hrd_parameters_present_flag,
80                vcl_hrd_parameters_present_flag,
81            )?);
82        }
83
84        Ok(HrdParameters { common_inf, sub_layers })
85    }
86}
87
88/// Directly part of [`HrdParameters`].
89#[derive(Debug, Clone, PartialEq)]
90pub struct CommonInf {
91    /// Sub-picture HRD parameters, if `sub_pic_hrd_params_present_flag` is `true`.
92    pub sub_pic_hrd_params: Option<SubPicHrdParams>,
93    /// Specifies (together with [`bit_rate_value_minus1[i]`](SubLayerHrdParameters::bit_rate_value_minus1)) the maximum
94    /// input bit rate of the i-th CPB.
95    pub bit_rate_scale: Option<u8>,
96    /// Specifies ((together with [`cpb_size_value_minus1[i]`](SubLayerHrdParameters::cpb_size_value_minus1))) the CPB size
97    /// of the i-th CPB when the CPB operates at the access unit level.
98    pub cpb_size_scale: Option<u8>,
99    /// This value plus 1 specifies the length, in bits, of the
100    /// `nal_initial_cpb_removal_delay[i]`, `nal_initial_cpb_removal_offset[i]`, `vcl_initial_cpb_removal_delay[i]`,
101    /// and `vcl_initial_cpb_removal_offset[i]` syntax elements of the buffering period SEI message.
102    pub initial_cpb_removal_delay_length_minus1: u8,
103    /// This value plus 1 specifies the length, in bits, of the cpb_delay_offset syntax
104    /// element in the buffering period SEI message and the au_cpb_removal_delay_minus1 syntax element in
105    /// the picture timing SEI message.
106    pub au_cpb_removal_delay_length_minus1: u8,
107    /// This value plus 1 specifies the length, in bits, of the dpb_delay_offset syntax
108    /// element in the buffering period SEI message and the pic_dpb_output_delay syntax element in the picture
109    /// timing SEI message.
110    pub dpb_output_delay_length_minus1: u8,
111}
112
113impl Default for CommonInf {
114    fn default() -> Self {
115        Self {
116            sub_pic_hrd_params: None,
117            bit_rate_scale: None,
118            cpb_size_scale: None,
119            initial_cpb_removal_delay_length_minus1: 23,
120            au_cpb_removal_delay_length_minus1: 23,
121            dpb_output_delay_length_minus1: 23,
122        }
123    }
124}
125
126/// Directly part of [`HrdParameters`].
127#[derive(Debug, Clone, PartialEq)]
128pub struct SubPicHrdParams {
129    /// Used to specify the clock sub-tick. A clock sub-tick is the minimum interval of
130    /// time that can be represented in the coded data.
131    pub tick_divisor_minus2: u8,
132    /// This value plus 1 specifies the length, in bits, of the
133    /// `du_cpb_removal_delay_increment_minus1[i]` and `du_common_cpb_removal_delay_increment_minus1`
134    /// syntax elements of the picture timing SEI message and the `du_spt_cpb_removal_delay_increment` syntax
135    /// element in the decoding unit information SEI message.
136    pub du_cpb_removal_delay_increment_length_minus1: u8,
137    /// Equal to `true` specifies that sub-picture level CPB removal
138    /// delay parameters are present in picture timing SEI messages and no decoding unit information SEI
139    /// message is available (in the CVS or provided through external means not specified in this document).
140    ///
141    /// Equal to `false` specifies that sub-picture level CPB removal delay
142    /// parameters are present in decoding unit information SEI messages and picture timing SEI messages do
143    /// not include sub-picture level CPB removal delay parameters.
144    pub sub_pic_cpb_params_in_pic_timing_sei_flag: bool,
145    /// This value plus 1 specifies the length, in bits, of
146    /// `pic_dpb_output_du_delay` syntax element in the picture timing SEI message and
147    /// `pic_spt_dpb_output_du_delay` syntax element in the decoding unit information SEI message.
148    pub dpb_output_delay_du_length_minus1: u8,
149    /// Specifies (together with [`cpb_size_du_value_minus1[i]`](SubLayerHrdParameters::cpb_size_du_value_minus1))
150    /// the CPB size of the i-th CPB when the CPB operates at sub-picture level.
151    pub cpb_size_du_scale: u8,
152}
153
154/// Directly part of [`HrdParameters`].
155#[derive(Debug, Clone, PartialEq)]
156pub struct HrdParametersSubLayer {
157    /// Equal to `true` indicates that, when `HighestTid` is equal to `i`, the temporal
158    /// distance between the HRD output times of consecutive pictures in output order is constrained as specified.
159    ///
160    /// Equal to `false` indicates that this constraint may not apply.
161    pub fixed_pic_rate_general_flag: bool,
162    /// Equal to `true` indicates that, when `HighestTid` is equal to `i`, the temporal
163    /// distance between the HRD output times of consecutive pictures in output order is constrained as specified.
164    ///
165    /// Equal to `false` indicates that this constraint may not apply.
166    pub fixed_pic_rate_within_cvs_flag: bool,
167    /// This value plus 1 (when present) specifies, when `HighestTid` is equal to `i`,
168    /// the temporal distance, in clock ticks, between the elemental units that specify the HRD output times of
169    /// consecutive pictures in output order as specified.
170    ///
171    /// The value is in range \[0, 2047\].
172    pub elemental_duration_in_tc_minus1: Option<u64>,
173    /// Specifies the HRD operational mode, when `HighestTid` is equal to `i`, as specified in
174    /// ISO/IEC 23008-2 Annex C or ISO/IEC 23008-2 F.13.
175    pub low_delay_hrd_flag: bool,
176    /// This value plus 1 specifies the number of alternative CPB specifications in the bitstream of the
177    /// CVS when `HighestTid` is equal to `i`.
178    ///
179    /// The value is in range \[0, 31\].
180    pub cpb_cnt_minus1: u64,
181    /// Sub-layer HRD parameters.
182    pub sub_layer_parameters: Vec<SubLayerHrdParameters>,
183}
184
185impl HrdParametersSubLayer {
186    fn parse(
187        bit_reader: &mut BitReader<impl io::Read>,
188        sub_pic_hrd_params_present_flag: bool,
189        nal_hrd_parameters_present_flag: bool,
190        vcl_hrd_parameters_present_flag: bool,
191    ) -> io::Result<Self> {
192        let mut fixed_pic_rate_within_cvs_flag = true;
193
194        let fixed_pic_rate_general_flag = bit_reader.read_bit()?;
195        if !fixed_pic_rate_general_flag {
196            fixed_pic_rate_within_cvs_flag = bit_reader.read_bit()?;
197        }
198
199        let mut elemental_duration_in_tc_minus1_value = None;
200        let mut low_delay_hrd_flag = false;
201        if fixed_pic_rate_within_cvs_flag {
202            let elemental_duration_in_tc_minus1 = bit_reader.read_exp_golomb()?;
203            range_check!(elemental_duration_in_tc_minus1, 0, 2047)?;
204            elemental_duration_in_tc_minus1_value = Some(elemental_duration_in_tc_minus1);
205        } else {
206            low_delay_hrd_flag = bit_reader.read_bit()?;
207        }
208
209        let mut cpb_cnt_minus1 = 0;
210        if !low_delay_hrd_flag {
211            cpb_cnt_minus1 = bit_reader.read_exp_golomb()?;
212            range_check!(cpb_cnt_minus1, 0, 31)?;
213        }
214
215        let mut sub_layer_parameters = Vec::new();
216
217        if nal_hrd_parameters_present_flag {
218            sub_layer_parameters.append(&mut SubLayerHrdParameters::parse(
219                bit_reader,
220                true,
221                cpb_cnt_minus1 + 1,
222                sub_pic_hrd_params_present_flag,
223            )?);
224        }
225
226        if vcl_hrd_parameters_present_flag {
227            sub_layer_parameters.append(&mut SubLayerHrdParameters::parse(
228                bit_reader,
229                false,
230                cpb_cnt_minus1 + 1,
231                sub_pic_hrd_params_present_flag,
232            )?);
233        }
234
235        Ok(Self {
236            fixed_pic_rate_general_flag,
237            fixed_pic_rate_within_cvs_flag,
238            elemental_duration_in_tc_minus1: elemental_duration_in_tc_minus1_value,
239            low_delay_hrd_flag,
240            cpb_cnt_minus1,
241            sub_layer_parameters,
242        })
243    }
244}
245
246/// Sub-layer HRD parameters.
247///
248/// `sub_layer_hrd_parameters(subLayerId)`
249///
250/// - ISO/IEC 23008-2 - E.2.3
251/// - ISO/IEC 23008-2 - E.3.3
252#[derive(Debug, Clone, PartialEq)]
253pub struct SubLayerHrdParameters {
254    /// Internal field to store if this is a NAL or VCL HRD
255    nal_hrd: bool,
256    /// Specifies (together with [`bit_rate_scale`](CommonInf::bit_rate_scale)) the maximum input bit rate
257    /// for the i-th CPB when the CPB operates at the access unit level.
258    ///
259    /// For any `i > 0`, `bit_rate_value_minus1[i]` is greater than `bit_rate_value_minus1[i − 1]`.
260    ///
261    /// The value is in range \[0, 2^32 - 2\].
262    ///
263    /// Defines [`BitRate[i]`](SubLayerHrdParameters::bit_rate).
264    pub bit_rate_value_minus1: u32,
265    /// Used together with [`cpb_size_scale`](CommonInf::cpb_size_scale) to specify
266    /// the i-th CPB size when the CPB operates at the access unit level.
267    ///
268    /// For any `i > 0`, `cpb_size_value_minus1[i]` is less than or equal to `cpb_size_value_minus1[i − 1]`.
269    ///
270    /// The value is in range \[0, 2^32 - 2\].
271    ///
272    /// Defines [`CpbSize[i]`](SubLayerHrdParameters::cpb_size).
273    pub cpb_size_value_minus1: u32,
274    /// Used together with [`cpb_size_du_scale`](SubPicHrdParams::cpb_size_du_scale) to specify
275    /// the i-th CPB size when the CPB operates at sub-picture level.
276    ///
277    /// For any `i > 0`, `cpb_size_du_value_minus1[i]` is less than or equal to `cpb_size_du_value_minus1[i − 1]`.
278    ///
279    /// The value is in range \[0, 2^32 - 2\].
280    ///
281    /// Defines [`CpbSize[i]`](SubLayerHrdParameters::cpb_size).
282    pub cpb_size_du_value_minus1: Option<u64>,
283    /// Specifies (together with [`bit_rate_scale`](CommonInf::bit_rate_scale)) the maximum input bit rate for
284    /// the i-th CPB when the CPB operates at the sub-picture level.
285    ///
286    /// For any `i > 0`, `bit_rate_du_value_minus1[i]` shall be greater than `bit_rate_du_value_minus1[i − 1]`.
287    ///
288    /// The value is in range \[0, 2^32 - 2\].
289    ///
290    /// Defines [`BitRate[i]`](SubLayerHrdParameters::bit_rate).
291    pub bit_rate_du_value_minus1: Option<u64>,
292    /// Equal to `false` specifies that to decode this CVS by the HRD using the i-th CPB specification, the
293    /// hypothetical stream scheduler (HSS) operates in an intermittent bit rate mode.
294    ///
295    /// Equal to `true` specifies that the HSS operates in a constant bit rate (CBR) mode.
296    pub cbr_flag: bool,
297}
298
299impl SubLayerHrdParameters {
300    fn parse<R: io::Read>(
301        bit_reader: &mut BitReader<R>,
302        nal_hrd: bool,
303        cpb_cnt: u64,
304        sub_pic_hrd_params_present_flag: bool,
305    ) -> io::Result<Vec<Self>> {
306        let mut parameters: Vec<Self> = Vec::with_capacity(cpb_cnt as usize);
307
308        for i in 0..cpb_cnt as usize {
309            let bit_rate_value_minus1 = bit_reader.read_exp_golomb()?;
310            range_check!(bit_rate_value_minus1, 0, 2u64.pow(32) - 2)?;
311            let bit_rate_value_minus1 = bit_rate_value_minus1 as u32;
312            if i > 0 && bit_rate_value_minus1 <= parameters[i - 1].bit_rate_value_minus1 {
313                return Err(io::Error::new(
314                    io::ErrorKind::InvalidData,
315                    "bit_rate_value_minus1 must be greater than the previous value",
316                ));
317            }
318
319            let cpb_size_value_minus1 = bit_reader.read_exp_golomb()?;
320            range_check!(cpb_size_value_minus1, 0, 2u64.pow(32) - 2)?;
321            let cpb_size_value_minus1 = cpb_size_value_minus1 as u32;
322            if i > 0 && cpb_size_value_minus1 > parameters[i - 1].cpb_size_value_minus1 {
323                return Err(io::Error::new(
324                    io::ErrorKind::InvalidData,
325                    "cpb_size_value_minus1 must be less than or equal to the previous value",
326                ));
327            }
328
329            let mut cpb_size_du_value_minus1 = None;
330            let mut bit_rate_du_value_minus1 = None;
331            if sub_pic_hrd_params_present_flag {
332                cpb_size_du_value_minus1 = Some(bit_reader.read_exp_golomb()?);
333                bit_rate_du_value_minus1 = Some(bit_reader.read_exp_golomb()?);
334            }
335
336            let cbr_flag = bit_reader.read_bit()?;
337
338            parameters.push(Self {
339                nal_hrd,
340                bit_rate_value_minus1,
341                cpb_size_value_minus1,
342                cpb_size_du_value_minus1,
343                bit_rate_du_value_minus1,
344                cbr_flag,
345            });
346        }
347
348        Ok(parameters)
349    }
350
351    /// When `SubPicHrdFlag` is equal to `false`, the bit rate in bits per second is given by:
352    /// `BitRate[i] = (bit_rate_value_minus1[ i ] + 1) * 2^(6 + bit_rate_scale)` (E-77)
353    ///
354    /// When `SubPicHrdFlag` is equal to `true`, the bit rate in bits per second is given by:
355    /// `BitRate[i] = (bit_rate_du_value_minus1[ i ] + 1) * 2^(6 + bit_rate_scale)` (E-80)
356    ///
357    /// When `SubPicHrdFlag` is equal to `true` and the `bit_rate_du_value_minus1[i]` syntax element is not present,
358    /// the value of `BitRate[i]` is inferred to be equal to `BrVclFactor * MaxBR` for VCL HRD parameters and to be
359    /// equal to `BrNalFactor * MaxBR` for NAL HRD parameters, where `MaxBR`, `BrVclFactor` and `BrNalFactor` are
360    /// specified in ISO/IEC 23008-2 - A.4.
361    pub fn bit_rate(
362        &self,
363        sub_pic_hrd_flag: bool,
364        bit_rate_scale: u8,
365        br_vcl_factor: u64,
366        br_nal_factor: u64,
367        max_br: u64,
368    ) -> u64 {
369        let value = if !sub_pic_hrd_flag {
370            self.bit_rate_value_minus1 as u64
371        } else {
372            self.bit_rate_du_value_minus1.unwrap_or_else(|| {
373                if self.nal_hrd {
374                    br_nal_factor * max_br
375                } else {
376                    br_vcl_factor * max_br
377                }
378            })
379        };
380        (value + 1) * 2u64.pow(6 + bit_rate_scale as u32)
381    }
382
383    /// When `SubPicHrdFlag` is equal to `false`, the CPB size in bits is given by:
384    /// `CpbSize[i] = (cpb_size_value_minus1[ i ] + 1) * 2^(4 + cpb_size_scale)` (E-78)
385    ///
386    /// When `SubPicHrdFlag` is equal to `true`, the CPB size in bits is given by:
387    /// `CpbSize[i] = (cpb_size_du_value_minus1[ i ] + 1) * 2^(4 + cpb_size_du_scale)` (E-79)
388    ///
389    /// When `SubPicHrdFlag` is equal to `true` and the `cpb_size_du_value_minus1[i]` syntax element is not present,
390    /// the value of `CpbSize[i]` is inferred to be equal to `CpbVclFactor * MaxCPB` for VCL HRD parameters and to
391    /// be equal to `CpbNalFactor * MaxCPB` for NAL HRD parameters, where `MaxCPB`, `CpbVclFactor` and
392    /// `CpbNalFactor` are specified in ISO/IEC 23008-2 - A.4.
393    pub fn cpb_size(
394        &self,
395        sub_pic_hrd_flag: bool,
396        cpb_size_scale: u8,
397        cpb_vcl_factor: u64,
398        cpb_nal_factor: u64,
399        max_cpb: u64,
400    ) -> u64 {
401        let value = if !sub_pic_hrd_flag {
402            self.bit_rate_value_minus1 as u64
403        } else {
404            self.bit_rate_du_value_minus1.unwrap_or_else(|| {
405                if self.nal_hrd {
406                    cpb_nal_factor * max_cpb
407                } else {
408                    cpb_vcl_factor * max_cpb
409                }
410            })
411        };
412        (value + 1) * 2u64.pow(4 + cpb_size_scale as u32)
413    }
414}
415
416#[cfg(test)]
417#[cfg_attr(all(test, coverage_nightly), coverage(off))]
418mod tests {
419    use byteorder::WriteBytesExt;
420    use scuffle_bytes_util::{BitReader, BitWriter};
421    use scuffle_expgolomb::BitWriterExpGolombExt;
422
423    use super::HrdParameters;
424
425    #[test]
426    fn test_parse() {
427        let mut data = Vec::new();
428        let mut bit_writer = BitWriter::new(&mut data);
429
430        bit_writer.write_bit(true).unwrap(); // nal_hrd_parameters_present_flag
431        bit_writer.write_bit(true).unwrap(); // vcl_hrd_parameters_present_flag
432
433        bit_writer.write_bit(false).unwrap(); // sub_pic_hrd_params_present_flag
434        bit_writer.write_bits(0, 4).unwrap(); // bit_rate_scale
435        bit_writer.write_bits(0, 4).unwrap(); // cpb_size_scale
436        bit_writer.write_bits(0, 5).unwrap(); // initial_cpb_removal_delay_length_minus1
437        bit_writer.write_bits(0, 5).unwrap(); // au_cpb_removal_delay_length_minus1
438        bit_writer.write_bits(0, 5).unwrap(); // dpb_output_delay_length_minus1
439
440        // Sub-layers
441        bit_writer.write_bit(true).unwrap(); // fixed_pic_rate_general_flag
442
443        bit_writer.write_exp_golomb(0).unwrap(); // elemental_duration_in_tc_minus1
444
445        bit_writer.write_exp_golomb(0).unwrap(); // cpb_cnt_minus1
446
447        // SubLayerHrdParameters
448        bit_writer.write_exp_golomb(0).unwrap(); // bit_rate_value_minus1
449        bit_writer.write_exp_golomb(0).unwrap(); // cpb_size_value_minus1
450        bit_writer.write_bit(false).unwrap(); // cbr_flag
451
452        // SubLayerHrdParameters
453        bit_writer.write_exp_golomb(0).unwrap(); // bit_rate_value_minus1
454        bit_writer.write_exp_golomb(0).unwrap(); // cpb_size_value_minus1
455        bit_writer.write_bit(false).unwrap(); // cbr_flag
456
457        bit_writer.write_bits(0, 8).unwrap(); // fill remaining bits
458
459        let mut bit_reader = BitReader::new(&data[..]);
460        let hrd_parameters = HrdParameters::parse(&mut bit_reader, true, 0).unwrap();
461        assert_eq!(hrd_parameters.common_inf.bit_rate_scale, Some(0));
462        assert_eq!(hrd_parameters.common_inf.cpb_size_scale, Some(0));
463        assert_eq!(hrd_parameters.common_inf.initial_cpb_removal_delay_length_minus1, 0);
464        assert_eq!(hrd_parameters.common_inf.au_cpb_removal_delay_length_minus1, 0);
465        assert_eq!(hrd_parameters.common_inf.dpb_output_delay_length_minus1, 0);
466        assert_eq!(hrd_parameters.sub_layers.len(), 1);
467        assert!(hrd_parameters.sub_layers[0].fixed_pic_rate_general_flag);
468        assert!(hrd_parameters.sub_layers[0].fixed_pic_rate_within_cvs_flag);
469        assert_eq!(hrd_parameters.sub_layers[0].elemental_duration_in_tc_minus1, Some(0));
470        assert!(!hrd_parameters.sub_layers[0].low_delay_hrd_flag);
471        assert_eq!(hrd_parameters.sub_layers[0].cpb_cnt_minus1, 0);
472        assert_eq!(hrd_parameters.sub_layers[0].sub_layer_parameters.len(), 2);
473        assert_eq!(hrd_parameters.sub_layers[0].sub_layer_parameters[0].bit_rate_value_minus1, 0);
474        assert_eq!(hrd_parameters.sub_layers[0].sub_layer_parameters[0].cpb_size_value_minus1, 0);
475        assert_eq!(
476            hrd_parameters.sub_layers[0].sub_layer_parameters[0].cpb_size_du_value_minus1,
477            None
478        );
479        assert_eq!(
480            hrd_parameters.sub_layers[0].sub_layer_parameters[0].bit_rate_du_value_minus1,
481            None
482        );
483        assert!(!hrd_parameters.sub_layers[0].sub_layer_parameters[0].cbr_flag);
484        assert_eq!(hrd_parameters.sub_layers[0].sub_layer_parameters[1].bit_rate_value_minus1, 0);
485        assert_eq!(hrd_parameters.sub_layers[0].sub_layer_parameters[1].cpb_size_value_minus1, 0);
486        assert_eq!(
487            hrd_parameters.sub_layers[0].sub_layer_parameters[1].cpb_size_du_value_minus1,
488            None
489        );
490        assert_eq!(
491            hrd_parameters.sub_layers[0].sub_layer_parameters[1].bit_rate_du_value_minus1,
492            None
493        );
494        assert!(!hrd_parameters.sub_layers[0].sub_layer_parameters[1].cbr_flag);
495
496        assert_eq!(
497            hrd_parameters.sub_layers[0].sub_layer_parameters[0].bit_rate(false, 0, 0, 0, 0),
498            64
499        );
500        assert_eq!(
501            hrd_parameters.sub_layers[0].sub_layer_parameters[0].bit_rate(true, 0, 0, 0, 0),
502            64
503        );
504        assert_eq!(
505            hrd_parameters.sub_layers[0].sub_layer_parameters[1].bit_rate(false, 0, 0, 0, 0),
506            64
507        );
508        assert_eq!(
509            hrd_parameters.sub_layers[0].sub_layer_parameters[1].bit_rate(true, 0, 0, 0, 0),
510            64
511        );
512
513        assert_eq!(
514            hrd_parameters.sub_layers[0].sub_layer_parameters[0].cpb_size(false, 0, 0, 0, 0),
515            16
516        );
517        assert_eq!(
518            hrd_parameters.sub_layers[0].sub_layer_parameters[0].cpb_size(true, 0, 0, 0, 0),
519            16
520        );
521        assert_eq!(
522            hrd_parameters.sub_layers[0].sub_layer_parameters[1].cpb_size(false, 0, 0, 0, 0),
523            16
524        );
525        assert_eq!(
526            hrd_parameters.sub_layers[0].sub_layer_parameters[1].cpb_size(true, 0, 0, 0, 0),
527            16
528        );
529    }
530
531    #[test]
532    fn test_parse_sub_pic_hrd_params_present_flag() {
533        let mut data = Vec::new();
534        let mut bit_writer = BitWriter::new(&mut data);
535
536        bit_writer.write_bit(true).unwrap(); // nal_hrd_parameters_present_flag
537        bit_writer.write_bit(true).unwrap(); // vcl_hrd_parameters_present_flag
538
539        bit_writer.write_bit(true).unwrap(); // sub_pic_hrd_params_present_flag
540        bit_writer.write_u8(42).unwrap(); // tick_divisor_minus2
541        bit_writer.write_bits(0, 5).unwrap(); // du_cpb_removal_delay_increment_length_minus1
542        bit_writer.write_bit(false).unwrap(); // sub_pic_cpb_params_in_pic_timing_sei_flag
543        bit_writer.write_bits(0, 5).unwrap(); // dpb_output_delay_du_length_minus1
544        bit_writer.write_bits(0, 4).unwrap(); // bit_rate_scale
545        bit_writer.write_bits(0, 4).unwrap(); // cpb_size_scale
546        bit_writer.write_bits(0, 4).unwrap(); // cpb_size_du_scale
547        bit_writer.write_bits(0, 5).unwrap(); // initial_cpb_removal_delay_length_minus1
548        bit_writer.write_bits(0, 5).unwrap(); // au_cpb_removal_delay_length_minus1
549        bit_writer.write_bits(0, 5).unwrap(); // dpb_output_delay_length_minus1
550
551        // Sub-layers
552        bit_writer.write_bit(true).unwrap(); // fixed_pic_rate_general_flag
553
554        bit_writer.write_exp_golomb(0).unwrap(); // elemental_duration_in_tc_minus1
555
556        bit_writer.write_exp_golomb(0).unwrap(); // cpb_cnt_minus1
557
558        // SubLayerHrdParameters
559        bit_writer.write_exp_golomb(0).unwrap(); // bit_rate_value_minus1
560        bit_writer.write_exp_golomb(0).unwrap(); // cpb_size_value_minus1
561        bit_writer.write_exp_golomb(0).unwrap(); // cpb_size_du_value_minus1
562        bit_writer.write_exp_golomb(0).unwrap(); // bit_rate_du_value_minus1
563        bit_writer.write_bit(false).unwrap(); // cbr_flag
564
565        // SubLayerHrdParameters
566        bit_writer.write_exp_golomb(0).unwrap(); // bit_rate_value_minus1
567        bit_writer.write_exp_golomb(0).unwrap(); // cpb_size_value_minus1
568        bit_writer.write_exp_golomb(0).unwrap(); // cpb_size_du_value_minus1
569        bit_writer.write_exp_golomb(0).unwrap(); // bit_rate_du_value_minus1
570        bit_writer.write_bit(false).unwrap(); // cbr_flag
571
572        bit_writer.write_bits(0, 8).unwrap(); // fill remaining bits
573
574        let mut bit_reader = BitReader::new(&data[..]);
575        let hrd_parameters = HrdParameters::parse(&mut bit_reader, true, 0).unwrap();
576        assert_eq!(hrd_parameters.common_inf.bit_rate_scale, Some(0));
577        assert_eq!(hrd_parameters.common_inf.cpb_size_scale, Some(0));
578        assert_eq!(hrd_parameters.common_inf.initial_cpb_removal_delay_length_minus1, 0);
579        assert_eq!(hrd_parameters.common_inf.au_cpb_removal_delay_length_minus1, 0);
580        assert_eq!(hrd_parameters.common_inf.dpb_output_delay_length_minus1, 0);
581        assert!(hrd_parameters.common_inf.sub_pic_hrd_params.is_some());
582        assert_eq!(hrd_parameters.sub_layers.len(), 1);
583        assert!(hrd_parameters.sub_layers[0].fixed_pic_rate_general_flag);
584        assert!(hrd_parameters.sub_layers[0].fixed_pic_rate_within_cvs_flag);
585        assert_eq!(hrd_parameters.sub_layers[0].elemental_duration_in_tc_minus1, Some(0));
586        assert!(!hrd_parameters.sub_layers[0].low_delay_hrd_flag);
587        assert_eq!(hrd_parameters.sub_layers[0].cpb_cnt_minus1, 0);
588        assert_eq!(hrd_parameters.sub_layers[0].sub_layer_parameters.len(), 2);
589        assert_eq!(hrd_parameters.sub_layers[0].sub_layer_parameters[0].bit_rate_value_minus1, 0);
590        assert_eq!(hrd_parameters.sub_layers[0].sub_layer_parameters[0].cpb_size_value_minus1, 0);
591        assert_eq!(
592            hrd_parameters.sub_layers[0].sub_layer_parameters[0].cpb_size_du_value_minus1,
593            Some(0)
594        );
595        assert_eq!(
596            hrd_parameters.sub_layers[0].sub_layer_parameters[0].bit_rate_du_value_minus1,
597            Some(0)
598        );
599        assert!(!hrd_parameters.sub_layers[0].sub_layer_parameters[0].cbr_flag);
600        assert_eq!(hrd_parameters.sub_layers[0].sub_layer_parameters[1].bit_rate_value_minus1, 0);
601        assert_eq!(hrd_parameters.sub_layers[0].sub_layer_parameters[1].cpb_size_value_minus1, 0);
602        assert_eq!(
603            hrd_parameters.sub_layers[0].sub_layer_parameters[1].cpb_size_du_value_minus1,
604            Some(0)
605        );
606        assert_eq!(
607            hrd_parameters.sub_layers[0].sub_layer_parameters[1].bit_rate_du_value_minus1,
608            Some(0)
609        );
610        assert!(!hrd_parameters.sub_layers[0].sub_layer_parameters[1].cbr_flag);
611
612        assert_eq!(
613            hrd_parameters.sub_layers[0].sub_layer_parameters[0].bit_rate(false, 0, 0, 0, 0),
614            64
615        );
616        assert_eq!(
617            hrd_parameters.sub_layers[0].sub_layer_parameters[0].bit_rate(true, 0, 0, 0, 0),
618            64
619        );
620        assert_eq!(
621            hrd_parameters.sub_layers[0].sub_layer_parameters[1].bit_rate(false, 0, 0, 0, 0),
622            64
623        );
624        assert_eq!(
625            hrd_parameters.sub_layers[0].sub_layer_parameters[1].bit_rate(true, 0, 0, 0, 0),
626            64
627        );
628
629        assert_eq!(
630            hrd_parameters.sub_layers[0].sub_layer_parameters[0].cpb_size(false, 0, 0, 0, 0),
631            16
632        );
633        assert_eq!(
634            hrd_parameters.sub_layers[0].sub_layer_parameters[0].cpb_size(true, 0, 0, 0, 0),
635            16
636        );
637        assert_eq!(
638            hrd_parameters.sub_layers[0].sub_layer_parameters[1].cpb_size(false, 0, 0, 0, 0),
639            16
640        );
641        assert_eq!(
642            hrd_parameters.sub_layers[0].sub_layer_parameters[1].cpb_size(true, 0, 0, 0, 0),
643            16
644        );
645    }
646}