cros_codecs/codec/h265/
parser.rs

1// Copyright 2023 The ChromiumOS Authors
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5//! An Annex B h.265 parser.
6//!
7//! Parses VPSs, SPSs, PPSs and Slices from NALUs.
8
9use std::collections::BTreeMap;
10use std::io::Read;
11use std::io::Seek;
12use std::io::SeekFrom;
13use std::rc::Rc;
14
15use crate::bitstream_utils::BitReader;
16use crate::codec::h264::nalu;
17use crate::codec::h264::nalu::Header;
18use crate::codec::h264::parser::Point;
19use crate::codec::h264::parser::Rect;
20
21// Given the max VPS id.
22const MAX_VPS_COUNT: usize = 16;
23// Given the max SPS id.
24const MAX_SPS_COUNT: usize = 16;
25// Given the max PPS id.
26const MAX_PPS_COUNT: usize = 64;
27// 7.4.7.1
28const MAX_REF_IDX_ACTIVE: u32 = 15;
29
30// 7.4.3.2.1:
31// num_short_term_ref_pic_sets specifies the number of st_ref_pic_set( ) syntax
32// structures included in the SPS. The value of num_short_term_ref_pic_sets
33// shall be in the range of 0 to 64, inclusive.
34// NOTE 5 – A decoder should allocate memory for a total number of
35// num_short_term_ref_pic_sets + 1 st_ref_pic_set( ) syntax structures since
36// there may be a st_ref_pic_set( ) syntax structure directly signalled in the
37// slice headers of a current picture. A st_ref_pic_set( ) syntax structure
38// directly signalled in the slice headers of a current picture has an index
39// equal to num_short_term_ref_pic_sets.
40const MAX_SHORT_TERM_REF_PIC_SETS: usize = 65;
41
42// 7.4.3.2.1:
43const MAX_LONG_TERM_REF_PIC_SETS: usize = 32;
44
45// From table 7-5.
46const DEFAULT_SCALING_LIST_0: [u8; 16] = [16; 16];
47
48// From Table 7-6.
49const DEFAULT_SCALING_LIST_1: [u8; 64] = [
50    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 17, 16, 17, 16, 17, 18, 17, 18, 18, 17, 18, 21, 19, 20,
51    21, 20, 19, 21, 24, 22, 22, 24, 24, 22, 22, 24, 25, 25, 27, 30, 27, 25, 25, 29, 31, 35, 35, 31,
52    29, 36, 41, 44, 41, 36, 47, 54, 54, 47, 65, 70, 65, 88, 88, 115,
53];
54
55// From Table 7-6.
56const DEFAULT_SCALING_LIST_2: [u8; 64] = [
57    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 20, 20, 20,
58    20, 20, 20, 20, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 28, 28, 28, 28, 28,
59    28, 33, 33, 33, 33, 33, 41, 41, 41, 41, 54, 54, 54, 71, 71, 91,
60];
61
62/// Table 7-1 – NAL unit type codes and NAL unit type classes
63#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
64pub enum NaluType {
65    #[default]
66    TrailN = 0,
67    TrailR = 1,
68    TsaN = 2,
69    TsaR = 3,
70    StsaN = 4,
71    StsaR = 5,
72    RadlN = 6,
73    RadlR = 7,
74    RaslN = 8,
75    RaslR = 9,
76    RsvVclN10 = 10,
77    RsvVclR11 = 11,
78    RsvVclN12 = 12,
79    RsvVclR13 = 13,
80    RsvVclN14 = 14,
81    RsvVclR15 = 15,
82    BlaWLp = 16,
83    BlaWRadl = 17,
84    BlaNLp = 18,
85    IdrWRadl = 19,
86    IdrNLp = 20,
87    CraNut = 21,
88    RsvIrapVcl22 = 22,
89    RsvIrapVcl23 = 23,
90    RsvVcl24 = 24,
91    RsvVcl25 = 25,
92    RsvVcl26 = 26,
93    RsvVcl27 = 27,
94    RsvVcl28 = 28,
95    RsvVcl29 = 29,
96    RsvVcl30 = 30,
97    RsvVcl31 = 31,
98    VpsNut = 32,
99    SpsNut = 33,
100    PpsNut = 34,
101    AudNut = 35,
102    EosNut = 36,
103    EobNut = 37,
104    FdNut = 38,
105    PrefixSeiNut = 39,
106    SuffixSeiNut = 40,
107    RsvNvcl41 = 41,
108    RsvNvcl42 = 42,
109    RsvNvcl43 = 43,
110    RsvNvcl44 = 44,
111    RsvNvcl45 = 45,
112    RsvNvcl46 = 46,
113    RsvNvcl47 = 47,
114}
115
116impl TryFrom<u32> for NaluType {
117    type Error = String;
118
119    fn try_from(value: u32) -> Result<Self, Self::Error> {
120        match value {
121            0 => Ok(NaluType::TrailN),
122            1 => Ok(NaluType::TrailR),
123            2 => Ok(NaluType::TsaN),
124            3 => Ok(NaluType::TsaR),
125            4 => Ok(NaluType::StsaN),
126            5 => Ok(NaluType::StsaR),
127            6 => Ok(NaluType::RadlN),
128            7 => Ok(NaluType::RadlR),
129            8 => Ok(NaluType::RaslN),
130            9 => Ok(NaluType::RaslR),
131            10 => Ok(NaluType::RsvVclN10),
132            11 => Ok(NaluType::RsvVclR11),
133            12 => Ok(NaluType::RsvVclN12),
134            13 => Ok(NaluType::RsvVclR13),
135            14 => Ok(NaluType::RsvVclN14),
136            15 => Ok(NaluType::RsvVclR15),
137            16 => Ok(NaluType::BlaWLp),
138            17 => Ok(NaluType::BlaWRadl),
139            18 => Ok(NaluType::BlaNLp),
140            19 => Ok(NaluType::IdrWRadl),
141            20 => Ok(NaluType::IdrNLp),
142            21 => Ok(NaluType::CraNut),
143            22 => Ok(NaluType::RsvIrapVcl22),
144            23 => Ok(NaluType::RsvIrapVcl23),
145            24 => Ok(NaluType::RsvVcl24),
146            25 => Ok(NaluType::RsvVcl25),
147            26 => Ok(NaluType::RsvVcl26),
148            27 => Ok(NaluType::RsvVcl27),
149            28 => Ok(NaluType::RsvVcl28),
150            29 => Ok(NaluType::RsvVcl29),
151            30 => Ok(NaluType::RsvVcl30),
152            31 => Ok(NaluType::RsvVcl31),
153            32 => Ok(NaluType::VpsNut),
154            33 => Ok(NaluType::SpsNut),
155            34 => Ok(NaluType::PpsNut),
156            35 => Ok(NaluType::AudNut),
157            36 => Ok(NaluType::EosNut),
158            37 => Ok(NaluType::EobNut),
159            38 => Ok(NaluType::FdNut),
160            39 => Ok(NaluType::PrefixSeiNut),
161            40 => Ok(NaluType::SuffixSeiNut),
162            41 => Ok(NaluType::RsvNvcl41),
163            42 => Ok(NaluType::RsvNvcl42),
164            43 => Ok(NaluType::RsvNvcl43),
165            44 => Ok(NaluType::RsvNvcl44),
166            45 => Ok(NaluType::RsvNvcl45),
167            46 => Ok(NaluType::RsvNvcl46),
168            47 => Ok(NaluType::RsvNvcl47),
169            _ => Err(format!("Invalid NaluType {}", value)),
170        }
171    }
172}
173
174impl NaluType {
175    /// Whether this is an IDR NALU.
176    pub fn is_idr(&self) -> bool {
177        matches!(self, Self::IdrWRadl | Self::IdrNLp)
178    }
179
180    /// Whether this is an IRAP NALU.
181    pub fn is_irap(&self) -> bool {
182        let type_ = *self as u32;
183        type_ >= Self::BlaWLp as u32 && type_ <= Self::RsvIrapVcl23 as u32
184    }
185
186    /// Whether this is a BLA NALU.
187    pub fn is_bla(&self) -> bool {
188        let type_ = *self as u32;
189        type_ >= Self::BlaWLp as u32 && type_ <= Self::BlaNLp as u32
190    }
191
192    /// Whether this is a CRA NALU.
193    pub fn is_cra(&self) -> bool {
194        matches!(self, Self::CraNut)
195    }
196
197    /// Whether this is a RADL NALU.
198    pub fn is_radl(&self) -> bool {
199        matches!(self, Self::RadlN | Self::RadlR)
200    }
201
202    /// Whether this is a RASL NALU.
203    pub fn is_rasl(&self) -> bool {
204        matches!(self, Self::RaslN | Self::RaslR)
205    }
206
207    //// Whether this is a SLNR NALU.
208    pub fn is_slnr(&self) -> bool {
209        // From the specification:
210        // If a picture has nal_unit_type equal to TRAIL_N, TSA_N, STSA_N,
211        // RADL_N, RASL_N, RSV_VCL_N10, RSV_VCL_N12 or RSV_VCL_N14, the picture
212        // is an SLNR picture. Otherwise, the picture is a sub-layer reference
213        // picture.
214        matches!(
215            self,
216            Self::TrailN
217                | Self::TsaN
218                | Self::StsaN
219                | Self::RadlN
220                | Self::RaslN
221                | Self::RsvVclN10
222                | Self::RsvVclN12
223                | Self::RsvVclN14
224        )
225    }
226}
227
228#[derive(Clone, Debug, Default, PartialEq, Eq)]
229pub struct NaluHeader {
230    /// The NALU type.
231    pub type_: NaluType,
232    /// Specifies the identifier of the layer to which a VCL NAL unit belongs or
233    /// the identifier of a layer to which a non-VCL NAL unit applies.
234    pub nuh_layer_id: u8,
235    /// Minus 1 specifies a temporal identifier for the NAL unit. The value of
236    /// nuh_temporal_id_plus1 shall not be equal to 0.
237    pub nuh_temporal_id_plus1: u8,
238}
239
240impl NaluHeader {
241    pub fn nuh_temporal_id(&self) -> u8 {
242        self.nuh_temporal_id_plus1.saturating_sub(1)
243    }
244}
245
246impl Header for NaluHeader {
247    fn parse<T: AsRef<[u8]>>(cursor: &mut std::io::Cursor<T>) -> Result<Self, String> {
248        let mut data = [0u8; 2];
249        cursor.read_exact(&mut data).map_err(|_| String::from("Broken Data"))?;
250        let mut r = BitReader::new(&data, false);
251        let _ = cursor.seek(SeekFrom::Current(-1 * data.len() as i64));
252
253        // Skip forbidden_zero_bit
254        r.skip_bits(1)?;
255
256        Ok(Self {
257            type_: NaluType::try_from(r.read_bits::<u32>(6)?)?,
258            nuh_layer_id: r.read_bits::<u8>(6)?,
259            nuh_temporal_id_plus1: r.read_bits::<u8>(3)?,
260        })
261    }
262
263    fn is_end(&self) -> bool {
264        matches!(self.type_, NaluType::EosNut | NaluType::EobNut)
265    }
266
267    fn len(&self) -> usize {
268        // 7.3.1.2
269        2
270    }
271}
272
273pub type Nalu<'a> = nalu::Nalu<'a, NaluHeader>;
274
275/// H265 levels as defined by table A.8.
276/// `general_level_idc` and `sub_layer_level_idc[ OpTid ]` shall be set equal to a
277/// value of 30 times the level number specified in Table A.8
278#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
279pub enum Level {
280    #[default]
281    L1 = 30,
282    L2 = 60,
283    L2_1 = 63,
284    L3 = 90,
285    L3_1 = 93,
286    L4 = 120,
287    L4_1 = 123,
288    L5 = 150,
289    L5_1 = 153,
290    L5_2 = 156,
291    L6 = 180,
292    L6_1 = 183,
293    L6_2 = 186,
294}
295
296impl TryFrom<u8> for Level {
297    type Error = String;
298
299    fn try_from(value: u8) -> Result<Self, Self::Error> {
300        match value {
301            30 => Ok(Level::L1),
302            60 => Ok(Level::L2),
303            63 => Ok(Level::L2_1),
304            90 => Ok(Level::L3),
305            93 => Ok(Level::L3_1),
306            120 => Ok(Level::L4),
307            123 => Ok(Level::L4_1),
308            150 => Ok(Level::L5),
309            153 => Ok(Level::L5_1),
310            156 => Ok(Level::L5_2),
311            180 => Ok(Level::L6),
312            183 => Ok(Level::L6_1),
313            186 => Ok(Level::L6_2),
314            _ => Err(format!("Invalid Level {}", value)),
315        }
316    }
317}
318
319/// H265 profiles. See A.3.
320#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
321pub enum Profile {
322    #[default]
323    Main = 1,
324    Main10 = 2,
325    MainStill = 3,
326    RangeExtensions = 4,
327    HighThroughput = 5,
328    MultiviewMain = 6,
329    ScalableMain = 7,
330    ThreeDMain = 8,
331    ScreenContentCoding = 9,
332    ScalableRangeExtensions = 10,
333    HighThroughputScreenContentCoding = 11,
334}
335
336impl TryFrom<u8> for Profile {
337    type Error = String;
338
339    fn try_from(value: u8) -> Result<Self, Self::Error> {
340        match value {
341            1 => Ok(Profile::Main),
342            2 => Ok(Profile::Main10),
343            3 => Ok(Profile::MainStill),
344            4 => Ok(Profile::RangeExtensions),
345            5 => Ok(Profile::HighThroughput),
346            6 => Ok(Profile::MultiviewMain),
347            7 => Ok(Profile::ScalableMain),
348            8 => Ok(Profile::ThreeDMain),
349            9 => Ok(Profile::ScreenContentCoding),
350            10 => Ok(Profile::ScalableRangeExtensions),
351            11 => Ok(Profile::HighThroughputScreenContentCoding),
352            _ => Err(format!("Invalid Profile {}", value)),
353        }
354    }
355}
356
357/// A H.265 Video Parameter Set.
358#[derive(Clone, Debug, PartialEq, Eq)]
359pub struct Vps {
360    /// Identifies the VPS for reference by other syntax elements.
361    pub video_parameter_set_id: u8,
362    /// If vps_base_layer_internal_flag is equal to 1 and
363    /// vps_base_layer_available_flag is equal to 1, the base layer is present
364    /// in the bitstream.
365    pub base_layer_internal_flag: bool,
366    /// See `base_layer_internal_flag`.
367    pub base_layer_available_flag: bool,
368    /// Plus 1 specifies the maximum allowed number of layers in each CVS
369    /// referring to the VPS.
370    pub max_layers_minus1: u8,
371    /// Plus 1 specifies the maximum number of temporal sub-layers that may be
372    /// present in each CVS referring to the VPS.
373    pub max_sub_layers_minus1: u8,
374    /// When vps_max_sub_layers_minus1 is greater than 0, specifies whether
375    /// inter prediction is additionally restricted for CVSs referring to the
376    /// VPS.
377    pub temporal_id_nesting_flag: bool,
378    /// ProfileTierLevel() data.
379    pub profile_tier_level: ProfileTierLevel,
380    /// When true, specifies that `vps_max_dec_pic_buffering_minus1[ i ]`,
381    /// `vps_max_num_reorder_pics[ i ]` and `vps_max_latency_increase_plus1[ i ]`
382    /// are present for vps_max_sub_layers_ minus1 + 1 sub-layers.
383    /// vps_sub_layer_ordering_info_present_flag equal to 0 specifies that the
384    /// values of `vps_max_dec_pic_buffering_minus1[ vps_max_sub_layers_minus1 ]`,
385    /// vps_max_num_reorder_pics[ vps_max_sub_ layers_minus1 ] and
386    /// `vps_max_latency_increase_plus1[ vps_max_sub_layers_minus1 ]` apply to all
387    /// sub-layers
388    pub sub_layer_ordering_info_present_flag: bool,
389    /// `max_dec_pic_buffering_minus1[i]` plus 1 specifies the maximum required
390    /// size of the decoded picture buffer for the CVS in units of picture
391    /// storage buffers when HighestTid is equal to i.
392    pub max_dec_pic_buffering_minus1: [u32; 7],
393    /// Indicates the maximum allowed number of pictures with PicOutputFlag
394    /// equal to 1 that can precede any picture with PicOutputFlag equal to 1 in
395    /// the CVS in decoding order and follow that picture with PicOutputFlag
396    /// equal to 1 in output order when HighestTid is equal to i.
397    pub max_num_reorder_pics: [u32; 7],
398    /// When true, `max_latency_increase_plus1[i]` is used to compute the value of
399    /// `VpsMaxLatencyPictures[ i ]`, which specifies the maximum number of
400    /// pictures with PicOutputFlag equal to 1 that can precede any picture with
401    /// PicOutputFlag equal to 1 in the CVS in output order and follow that
402    /// picture with PicOutputFlag equal to 1 in decoding order when HighestTid
403    /// is equal to i.
404    pub max_latency_increase_plus1: [u32; 7],
405    /// Specifies the maximum allowed value of nuh_layer_id of all NAL units in
406    /// each CVS referring to the VPS.
407    pub max_layer_id: u8,
408    /// num_layer_sets_minus1 plus 1 specifies the number of layer sets that are
409    /// specified by the VPS.
410    pub num_layer_sets_minus1: u32,
411    /// When true, specifies that num_units_in_tick, time_scale,
412    /// poc_proportional_to_timing_flag and num_hrd_parameters are present in
413    /// the VPS.
414    pub timing_info_present_flag: bool,
415    /// The number of time units of a clock operating at the frequency
416    /// vps_time_scale Hz that corresponds to one increment (called a clock
417    /// tick) of a clock tick counter. The value of vps_num_units_in_tick shall
418    /// be greater than 0. A clock tick, in units of seconds, is equal to the
419    /// quotient of vps_num_units_in_tick divided by vps_time_scale. For
420    /// example, when the picture rate of a video signal is 25 Hz,
421    /// vps_time_scale may be equal to 27 000 000 and vps_num_units_in_tick may
422    /// be equal to 1 080 000, and consequently a clock tick may be 0.04
423    /// seconds.
424    pub num_units_in_tick: u32,
425    /// The number of time units that pass in one second. For example, a time
426    /// coordinate system that measures time using a 27 MHz clock has a
427    /// vps_time_scale of 27 000 000.
428    pub time_scale: u32,
429    /// When true, indicates that the picture order count value for each picture
430    /// in the CVS that is not the first picture in the CVS, in decoding order,
431    /// is proportional to the output time of the picture relative to the output
432    /// time of the first picture in the CVS.  When false, indicates that the
433    /// picture order count value for each picture in the CVS that is not the
434    /// first picture in the CVS, in decoding order, may or may not be
435    /// proportional to the output time of the picture relative to the output
436    /// time of the first picture in the CVS.
437    pub poc_proportional_to_timing_flag: bool,
438    /// num_ticks_poc_diff_one_minus1 plus 1 specifies the number of clock ticks
439    /// corresponding to a difference of picture order count values equal to 1.
440    pub num_ticks_poc_diff_one_minus1: u32,
441    /// Specifies the number of hrd_parameters( ) syntax structures present in
442    /// the VPS RBSP before the vps_extension_flag syntax element.
443    pub num_hrd_parameters: u32,
444    /// `hrd_layer_set_idx[ i ]` specifies the index, into the list of layer sets
445    /// specified by the VPS, of the layer set to which the i-th hrd_parameters(
446    /// ) syntax structure in the VPS applies.
447    pub hrd_layer_set_idx: Vec<u16>,
448    /// `cprms_present_flag[ i ]` equal to true specifies that the HRD parameters
449    /// that are common for all sub-layers are present in the i-th
450    /// hrd_parameters( ) syntax structure in the VPS. `cprms_present_flag[ i ]`
451    /// equal to false specifies that the HRD parameters that are common for all
452    /// sub-layers are not present in the i-th hrd_parameters( ) syntax
453    /// structure in the VPS and are derived to be the same as the ( i − 1 )-th
454    /// hrd_parameters( ) syntax structure in the VPS. `cprms_present_flag[ 0 ]`
455    /// is inferred to be equal to true.
456    pub cprms_present_flag: Vec<bool>,
457    /// The hrd_parameters() data.
458    pub hrd_parameters: Vec<HrdParams>,
459    /// When false, specifies that no vps_extension_data_flag syntax elements
460    /// are present in the VPS RBSP syntax structure. When true, specifies that
461    /// there are vps_extension_data_flag syntax elements present in the VPS
462    /// RBSP syntax structure. Decoders conforming to a profile specified in
463    /// Annex A but not supporting the INBLD capability specified in Annex F
464    /// shall ignore all data that follow the value 1 for vps_extension_flag in
465    /// a VPS NAL unit.
466    pub extension_flag: bool,
467}
468
469impl Default for Vps {
470    fn default() -> Self {
471        Self {
472            video_parameter_set_id: Default::default(),
473            base_layer_internal_flag: Default::default(),
474            base_layer_available_flag: Default::default(),
475            max_layers_minus1: Default::default(),
476            max_sub_layers_minus1: Default::default(),
477            temporal_id_nesting_flag: Default::default(),
478            profile_tier_level: Default::default(),
479            sub_layer_ordering_info_present_flag: Default::default(),
480            max_dec_pic_buffering_minus1: Default::default(),
481            max_num_reorder_pics: Default::default(),
482            max_latency_increase_plus1: Default::default(),
483            max_layer_id: Default::default(),
484            num_layer_sets_minus1: Default::default(),
485            timing_info_present_flag: Default::default(),
486            num_units_in_tick: Default::default(),
487            time_scale: Default::default(),
488            poc_proportional_to_timing_flag: Default::default(),
489            num_ticks_poc_diff_one_minus1: Default::default(),
490            num_hrd_parameters: Default::default(),
491            hrd_layer_set_idx: Default::default(),
492            cprms_present_flag: vec![true],
493            hrd_parameters: Default::default(),
494            extension_flag: Default::default(),
495        }
496    }
497}
498
499#[derive(Clone, Debug, Default, PartialEq, Eq)]
500pub struct ProfileTierLevel {
501    /// Specifies the context for the interpretation of general_profile_idc and
502    /// `general_profile_compatibility_flag[ j ]` for all values of j in the range
503    /// of 0 to 31, inclusive.
504    pub general_profile_space: u8,
505    /// Specifies the tier context for the interpretation of general_level_idc
506    /// as specified in Annex A.
507    pub general_tier_flag: bool,
508    /// When general_profile_space is equal to 0, indicates a profile to which
509    /// the CVS conforms as specified in Annex A. Bitstreams shall not contain
510    /// values of general_profile_idc other than those specified in Annex A.
511    /// Other values of general_profile_idc are reserved for future use by ITU-T
512    /// | ISO/IEC.
513    pub general_profile_idc: u8,
514    /// `general_profile_compatibility_flag[ j ]` equal to true, when
515    /// general_profile_space is false, indicates that the CVS conforms to the
516    /// profile indicated by general_profile_idc equal to j as specified in
517    /// Annex A.
518    pub general_profile_compatibility_flag: [bool; 32],
519    /// general_progressive_source_flag and general_interlaced_source_flag are
520    /// interpreted as follows:
521    ///
522    /// –If general_progressive_source_flag is true and
523    /// general_interlaced_source_flag is false, the source scan type of the
524    /// pictures in the CVS should be interpreted as progressive only.
525    ///
526    /// –Otherwise, if general_progressive_source_flag is false and
527    /// general_interlaced_source_flag is true, the source scan type of the
528    /// pictures in the CVS should be interpreted as interlaced only.
529    ///
530    /// –Otherwise, if general_progressive_source_flag is false and
531    /// general_interlaced_source_flag is false, the source scan type of the
532    /// pictures in the CVS should be interpreted as unknown or unspecified.
533    ///
534    /// –Otherwise (general_progressive_source_flag is true and
535    /// general_interlaced_source_flag is true), the source scan type of each
536    /// picture in the CVS is indicated at the picture level using the syntax
537    /// element source_scan_type in a picture timing SEI message.
538    pub general_progressive_source_flag: bool,
539    /// See `general_progressive_source_flag`.
540    pub general_interlaced_source_flag: bool,
541    /// If true, specifies that there are no frame packing arrangement SEI
542    /// messages, segmented rectangular frame packing arrangement SEI messages,
543    /// equirectangular projection SEI messages, or cubemap projection SEI
544    /// messages present in the CVS. If false, indicates that there may or may
545    /// not be one or more frame packing arrangement SEI messages, segmented
546    /// rectangular frame packing arrangement SEI messages, equirectangular
547    /// projection SEI messages, or cubemap projection SEI messages present in
548    /// the CVS.
549    pub general_non_packed_constraint_flag: bool,
550    /// When true, specifies that field_seq_flag is false. When false, indicates
551    /// that field_seq_flag may or may not be false.
552    pub general_frame_only_constraint_flag: bool,
553    /// See Annex A.
554    pub general_max_12bit_constraint_flag: bool,
555    /// See Annex A.
556    pub general_max_10bit_constraint_flag: bool,
557    /// See Annex A.
558    pub general_max_8bit_constraint_flag: bool,
559    /// See Annex A.
560    pub general_max_422chroma_constraint_flag: bool,
561    /// See Annex A.
562    pub general_max_420chroma_constraint_flag: bool,
563    /// See Annex A.
564    pub general_max_monochrome_constraint_flag: bool,
565    /// See Annex A.
566    pub general_intra_constraint_flag: bool,
567    /// See Annex A.
568    pub general_lower_bit_rate_constraint_flag: bool,
569    /// See Annex A.
570    pub general_max_14bit_constraint_flag: bool,
571    /// See Annex A.
572    pub general_one_picture_only_constraint_flag: bool,
573    /// When true, specifies that the INBLD capability as specified in Annex F
574    /// is required for decoding of the layer to which the profile_tier_level( )
575    /// syntax structure applies. When false, specifies that the INBLD
576    /// capability as specified in Annex F is not required for decoding of the
577    /// layer to which the profile_tier_level( ) syntax structure applies.
578    pub general_inbld_flag: bool,
579    /// Indicates a level to which the CVS conforms as specified in Annex A.
580    pub general_level_idc: Level,
581    /// Sub-layer syntax element.
582    pub sub_layer_profile_present_flag: [bool; 6],
583    /// Sub-layer syntax element.
584    pub sub_layer_level_present_flag: [bool; 6],
585    /// Sub-layer syntax element.
586    pub sub_layer_profile_space: [u8; 6],
587    /// Sub-layer syntax element.
588    pub sub_layer_tier_flag: [bool; 6],
589    /// Sub-layer syntax element.
590    pub sub_layer_profile_idc: [u8; 6],
591    /// Sub-layer syntax element.
592    pub sub_layer_profile_compatibility_flag: [[bool; 32]; 6],
593    /// Sub-layer syntax element.
594    pub sub_layer_progressive_source_flag: [bool; 6],
595    /// Sub-layer syntax element.
596    pub sub_layer_interlaced_source_flag: [bool; 6],
597    /// Sub-layer syntax element.
598    pub sub_layer_non_packed_constraint_flag: [bool; 6],
599    /// Sub-layer syntax element.
600    pub sub_layer_frame_only_constraint_flag: [bool; 6],
601    /// Sub-layer syntax element.
602    pub sub_layer_max_12bit_constraint_flag: [bool; 6],
603    /// Sub-layer syntax element.
604    pub sub_layer_max_10bit_constraint_flag: [bool; 6],
605    /// Sub-layer syntax element.
606    pub sub_layer_max_8bit_constraint_flag: [bool; 6],
607    /// Sub-layer syntax element.
608    pub sub_layer_max_422chroma_constraint_flag: [bool; 6],
609    /// Sub-layer syntax element.
610    pub sub_layer_max_420chroma_constraint_flag: [bool; 6],
611    /// Sub-layer syntax element.
612    pub sub_layer_max_monochrome_constraint_flag: [bool; 6],
613    /// Sub-layer syntax element.
614    pub sub_layer_intra_constraint_flag: [bool; 6],
615    /// Sub-layer syntax element.
616    pub sub_layer_one_picture_only_constraint_flag: [bool; 6],
617    /// Sub-layer syntax element.
618    pub sub_layer_lower_bit_rate_constraint_flag: [bool; 6],
619    /// Sub-layer syntax element.
620    pub sub_layer_max_14bit_constraint_flag: [bool; 6],
621    /// Sub-layer syntax element.
622    pub sub_layer_inbld_flag: [bool; 6],
623    /// Sub-layer syntax element.
624    pub sub_layer_level_idc: [Level; 6],
625}
626
627impl ProfileTierLevel {
628    pub fn max_luma_ps(&self) -> u32 {
629        // See Table A.8.
630        match self.general_level_idc {
631            Level::L1 => 36864,
632            Level::L2 => 122880,
633            Level::L2_1 => 245760,
634            Level::L3 => 552960,
635            Level::L3_1 => 983040,
636            Level::L4 | Level::L4_1 => 2228224,
637            Level::L5 | Level::L5_1 | Level::L5_2 => 8912896,
638            _ => 35651584,
639        }
640    }
641
642    pub fn max_dpb_pic_buf(&self) -> u32 {
643        if self.general_profile_idc >= 1 && self.general_profile_idc <= 5 {
644            6
645        } else {
646            7
647        }
648    }
649}
650
651#[derive(Clone, Debug, Default, PartialEq, Eq)]
652pub struct SpsRangeExtension {
653    pub transform_skip_rotation_enabled_flag: bool,
654    pub transform_skip_context_enabled_flag: bool,
655    pub implicit_rdpcm_enabled_flag: bool,
656    pub explicit_rdpcm_enabled_flag: bool,
657    pub extended_precision_processing_flag: bool,
658    pub intra_smoothing_disabled_flag: bool,
659    pub high_precision_offsets_enabled_flag: bool,
660    pub persistent_rice_adaptation_enabled_flag: bool,
661    pub cabac_bypass_alignment_enabled_flag: bool,
662}
663
664#[derive(Clone, Debug, PartialEq, Eq)]
665pub struct SpsSccExtension {
666    /// When set, specifies that a picture in the CVS may be included in a
667    /// reference picture list of a slice of the picture itself.  When not set,
668    /// specifies that a picture in the CVS is never included in a reference
669    /// picture list of a slice of the picture itself.
670    pub curr_pic_ref_enabled_flag: bool,
671    /// When set, specifies that the decoding process for palette mode may be
672    /// used for intra blocks. When not set, specifies that the decoding process
673    /// for palette mode is not applied.
674    pub palette_mode_enabled_flag: bool,
675    /// Specifies the maximum allowed palette size.
676    pub palette_max_size: u8,
677    /// Specifies the difference between the maximum allowed palette predictor
678    /// size and the maximum allowed palette size.
679    pub delta_palette_max_predictor_size: u8,
680    /// When set, specifies that the sequence palette predictors are initialized
681    /// using the sps_palette_predictor_initializers. When not set, specifies
682    /// that the entries in the sequence palette predictor are initialized to 0.
683    pub palette_predictor_initializers_present_flag: bool,
684    /// num_palette_predictor_initializers_minus1 plus 1 specifies the number of
685    /// entries in the sequence palette predictor initializer.
686    pub num_palette_predictor_initializer_minus1: u8,
687    /// `palette_predictor_initializer[ comp ][ i ]` specifies the value of the
688    /// comp-th component of the i-th palette entry in the SPS that is used to
689    /// initialize the array PredictorPaletteEntries.
690    pub palette_predictor_initializer: [[u32; 128]; 3],
691    /// Controls the presence and inference of the use_integer_mv_flag that
692    /// specifies the resolution of motion vectors for inter prediction.
693    pub motion_vector_resolution_control_idc: u8,
694    /// When set, specifies that the intra boundary filtering process is
695    /// unconditionally disabled for intra prediction.  If not set, specifies
696    /// that the intra boundary filtering process may be used.
697    pub intra_boundary_filtering_disabled_flag: bool,
698}
699
700impl Default for SpsSccExtension {
701    fn default() -> Self {
702        Self {
703            curr_pic_ref_enabled_flag: Default::default(),
704            palette_mode_enabled_flag: Default::default(),
705            palette_max_size: Default::default(),
706            delta_palette_max_predictor_size: Default::default(),
707            palette_predictor_initializers_present_flag: Default::default(),
708            num_palette_predictor_initializer_minus1: Default::default(),
709            palette_predictor_initializer: [[0; 128]; 3],
710            motion_vector_resolution_control_idc: Default::default(),
711            intra_boundary_filtering_disabled_flag: Default::default(),
712        }
713    }
714}
715
716/// A H.265 Sequence Parameter Set.
717#[derive(Clone, Debug, Default, PartialEq, Eq)]
718pub struct Sps {
719    /// Specifies the value of the vps_video_parameter_set_id of the active VPS.
720    pub video_parameter_set_id: u8,
721    /// `max_sub_layers_minus1` plus 1 specifies the maximum number of temporal
722    /// sub-layers that may be present in each CVS referring to the SPS.
723    pub max_sub_layers_minus1: u8,
724    /// When sps_max_sub_layers_minus1 is greater than 0, specifies whether
725    /// inter prediction is additionally restricted for CVSs referring to the
726    /// SPS.
727    pub temporal_id_nesting_flag: bool,
728    /// profile_tier_level() data.
729    pub profile_tier_level: ProfileTierLevel,
730    /// Provides an identifier for the SPS for reference by other syntax
731    /// elements.
732    pub seq_parameter_set_id: u8,
733    /// Specifies the chroma sampling relative to the luma sampling as specified
734    /// in clause 6.2.
735    pub chroma_format_idc: u8,
736    /// When true, specifies that the three colour components of the 4:4:4
737    /// chroma format are coded separately. When false, specifies that the
738    /// colour components are not coded separately.
739    pub separate_colour_plane_flag: bool,
740    /// Specifies the width of each decoded picture in units of luma samples.
741    pub pic_width_in_luma_samples: u16,
742    /// Specifies the height of each decoded picture in units of luma samples.
743    pub pic_height_in_luma_samples: u16,
744    /// When true, indicates that the conformance cropping window offset
745    /// parameters follow next in the SPS. When false, indicates that the
746    /// conformance cropping window offset parameters are not present.
747    pub conformance_window_flag: bool,
748    /* if conformance_window_flag */
749    /// Specify the samples of the pictures in the CVS that are output from the
750    /// decoding process, in terms of a rectangular region specified in picture
751    /// coordinates for output.
752    pub conf_win_left_offset: u32,
753    pub conf_win_right_offset: u32,
754    pub conf_win_top_offset: u32,
755    pub conf_win_bottom_offset: u32,
756
757    /// Specifies the bit depth of the samples of the luma array BitDepthY and
758    /// the value of the luma quantization parameter range offset QpBdOffsetY.
759    pub bit_depth_luma_minus8: u8,
760    /// Specifies the bit depth of the samples of the chroma arrays BitDepthC
761    /// and the value of the chroma quantization parameter range offset
762    /// QpBdOffsetC.
763    pub bit_depth_chroma_minus8: u8,
764    /// Specifies the value of the variable MaxPicOrderCntLsb that is used in
765    /// the decoding process for picture order count.
766    pub log2_max_pic_order_cnt_lsb_minus4: u8,
767    /// When true, specifies that `max_dec_pic_buffering_minus1[ i ]`,
768    /// `max_num_reorder_pics[ i ]` and `max_latency_increase_plus1[ i ]` are
769    /// present for max_sub_layers_minus1 + 1 sub- layers. When false, specifies
770    /// that the values of `max_dec_pic_ buffering_minus1[ max_sub_layers_minus1
771    /// ]`, `max_num_reorder_pics[ max_sub_layers_minus1 ]` and max_
772    /// `latency_increase_plus1[ max_sub_layers_minus1 ]` apply to all sub-layers.
773    pub sub_layer_ordering_info_present_flag: bool,
774    /// `max_dec_pic_buffering_minus1[ i ]` plus 1 specifies the maximum required
775    /// size of the decoded picture buffer for the CVS in units of picture
776    /// storage buffers when HighestTid is equal to i.
777    pub max_dec_pic_buffering_minus1: [u8; 7],
778    /// `max_num_reorder_pics[ i ]` indicates the maximum allowed number of
779    /// pictures with PicOutputFlag equal to 1 that can precede any picture with
780    /// PicOutputFlag equal to 1 in the CVS in decoding order and follow that
781    /// picture with PicOutputFlag equal to 1 in output order when HighestTid is
782    /// equal to i.
783    pub max_num_reorder_pics: [u8; 7],
784    /// `max_latency_increase_plus1[ i ]` not equal to 0 is used to compute the
785    /// value of `SpsMaxLatencyPictures[ i ]`, which specifies the maximum number
786    /// of pictures with PicOutputFlag equal to 1 that can precede any picture
787    /// with PicOutputFlag equal to 1 in the CVS in output order and follow that
788    /// picture with PicOutputFlag equal to 1 in decoding order when HighestTid
789    /// is equal to i.
790    pub max_latency_increase_plus1: [u8; 7],
791    /// min_luma_coding_block_size_minus3 plus 3 specifies the minimum luma
792    /// coding block size.
793    pub log2_min_luma_coding_block_size_minus3: u8,
794    /// Specifies the difference between the maximum and minimum luma coding
795    /// block size.
796    pub log2_diff_max_min_luma_coding_block_size: u8,
797    /// min_luma_transform_block_size_minus2 plus 2 specifies the minimum luma
798    /// transform block size.
799    pub log2_min_luma_transform_block_size_minus2: u8,
800    /// Specifies the difference between the maximum and minimum luma transform
801    /// block size.
802    pub log2_diff_max_min_luma_transform_block_size: u8,
803    /// Specifies the maximum hierarchy depth for transform units of coding
804    /// units coded in inter prediction mode.
805    pub max_transform_hierarchy_depth_inter: u8,
806    /// Specifies the maximum hierarchy depth for transform units of coding
807    /// units coded in intra prediction mode.
808    pub max_transform_hierarchy_depth_intra: u8,
809    /// When true, specifies that a scaling list is used for the scaling process
810    /// for transform coefficients. When false, specifies that scaling list is
811    /// not used for the scaling process for transform coefficients.
812    pub scaling_list_enabled_flag: bool,
813    /* if scaling_list_enabled_flag */
814    /// When true, specifies that the scaling_list_data( ) syntax structure is
815    /// present in the SPS. When false, specifies that the scaling_list_data( )
816    /// syntax structure is not present in the SPS.
817    pub scaling_list_data_present_flag: bool,
818    /// The scaling_list_data() syntax data.
819    pub scaling_list: ScalingLists,
820    /// When true, specifies that asymmetric motion partitions, i.e., PartMode
821    /// equal to PART_2NxnU, PART_2NxnD, PART_nLx2N or PART_nRx2N, may be used
822    /// in CTBs. When false, specifies that asymmetric motion partitions cannot
823    /// be used in CTBs.
824    pub amp_enabled_flag: bool,
825    /// When true, specifies that the sample adaptive offset process is applied
826    /// to the reconstructed picture after the deblocking filter process.  When
827    /// false, specifies that the sample adaptive offset process is not applied
828    /// to the reconstructed picture after the deblocking filter process.
829    pub sample_adaptive_offset_enabled_flag: bool,
830    /// When false, specifies that PCM-related syntax
831    /// (pcm_sample_bit_depth_luma_minus1, pcm_sample_ bit_depth_chroma_minus1,
832    /// log2_min_pcm_luma_coding_block_size_minus3, log2_diff_max_min_pcm_luma_
833    /// coding_block_size, pcm_loop_filter_disabled_flag, pcm_flag,
834    /// pcm_alignment_zero_bit syntax elements and pcm_sample( ) syntax
835    /// structure) is not present in the CVS.
836    pub pcm_enabled_flag: bool,
837
838    /* if pcm_enabled_flag */
839    pub pcm_sample_bit_depth_luma_minus1: u8,
840    /// Specifies the number of bits used to represent each of PCM sample values
841    /// of the luma component.
842    pub pcm_sample_bit_depth_chroma_minus1: u8,
843    /// Specifies the number of bits used to represent each of PCM sample values
844    /// of the chroma components.
845    pub log2_min_pcm_luma_coding_block_size_minus3: u8,
846    /// Specifies the difference between the maximum and minimum size of coding
847    /// blocks with pcm_flag equal to true.
848    pub log2_diff_max_min_pcm_luma_coding_block_size: u8,
849    /// Specifies whether the loop filter process is disabled on reconstructed
850    /// samples in a coding unit with pcm_flag equal to true as follows:
851    ///
852    /// – If pcm_loop_filter_disabled_flag is set, the deblocking filter and
853    /// sample adaptive offset filter processes on the reconstructed samples in
854    /// a coding unit with pcm_flag set are disabled.
855    ///
856    /// – Otherwise (pcm_loop_filter_disabled_flag value is not set), the
857    /// deblocking filter and sample adaptive offset filter processes on the
858    /// reconstructed samples in a coding unit with pcm_flag set are not
859    /// disabled.
860    pub pcm_loop_filter_disabled_flag: bool,
861    /// Specifies the number of st_ref_pic_set( ) syntax structures included in
862    /// the SPS.
863    pub num_short_term_ref_pic_sets: u8,
864    /// the st_ref_pic_set() data.
865    pub short_term_ref_pic_set: Vec<ShortTermRefPicSet>,
866    /// If unset, specifies that no long-term reference picture is used for
867    /// inter prediction of any coded picture in the CVS.
868    /// If set, specifies that long-term reference pictures may be used for
869    /// inter prediction of one or more coded pictures in the CVS.
870    pub long_term_ref_pics_present_flag: bool,
871
872    /* if long_term_ref_pics_present_flag */
873    /// Specifies the number of candidate long-term reference pictures that are
874    /// specified in the SPS.
875    pub num_long_term_ref_pics_sps: u8,
876    /// `lt_ref_pic_poc_lsb_sps[ i ]` specifies the picture order count modulo
877    /// MaxPicOrderCntLsb of the i-th candidate long-term reference picture
878    /// specified in the SPS.
879    pub lt_ref_pic_poc_lsb_sps: [u32; MAX_LONG_TERM_REF_PIC_SETS],
880    /// `used_by_curr_pic_lt_sps_flag[ i ]` equal to false specifies that the i-th
881    /// candidate long-term reference picture specified in the SPS is not used
882    /// for reference by a picture that includes in its long-term reference
883    /// picture set (RPS) the i-th candidate long-term reference picture
884    /// specified in the SPS.
885    pub used_by_curr_pic_lt_sps_flag: [bool; MAX_LONG_TERM_REF_PIC_SETS],
886    /// When set, specifies that slice_temporal_mvp_enabled_flag is present in
887    /// the slice headers of non-IDR pictures in the CVS. When not set,
888    /// specifies that slice_temporal_mvp_enabled_flag is not present in slice
889    /// headers and that temporal motion vector predictors are not used in the
890    /// CVS.
891    pub temporal_mvp_enabled_flag: bool,
892    /// When set, specifies that bi-linear interpolation is conditionally used
893    /// in the intraprediction filtering process in the CVS as specified in
894    /// clause 8.4.4.2.3.
895    pub strong_intra_smoothing_enabled_flag: bool,
896    /// When set, specifies that the vui_parameters( ) syntax structure as
897    /// specified in Annex E is present. When not set, specifies that the
898    /// vui_parameters( ) syntax structure as specified in Annex E is not
899    /// present.
900    pub vui_parameters_present_flag: bool,
901    /// The vui_parameters() data.
902    pub vui_parameters: VuiParams,
903    /// When set, specifies that the syntax elements sps_range_extension_flag,
904    /// sps_multilayer_extension_flag, sps_3d_extension_flag,
905    /// sps_scc_extension_flag, and sps_extension_4bits are present in the SPS
906    /// RBSP syntax structure. When not set, specifies that these syntax
907    /// elements are not present.
908    pub extension_present_flag: bool,
909
910    pub range_extension_flag: bool,
911    /// The sps_range_extension() data.
912    pub range_extension: SpsRangeExtension,
913    /// When set, specifies that the sps_scc_extension( ) syntax structure is
914    /// present in the SPS RBSP syntax structure. When not set, specifies that
915    /// this syntax structure is not present
916    pub scc_extension_flag: bool,
917    /// The sps_scc_extension() data.
918    pub scc_extension: SpsSccExtension,
919
920    // Internal H265 variables. Computed from the bitstream.
921    /// Equivalent to MinCbLog2SizeY in the specification.
922    pub min_cb_log2_size_y: u32,
923    /// Equivalent to CtbLog2SizeY in the specification.
924    pub ctb_log2_size_y: u32,
925    /// Equivalent to CtbSizeY in the specification.
926    pub ctb_size_y: u32,
927    /// Equivalent to PicHeightInCtbsY in the specification.
928    pub pic_height_in_ctbs_y: u32,
929    /// Equivalent to PicWidthInCtbsY in the specification.
930    pub pic_width_in_ctbs_y: u32,
931    /// Equivalent to PicSizeInCtbsY in the specification.
932    pub pic_size_in_ctbs_y: u32,
933    /// Equivalent to ChromaArrayType in the specification.
934    pub chroma_array_type: u8,
935    /// Equivalent to WpOffsetHalfRangeY in the specification.
936    pub wp_offset_half_range_y: u32,
937    /// Equivalent to WpOffsetHalfRangeC in the specification.
938    pub wp_offset_half_range_c: u32,
939    /// Equivalent to MaxTbLog2SizeY in the specification.
940    pub max_tb_log2_size_y: u32,
941    /// Equivalent to PicSizeInSamplesY in the specification.
942    pub pic_size_in_samples_y: u32,
943
944    /// The VPS referenced by this SPS, if any.
945    pub vps: Option<Rc<Vps>>,
946}
947
948impl Sps {
949    pub fn max_dpb_size(&self) -> usize {
950        let max_luma_ps = self.profile_tier_level.max_luma_ps();
951        let max_dpb_pic_buf = self.profile_tier_level.max_dpb_pic_buf();
952
953        // Equation A-2
954        let max = if self.pic_size_in_samples_y <= (max_luma_ps >> 2) {
955            std::cmp::min(4 * max_dpb_pic_buf, 16)
956        } else if self.pic_size_in_samples_y <= (max_luma_ps >> 1) {
957            std::cmp::min(2 * max_dpb_pic_buf, 16)
958        } else if self.pic_size_in_samples_y <= ((3 * max_luma_ps) >> 2) {
959            std::cmp::min(4 * max_dpb_pic_buf / 3, 16)
960        } else {
961            max_dpb_pic_buf
962        };
963
964        max as usize
965    }
966
967    pub fn width(&self) -> u16 {
968        self.pic_width_in_luma_samples
969    }
970
971    pub fn height(&self) -> u16 {
972        self.pic_height_in_luma_samples
973    }
974
975    pub fn visible_rectangle(&self) -> Rect<u32> {
976        // From the specification:
977        // NOTE 3 – The conformance cropping window offset parameters are
978        // only applied at the output. All internal decoding processes are
979        // applied to the uncropped picture size.
980        if !self.conformance_window_flag {
981            return Rect {
982                min: Point { x: 0, y: 0 },
983                max: Point { x: u32::from(self.width()), y: u32::from(self.height()) },
984            };
985        }
986        const SUB_HEIGHT_C: [u32; 5] = [1, 2, 1, 1, 1];
987        const SUB_WIDTH_C: [u32; 5] = [1, 2, 2, 1, 1];
988
989        let crop_unit_y = SUB_HEIGHT_C[usize::from(self.chroma_array_type)];
990        let crop_unit_x = SUB_WIDTH_C[usize::from(self.chroma_array_type)];
991        let crop_left = crop_unit_x * self.conf_win_left_offset;
992        let crop_right = crop_unit_x * self.conf_win_right_offset;
993        let crop_top = crop_unit_y * self.conf_win_top_offset;
994        let crop_bottom = crop_unit_y * self.conf_win_bottom_offset;
995
996        Rect {
997            min: Point { x: crop_left, y: crop_top },
998            max: Point {
999                x: u32::from(self.width()) - crop_left - crop_right,
1000                y: u32::from(self.height()) - crop_top - crop_bottom,
1001            },
1002        }
1003    }
1004}
1005
1006#[derive(Clone, Debug, PartialEq, Eq)]
1007pub struct PpsSccExtension {
1008    /// When set, specifies that a picture referring to the PPS may be included
1009    /// in a reference picture list of a slice of the picture itself.  If not
1010    /// set, specifies that a picture referring to the PPS is never included in
1011    /// a reference picture list of a slice of the picture itself.
1012    pub curr_pic_ref_enabled_flag: bool,
1013    /// When set, specifies that an adaptive colour transform may be applied to
1014    /// the residual in the decoding process. When not set, specifies that
1015    /// adaptive colour transform is not applied to the residual.
1016    pub residual_adaptive_colour_transform_enabled_flag: bool,
1017    /// When set, specifies that slice_act_y_qp_offset, slice_act_cb_qp_offset,
1018    /// slice_act_cr_qp_offset are present in the slice header.  When not set,
1019    /// specifies that slice_act_y_qp_offset, slice_act_cb_qp_offset,
1020    /// slice_act_cr_qp_offset are not present in the slice header.
1021    pub slice_act_qp_offsets_present_flag: bool,
1022    /// See the specificartion for more details.
1023    pub act_y_qp_offset_plus5: i8,
1024    /// See the specificartion for more details.
1025    pub act_cb_qp_offset_plus5: i8,
1026    /// See the specificartion for more details.
1027    pub act_cr_qp_offset_plus3: i8,
1028    /// When set, specifies that the palette predictor initializers used for the
1029    /// pictures referring to the PPS are derived based on the palette predictor
1030    /// initializers specified by the PPS. If not set, specifies that the
1031    /// palette predictor initializers used for the pictures referring to the
1032    /// PPS are inferred to be equal to those specified by the active SPS.
1033    pub palette_predictor_initializers_present_flag: bool,
1034    /// Specifies the number of entries in the picture palette predictor
1035    /// initializer.
1036    pub num_palette_predictor_initializers: u8,
1037    /// When set, specifies that the pictures that refer to this PPS are
1038    /// monochrome. If not set, specifies that the pictures that refer to this
1039    /// PPS have multiple components.
1040    pub monochrome_palette_flag: bool,
1041    /// luma_bit_depth_entry_minus8 plus 8 specifies the bit depth of the luma
1042    /// component of the entries of the palette predictor initializer.
1043    pub luma_bit_depth_entry_minus8: u8,
1044    /// chroma_bit_depth_entry_minus8 plus 8 specifies the bit depth of the
1045    /// chroma components of the entries of the palette predictor initializer.
1046    pub chroma_bit_depth_entry_minus8: u8,
1047    /// `pps_palette_predictor_initializer[ comp ][ i ]` specifies the value of
1048    /// the comp-th component of the i-th palette entry in the PPS that is used
1049    /// to initialize the array PredictorPaletteEntries.
1050    pub palette_predictor_initializer: [[u8; 128]; 3],
1051}
1052
1053impl Default for PpsSccExtension {
1054    fn default() -> Self {
1055        Self {
1056            curr_pic_ref_enabled_flag: Default::default(),
1057            residual_adaptive_colour_transform_enabled_flag: Default::default(),
1058            slice_act_qp_offsets_present_flag: Default::default(),
1059            act_y_qp_offset_plus5: Default::default(),
1060            act_cb_qp_offset_plus5: Default::default(),
1061            act_cr_qp_offset_plus3: Default::default(),
1062            palette_predictor_initializers_present_flag: Default::default(),
1063            num_palette_predictor_initializers: Default::default(),
1064            monochrome_palette_flag: Default::default(),
1065            luma_bit_depth_entry_minus8: Default::default(),
1066            chroma_bit_depth_entry_minus8: Default::default(),
1067            palette_predictor_initializer: [[0; 128]; 3],
1068        }
1069    }
1070}
1071
1072#[derive(Clone, Debug, Default, PartialEq, Eq)]
1073pub struct PpsRangeExtension {
1074    /// log2_max_transform_skip_block_size_minus2 plus 2 specifies the maximum
1075    /// transform block size for which transform_skip_flag may be present in
1076    /// coded pictures referring to the PPS. When not present, the value of
1077    /// log2_max_transform_skip_block_size_minus2 is inferred to be equal to 0.
1078    /// When present, the value of log2_max_transform_skip_block_size_minus2
1079    /// shall be less than or equal to MaxTbLog2SizeY − 2.
1080    pub log2_max_transform_skip_block_size_minus2: u32,
1081    /// When set, specifies that log2_res_scale_abs_plus1 and
1082    /// res_scale_sign_flag may be present in the transform unit syntax for
1083    /// pictures referring to the PPS. When not set, specifies that
1084    /// log2_res_scale_abs_plus1 and res_scale_sign_flag are not present for
1085    /// pictures referring to the PPS.
1086    pub cross_component_prediction_enabled_flag: bool,
1087    /// When set, specifies that the cu_chroma_qp_offset_flag may be present in
1088    /// the transform unit syntax. When not set, specifies that the
1089    /// cu_chroma_qp_offset_flag is not present in the transform unit syntax.
1090    pub chroma_qp_offset_list_enabled_flag: bool,
1091    /// Specifies the difference between the luma CTB size and the minimum luma
1092    /// coding block size of coding units that convey cu_chroma_qp_offset_flag.
1093    pub diff_cu_chroma_qp_offset_depth: u32,
1094    /// chroma_qp_offset_list_len_minus1 plus 1 specifies the number of
1095    /// `cb_qp_offset_list[ i ]` and `cr_qp_offset_list[ i ]` syntax elements that
1096    /// are present in the PPS.
1097    pub chroma_qp_offset_list_len_minus1: u32,
1098    /// Specify offsets used in the derivation of Qp′Cb and Qp′Cr, respectively.
1099    pub cb_qp_offset_list: [i32; 6],
1100    /// Specify offsets used in the derivation of Qp′Cb and Qp′Cr, respectively.
1101    pub cr_qp_offset_list: [i32; 6],
1102    /// The base 2 logarithm of the scaling parameter that is used to scale
1103    /// sample adaptive offset (SAO) offset values for luma samples.
1104    pub log2_sao_offset_scale_luma: u32,
1105    /// The base 2 logarithm of the scaling parameter that is used to scale SAO
1106    /// offset values for chroma samples.
1107    pub log2_sao_offset_scale_chroma: u32,
1108}
1109
1110/// A H.265 Picture Parameter Set.
1111#[derive(Clone, Debug, PartialEq, Eq)]
1112pub struct Pps {
1113    /// Identifies the PPS for reference by other syntax elements.
1114    pub pic_parameter_set_id: u8,
1115    /// Specifies the value of sps_seq_parameter_set_id for the active SPS.
1116    pub seq_parameter_set_id: u8,
1117    /// When set, specifies the presence of the syntax element
1118    /// dependent_slice_segment_flag in the slice segment headers for coded
1119    /// pictures referring to the PPS. When not set, specifies the absence of
1120    /// the syntax element dependent_slice_segment_flag in the slice segment
1121    /// headers for coded pictures referring to the PPS.
1122    pub dependent_slice_segments_enabled_flag: bool,
1123    /// When set, indicates that the pic_output_flag syntax element is present
1124    /// in the associated slice headers. When not set, indicates that the
1125    /// pic_output_flag syntax element is not present in the associated slice
1126    /// headers.
1127    pub output_flag_present_flag: bool,
1128    /// Specifies the number of extra slice header bits that are present in the
1129    /// slice header RBSP for coded pictures referring to the PPS.
1130    pub num_extra_slice_header_bits: u8,
1131    /// When not set, specifies that sign bit hiding is disabled. Whens set,
1132    /// specifies that sign bit hiding is enabled.
1133    pub sign_data_hiding_enabled_flag: bool,
1134    /// When set, specifies that cabac_init_flag is present in slice headers
1135    /// referring to the PPS. When not set, specifies that cabac_init_flag is
1136    /// not present in slice headers referring to the PPS.
1137    pub cabac_init_present_flag: bool,
1138    /// Specifies the inferred value of num_ref_idx_l0_active_minus1 for P and B
1139    /// slices with num_ref_idx_active_override_flag not set.
1140    pub num_ref_idx_l0_default_active_minus1: u8,
1141    /// Specifies the inferred value of num_ref_idx_l1_active_minus1 for B
1142    /// slices with num_ref_idx_active_override_flag not set.
1143    pub num_ref_idx_l1_default_active_minus1: u8,
1144    /// init_qp_minus26 plus 26 specifies the initial value of SliceQpY for each
1145    /// slice referring to the PPS. The initial value of SliceQpY is modified at
1146    /// the slice segment layer when a non-zero value of slice_qp_delta is
1147    /// decoded.
1148    pub init_qp_minus26: i8,
1149    /// When not set, specifies that intra prediction allows usage of residual
1150    /// data and decoded samples of neighbouring coding blocks coded using
1151    /// either intra or inter prediction modes. When set, specifies constrained
1152    /// intra prediction, in which case intra prediction only uses residual data
1153    /// and decoded samples from neighbouring coding blocks coded using intra
1154    /// prediction modes.
1155    pub constrained_intra_pred_flag: bool,
1156    /// When set, specifies that transform_skip_flag may be present in the
1157    /// residual coding syntax. When not set, specifies that transform_skip_flag
1158    /// is not present in the residual coding syntax.
1159    pub transform_skip_enabled_flag: bool,
1160    /// When set, specifies that the diff_cu_qp_delta_depth syntax element is
1161    /// present in the PPS and that cu_qp_delta_abs may be present in the
1162    /// transform unit syntax and the palette syntax. When not set, specifies
1163    /// that the diff_cu_qp_delta_depth syntax element is not present in the PPS
1164    /// and that cu_qp_delta_abs is not present in the transform unit syntax and
1165    /// the palette syntax.
1166    pub cu_qp_delta_enabled_flag: bool,
1167
1168    /*if cu_qp_delta_enabled_flag */
1169    /// Specifies the difference between the luma CTB size and the minimum luma
1170    /// coding block size of coding units that convey cu_qp_delta_abs and
1171    /// cu_qp_delta_sign_flag.
1172    pub diff_cu_qp_delta_depth: u8,
1173    /// Specifies the offsets to the luma quantization parameter Qp′Y used for
1174    /// deriving Qp′Cb and Qp′Cr, respectively.
1175    pub cb_qp_offset: i8,
1176    /// Specifies the offsets to the luma quantization parameter Qp′Y used for
1177    /// deriving Qp′Cb and Qp′Cr, respectively.
1178    pub cr_qp_offset: i8,
1179    /// When set, indicates that the slice_cb_qp_offset and slice_cr_qp_offset
1180    /// syntax elements are present in the associated slice headers.  When not
1181    /// set, indicates that these syntax elements are not present in the
1182    /// associated slice headers. When ChromaArrayType is equal to 0,
1183    /// pps_slice_chroma_qp_offsets_present_flag shall be equal to 0
1184    pub slice_chroma_qp_offsets_present_flag: bool,
1185    /// When not set, specifies that weighted prediction is not applied to P
1186    /// slices. When set, specifies that weighted prediction is applied to P
1187    /// slices.
1188    pub weighted_pred_flag: bool,
1189    /// When not set, specifies that the default weighted prediction is applied
1190    /// to B slices. When set, specifies that weighted prediction is applied to
1191    /// B slices.
1192    pub weighted_bipred_flag: bool,
1193    /// When set, specifies that `cu_transquant_bypass_flag` is present, When
1194    /// not set, specifies that `cu_transquant_bypass_flag` is not present.
1195    pub transquant_bypass_enabled_flag: bool,
1196    /// When set, specifies that there is more than one tile in each picture
1197    /// referring to the PPS. When not set, specifies that there is only one
1198    /// tile in each picture referring to the PPS.
1199    pub tiles_enabled_flag: bool,
1200    /// When set, specifies that a specific synchronization process for context
1201    /// variables, and when applicable, Rice parameter initialization states and
1202    /// palette predictor variables, is invoked before decoding the CTU which
1203    /// includes the first CTB of a row of CTBs in each tile in each picture
1204    /// referring to the PPS, and a specific storage process for context
1205    /// variables, and when applicable, Rice parameter initialization states and
1206    /// palette predictor variables, is invoked after decoding the CTU which
1207    /// includes the second CTB of a row of CTBs in each tile in each picture
1208    /// referring to the PPS. When not set, specifies that no specific
1209    /// synchronization process for context variables, and when applicable, Rice
1210    /// parameter initialization states and palette predictor variables, is
1211    /// required to be invoked before decoding the CTU which includes the first
1212    /// CTB of a row of CTBs in each tile in each picture referring to the PPS,
1213    /// and no specific storage process for context variables, and when
1214    /// applicable, Rice parameter initialization states and palette predictor
1215    /// variables, is required to be invoked after decoding the CTU which
1216    /// includes the second CTB of a row of CTBs in each tile in each picture
1217    /// referring to the PPS.
1218    pub entropy_coding_sync_enabled_flag: bool,
1219    /// num_tile_columns_minus1 plus 1 specifies the number of tile columns
1220    /// partitioning the picture.
1221    pub num_tile_columns_minus1: u8,
1222    /// num_tile_rows_minus1 plus 1 specifies the number of tile rows
1223    /// partitioning the picture.
1224    pub num_tile_rows_minus1: u8,
1225    /// When set, specifies that tile column boundaries and likewise tile row
1226    /// boundaries are distributed uniformly across the picture.  When not set,
1227    /// specifies that tile column boundaries and likewise tile row boundaries
1228    /// are not distributed uniformly across the picture but signalled
1229    /// explicitly using the syntax elements `column_width_minus1[ i ]` and
1230    /// `row_height_minus1[ i ]`.
1231    pub uniform_spacing_flag: bool,
1232    /// `column_width_minus1[ i ]` plus 1 specifies the width of the i-th tile
1233    /// column in units of CTBs.
1234    pub column_width_minus1: [u32; 19],
1235    /// `row_height_minus1[ i ]` plus 1 specifies the height of the i-th tile row
1236    /// in units of CTBs.
1237    pub row_height_minus1: [u32; 21],
1238    /// When set, specifies that in-loop filtering operations may be performed
1239    /// across tile boundaries in pictures referring to the PPS.  When not set,
1240    /// specifies that in-loop filtering operations are not performed across
1241    /// tile boundaries in pictures referring to the PPS. The in-loop filtering
1242    /// operations include the deblocking filter and sample adaptive offset
1243    /// filter operations.
1244    pub loop_filter_across_tiles_enabled_flag: bool,
1245    /// When set, specifies that in-loop filtering operations may be performed
1246    /// across left and upper boundaries of slices referring to the PPS.  When
1247    /// not set, specifies that in-loop filtering operations are not performed
1248    /// across left and upper boundaries of slices referring to the PPS. The in-
1249    /// loop filtering operations include the deblocking filter and sample
1250    /// adaptive offset filter operations.
1251    pub loop_filter_across_slices_enabled_flag: bool,
1252    /// When set, specifies the presence of deblocking filter control syntax
1253    /// elements in the PPS. When not set, specifies the absence of deblocking
1254    /// filter control syntax elements in the PPS.
1255    pub deblocking_filter_control_present_flag: bool,
1256    /// When set, specifies the presence of deblocking_filter_override_flag in
1257    /// the slice headers for pictures referring to the PPS.  When not set,
1258    /// specifies the absence of deblocking_filter_override_flag in the slice
1259    /// headers for pictures referring to the PPS.
1260    pub deblocking_filter_override_enabled_flag: bool,
1261    /// When set, specifies that the operation of deblocking filter is not
1262    /// applied for slices referring to the PPS in which
1263    /// slice_deblocking_filter_disabled_flag is not present.  When not set,
1264    /// specifies that the operation of the deblocking filter is applied for
1265    /// slices referring to the PPS in which
1266    /// slice_deblocking_filter_disabled_flag is not present.
1267    pub deblocking_filter_disabled_flag: bool,
1268    /// Specify the default deblocking parameter offsets for β and tC (divided
1269    /// by 2) that are applied for slices referring to the PPS, unless the
1270    /// default deblocking parameter offsets are overridden by the deblocking
1271    /// parameter offsets present in the slice headers of the slices referring
1272    /// to the PPS.
1273    pub beta_offset_div2: i8,
1274    /// Specify the default deblocking parameter offsets for β and tC (divided
1275    /// by 2) that are applied for slices referring to the PPS, unless the
1276    /// default deblocking parameter offsets are overridden by the deblocking
1277    /// parameter offsets present in the slice headers of the slices referring
1278    /// to the PPS.
1279    pub tc_offset_div2: i8,
1280    /// When set, specifies that the scaling list data used for the pictures
1281    /// referring to the PPS are derived based on the scaling lists specified by
1282    /// the active SPS and the scaling lists specified by the PPS.
1283    /// pps_scaling_list_data_present_flag equal to 0 specifies that the scaling
1284    /// list data used for the pictures referring to the PPS are inferred to be
1285    /// equal to those specified by the active SPS.
1286    pub scaling_list_data_present_flag: bool,
1287    /// The scaling list data.
1288    pub scaling_list: ScalingLists,
1289    /// When set, specifies that the syntax structure
1290    /// ref_pic_lists_modification( ) is present in the slice segment header.
1291    /// When not set, specifies that the syntax structure
1292    /// ref_pic_lists_modification( ) is not present in the slice segment header
1293    pub lists_modification_present_flag: bool,
1294    /// log2_parallel_merge_level_minus2 plus 2 specifies the value of the
1295    /// variable Log2ParMrgLevel, which is used in the derivation process for
1296    /// luma motion vectors for merge mode as specified in clause 8.5.3.2.2 and
1297    /// the derivation process for spatial merging candidates as specified in
1298    /// clause 8.5.3.2.3.
1299    pub log2_parallel_merge_level_minus2: u8,
1300    /// When not set, specifies that no slice segment header extension syntax
1301    /// elements are present in the slice segment headers for coded pictures
1302    /// referring to the PPS. When set, specifies that slice segment header
1303    /// extension syntax elements are present in the slice segment headers for
1304    /// coded pictures referring to the PPS.
1305    pub slice_segment_header_extension_present_flag: bool,
1306    /// When set, specifies that the syntax elements pps_range_extension_flag,
1307    /// pps_multilayer_extension_flag, pps_3d_extension_flag,
1308    /// pps_scc_extension_flag, and pps_extension_4bits are present in the
1309    /// picture parameter set RBSP syntax structure. When not set, specifies
1310    /// that these syntax elements are not present.
1311    pub extension_present_flag: bool,
1312    /// When setspecifies that the pps_range_extension( ) syntax structure is
1313    /// present in the PPS RBSP syntax structure. When not set, specifies that
1314    /// this syntax structure is not present.
1315    pub range_extension_flag: bool,
1316    /// The range extension data.
1317    pub range_extension: PpsRangeExtension,
1318
1319    pub scc_extension_flag: bool,
1320    /// The SCC extension data.
1321    pub scc_extension: PpsSccExtension,
1322
1323    // Internal variables.
1324    /// Equivalent to QpBdOffsetY in the specification.
1325    pub qp_bd_offset_y: u32,
1326
1327    /// The SPS referenced by this PPS.
1328    pub sps: Rc<Sps>,
1329}
1330
1331#[derive(Clone, Debug, PartialEq, Eq)]
1332pub struct ScalingLists {
1333    /// plus 8 specifies the value of the variable `ScalingFactor[ 2 ][ matrixId
1334    /// ] [ 0 ][ 0 ]` for the scaling list for the 16x16 size.
1335    pub scaling_list_dc_coef_minus8_16x16: [i16; 6],
1336    /// plus 8 specifies the value of the variable `ScalingFactor[ 3 ][ matrixId
1337    /// ][ 0 ][ 0 ]` for the scaling list for the 32x32 size.
1338    pub scaling_list_dc_coef_minus8_32x32: [i16; 6],
1339    /// The 4x4 scaling list.
1340    pub scaling_list_4x4: [[u8; 16]; 6],
1341    /// The 8x8 scaling list.
1342    pub scaling_list_8x8: [[u8; 64]; 6],
1343    /// The 16x16 scaling list.
1344    pub scaling_list_16x16: [[u8; 64]; 6],
1345    /// The 32x32 scaling list.
1346    pub scaling_list_32x32: [[u8; 64]; 6],
1347}
1348
1349impl Default for ScalingLists {
1350    fn default() -> Self {
1351        Self {
1352            scaling_list_dc_coef_minus8_16x16: Default::default(),
1353            scaling_list_dc_coef_minus8_32x32: Default::default(),
1354            scaling_list_4x4: Default::default(),
1355            scaling_list_8x8: [[0; 64]; 6],
1356            scaling_list_16x16: [[0; 64]; 6],
1357            scaling_list_32x32: [[0; 64]; 6],
1358        }
1359    }
1360}
1361
1362#[derive(Clone, Debug, Default, PartialEq, Eq)]
1363pub struct RefPicListModification {
1364    /// Whenset, indicates that reference picture list 0 is specified explicitly
1365    /// by a list of `list_entry_l0[ i ]` values.  When not set, indicates that
1366    /// reference picture list 0 is determined implicitly.
1367    pub ref_pic_list_modification_flag_l0: bool,
1368    /// `list_entry_l0[ i ]` specifies the index of the reference picture in
1369    /// RefPicListTemp0 to be placed at the current position of reference
1370    /// picture list 0.
1371    pub list_entry_l0: Vec<u32>,
1372    /// Whenset, indicates that reference picture list 1 is specified explicitly
1373    /// by a list of `list_entry_l1[ i ]` values.  When not set, indicates that
1374    /// reference picture list 1 is determined implicitly.
1375    pub ref_pic_list_modification_flag_l1: bool,
1376    /// `list_entry_l1[ i ]` specifies the index of the reference picture in
1377    /// RefPicListTemp1 to be placed at the current position of reference
1378    /// picture list 1.
1379    pub list_entry_l1: Vec<u32>,
1380}
1381
1382#[derive(Clone, Debug, Default, PartialEq, Eq)]
1383pub struct PredWeightTable {
1384    /// The base 2 logarithm of the denominator for all luma weighting factors.
1385    pub luma_log2_weight_denom: u8,
1386    /// The difference of the base 2 logarithm of the denominator for all chroma
1387    /// weighting factors.
1388    pub delta_chroma_log2_weight_denom: i8,
1389    /// `luma_weight_l0_flag[ i ]` set specifies that weighting factors for the
1390    /// luma component of list 0 prediction using `RefPicList0[ i ]` are present.
1391    /// `luma_weight_l0_flag[ i ]` not set specifies that these weighting factors
1392    /// are not present.
1393    pub luma_weight_l0_flag: [bool; 15],
1394    /// `chroma_weight_l0_flag[ i ]` set specifies that weighting factors for the
1395    /// chroma prediction values of list 0 prediction using `RefPicList0[ i ]` are
1396    /// present. `chroma_weight_l0_flag[ i ]` not set specifies that these
1397    /// weighting factors are not present.
1398    pub chroma_weight_l0_flag: [bool; 15],
1399    /// `delta_luma_weight_l0[ i ]` is the difference of the weighting factor
1400    /// applied to the luma prediction value for list 0 prediction using
1401    /// `RefPicList0[ i ]`.
1402    pub delta_luma_weight_l0: [i8; 15],
1403    /// `luma_offset_l0[ i ]` is the additive offset applied to the luma
1404    /// prediction value for list 0 prediction using `RefPicList0[ i ]`.
1405    pub luma_offset_l0: [i8; 15],
1406    /// `delta_chroma_weight_l0[ i ][ j ]` is the difference of the weighting
1407    /// factor applied to the chroma prediction values for list 0 prediction
1408    /// using `RefPicList0[ i ]` with j equal to 0 for Cb and j equal to 1 for Cr.
1409    pub delta_chroma_weight_l0: [[i8; 2]; 15],
1410    /// `delta_chroma_offset_l0[ i ][ j ]` is the difference of the additive
1411    /// offset applied to the chroma prediction values for list 0 prediction
1412    /// using `RefPicList0[ i ]` with j equal to 0 for Cb and j equal to 1 for Cr.
1413    pub delta_chroma_offset_l0: [[i16; 2]; 15],
1414
1415    // `luma_weight_l1_flag[ i ]`, `chroma_weight_l1_flag[ i ]`,
1416    // `delta_luma_weight_l1[ i ]`, `luma_offset_l1[ i ]`, delta_chroma_weight_l1[ i
1417    // `][ j ]` and `delta_chroma_offset_l1[ i ]`[ j ] have the same
1418    // `semanticsasluma_weight_l0_flag[ i ]`, `chroma_weight_l0_flag[ i ]`,
1419    // `delta_luma_weight_l0[ i ]`, `luma_offset_l0[ i ]`, `delta_chroma_weight_l0[ i
1420    // ][ j ]` and `delta_chroma_offset_l0[ i ][ j ]`, respectively, with `l0`, `L0`,
1421    // `list 0` and `List0` replaced by `l1`, `L1`, `list 1` and `List1`, respectively.
1422    pub luma_weight_l1_flag: [bool; 15],
1423    pub chroma_weight_l1_flag: [bool; 15],
1424    pub delta_luma_weight_l1: [i8; 15],
1425    pub luma_offset_l1: [i8; 15],
1426
1427    pub delta_chroma_weight_l1: [[i8; 2]; 15],
1428    pub delta_chroma_offset_l1: [[i16; 2]; 15],
1429
1430    // Calculated.
1431    /// Same as ChromaLog2WeightDenom in the specification.
1432    pub chroma_log2_weight_denom: u8,
1433}
1434
1435#[derive(Clone, Debug, PartialEq, Eq)]
1436pub struct ShortTermRefPicSet {
1437    /// When set, specifies that the stRpsIdx-th candidate short-term RPS is
1438    /// predicted from another candidate short-term RPS, which is referred to as
1439    /// the source candidate short-term RPS.
1440    pub inter_ref_pic_set_prediction_flag: bool,
1441    /// delta_idx_minus1 plus 1 specifies the difference between the value of
1442    /// stRpsIdx and the index, into the list of the candidate short-term RPSs
1443    /// specified in the SPS, of the source candidate short-term RPS.
1444    pub delta_idx_minus1: u8,
1445    /// delta_rps_sign and abs_delta_rps_minus1 together specify the value of
1446    /// the variable deltaRps.
1447    pub delta_rps_sign: bool,
1448    /// delta_rps_sign and abs_delta_rps_minus1 together specify the value of
1449    /// the variable deltaRps.
1450    pub abs_delta_rps_minus1: u16,
1451    /// specifies the number of entries in the stRpsIdx-th candidate short-term
1452    /// RPS that have picture order count values less than the picture order
1453    /// count value of the current picture.
1454    pub num_negative_pics: u8,
1455    /// specifies the number of entries in the stRpsIdx-th candidate short-term
1456    /// RPS that have picture order count values greater than the picture order
1457    /// count value of the current picture.
1458    pub num_positive_pics: u8,
1459    /// Same as UsedByCurrPicS0 in the specification.
1460    pub used_by_curr_pic_s0: [bool; MAX_SHORT_TERM_REF_PIC_SETS],
1461    /// Same as UsedByCurrPicS1 in the specification.
1462    pub used_by_curr_pic_s1: [bool; MAX_SHORT_TERM_REF_PIC_SETS],
1463    /// Same as DeltaPocS0 in the specification.
1464    pub delta_poc_s0: [i32; MAX_SHORT_TERM_REF_PIC_SETS],
1465    /// Same as DeltaPocS1 in the specification.
1466    pub delta_poc_s1: [i32; MAX_SHORT_TERM_REF_PIC_SETS],
1467    /// Same as NumDeltaPocs in the specification.
1468    pub num_delta_pocs: u32,
1469}
1470
1471impl Default for ShortTermRefPicSet {
1472    fn default() -> Self {
1473        Self {
1474            inter_ref_pic_set_prediction_flag: Default::default(),
1475            delta_idx_minus1: Default::default(),
1476            delta_rps_sign: Default::default(),
1477            abs_delta_rps_minus1: Default::default(),
1478            num_negative_pics: Default::default(),
1479            num_positive_pics: Default::default(),
1480            used_by_curr_pic_s0: [false; MAX_SHORT_TERM_REF_PIC_SETS],
1481            used_by_curr_pic_s1: [false; MAX_SHORT_TERM_REF_PIC_SETS],
1482            delta_poc_s0: [0; MAX_SHORT_TERM_REF_PIC_SETS],
1483            delta_poc_s1: [0; MAX_SHORT_TERM_REF_PIC_SETS],
1484            num_delta_pocs: Default::default(),
1485        }
1486    }
1487}
1488
1489#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1490/// See table 7-7 in the specification.
1491pub enum SliceType {
1492    B = 0,
1493    P = 1,
1494    I = 2,
1495}
1496
1497impl TryFrom<u32> for SliceType {
1498    type Error = String;
1499
1500    fn try_from(value: u32) -> Result<Self, Self::Error> {
1501        match value {
1502            0 => Ok(SliceType::B),
1503            1 => Ok(SliceType::P),
1504            2 => Ok(SliceType::I),
1505            _ => Err(format!("Invalid SliceType {}", value)),
1506        }
1507    }
1508}
1509
1510impl SliceType {
1511    /// Whether this is a P slice. See table 7-7 in the specification.
1512    pub fn is_p(&self) -> bool {
1513        matches!(self, SliceType::P)
1514    }
1515
1516    /// Whether this is a B slice. See table 7-7 in the specification.
1517    pub fn is_b(&self) -> bool {
1518        matches!(self, SliceType::B)
1519    }
1520
1521    /// Whether this is an I slice. See table 7-7 in the specification.
1522    pub fn is_i(&self) -> bool {
1523        matches!(self, SliceType::I)
1524    }
1525}
1526
1527impl Default for SliceType {
1528    fn default() -> Self {
1529        Self::P
1530    }
1531}
1532
1533#[derive(Clone, Debug, PartialEq, Eq)]
1534pub struct SliceHeader {
1535    /// When set, specifies that the slice segment is the first slice segment of
1536    /// the picture in decoding order. When not set, specifies that the slice
1537    /// segment is not the first slice segment of the picture in decoding order.
1538    pub first_slice_segment_in_pic_flag: bool,
1539    /// Affects the output of previously-decoded pictures in the decoded picture
1540    /// buffer after the decoding of an IDR or a BLA picture that is not the
1541    /// first picture in the bitstream as specified in Annex C.
1542    pub no_output_of_prior_pics_flag: bool,
1543    /// Specifies the value of pps_pic_parameter_set_id for the PPS in use.
1544    pub pic_parameter_set_id: u8,
1545    /// When set, specifies that the value of each slice segment header syntax
1546    /// element that is not present is inferred to be equal to the value of the
1547    /// corresponding slice segment header syntax element in the slice header.
1548    pub dependent_slice_segment_flag: bool,
1549    /// Specifies the address of the first CTB in the slice segment, in CTB
1550    /// raster scan of a picture.
1551    pub segment_address: u32,
1552    /// Specifies the coding type of the slice according to Table 7-7.
1553    pub type_: SliceType,
1554    /// Affects the decoded picture output and removal processes as specified in
1555    /// Annex C.
1556    pub pic_output_flag: bool,
1557    /// Specifies the colour plane associated with the current slice RBSP when
1558    /// separate_colour_plane_flag is set. The value of colour_plane_id shall be
1559    /// in the range of 0 to 2, inclusive. colour_plane_id values 0, 1 and 2
1560    /// correspond to the Y, Cb and Cr planes, respectively.
1561    pub colour_plane_id: u8,
1562    /// Specifies the picture order count modulo MaxPicOrderCntLsb for the
1563    /// current picture. The length of the slice_pic_order_cnt_lsb syntax
1564    /// element is log2_max_pic_order_cnt_lsb_minus4 + 4 bits.
1565    pub pic_order_cnt_lsb: u16,
1566    /// When set, specifies that the short-term RPS of the current picture is
1567    /// derived based on one of the st_ref_pic_set( ) syntax structures in the
1568    /// active SPS that is identified by the syntax element
1569    /// short_term_ref_pic_set_idx in the slice header.  When not set, specifies
1570    /// that the short-term RPS of the current picture is derived based on the
1571    /// st_ref_pic_set( ) syntax structure that is directly included in the
1572    /// slice headers of the current picture.
1573    pub short_term_ref_pic_set_sps_flag: bool,
1574    /// The st_ref_pic_set() data.
1575    pub short_term_ref_pic_set: ShortTermRefPicSet,
1576    /// Specifies the index, into the list of the st_ref_pic_set( ) syntax
1577    /// structures included in the active SPS, of the st_ref_pic_set( ) syntax
1578    /// structure that is used for derivation of the short-term RPS of the
1579    /// current picture.
1580    pub short_term_ref_pic_set_idx: u8,
1581    /// Specifies the number of entries in the long-term RPS of the current
1582    /// picture that are derived based on the candidate long-term reference
1583    /// pictures specified in the active SPS.
1584    pub num_long_term_sps: u8,
1585    /// Specifies the number of entries in the long-term RPS of the current
1586    /// picture that are directly signalled in the slice header.
1587    pub num_long_term_pics: u8,
1588    /// `lt_idx_sps[ i ]` specifies an index, into the list of candidate long-term
1589    /// reference pictures specified in the active SPS, of the i-th entry in the
1590    /// long-term RPS of the current picture.
1591    pub lt_idx_sps: [u8; 16],
1592    /// Same as PocLsbLt in the specification.
1593    pub poc_lsb_lt: [u32; 16],
1594    /// Same as UsedByCurrPicLt in the specification.
1595    pub used_by_curr_pic_lt: [bool; 16],
1596    /// When set, specifies that that `delta_poc_msb_cycle_lt[i]` is present.
1597    pub delta_poc_msb_present_flag: [bool; 16],
1598    /// Same as DeltaPocMsbCycleLt in the specification.
1599    pub delta_poc_msb_cycle_lt: [u32; 16],
1600    /// Specifies whether temporal motion vector predictors can be used for
1601    /// inter prediction. If slice_temporal_mvp_enabled_flag is not set, the
1602    /// syntax elements of the current picture shall be constrained such that no
1603    /// temporal motion vector predictor is used in decoding of the current
1604    /// picture. Otherwise (slice_temporal_mvp_enabled_flag is set), temporal
1605    /// motion vector predictors may be used in decoding of the current picture.
1606    pub temporal_mvp_enabled_flag: bool,
1607    /// When set, specifies that SAO is enabled for the luma component in the
1608    /// current slice; slice_sao_luma_flag not set specifies that SAO is
1609    /// disabled for the luma component in the current slice.
1610    pub sao_luma_flag: bool,
1611    /// When set, specifies that SAO is enabled for the chroma component in the
1612    /// current slice; When not set, specifies that SAO is disabled for the
1613    /// chroma component in the current slice.
1614    pub sao_chroma_flag: bool,
1615    /// When set, specifies that the syntax element num_ref_idx_l0_active_minus1
1616    /// is present for P and B slices and that the syntax element
1617    /// num_ref_idx_l1_active_minus1 is present for B slices. When not set,
1618    /// specifies that the syntax elements num_ref_idx_l0_active_minus1 and
1619    /// num_ref_idx_l1_active_minus1 are not present.
1620    pub num_ref_idx_active_override_flag: bool,
1621    /// Specifies the maximum reference index for
1622    /// reference picture list 0 that may be used to decode the slice.
1623    pub num_ref_idx_l0_active_minus1: u8,
1624    /// Specifies the maximum reference index for reference picture list 1 that
1625    /// may be used to decode the slice.
1626    pub num_ref_idx_l1_active_minus1: u8,
1627    /// The RefPicListModification data.
1628    pub ref_pic_list_modification: RefPicListModification,
1629    /// When set, indicates that the mvd_coding( x0, y0, 1 ) syntax structure is
1630    /// not parsed and `MvdL1[ x0 ]`[ y0 `][ compIdx ]` is set equal to 0 for
1631    /// compIdx = 0..1. When not set, indicates that the mvd_coding( x0, y0, 1 )
1632    /// syntax structure is parsed.
1633    pub mvd_l1_zero_flag: bool,
1634    /// Specifies the method for determining the initialization table used in
1635    /// the initialization process for context variables.
1636    pub cabac_init_flag: bool,
1637    /// When set, specifies that the collocated picture used for temporal motion
1638    /// vector prediction is derived from reference picture list 0.  When not
1639    /// set, specifies that the collocated picture used for temporal motion
1640    /// vector prediction is derived from reference picture list 1.
1641    pub collocated_from_l0_flag: bool,
1642    /// Specifies the reference index of the collocated picture used for
1643    /// temporal motion vector prediction.
1644    pub collocated_ref_idx: u8,
1645    /// The PredWeightTable data.
1646    pub pred_weight_table: PredWeightTable,
1647    /// Specifies the maximum number of merging motion vector prediction (MVP)
1648    /// candidates supported in the slice subtracted from 5.
1649    pub five_minus_max_num_merge_cand: u8,
1650    /// Specifies that the resolution of motion vectors for inter prediction in
1651    /// the current slice is integer. When not set, specifies
1652    /// that the resolution of motion vectors for inter prediction in the
1653    /// current slice that refer to pictures other than the current picture is
1654    /// fractional with quarter-sample precision in units of luma samples.
1655    pub use_integer_mv_flag: bool,
1656    /// Specifies the initial value of QpY to be used for the coding blocks in
1657    /// the slice until modified by the value of CuQpDeltaVal in the coding unit
1658    /// layer.
1659    pub qp_delta: i8,
1660    /// Specifies a difference to be added to the value of pps_cb_qp_offset when
1661    /// determining the value of the Qp′Cb quantization parameter.
1662    pub cb_qp_offset: i8,
1663    /// Specifies a difference to be added to the value of pps_cb_qr_offset when
1664    /// determining the value of the Qp′Cr quantization parameter.
1665    pub cr_qp_offset: i8,
1666    /// Specifies offsets to the quantization parameter values qP derived in
1667    /// clause 8.6.2 for luma, Cb, and Cr components, respectively.
1668    pub slice_act_y_qp_offset: i8,
1669    /// Specifies offsets to the quantization parameter values qP derived in
1670    /// clause 8.6.2 for luma, Cb, and Cr components, respectively.
1671    pub slice_act_cb_qp_offset: i8,
1672    /// Specifies offsets to the quantization parameter values qP derived in
1673    /// clause 8.6.2 for luma, Cb, and Cr components, respectively.
1674    pub slice_act_cr_qp_offset: i8,
1675    /// When set, specifies that the cu_chroma_qp_offset_flag may be present in
1676    /// the transform unit syntax. When not set, specifies that the
1677    /// cu_chroma_qp_offset_flag is not present in the transform unit syntax.
1678    pub cu_chroma_qp_offset_enabled_flag: bool,
1679    /// When set, specifies that deblocking parameters are present in the slice
1680    /// header. When not set, specifies that deblocking parameters are not
1681    /// present in the slice header.
1682    pub deblocking_filter_override_flag: bool,
1683    /// When set, specifies that the operation of the deblocking filter is not
1684    /// applied for the current slice. When not set, specifies that the
1685    /// operation of the deblocking filter is applied for the current slice.
1686    pub deblocking_filter_disabled_flag: bool,
1687    /// Specifies the deblocking parameter offsets for β and tC (divided by 2)
1688    /// for the current slice.
1689    pub beta_offset_div2: i8,
1690    /// Specifies the deblocking parameter offsets for β and tC (divided by 2)
1691    /// for the current slice.
1692    pub tc_offset_div2: i8,
1693    /// When set, specifies that in-loop filtering operations may be performed
1694    /// across the left and upper boundaries of the current slice.  When not
1695    /// set, specifies that in-loop operations are not performed across left and
1696    /// upper boundaries of the current slice. The in-loop filtering operations
1697    /// include the deblocking filter and sample adaptive offset filter.
1698    pub loop_filter_across_slices_enabled_flag: bool,
1699    /// Specifies the number of `entry_point_offset_minus1[ i ]` syntax elements
1700    /// in the slice header.
1701    pub num_entry_point_offsets: u32,
1702    /// offset_len_minus1 plus 1 specifies the length, in bits, of the
1703    /// `entry_point_offset_minus1[ i ]` syntax elements.
1704    pub offset_len_minus1: u8,
1705    /// `entry_point_offset_minus1[ i ]` plus 1 specifies the i-th entry point
1706    /// offset in bytes, and is represented by offset_len_minus1 plus 1 bits.
1707    /// The slice segment data that follow the slice segment header consists of
1708    /// num_entry_point_offsets + 1 subsets, with subset index values ranging
1709    /// from 0 to num_entry_point_offsets, inclusive. See the specification for
1710    /// more details.
1711    pub entry_point_offset_minus1: [u32; 32],
1712    /// Same as NumPicTotalCurr in the specification.
1713    pub num_pic_total_curr: u32,
1714    // Size of slice_header() in bits.
1715    pub header_bit_size: u32,
1716    // Number of emulation prevention bytes (EPB) in this slice_header().
1717    pub n_emulation_prevention_bytes: u32,
1718    /// Same as CurrRpsIdx in the specification.
1719    pub curr_rps_idx: u8,
1720    /// Number of bits taken by st_ref_pic_set minus Emulation Prevention Bytes.
1721    pub st_rps_bits: u32,
1722}
1723
1724impl Default for SliceHeader {
1725    fn default() -> Self {
1726        Self {
1727            first_slice_segment_in_pic_flag: Default::default(),
1728            no_output_of_prior_pics_flag: Default::default(),
1729            pic_parameter_set_id: Default::default(),
1730            dependent_slice_segment_flag: Default::default(),
1731            segment_address: Default::default(),
1732            type_: Default::default(),
1733            pic_output_flag: true,
1734            colour_plane_id: Default::default(),
1735            pic_order_cnt_lsb: Default::default(),
1736            short_term_ref_pic_set_sps_flag: Default::default(),
1737            short_term_ref_pic_set: Default::default(),
1738            short_term_ref_pic_set_idx: Default::default(),
1739            num_long_term_sps: Default::default(),
1740            num_long_term_pics: Default::default(),
1741            lt_idx_sps: Default::default(),
1742            poc_lsb_lt: Default::default(),
1743            used_by_curr_pic_lt: Default::default(),
1744            delta_poc_msb_present_flag: Default::default(),
1745            delta_poc_msb_cycle_lt: Default::default(),
1746            temporal_mvp_enabled_flag: Default::default(),
1747            sao_luma_flag: Default::default(),
1748            sao_chroma_flag: Default::default(),
1749            num_ref_idx_active_override_flag: Default::default(),
1750            num_ref_idx_l0_active_minus1: Default::default(),
1751            num_ref_idx_l1_active_minus1: Default::default(),
1752            ref_pic_list_modification: Default::default(),
1753            mvd_l1_zero_flag: Default::default(),
1754            cabac_init_flag: Default::default(),
1755            collocated_from_l0_flag: true,
1756            collocated_ref_idx: Default::default(),
1757            pred_weight_table: Default::default(),
1758            five_minus_max_num_merge_cand: Default::default(),
1759            use_integer_mv_flag: Default::default(),
1760            qp_delta: Default::default(),
1761            cb_qp_offset: Default::default(),
1762            cr_qp_offset: Default::default(),
1763            slice_act_y_qp_offset: Default::default(),
1764            slice_act_cb_qp_offset: Default::default(),
1765            slice_act_cr_qp_offset: Default::default(),
1766            cu_chroma_qp_offset_enabled_flag: Default::default(),
1767            deblocking_filter_override_flag: Default::default(),
1768            deblocking_filter_disabled_flag: Default::default(),
1769            beta_offset_div2: Default::default(),
1770            tc_offset_div2: Default::default(),
1771            loop_filter_across_slices_enabled_flag: Default::default(),
1772            num_entry_point_offsets: Default::default(),
1773            offset_len_minus1: Default::default(),
1774            entry_point_offset_minus1: Default::default(),
1775            num_pic_total_curr: Default::default(),
1776            header_bit_size: Default::default(),
1777            n_emulation_prevention_bytes: Default::default(),
1778            curr_rps_idx: Default::default(),
1779            st_rps_bits: Default::default(),
1780        }
1781    }
1782}
1783
1784/// A H265 slice. An integer number of macroblocks or macroblock pairs ordered
1785/// consecutively in the raster scan within a particular slice group
1786pub struct Slice<'a> {
1787    /// The slice header.
1788    pub header: SliceHeader,
1789    /// The NAL unit backing this slice.
1790    pub nalu: Nalu<'a>,
1791}
1792
1793impl<'a> Slice<'a> {
1794    /// Sets the header for dependent slices by copying from an independent
1795    /// slice.
1796    pub fn replace_header(&mut self, header: SliceHeader) -> Result<(), String> {
1797        if !self.header.dependent_slice_segment_flag {
1798            Err("Replacing the slice header is only possible for dependent slices".into())
1799        } else {
1800            let first_slice_segment_in_pic_flag = self.header.first_slice_segment_in_pic_flag;
1801            let no_output_of_prior_pics_flag = self.header.no_output_of_prior_pics_flag;
1802            let pic_parameter_set_id = self.header.pic_parameter_set_id;
1803            let dependent_slice_segment_flag = self.header.dependent_slice_segment_flag;
1804            let segment_address = self.header.segment_address;
1805
1806            let offset_len_minus1 = self.header.offset_len_minus1;
1807            let entry_point_offset_minus1 = self.header.entry_point_offset_minus1;
1808            let num_pic_total_curr = self.header.num_pic_total_curr;
1809            let header_bit_size = self.header.header_bit_size;
1810            let n_emulation_prevention_bytes = self.header.n_emulation_prevention_bytes;
1811            let curr_rps_idx = self.header.curr_rps_idx;
1812            let st_rps_bits = self.header.st_rps_bits;
1813
1814            self.header = header;
1815
1816            self.header.first_slice_segment_in_pic_flag = first_slice_segment_in_pic_flag;
1817            self.header.no_output_of_prior_pics_flag = no_output_of_prior_pics_flag;
1818            self.header.pic_parameter_set_id = pic_parameter_set_id;
1819            self.header.dependent_slice_segment_flag = dependent_slice_segment_flag;
1820            self.header.segment_address = segment_address;
1821            self.header.offset_len_minus1 = offset_len_minus1;
1822            self.header.entry_point_offset_minus1 = entry_point_offset_minus1;
1823            self.header.num_pic_total_curr = num_pic_total_curr;
1824            self.header.header_bit_size = header_bit_size;
1825            self.header.n_emulation_prevention_bytes = n_emulation_prevention_bytes;
1826            self.header.curr_rps_idx = curr_rps_idx;
1827            self.header.st_rps_bits = st_rps_bits;
1828
1829            Ok(())
1830        }
1831    }
1832}
1833
1834#[derive(Clone, Debug, Default, PartialEq, Eq)]
1835pub struct SublayerHrdParameters {
1836    // NOTE: The value of CpbCnt is cpb_cnt_minus1[i] + 1, and cpb_cnt_minus1
1837    // ranges from 0..=31
1838    /// `bit_rate_value_minus1[ i ]` (together with bit_rate_scale) specifies the
1839    /// maximum input bit rate for the i-th CPB when the CPB operates at the
1840    /// access unit level
1841    pub bit_rate_value_minus1: [u32; 32],
1842    /// `cpb_size_value_minus1[ i ]` is used together with cpb_size_scale to
1843    /// specify the i-th CPB size when the CPB operates at the access unit
1844    /// level.
1845    pub cpb_size_value_minus1: [u32; 32],
1846    /// `cpb_size_du_value_minus1[ i ]` is used together with cpb_size_du_scale to
1847    /// specify the i-th CPB size when the CPB operates at sub-picture level.
1848    pub cpb_size_du_value_minus1: [u32; 32],
1849    /// `bit_rate_du_value_minus1[ i ]` (together with bit_rate_scale) specifies
1850    /// the maximum input bit rate for the i-th CPB when the CPB operates at the
1851    /// sub-picture level.
1852    pub bit_rate_du_value_minus1: [u32; 32],
1853    /// `cbr_flag[ i ]` not set specifies that to decode this CVS by the HRD using
1854    /// the i-th CPB specification.
1855    pub cbr_flag: [bool; 32],
1856}
1857
1858#[derive(Clone, Debug, PartialEq, Eq)]
1859pub struct HrdParams {
1860    /// When set, specifies that NAL HRD parameters (pertaining to the Type II
1861    /// bitstream conformance point) are present in the hrd_parameters( ) syntax
1862    /// structure. When not set, specifies that NAL HRD parameters are not
1863    /// present in the hrd_parameters( ) syntax structure.
1864    pub nal_hrd_parameters_present_flag: bool,
1865    /// When set, specifies that VCL HRD parameters (pertaining to the Type I
1866    /// bitstream conformance point) are present in the hrd_parameters( ) syntax
1867    /// structure. When not set, specifies that VCL HRD parameters are not
1868    /// present in the hrd_parameters( ) syntax structure.
1869    pub vcl_hrd_parameters_present_flag: bool,
1870    /// When set, specifies that sub-picture level HRD parameters are present
1871    /// and the HRD may operate at access unit level or sub-picture level. When
1872    /// not set, specifies that sub-picture level HRD parameters are not present
1873    /// and the HRD operates at access unit level.
1874    pub sub_pic_hrd_params_present_flag: bool,
1875    /// Used to specify the clock sub-tick. A clock sub-tick is the minimum
1876    /// interval of time that can be represented in the coded data when
1877    /// sub_pic_hrd_params_present_flag is set.
1878    pub tick_divisor_minus2: u8,
1879    /// du_cpb_removal_delay_increment_length_minus1 plus 1 specifies the
1880    /// length, in bits, of the `du_cpb_removal_delay_increment_minus1[ i ]` and
1881    /// du_common_cpb_removal_delay_increment_minus1 syntax elements of the
1882    /// picture timing SEI message and the du_spt_cpb_removal_delay_increment
1883    /// syntax element in the decoding unit information SEI message.
1884    pub du_cpb_removal_delay_increment_length_minus1: u8,
1885    /// When set, specifies that sub-picture level CPB removal delay parameters
1886    /// are present in picture timing SEI messages and no decoding unit
1887    /// information SEI message is available (in the CVS or provided through
1888    /// external means not specified in this Specification).  When not set,
1889    /// specifies that sub-picture level CPB removal delay parameters are
1890    /// present in decoding unit information SEI messages and picture timing SEI
1891    /// messages do not include sub-picture level CPB removal delay parameters.
1892    pub sub_pic_cpb_params_in_pic_timing_sei_flag: bool,
1893    /// dpb_output_delay_du_length_minus1 plus 1 specifies the length, in bits,
1894    /// of the pic_dpb_output_du_delay syntax element in the picture timing SEI
1895    /// message and the pic_spt_dpb_output_du_delay syntax element in the
1896    /// decoding unit information SEI message.
1897    pub dpb_output_delay_du_length_minus1: u8,
1898    /// Together with `bit_rate_value_minus1[ i ]`, specifies the maximum input
1899    /// bit rate of the i-th CPB.
1900    pub bit_rate_scale: u8,
1901    /// Together with `cpb_size_du_value_minus1[ i ]`, specifies the CPB size of
1902    /// the i-th CPB when the CPB operates at sub-picture level.
1903    pub cpb_size_scale: u8,
1904    /// Together with `cpb_size_du_value_minus1[ i ]`, specifies the CPB size of
1905    /// the i-th CPB when the CPB operates at sub-picture level.
1906    pub cpb_size_du_scale: u8,
1907    /// initial_cpb_removal_delay_length_minus1 plus 1 specifies the length, in
1908    /// bits, of the `nal_initial_cpb_removal_delay[ i ]`,
1909    /// `nal_initial_cpb_removal_offset[ i ]`, `vcl_initial_cpb_removal_delay[ i ]`
1910    /// and `vcl_initial_cpb_removal_offset[ i ]` syntax elements of the buffering
1911    /// period SEI message.
1912    pub initial_cpb_removal_delay_length_minus1: u8,
1913    /// au_cpb_removal_delay_length_minus1 plus 1 specifies the length, in bits,
1914    /// of the cpb_delay_offset syntax element in the buffering period SEI
1915    /// message and the au_cpb_removal_delay_minus1 syntax element in the
1916    /// picture timing SEI message.
1917    pub au_cpb_removal_delay_length_minus1: u8,
1918    /// dpb_output_delay_length_minus1 plus 1 specifies the length, in bits, of
1919    /// the dpb_delay_offset syntax element in the buffering period SEI message
1920    /// and the pic_dpb_output_delay syntax element in the picture timing SEI
1921    /// message.
1922    pub dpb_output_delay_length_minus1: u8,
1923    /// `fixed_pic_rate_general_flag[ i ]` set indicates that, when HighestTid is
1924    /// equal to i, the temporal distance between the HRD output times of
1925    /// consecutive pictures in output order is constrained as specified in the
1926    /// specification. `fixed_pic_rate_general_flag[ i ]` not set indicates that
1927    /// this constraint may not apply.
1928    pub fixed_pic_rate_general_flag: [bool; 7],
1929    /// `fixed_pic_rate_within_cvs_flag[ i ]` set indicates that, when HighestTid
1930    /// is equal to i, the temporal distance between the HRD output times of
1931    /// consecutive pictures in output order is constrained as specified in the
1932    /// specification. `fixed_pic_rate_within_cvs_flag[ i ]` not set indicates
1933    /// that this constraint may not apply.
1934    pub fixed_pic_rate_within_cvs_flag: [bool; 7],
1935    /// `elemental_duration_in_tc_minus1[ i ]` plus 1 (when present) specifies,
1936    /// when HighestTid is equal to i, the temporal distance, in clock ticks,
1937    /// between the elemental units that specify the HRD output times of
1938    /// consecutive pictures in output order as specified in the specification.
1939    pub elemental_duration_in_tc_minus1: [u32; 7],
1940    /// `low_delay_hrd_flag[ i ]` specifies the HRD operational mode, when
1941    /// HighestTid is equal to i, as specified in Annex C or clause F.13.
1942    pub low_delay_hrd_flag: [bool; 7],
1943    /// `cpb_cnt_minus1[ i ]` plus 1 specifies the number of alternative CPB
1944    /// specifications in the bitstream of the CVS when HighestTid is equal to
1945    /// i.
1946    pub cpb_cnt_minus1: [u32; 7],
1947    /// The NAL HRD data.
1948    pub nal_hrd: [SublayerHrdParameters; 7],
1949    /// The VCL HRD data.
1950    pub vcl_hrd: [SublayerHrdParameters; 7],
1951}
1952
1953impl Default for HrdParams {
1954    fn default() -> Self {
1955        Self {
1956            initial_cpb_removal_delay_length_minus1: 23,
1957            au_cpb_removal_delay_length_minus1: 23,
1958            dpb_output_delay_du_length_minus1: 23,
1959            nal_hrd_parameters_present_flag: Default::default(),
1960            vcl_hrd_parameters_present_flag: Default::default(),
1961            sub_pic_hrd_params_present_flag: Default::default(),
1962            tick_divisor_minus2: Default::default(),
1963            du_cpb_removal_delay_increment_length_minus1: Default::default(),
1964            sub_pic_cpb_params_in_pic_timing_sei_flag: Default::default(),
1965            bit_rate_scale: Default::default(),
1966            cpb_size_scale: Default::default(),
1967            cpb_size_du_scale: Default::default(),
1968            dpb_output_delay_length_minus1: Default::default(),
1969            fixed_pic_rate_general_flag: Default::default(),
1970            fixed_pic_rate_within_cvs_flag: Default::default(),
1971            elemental_duration_in_tc_minus1: Default::default(),
1972            low_delay_hrd_flag: Default::default(),
1973            cpb_cnt_minus1: Default::default(),
1974            nal_hrd: Default::default(),
1975            vcl_hrd: Default::default(),
1976        }
1977    }
1978}
1979
1980#[derive(Clone, Debug, PartialEq, Eq)]
1981pub struct VuiParams {
1982    /// When set, specifies that aspect_ratio_idc is present.  When not set,
1983    /// specifies that aspect_ratio_idc is not present.
1984    pub aspect_ratio_info_present_flag: bool,
1985    /// Specifies the value of the sample aspect ratio of the luma samples.
1986    pub aspect_ratio_idc: u32,
1987    /// Indicates the horizontal size of the sample aspect ratio (in arbitrary
1988    /// units).
1989    pub sar_width: u32,
1990    /// Indicates the vertical size of the sample aspect ratio (in arbitrary
1991    /// units).
1992    pub sar_height: u32,
1993    /// When set, specifies that the overscan_appropriate_flag is present. When
1994    /// not set, the preferred display method for the video signal is
1995    /// unspecified.
1996    pub overscan_info_present_flag: bool,
1997    /// When set indicates that the cropped decoded pictures output are suitable
1998    /// for display using overscan. When not set, indicates that the cropped
1999    /// decoded pictures output contain visually important information in the
2000    /// entire region out to the edges of the conformance cropping window of the
2001    /// picture, such that the cropped decoded pictures output should not be
2002    /// displayed using overscan.
2003    pub overscan_appropriate_flag: bool,
2004    /// When set, specifies that video_format, video_full_range_flag and
2005    /// colour_description_present_flag are present.  When not set, specify that
2006    /// video_format, video_full_range_flag and colour_description_present_flag
2007    /// are not present.
2008    pub video_signal_type_present_flag: bool,
2009    /// Indicates the representation of the pictures as specified in Table E.2,
2010    /// before being coded in accordance with this Specification.
2011    pub video_format: u8,
2012    /// Indicates the black level and range of the luma and chroma signals as
2013    /// derived from E′Y, E′PB, and E′PR or E′R, E′G, and E′B real-valued
2014    /// component signals.
2015    pub video_full_range_flag: bool,
2016    /// When set, specifies that colour_primaries, transfer_characteristics, and
2017    /// matrix_coeffs are present. When not set, specifies that
2018    /// colour_primaries, transfer_characteristics, and matrix_coeffs are not
2019    /// present.
2020    pub colour_description_present_flag: bool,
2021    /// Indicates the chromaticity coordinates of the source primaries as
2022    /// specified in Table E.3 in terms of the CIE 1931 definition of x and y as
2023    /// specified in ISO 11664-1.
2024    pub colour_primaries: u32,
2025    /// See table E.4 in the specification.
2026    pub transfer_characteristics: u32,
2027    /// Describes the matrix coefficients used in deriving luma and chroma
2028    /// signals from the green, blue, and red, or Y, Z, and X primaries, as
2029    /// specified in Table E.5.
2030    pub matrix_coeffs: u32,
2031    /// When true, specifies that chroma_sample_loc_type_top_field and
2032    /// chroma_sample_loc_type_bottom_field are present. When false, specifies
2033    /// that chroma_sample_loc_type_top_field and
2034    /// chroma_sample_loc_type_bottom_field are not present.
2035    pub chroma_loc_info_present_flag: bool,
2036    /// See the specification for more details.
2037    pub chroma_sample_loc_type_top_field: u32,
2038    /// See the specification for more details.
2039    pub chroma_sample_loc_type_bottom_field: u32,
2040    /// When true, indicates that the value of all decoded chroma samples is
2041    /// equal to 1 << ( BitDepthC − 1 ). When false, provides no indication of
2042    /// decoded chroma sample values.
2043    pub neutral_chroma_indication_flag: bool,
2044    /// When true, indicates that the CVS conveys pictures that represent
2045    /// fields, and specifies that a picture timing SEI message shall be present
2046    /// in every access unit of the current CVS. When false, indicates that the
2047    /// CVS conveys pictures that represent frames and that a picture timing SEI
2048    /// message may or may not be present in any access unit of the current CVS.
2049    pub field_seq_flag: bool,
2050    /// When true, specifies that picture timing SEI messages are present for
2051    /// every picture and include the pic_struct, source_scan_type and
2052    /// duplicate_flag syntax elements. When false, specifies that the
2053    /// pic_struct syntax element is not present in picture timing SEI messages.
2054    pub frame_field_info_present_flag: bool,
2055    /// When true, indicates that the default display window parameters follow
2056    /// next in the VUI. When false, indicates that the default display window
2057    /// parameters are not present.
2058    pub default_display_window_flag: bool,
2059    /// Specifies the samples of the pictures in the CVS that are within the
2060    /// default display window, in terms of a rectangular region specified in
2061    /// picture coordinates for display.
2062    pub def_disp_win_left_offset: u32,
2063    /// Specifies the samples of the pictures in the CVS that are within the
2064    /// default display window, in terms of a rectangular region specified in
2065    /// picture coordinates for display.
2066    pub def_disp_win_right_offset: u32,
2067    /// Specifies the samples of the pictures in the CVS that are within the
2068    /// default display window, in terms of a rectangular region specified in
2069    /// picture coordinates for display.
2070    pub def_disp_win_top_offset: u32,
2071    /// Specifies the samples of the pictures in the CVS that are within the
2072    /// default display window, in terms of a rectangular region specified in
2073    /// picture coordinates for display.
2074    pub def_disp_win_bottom_offset: u32,
2075    /// When set, specifies that vui_num_units_in_tick, vui_time_scale,
2076    /// vui_poc_proportional_to_timing_flag and vui_hrd_parameters_present_flag
2077    /// are present in the vui_parameters( ) syntax structure.  When not set,
2078    /// specifies that vui_num_units_in_tick, vui_time_scale,
2079    /// vui_poc_proportional_to_timing_flag and vui_hrd_parameters_present_flag
2080    /// are not present in the vui_parameters( ) syntax structure
2081    pub timing_info_present_flag: bool,
2082    /// The number of time units of a clock operating at the frequency
2083    /// vui_time_scale Hz that corresponds to one increment (called a clock
2084    /// tick) of a clock tick counter.
2085    pub num_units_in_tick: u32,
2086    /// Is the number of time units that pass in one second. For example, a time
2087    /// coordinate system that measures time using a 27 MHz clock has a
2088    /// vui_time_scale of 27 000 000.
2089    pub time_scale: u32,
2090    /// When set, indicates that the picture order count value for each picture
2091    /// in the CVS that is not the first picture in the CVS, in decoding order,
2092    /// is proportional to the output time of the picture relative to the output
2093    /// time of the first picture in the CVS.  When not set, indicates that the
2094    /// picture order count value for each picture in the CVS that is not the
2095    /// first picture in the CVS, in decoding order, may or may not be
2096    /// proportional to the output time of the picture relative to the output
2097    /// time of the first picture in the CVS.
2098    pub poc_proportional_to_timing_flag: bool,
2099    /// vui_num_ticks_poc_diff_one_minus1 plus 1 specifies the number of clock
2100    /// ticks corresponding to a difference of picture order count values equal
2101    /// to 1.
2102    pub num_ticks_poc_diff_one_minus1: u32,
2103    /// When set, specifies that the syntax structure hrd_parameters( ) is
2104    /// present in the vui_parameters( ) syntax structure.  When not set,
2105    /// specifies that the syntax structure hrd_parameters( ) is not present in
2106    /// the vui_parameters( ) syntax structure.
2107    pub hrd_parameters_present_flag: bool,
2108    /// The hrd_parameters() data.
2109    pub hrd: HrdParams,
2110    /// When set, specifies that the bitstream restriction parameters for the
2111    /// CVS are present. When not set, specifies that the bitstream restriction
2112    /// parameters for the CVS are not present.
2113    pub bitstream_restriction_flag: bool,
2114    /// When set, indicates that each PPS that is active in the CVS has the same
2115    /// value of the syntax elements num_tile_columns_minus1,
2116    /// num_tile_rows_minus1, uniform_spacing_flag, `column_width_minus1[ i ]`,
2117    /// `row_height_minus1[ i ]` and loop_filter_across_tiles_enabled_flag, when
2118    /// present. When not set, indicates that tiles syntax elements in different
2119    /// PPSs may or may not have the same value
2120    pub tiles_fixed_structure_flag: bool,
2121    /// When not set, indicates that no sample outside the picture boundaries
2122    /// and no sample at a fractional sample position for which the sample value
2123    /// is derived using one or more samples outside the picture boundaries is
2124    /// used for inter prediction of any sample.  When set, indicates that one
2125    /// or more samples outside the picture boundaries may be used in inter
2126    /// prediction.
2127    pub motion_vectors_over_pic_boundaries_flag: bool,
2128    /// When set, indicates that all P and B slices (when present) that belong
2129    /// to the same picture have an identical reference picture list 0 and that
2130    /// all B slices (when present) that belong to the same picture have an
2131    /// identical reference picture list 1.
2132    pub restricted_ref_pic_lists_flag: bool,
2133    /// When not equal to 0, establishes a bound on the maximum possible size of
2134    /// distinct coded spatial segmentation regions in the pictures of the CVS.
2135    pub min_spatial_segmentation_idc: u32,
2136    /// Indicates a number of bytes not exceeded by the sum of the sizes of the
2137    /// VCL NAL units associated with any coded picture in the CVS.
2138    pub max_bytes_per_pic_denom: u32,
2139    /// Indicates an upper bound for the number of coded bits of coding_unit( )
2140    /// data for anycoding block in any picture of the CVS.
2141    pub max_bits_per_min_cu_denom: u32,
2142    /// Indicate the maximum absolute value of a decoded horizontal and vertical
2143    /// motion vector component, respectively, in quarter luma sample units, for
2144    /// all pictures in the CVS.
2145    pub log2_max_mv_length_horizontal: u32,
2146    /// Indicate the maximum absolute value of a decoded horizontal and vertical
2147    /// motion vector component, respectively, in quarter luma sample units, for
2148    /// all pictures in the CVS.
2149    pub log2_max_mv_length_vertical: u32,
2150}
2151
2152impl Default for VuiParams {
2153    fn default() -> Self {
2154        Self {
2155            aspect_ratio_info_present_flag: Default::default(),
2156            aspect_ratio_idc: Default::default(),
2157            sar_width: Default::default(),
2158            sar_height: Default::default(),
2159            overscan_info_present_flag: Default::default(),
2160            overscan_appropriate_flag: Default::default(),
2161            video_signal_type_present_flag: Default::default(),
2162            video_format: 5,
2163            video_full_range_flag: Default::default(),
2164            colour_description_present_flag: Default::default(),
2165            colour_primaries: 2,
2166            transfer_characteristics: 2,
2167            matrix_coeffs: 2,
2168            chroma_loc_info_present_flag: Default::default(),
2169            chroma_sample_loc_type_top_field: Default::default(),
2170            chroma_sample_loc_type_bottom_field: Default::default(),
2171            neutral_chroma_indication_flag: Default::default(),
2172            field_seq_flag: Default::default(),
2173            frame_field_info_present_flag: Default::default(),
2174            default_display_window_flag: Default::default(),
2175            def_disp_win_left_offset: Default::default(),
2176            def_disp_win_right_offset: Default::default(),
2177            def_disp_win_top_offset: Default::default(),
2178            def_disp_win_bottom_offset: Default::default(),
2179            timing_info_present_flag: Default::default(),
2180            num_units_in_tick: Default::default(),
2181            time_scale: Default::default(),
2182            poc_proportional_to_timing_flag: Default::default(),
2183            num_ticks_poc_diff_one_minus1: Default::default(),
2184            hrd_parameters_present_flag: Default::default(),
2185            hrd: Default::default(),
2186            bitstream_restriction_flag: Default::default(),
2187            tiles_fixed_structure_flag: Default::default(),
2188            motion_vectors_over_pic_boundaries_flag: true,
2189            restricted_ref_pic_lists_flag: Default::default(),
2190            min_spatial_segmentation_idc: Default::default(),
2191            max_bytes_per_pic_denom: 2,
2192            max_bits_per_min_cu_denom: 1,
2193            log2_max_mv_length_horizontal: 15,
2194            log2_max_mv_length_vertical: 15,
2195        }
2196    }
2197}
2198
2199#[derive(Clone, Debug, Default)]
2200pub struct Parser {
2201    active_vpses: BTreeMap<u8, Rc<Vps>>,
2202    active_spses: BTreeMap<u8, Rc<Sps>>,
2203    active_ppses: BTreeMap<u8, Rc<Pps>>,
2204}
2205
2206impl Parser {
2207    /// Parse a VPS NALU.
2208    pub fn parse_vps(&mut self, nalu: &Nalu) -> Result<&Vps, String> {
2209        if !matches!(nalu.header.type_, NaluType::VpsNut) {
2210            return Err(format!(
2211                "Invalid NALU type, expected {:?}, got {:?}",
2212                NaluType::VpsNut,
2213                nalu.header.type_
2214            ));
2215        }
2216
2217        let data = nalu.as_ref();
2218        let header = &nalu.header;
2219        let hdr_len = header.len();
2220        // Skip the header
2221        let mut r = BitReader::new(&data[hdr_len..], true);
2222
2223        let mut vps = Vps {
2224            video_parameter_set_id: r.read_bits(4)?,
2225            base_layer_internal_flag: r.read_bit()?,
2226            base_layer_available_flag: r.read_bit()?,
2227            max_layers_minus1: r.read_bits(6)?,
2228            max_sub_layers_minus1: r.read_bits(3)?,
2229            temporal_id_nesting_flag: r.read_bit()?,
2230            ..Default::default()
2231        };
2232
2233        r.skip_bits(16)?; // vps_reserved_0xffff_16bits
2234
2235        let ptl = &mut vps.profile_tier_level;
2236        Self::parse_profile_tier_level(ptl, &mut r, true, vps.max_sub_layers_minus1)?;
2237
2238        vps.sub_layer_ordering_info_present_flag = r.read_bit()?;
2239
2240        let start =
2241            if vps.sub_layer_ordering_info_present_flag { 0 } else { vps.max_sub_layers_minus1 }
2242                as usize;
2243
2244        for i in start..=usize::from(vps.max_sub_layers_minus1) {
2245            vps.max_dec_pic_buffering_minus1[i] = r.read_ue_max(15)?;
2246            vps.max_num_reorder_pics[i] = r.read_ue_max(vps.max_dec_pic_buffering_minus1[i])?;
2247            vps.max_latency_increase_plus1[i] = r.read_ue()?;
2248
2249            if i > 0 {
2250                if vps.max_dec_pic_buffering_minus1[i] < vps.max_dec_pic_buffering_minus1[i - 1] {
2251                    return Err(format!(
2252                        "Invalid max_dec_pic_buffering_minus1[{}]: {}",
2253                        i, vps.max_dec_pic_buffering_minus1[i]
2254                    ));
2255                }
2256
2257                if vps.max_num_reorder_pics[i] < vps.max_num_reorder_pics[i - 1] {
2258                    return Err(format!(
2259                        "Invalid max_num_reorder_pics[{}]: {}",
2260                        i, vps.max_num_reorder_pics[i]
2261                    ));
2262                }
2263            }
2264        }
2265
2266        // vps_sub_layer_ordering_info_present_flag equal to 0 specifies that
2267        // the values of vps_max_dec_pic_buffering_minus1[
2268        // vps_max_sub_layers_minus1 ], vps_max_num_reorder_pics[ vps_max_sub_
2269        // layers_minus1 ] and vps_max_latency_increase_plus1[
2270        // vps_max_sub_layers_minus1 ] apply to all sub-layers
2271        if !vps.sub_layer_ordering_info_present_flag {
2272            let max_num_sublayers = usize::from(vps.max_sub_layers_minus1);
2273            for i in 0..max_num_sublayers {
2274                vps.max_dec_pic_buffering_minus1[i] =
2275                    vps.max_dec_pic_buffering_minus1[max_num_sublayers];
2276
2277                vps.max_num_reorder_pics[i] = vps.max_num_reorder_pics[max_num_sublayers];
2278
2279                vps.max_latency_increase_plus1[i] =
2280                    vps.max_latency_increase_plus1[max_num_sublayers];
2281            }
2282        }
2283
2284        vps.max_layer_id = r.read_bits(6)?;
2285        if vps.max_layer_id > 62 {
2286            return Err(format!("Invalid max_layer_id {}", vps.max_layer_id));
2287        }
2288
2289        vps.num_layer_sets_minus1 = r.read_ue_max(1023)?;
2290
2291        for _ in 1..=vps.num_layer_sets_minus1 {
2292            for _ in 0..=vps.max_layer_id {
2293                // Skip layer_id_included_flag[i][j] for now.
2294                r.skip_bits(1)?;
2295            }
2296        }
2297
2298        vps.timing_info_present_flag = r.read_bit()?;
2299
2300        if vps.timing_info_present_flag {
2301            vps.num_units_in_tick = r.read_bits::<u32>(31)? << 1;
2302            vps.num_units_in_tick |= r.read_bits::<u32>(1)?;
2303
2304            vps.time_scale = r.read_bits::<u32>(31)? << 1;
2305            vps.time_scale |= r.read_bits::<u32>(1)?;
2306
2307            vps.poc_proportional_to_timing_flag = r.read_bit()?;
2308            if vps.poc_proportional_to_timing_flag {
2309                vps.num_ticks_poc_diff_one_minus1 = r.read_ue()?;
2310            }
2311
2312            vps.num_hrd_parameters = r.read_ue()?;
2313
2314            for i in 0..vps.num_hrd_parameters as usize {
2315                vps.hrd_layer_set_idx.push(r.read_ue()?);
2316                if i > 0 {
2317                    vps.cprms_present_flag.push(r.read_bit()?);
2318                }
2319
2320                let mut hrd = HrdParams::default();
2321                Self::parse_hrd_parameters(
2322                    vps.cprms_present_flag[i],
2323                    vps.max_sub_layers_minus1,
2324                    &mut hrd,
2325                    &mut r,
2326                )?;
2327
2328                vps.hrd_parameters.push(hrd);
2329            }
2330        }
2331
2332        vps.extension_flag = r.read_bit()?;
2333
2334        if self.active_vpses.keys().len() >= MAX_VPS_COUNT {
2335            return Err("Broken data: Number of active VPSs > MAX_VPS_COUNT".into());
2336        }
2337
2338        let key = vps.video_parameter_set_id;
2339        let vps = Rc::new(vps);
2340        self.active_vpses.remove(&key);
2341        Ok(self.active_vpses.entry(key).or_insert(vps))
2342    }
2343
2344    fn parse_profile_tier_level(
2345        ptl: &mut ProfileTierLevel,
2346        r: &mut BitReader,
2347        profile_present_flag: bool,
2348        sps_max_sub_layers_minus_1: u8,
2349    ) -> Result<(), String> {
2350        if profile_present_flag {
2351            ptl.general_profile_space = r.read_bits(2)?;
2352            ptl.general_tier_flag = r.read_bit()?;
2353            ptl.general_profile_idc = r.read_bits(5)?;
2354
2355            for i in 0..32 {
2356                ptl.general_profile_compatibility_flag[i] = r.read_bit()?;
2357            }
2358
2359            ptl.general_progressive_source_flag = r.read_bit()?;
2360            ptl.general_interlaced_source_flag = r.read_bit()?;
2361            ptl.general_non_packed_constraint_flag = r.read_bit()?;
2362            ptl.general_frame_only_constraint_flag = r.read_bit()?;
2363
2364            if ptl.general_profile_idc == 4
2365                || ptl.general_profile_compatibility_flag[4]
2366                || ptl.general_profile_idc == 5
2367                || ptl.general_profile_compatibility_flag[5]
2368                || ptl.general_profile_idc == 6
2369                || ptl.general_profile_compatibility_flag[6]
2370                || ptl.general_profile_idc == 7
2371                || ptl.general_profile_compatibility_flag[7]
2372                || ptl.general_profile_idc == 8
2373                || ptl.general_profile_compatibility_flag[8]
2374                || ptl.general_profile_idc == 9
2375                || ptl.general_profile_compatibility_flag[9]
2376                || ptl.general_profile_idc == 10
2377                || ptl.general_profile_compatibility_flag[10]
2378                || ptl.general_profile_idc == 11
2379                || ptl.general_profile_compatibility_flag[11]
2380            {
2381                ptl.general_max_12bit_constraint_flag = r.read_bit()?;
2382                ptl.general_max_10bit_constraint_flag = r.read_bit()?;
2383                ptl.general_max_8bit_constraint_flag = r.read_bit()?;
2384                ptl.general_max_422chroma_constraint_flag = r.read_bit()?;
2385                ptl.general_max_420chroma_constraint_flag = r.read_bit()?;
2386                ptl.general_max_monochrome_constraint_flag = r.read_bit()?;
2387                ptl.general_intra_constraint_flag = r.read_bit()?;
2388                ptl.general_one_picture_only_constraint_flag = r.read_bit()?;
2389                ptl.general_lower_bit_rate_constraint_flag = r.read_bit()?;
2390                if ptl.general_profile_idc == 5
2391                    || ptl.general_profile_compatibility_flag[5]
2392                    || ptl.general_profile_idc == 9
2393                    || ptl.general_profile_compatibility_flag[9]
2394                    || ptl.general_profile_idc == 10
2395                    || ptl.general_profile_compatibility_flag[10]
2396                    || ptl.general_profile_idc == 11
2397                    || ptl.general_profile_compatibility_flag[11]
2398                {
2399                    ptl.general_max_14bit_constraint_flag = r.read_bit()?;
2400                    // Skip general_reserved_zero_33bits
2401                    r.skip_bits(31)?;
2402                    r.skip_bits(2)?;
2403                } else {
2404                    // Skip general_reserved_zero_34bits
2405                    r.skip_bits(31)?;
2406                    r.skip_bits(3)?;
2407                }
2408            } else if ptl.general_profile_idc == 2 || ptl.general_profile_compatibility_flag[2] {
2409                // Skip general_reserved_zero_7bits
2410                r.skip_bits(7)?;
2411                ptl.general_one_picture_only_constraint_flag = r.read_bit()?;
2412                // Skip general_reserved_zero_35bits
2413                r.skip_bits(31)?;
2414                r.skip_bits(4)?;
2415            } else {
2416                r.skip_bits(31)?;
2417                r.skip_bits(12)?;
2418            }
2419
2420            if ptl.general_profile_idc == 1
2421                || ptl.general_profile_compatibility_flag[1]
2422                || ptl.general_profile_idc == 2
2423                || ptl.general_profile_compatibility_flag[2]
2424                || ptl.general_profile_idc == 3
2425                || ptl.general_profile_compatibility_flag[3]
2426                || ptl.general_profile_idc == 4
2427                || ptl.general_profile_compatibility_flag[4]
2428                || ptl.general_profile_idc == 5
2429                || ptl.general_profile_compatibility_flag[5]
2430                || ptl.general_profile_idc == 9
2431                || ptl.general_profile_compatibility_flag[9]
2432                || ptl.general_profile_idc == 11
2433                || ptl.general_profile_compatibility_flag[11]
2434            {
2435                ptl.general_inbld_flag = r.read_bit()?;
2436            } else {
2437                r.skip_bits(1)?;
2438            }
2439        }
2440
2441        let level: u8 = r.read_bits(8)?;
2442        ptl.general_level_idc = Level::try_from(level)?;
2443
2444        for i in 0..sps_max_sub_layers_minus_1 as usize {
2445            ptl.sub_layer_profile_present_flag[i] = r.read_bit()?;
2446            ptl.sub_layer_level_present_flag[i] = r.read_bit()?;
2447        }
2448
2449        if sps_max_sub_layers_minus_1 > 0 {
2450            for _ in sps_max_sub_layers_minus_1..8 {
2451                r.skip_bits(2)?;
2452            }
2453        }
2454
2455        for i in 0..sps_max_sub_layers_minus_1 as usize {
2456            if ptl.sub_layer_level_present_flag[i] {
2457                ptl.sub_layer_profile_space[i] = r.read_bits(2)?;
2458                ptl.sub_layer_tier_flag[i] = r.read_bit()?;
2459                ptl.sub_layer_profile_idc[i] = r.read_bits(5)?;
2460                for j in 0..32 {
2461                    ptl.sub_layer_profile_compatibility_flag[i][j] = r.read_bit()?;
2462                }
2463                ptl.sub_layer_progressive_source_flag[i] = r.read_bit()?;
2464                ptl.sub_layer_interlaced_source_flag[i] = r.read_bit()?;
2465                ptl.sub_layer_non_packed_constraint_flag[i] = r.read_bit()?;
2466                ptl.sub_layer_frame_only_constraint_flag[i] = r.read_bit()?;
2467
2468                if ptl.sub_layer_profile_idc[i] == 4
2469                    || ptl.sub_layer_profile_compatibility_flag[i][4]
2470                    || ptl.sub_layer_profile_idc[i] == 5
2471                    || ptl.sub_layer_profile_compatibility_flag[i][5]
2472                    || ptl.sub_layer_profile_idc[i] == 6
2473                    || ptl.sub_layer_profile_compatibility_flag[i][6]
2474                    || ptl.sub_layer_profile_idc[i] == 7
2475                    || ptl.sub_layer_profile_compatibility_flag[i][7]
2476                    || ptl.sub_layer_profile_idc[i] == 8
2477                    || ptl.sub_layer_profile_compatibility_flag[i][8]
2478                    || ptl.sub_layer_profile_idc[i] == 9
2479                    || ptl.sub_layer_profile_compatibility_flag[i][9]
2480                    || ptl.sub_layer_profile_idc[i] == 10
2481                    || ptl.sub_layer_profile_compatibility_flag[i][10]
2482                    || ptl.sub_layer_profile_idc[i] == 11
2483                    || ptl.sub_layer_profile_compatibility_flag[i][11]
2484                {
2485                    ptl.sub_layer_max_12bit_constraint_flag[i] = r.read_bit()?;
2486                    ptl.sub_layer_max_10bit_constraint_flag[i] = r.read_bit()?;
2487                    ptl.sub_layer_max_8bit_constraint_flag[i] = r.read_bit()?;
2488                    ptl.sub_layer_max_422chroma_constraint_flag[i] = r.read_bit()?;
2489                    ptl.sub_layer_max_420chroma_constraint_flag[i] = r.read_bit()?;
2490                    ptl.sub_layer_max_monochrome_constraint_flag[i] = r.read_bit()?;
2491                    ptl.sub_layer_intra_constraint_flag[i] = r.read_bit()?;
2492                    ptl.sub_layer_one_picture_only_constraint_flag[i] = r.read_bit()?;
2493                    ptl.sub_layer_lower_bit_rate_constraint_flag[i] = r.read_bit()?;
2494
2495                    if ptl.sub_layer_profile_idc[i] == 5
2496                        || ptl.sub_layer_profile_compatibility_flag[i][5]
2497                        || ptl.sub_layer_profile_idc[i] == 9
2498                        || ptl.sub_layer_profile_compatibility_flag[i][9]
2499                        || ptl.sub_layer_profile_idc[i] == 10
2500                        || ptl.sub_layer_profile_compatibility_flag[i][10]
2501                        || ptl.sub_layer_profile_idc[i] == 11
2502                        || ptl.sub_layer_profile_compatibility_flag[i][11]
2503                    {
2504                        ptl.sub_layer_max_14bit_constraint_flag[i] = r.read_bit()?;
2505                        r.skip_bits(33)?;
2506                    } else {
2507                        r.skip_bits(34)?;
2508                    }
2509                } else if ptl.sub_layer_profile_idc[i] == 2
2510                    || ptl.sub_layer_profile_compatibility_flag[i][2]
2511                {
2512                    r.skip_bits(7)?;
2513                    ptl.sub_layer_one_picture_only_constraint_flag[i] = r.read_bit()?;
2514                    r.skip_bits(35)?;
2515                } else {
2516                    r.skip_bits(43)?;
2517                }
2518
2519                if ptl.sub_layer_profile_idc[i] == 1
2520                    || ptl.sub_layer_profile_compatibility_flag[i][1]
2521                    || ptl.sub_layer_profile_idc[i] == 2
2522                    || ptl.sub_layer_profile_compatibility_flag[i][2]
2523                    || ptl.sub_layer_profile_idc[i] == 3
2524                    || ptl.sub_layer_profile_compatibility_flag[i][3]
2525                    || ptl.sub_layer_profile_idc[i] == 4
2526                    || ptl.sub_layer_profile_compatibility_flag[i][4]
2527                    || ptl.sub_layer_profile_idc[i] == 5
2528                    || ptl.sub_layer_profile_compatibility_flag[i][5]
2529                    || ptl.sub_layer_profile_idc[i] == 9
2530                    || ptl.sub_layer_profile_compatibility_flag[i][9]
2531                    || ptl.sub_layer_profile_idc[i] == 11
2532                    || ptl.sub_layer_profile_compatibility_flag[i][11]
2533                {
2534                    ptl.sub_layer_inbld_flag[i] = r.read_bit()?;
2535                } else {
2536                    r.skip_bits(1)?;
2537                }
2538
2539                if ptl.sub_layer_level_present_flag[i] {
2540                    let level: u8 = r.read_bits(8)?;
2541                    ptl.sub_layer_level_idc[i] = Level::try_from(level)?;
2542                }
2543            }
2544        }
2545        Ok(())
2546    }
2547
2548    fn fill_default_scaling_list(sl: &mut ScalingLists, size_id: i32, matrix_id: i32) {
2549        if size_id == 0 {
2550            sl.scaling_list_4x4[matrix_id as usize] = DEFAULT_SCALING_LIST_0;
2551            return;
2552        }
2553
2554        let dst = match size_id {
2555            1 => &mut sl.scaling_list_8x8[matrix_id as usize],
2556            2 => &mut sl.scaling_list_16x16[matrix_id as usize],
2557            3 => &mut sl.scaling_list_32x32[matrix_id as usize],
2558            _ => panic!("Invalid size_id {}", size_id),
2559        };
2560
2561        let src = if matrix_id < 3 {
2562            &DEFAULT_SCALING_LIST_1
2563        } else if matrix_id <= 5 {
2564            &DEFAULT_SCALING_LIST_2
2565        } else {
2566            panic!("Invalid matrix_id {}", matrix_id);
2567        };
2568
2569        *dst = *src;
2570
2571        //  When `scaling_list_pred_mode_flag[ sizeId ]`[ matrixId ] is equal to
2572        //  0, scaling_list_pred_matrix_id_ `delta[ sizeId ]`[ matrixId ] is equal
2573        //  to 0 and sizeId is greater than 1, the value of
2574        //  scaling_list_dc_coef_minus8[ sizeId − 2 `][ matrixId ]` is inferred to
2575        //  be equal to 8.
2576        //
2577        // Since we are using a slightly different layout here, with two
2578        // different field names (i.e. 16x16, and 32x32), we must differentiate
2579        // between size_id == 2 or size_id == 3.
2580        if size_id == 2 {
2581            sl.scaling_list_dc_coef_minus8_16x16[matrix_id as usize] = 8;
2582        } else if size_id == 3 {
2583            sl.scaling_list_dc_coef_minus8_32x32[matrix_id as usize] = 8;
2584        }
2585    }
2586
2587    fn parse_scaling_list_data(sl: &mut ScalingLists, r: &mut BitReader) -> Result<(), String> {
2588        // 7.4.5
2589        for size_id in 0..4 {
2590            let mut matrix_id = 0;
2591            while matrix_id < 6 {
2592                let scaling_list_pred_mode_flag = r.read_bit()?;
2593                // If `scaling_list_pred_matrix_id_delta[ sizeId ]`[ matrixId ] is
2594                // equal to 0, the scaling list is inferred from the default
2595                // scaling list `ScalingList[ sizeId ]`[ matrixId `][ i ]` as specified
2596                // in Table 7-5 and Table 7-6 for i = 0..Min( 63, ( 1 << ( 4 + (
2597                // sizeId << 1 ) ) ) − 1 ).
2598                if !scaling_list_pred_mode_flag {
2599                    let scaling_list_pred_matrix_id_delta: u32 = r.read_ue()?;
2600                    if scaling_list_pred_matrix_id_delta == 0 {
2601                        Self::fill_default_scaling_list(sl, size_id, matrix_id);
2602                    } else {
2603                        // Equation 7-42
2604                        let factor = if size_id == 3 { 3 } else { 1 };
2605                        let ref_matrix_id =
2606                            matrix_id as u32 - scaling_list_pred_matrix_id_delta * factor;
2607                        if size_id == 0 {
2608                            sl.scaling_list_4x4[matrix_id as usize] =
2609                                sl.scaling_list_4x4[ref_matrix_id as usize];
2610                        } else {
2611                            let src = match size_id {
2612                                1 => sl.scaling_list_8x8[ref_matrix_id as usize],
2613                                2 => sl.scaling_list_16x16[ref_matrix_id as usize],
2614                                3 => sl.scaling_list_32x32[ref_matrix_id as usize],
2615                                _ => return Err(format!("Invalid size_id {}", size_id)),
2616                            };
2617
2618                            let dst = match size_id {
2619                                1 => &mut sl.scaling_list_8x8[matrix_id as usize],
2620                                2 => &mut sl.scaling_list_16x16[matrix_id as usize],
2621                                3 => &mut sl.scaling_list_32x32[matrix_id as usize],
2622                                _ => return Err(format!("Invalid size_id {}", size_id)),
2623                            };
2624
2625                            *dst = src;
2626
2627                            if size_id == 2 {
2628                                sl.scaling_list_dc_coef_minus8_16x16[matrix_id as usize] =
2629                                    sl.scaling_list_dc_coef_minus8_16x16[ref_matrix_id as usize];
2630                            } else if size_id == 3 {
2631                                sl.scaling_list_dc_coef_minus8_32x32[matrix_id as usize] =
2632                                    sl.scaling_list_dc_coef_minus8_32x32[ref_matrix_id as usize];
2633                            }
2634                        }
2635                    }
2636                } else {
2637                    let mut next_coef = 8i32;
2638                    let coef_num = std::cmp::min(64, 1 << (4 + (size_id << 1)));
2639
2640                    if size_id > 1 {
2641                        if size_id == 2 {
2642                            sl.scaling_list_dc_coef_minus8_16x16[matrix_id as usize] =
2643                                r.read_se_bounded(-7, 247)?;
2644                            next_coef =
2645                                i32::from(sl.scaling_list_dc_coef_minus8_16x16[matrix_id as usize])
2646                                    + 8;
2647                        } else if size_id == 3 {
2648                            sl.scaling_list_dc_coef_minus8_32x32[matrix_id as usize] =
2649                                r.read_se_bounded(-7, 247)?;
2650                            next_coef =
2651                                i32::from(sl.scaling_list_dc_coef_minus8_32x32[matrix_id as usize])
2652                                    + 8;
2653                        }
2654                    }
2655
2656                    for i in 0..coef_num as usize {
2657                        let scaling_list_delta_coef: i32 = r.read_se_bounded(-128, 127)?;
2658                        next_coef = (next_coef + scaling_list_delta_coef + 256) % 256;
2659                        match size_id {
2660                            0 => sl.scaling_list_4x4[matrix_id as usize][i] = next_coef as _,
2661                            1 => sl.scaling_list_8x8[matrix_id as usize][i] = next_coef as _,
2662                            2 => sl.scaling_list_16x16[matrix_id as usize][i] = next_coef as _,
2663                            3 => sl.scaling_list_32x32[matrix_id as usize][i] = next_coef as _,
2664                            _ => return Err(format!("Invalid size_id {}", size_id)),
2665                        }
2666                    }
2667                }
2668                let step = if size_id == 3 { 3 } else { 1 };
2669                matrix_id += step;
2670            }
2671        }
2672        Ok(())
2673    }
2674
2675    fn parse_short_term_ref_pic_set(
2676        sps: &Sps,
2677        st: &mut ShortTermRefPicSet,
2678        r: &mut BitReader,
2679        st_rps_idx: u8,
2680    ) -> Result<(), String> {
2681        if st_rps_idx != 0 {
2682            st.inter_ref_pic_set_prediction_flag = r.read_bit()?;
2683        }
2684
2685        // (7-59)
2686        if st.inter_ref_pic_set_prediction_flag {
2687            if st_rps_idx == sps.num_short_term_ref_pic_sets {
2688                st.delta_idx_minus1 = r.read_ue_max(st_rps_idx as u32 - 1)?;
2689            }
2690
2691            st.delta_rps_sign = r.read_bit()?;
2692            // The value of abs_delta_rps_minus1 shall be in the range of 0 to
2693            // 2^15 − 1, inclusive.
2694            st.abs_delta_rps_minus1 = r.read_ue_max(32767)?;
2695
2696            let ref_rps_idx = st_rps_idx - (st.delta_idx_minus1 + 1);
2697            let delta_rps =
2698                (1 - 2 * st.delta_rps_sign as i32) * (st.abs_delta_rps_minus1 as i32 + 1);
2699
2700            let ref_st = sps
2701                .short_term_ref_pic_set
2702                .get(usize::from(ref_rps_idx))
2703                .ok_or::<String>("Invalid ref_rps_idx".into())?;
2704
2705            let mut used_by_curr_pic_flag = [false; 64];
2706
2707            // 7.4.8 - defaults to 1 if not present
2708            let mut use_delta_flag = [true; 64];
2709
2710            for j in 0..=ref_st.num_delta_pocs as usize {
2711                used_by_curr_pic_flag[j] = r.read_bit()?;
2712                if !used_by_curr_pic_flag[j] {
2713                    use_delta_flag[j] = r.read_bit()?;
2714                }
2715            }
2716
2717            // (7-61)
2718            let mut i = 0;
2719            // Ranges are [a,b[, but the real loop is [b, a], i.e.
2720            // [num_positive_pics - 1, 0]. Use ..= so that b is included when
2721            // rev() is called.
2722            for j in (0..=isize::from(ref_st.num_positive_pics) - 1)
2723                .rev()
2724                .take_while(|j| *j >= 0)
2725                .map(|j| j as usize)
2726            {
2727                let d_poc = ref_st.delta_poc_s1[j] + delta_rps;
2728                if d_poc < 0 && use_delta_flag[usize::from(ref_st.num_negative_pics) + j] {
2729                    st.delta_poc_s0[i] = d_poc;
2730                    st.used_by_curr_pic_s0[i] =
2731                        used_by_curr_pic_flag[usize::from(ref_st.num_negative_pics) + j];
2732
2733                    i += 1;
2734                }
2735            }
2736
2737            if delta_rps < 0 && use_delta_flag[ref_st.num_delta_pocs as usize] {
2738                st.delta_poc_s0[i] = delta_rps;
2739                st.used_by_curr_pic_s0[i] = used_by_curr_pic_flag[ref_st.num_delta_pocs as usize];
2740
2741                i += 1;
2742            }
2743
2744            // Let's *not* change the original algorithm in any way.
2745            #[allow(clippy::needless_range_loop)]
2746            for j in 0..ref_st.num_negative_pics as usize {
2747                let d_poc = ref_st.delta_poc_s0[j] + delta_rps;
2748                if d_poc < 0 && use_delta_flag[j] {
2749                    st.delta_poc_s0[i] = d_poc;
2750                    st.used_by_curr_pic_s0[i] = used_by_curr_pic_flag[j];
2751
2752                    i += 1;
2753                }
2754            }
2755
2756            st.num_negative_pics = i as u8;
2757
2758            // (7-62)
2759            let mut i = 0;
2760            // Ranges are [a,b[, but the real loop is [b, a], i.e.
2761            // [num_negative_pics - 1, 0]. Use ..= so that b is included when
2762            // rev() is called.
2763            for j in (0..=isize::from(ref_st.num_negative_pics) - 1)
2764                .rev()
2765                .take_while(|j| *j >= 0)
2766                .map(|j| j as usize)
2767            {
2768                let d_poc = ref_st.delta_poc_s0[j] + delta_rps;
2769                if d_poc > 0 && use_delta_flag[j] {
2770                    st.delta_poc_s1[i] = d_poc;
2771                    st.used_by_curr_pic_s1[i] = used_by_curr_pic_flag[j];
2772
2773                    i += 1;
2774                }
2775            }
2776
2777            if delta_rps > 0 && use_delta_flag[ref_st.num_delta_pocs as usize] {
2778                st.delta_poc_s1[i] = delta_rps;
2779                st.used_by_curr_pic_s1[i] = used_by_curr_pic_flag[ref_st.num_delta_pocs as usize];
2780
2781                i += 1;
2782            }
2783
2784            for j in 0..usize::from(ref_st.num_positive_pics) {
2785                let d_poc = ref_st.delta_poc_s1[j] + delta_rps;
2786                if d_poc > 0 && use_delta_flag[ref_st.num_negative_pics as usize + j] {
2787                    st.delta_poc_s1[i] = d_poc;
2788                    st.used_by_curr_pic_s1[i] =
2789                        used_by_curr_pic_flag[ref_st.num_negative_pics as usize + j];
2790
2791                    i += 1;
2792                }
2793            }
2794
2795            st.num_positive_pics = i as u8;
2796        } else {
2797            st.num_negative_pics = r.read_ue_max(u32::from(
2798                sps.max_dec_pic_buffering_minus1[usize::from(sps.max_sub_layers_minus1)],
2799            ))?;
2800
2801            st.num_positive_pics = r.read_ue_max(u32::from(
2802                sps.max_dec_pic_buffering_minus1[usize::from(sps.max_sub_layers_minus1)]
2803                    - st.num_negative_pics,
2804            ))?;
2805
2806            for i in 0..usize::from(st.num_negative_pics) {
2807                let delta_poc_s0_minus1: u32 = r.read_ue_max(32767)?;
2808
2809                if i == 0 {
2810                    st.delta_poc_s0[i] = -(delta_poc_s0_minus1 as i32 + 1);
2811                } else {
2812                    st.delta_poc_s0[i] = st.delta_poc_s0[i - 1] - (delta_poc_s0_minus1 as i32 + 1);
2813                }
2814
2815                st.used_by_curr_pic_s0[i] = r.read_bit()?;
2816            }
2817
2818            for i in 0..usize::from(st.num_positive_pics) {
2819                let delta_poc_s1_minus1: u32 = r.read_ue_max(32767)?;
2820
2821                if i == 0 {
2822                    st.delta_poc_s1[i] = delta_poc_s1_minus1 as i32 + 1;
2823                } else {
2824                    st.delta_poc_s1[i] = st.delta_poc_s1[i - 1] + (delta_poc_s1_minus1 as i32 + 1);
2825                }
2826
2827                st.used_by_curr_pic_s1[i] = r.read_bit()?;
2828            }
2829        }
2830
2831        st.num_delta_pocs = u32::from(st.num_negative_pics + st.num_positive_pics);
2832
2833        Ok(())
2834    }
2835
2836    fn parse_sublayer_hrd_parameters(
2837        h: &mut SublayerHrdParameters,
2838        cpb_cnt: u32,
2839        sub_pic_hrd_params_present_flag: bool,
2840        r: &mut BitReader,
2841    ) -> Result<(), String> {
2842        for i in 0..cpb_cnt as usize {
2843            h.bit_rate_value_minus1[i] = r.read_ue_max((2u64.pow(32) - 2) as u32)?;
2844            h.cpb_size_value_minus1[i] = r.read_ue_max((2u64.pow(32) - 2) as u32)?;
2845            if sub_pic_hrd_params_present_flag {
2846                h.cpb_size_du_value_minus1[i] = r.read_ue_max((2u64.pow(32) - 2) as u32)?;
2847                h.bit_rate_du_value_minus1[i] = r.read_ue_max((2u64.pow(32) - 2) as u32)?;
2848            }
2849
2850            h.cbr_flag[i] = r.read_bit()?;
2851        }
2852
2853        Ok(())
2854    }
2855
2856    fn parse_hrd_parameters(
2857        common_inf_present_flag: bool,
2858        max_num_sublayers_minus1: u8,
2859        hrd: &mut HrdParams,
2860        r: &mut BitReader,
2861    ) -> Result<(), String> {
2862        if common_inf_present_flag {
2863            hrd.nal_hrd_parameters_present_flag = r.read_bit()?;
2864            hrd.vcl_hrd_parameters_present_flag = r.read_bit()?;
2865            if hrd.nal_hrd_parameters_present_flag || hrd.vcl_hrd_parameters_present_flag {
2866                hrd.sub_pic_hrd_params_present_flag = r.read_bit()?;
2867                if hrd.sub_pic_hrd_params_present_flag {
2868                    hrd.tick_divisor_minus2 = r.read_bits(8)?;
2869                    hrd.du_cpb_removal_delay_increment_length_minus1 = r.read_bits(5)?;
2870                    hrd.sub_pic_cpb_params_in_pic_timing_sei_flag = r.read_bit()?;
2871                    hrd.dpb_output_delay_du_length_minus1 = r.read_bits(5)?;
2872                }
2873                hrd.bit_rate_scale = r.read_bits(4)?;
2874                hrd.cpb_size_scale = r.read_bits(4)?;
2875                if hrd.sub_pic_hrd_params_present_flag {
2876                    hrd.cpb_size_du_scale = r.read_bits(4)?;
2877                }
2878                hrd.initial_cpb_removal_delay_length_minus1 = r.read_bits(5)?;
2879                hrd.au_cpb_removal_delay_length_minus1 = r.read_bits(5)?;
2880                hrd.dpb_output_delay_length_minus1 = r.read_bits(5)?;
2881            }
2882        }
2883
2884        for i in 0..=max_num_sublayers_minus1 as usize {
2885            hrd.fixed_pic_rate_general_flag[i] = r.read_bit()?;
2886            if !hrd.fixed_pic_rate_general_flag[i] {
2887                hrd.fixed_pic_rate_within_cvs_flag[i] = r.read_bit()?;
2888            }
2889            if hrd.fixed_pic_rate_within_cvs_flag[i] {
2890                hrd.elemental_duration_in_tc_minus1[i] = r.read_ue_max(2047)?;
2891            } else {
2892                hrd.low_delay_hrd_flag[i] = r.read_bit()?;
2893            }
2894
2895            if !hrd.low_delay_hrd_flag[i] {
2896                hrd.cpb_cnt_minus1[i] = r.read_ue_max(31)?;
2897            }
2898
2899            if hrd.nal_hrd_parameters_present_flag {
2900                Self::parse_sublayer_hrd_parameters(
2901                    &mut hrd.nal_hrd[i],
2902                    hrd.cpb_cnt_minus1[i] + 1,
2903                    hrd.sub_pic_hrd_params_present_flag,
2904                    r,
2905                )?;
2906            }
2907
2908            if hrd.vcl_hrd_parameters_present_flag {
2909                Self::parse_sublayer_hrd_parameters(
2910                    &mut hrd.vcl_hrd[i],
2911                    hrd.cpb_cnt_minus1[i] + 1,
2912                    hrd.sub_pic_hrd_params_present_flag,
2913                    r,
2914                )?;
2915            }
2916        }
2917
2918        Ok(())
2919    }
2920
2921    fn parse_vui_parameters(sps: &mut Sps, r: &mut BitReader) -> Result<(), String> {
2922        let vui = &mut sps.vui_parameters;
2923
2924        vui.aspect_ratio_info_present_flag = r.read_bit()?;
2925        if vui.aspect_ratio_info_present_flag {
2926            vui.aspect_ratio_idc = r.read_bits(8)?;
2927            const EXTENDED_SAR: u32 = 255;
2928            if vui.aspect_ratio_idc == EXTENDED_SAR {
2929                vui.sar_width = r.read_bits(16)?;
2930                vui.sar_height = r.read_bits(16)?;
2931            }
2932        }
2933
2934        vui.overscan_info_present_flag = r.read_bit()?;
2935        if vui.overscan_info_present_flag {
2936            vui.overscan_appropriate_flag = r.read_bit()?;
2937        }
2938
2939        vui.video_signal_type_present_flag = r.read_bit()?;
2940        if vui.video_signal_type_present_flag {
2941            vui.video_format = r.read_bits(3)?;
2942            vui.video_full_range_flag = r.read_bit()?;
2943            vui.colour_description_present_flag = r.read_bit()?;
2944            if vui.colour_description_present_flag {
2945                vui.colour_primaries = r.read_bits(8)?;
2946                vui.transfer_characteristics = r.read_bits(8)?;
2947                vui.matrix_coeffs = r.read_bits(8)?;
2948            }
2949        }
2950
2951        vui.chroma_loc_info_present_flag = r.read_bit()?;
2952        if vui.chroma_loc_info_present_flag {
2953            vui.chroma_sample_loc_type_top_field = r.read_ue_max(5)?;
2954            vui.chroma_sample_loc_type_bottom_field = r.read_ue_max(5)?;
2955        }
2956
2957        vui.neutral_chroma_indication_flag = r.read_bit()?;
2958        vui.field_seq_flag = r.read_bit()?;
2959        vui.frame_field_info_present_flag = r.read_bit()?;
2960        vui.default_display_window_flag = r.read_bit()?;
2961
2962        if vui.default_display_window_flag {
2963            vui.def_disp_win_left_offset = r.read_ue()?;
2964            vui.def_disp_win_right_offset = r.read_ue()?;
2965            vui.def_disp_win_top_offset = r.read_ue()?;
2966            vui.def_disp_win_bottom_offset = r.read_ue()?;
2967        }
2968
2969        vui.timing_info_present_flag = r.read_bit()?;
2970        if vui.timing_info_present_flag {
2971            vui.num_units_in_tick = r.read_bits::<u32>(31)? << 1;
2972            vui.num_units_in_tick |= r.read_bits::<u32>(1)?;
2973
2974            if vui.num_units_in_tick == 0 {
2975                log::warn!("Incompliant value for num_units_in_tick {}", vui.num_units_in_tick);
2976            }
2977
2978            vui.time_scale = r.read_bits::<u32>(31)? << 1;
2979            vui.time_scale |= r.read_bits::<u32>(1)?;
2980
2981            if vui.time_scale == 0 {
2982                log::warn!("Incompliant value for time_scale {}", vui.time_scale);
2983            }
2984
2985            vui.poc_proportional_to_timing_flag = r.read_bit()?;
2986            if vui.poc_proportional_to_timing_flag {
2987                vui.num_ticks_poc_diff_one_minus1 = r.read_ue_max((2u64.pow(32) - 2) as u32)?;
2988            }
2989
2990            vui.hrd_parameters_present_flag = r.read_bit()?;
2991            if vui.hrd_parameters_present_flag {
2992                let sps_max_sub_layers_minus1 = sps.max_sub_layers_minus1;
2993                Self::parse_hrd_parameters(true, sps_max_sub_layers_minus1, &mut vui.hrd, r)?;
2994            }
2995        }
2996
2997        vui.bitstream_restriction_flag = r.read_bit()?;
2998        if vui.bitstream_restriction_flag {
2999            vui.tiles_fixed_structure_flag = r.read_bit()?;
3000            vui.motion_vectors_over_pic_boundaries_flag = r.read_bit()?;
3001            vui.restricted_ref_pic_lists_flag = r.read_bit()?;
3002
3003            vui.min_spatial_segmentation_idc = r.read_ue_max(4095)?;
3004            vui.max_bytes_per_pic_denom = r.read_ue()?;
3005            vui.max_bits_per_min_cu_denom = r.read_ue()?;
3006            vui.log2_max_mv_length_horizontal = r.read_ue_max(16)?;
3007            vui.log2_max_mv_length_vertical = r.read_ue_max(15)?;
3008        }
3009
3010        Ok(())
3011    }
3012
3013    fn parse_sps_scc_extension(sps: &mut Sps, r: &mut BitReader) -> Result<(), String> {
3014        let scc = &mut sps.scc_extension;
3015
3016        scc.curr_pic_ref_enabled_flag = r.read_bit()?;
3017        scc.palette_mode_enabled_flag = r.read_bit()?;
3018        if scc.palette_mode_enabled_flag {
3019            scc.palette_max_size = r.read_ue_max(64)?;
3020            scc.delta_palette_max_predictor_size =
3021                r.read_ue_max(128 - u32::from(scc.palette_max_size))?;
3022            scc.palette_predictor_initializers_present_flag = r.read_bit()?;
3023            if scc.palette_predictor_initializers_present_flag {
3024                let max =
3025                    u32::from(scc.palette_max_size + scc.delta_palette_max_predictor_size - 1);
3026                scc.num_palette_predictor_initializer_minus1 = r.read_ue_max(max)?;
3027
3028                let num_comps = if sps.chroma_format_idc == 0 { 1 } else { 3 };
3029                for comp in 0..num_comps {
3030                    for i in 0..=usize::from(scc.num_palette_predictor_initializer_minus1) {
3031                        let num_bits = if comp == 0 {
3032                            sps.bit_depth_luma_minus8 + 8
3033                        } else {
3034                            sps.bit_depth_chroma_minus8 + 8
3035                        };
3036                        scc.palette_predictor_initializer[comp][i] =
3037                            r.read_bits(usize::from(num_bits))?;
3038                    }
3039                }
3040            }
3041        }
3042
3043        scc.motion_vector_resolution_control_idc = r.read_bits(2)?;
3044        scc.intra_boundary_filtering_disabled_flag = r.read_bit()?;
3045
3046        Ok(())
3047    }
3048
3049    fn parse_sps_range_extension(sps: &mut Sps, r: &mut BitReader) -> Result<(), String> {
3050        let ext = &mut sps.range_extension;
3051
3052        ext.transform_skip_rotation_enabled_flag = r.read_bit()?;
3053        ext.transform_skip_context_enabled_flag = r.read_bit()?;
3054        ext.implicit_rdpcm_enabled_flag = r.read_bit()?;
3055        ext.explicit_rdpcm_enabled_flag = r.read_bit()?;
3056        ext.extended_precision_processing_flag = r.read_bit()?;
3057        ext.intra_smoothing_disabled_flag = r.read_bit()?;
3058        ext.high_precision_offsets_enabled_flag = r.read_bit()?;
3059        ext.persistent_rice_adaptation_enabled_flag = r.read_bit()?;
3060        ext.cabac_bypass_alignment_enabled_flag = r.read_bit()?;
3061
3062        Ok(())
3063    }
3064
3065    /// Parse a SPS NALU.
3066    pub fn parse_sps(&mut self, nalu: &Nalu) -> Result<&Sps, String> {
3067        if !matches!(nalu.header.type_, NaluType::SpsNut) {
3068            return Err(format!(
3069                "Invalid NALU type, expected {:?}, got {:?}",
3070                NaluType::SpsNut,
3071                nalu.header.type_
3072            ));
3073        }
3074
3075        let data = nalu.as_ref();
3076        let header = &nalu.header;
3077        let hdr_len = header.len();
3078        // Skip the header
3079        let mut r = BitReader::new(&data[hdr_len..], true);
3080
3081        let video_parameter_set_id = r.read_bits(4)?;
3082
3083        // A non-existing VPS means the SPS is not using any VPS.
3084        let vps = self.get_vps(video_parameter_set_id).cloned();
3085
3086        let mut sps = Sps {
3087            video_parameter_set_id,
3088            max_sub_layers_minus1: r.read_bits(3)?,
3089            temporal_id_nesting_flag: r.read_bit()?,
3090            vps,
3091            ..Default::default()
3092        };
3093
3094        Self::parse_profile_tier_level(
3095            &mut sps.profile_tier_level,
3096            &mut r,
3097            true,
3098            sps.max_sub_layers_minus1,
3099        )?;
3100
3101        sps.seq_parameter_set_id = r.read_ue_max(MAX_SPS_COUNT as u32 - 1)?;
3102        sps.chroma_format_idc = r.read_ue_max(3)?;
3103
3104        if sps.chroma_format_idc == 3 {
3105            sps.separate_colour_plane_flag = r.read_bit()?;
3106        }
3107
3108        sps.chroma_array_type =
3109            if sps.separate_colour_plane_flag { 0 } else { sps.chroma_format_idc };
3110
3111        sps.pic_width_in_luma_samples = r.read_ue_bounded(1, 16888)?;
3112        sps.pic_height_in_luma_samples = r.read_ue_bounded(1, 16888)?;
3113
3114        sps.conformance_window_flag = r.read_bit()?;
3115        if sps.conformance_window_flag {
3116            sps.conf_win_left_offset = r.read_ue()?;
3117            sps.conf_win_right_offset = r.read_ue()?;
3118            sps.conf_win_top_offset = r.read_ue()?;
3119            sps.conf_win_bottom_offset = r.read_ue()?;
3120        }
3121
3122        sps.bit_depth_luma_minus8 = r.read_ue_max(6)?;
3123        sps.bit_depth_chroma_minus8 = r.read_ue_max(6)?;
3124        sps.log2_max_pic_order_cnt_lsb_minus4 = r.read_ue_max(12)?;
3125        sps.sub_layer_ordering_info_present_flag = r.read_bit()?;
3126
3127        {
3128            let i = if sps.sub_layer_ordering_info_present_flag {
3129                0
3130            } else {
3131                sps.max_sub_layers_minus1
3132            };
3133
3134            for j in i..=sps.max_sub_layers_minus1 {
3135                sps.max_dec_pic_buffering_minus1[j as usize] = r.read_ue_max(16)?;
3136                sps.max_num_reorder_pics[j as usize] =
3137                    r.read_ue_max(sps.max_dec_pic_buffering_minus1[j as usize] as _)?;
3138                sps.max_latency_increase_plus1[j as usize] = r.read_ue_max(u32::MAX - 1)?;
3139            }
3140        }
3141
3142        sps.log2_min_luma_coding_block_size_minus3 = r.read_ue_max(3)?;
3143        sps.log2_diff_max_min_luma_coding_block_size = r.read_ue_max(6)?;
3144        sps.log2_min_luma_transform_block_size_minus2 = r.read_ue_max(3)?;
3145        sps.log2_diff_max_min_luma_transform_block_size = r.read_ue_max(3)?;
3146
3147        // (7-10)
3148        sps.min_cb_log2_size_y = u32::from(sps.log2_min_luma_coding_block_size_minus3 + 3);
3149        // (7-11)
3150        sps.ctb_log2_size_y =
3151            sps.min_cb_log2_size_y + u32::from(sps.log2_diff_max_min_luma_coding_block_size);
3152        // (7-12)
3153        sps.ctb_size_y = 1 << sps.ctb_log2_size_y;
3154        // (7-17)
3155        sps.pic_height_in_ctbs_y =
3156            (sps.pic_height_in_luma_samples as f64 / sps.ctb_size_y as f64).ceil() as u32;
3157        // (7-15)
3158        sps.pic_width_in_ctbs_y =
3159            (sps.pic_width_in_luma_samples as f64 / sps.ctb_size_y as f64).ceil() as u32;
3160
3161        sps.max_tb_log2_size_y = u32::from(
3162            sps.log2_min_luma_transform_block_size_minus2
3163                + 2
3164                + sps.log2_diff_max_min_luma_transform_block_size,
3165        );
3166
3167        sps.pic_size_in_samples_y =
3168            u32::from(sps.pic_width_in_luma_samples) * u32::from(sps.pic_height_in_luma_samples);
3169
3170        if sps.max_tb_log2_size_y > std::cmp::min(sps.ctb_log2_size_y, 5) {
3171            return Err(format!("Invalid value for MaxTbLog2SizeY: {}", sps.max_tb_log2_size_y));
3172        }
3173
3174        sps.pic_size_in_ctbs_y = sps.pic_width_in_ctbs_y * sps.pic_height_in_ctbs_y;
3175
3176        sps.max_transform_hierarchy_depth_inter = r.read_ue_max(4)?;
3177        sps.max_transform_hierarchy_depth_intra = r.read_ue_max(4)?;
3178
3179        sps.scaling_list_enabled_flag = r.read_bit()?;
3180        if sps.scaling_list_enabled_flag {
3181            sps.scaling_list_data_present_flag = r.read_bit()?;
3182            if sps.scaling_list_data_present_flag {
3183                Self::parse_scaling_list_data(&mut sps.scaling_list, &mut r)?;
3184            }
3185        }
3186
3187        sps.amp_enabled_flag = r.read_bit()?;
3188        sps.sample_adaptive_offset_enabled_flag = r.read_bit()?;
3189
3190        sps.pcm_enabled_flag = r.read_bit()?;
3191        if sps.pcm_enabled_flag {
3192            sps.pcm_sample_bit_depth_luma_minus1 = r.read_bits(4)?;
3193            sps.pcm_sample_bit_depth_chroma_minus1 = r.read_bits(4)?;
3194            sps.log2_min_pcm_luma_coding_block_size_minus3 = r.read_ue_max(2)?;
3195            sps.log2_diff_max_min_pcm_luma_coding_block_size = r.read_ue_max(2)?;
3196            sps.pcm_loop_filter_disabled_flag = r.read_bit()?;
3197        }
3198
3199        sps.num_short_term_ref_pic_sets = r.read_ue_max(64)?;
3200
3201        for i in 0..sps.num_short_term_ref_pic_sets {
3202            let mut st = ShortTermRefPicSet::default();
3203            Self::parse_short_term_ref_pic_set(&sps, &mut st, &mut r, i)?;
3204            sps.short_term_ref_pic_set.push(st);
3205        }
3206
3207        sps.long_term_ref_pics_present_flag = r.read_bit()?;
3208        if sps.long_term_ref_pics_present_flag {
3209            sps.num_long_term_ref_pics_sps = r.read_ue_max(32)?;
3210            for i in 0..usize::from(sps.num_long_term_ref_pics_sps) {
3211                sps.lt_ref_pic_poc_lsb_sps[i] =
3212                    r.read_bits(usize::from(sps.log2_max_pic_order_cnt_lsb_minus4) + 4)?;
3213                sps.used_by_curr_pic_lt_sps_flag[i] = r.read_bit()?;
3214            }
3215        }
3216
3217        sps.temporal_mvp_enabled_flag = r.read_bit()?;
3218        sps.strong_intra_smoothing_enabled_flag = r.read_bit()?;
3219
3220        sps.vui_parameters_present_flag = r.read_bit()?;
3221        if sps.vui_parameters_present_flag {
3222            Self::parse_vui_parameters(&mut sps, &mut r)?;
3223        }
3224
3225        sps.extension_present_flag = r.read_bit()?;
3226        if sps.extension_present_flag {
3227            sps.range_extension_flag = r.read_bit()?;
3228            if sps.range_extension_flag {
3229                Self::parse_sps_range_extension(&mut sps, &mut r)?;
3230            }
3231
3232            let multilayer_extension_flag = r.read_bit()?;
3233            if multilayer_extension_flag {
3234                return Err("Multilayer extension not supported.".into());
3235            }
3236
3237            let three_d_extension_flag = r.read_bit()?;
3238            if three_d_extension_flag {
3239                return Err("3D extension not supported.".into());
3240            }
3241
3242            sps.scc_extension_flag = r.read_bit()?;
3243            if sps.scc_extension_flag {
3244                Self::parse_sps_scc_extension(&mut sps, &mut r)?;
3245            }
3246        }
3247
3248        let shift = if sps.range_extension.high_precision_offsets_enabled_flag {
3249            sps.bit_depth_luma_minus8 + 7
3250        } else {
3251            7
3252        };
3253
3254        sps.wp_offset_half_range_y = 1 << shift;
3255
3256        let shift = if sps.range_extension.high_precision_offsets_enabled_flag {
3257            sps.bit_depth_chroma_minus8 + 7
3258        } else {
3259            7
3260        };
3261
3262        sps.wp_offset_half_range_c = 1 << shift;
3263
3264        log::debug!(
3265            "Parsed SPS({}), resolution: ({}, {}): NAL size was {}",
3266            sps.seq_parameter_set_id,
3267            sps.width(),
3268            sps.height(),
3269            nalu.size
3270        );
3271
3272        if self.active_spses.keys().len() >= MAX_SPS_COUNT {
3273            return Err("Broken data: Number of active SPSs > MAX_SPS_COUNT".into());
3274        }
3275
3276        let key = sps.seq_parameter_set_id;
3277        let sps = Rc::new(sps);
3278        self.active_spses.remove(&key);
3279        Ok(self.active_spses.entry(key).or_insert(sps))
3280    }
3281
3282    fn parse_pps_scc_extension(pps: &mut Pps, sps: &Sps, r: &mut BitReader) -> Result<(), String> {
3283        let scc = &mut pps.scc_extension;
3284        scc.curr_pic_ref_enabled_flag = r.read_bit()?;
3285        scc.residual_adaptive_colour_transform_enabled_flag = r.read_bit()?;
3286        if scc.residual_adaptive_colour_transform_enabled_flag {
3287            scc.slice_act_qp_offsets_present_flag = r.read_bit()?;
3288            scc.act_y_qp_offset_plus5 = r.read_se_bounded(-7, 17)?;
3289            scc.act_cb_qp_offset_plus5 = r.read_se_bounded(-7, 17)?;
3290            scc.act_cr_qp_offset_plus3 = r.read_se_bounded(-9, 15)?;
3291        }
3292
3293        scc.palette_predictor_initializers_present_flag = r.read_bit()?;
3294        if scc.palette_predictor_initializers_present_flag {
3295            let max = sps.scc_extension.palette_max_size
3296                + sps.scc_extension.delta_palette_max_predictor_size;
3297            scc.num_palette_predictor_initializers = r.read_ue_max(max.into())?;
3298            if scc.num_palette_predictor_initializers > 0 {
3299                scc.monochrome_palette_flag = r.read_bit()?;
3300                scc.luma_bit_depth_entry_minus8 = r.read_ue_bounded(
3301                    sps.bit_depth_luma_minus8.into(),
3302                    sps.bit_depth_luma_minus8.into(),
3303                )?;
3304                if !scc.monochrome_palette_flag {
3305                    scc.chroma_bit_depth_entry_minus8 = r.read_ue_bounded(
3306                        sps.bit_depth_chroma_minus8.into(),
3307                        sps.bit_depth_chroma_minus8.into(),
3308                    )?;
3309                }
3310
3311                let num_comps = if scc.monochrome_palette_flag { 1 } else { 3 };
3312                for comp in 0..num_comps {
3313                    let num_bits = if comp == 0 {
3314                        scc.luma_bit_depth_entry_minus8 + 8
3315                    } else {
3316                        scc.chroma_bit_depth_entry_minus8 + 8
3317                    };
3318                    for i in 0..usize::from(scc.num_palette_predictor_initializers) {
3319                        scc.palette_predictor_initializer[comp][i] =
3320                            r.read_bits(num_bits.into())?;
3321                    }
3322                }
3323            }
3324        }
3325        Ok(())
3326    }
3327
3328    fn parse_pps_range_extension(
3329        pps: &mut Pps,
3330        sps: &Sps,
3331        r: &mut BitReader,
3332    ) -> Result<(), String> {
3333        let rext = &mut pps.range_extension;
3334
3335        if pps.transform_skip_enabled_flag {
3336            rext.log2_max_transform_skip_block_size_minus2 =
3337                r.read_ue_max(sps.max_tb_log2_size_y - 2)?;
3338        }
3339
3340        rext.cross_component_prediction_enabled_flag = r.read_bit()?;
3341        rext.chroma_qp_offset_list_enabled_flag = r.read_bit()?;
3342        if rext.chroma_qp_offset_list_enabled_flag {
3343            rext.diff_cu_chroma_qp_offset_depth = r.read_ue()?;
3344            rext.chroma_qp_offset_list_len_minus1 = r.read_ue_max(5)?;
3345            for i in 0..=rext.chroma_qp_offset_list_len_minus1 as usize {
3346                rext.cb_qp_offset_list[i] = r.read_se_bounded(-12, 12)?;
3347                rext.cr_qp_offset_list[i] = r.read_se_bounded(-12, 12)?;
3348            }
3349        }
3350
3351        let bit_depth_y = sps.bit_depth_luma_minus8 + 8;
3352        let max = u32::from(std::cmp::max(0, bit_depth_y - 10));
3353
3354        rext.log2_sao_offset_scale_luma = r.read_ue_max(max)?;
3355        rext.log2_sao_offset_scale_chroma = r.read_ue_max(max)?;
3356
3357        Ok(())
3358    }
3359
3360    /// Parse a PPS NALU.
3361    pub fn parse_pps(&mut self, nalu: &Nalu) -> Result<&Pps, String> {
3362        if !matches!(nalu.header.type_, NaluType::PpsNut) {
3363            return Err(format!(
3364                "Invalid NALU type, expected {:?}, got {:?}",
3365                NaluType::PpsNut,
3366                nalu.header.type_
3367            ));
3368        }
3369
3370        let data = nalu.as_ref();
3371        let header = &nalu.header;
3372        let hdr_len = header.len();
3373        // Skip the header
3374        let mut r = BitReader::new(&data[hdr_len..], true);
3375
3376        let pic_parameter_set_id = r.read_ue_max(MAX_PPS_COUNT as u32 - 1)?;
3377        let seq_parameter_set_id = r.read_ue_max(MAX_SPS_COUNT as u32 - 1)?;
3378
3379        let sps = self.get_sps(seq_parameter_set_id).ok_or::<String>(format!(
3380            "Could not get SPS for seq_parameter_set_id {}",
3381            seq_parameter_set_id
3382        ))?;
3383
3384        let mut pps = Pps {
3385            pic_parameter_set_id,
3386            seq_parameter_set_id,
3387            dependent_slice_segments_enabled_flag: Default::default(),
3388            output_flag_present_flag: Default::default(),
3389            num_extra_slice_header_bits: Default::default(),
3390            sign_data_hiding_enabled_flag: Default::default(),
3391            cabac_init_present_flag: Default::default(),
3392            num_ref_idx_l0_default_active_minus1: Default::default(),
3393            num_ref_idx_l1_default_active_minus1: Default::default(),
3394            init_qp_minus26: Default::default(),
3395            constrained_intra_pred_flag: Default::default(),
3396            transform_skip_enabled_flag: Default::default(),
3397            cu_qp_delta_enabled_flag: Default::default(),
3398            diff_cu_qp_delta_depth: Default::default(),
3399            cb_qp_offset: Default::default(),
3400            cr_qp_offset: Default::default(),
3401            slice_chroma_qp_offsets_present_flag: Default::default(),
3402            weighted_pred_flag: Default::default(),
3403            weighted_bipred_flag: Default::default(),
3404            transquant_bypass_enabled_flag: Default::default(),
3405            tiles_enabled_flag: Default::default(),
3406            entropy_coding_sync_enabled_flag: Default::default(),
3407            num_tile_columns_minus1: Default::default(),
3408            num_tile_rows_minus1: Default::default(),
3409            uniform_spacing_flag: true,
3410            column_width_minus1: Default::default(),
3411            row_height_minus1: Default::default(),
3412            loop_filter_across_tiles_enabled_flag: true,
3413            loop_filter_across_slices_enabled_flag: Default::default(),
3414            deblocking_filter_control_present_flag: Default::default(),
3415            deblocking_filter_override_enabled_flag: Default::default(),
3416            deblocking_filter_disabled_flag: Default::default(),
3417            beta_offset_div2: Default::default(),
3418            tc_offset_div2: Default::default(),
3419            scaling_list_data_present_flag: Default::default(),
3420            scaling_list: Default::default(),
3421            lists_modification_present_flag: Default::default(),
3422            log2_parallel_merge_level_minus2: Default::default(),
3423            slice_segment_header_extension_present_flag: Default::default(),
3424            extension_present_flag: Default::default(),
3425            range_extension_flag: Default::default(),
3426            range_extension: Default::default(),
3427            qp_bd_offset_y: Default::default(),
3428            scc_extension: Default::default(),
3429            scc_extension_flag: Default::default(),
3430            sps: Rc::clone(sps),
3431        };
3432
3433        pps.dependent_slice_segments_enabled_flag = r.read_bit()?;
3434        pps.output_flag_present_flag = r.read_bit()?;
3435        pps.num_extra_slice_header_bits = r.read_bits(3)?;
3436        pps.sign_data_hiding_enabled_flag = r.read_bit()?;
3437        pps.cabac_init_present_flag = r.read_bit()?;
3438
3439        // 7.4.7.1
3440        pps.num_ref_idx_l0_default_active_minus1 = r.read_ue_max(14)?;
3441        pps.num_ref_idx_l1_default_active_minus1 = r.read_ue_max(14)?;
3442
3443        // (7-5)
3444        let qp_bd_offset_y = 6 * i32::from(sps.bit_depth_luma_minus8);
3445
3446        pps.init_qp_minus26 = r.read_se_bounded(-(26 + qp_bd_offset_y), 25)?;
3447        pps.qp_bd_offset_y = qp_bd_offset_y as u32;
3448        pps.constrained_intra_pred_flag = r.read_bit()?;
3449        pps.transform_skip_enabled_flag = r.read_bit()?;
3450        pps.cu_qp_delta_enabled_flag = r.read_bit()?;
3451
3452        if pps.cu_qp_delta_enabled_flag {
3453            pps.diff_cu_qp_delta_depth =
3454                r.read_ue_max(u32::from(sps.log2_diff_max_min_luma_coding_block_size))?;
3455        }
3456
3457        pps.cb_qp_offset = r.read_se_bounded(-12, 12)?;
3458        pps.cr_qp_offset = r.read_se_bounded(-12, 12)?;
3459
3460        pps.slice_chroma_qp_offsets_present_flag = r.read_bit()?;
3461        pps.weighted_pred_flag = r.read_bit()?;
3462        pps.weighted_bipred_flag = r.read_bit()?;
3463        pps.transquant_bypass_enabled_flag = r.read_bit()?;
3464        pps.tiles_enabled_flag = r.read_bit()?;
3465        pps.entropy_coding_sync_enabled_flag = r.read_bit()?;
3466
3467        // A mix of the rbsp data and the algorithm in 6.5.1
3468        if pps.tiles_enabled_flag {
3469            pps.num_tile_columns_minus1 = r.read_ue_max(sps.pic_width_in_ctbs_y - 1)?;
3470            pps.num_tile_rows_minus1 = r.read_ue_max(sps.pic_height_in_ctbs_y - 1)?;
3471            pps.uniform_spacing_flag = r.read_bit()?;
3472            if !pps.uniform_spacing_flag {
3473                pps.column_width_minus1[usize::from(pps.num_tile_columns_minus1)] =
3474                    sps.pic_width_in_ctbs_y - 1;
3475
3476                for i in 0..usize::from(pps.num_tile_columns_minus1) {
3477                    pps.column_width_minus1[i] = r.read_ue_max(
3478                        pps.column_width_minus1[usize::from(pps.num_tile_columns_minus1)] - 1,
3479                    )?;
3480                    pps.column_width_minus1[usize::from(pps.num_tile_columns_minus1)] -=
3481                        pps.column_width_minus1[i] + 1;
3482                }
3483
3484                pps.row_height_minus1[usize::from(pps.num_tile_rows_minus1)] =
3485                    sps.pic_height_in_ctbs_y - 1;
3486
3487                for i in 0..usize::from(pps.num_tile_rows_minus1) {
3488                    pps.row_height_minus1[i] = r.read_ue_max(
3489                        pps.row_height_minus1[usize::from(pps.num_tile_rows_minus1)] - 1,
3490                    )?;
3491                    pps.row_height_minus1[usize::from(pps.num_tile_rows_minus1)] -=
3492                        pps.row_height_minus1[i] + 1;
3493                }
3494            } else {
3495                let nrows = u32::from(pps.num_tile_rows_minus1) + 1;
3496                let ncols = u32::from(pps.num_tile_columns_minus1) + 1;
3497
3498                for j in 0..ncols {
3499                    pps.column_width_minus1[j as usize] = ((j + 1) * sps.pic_width_in_ctbs_y)
3500                        / ncols
3501                        - j * sps.pic_width_in_ctbs_y / ncols
3502                        - 1;
3503                }
3504
3505                for j in 0..nrows {
3506                    pps.row_height_minus1[j as usize] = ((j + 1) * sps.pic_height_in_ctbs_y)
3507                        / nrows
3508                        - j * sps.pic_height_in_ctbs_y / nrows
3509                        - 1;
3510                }
3511            }
3512
3513            pps.loop_filter_across_tiles_enabled_flag = r.read_bit()?;
3514        }
3515
3516        pps.loop_filter_across_slices_enabled_flag = r.read_bit()?;
3517        pps.deblocking_filter_control_present_flag = r.read_bit()?;
3518
3519        if pps.deblocking_filter_control_present_flag {
3520            pps.deblocking_filter_override_enabled_flag = r.read_bit()?;
3521            pps.deblocking_filter_disabled_flag = r.read_bit()?;
3522            if !pps.deblocking_filter_disabled_flag {
3523                pps.beta_offset_div2 = r.read_se_bounded(-6, 6)?;
3524                pps.tc_offset_div2 = r.read_se_bounded(-6, 6)?;
3525            }
3526        }
3527
3528        pps.scaling_list_data_present_flag = r.read_bit()?;
3529
3530        if pps.scaling_list_data_present_flag {
3531            Self::parse_scaling_list_data(&mut pps.scaling_list, &mut r)?;
3532        } else {
3533            for size_id in 0..4 {
3534                let mut matrix_id = 0;
3535                while matrix_id < 6 {
3536                    Self::fill_default_scaling_list(&mut pps.scaling_list, size_id, matrix_id);
3537                    let step = if size_id == 3 { 3 } else { 1 };
3538                    matrix_id += step;
3539                }
3540            }
3541        }
3542
3543        pps.lists_modification_present_flag = r.read_bit()?;
3544        pps.log2_parallel_merge_level_minus2 = r.read_ue_max(sps.ctb_log2_size_y - 2)?;
3545        pps.slice_segment_header_extension_present_flag = r.read_bit()?;
3546
3547        pps.extension_present_flag = r.read_bit()?;
3548        if pps.extension_present_flag {
3549            pps.range_extension_flag = r.read_bit()?;
3550
3551            if pps.range_extension_flag {
3552                Self::parse_pps_range_extension(&mut pps, sps, &mut r)?;
3553            }
3554
3555            let multilayer_extension_flag = r.read_bit()?;
3556            if multilayer_extension_flag {
3557                return Err("Multilayer extension is not supported".into());
3558            }
3559
3560            let three_d_extension_flag = r.read_bit()?;
3561            if three_d_extension_flag {
3562                return Err("3D extension is not supported".into());
3563            }
3564
3565            pps.scc_extension_flag = r.read_bit()?;
3566            if pps.scc_extension_flag {
3567                Self::parse_pps_scc_extension(&mut pps, sps, &mut r)?;
3568            }
3569
3570            r.skip_bits(4)?; // pps_extension_4bits
3571        }
3572
3573        log::debug!("Parsed PPS({}), NAL size was {}", pps.pic_parameter_set_id, nalu.size);
3574
3575        if self.active_ppses.keys().len() >= MAX_PPS_COUNT {
3576            return Err("Broken Data: number of active PPSs > MAX_PPS_COUNT".into());
3577        }
3578
3579        let key = pps.pic_parameter_set_id;
3580        let pps = Rc::new(pps);
3581        self.active_ppses.remove(&key);
3582        Ok(self.active_ppses.entry(key).or_insert(pps))
3583    }
3584
3585    fn parse_pred_weight_table(
3586        hdr: &mut SliceHeader,
3587        r: &mut BitReader,
3588        sps: &Sps,
3589    ) -> Result<(), String> {
3590        let pwt = &mut hdr.pred_weight_table;
3591
3592        pwt.luma_log2_weight_denom = r.read_ue_max(7)?;
3593        if sps.chroma_array_type != 0 {
3594            pwt.delta_chroma_log2_weight_denom = r.read_se()?;
3595            pwt.chroma_log2_weight_denom = (pwt.luma_log2_weight_denom as i32
3596                + pwt.delta_chroma_log2_weight_denom as i32)
3597                .try_into()
3598                .map_err(|_| {
3599                    String::from("Integer overflow on chroma_log2_weight_denom calculation")
3600                })?;
3601        }
3602
3603        for i in 0..=usize::from(hdr.num_ref_idx_l0_active_minus1) {
3604            pwt.luma_weight_l0_flag[i] = r.read_bit()?;
3605        }
3606
3607        if sps.chroma_array_type != 0 {
3608            for i in 0..=usize::from(hdr.num_ref_idx_l0_active_minus1) {
3609                pwt.chroma_weight_l0_flag[i] = r.read_bit()?;
3610            }
3611        }
3612
3613        for i in 0..=usize::from(hdr.num_ref_idx_l0_active_minus1) {
3614            if pwt.luma_weight_l0_flag[i] {
3615                pwt.delta_luma_weight_l0[i] = r.read_se_bounded(-128, 127)?;
3616                pwt.luma_offset_l0[i] = r.read_se_bounded(-128, 127)?;
3617            }
3618
3619            if pwt.chroma_weight_l0_flag[i] {
3620                for j in 0..2 {
3621                    pwt.delta_chroma_weight_l0[i][j] = r.read_se_bounded(-128, 127)?;
3622                    pwt.delta_chroma_offset_l0[i][j] = r.read_se_bounded(
3623                        -4 * sps.wp_offset_half_range_c as i32,
3624                        4 * sps.wp_offset_half_range_c as i32 - 1,
3625                    )?;
3626                }
3627            }
3628        }
3629
3630        if hdr.type_.is_b() {
3631            for i in 0..=usize::from(hdr.num_ref_idx_l1_active_minus1) {
3632                pwt.luma_weight_l1_flag[i] = r.read_bit()?;
3633            }
3634
3635            if sps.chroma_format_idc != 0 {
3636                for i in 0..=usize::from(hdr.num_ref_idx_l1_active_minus1) {
3637                    pwt.chroma_weight_l1_flag[i] = r.read_bit()?;
3638                }
3639            }
3640
3641            for i in 0..=usize::from(hdr.num_ref_idx_l1_active_minus1) {
3642                if pwt.luma_weight_l1_flag[i] {
3643                    pwt.delta_luma_weight_l1[i] = r.read_se_bounded(-128, 127)?;
3644                    pwt.luma_offset_l1[i] = r.read_se_bounded(-128, 127)?;
3645                }
3646
3647                if pwt.chroma_weight_l1_flag[i] {
3648                    for j in 0..2 {
3649                        pwt.delta_chroma_weight_l1[i][j] = r.read_se_bounded(-128, 127)?;
3650                        pwt.delta_chroma_offset_l1[i][j] = r.read_se_bounded(
3651                            -4 * sps.wp_offset_half_range_c as i32,
3652                            4 * sps.wp_offset_half_range_c as i32 - 1,
3653                        )?;
3654                    }
3655                }
3656            }
3657        }
3658
3659        Ok(())
3660    }
3661
3662    fn parse_ref_pic_lists_modification(
3663        hdr: &mut SliceHeader,
3664        r: &mut BitReader,
3665    ) -> Result<(), String> {
3666        let rplm = &mut hdr.ref_pic_list_modification;
3667
3668        rplm.ref_pic_list_modification_flag_l0 = r.read_bit()?;
3669        if rplm.ref_pic_list_modification_flag_l0 {
3670            for _ in 0..=hdr.num_ref_idx_l0_active_minus1 {
3671                let num_bits = (hdr.num_pic_total_curr as f64).log2().ceil() as _;
3672
3673                let entry = r.read_bits(num_bits)?;
3674
3675                if entry > hdr.num_pic_total_curr - 1 {
3676                    return Err(format!(
3677                        "Invalid list_entry_l0 {}, expected at max NumPicTotalCurr - 1: {}",
3678                        entry,
3679                        hdr.num_pic_total_curr - 1
3680                    ));
3681                }
3682
3683                rplm.list_entry_l0.push(entry);
3684            }
3685        }
3686
3687        if hdr.type_.is_b() {
3688            rplm.ref_pic_list_modification_flag_l1 = r.read_bit()?;
3689            if rplm.ref_pic_list_modification_flag_l1 {
3690                for _ in 0..=hdr.num_ref_idx_l1_active_minus1 {
3691                    let num_bits = (hdr.num_pic_total_curr as f64).log2().ceil() as _;
3692
3693                    let entry = r.read_bits(num_bits)?;
3694
3695                    if entry > hdr.num_pic_total_curr - 1 {
3696                        return Err(format!(
3697                            "Invalid list_entry_l1 {}, expected at max NumPicTotalCurr - 1: {}",
3698                            entry,
3699                            hdr.num_pic_total_curr - 1
3700                        ));
3701                    }
3702
3703                    rplm.list_entry_l1.push(entry);
3704                }
3705            }
3706        }
3707
3708        Ok(())
3709    }
3710
3711    /// Further sets default values given `sps` and `pps`.
3712    pub fn slice_header_set_defaults(hdr: &mut SliceHeader, sps: &Sps, pps: &Pps) {
3713        // Set some defaults that can't be defined in Default::default().
3714        hdr.deblocking_filter_disabled_flag = pps.deblocking_filter_disabled_flag;
3715        hdr.beta_offset_div2 = pps.beta_offset_div2;
3716        hdr.tc_offset_div2 = pps.tc_offset_div2;
3717        hdr.loop_filter_across_slices_enabled_flag = pps.loop_filter_across_slices_enabled_flag;
3718        hdr.curr_rps_idx = sps.num_short_term_ref_pic_sets;
3719        hdr.use_integer_mv_flag = sps.scc_extension.motion_vector_resolution_control_idc != 0;
3720    }
3721
3722    /// Parses a slice header from a slice NALU.
3723    pub fn parse_slice_header<'a>(&mut self, nalu: Nalu<'a>) -> Result<Slice<'a>, String> {
3724        if !matches!(
3725            nalu.header.type_,
3726            NaluType::TrailN
3727                | NaluType::TrailR
3728                | NaluType::TsaN
3729                | NaluType::TsaR
3730                | NaluType::StsaN
3731                | NaluType::StsaR
3732                | NaluType::RadlN
3733                | NaluType::RadlR
3734                | NaluType::RaslN
3735                | NaluType::RaslR
3736                | NaluType::BlaWLp
3737                | NaluType::BlaWRadl
3738                | NaluType::BlaNLp
3739                | NaluType::IdrWRadl
3740                | NaluType::IdrNLp
3741                | NaluType::CraNut,
3742        ) {
3743            return Err(format!("Invalid NALU type: {:?} is not a slice NALU", nalu.header.type_));
3744        }
3745
3746        let data = nalu.as_ref();
3747        let nalu_header = &nalu.header;
3748        let hdr_len = nalu_header.len();
3749        // Skip the header
3750        let mut r = BitReader::new(&data[hdr_len..], true);
3751
3752        let mut hdr =
3753            SliceHeader { first_slice_segment_in_pic_flag: r.read_bit()?, ..Default::default() };
3754
3755        if nalu.header.type_.is_irap() {
3756            hdr.no_output_of_prior_pics_flag = r.read_bit()?;
3757        }
3758
3759        hdr.pic_parameter_set_id = r.read_ue_max(63)?;
3760
3761        let pps = self.get_pps(hdr.pic_parameter_set_id).ok_or::<String>(format!(
3762            "Could not get PPS for pic_parameter_set_id {}",
3763            hdr.pic_parameter_set_id
3764        ))?;
3765
3766        let sps = &pps.sps;
3767
3768        Self::slice_header_set_defaults(&mut hdr, sps, pps);
3769
3770        if !hdr.first_slice_segment_in_pic_flag {
3771            if pps.dependent_slice_segments_enabled_flag {
3772                hdr.dependent_slice_segment_flag = r.read_bit()?;
3773            }
3774
3775            let num_bits = (sps.pic_size_in_ctbs_y as f64).log2().ceil() as _;
3776            hdr.segment_address = r.read_bits(num_bits)?;
3777
3778            if hdr.segment_address > sps.pic_size_in_ctbs_y - 1 {
3779                return Err(format!("Invalid slice_segment_address {}", hdr.segment_address));
3780            }
3781        }
3782
3783        if !hdr.dependent_slice_segment_flag {
3784            r.skip_bits(usize::from(pps.num_extra_slice_header_bits))?;
3785
3786            let slice_type: u32 = r.read_ue()?;
3787            hdr.type_ = SliceType::try_from(slice_type)?;
3788
3789            if pps.output_flag_present_flag {
3790                hdr.pic_output_flag = r.read_bit()?;
3791            }
3792
3793            if sps.separate_colour_plane_flag {
3794                hdr.colour_plane_id = r.read_bits(2)?;
3795            }
3796
3797            if !matches!(nalu_header.type_, NaluType::IdrWRadl | NaluType::IdrNLp) {
3798                let num_bits = usize::from(sps.log2_max_pic_order_cnt_lsb_minus4 + 4);
3799                hdr.pic_order_cnt_lsb = r.read_bits(num_bits)?;
3800
3801                if u32::from(hdr.pic_order_cnt_lsb)
3802                    > 2u32.pow(u32::from(sps.log2_max_pic_order_cnt_lsb_minus4 + 4))
3803                {
3804                    return Err(format!("Invalid pic_order_cnt_lsb {}", hdr.pic_order_cnt_lsb));
3805                }
3806
3807                hdr.short_term_ref_pic_set_sps_flag = r.read_bit()?;
3808
3809                if !hdr.short_term_ref_pic_set_sps_flag {
3810                    let epb_before = r.num_epb();
3811                    let bits_left_before = r.num_bits_left();
3812
3813                    let st_rps_idx = sps.num_short_term_ref_pic_sets;
3814
3815                    Self::parse_short_term_ref_pic_set(
3816                        sps,
3817                        &mut hdr.short_term_ref_pic_set,
3818                        &mut r,
3819                        st_rps_idx,
3820                    )?;
3821
3822                    hdr.st_rps_bits = ((bits_left_before - r.num_bits_left())
3823                        - 8 * (r.num_epb() - epb_before))
3824                        as u32;
3825                } else if sps.num_short_term_ref_pic_sets > 1 {
3826                    let num_bits = (sps.num_short_term_ref_pic_sets as f64).log2().ceil() as _;
3827                    hdr.short_term_ref_pic_set_idx = r.read_bits(num_bits)?;
3828
3829                    if hdr.short_term_ref_pic_set_idx > sps.num_short_term_ref_pic_sets - 1 {
3830                        return Err(format!(
3831                            "Invalid short_term_ref_pic_set_idx {}",
3832                            hdr.short_term_ref_pic_set_idx
3833                        ));
3834                    }
3835                }
3836
3837                if hdr.short_term_ref_pic_set_sps_flag {
3838                    hdr.curr_rps_idx = hdr.short_term_ref_pic_set_idx;
3839                }
3840
3841                if sps.long_term_ref_pics_present_flag {
3842                    if sps.num_long_term_ref_pics_sps > 0 {
3843                        hdr.num_long_term_sps =
3844                            r.read_ue_max(u32::from(sps.num_long_term_ref_pics_sps))?;
3845                    }
3846
3847                    hdr.num_long_term_pics = r.read_ue_max(
3848                        MAX_LONG_TERM_REF_PIC_SETS as u32 - u32::from(hdr.num_long_term_sps),
3849                    )?;
3850
3851                    let num_lt = hdr.num_long_term_sps + hdr.num_long_term_pics;
3852                    for i in 0..usize::from(num_lt) {
3853                        // The variables `PocLsbLt[ i ]` and `UsedByCurrPicLt[ i ]` are derived as follows:
3854                        //
3855                        // – If i is less than num_long_term_sps, `PocLsbLt[ i ]` is set equal to
3856                        // lt_ref_pic_poc_lsb_sps[ `lt_idx_sps[ i ]` ] and `UsedByCurrPicLt[ i ]` is set equal
3857                        // to used_by_curr_pic_lt_sps_flag[ `lt_idx_sps[ i ]` ].
3858                        //
3859                        // – Otherwise, `PocLsbLt[ i ]`
3860                        // is set equal to `poc_lsb_lt[ i ]` and `UsedByCurrPicLt[ i ]` is set equal to
3861                        // `used_by_curr_pic_lt_flag[ i ]`.
3862                        if i < usize::from(hdr.num_long_term_sps) {
3863                            if sps.num_long_term_ref_pics_sps > 1 {
3864                                let num_bits =
3865                                    (sps.num_long_term_ref_pics_sps as f64).log2().ceil() as _;
3866
3867                                hdr.lt_idx_sps[i] = r.read_bits(num_bits)?;
3868
3869                                if hdr.lt_idx_sps[i] > sps.num_long_term_ref_pics_sps - 1 {
3870                                    return Err(format!(
3871                                        "Invalid lt_idx_sps[{}] {}",
3872                                        i, hdr.lt_idx_sps[i]
3873                                    ));
3874                                }
3875                            }
3876
3877                            hdr.poc_lsb_lt[i] =
3878                                sps.lt_ref_pic_poc_lsb_sps[usize::from(hdr.lt_idx_sps[i])];
3879                            hdr.used_by_curr_pic_lt[i] =
3880                                sps.used_by_curr_pic_lt_sps_flag[usize::from(hdr.lt_idx_sps[i])];
3881                        } else {
3882                            let num_bits = usize::from(sps.log2_max_pic_order_cnt_lsb_minus4) + 4;
3883                            hdr.poc_lsb_lt[i] = r.read_bits(num_bits)?;
3884                            hdr.used_by_curr_pic_lt[i] = r.read_bit()?;
3885                        }
3886
3887                        hdr.delta_poc_msb_present_flag[i] = r.read_bit()?;
3888                        if hdr.delta_poc_msb_present_flag[i] {
3889                            // The value of `delta_poc_msb_cycle_lt[ i ]` shall be
3890                            // in the range of 0 to 2(32 −
3891                            // log2_max_pic_order_cnt_lsb_minus4 − 4 ),
3892                            // inclusive. When `delta_poc_msb_cycle_lt[ i ]` is
3893                            // not present, it is inferred to be equal to 0.
3894                            let max =
3895                                2u32.pow(32 - u32::from(sps.log2_max_pic_order_cnt_lsb_minus4) - 4);
3896                            hdr.delta_poc_msb_cycle_lt[i] = r.read_ue_max(max)?;
3897                        }
3898                        // Equation 7-52 (simplified)
3899                        if i != 0 && i != usize::from(hdr.num_long_term_sps) {
3900                            hdr.delta_poc_msb_cycle_lt[i] += hdr.delta_poc_msb_cycle_lt[i - 1];
3901                        }
3902                    }
3903                }
3904
3905                if sps.temporal_mvp_enabled_flag {
3906                    hdr.temporal_mvp_enabled_flag = r.read_bit()?;
3907                }
3908            }
3909
3910            if sps.sample_adaptive_offset_enabled_flag {
3911                hdr.sao_luma_flag = r.read_bit()?;
3912                if sps.chroma_array_type != 0 {
3913                    hdr.sao_chroma_flag = r.read_bit()?;
3914                }
3915            }
3916
3917            if hdr.type_.is_p() || hdr.type_.is_b() {
3918                hdr.num_ref_idx_active_override_flag = r.read_bit()?;
3919                if hdr.num_ref_idx_active_override_flag {
3920                    hdr.num_ref_idx_l0_active_minus1 = r.read_ue_max(MAX_REF_IDX_ACTIVE - 1)?;
3921                    if hdr.type_.is_b() {
3922                        hdr.num_ref_idx_l1_active_minus1 = r.read_ue_max(MAX_REF_IDX_ACTIVE - 1)?;
3923                    }
3924                } else {
3925                    hdr.num_ref_idx_l0_active_minus1 = pps.num_ref_idx_l0_default_active_minus1;
3926                    hdr.num_ref_idx_l1_active_minus1 = pps.num_ref_idx_l1_default_active_minus1;
3927                }
3928
3929                // 7-57
3930                let mut num_pic_total_curr = 0;
3931                let rps = if hdr.short_term_ref_pic_set_sps_flag {
3932                    sps.short_term_ref_pic_set
3933                        .get(usize::from(hdr.curr_rps_idx))
3934                        .ok_or::<String>("Invalid RPS".into())?
3935                } else {
3936                    &hdr.short_term_ref_pic_set
3937                };
3938
3939                for i in 0..usize::from(rps.num_negative_pics) {
3940                    if rps.used_by_curr_pic_s0[i] {
3941                        num_pic_total_curr += 1;
3942                    }
3943                }
3944
3945                for i in 0..usize::from(rps.num_positive_pics) {
3946                    if rps.used_by_curr_pic_s1[i] {
3947                        num_pic_total_curr += 1;
3948                    }
3949                }
3950
3951                for i in 0..usize::from(hdr.num_long_term_sps + hdr.num_long_term_pics) {
3952                    if hdr.used_by_curr_pic_lt[i] {
3953                        num_pic_total_curr += 1;
3954                    }
3955                }
3956
3957                if pps.scc_extension.curr_pic_ref_enabled_flag {
3958                    num_pic_total_curr += 1;
3959                }
3960
3961                hdr.num_pic_total_curr = num_pic_total_curr;
3962
3963                if pps.lists_modification_present_flag && hdr.num_pic_total_curr > 1 {
3964                    Self::parse_ref_pic_lists_modification(&mut hdr, &mut r)?;
3965                }
3966
3967                if hdr.type_.is_b() {
3968                    hdr.mvd_l1_zero_flag = r.read_bit()?;
3969                }
3970
3971                if pps.cabac_init_present_flag {
3972                    hdr.cabac_init_flag = r.read_bit()?;
3973                }
3974
3975                if hdr.temporal_mvp_enabled_flag {
3976                    if hdr.type_.is_b() {
3977                        hdr.collocated_from_l0_flag = r.read_bit()?;
3978                    }
3979
3980                    if (hdr.collocated_from_l0_flag && hdr.num_ref_idx_l0_active_minus1 > 0)
3981                        || (!hdr.collocated_from_l0_flag && hdr.num_ref_idx_l1_active_minus1 > 0)
3982                    {
3983                        let max = if (hdr.type_.is_p() || hdr.type_.is_b())
3984                            && hdr.collocated_from_l0_flag
3985                        {
3986                            hdr.num_ref_idx_l0_active_minus1
3987                        } else if hdr.type_.is_b() && !hdr.collocated_from_l0_flag {
3988                            hdr.num_ref_idx_l1_active_minus1
3989                        } else {
3990                            return Err("Invalid value for collocated_ref_idx".into());
3991                        };
3992
3993                        {
3994                            hdr.collocated_ref_idx = r.read_ue_max(u32::from(max))?;
3995                        }
3996                    }
3997                }
3998
3999                if (pps.weighted_pred_flag && hdr.type_.is_p())
4000                    || (pps.weighted_bipred_flag && hdr.type_.is_b())
4001                {
4002                    Self::parse_pred_weight_table(&mut hdr, &mut r, sps)?;
4003                }
4004
4005                hdr.five_minus_max_num_merge_cand = r.read_ue()?;
4006
4007                if sps.scc_extension.motion_vector_resolution_control_idc == 2 {
4008                    hdr.use_integer_mv_flag = r.read_bit()?;
4009                }
4010            }
4011
4012            hdr.qp_delta = r.read_se_bounded(-87, 77)?;
4013
4014            let slice_qp_y = (26 + pps.init_qp_minus26 + hdr.qp_delta) as i32;
4015            if slice_qp_y < -(pps.qp_bd_offset_y as i32) || slice_qp_y > 51 {
4016                return Err(format!("Invalid slice_qp_delta: {}", hdr.qp_delta));
4017            }
4018
4019            if pps.slice_chroma_qp_offsets_present_flag {
4020                hdr.cb_qp_offset = r.read_se_bounded(-12, 12)?;
4021
4022                let qp_offset = pps.cb_qp_offset + hdr.cb_qp_offset;
4023                if !(-12..=12).contains(&qp_offset) {
4024                    return Err(format!(
4025                        "Invalid value for slice_cb_qp_offset: {}",
4026                        hdr.cb_qp_offset
4027                    ));
4028                }
4029
4030                hdr.cr_qp_offset = r.read_se_bounded(-12, 12)?;
4031
4032                let qp_offset = pps.cr_qp_offset + hdr.cr_qp_offset;
4033                if !(-12..=12).contains(&qp_offset) {
4034                    return Err(format!(
4035                        "Invalid value for slice_cr_qp_offset: {}",
4036                        hdr.cr_qp_offset
4037                    ));
4038                }
4039            }
4040
4041            if pps.scc_extension.slice_act_qp_offsets_present_flag {
4042                hdr.slice_act_y_qp_offset = r.read_se_bounded(-12, 12)?;
4043                hdr.slice_act_cb_qp_offset = r.read_se_bounded(-12, 12)?;
4044                hdr.slice_act_cr_qp_offset = r.read_se_bounded(-12, 12)?;
4045            }
4046
4047            if pps.range_extension.chroma_qp_offset_list_enabled_flag {
4048                hdr.cu_chroma_qp_offset_enabled_flag = r.read_bit()?;
4049            }
4050
4051            if pps.deblocking_filter_override_enabled_flag {
4052                hdr.deblocking_filter_override_flag = r.read_bit()?;
4053            }
4054
4055            if hdr.deblocking_filter_override_flag {
4056                hdr.deblocking_filter_disabled_flag = r.read_bit()?;
4057                if !hdr.deblocking_filter_disabled_flag {
4058                    hdr.beta_offset_div2 = r.read_se_bounded(-6, 6)?;
4059                    hdr.tc_offset_div2 = r.read_se_bounded(-6, 6)?;
4060                }
4061            }
4062
4063            if pps.loop_filter_across_slices_enabled_flag
4064                && (hdr.sao_luma_flag
4065                    || hdr.sao_chroma_flag
4066                    || !hdr.deblocking_filter_disabled_flag)
4067            {
4068                hdr.loop_filter_across_slices_enabled_flag = r.read_bit()?;
4069            }
4070        }
4071
4072        if pps.tiles_enabled_flag || pps.entropy_coding_sync_enabled_flag {
4073            let max = if !pps.tiles_enabled_flag && pps.entropy_coding_sync_enabled_flag {
4074                sps.pic_height_in_ctbs_y - 1
4075            } else if pps.tiles_enabled_flag && !pps.entropy_coding_sync_enabled_flag {
4076                u32::from((pps.num_tile_columns_minus1 + 1) * (pps.num_tile_rows_minus1 + 1) - 1)
4077            } else {
4078                (u32::from(pps.num_tile_columns_minus1) + 1) * sps.pic_height_in_ctbs_y - 1
4079            };
4080
4081            hdr.num_entry_point_offsets = r.read_ue_max(max)?;
4082            if hdr.num_entry_point_offsets > 0 {
4083                hdr.offset_len_minus1 = r.read_ue_max(31)?;
4084                for i in 0..hdr.num_entry_point_offsets as usize {
4085                    let num_bits = usize::from(hdr.offset_len_minus1 + 1);
4086                    hdr.entry_point_offset_minus1[i] = r.read_bits(num_bits)?;
4087                }
4088            }
4089        }
4090
4091        if pps.slice_segment_header_extension_present_flag {
4092            let segment_header_extension_length = r.read_ue_max(256)?;
4093            for _ in 0..segment_header_extension_length {
4094                r.skip_bits(8)?; // slice_segment_header_extension_data_byte[i]
4095            }
4096        }
4097
4098        // byte_alignment()
4099        r.skip_bits(1)?; // Alignment bit
4100        let num_bits = r.num_bits_left() % 8;
4101        r.skip_bits(num_bits)?;
4102
4103        let epb = r.num_epb();
4104        hdr.header_bit_size = ((nalu.size - epb) * 8 - r.num_bits_left()) as u32;
4105
4106        hdr.n_emulation_prevention_bytes = epb as u32;
4107
4108        log::debug!("Parsed slice {:?}, NAL size was {}", nalu_header.type_, nalu.size);
4109
4110        Ok(Slice { header: hdr, nalu })
4111    }
4112
4113    /// Returns a previously parsed vps given `vps_id`, if any.
4114    pub fn get_vps(&self, vps_id: u8) -> Option<&Rc<Vps>> {
4115        self.active_vpses.get(&vps_id)
4116    }
4117
4118    /// Returns a previously parsed sps given `sps_id`, if any.
4119    pub fn get_sps(&self, sps_id: u8) -> Option<&Rc<Sps>> {
4120        self.active_spses.get(&sps_id)
4121    }
4122
4123    /// Returns a previously parsed pps given `pps_id`, if any.
4124    pub fn get_pps(&self, pps_id: u8) -> Option<&Rc<Pps>> {
4125        self.active_ppses.get(&pps_id)
4126    }
4127}
4128
4129#[cfg(test)]
4130mod tests {
4131    use std::io::Cursor;
4132
4133    use crate::codec::h264::nalu::Nalu;
4134    use crate::codec::h265::parser::Level;
4135    use crate::codec::h265::parser::NaluHeader;
4136    use crate::codec::h265::parser::NaluType;
4137    use crate::codec::h265::parser::Parser;
4138    use crate::codec::h265::parser::SliceType;
4139
4140    const STREAM_BEAR: &[u8] = include_bytes!("test_data/bear.h265");
4141    const STREAM_BEAR_NUM_NALUS: usize = 35;
4142
4143    const STREAM_BBB: &[u8] = include_bytes!("test_data/bbb.h265");
4144    const STREAM_BBB_NUM_NALUS: usize = 64;
4145
4146    const STREAM_TEST25FPS: &[u8] = include_bytes!("test_data/test-25fps.h265");
4147    const STREAM_TEST25FPS_NUM_NALUS: usize = 254;
4148
4149    const STREAM_TEST_25_FPS_SLICE_0: &[u8] =
4150        include_bytes!("test_data/test-25fps-h265-slice-data-0.bin");
4151    const STREAM_TEST_25_FPS_SLICE_1: &[u8] =
4152        include_bytes!("test_data/test-25fps-h265-slice-data-1.bin");
4153
4154    fn dispatch_parse_call(parser: &mut Parser, nalu: Nalu<NaluHeader>) -> Result<(), String> {
4155        match nalu.header.type_ {
4156            NaluType::TrailN
4157            | NaluType::TrailR
4158            | NaluType::TsaN
4159            | NaluType::TsaR
4160            | NaluType::StsaN
4161            | NaluType::StsaR
4162            | NaluType::RadlN
4163            | NaluType::RadlR
4164            | NaluType::RaslN
4165            | NaluType::RaslR
4166            | NaluType::BlaWLp
4167            | NaluType::BlaWRadl
4168            | NaluType::BlaNLp
4169            | NaluType::IdrWRadl
4170            | NaluType::IdrNLp
4171            | NaluType::CraNut => {
4172                parser.parse_slice_header(nalu).unwrap();
4173            }
4174            NaluType::VpsNut => {
4175                parser.parse_vps(&nalu).unwrap();
4176            }
4177            NaluType::SpsNut => {
4178                parser.parse_sps(&nalu).unwrap();
4179            }
4180            NaluType::PpsNut => {
4181                parser.parse_pps(&nalu).unwrap();
4182            }
4183            _ => { /* ignore */ }
4184        }
4185        Ok(())
4186    }
4187
4188    fn find_nalu_by_type(
4189        bitstream: &[u8],
4190        nalu_type: NaluType,
4191        mut nskip: i32,
4192    ) -> Option<Nalu<NaluHeader>> {
4193        let mut cursor = Cursor::new(bitstream);
4194        while let Ok(nalu) = Nalu::<NaluHeader>::next(&mut cursor) {
4195            if nalu.header.type_ == nalu_type {
4196                if nskip == 0 {
4197                    return Some(nalu);
4198                } else {
4199                    nskip -= 1;
4200                }
4201            }
4202        }
4203
4204        None
4205    }
4206
4207    /// This test is adapted from chromium, available at media/video/h265_parser_unittest.cc
4208    #[test]
4209    fn parse_nalus_from_stream_file() {
4210        let mut cursor = Cursor::new(STREAM_BEAR);
4211        let mut num_nalus = 0;
4212        while Nalu::<NaluHeader>::next(&mut cursor).is_ok() {
4213            num_nalus += 1;
4214        }
4215
4216        assert_eq!(num_nalus, STREAM_BEAR_NUM_NALUS);
4217
4218        let mut cursor = Cursor::new(STREAM_BBB);
4219        let mut num_nalus = 0;
4220        while Nalu::<NaluHeader>::next(&mut cursor).is_ok() {
4221            num_nalus += 1;
4222        }
4223
4224        assert_eq!(num_nalus, STREAM_BBB_NUM_NALUS);
4225
4226        let mut cursor = Cursor::new(STREAM_TEST25FPS);
4227        let mut num_nalus = 0;
4228        while Nalu::<NaluHeader>::next(&mut cursor).is_ok() {
4229            num_nalus += 1;
4230        }
4231
4232        assert_eq!(num_nalus, STREAM_TEST25FPS_NUM_NALUS);
4233    }
4234
4235    /// Parse the syntax, making sure we can parse the files without crashing.
4236    /// Does not check whether the parsed values are correct.
4237    #[test]
4238    fn parse_syntax_from_nals() {
4239        let mut cursor = Cursor::new(STREAM_BBB);
4240        let mut parser = Parser::default();
4241
4242        while let Ok(nalu) = Nalu::<NaluHeader>::next(&mut cursor) {
4243            dispatch_parse_call(&mut parser, nalu).unwrap();
4244        }
4245
4246        let mut cursor = Cursor::new(STREAM_BEAR);
4247        let mut parser = Parser::default();
4248
4249        while let Ok(nalu) = Nalu::<NaluHeader>::next(&mut cursor) {
4250            dispatch_parse_call(&mut parser, nalu).unwrap();
4251        }
4252
4253        let mut cursor = Cursor::new(STREAM_TEST25FPS);
4254        let mut parser = Parser::default();
4255
4256        while let Ok(nalu) = Nalu::<NaluHeader>::next(&mut cursor) {
4257            dispatch_parse_call(&mut parser, nalu).unwrap();
4258        }
4259    }
4260
4261    /// Adapted from Chromium (media/video/h265_parser_unittest.cc::VpsParsing())
4262    #[test]
4263    fn chromium_vps_parsing() {
4264        let mut cursor = Cursor::new(STREAM_BEAR);
4265        let mut parser = Parser::default();
4266
4267        let vps_nalu = Nalu::<NaluHeader>::next(&mut cursor).unwrap();
4268        let vps = parser.parse_vps(&vps_nalu).unwrap();
4269
4270        assert!(vps.base_layer_internal_flag);
4271        assert!(vps.base_layer_available_flag);
4272        assert_eq!(vps.max_layers_minus1, 0);
4273        assert_eq!(vps.max_sub_layers_minus1, 0);
4274        assert!(vps.temporal_id_nesting_flag);
4275        assert_eq!(vps.profile_tier_level.general_profile_idc, 1);
4276        assert_eq!(vps.profile_tier_level.general_level_idc, Level::L2);
4277        assert_eq!(vps.max_dec_pic_buffering_minus1[0], 4);
4278        assert_eq!(vps.max_num_reorder_pics[0], 2);
4279        assert_eq!(vps.max_latency_increase_plus1[0], 0);
4280        for i in 1..7 {
4281            assert_eq!(vps.max_dec_pic_buffering_minus1[i], 0);
4282            assert_eq!(vps.max_num_reorder_pics[i], 0);
4283            assert_eq!(vps.max_latency_increase_plus1[i], 0);
4284        }
4285        assert_eq!(vps.max_layer_id, 0);
4286        assert_eq!(vps.num_layer_sets_minus1, 0);
4287        assert!(!vps.timing_info_present_flag);
4288    }
4289
4290    /// Adapted from Chromium (media/video/h265_parser_unittest.cc::SpsParsing())
4291    #[test]
4292    fn chromium_sps_parsing() {
4293        let mut parser = Parser::default();
4294        let sps_nalu = find_nalu_by_type(STREAM_BEAR, NaluType::SpsNut, 0).unwrap();
4295        let sps = parser.parse_sps(&sps_nalu).unwrap();
4296
4297        assert_eq!(sps.max_sub_layers_minus1, 0);
4298        assert_eq!(sps.profile_tier_level.general_profile_idc, 1);
4299        assert_eq!(sps.profile_tier_level.general_level_idc, Level::L2);
4300        assert_eq!(sps.seq_parameter_set_id, 0);
4301        assert_eq!(sps.chroma_format_idc, 1);
4302        assert!(!sps.separate_colour_plane_flag);
4303        assert_eq!(sps.pic_width_in_luma_samples, 320);
4304        assert_eq!(sps.pic_height_in_luma_samples, 184);
4305        assert_eq!(sps.conf_win_left_offset, 0);
4306        assert_eq!(sps.conf_win_right_offset, 0);
4307        assert_eq!(sps.conf_win_top_offset, 0);
4308        assert_eq!(sps.conf_win_bottom_offset, 2);
4309        assert_eq!(sps.bit_depth_luma_minus8, 0);
4310        assert_eq!(sps.bit_depth_chroma_minus8, 0);
4311        assert_eq!(sps.log2_max_pic_order_cnt_lsb_minus4, 4);
4312        assert_eq!(sps.max_dec_pic_buffering_minus1[0], 4);
4313        assert_eq!(sps.max_num_reorder_pics[0], 2);
4314        assert_eq!(sps.max_latency_increase_plus1[0], 0);
4315        for i in 1..7 {
4316            assert_eq!(sps.max_dec_pic_buffering_minus1[i], 0);
4317            assert_eq!(sps.max_num_reorder_pics[i], 0);
4318            assert_eq!(sps.max_latency_increase_plus1[i], 0);
4319        }
4320        assert_eq!(sps.log2_min_luma_coding_block_size_minus3, 0);
4321        assert_eq!(sps.log2_diff_max_min_luma_coding_block_size, 3);
4322        assert_eq!(sps.log2_min_luma_transform_block_size_minus2, 0);
4323        assert_eq!(sps.log2_diff_max_min_luma_transform_block_size, 3);
4324        assert_eq!(sps.max_transform_hierarchy_depth_inter, 0);
4325        assert_eq!(sps.max_transform_hierarchy_depth_intra, 0);
4326        assert!(!sps.scaling_list_enabled_flag);
4327        assert!(!sps.scaling_list_data_present_flag);
4328        assert!(!sps.amp_enabled_flag);
4329        assert!(sps.sample_adaptive_offset_enabled_flag);
4330        assert!(!sps.pcm_enabled_flag);
4331        assert_eq!(sps.pcm_sample_bit_depth_luma_minus1, 0);
4332        assert_eq!(sps.pcm_sample_bit_depth_chroma_minus1, 0);
4333        assert_eq!(sps.log2_min_pcm_luma_coding_block_size_minus3, 0);
4334        assert_eq!(sps.log2_diff_max_min_pcm_luma_coding_block_size, 0);
4335        assert!(!sps.pcm_loop_filter_disabled_flag);
4336        assert_eq!(sps.num_short_term_ref_pic_sets, 0);
4337        assert_eq!(sps.num_long_term_ref_pics_sps, 0);
4338        assert!(sps.temporal_mvp_enabled_flag);
4339        assert!(sps.strong_intra_smoothing_enabled_flag);
4340        assert_eq!(sps.vui_parameters.sar_width, 0);
4341        assert_eq!(sps.vui_parameters.sar_height, 0);
4342        assert!(!sps.vui_parameters.video_full_range_flag);
4343        assert!(!sps.vui_parameters.colour_description_present_flag);
4344
4345        // Note: the original test has 0 for the three variables below, but they
4346        // have valid defaults in the spec (i.e.: 2).
4347        assert_eq!(sps.vui_parameters.colour_primaries, 2);
4348        assert_eq!(sps.vui_parameters.transfer_characteristics, 2);
4349        assert_eq!(sps.vui_parameters.matrix_coeffs, 2);
4350
4351        assert_eq!(sps.vui_parameters.def_disp_win_left_offset, 0);
4352        assert_eq!(sps.vui_parameters.def_disp_win_right_offset, 0);
4353        assert_eq!(sps.vui_parameters.def_disp_win_top_offset, 0);
4354        assert_eq!(sps.vui_parameters.def_disp_win_bottom_offset, 0);
4355    }
4356
4357    /// Adapted from Chromium (media/video/h265_parser_unittest.cc::PpsParsing())
4358    #[test]
4359    fn chromium_pps_parsing() {
4360        let mut parser = Parser::default();
4361
4362        // Have to parse the SPS to set up the parser's internal state.
4363        let sps_nalu = find_nalu_by_type(STREAM_BEAR, NaluType::SpsNut, 0).unwrap();
4364        parser.parse_sps(&sps_nalu).unwrap();
4365
4366        let pps_nalu = find_nalu_by_type(STREAM_BEAR, NaluType::PpsNut, 0).unwrap();
4367        let pps = parser.parse_pps(&pps_nalu).unwrap();
4368
4369        assert_eq!(pps.pic_parameter_set_id, 0);
4370        assert_eq!(pps.seq_parameter_set_id, 0);
4371        assert!(!pps.dependent_slice_segments_enabled_flag);
4372        assert!(!pps.output_flag_present_flag);
4373        assert_eq!(pps.num_extra_slice_header_bits, 0);
4374        assert!(pps.sign_data_hiding_enabled_flag);
4375        assert!(!pps.cabac_init_present_flag);
4376        assert_eq!(pps.num_ref_idx_l0_default_active_minus1, 0);
4377        assert_eq!(pps.num_ref_idx_l1_default_active_minus1, 0);
4378        assert_eq!(pps.init_qp_minus26, 0);
4379        assert!(!pps.constrained_intra_pred_flag);
4380        assert!(!pps.transform_skip_enabled_flag);
4381        assert!(pps.cu_qp_delta_enabled_flag);
4382        assert_eq!(pps.diff_cu_qp_delta_depth, 0);
4383        assert_eq!(pps.cb_qp_offset, 0);
4384        assert_eq!(pps.cr_qp_offset, 0);
4385        assert!(!pps.slice_chroma_qp_offsets_present_flag);
4386        assert!(pps.weighted_pred_flag);
4387        assert!(!pps.weighted_bipred_flag);
4388        assert!(!pps.transquant_bypass_enabled_flag);
4389        assert!(!pps.tiles_enabled_flag);
4390        assert!(pps.entropy_coding_sync_enabled_flag);
4391        assert!(pps.loop_filter_across_tiles_enabled_flag);
4392        assert!(!pps.scaling_list_data_present_flag);
4393        assert!(!pps.lists_modification_present_flag);
4394        assert_eq!(pps.log2_parallel_merge_level_minus2, 0);
4395        assert!(!pps.slice_segment_header_extension_present_flag);
4396    }
4397
4398    /// Adapted from Chromium (media/video/h265_parser_unittest.cc::SliceHeaderParsing())
4399    #[test]
4400    fn chromium_slice_header_parsing() {
4401        let mut parser = Parser::default();
4402
4403        // Have to parse the SPS/VPS/PPS to set up the parser's internal state.
4404        let vps_nalu = find_nalu_by_type(STREAM_BEAR, NaluType::VpsNut, 0).unwrap();
4405        parser.parse_vps(&vps_nalu).unwrap();
4406
4407        let sps_nalu = find_nalu_by_type(STREAM_BEAR, NaluType::SpsNut, 0).unwrap();
4408        parser.parse_sps(&sps_nalu).unwrap();
4409
4410        let pps_nalu = find_nalu_by_type(STREAM_BEAR, NaluType::PpsNut, 0).unwrap();
4411        parser.parse_pps(&pps_nalu).unwrap();
4412
4413        // Just like the Chromium test, do an IDR slice, then a non IDR slice.
4414        let slice_nalu = find_nalu_by_type(STREAM_BEAR, NaluType::IdrWRadl, 0).unwrap();
4415        let slice = parser.parse_slice_header(slice_nalu).unwrap();
4416        let hdr = &slice.header;
4417        assert!(hdr.first_slice_segment_in_pic_flag);
4418        assert!(!hdr.no_output_of_prior_pics_flag);
4419        assert_eq!(hdr.pic_parameter_set_id, 0);
4420        assert!(!hdr.dependent_slice_segment_flag);
4421        assert_eq!(hdr.type_, SliceType::I);
4422        assert!(hdr.sao_luma_flag);
4423        assert!(hdr.sao_chroma_flag);
4424        assert_eq!(hdr.qp_delta, 8);
4425        assert!(hdr.loop_filter_across_slices_enabled_flag);
4426
4427        let slice_nalu = find_nalu_by_type(STREAM_BEAR, NaluType::TrailR, 0).unwrap();
4428        let slice = parser.parse_slice_header(slice_nalu).unwrap();
4429        let hdr = &slice.header;
4430        assert!(hdr.first_slice_segment_in_pic_flag);
4431        assert_eq!(hdr.pic_parameter_set_id, 0);
4432        assert!(!hdr.dependent_slice_segment_flag);
4433        assert_eq!(hdr.type_, SliceType::P);
4434        assert_eq!(hdr.pic_order_cnt_lsb, 4);
4435        assert!(!hdr.short_term_ref_pic_set_sps_flag);
4436        assert_eq!(hdr.short_term_ref_pic_set.num_negative_pics, 1);
4437        assert_eq!(hdr.short_term_ref_pic_set.num_positive_pics, 0);
4438        assert_eq!(hdr.short_term_ref_pic_set.delta_poc_s0[0], -4);
4439        assert!(hdr.short_term_ref_pic_set.used_by_curr_pic_s0[0]);
4440        assert!(hdr.temporal_mvp_enabled_flag);
4441        assert!(hdr.sao_luma_flag);
4442        assert!(hdr.sao_chroma_flag);
4443        assert!(!hdr.num_ref_idx_active_override_flag);
4444        assert_eq!(hdr.pred_weight_table.luma_log2_weight_denom, 0);
4445        assert_eq!(hdr.pred_weight_table.delta_chroma_log2_weight_denom, 7);
4446        assert_eq!(hdr.pred_weight_table.delta_luma_weight_l0[0], 0);
4447        assert_eq!(hdr.pred_weight_table.luma_offset_l0[0], -2);
4448        assert_eq!(hdr.pred_weight_table.delta_chroma_weight_l0[0][0], -9);
4449        assert_eq!(hdr.pred_weight_table.delta_chroma_weight_l0[0][1], -9);
4450        assert_eq!(hdr.pred_weight_table.delta_chroma_offset_l0[0][0], 0);
4451        assert_eq!(hdr.pred_weight_table.delta_chroma_offset_l0[0][1], 0);
4452        assert_eq!(hdr.five_minus_max_num_merge_cand, 3);
4453        assert_eq!(hdr.qp_delta, 8);
4454        assert!(hdr.loop_filter_across_slices_enabled_flag);
4455    }
4456
4457    /// A custom test for VPS parsing with data manually extracted from
4458    /// GStreamer using GDB.
4459    #[test]
4460    fn test25fps_vps_header_parsing() {
4461        let mut cursor = Cursor::new(STREAM_TEST25FPS);
4462        let mut parser = Parser::default();
4463
4464        let vps_nalu = Nalu::<NaluHeader>::next(&mut cursor).unwrap();
4465        let vps = parser.parse_vps(&vps_nalu).unwrap();
4466        assert!(vps.base_layer_internal_flag);
4467        assert!(vps.base_layer_available_flag);
4468        assert_eq!(vps.max_layers_minus1, 0);
4469        assert_eq!(vps.max_sub_layers_minus1, 0);
4470        assert!(vps.temporal_id_nesting_flag);
4471        assert_eq!(vps.profile_tier_level.general_profile_space, 0);
4472        assert!(!vps.profile_tier_level.general_tier_flag);
4473        assert_eq!(vps.profile_tier_level.general_profile_idc, 1);
4474        for i in 0..32 {
4475            let val = i == 1 || i == 2;
4476            assert_eq!(vps.profile_tier_level.general_profile_compatibility_flag[i], val);
4477        }
4478        assert!(vps.profile_tier_level.general_progressive_source_flag);
4479        assert!(!vps.profile_tier_level.general_interlaced_source_flag);
4480        assert!(!vps.profile_tier_level.general_non_packed_constraint_flag,);
4481        assert!(vps.profile_tier_level.general_frame_only_constraint_flag,);
4482        assert!(!vps.profile_tier_level.general_max_12bit_constraint_flag,);
4483        assert!(!vps.profile_tier_level.general_max_10bit_constraint_flag,);
4484        assert!(!vps.profile_tier_level.general_max_8bit_constraint_flag,);
4485        assert!(!vps.profile_tier_level.general_max_422chroma_constraint_flag,);
4486        assert!(!vps.profile_tier_level.general_max_420chroma_constraint_flag,);
4487        assert!(!vps.profile_tier_level.general_max_monochrome_constraint_flag,);
4488        assert!(!vps.profile_tier_level.general_intra_constraint_flag);
4489        assert!(!vps.profile_tier_level.general_one_picture_only_constraint_flag,);
4490        assert!(!vps.profile_tier_level.general_lower_bit_rate_constraint_flag,);
4491        assert!(!vps.profile_tier_level.general_max_14bit_constraint_flag,);
4492        assert_eq!(vps.profile_tier_level.general_level_idc, Level::L2);
4493
4494        assert!(vps.sub_layer_ordering_info_present_flag);
4495        assert_eq!(vps.max_dec_pic_buffering_minus1[0], 4);
4496        assert_eq!(vps.max_num_reorder_pics[0], 2);
4497        assert_eq!(vps.max_latency_increase_plus1[0], 5);
4498        for i in 1..7 {
4499            assert_eq!(vps.max_dec_pic_buffering_minus1[i], 0);
4500            assert_eq!(vps.max_num_reorder_pics[i], 0);
4501            assert_eq!(vps.max_latency_increase_plus1[i], 0);
4502        }
4503
4504        assert_eq!(vps.max_layer_id, 0);
4505        assert_eq!(vps.num_layer_sets_minus1, 0);
4506        assert!(!vps.timing_info_present_flag);
4507        assert_eq!(vps.num_units_in_tick, 0);
4508        assert_eq!(vps.time_scale, 0);
4509        assert!(!vps.poc_proportional_to_timing_flag);
4510        assert_eq!(vps.num_ticks_poc_diff_one_minus1, 0);
4511        assert_eq!(vps.num_hrd_parameters, 0);
4512    }
4513
4514    /// A custom test for SPS parsing with data manually extracted from
4515    /// GStreamer using GDB.
4516    #[test]
4517    fn test25fps_sps_header_parsing() {
4518        let mut parser = Parser::default();
4519
4520        let sps_nalu = find_nalu_by_type(STREAM_TEST25FPS, NaluType::SpsNut, 0).unwrap();
4521        let sps = parser.parse_sps(&sps_nalu).unwrap();
4522
4523        assert_eq!(sps.max_sub_layers_minus1, 0);
4524
4525        assert_eq!(sps.profile_tier_level.general_profile_space, 0);
4526        assert!(!sps.profile_tier_level.general_tier_flag);
4527        assert_eq!(sps.profile_tier_level.general_profile_idc, 1);
4528        for i in 0..32 {
4529            let val = i == 1 || i == 2;
4530            assert_eq!(sps.profile_tier_level.general_profile_compatibility_flag[i], val);
4531        }
4532        assert!(sps.profile_tier_level.general_progressive_source_flag);
4533        assert!(!sps.profile_tier_level.general_interlaced_source_flag);
4534        assert!(!sps.profile_tier_level.general_non_packed_constraint_flag,);
4535        assert!(sps.profile_tier_level.general_frame_only_constraint_flag,);
4536        assert!(!sps.profile_tier_level.general_max_12bit_constraint_flag,);
4537        assert!(!sps.profile_tier_level.general_max_10bit_constraint_flag,);
4538        assert!(!sps.profile_tier_level.general_max_8bit_constraint_flag,);
4539        assert!(!sps.profile_tier_level.general_max_422chroma_constraint_flag,);
4540        assert!(!sps.profile_tier_level.general_max_420chroma_constraint_flag,);
4541        assert!(!sps.profile_tier_level.general_max_monochrome_constraint_flag,);
4542        assert!(!sps.profile_tier_level.general_intra_constraint_flag);
4543        assert!(!sps.profile_tier_level.general_one_picture_only_constraint_flag,);
4544        assert!(!sps.profile_tier_level.general_lower_bit_rate_constraint_flag,);
4545        assert!(!sps.profile_tier_level.general_max_14bit_constraint_flag,);
4546        assert_eq!(sps.profile_tier_level.general_level_idc, Level::L2);
4547
4548        assert_eq!(sps.seq_parameter_set_id, 0);
4549        assert_eq!(sps.chroma_format_idc, 1);
4550        assert!(!sps.separate_colour_plane_flag);
4551        assert_eq!(sps.pic_width_in_luma_samples, 320);
4552        assert_eq!(sps.pic_height_in_luma_samples, 240);
4553        assert_eq!(sps.conf_win_left_offset, 0);
4554        assert_eq!(sps.conf_win_right_offset, 0);
4555        assert_eq!(sps.conf_win_top_offset, 0);
4556        assert_eq!(sps.conf_win_bottom_offset, 0);
4557        assert_eq!(sps.bit_depth_luma_minus8, 0);
4558        assert_eq!(sps.bit_depth_chroma_minus8, 0);
4559        assert_eq!(sps.log2_max_pic_order_cnt_lsb_minus4, 4);
4560        assert!(sps.sub_layer_ordering_info_present_flag);
4561        assert_eq!(sps.max_dec_pic_buffering_minus1[0], 4);
4562        assert_eq!(sps.max_num_reorder_pics[0], 2);
4563        assert_eq!(sps.max_latency_increase_plus1[0], 5);
4564        for i in 1..7 {
4565            assert_eq!(sps.max_dec_pic_buffering_minus1[i], 0);
4566            assert_eq!(sps.max_num_reorder_pics[i], 0);
4567            assert_eq!(sps.max_latency_increase_plus1[i], 0);
4568        }
4569        assert_eq!(sps.log2_min_luma_coding_block_size_minus3, 0);
4570        assert_eq!(sps.log2_diff_max_min_luma_coding_block_size, 3);
4571        assert_eq!(sps.log2_min_luma_transform_block_size_minus2, 0);
4572        assert_eq!(sps.log2_diff_max_min_luma_transform_block_size, 3);
4573        assert_eq!(sps.max_transform_hierarchy_depth_inter, 0);
4574        assert_eq!(sps.max_transform_hierarchy_depth_intra, 0);
4575        assert!(!sps.scaling_list_enabled_flag);
4576        assert!(!sps.scaling_list_data_present_flag);
4577        assert!(!sps.amp_enabled_flag);
4578        assert!(sps.sample_adaptive_offset_enabled_flag);
4579        assert!(!sps.pcm_enabled_flag);
4580        assert_eq!(sps.pcm_sample_bit_depth_luma_minus1, 0);
4581        assert_eq!(sps.pcm_sample_bit_depth_chroma_minus1, 0);
4582        assert_eq!(sps.log2_min_pcm_luma_coding_block_size_minus3, 0);
4583        assert_eq!(sps.log2_diff_max_min_pcm_luma_coding_block_size, 0);
4584        assert!(!sps.pcm_loop_filter_disabled_flag);
4585        assert_eq!(sps.num_short_term_ref_pic_sets, 0);
4586        assert_eq!(sps.num_long_term_ref_pics_sps, 0);
4587        assert!(sps.temporal_mvp_enabled_flag);
4588        assert!(sps.strong_intra_smoothing_enabled_flag);
4589        assert_eq!(sps.vui_parameters.sar_width, 0);
4590        assert_eq!(sps.vui_parameters.sar_height, 0);
4591        assert!(!sps.vui_parameters.video_full_range_flag);
4592        assert!(!sps.vui_parameters.colour_description_present_flag);
4593        assert!(sps.vui_parameters.video_signal_type_present_flag);
4594        assert!(sps.vui_parameters.timing_info_present_flag);
4595        assert_eq!(sps.vui_parameters.num_units_in_tick, 1);
4596        assert_eq!(sps.vui_parameters.time_scale, 25);
4597        assert!(!sps.vui_parameters.poc_proportional_to_timing_flag);
4598        assert_eq!(sps.vui_parameters.num_ticks_poc_diff_one_minus1, 0);
4599        assert!(!sps.vui_parameters.hrd_parameters_present_flag);
4600        assert_eq!(sps.vui_parameters.colour_primaries, 2);
4601        assert_eq!(sps.vui_parameters.transfer_characteristics, 2);
4602        assert_eq!(sps.vui_parameters.matrix_coeffs, 2);
4603        assert_eq!(sps.vui_parameters.def_disp_win_left_offset, 0);
4604        assert_eq!(sps.vui_parameters.def_disp_win_right_offset, 0);
4605        assert_eq!(sps.vui_parameters.def_disp_win_top_offset, 0);
4606        assert_eq!(sps.vui_parameters.def_disp_win_bottom_offset, 0);
4607    }
4608
4609    /// A custom test for PPS parsing with data manually extracted from
4610    /// GStreamer using GDB.
4611    #[test]
4612    fn test25fps_pps_header_parsing() {
4613        let mut parser = Parser::default();
4614
4615        let sps_nalu = find_nalu_by_type(STREAM_TEST25FPS, NaluType::SpsNut, 0).unwrap();
4616        parser.parse_sps(&sps_nalu).unwrap();
4617
4618        let pps_nalu = find_nalu_by_type(STREAM_TEST25FPS, NaluType::PpsNut, 0).unwrap();
4619        let pps = parser.parse_pps(&pps_nalu).unwrap();
4620
4621        assert!(!pps.dependent_slice_segments_enabled_flag);
4622        assert!(!pps.output_flag_present_flag);
4623        assert_eq!(pps.num_extra_slice_header_bits, 0);
4624        assert!(pps.sign_data_hiding_enabled_flag);
4625        assert!(!pps.cabac_init_present_flag);
4626        assert_eq!(pps.num_ref_idx_l0_default_active_minus1, 0);
4627        assert_eq!(pps.num_ref_idx_l1_default_active_minus1, 0);
4628        assert_eq!(pps.init_qp_minus26, 0);
4629        assert!(!pps.constrained_intra_pred_flag);
4630        assert!(!pps.transform_skip_enabled_flag);
4631        assert!(pps.cu_qp_delta_enabled_flag);
4632        assert_eq!(pps.diff_cu_qp_delta_depth, 1);
4633        assert_eq!(pps.cb_qp_offset, 0);
4634        assert_eq!(pps.cr_qp_offset, 0);
4635        assert!(!pps.slice_chroma_qp_offsets_present_flag);
4636        assert!(pps.weighted_pred_flag);
4637        assert!(!pps.weighted_bipred_flag);
4638        assert!(!pps.transquant_bypass_enabled_flag);
4639        assert!(!pps.tiles_enabled_flag);
4640        assert!(pps.entropy_coding_sync_enabled_flag);
4641        assert_eq!(pps.num_tile_rows_minus1, 0);
4642        assert_eq!(pps.num_tile_columns_minus1, 0);
4643        assert!(pps.uniform_spacing_flag);
4644        assert_eq!(pps.column_width_minus1, [0; 19]);
4645        assert_eq!(pps.row_height_minus1, [0; 21]);
4646        assert!(pps.loop_filter_across_slices_enabled_flag);
4647        assert!(pps.loop_filter_across_tiles_enabled_flag);
4648        assert!(!pps.deblocking_filter_control_present_flag);
4649        assert!(!pps.deblocking_filter_override_enabled_flag);
4650        assert!(!pps.deblocking_filter_disabled_flag);
4651        assert_eq!(pps.beta_offset_div2, 0);
4652        assert_eq!(pps.tc_offset_div2, 0);
4653        assert!(!pps.lists_modification_present_flag);
4654        assert_eq!(pps.log2_parallel_merge_level_minus2, 0);
4655        assert!(!pps.slice_segment_header_extension_present_flag);
4656        assert!(!pps.extension_present_flag);
4657    }
4658
4659    /// A custom test for slice header parsing with data manually extracted from
4660    /// GStreamer using GDB.
4661    #[test]
4662    fn test25fps_slice_header_parsing() {
4663        let mut parser = Parser::default();
4664
4665        // Have to parse the SPS/VPS/PPS to set up the parser's internal state.
4666        let vps_nalu = find_nalu_by_type(STREAM_TEST25FPS, NaluType::VpsNut, 0).unwrap();
4667        parser.parse_vps(&vps_nalu).unwrap();
4668
4669        let sps_nalu = find_nalu_by_type(STREAM_TEST25FPS, NaluType::SpsNut, 0).unwrap();
4670        parser.parse_sps(&sps_nalu).unwrap();
4671
4672        let pps_nalu = find_nalu_by_type(STREAM_TEST25FPS, NaluType::PpsNut, 0).unwrap();
4673        parser.parse_pps(&pps_nalu).unwrap();
4674
4675        let slice_nalu = find_nalu_by_type(STREAM_TEST25FPS, NaluType::IdrNLp, 0).unwrap();
4676        let slice = parser.parse_slice_header(slice_nalu).unwrap();
4677        let hdr = &slice.header;
4678
4679        assert!(hdr.first_slice_segment_in_pic_flag);
4680        assert!(!hdr.no_output_of_prior_pics_flag);
4681        assert!(!hdr.dependent_slice_segment_flag);
4682        assert_eq!(hdr.type_, SliceType::I);
4683        assert!(hdr.pic_output_flag);
4684        assert_eq!(hdr.colour_plane_id, 0);
4685        assert_eq!(hdr.pic_order_cnt_lsb, 0);
4686        assert!(!hdr.short_term_ref_pic_set_sps_flag);
4687        assert_eq!(hdr.lt_idx_sps, [0; 16]);
4688        assert_eq!(hdr.poc_lsb_lt, [0; 16]);
4689        assert_eq!(hdr.used_by_curr_pic_lt, [false; 16]);
4690        assert_eq!(hdr.delta_poc_msb_cycle_lt, [0; 16]);
4691        assert_eq!(hdr.delta_poc_msb_present_flag, [false; 16]);
4692        assert!(!hdr.temporal_mvp_enabled_flag);
4693        assert!(hdr.sao_luma_flag);
4694        assert!(hdr.sao_chroma_flag);
4695        assert!(!hdr.num_ref_idx_active_override_flag);
4696        assert_eq!(hdr.num_ref_idx_l0_active_minus1, 0);
4697        assert_eq!(hdr.num_ref_idx_l1_active_minus1, 0);
4698        assert!(!hdr.cabac_init_flag);
4699        assert!(hdr.collocated_from_l0_flag);
4700        assert_eq!(hdr.five_minus_max_num_merge_cand, 0);
4701        assert!(!hdr.use_integer_mv_flag);
4702        assert_eq!(hdr.qp_delta, 7);
4703        assert_eq!(hdr.cb_qp_offset, 0);
4704        assert_eq!(hdr.cr_qp_offset, 0);
4705        assert!(!hdr.cu_chroma_qp_offset_enabled_flag);
4706        assert!(!hdr.deblocking_filter_override_flag);
4707        assert!(!hdr.deblocking_filter_override_flag);
4708        assert_eq!(hdr.beta_offset_div2, 0);
4709        assert_eq!(hdr.tc_offset_div2, 0);
4710        assert!(hdr.loop_filter_across_slices_enabled_flag);
4711        assert_eq!(hdr.num_entry_point_offsets, 3);
4712        assert_eq!(hdr.offset_len_minus1, 11);
4713        assert_eq!(hdr.num_pic_total_curr, 0);
4714
4715        // Remove the 2 bytes from the NALU header.
4716        assert_eq!(hdr.header_bit_size - 16, 72);
4717
4718        assert_eq!(hdr.n_emulation_prevention_bytes, 0);
4719
4720        assert_eq!(slice.nalu.as_ref(), STREAM_TEST_25_FPS_SLICE_0);
4721
4722        // Next slice
4723        let slice_nalu = find_nalu_by_type(STREAM_TEST25FPS, NaluType::TrailR, 0).unwrap();
4724        let slice = parser.parse_slice_header(slice_nalu).unwrap();
4725        let hdr = &slice.header;
4726
4727        assert!(hdr.first_slice_segment_in_pic_flag);
4728        assert!(!hdr.no_output_of_prior_pics_flag);
4729        assert!(!hdr.dependent_slice_segment_flag);
4730        assert_eq!(hdr.type_, SliceType::P);
4731        assert!(hdr.pic_output_flag);
4732        assert_eq!(hdr.colour_plane_id, 0);
4733        assert_eq!(hdr.pic_order_cnt_lsb, 3);
4734        assert!(!hdr.short_term_ref_pic_set_sps_flag);
4735        assert_eq!(hdr.short_term_ref_pic_set.num_delta_pocs, 1);
4736        assert_eq!(hdr.short_term_ref_pic_set.num_negative_pics, 1);
4737        assert_eq!(hdr.short_term_ref_pic_set.num_positive_pics, 0);
4738        assert!(hdr.short_term_ref_pic_set.used_by_curr_pic_s0[0]);
4739        assert_eq!(hdr.short_term_ref_pic_set.delta_poc_s0[0], -3);
4740        assert_eq!(hdr.lt_idx_sps, [0; 16]);
4741        assert_eq!(hdr.poc_lsb_lt, [0; 16]);
4742        assert_eq!(hdr.used_by_curr_pic_lt, [false; 16]);
4743        assert_eq!(hdr.delta_poc_msb_cycle_lt, [0; 16]);
4744        assert_eq!(hdr.delta_poc_msb_present_flag, [false; 16]);
4745        assert!(hdr.temporal_mvp_enabled_flag);
4746        assert!(hdr.sao_luma_flag);
4747        assert!(hdr.sao_chroma_flag);
4748        assert!(!hdr.num_ref_idx_active_override_flag);
4749        assert_eq!(hdr.num_ref_idx_l0_active_minus1, 0);
4750        assert_eq!(hdr.num_ref_idx_l1_active_minus1, 0);
4751        assert!(!hdr.cabac_init_flag);
4752        assert!(hdr.collocated_from_l0_flag);
4753        assert_eq!(hdr.pred_weight_table.luma_log2_weight_denom, 7);
4754        assert_eq!(hdr.five_minus_max_num_merge_cand, 2);
4755        assert!(!hdr.use_integer_mv_flag);
4756        assert_eq!(hdr.num_entry_point_offsets, 3);
4757        assert_eq!(hdr.qp_delta, 7);
4758        assert_eq!(hdr.cb_qp_offset, 0);
4759        assert_eq!(hdr.cr_qp_offset, 0);
4760        assert!(!hdr.cu_chroma_qp_offset_enabled_flag);
4761        assert!(!hdr.deblocking_filter_override_flag);
4762        assert!(!hdr.deblocking_filter_override_flag);
4763        assert_eq!(hdr.beta_offset_div2, 0);
4764        assert_eq!(hdr.tc_offset_div2, 0);
4765        assert!(!hdr.loop_filter_across_slices_enabled_flag);
4766        assert_eq!(hdr.num_entry_point_offsets, 3);
4767        assert_eq!(hdr.offset_len_minus1, 10);
4768        assert_eq!(hdr.num_pic_total_curr, 1);
4769
4770        assert_eq!(slice.nalu.size, 2983);
4771        // Subtract 2 bytes to account for the header size.
4772        assert_eq!(hdr.header_bit_size - 16, 96);
4773        assert_eq!(slice.nalu.as_ref(), STREAM_TEST_25_FPS_SLICE_1);
4774
4775        // Next slice
4776        let slice_nalu = find_nalu_by_type(STREAM_TEST25FPS, NaluType::TrailR, 1).unwrap();
4777        let slice = parser.parse_slice_header(slice_nalu).unwrap();
4778        let hdr = &slice.header;
4779
4780        assert_eq!(slice.nalu.size, 290);
4781        // Subtract 2 bytes to account for the header size.
4782        assert_eq!(hdr.header_bit_size - 16, 80);
4783    }
4784}