scuffle_h265/sps/vui_parameters/
hrd_parameters.rs

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