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