cros_codecs/codec/h264/
parser.rs

1// Copyright 2022 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// Can't reasonably expect client code to consume everything that has been parsed.
6#![allow(dead_code)]
7
8use std::collections::BTreeMap;
9use std::io::Cursor;
10use std::io::Read;
11use std::io::Seek;
12use std::io::SeekFrom;
13use std::rc::Rc;
14
15use crate::bitstream_utils::BitReader;
16use crate::codec::h264::nalu;
17use crate::codec::h264::nalu::Header;
18use crate::codec::h264::picture::Field;
19
20pub type Nalu<'a> = nalu::Nalu<'a, NaluHeader>;
21
22pub(super) const DEFAULT_4X4_INTRA: [u8; 16] =
23    [6, 13, 13, 20, 20, 20, 28, 28, 28, 28, 32, 32, 32, 37, 37, 42];
24
25pub(super) const DEFAULT_4X4_INTER: [u8; 16] =
26    [10, 14, 14, 20, 20, 20, 24, 24, 24, 24, 27, 27, 27, 30, 30, 34];
27
28pub(super) const DEFAULT_8X8_INTRA: [u8; 64] = [
29    6, 10, 10, 13, 11, 13, 16, 16, 16, 16, 18, 18, 18, 18, 18, 23, 23, 23, 23, 23, 23, 25, 25, 25,
30    25, 25, 25, 25, 27, 27, 27, 27, 27, 27, 27, 27, 29, 29, 29, 29, 29, 29, 29, 31, 31, 31, 31, 31,
31    31, 33, 33, 33, 33, 33, 36, 36, 36, 36, 38, 38, 38, 40, 40, 42,
32];
33
34pub(super) const DEFAULT_8X8_INTER: [u8; 64] = [
35    9, 13, 13, 15, 13, 15, 17, 17, 17, 17, 19, 19, 19, 19, 19, 21, 21, 21, 21, 21, 21, 22, 22, 22,
36    22, 22, 22, 22, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 27, 27, 27, 27, 27,
37    27, 28, 28, 28, 28, 28, 30, 30, 30, 30, 32, 32, 32, 33, 33, 35,
38];
39
40const MAX_PPS_COUNT: u16 = 256;
41const MAX_SPS_COUNT: u8 = 32;
42
43/// The maximum number of pictures in the DPB, as per A.3.1, clause h)
44const DPB_MAX_SIZE: usize = 16;
45
46#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
47pub struct Point<T> {
48    pub x: T,
49    pub y: T,
50}
51
52#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
53pub struct Rect<T> {
54    pub min: Point<T>,
55    pub max: Point<T>,
56}
57
58#[derive(Debug, PartialEq, Eq, Clone, Copy)]
59pub enum NaluType {
60    Unknown = 0,
61    Slice = 1,
62    SliceDpa = 2,
63    SliceDpb = 3,
64    SliceDpc = 4,
65    SliceIdr = 5,
66    Sei = 6,
67    Sps = 7,
68    Pps = 8,
69    AuDelimiter = 9,
70    SeqEnd = 10,
71    StreamEnd = 11,
72    FillerData = 12,
73    SpsExt = 13,
74    PrefixUnit = 14,
75    SubsetSps = 15,
76    DepthSps = 16,
77    SliceAux = 19,
78    SliceExt = 20,
79    SliceDepth = 21,
80}
81
82impl TryFrom<u8> for NaluType {
83    type Error = String;
84
85    fn try_from(value: u8) -> Result<Self, Self::Error> {
86        match value {
87            0 => Ok(NaluType::Unknown),
88            1 => Ok(NaluType::Slice),
89            2 => Ok(NaluType::SliceDpa),
90            3 => Ok(NaluType::SliceDpb),
91            4 => Ok(NaluType::SliceDpc),
92            5 => Ok(NaluType::SliceIdr),
93            6 => Ok(NaluType::Sei),
94            7 => Ok(NaluType::Sps),
95            8 => Ok(NaluType::Pps),
96            9 => Ok(NaluType::AuDelimiter),
97            10 => Ok(NaluType::SeqEnd),
98            11 => Ok(NaluType::StreamEnd),
99            12 => Ok(NaluType::FillerData),
100            13 => Ok(NaluType::SpsExt),
101            14 => Ok(NaluType::PrefixUnit),
102            15 => Ok(NaluType::SubsetSps),
103            16 => Ok(NaluType::DepthSps),
104            19 => Ok(NaluType::SliceAux),
105            20 => Ok(NaluType::SliceExt),
106            21 => Ok(NaluType::SliceDepth),
107            _ => Err(format!("Invalid NaluType {}", value)),
108        }
109    }
110}
111
112#[derive(Clone, Debug, Default, PartialEq, Eq)]
113pub struct RefPicListModification {
114    pub modification_of_pic_nums_idc: u8,
115    /* if modification_of_pic_nums_idc == 0 || 1 */
116    pub abs_diff_pic_num_minus1: u32,
117    /* if modification_of_pic_nums_idc == 2 */
118    pub long_term_pic_num: u32,
119    /* if modification_of_pic_nums_idc == 4 || 5 */
120    pub abs_diff_view_idx_minus1: u32,
121}
122
123#[derive(Clone, Debug, Default, PartialEq, Eq)]
124pub struct PredWeightTable {
125    pub luma_log2_weight_denom: u8,
126    pub chroma_log2_weight_denom: u8,
127
128    pub luma_weight_l0: [i16; 32],
129    pub luma_offset_l0: [i8; 32],
130
131    /* if seq->ChromaArrayType != 0 */
132    pub chroma_weight_l0: [[i16; 2]; 32],
133    pub chroma_offset_l0: [[i8; 2]; 32],
134
135    /* if slice->slice_type % 5 == 1 */
136    pub luma_weight_l1: [i16; 32],
137    pub luma_offset_l1: [i16; 32],
138
139    /* and if seq->ChromaArrayType != 0 */
140    pub chroma_weight_l1: [[i16; 2]; 32],
141    pub chroma_offset_l1: [[i8; 2]; 32],
142}
143
144/// Representation of `MaxLongTermFrameIdx`.
145///
146/// `MaxLongTermFrameIdx` is derived from `max_long_term_frame_idx_plus1`, an unsigned integer with
147/// a special value indicating "no long-term frame indices". This type allows easy conversion
148/// between the actual and "plus1" representation, while ensuring that the special value is always
149/// handled by the code.
150#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
151pub enum MaxLongTermFrameIdx {
152    #[default]
153    NoLongTermFrameIndices,
154    Idx(u32),
155}
156
157impl MaxLongTermFrameIdx {
158    /// Create a value from `max_long_term_frame_idx_plus1`.
159    pub fn from_value_plus1(max_long_term_frame_idx_plus1: u32) -> Self {
160        match max_long_term_frame_idx_plus1 {
161            0 => Self::NoLongTermFrameIndices,
162            i @ 1.. => Self::Idx(i - 1),
163        }
164    }
165
166    /// Convert this value to the representation used by `max_long_term_frame_idx_plus1`.
167    pub fn to_value_plus1(self) -> u32 {
168        match self {
169            Self::NoLongTermFrameIndices => 0,
170            Self::Idx(i) => i + 1,
171        }
172    }
173}
174
175impl PartialEq<u32> for MaxLongTermFrameIdx {
176    fn eq(&self, other: &u32) -> bool {
177        match self {
178            MaxLongTermFrameIdx::NoLongTermFrameIndices => false,
179            MaxLongTermFrameIdx::Idx(idx) => idx.eq(other),
180        }
181    }
182}
183
184impl PartialOrd<u32> for MaxLongTermFrameIdx {
185    fn partial_cmp(&self, other: &u32) -> Option<std::cmp::Ordering> {
186        match self {
187            MaxLongTermFrameIdx::NoLongTermFrameIndices => Some(std::cmp::Ordering::Less),
188            MaxLongTermFrameIdx::Idx(idx) => Some(idx.cmp(other)),
189        }
190    }
191}
192
193#[derive(Clone, Debug, Default, PartialEq, Eq)]
194pub struct RefPicMarkingInner {
195    /// Specifies a control operation to be applied to affect the reference
196    /// picture marking. The `memory_management_control_operation` syntax element
197    /// is followed by data necessary for the operation specified by the value
198    /// of `memory_management_control_operation`. The values and control
199    /// operations associated with `memory_management_control_operation` are
200    /// specified in Table 7-9
201    pub memory_management_control_operation: u8,
202
203    /// Used (with memory_management_control_operation equal to 3 or 1) to
204    /// assign a long-term frame index to a short-term reference picture or to
205    /// mark a short-term reference picture as "unused for reference".
206    pub difference_of_pic_nums_minus1: u32,
207
208    /// Used (with memory_management_control_operation equal to 2) to mark a
209    /// long-term reference picture as "unused for reference".
210    pub long_term_pic_num: u32,
211
212    /// Used (with memory_management_control_operation equal to 3 or 6) to
213    /// assign a long-term frame index to a picture.
214    pub long_term_frame_idx: u32,
215
216    /// Specifies the maximum value of long-term frame index allowed for
217    /// long-term reference pictures (until receipt of another value of
218    /// `max_long_term_frame_idx_plus1`).
219    pub max_long_term_frame_idx: MaxLongTermFrameIdx,
220}
221
222#[derive(Clone, Debug, Default, PartialEq, Eq)]
223pub struct RefPicMarking {
224    /// Specifies how the previously-decoded pictures in the decoded picture
225    /// buffer are treated after decoding of an IDR picture. See Annex C.
226    pub no_output_of_prior_pics_flag: bool,
227
228    /// If unset, specifies that the MaxLongTermFrameIdx variable is set equal
229    /// to "no long-term frame indices" and that the IDR picture is marked as
230    /// "used for short-term reference". If set, specifies that the
231    /// MaxLongTermFrameIdx variable is set equal to 0 and that the current IDR
232    /// picture is marked "used for long-term reference" and is assigned
233    /// LongTermFrameIdx equal to 0.
234    pub long_term_reference_flag: bool,
235
236    /// Selects the reference picture marking mode of the currently decoded
237    /// picture as specified in Table 7-8.
238    pub adaptive_ref_pic_marking_mode_flag: bool,
239
240    /// An Vec with additional data used in the marking process.
241    pub inner: Vec<RefPicMarkingInner>,
242}
243
244#[derive(Clone, Debug, Default, PartialEq, Eq)]
245pub struct SliceHeader {
246    /// Specifies the address of the first macroblock in the slice.
247    pub first_mb_in_slice: u32,
248
249    /// Specifies the coding type of the slice according to Table 7-6.
250    pub slice_type: SliceType,
251
252    // Specifies the picture parameter set in use
253    pub pic_parameter_set_id: u8,
254
255    /// Specifies the colour plane associated with the current slice RBSP when
256    /// `separate_colour_plane_flag` is set.
257    pub colour_plane_id: u8,
258
259    /// Used as an identifier for pictures and shall be represented by
260    /// `log2_max_frame_num_minus4 + 4` bits in the bitstream.
261    pub frame_num: u16,
262
263    /// If set, specifies that the slice is a slice of a coded field. If not
264    /// set, specifies that the slice is a slice of a coded frame.
265    pub field_pic_flag: bool,
266
267    /// If set, specifies that the slice is part of a coded bottom field. If not
268    /// set, specifies that the picture is a coded top field.
269    pub bottom_field_flag: bool,
270
271    /// Identifies an IDR picture. The values of `idr_pic_id` in all the slices
272    /// of an IDR picture shall remain unchanged. When two consecutive access
273    /// units in decoding order are both IDR access units, the value of
274    /// `idr_pic_id` in the slices of the first such IDR access unit shall
275    /// differ from the `idr_pic_id` in the second such IDR access unit
276    pub idr_pic_id: u16,
277
278    /// Specifies the picture order count modulo `MaxPicOrderCntLsb` for the top
279    /// field of a coded frame or for a coded field. The length of the
280    /// `pic_order_cnt_lsb` syntax element is
281    /// `log2_max_pic_order_cnt_lsb_minus4` + 4 bits.
282    pub pic_order_cnt_lsb: u16,
283
284    ///  Specifies the picture order count difference between the bottom field
285    ///  and the top field of a coded frame as follows
286    pub delta_pic_order_cnt_bottom: i32,
287
288    /// The first entry specifies the picture order count difference from the
289    /// expected picture order count for the top field of a coded frame or for a
290    /// coded field as specified in clause 8.2.1 The second entry  specifies the
291    /// picture order count difference from the expected picture order count for
292    /// the bottom field of a coded frame specified in clause 8.2.1.
293    pub delta_pic_order_cnt: [i32; 2],
294
295    /// This value is required by V4L2 stateless decode params so it is calculated
296    /// by parser while processing slice header.
297    pub pic_order_cnt_bit_size: usize,
298
299    /// Shall be equal to 0 for slices and slice data partitions belonging to
300    /// the primary coded picture. The value of `redundant_pic_cnt shall` be
301    /// greater than 0 for coded slices or coded slice data partitions of a
302    /// redundant coded picture
303    pub redundant_pic_cnt: u8,
304
305    /// Specifies the method used in the decoding process to derive motion
306    /// vectors and reference indices for inter prediction >
307    pub direct_spatial_mv_pred_flag: bool,
308
309    /// If set, specifies that the syntax element `num_ref_idx_l0_active_minus1`
310    /// is present for P, SP, and B slices and that the syntax element
311    /// `num_ref_idx_l1_active_minus1` is present for B slices. If not set,
312    /// specifies that the syntax elements `num_ref_idx_l0_active_minus1` and
313    /// `num_ref_idx_l1_active_minus1` are not present.
314    pub num_ref_idx_active_override_flag: bool,
315
316    /// Specifies the maximum reference index for reference picture list 0 that
317    /// shall be used to decode the slice.
318    pub num_ref_idx_l0_active_minus1: u8,
319
320    /// Specifies the maximum reference index for reference picture list 1 that
321    /// shall be used to decode the slice.
322    pub num_ref_idx_l1_active_minus1: u8,
323
324    /// If set, specifies that the syntax element `modification_of_pic_nums_idc`
325    /// is present for specifying reference picture list 0. If not set,
326    /// specifies that this syntax element is not present.
327    pub ref_pic_list_modification_flag_l0: bool,
328
329    /// Reference picture list 0 modification as parsed with the
330    /// `ref_pic_list_modification()` process.
331    pub ref_pic_list_modification_l0: Vec<RefPicListModification>,
332
333    /// If set, specifies that the syntax element `modification_of_pic_nums_idc`
334    /// is present for specifying reference picture list 1. If not set,
335    /// specifies that this syntax element is not present.
336    pub ref_pic_list_modification_flag_l1: bool,
337
338    /// Reference picture list 1 modification as parsed with the
339    /// `ref_pic_list_modification()` process.
340    pub ref_pic_list_modification_l1: Vec<RefPicListModification>,
341
342    /// Prediction weight table as parsed using 7.3.3.2
343    pub pred_weight_table: PredWeightTable,
344
345    /// Decoded reference picture marking parsed using 7.3.3.3
346    pub dec_ref_pic_marking: RefPicMarking,
347
348    /// This value is required by V4L2 stateless decode params so it is calculated
349    /// by parser while processing slice header.
350    pub dec_ref_pic_marking_bit_size: usize,
351
352    /// Specifies the index for determining the initialization table used in the
353    /// initialization process for context variables.
354    pub cabac_init_idc: u8,
355
356    /// Specifies the initial value of QP Y to be used for all the macroblocks
357    /// in the slice until modified by the value of `mb_qp_delta` in the
358    /// macroblock layer. The initial QPY quantization parameter for the slice
359    /// is computed using 7-30.
360    pub slice_qp_delta: i8,
361
362    /// Specifies the decoding process to be used to decode P macroblocks in an
363    /// SP slice.
364    pub sp_for_switch_flag: bool,
365
366    /// Specifies the value of QSY for all the macroblocks in SP and SI slices.
367    /// The QSY quantization parameter for the slice is computed using 7-31.
368    pub slice_qs_delta: i8,
369
370    /// Specifies whether the operation of the deblocking filter shall be
371    /// disabled across some block edges of the slice and specifies for which
372    /// edges the filtering is disabled.
373    pub disable_deblocking_filter_idc: u8,
374
375    /// Specifies the offset used in accessing the α and tC0 deblocking filter
376    /// tables for filtering operations controlled by the macroblocks within the
377    /// slice. From this value, the offset that shall be applied when addressing
378    /// these tables shall be computed using 7-32.
379    pub slice_alpha_c0_offset_div2: i8,
380
381    /// Specifies the offset used in accessing the β deblocking filter table for
382    /// filtering operations controlled by the macroblocks within the slice.
383    /// From this value, the offset that is applied when addressing the β table
384    /// of the deblocking filter shall be computed using 7-33.
385    pub slice_beta_offset_div2: i8,
386
387    /// Same as `MaxPicNum` in the specification.
388    pub max_pic_num: u32,
389
390    /// Size of the slice_header() in bits
391    pub header_bit_size: usize,
392
393    /// Number of emulation prevention bytes (EPB) in this slice_header()
394    pub n_emulation_prevention_bytes: usize,
395}
396
397impl SliceHeader {
398    /// Returns the field that is coded by this header.
399    pub fn field(&self) -> Field {
400        if self.field_pic_flag {
401            if self.bottom_field_flag {
402                Field::Bottom
403            } else {
404                Field::Top
405            }
406        } else {
407            Field::Frame
408        }
409    }
410}
411
412pub struct SliceHeaderBuilder(SliceHeader);
413
414impl SliceHeaderBuilder {
415    pub fn new(pps: &Pps) -> Self {
416        SliceHeaderBuilder(SliceHeader {
417            pic_parameter_set_id: pps.pic_parameter_set_id,
418            ..Default::default()
419        })
420    }
421
422    pub fn slice_type(mut self, type_: SliceType) -> Self {
423        self.0.slice_type = type_;
424        self
425    }
426
427    pub fn first_mb_in_slice(mut self, value: u32) -> Self {
428        self.0.first_mb_in_slice = value;
429        self
430    }
431
432    pub fn pic_order_cnt_lsb(mut self, value: u16) -> Self {
433        self.0.pic_order_cnt_lsb = value;
434        self
435    }
436
437    pub fn idr_pic_id(mut self, value: u16) -> Self {
438        self.0.idr_pic_id = value;
439        self
440    }
441
442    pub fn num_ref_idx_active_override_flag(mut self, value: bool) -> Self {
443        self.0.num_ref_idx_active_override_flag = value;
444        self
445    }
446
447    pub fn num_ref_idx_l0_active_minus1(mut self, value: u8) -> Self {
448        self = self.num_ref_idx_active_override_flag(true);
449        self.0.num_ref_idx_l0_active_minus1 = value;
450        self
451    }
452
453    pub fn num_ref_idx_l0_active(self, value: u8) -> Self {
454        self.num_ref_idx_l0_active_minus1(value - 1)
455    }
456
457    pub fn num_ref_idx_l1_active_minus1(mut self, value: u8) -> Self {
458        self = self.num_ref_idx_active_override_flag(true);
459        self.0.num_ref_idx_l1_active_minus1 = value;
460        self
461    }
462
463    pub fn num_ref_idx_l1_active(self, value: u8) -> Self {
464        self.num_ref_idx_l1_active_minus1(value - 1)
465    }
466
467    pub fn build(self) -> SliceHeader {
468        self.0
469    }
470}
471
472/// A H264 slice. An integer number of macroblocks or macroblock pairs ordered
473/// consecutively in the raster scan within a particular slice group
474pub struct Slice<'a> {
475    /// The slice header.
476    pub header: SliceHeader,
477    /// The NAL unit backing this slice.
478    pub nalu: Nalu<'a>,
479}
480
481#[derive(Clone, Copy, Debug, PartialEq, Eq)]
482/// See table 7-6 in the specification.
483pub enum SliceType {
484    P = 0,
485    B = 1,
486    I = 2,
487    Sp = 3,
488    Si = 4,
489}
490
491impl TryFrom<u8> for SliceType {
492    type Error = String;
493
494    fn try_from(value: u8) -> Result<Self, Self::Error> {
495        match value {
496            0 => Ok(SliceType::P),
497            1 => Ok(SliceType::B),
498            2 => Ok(SliceType::I),
499            3 => Ok(SliceType::Sp),
500            4 => Ok(SliceType::Si),
501            _ => Err(format!("Invalid SliceType {}", value)),
502        }
503    }
504}
505
506impl SliceType {
507    /// Whether this is a P slice. See table 7-6 in the specification.
508    pub fn is_p(&self) -> bool {
509        matches!(self, SliceType::P)
510    }
511
512    /// Whether this is a B slice. See table 7-6 in the specification.
513    pub fn is_b(&self) -> bool {
514        matches!(self, SliceType::B)
515    }
516
517    /// Whether this is an I slice. See table 7-6 in the specification.
518    pub fn is_i(&self) -> bool {
519        matches!(self, SliceType::I)
520    }
521
522    /// Whether this is a SP slice. See table 7-6 in the specification.
523    pub fn is_sp(&self) -> bool {
524        matches!(self, SliceType::Sp)
525    }
526
527    /// Whether this is a SI slice. See table 7-6 in the specification.
528    pub fn is_si(&self) -> bool {
529        matches!(self, SliceType::Si)
530    }
531}
532
533impl Default for SliceType {
534    fn default() -> Self {
535        Self::P
536    }
537}
538
539#[derive(Clone, Copy)]
540#[repr(u8)]
541pub enum Profile {
542    Baseline = 66,
543    Main = 77,
544    Extended = 88,
545    High = 100,
546    High10 = 110,
547    High422P = 122,
548}
549
550impl TryFrom<u8> for Profile {
551    type Error = String;
552
553    fn try_from(value: u8) -> Result<Self, Self::Error> {
554        match value {
555            66 => Ok(Profile::Baseline),
556            77 => Ok(Profile::Main),
557            88 => Ok(Profile::Extended),
558            100 => Ok(Profile::High),
559            110 => Ok(Profile::High10),
560            122 => Ok(Profile::High422P),
561            _ => Err(format!("Invalid Profile {}", value)),
562        }
563    }
564}
565
566#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
567pub enum Level {
568    #[default]
569    L1 = 10,
570    L1B = 9,
571    L1_1 = 11,
572    L1_2 = 12,
573    L1_3 = 13,
574    L2_0 = 20,
575    L2_1 = 21,
576    L2_2 = 22,
577    L3 = 30,
578    L3_1 = 31,
579    L3_2 = 32,
580    L4 = 40,
581    L4_1 = 41,
582    L4_2 = 42,
583    L5 = 50,
584    L5_1 = 51,
585    L5_2 = 52,
586    L6 = 60,
587    L6_1 = 61,
588    L6_2 = 62,
589}
590
591impl TryFrom<u8> for Level {
592    type Error = String;
593
594    fn try_from(value: u8) -> Result<Self, Self::Error> {
595        match value {
596            10 => Ok(Level::L1),
597            9 => Ok(Level::L1B),
598            11 => Ok(Level::L1_1),
599            12 => Ok(Level::L1_2),
600            13 => Ok(Level::L1_3),
601            20 => Ok(Level::L2_0),
602            21 => Ok(Level::L2_1),
603            22 => Ok(Level::L2_2),
604            30 => Ok(Level::L3),
605            31 => Ok(Level::L3_1),
606            32 => Ok(Level::L3_2),
607            40 => Ok(Level::L4),
608            41 => Ok(Level::L4_1),
609            42 => Ok(Level::L4_2),
610            50 => Ok(Level::L5),
611            51 => Ok(Level::L5_1),
612            52 => Ok(Level::L5_2),
613            60 => Ok(Level::L6),
614            61 => Ok(Level::L6_1),
615            62 => Ok(Level::L6_2),
616            _ => Err(format!("Invalid Level {}", value)),
617        }
618    }
619}
620
621/// A H264 Sequence Parameter Set. A syntax structure containing syntax elements
622/// that apply to zero or more entire coded video sequences as determined by the
623/// content of a seq_parameter_set_id syntax element found in the picture
624/// parameter set referred to by the pic_parameter_set_id syntax element found
625/// in each slice header.
626#[derive(Debug, PartialEq, Eq)]
627pub struct Sps {
628    /// Identifies the sequence parameter set that is referred to by the picture
629    /// parameter set
630    pub seq_parameter_set_id: u8,
631
632    /// Profile to which the coded video sequence conforms
633    pub profile_idc: u8,
634
635    /// Retains the same meaning as in the specification. See 7.4.2.1.1
636    pub constraint_set0_flag: bool,
637    /// Retains the same meaning as in the specification. See 7.4.2.1.1
638    pub constraint_set1_flag: bool,
639    /// Retains the same meaning as in the specification. See 7.4.2.1.1
640    pub constraint_set2_flag: bool,
641    /// Retains the same meaning as in the specification. See 7.4.2.1.1
642    pub constraint_set3_flag: bool,
643    /// Retains the same meaning as in the specification. See 7.4.2.1.1
644    pub constraint_set4_flag: bool,
645    /// Retains the same meaning as in the specification. See 7.4.2.1.1
646    pub constraint_set5_flag: bool,
647
648    /// Level to which the coded video sequence conforms
649    pub level_idc: Level,
650
651    /// Specifies the chroma sampling relative to the luma sampling as specified
652    /// in clause 6.2.
653    pub chroma_format_idc: u8,
654
655    /// Specifies whether the three colour components of the 4:4:4 chroma format
656    /// are coded separately.
657    pub separate_colour_plane_flag: bool,
658
659    /// Specifies the bit depth of the samples of the luma array and the value
660    /// of the luma quantization parameter range offset QpBdOffsetY. See 7-3 and
661    /// 7-4.
662    pub bit_depth_luma_minus8: u8,
663
664    /// Specifies the bit depth of the samples of the chroma arrays and the
665    /// value of the chroma quantization parameter range offset QpBdOffsetC. See
666    /// 7-5 and 7-6.
667    pub bit_depth_chroma_minus8: u8,
668
669    /// qpprime_y_zero_transform_bypass_flag equal to 1 specifies that, when
670    /// QP′Y is equal to 0, a transform bypass operation for the transform
671    /// coefficient decoding process and picture construction process prior to
672    /// deblocking filter process as specified in clause 8.5 shall be applied.
673    /// qpprime_y_zero_transform_bypass_flag equal to 0 specifies that the
674    /// transform coefficient decoding process and picture construction process
675    /// prior to deblocking filter process shall not use the transform bypass
676    /// operation
677    /// QP′Y is defined in 7-38 as QP′Y = QPY + QpBdOffsetY
678    pub qpprime_y_zero_transform_bypass_flag: bool,
679
680    /// Whether `seq_scaling_list_present_flag[i]` for i = 0..7 or i = 0..11 is
681    /// present or whether the sequence level scaling list shall be specified by
682    /// Flat_4x4_16 for i = 0..5 and flat_8x8_16 for i = 6..11
683    pub seq_scaling_matrix_present_flag: bool,
684
685    /// 4x4 Scaling list as read with 7.3.2.1.1.1
686    pub scaling_lists_4x4: [[u8; 16]; 6],
687    /// 8x8 Scaling list as read with 7.3.2.1.1.1
688    pub scaling_lists_8x8: [[u8; 64]; 6],
689
690    /// Specifies the value of the variable MaxFrameNum that is used in
691    /// frame_num related derivations as follows: MaxFrameNum = 2 ^
692    /// (log2_max_frame_num_minus4 + 4 )
693    pub log2_max_frame_num_minus4: u8,
694
695    /// Specifies the method to decode picture order count (as specified in
696    /// clause 8.2.1)
697    pub pic_order_cnt_type: u8,
698
699    /// Specifies the value of the variable MaxPicOrderCntLsb that is used in
700    /// the decoding process for picture order count as specified in clause
701    /// 8.2.1 as follows: MaxPicOrderCntLsb = 2 ^ (
702    /// log2_max_pic_order_cnt_lsb_minus4 + 4 ).
703    pub log2_max_pic_order_cnt_lsb_minus4: u8,
704
705    /// If true, specifies that `delta_pic_order_cnt[0]` and
706    /// `delta_pic_order_cnt[1]` are not present in the slice headers of the
707    /// sequence and shall be inferred to be equal to 0.
708    /// If false, specifies that `delta_pic_order_cnt[0]` is present in the
709    /// slice headers of the sequence and `delta_pic_order_cnt[1]` may be
710    /// present in the slice headers of the sequence.
711    pub delta_pic_order_always_zero_flag: bool,
712
713    /// Used to calculate the picture order count of a non-reference picture as
714    /// specified in clause 8.2.1.
715    pub offset_for_non_ref_pic: i32,
716
717    /// Used to calculate the picture order count of a bottom field as specified
718    /// in clause 8.2.1.
719    pub offset_for_top_to_bottom_field: i32,
720
721    /// Used in the decoding process for picture order count as specified in
722    /// clause 8.2.1
723    pub num_ref_frames_in_pic_order_cnt_cycle: u8,
724
725    /// An element of a list of num_ref_frames_in_pic_order_cnt_cycle values
726    /// used in the decoding process for picture order count as specified in
727    /// clause 8.2.
728    pub offset_for_ref_frame: [i32; 255],
729
730    /// Specifies the maximum number of short-term and long-term reference
731    /// frames, complementary reference field pairs, and non-paired reference
732    /// fields that may be used by the decoding process for inter prediction of
733    /// any picture in the coded video sequence. Also
734    /// determines the size of the sliding window operation as specified in
735    /// clause 8.2.5.3.
736    pub max_num_ref_frames: u8,
737
738    /// Specifies the allowed values of frame_num as specified in clause 7.4.3
739    /// and the decoding process in case of an inferred gap between values of
740    /// frame_num as specified in clause 8.2.5.2
741    pub gaps_in_frame_num_value_allowed_flag: bool,
742
743    /// Plus 1 specifies the width of each decoded picture in units of
744    /// macroblocks.
745    pub pic_width_in_mbs_minus1: u16,
746    /// Plus 1 specifies the height in slice group map units of a decoded frame
747    /// or field.
748    pub pic_height_in_map_units_minus1: u16,
749
750    /// If true,  specifies that every coded picture of the coded video sequence
751    /// is a coded frame containing only frame macroblocks, else specifies that
752    /// coded pictures of the coded video sequence may either be coded fields or
753    /// coded frames.
754    pub frame_mbs_only_flag: bool,
755
756    /// If true, specifies the possible use of switching between frame and field
757    /// macroblocks within frames, else, specifies no switching between frame
758    /// and field macroblocks within a picture.
759    pub mb_adaptive_frame_field_flag: bool,
760
761    /// Specifies the method used in the derivation process for luma motion
762    /// vectors for B_Skip, B_Direct_16x16 and B_Direct_8x8 as specified in
763    /// clause 8.4.1.2.
764    pub direct_8x8_inference_flag: bool,
765
766    /// If true, specifies that the frame cropping offset parameters follow next
767    /// in the sequence parameter, else specifies that the frame cropping offset
768    /// parameters are not present
769    pub frame_cropping_flag: bool,
770
771    /// Specify the samples of the pictures in the coded video sequence that are
772    /// output from the decoding process, in terms of a rectangular region
773    /// specified in frame coordinates for output.
774    pub frame_crop_left_offset: u32,
775    /// Specify the samples of the pictures in the coded video sequence that are
776    /// output from the decoding process, in terms of a rectangular region
777    /// specified in frame coordinates for output.
778    pub frame_crop_right_offset: u32,
779    /// Specify the samples of the pictures in the coded video sequence that are
780    /// output from the decoding process, in terms of a rectangular region
781    /// specified in frame coordinates for output.
782    pub frame_crop_top_offset: u32,
783    /// Specify the samples of the pictures in the coded video sequence that are
784    /// output from the decoding process, in terms of a rectangular region
785    /// specified in frame coordinates for output.
786    pub frame_crop_bottom_offset: u32,
787
788    // Calculated
789    /// Same as ExpectedDeltaPerPicOrderCntCycle, see 7-12 in the specification.
790    pub expected_delta_per_pic_order_cnt_cycle: i32,
791
792    pub vui_parameters_present_flag: bool,
793    pub vui_parameters: VuiParams,
794}
795
796impl Sps {
797    /// Returns the coded width of the stream.
798    ///
799    /// See 7-13 through 7-17 in the specification.
800    pub const fn width(&self) -> u32 {
801        (self.pic_width_in_mbs_minus1 as u32 + 1) * 16
802    }
803
804    /// Returns the coded height of the stream.
805    ///
806    /// See 7-13 through 7-17 in the specification.
807    pub const fn height(&self) -> u32 {
808        (self.pic_height_in_map_units_minus1 as u32 + 1)
809            * 16
810            * (2 - self.frame_mbs_only_flag as u32)
811    }
812
813    /// Returns `ChromaArrayType`, as computed in the specification.
814    pub const fn chroma_array_type(&self) -> u8 {
815        match self.separate_colour_plane_flag {
816            false => self.chroma_format_idc,
817            true => 0,
818        }
819    }
820
821    /// Returns `SubWidthC` and `SubHeightC`.
822    ///
823    /// See table 6-1 in the specification.
824    fn sub_width_height_c(&self) -> (u32, u32) {
825        match (self.chroma_format_idc, self.separate_colour_plane_flag) {
826            (1, false) => (2, 2),
827            (2, false) => (2, 1),
828            (3, false) => (1, 1),
829            // undefined.
830            _ => (1, 1),
831        }
832    }
833
834    /// Returns `CropUnitX` and `CropUnitY`.
835    ///
836    /// See 7-19 through 7-22 in the specification.
837    fn crop_unit_x_y(&self) -> (u32, u32) {
838        match self.chroma_array_type() {
839            0 => (1, 2 - u32::from(self.frame_mbs_only_flag)),
840            _ => {
841                let (sub_width_c, sub_height_c) = self.sub_width_height_c();
842                (sub_width_c, sub_height_c * (2 - u32::from(self.frame_mbs_only_flag)))
843            }
844        }
845    }
846
847    /// Same as MaxFrameNum. See 7-10 in the specification.
848    pub fn max_frame_num(&self) -> u32 {
849        1 << (self.log2_max_frame_num_minus4 + 4)
850    }
851
852    pub fn visible_rectangle(&self) -> Rect<u32> {
853        if !self.frame_cropping_flag {
854            return Rect {
855                min: Point { x: 0, y: 0 },
856                max: Point { x: self.width(), y: self.height() },
857            };
858        }
859
860        let (crop_unit_x, crop_unit_y) = self.crop_unit_x_y();
861
862        let crop_left = crop_unit_x * self.frame_crop_left_offset;
863        let crop_right = crop_unit_x * self.frame_crop_right_offset;
864        let crop_top = crop_unit_y * self.frame_crop_top_offset;
865        let crop_bottom = crop_unit_y * self.frame_crop_bottom_offset;
866
867        Rect {
868            min: Point { x: crop_left, y: crop_top },
869            max: Point {
870                x: self.width() - crop_left - crop_right,
871                y: self.height() - crop_top - crop_bottom,
872            },
873        }
874    }
875
876    pub fn max_dpb_frames(&self) -> usize {
877        let profile = self.profile_idc;
878        let mut level = self.level_idc;
879
880        // A.3.1 and A.3.2: Level 1b for Baseline, Constrained Baseline and Main
881        // profile if level_idc == 11 and constraint_set3_flag == 1
882        if matches!(level, Level::L1_1)
883            && (profile == Profile::Baseline as u8 || profile == Profile::Main as u8)
884            && self.constraint_set3_flag
885        {
886            level = Level::L1B;
887        };
888
889        // Table A.1
890        let max_dpb_mbs = match level {
891            Level::L1 => 396,
892            Level::L1B => 396,
893            Level::L1_1 => 900,
894            Level::L1_2 => 2376,
895            Level::L1_3 => 2376,
896            Level::L2_0 => 2376,
897            Level::L2_1 => 4752,
898            Level::L2_2 => 8100,
899            Level::L3 => 8100,
900            Level::L3_1 => 18000,
901            Level::L3_2 => 20480,
902            Level::L4 => 32768,
903            Level::L4_1 => 32768,
904            Level::L4_2 => 34816,
905            Level::L5 => 110400,
906            Level::L5_1 => 184320,
907            Level::L5_2 => 184320,
908            Level::L6 => 696320,
909            Level::L6_1 => 696320,
910            Level::L6_2 => 696320,
911        };
912
913        let width_mb = self.width() / 16;
914        let height_mb = self.height() / 16;
915
916        let max_dpb_frames =
917            std::cmp::min(max_dpb_mbs / (width_mb * height_mb), DPB_MAX_SIZE as u32) as usize;
918
919        let mut max_dpb_frames = std::cmp::max(max_dpb_frames, self.max_num_ref_frames as usize);
920
921        if self.vui_parameters_present_flag && self.vui_parameters.bitstream_restriction_flag {
922            max_dpb_frames = std::cmp::max(1, self.vui_parameters.max_dec_frame_buffering as usize);
923        }
924
925        max_dpb_frames
926    }
927
928    pub fn max_num_order_frames(&self) -> u32 {
929        let vui = &self.vui_parameters;
930        let present = self.vui_parameters_present_flag && vui.bitstream_restriction_flag;
931
932        if present {
933            vui.max_num_reorder_frames
934        } else {
935            let profile = self.profile_idc;
936            if (profile == 44
937                || profile == 86
938                || profile == 100
939                || profile == 110
940                || profile == 122
941                || profile == 244)
942                && self.constraint_set3_flag
943            {
944                0
945            } else {
946                self.max_dpb_frames() as u32
947            }
948        }
949    }
950}
951
952// TODO: Replace with builder
953impl Default for Sps {
954    fn default() -> Self {
955        Self {
956            scaling_lists_4x4: [[0; 16]; 6],
957            scaling_lists_8x8: [[0; 64]; 6],
958            offset_for_ref_frame: [0; 255],
959            seq_parameter_set_id: Default::default(),
960            profile_idc: Default::default(),
961            constraint_set0_flag: Default::default(),
962            constraint_set1_flag: Default::default(),
963            constraint_set2_flag: Default::default(),
964            constraint_set3_flag: Default::default(),
965            constraint_set4_flag: Default::default(),
966            constraint_set5_flag: Default::default(),
967            level_idc: Default::default(),
968            chroma_format_idc: Default::default(),
969            separate_colour_plane_flag: Default::default(),
970            bit_depth_luma_minus8: Default::default(),
971            bit_depth_chroma_minus8: Default::default(),
972            qpprime_y_zero_transform_bypass_flag: Default::default(),
973            seq_scaling_matrix_present_flag: Default::default(),
974            log2_max_frame_num_minus4: Default::default(),
975            pic_order_cnt_type: Default::default(),
976            log2_max_pic_order_cnt_lsb_minus4: Default::default(),
977            delta_pic_order_always_zero_flag: Default::default(),
978            offset_for_non_ref_pic: Default::default(),
979            offset_for_top_to_bottom_field: Default::default(),
980            num_ref_frames_in_pic_order_cnt_cycle: Default::default(),
981            max_num_ref_frames: Default::default(),
982            gaps_in_frame_num_value_allowed_flag: Default::default(),
983            pic_width_in_mbs_minus1: Default::default(),
984            pic_height_in_map_units_minus1: Default::default(),
985            frame_mbs_only_flag: Default::default(),
986            mb_adaptive_frame_field_flag: Default::default(),
987            direct_8x8_inference_flag: Default::default(),
988            frame_cropping_flag: Default::default(),
989            frame_crop_left_offset: Default::default(),
990            frame_crop_right_offset: Default::default(),
991            frame_crop_top_offset: Default::default(),
992            frame_crop_bottom_offset: Default::default(),
993            expected_delta_per_pic_order_cnt_cycle: Default::default(),
994            vui_parameters_present_flag: Default::default(),
995            vui_parameters: Default::default(),
996        }
997    }
998}
999
1000#[derive(Default)]
1001pub struct SpsBuilder(Sps);
1002
1003impl SpsBuilder {
1004    pub fn new() -> Self {
1005        Default::default()
1006    }
1007
1008    pub fn seq_parameter_set_id(mut self, value: u8) -> Self {
1009        self.0.seq_parameter_set_id = value;
1010        self
1011    }
1012
1013    pub fn profile_idc(mut self, value: Profile) -> Self {
1014        self.0.profile_idc = value as u8;
1015        self
1016    }
1017
1018    pub fn level_idc(mut self, value: Level) -> Self {
1019        self.0.level_idc = value;
1020        self
1021    }
1022
1023    pub fn frame_crop_offsets(mut self, top: u32, bottom: u32, left: u32, right: u32) -> Self {
1024        self.0.frame_cropping_flag = true;
1025        self.0.frame_crop_top_offset = top;
1026        self.0.frame_crop_bottom_offset = bottom;
1027        self.0.frame_crop_left_offset = left;
1028        self.0.frame_crop_right_offset = right;
1029        self
1030    }
1031
1032    pub fn frame_crop(self, top: u32, bottom: u32, left: u32, right: u32) -> Self {
1033        let sub_width_c = if self.0.chroma_format_idc > 2 { 1 } else { 2 };
1034        let sub_height_c = if self.0.chroma_format_idc > 1 { 1 } else { 2 };
1035
1036        let crop_unit_x = sub_width_c;
1037        let crop_unit_y = sub_height_c * (if self.0.frame_mbs_only_flag { 1 } else { 2 });
1038
1039        self.frame_crop_offsets(
1040            top / crop_unit_y,
1041            bottom / crop_unit_y,
1042            left / crop_unit_x,
1043            right / crop_unit_x,
1044        )
1045    }
1046
1047    pub fn resolution(mut self, width: u32, height: u32) -> Self {
1048        const MB_SIZE: u32 = 16;
1049
1050        let mb_width = (width + MB_SIZE - 1) / MB_SIZE;
1051        let mb_height = (height + MB_SIZE - 1) / MB_SIZE;
1052
1053        self.0.pic_width_in_mbs_minus1 = (mb_width - 1) as u16;
1054        self.0.pic_height_in_map_units_minus1 = (mb_height - 1) as u16;
1055
1056        let compressed_width = mb_width * MB_SIZE;
1057        let compressed_height = mb_height * MB_SIZE;
1058
1059        if compressed_width != width || compressed_height != height {
1060            self = self.frame_crop(0, compressed_height - height, 0, compressed_width - width);
1061        }
1062
1063        self
1064    }
1065
1066    pub fn chroma_format_idc(mut self, value: u8) -> Self {
1067        self.0.chroma_format_idc = value;
1068        self
1069    }
1070
1071    pub fn max_num_ref_frames(mut self, value: u8) -> Self {
1072        self.0.max_num_ref_frames = value;
1073        self
1074    }
1075
1076    pub fn frame_mbs_only_flag(mut self, value: bool) -> Self {
1077        self.0.frame_mbs_only_flag = value;
1078        self
1079    }
1080
1081    pub fn mb_adaptive_frame_field_flag(mut self, value: bool) -> Self {
1082        self.0.mb_adaptive_frame_field_flag = value;
1083        self
1084    }
1085
1086    pub fn seq_scaling_matrix_present_flag(mut self, value: bool) -> Self {
1087        self.0.seq_scaling_matrix_present_flag = value;
1088        self
1089    }
1090
1091    pub fn direct_8x8_inference_flag(mut self, value: bool) -> Self {
1092        self.0.direct_8x8_inference_flag = value;
1093        self
1094    }
1095
1096    pub fn vui_parameters_present(mut self) -> Self {
1097        if self.0.vui_parameters_present_flag {
1098            return self;
1099        }
1100
1101        self.0.vui_parameters_present_flag = true;
1102        // Disable all options at default
1103        self.0.vui_parameters.aspect_ratio_info_present_flag = false;
1104        self.0.vui_parameters.overscan_info_present_flag = false;
1105        self.0.vui_parameters.video_signal_type_present_flag = false;
1106        self.0.vui_parameters.colour_description_present_flag = false;
1107        self.0.vui_parameters.chroma_loc_info_present_flag = false;
1108        self.0.vui_parameters.timing_info_present_flag = false;
1109        self.0.vui_parameters.nal_hrd_parameters_present_flag = false;
1110        self.0.vui_parameters.vcl_hrd_parameters_present_flag = false;
1111        self.0.vui_parameters.pic_struct_present_flag = false;
1112        self.0.vui_parameters.bitstream_restriction_flag = false;
1113        self
1114    }
1115
1116    pub fn aspect_ratio_idc(mut self, value: u8) -> Self {
1117        self = self.vui_parameters_present();
1118        self.0.vui_parameters.aspect_ratio_info_present_flag = true;
1119        self.0.vui_parameters.aspect_ratio_idc = value;
1120        self
1121    }
1122
1123    pub fn sar_resolution(mut self, width: u16, height: u16) -> Self {
1124        self = self.aspect_ratio_idc(255);
1125        self.0.vui_parameters.sar_width = width;
1126        self.0.vui_parameters.sar_height = height;
1127        self
1128    }
1129
1130    pub fn aspect_ratio(self, width_ratio: u16, height_ratio: u16) -> Self {
1131        // H.264 Table E-1
1132        match (width_ratio, height_ratio) {
1133            (1, 1) => self.aspect_ratio_idc(1),
1134            (12, 11) => self.aspect_ratio_idc(2),
1135            (10, 11) => self.aspect_ratio_idc(3),
1136            (16, 11) => self.aspect_ratio_idc(4),
1137            (40, 33) => self.aspect_ratio_idc(5),
1138            (24, 11) => self.aspect_ratio_idc(6),
1139            (20, 11) => self.aspect_ratio_idc(7),
1140            (32, 11) => self.aspect_ratio_idc(8),
1141            (80, 33) => self.aspect_ratio_idc(9),
1142            (18, 11) => self.aspect_ratio_idc(10),
1143            (15, 11) => self.aspect_ratio_idc(11),
1144            (64, 33) => self.aspect_ratio_idc(12),
1145            (160, 99) => self.aspect_ratio_idc(13),
1146            (4, 3) => self.aspect_ratio_idc(14),
1147            (3, 2) => self.aspect_ratio_idc(15),
1148            (2, 1) => self.aspect_ratio_idc(16),
1149
1150            _ => self.sar_resolution(width_ratio, height_ratio),
1151        }
1152    }
1153
1154    pub fn timing_info(
1155        mut self,
1156        num_units_in_tick: u32,
1157        time_scale: u32,
1158        fixed_frame_rate_flag: bool,
1159    ) -> Self {
1160        self = self.vui_parameters_present();
1161        self.0.vui_parameters.timing_info_present_flag = true;
1162        self.0.vui_parameters.num_units_in_tick = num_units_in_tick;
1163        self.0.vui_parameters.time_scale = time_scale;
1164        self.0.vui_parameters.fixed_frame_rate_flag = fixed_frame_rate_flag;
1165        self
1166    }
1167
1168    pub fn log2_max_frame_num_minus4(mut self, value: u8) -> Self {
1169        self.0.log2_max_frame_num_minus4 = value;
1170        self
1171    }
1172
1173    pub fn max_frame_num(self, value: u32) -> Self {
1174        self.log2_max_frame_num_minus4(value.ilog2() as u8 - 4u8)
1175    }
1176
1177    pub fn pic_order_cnt_type(mut self, value: u8) -> Self {
1178        self.0.pic_order_cnt_type = value;
1179        self
1180    }
1181
1182    pub fn log2_max_pic_order_cnt_lsb_minus4(mut self, value: u8) -> Self {
1183        self.0.log2_max_pic_order_cnt_lsb_minus4 = value;
1184        self
1185    }
1186
1187    pub fn max_pic_order_cnt_lsb(self, value: u32) -> Self {
1188        self.log2_max_pic_order_cnt_lsb_minus4(value.ilog2() as u8 - 4u8)
1189    }
1190
1191    pub fn delta_pic_order_always_zero_flag(mut self, value: bool) -> Self {
1192        self.0.delta_pic_order_always_zero_flag = value;
1193        self
1194    }
1195
1196    pub fn bit_depth_chroma_minus8(mut self, value: u8) -> Self {
1197        self.0.bit_depth_chroma_minus8 = value;
1198        self
1199    }
1200
1201    pub fn bit_depth_chroma(self, value: u8) -> Self {
1202        self.bit_depth_luma_minus8(value - 8u8)
1203    }
1204
1205    pub fn bit_depth_luma_minus8(mut self, value: u8) -> Self {
1206        self.0.bit_depth_luma_minus8 = value;
1207        self
1208    }
1209
1210    pub fn bit_depth_luma(self, value: u8) -> Self {
1211        self.bit_depth_luma_minus8(value - 8u8)
1212    }
1213
1214    pub fn build(self) -> Rc<Sps> {
1215        Rc::new(self.0)
1216    }
1217}
1218
1219#[derive(Clone, Debug, Default, PartialEq, Eq)]
1220pub struct HrdParams {
1221    /// Plus 1 specifies the number of alternative CPB specifications in the
1222    /// bitstream. The value of `cpb_cnt_minus1` shall be in the range of 0 to 31,
1223    /// inclusive
1224    pub cpb_cnt_minus1: u8,
1225    /// Together with `bit_rate_value_minus1[ SchedSelIdx ]` specifies the
1226    /// maximum input bit rate of the `SchedSelIdx`-th CPB.
1227    pub bit_rate_scale: u8,
1228    /// Together with `cpb_size_value_minus1[ SchedSelIdx ]` specifies the CPB
1229    /// size of the SchedSelIdx-th CPB.
1230    pub cpb_size_scale: u8,
1231
1232    /// `[ SchedSelIdx ]` (together with bit_rate_scale) specifies the maximum
1233    /// input bit rate for the SchedSelIdx-th CPB.
1234    pub bit_rate_value_minus1: [u32; 32],
1235    /// `[ SchedSelIdx ]` is used together with cpb_size_scale to specify the
1236    /// SchedSelIdx-th CPB size.
1237    pub cpb_size_value_minus1: [u32; 32],
1238    /// `[ SchedSelIdx ]` equal to 0 specifies that to decode this bitstream by
1239    /// the HRD using the `SchedSelIdx`-th CPB specification, the hypothetical
1240    /// stream delivery scheduler (HSS) operates in an intermittent bit rate
1241    /// mode. `cbr_flag[ SchedSelIdx ]` equal to 1 specifies that the HSS operates
1242    /// in a constant bit rate (CBR) mode
1243    pub cbr_flag: [bool; 32],
1244
1245    /// Specifies the length in bits of the `initial_cpb_removal_delay[
1246    /// SchedSelIdx ]` and `initial_cpb_removal_delay_offset[ SchedSelIdx ]` syntax
1247    /// elements of the buffering period SEI message.
1248    pub initial_cpb_removal_delay_length_minus1: u8,
1249    /// Specifies the length in bits of the `cpb_removal_delay` syntax element.
1250    pub cpb_removal_delay_length_minus1: u8,
1251    /// Specifies the length in bits of the `dpb_output_delay` syntax element.
1252    pub dpb_output_delay_length_minus1: u8,
1253    /// If greater than 0, specifies the length in bits of the `time_offset`
1254    /// syntax element. `time_offset_length` equal to 0 specifies that the
1255    /// `time_offset` syntax element is not present
1256    pub time_offset_length: u8,
1257}
1258
1259#[derive(Clone, Debug, PartialEq, Eq)]
1260pub struct VuiParams {
1261    /// Specifies whether `aspect_ratio_idc` is present.
1262    pub aspect_ratio_info_present_flag: bool,
1263    /// Specifies the value of the sample aspect ratio of the luma samples.
1264    /// Table E-1 shows the meaning of the code. When aspect_ratio_idc indicates
1265    /// Extended_SAR, the sample aspect ratio is represented by sar_width :
1266    /// sar_height. When the aspect_ratio_idc syntax element is not present,
1267    /// aspect_ratio_idc value shall be inferred to be equal to 0
1268    pub aspect_ratio_idc: u8,
1269
1270    /* if aspect_ratio_idc == 255 */
1271    /// Indicates the horizontal size of the sample aspect ratio (in arbitrary
1272    /// units)
1273    pub sar_width: u16,
1274    /// Indicates the vertical size of the sample aspect ratio (in the same
1275    /// arbitrary units as sar_width).
1276    pub sar_height: u16,
1277
1278    /// If true specifies that the overscan_appropriate_flag is present. Else,
1279    /// the preferred display method for the video signal is unspecified
1280    pub overscan_info_present_flag: bool,
1281    /* if overscan_info_present_flag */
1282    /// If true, indicates that the cropped decoded pictures output are suitable
1283    /// for display using overscan. Else, indicates that the cropped decoded
1284    /// pictures output contain visually important information in the entire
1285    /// region out to the edges of the cropping rectangle of the picture, such
1286    /// that the cropped decoded pictures output should not be displayed using
1287    /// overscan.
1288    pub overscan_appropriate_flag: bool,
1289
1290    /// Specifies that video_format, video_full_range_flag and
1291    /// colour_description_present_flag are present
1292    pub video_signal_type_present_flag: bool,
1293    /// Indicates the representation of the pictures as specified in Table E-2,
1294    /// before being coded in accordance with this Recommendation |
1295    /// International Standard. When the video_format syntax element is not
1296    /// present, video_format value shall be inferred to be equal to 5.
1297    pub video_format: u8,
1298    /// Indicates the black level and range of the luma and chroma signals as
1299    /// derived from E′Y, E′PB, and E′PR or E′ R, E′G, and E′B real-valued
1300    /// component signals.
1301    pub video_full_range_flag: bool,
1302    /// Specifies that colour_primaries, transfer_characteristics and
1303    /// matrix_coefficients are present.
1304    pub colour_description_present_flag: bool,
1305    /// Indicates the chromaticity coordinates of the source primaries as
1306    /// specified in Table E-3 in terms of the CIE 1931 definition of x and y as
1307    /// specified by ISO 11664-1.
1308    pub colour_primaries: u8,
1309    /// Retains same meaning as in the specification.
1310    pub transfer_characteristics: u8,
1311    /// Describes the matrix coefficients used in deriving luma and chroma
1312    /// signals from the green, blue, and red, or Y, Z, and X primaries, as
1313    /// specified in Table E-5.
1314    pub matrix_coefficients: u8,
1315
1316    /// Specifies that chroma_sample_loc_type_top_field and
1317    /// chroma_sample_loc_type_bottom_field are present
1318    pub chroma_loc_info_present_flag: bool,
1319    /// Specify the location of chroma samples. See the spec for more details.
1320    pub chroma_sample_loc_type_top_field: u8,
1321    /// Specify the location of chroma samples. See the spec for more details.
1322    pub chroma_sample_loc_type_bottom_field: u8,
1323
1324    /// Specifies that num_units_in_tick, time_scale and fixed_frame_rate_flag
1325    /// are present in the bitstream
1326    pub timing_info_present_flag: bool,
1327    /* if timing_info_present_flag */
1328    /// The number of time units of a clock operating at the frequency
1329    /// time_scale Hz that corresponds to one increment (called a clock tick) of
1330    /// a clock tick counter
1331    pub num_units_in_tick: u32,
1332    /// The number of time units that pass in one second. For example, a time
1333    /// coordinate system that measures time using a 27 MHz clock has a
1334    /// time_scale of 27 000 000. time_scale shall be greater than 0.
1335    pub time_scale: u32,
1336    /// Retains the same meaning as the specification.
1337    pub fixed_frame_rate_flag: bool,
1338
1339    /// Specifies that NAL HRD parameters (pertaining to Type II bitstream
1340    /// conformance) are present.
1341    pub nal_hrd_parameters_present_flag: bool,
1342    /* if nal_hrd_parameters_present_flag */
1343    /// The NAL HDR parameters
1344    pub nal_hrd_parameters: HrdParams,
1345    /// Specifies that VCL HRD parameters (pertaining to all bitstream
1346    /// conformance) are present.
1347    pub vcl_hrd_parameters_present_flag: bool,
1348    /* if vcl_hrd_parameters_present_flag */
1349    /// The VCL HRD parameters
1350    pub vcl_hrd_parameters: HrdParams,
1351
1352    /// Specifies the HRD operational mode as specified in Annex C.
1353    pub low_delay_hrd_flag: bool,
1354
1355    /// Specifies that picture timing SEI messages (clause D.2.3) are present
1356    /// that include the pic_struct syntax element.
1357    pub pic_struct_present_flag: bool,
1358
1359    /// Specifies that the following coded video sequence bitstream restriction
1360    /// parameters are present
1361    pub bitstream_restriction_flag: bool,
1362    /*  if bitstream_restriction_flag */
1363    /// If false, indicates that no sample outside the picture boundaries and no
1364    /// sample at a fractional sample position for which the sample value is
1365    /// derived using one or more samples outside the picture boundaries is used
1366    /// for inter prediction of any sample. If true, indicates that one or more
1367    /// samples outside picture boundaries may be used in inter prediction. When
1368    /// the motion_vectors_over_pic_boundaries_flag syntax element is not
1369    /// present, motion_vectors_over_pic_boundaries_flag value shall be inferred
1370    /// to be true.
1371    pub motion_vectors_over_pic_boundaries_flag: bool,
1372    /// Indicates a number of bytes not exceeded by the sum of the sizes of the
1373    /// VCL NAL units associated with any coded picture in the coded video
1374    /// sequence.
1375    pub max_bytes_per_pic_denom: u32,
1376    /// Indicates an upper bound for the number of coded bits of
1377    /// macroblock_layer( ) data for any macroblock in any picture of the coded
1378    /// video sequence
1379    pub max_bits_per_mb_denom: u32,
1380    /// Retains the same meaning as the specification.
1381    pub log2_max_mv_length_horizontal: u32,
1382    /// Retains the same meaning as the specification.
1383    pub log2_max_mv_length_vertical: u32,
1384    /// Indicates an upper bound for the number of frames buffers, in the
1385    /// decoded picture buffer (DPB), that are required for storing frames,
1386    /// complementary field pairs, and non-paired fields before output. It is a
1387    /// requirement of bitstream conformance that the maximum number of frames,
1388    /// complementary field pairs, or non-paired fields that precede any frame,
1389    /// complementary field pair, or non-paired field in the coded video
1390    /// sequence in decoding order and follow it in output order shall be less
1391    /// than or equal to max_num_reorder_frames. The value of
1392    /// max_num_reorder_frames shall be in the range of 0 to
1393    /// max_dec_frame_buffering, inclusive.
1394    ///
1395    /// When the max_num_reorder_frames syntax element is not present, the value
1396    /// of max_num_reorder_frames value shall be inferred as follows:
1397    /// If profile_idc is equal to 44, 86, 100, 110, 122, or 244 and
1398    /// constraint_set3_flag is equal to 1, the value of max_num_reorder_frames
1399    /// shall be inferred to be equal to 0.
1400    ///
1401    /// Otherwise (profile_idc is not equal to 44, 86, 100, 110, 122, or 244 or
1402    /// constraint_set3_flag is equal to 0), the value of max_num_reorder_frames
1403    /// shall be inferred to be equal to MaxDpbFrames.
1404    pub max_num_reorder_frames: u32,
1405    /// Specifies the required size of the HRD decoded picture buffer (DPB) in
1406    /// units of frame buffers. It is a requirement of bitstream conformance
1407    /// that the coded video sequence shall not require a decoded picture buffer
1408    /// with size of more than Max( 1, max_dec_frame_buffering ) frame buffers
1409    /// to enable the output of decoded pictures at the output times specified
1410    /// by dpb_output_delay of the picture timing SEI messages. The value of
1411    /// max_dec_frame_buffering shall be greater than or equal to
1412    /// max_num_ref_frames. An upper bound for the value of
1413    /// max_dec_frame_buffering is specified by the level limits in clauses
1414    /// A.3.1, A.3.2, G.10.2.1, and H.10.2.
1415    ///
1416    /// When the max_dec_frame_buffering syntax element is not present, the
1417    /// value of max_dec_frame_buffering shall be inferred as follows:
1418    ///
1419    /// If profile_idc is equal to 44, 86, 100, 110, 122, or 244 and
1420    /// constraint_set3_flag is equal to 1, the value of max_dec_frame_buffering
1421    /// shall be inferred to be equal to 0.
1422    ///
1423    /// Otherwise (profile_idc is not equal to 44, 86, 100, 110, 122, or 244 or
1424    /// constraint_set3_flag is equal to 0), the value of
1425    /// max_dec_frame_buffering shall be inferred to be equal to MaxDpbFrames.
1426    pub max_dec_frame_buffering: u32,
1427}
1428
1429impl Default for VuiParams {
1430    fn default() -> Self {
1431        Self {
1432            aspect_ratio_info_present_flag: Default::default(),
1433            aspect_ratio_idc: Default::default(),
1434            sar_width: Default::default(),
1435            sar_height: Default::default(),
1436            overscan_info_present_flag: Default::default(),
1437            overscan_appropriate_flag: Default::default(),
1438            video_signal_type_present_flag: Default::default(),
1439            video_format: 5,
1440            video_full_range_flag: Default::default(),
1441            colour_description_present_flag: Default::default(),
1442            colour_primaries: 2,
1443            transfer_characteristics: 2,
1444            matrix_coefficients: 2,
1445            chroma_loc_info_present_flag: Default::default(),
1446            chroma_sample_loc_type_top_field: Default::default(),
1447            chroma_sample_loc_type_bottom_field: Default::default(),
1448            timing_info_present_flag: Default::default(),
1449            num_units_in_tick: Default::default(),
1450            time_scale: Default::default(),
1451            fixed_frame_rate_flag: Default::default(),
1452            nal_hrd_parameters_present_flag: Default::default(),
1453            nal_hrd_parameters: Default::default(),
1454            vcl_hrd_parameters_present_flag: Default::default(),
1455            vcl_hrd_parameters: Default::default(),
1456            low_delay_hrd_flag: Default::default(),
1457            pic_struct_present_flag: Default::default(),
1458            bitstream_restriction_flag: Default::default(),
1459            motion_vectors_over_pic_boundaries_flag: Default::default(),
1460            max_bytes_per_pic_denom: Default::default(),
1461            max_bits_per_mb_denom: Default::default(),
1462            log2_max_mv_length_horizontal: Default::default(),
1463            log2_max_mv_length_vertical: Default::default(),
1464            max_num_reorder_frames: Default::default(),
1465            max_dec_frame_buffering: Default::default(),
1466        }
1467    }
1468}
1469
1470/// A H264 Picture Parameter Set. A syntax structure containing syntax elements
1471/// that apply to zero or more entire coded pictures as determined by the
1472/// `pic_parameter_set_id` syntax element found in each slice header.
1473#[derive(Debug, PartialEq, Eq)]
1474pub struct Pps {
1475    /// Identifies the picture parameter set that is referred to in the slice header.
1476    pub pic_parameter_set_id: u8,
1477
1478    /// Refers to the active sequence parameter set.
1479    pub seq_parameter_set_id: u8,
1480
1481    /// Selects the entropy decoding method to be applied for the syntax
1482    /// elements for which two descriptors appear in the syntax tables as
1483    /// follows: If `entropy_coding_mode_flag` is false, the method specified by
1484    /// the left descriptor in the syntax table is applied (Exp-Golomb coded,
1485    /// see clause 9.1 or CAVLC, see clause 9.2). Otherwise
1486    /// (`entropy_coding_mode_flag` is true), the method specified by the right
1487    /// descriptor in the syntax table is applied (CABAC, see clause 9.3).
1488    pub entropy_coding_mode_flag: bool,
1489
1490    /// If true, specifies that the syntax elements delta_pic_order_cnt_bottom
1491    /// (when `pic_order_cnt_type` is equal to 0) or `delta_pic_order_cnt[1]`
1492    /// (when `pic_order_cnt_type` is equal to 1), which are related to picture
1493    /// order counts for the bottom field of a coded frame, are present in the
1494    /// slice headers for coded frames as specified in clause 7.3.3. Otherwise,
1495    /// specifies that the syntax elements `delta_pic_order_cnt_bottom` and
1496    /// `delta_pic_order_cnt[1]` are not present in the slice headers.
1497    pub bottom_field_pic_order_in_frame_present_flag: bool,
1498
1499    /// Plus 1 specifies the number of slice groups for a picture. When
1500    /// `num_slice_groups_minus1` is equal to 0, all slices of the picture
1501    /// belong to the same slice group. The allowed range of
1502    /// `num_slice_groups_minus1` is specified in Annex A.
1503    pub num_slice_groups_minus1: u32,
1504
1505    /// Specifies how `num_ref_idx_l0_active_minus1` is inferred for P, SP, and
1506    /// B slices with `num_ref_idx_active_override_flag` not set.
1507    pub num_ref_idx_l0_default_active_minus1: u8,
1508
1509    /// Specifies how `num_ref_idx_l1_active_minus1` is inferred for B slices
1510    /// with `num_ref_idx_active_override_flag` not set.
1511    pub num_ref_idx_l1_default_active_minus1: u8,
1512
1513    /// If not set, specifies that the default weighted prediction shall be
1514    /// applied to P and SP slices. If set, specifies that explicit weighted
1515    /// prediction shall be applied to P and SP slices.
1516    pub weighted_pred_flag: bool,
1517
1518    /// `weighted_bipred_idc` equal to 0 specifies that the default weighted
1519    /// prediction shall be applied to B slices. `weighted_bipred_idc` equal to
1520    /// 1 specifies that explicit weighted prediction shall be applied to B
1521    /// slices. `weighted_bipred_idc` equal to 2 specifies that implicit
1522    /// weighted prediction shall be applied to B slices
1523    pub weighted_bipred_idc: u8,
1524
1525    /// Specifies the initial value minus 26 of SliceQPY for each slice. The
1526    /// initial value is modified at the slice layer when a non-zero value of
1527    /// `slice_qp_delta` is decoded, and is modified further when a non-zero
1528    /// value of `mb_qp_delta` is decoded at the macroblock layer.
1529    pub pic_init_qp_minus26: i8,
1530
1531    /// Specifies the initial value minus 26 of SliceQSY for all macroblocks in
1532    /// SP or SI slices. The initial value is modified at the slice layer when a
1533    /// non-zero value of `slice_qs_delta` is decoded.
1534    pub pic_init_qs_minus26: i8,
1535
1536    /// Specifies the offset that shall be added to QP Y and QSY for addressing
1537    /// the table of QPC values for the Cb chroma component.
1538    pub chroma_qp_index_offset: i8,
1539
1540    /// If set, specifies that a set of syntax elements controlling the
1541    /// characteristics of the deblocking filter is present in the slice header.
1542    /// If not set, specifies that the set of syntax elements controlling the
1543    /// characteristics of the deblocking filter is not present in the slice
1544    /// headers and their inferred values are in effect.
1545    pub deblocking_filter_control_present_flag: bool,
1546
1547    /// If not set, specifies that intra prediction allows usage of residual
1548    /// data and decoded samples of neighbouring macroblocks coded using Inter
1549    /// macroblock prediction modes for the prediction of macroblocks coded
1550    /// using Intra macroblock prediction modes. If set, specifies constrained
1551    /// intra prediction, in which case prediction of macroblocks coded using
1552    /// Intra macroblock prediction modes only uses residual data and decoded
1553    /// samples from I or SI macroblock types.
1554    pub constrained_intra_pred_flag: bool,
1555
1556    /// If not set, specifies that the `redundant_pic_cnt` syntax element is not
1557    /// present in slice headers, coded slice data partition B NAL units, and
1558    /// coded slice data partition C NAL units that refer (either directly or by
1559    /// association with a corresponding coded slice data partition A NAL unit)
1560    /// to the picture parameter set. If set, specifies that the
1561    /// `redundant_pic_cnt` syntax element is present in all slice headers,
1562    /// coded slice data partition B NAL units, and coded slice data partition C
1563    /// NAL units that refer (either directly or by association with a
1564    /// corresponding coded slice data partition A NAL unit) to the picture
1565    /// parameter set.
1566    pub redundant_pic_cnt_present_flag: bool,
1567
1568    /// If set, specifies that the 8x8 transform decoding process may be in use
1569    /// (see clause 8.5). If not set, specifies that the 8x8 transform decoding
1570    /// process is not in use.
1571    pub transform_8x8_mode_flag: bool,
1572
1573    ///  If set, specifies that parameters are present to modify the scaling
1574    ///  lists specified in the sequence parameter set. If not set, specifies
1575    ///  that the scaling lists used for the picture shall be inferred to be
1576    ///  equal to those specified by the sequence parameter set.
1577    pub pic_scaling_matrix_present_flag: bool,
1578
1579    /// 4x4 Scaling list as read with 7.3.2.1.1.1
1580    pub scaling_lists_4x4: [[u8; 16]; 6],
1581    /// 8x8 Scaling list as read with 7.3.2.1.1.1
1582    pub scaling_lists_8x8: [[u8; 64]; 6],
1583
1584    /// Specifies the offset that shall be added to QPY and QSY for addressing
1585    /// the table of QPC values for the Cr chroma component. When
1586    /// `second_chroma_qp_index_offset` is not present, it shall be inferred to be
1587    /// equal to `chroma_qp_index_offset`.
1588    pub second_chroma_qp_index_offset: i8,
1589
1590    /// The SPS referenced by this PPS.
1591    pub sps: Rc<Sps>,
1592}
1593
1594pub struct PpsBuilder(Pps);
1595
1596impl PpsBuilder {
1597    pub fn new(sps: Rc<Sps>) -> Self {
1598        PpsBuilder(Pps {
1599            pic_parameter_set_id: 0,
1600            seq_parameter_set_id: sps.seq_parameter_set_id,
1601            entropy_coding_mode_flag: false,
1602            bottom_field_pic_order_in_frame_present_flag: false,
1603            num_slice_groups_minus1: 0,
1604            num_ref_idx_l0_default_active_minus1: 0,
1605            num_ref_idx_l1_default_active_minus1: 0,
1606            weighted_pred_flag: false,
1607            weighted_bipred_idc: 0,
1608            pic_init_qp_minus26: 0,
1609            pic_init_qs_minus26: 0,
1610            chroma_qp_index_offset: 0,
1611            deblocking_filter_control_present_flag: false,
1612            constrained_intra_pred_flag: false,
1613            redundant_pic_cnt_present_flag: false,
1614            transform_8x8_mode_flag: false,
1615            pic_scaling_matrix_present_flag: false,
1616            scaling_lists_4x4: [[0; 16]; 6],
1617            scaling_lists_8x8: [[0; 64]; 6],
1618            second_chroma_qp_index_offset: 0,
1619            sps,
1620        })
1621    }
1622
1623    pub fn pic_parameter_set_id(mut self, value: u8) -> Self {
1624        self.0.pic_parameter_set_id = value;
1625        self
1626    }
1627
1628    pub fn pic_init_qp_minus26(mut self, value: i8) -> Self {
1629        self.0.pic_init_qp_minus26 = value;
1630        self
1631    }
1632
1633    pub fn pic_init_qp(self, value: u8) -> Self {
1634        self.pic_init_qp_minus26(value as i8 - 26)
1635    }
1636
1637    pub fn deblocking_filter_control_present_flag(mut self, value: bool) -> Self {
1638        self.0.deblocking_filter_control_present_flag = value;
1639        self
1640    }
1641
1642    pub fn num_ref_idx_l0_default_active_minus1(mut self, value: u8) -> Self {
1643        self.0.num_ref_idx_l0_default_active_minus1 = value;
1644        self
1645    }
1646
1647    pub fn num_ref_idx_l0_default_active(self, value: u8) -> Self {
1648        self.num_ref_idx_l0_default_active_minus1(value - 1)
1649    }
1650
1651    pub fn num_ref_idx_l1_default_active_minus1(mut self, value: u8) -> Self {
1652        self.0.num_ref_idx_l1_default_active_minus1 = value;
1653        self
1654    }
1655
1656    pub fn num_ref_idx_l1_default_active(self, value: u8) -> Self {
1657        self.num_ref_idx_l1_default_active_minus1(value - 1)
1658    }
1659
1660    pub fn build(self) -> Rc<Pps> {
1661        Rc::new(self.0)
1662    }
1663}
1664
1665#[derive(Debug, Default)]
1666pub struct Parser {
1667    active_spses: BTreeMap<u8, Rc<Sps>>,
1668    active_ppses: BTreeMap<u8, Rc<Pps>>,
1669}
1670
1671impl Parser {
1672    fn fill_default_scaling_list_4x4(scaling_list4x4: &mut [u8; 16], i: usize) {
1673        // See table 7.2 in the spec.
1674        assert!(i < 6);
1675        if i < 3 {
1676            *scaling_list4x4 = DEFAULT_4X4_INTRA;
1677        } else if i < 6 {
1678            *scaling_list4x4 = DEFAULT_4X4_INTER;
1679        }
1680    }
1681
1682    fn fill_default_scaling_list_8x8(scaling_list8x8: &mut [u8; 64], i: usize) {
1683        assert!(i < 6);
1684        if i % 2 == 0 {
1685            *scaling_list8x8 = DEFAULT_8X8_INTRA;
1686        } else {
1687            *scaling_list8x8 = DEFAULT_8X8_INTER;
1688        }
1689    }
1690
1691    fn fill_fallback_scaling_list_4x4(
1692        scaling_list4x4: &mut [[u8; 16]; 6],
1693        i: usize,
1694        default_scaling_list_intra: &[u8; 16],
1695        default_scaling_list_inter: &[u8; 16],
1696    ) {
1697        // See table 7.2 in the spec.
1698        scaling_list4x4[i] = match i {
1699            0 => *default_scaling_list_intra,
1700            1 => scaling_list4x4[0],
1701            2 => scaling_list4x4[1],
1702            3 => *default_scaling_list_inter,
1703            4 => scaling_list4x4[3],
1704            5 => scaling_list4x4[4],
1705            _ => panic!("Unexpected value {}", i),
1706        }
1707    }
1708
1709    fn fill_fallback_scaling_list_8x8(
1710        scaling_list8x8: &mut [[u8; 64]; 6],
1711        i: usize,
1712        default_scaling_list_intra: &[u8; 64],
1713        default_scaling_list_inter: &[u8; 64],
1714    ) {
1715        // See table 7.2 in the spec.
1716        scaling_list8x8[i] = match i {
1717            0 => *default_scaling_list_intra,
1718            1 => *default_scaling_list_inter,
1719            2 => scaling_list8x8[0],
1720            3 => scaling_list8x8[1],
1721            4 => scaling_list8x8[2],
1722            5 => scaling_list8x8[3],
1723            _ => panic!("Unexpected value {}", i),
1724        }
1725    }
1726
1727    fn fill_scaling_list_flat(
1728        scaling_list4x4: &mut [[u8; 16]; 6],
1729        scaling_list8x8: &mut [[u8; 64]; 6],
1730    ) {
1731        // (7-8) in the spec.
1732        for outer in scaling_list4x4 {
1733            for inner in outer {
1734                *inner = 16;
1735            }
1736        }
1737
1738        // (7-9) in the spec.
1739        for outer in scaling_list8x8 {
1740            for inner in outer {
1741                *inner = 16;
1742            }
1743        }
1744    }
1745
1746    fn parse_scaling_list<U: AsMut<[u8]>>(
1747        r: &mut BitReader,
1748        scaling_list: &mut U,
1749        use_default: &mut bool,
1750    ) -> Result<(), String> {
1751        // 7.3.2.1.1.1
1752        let mut last_scale = 8u8;
1753        let mut next_scale = 8u8;
1754
1755        for j in 0..scaling_list.as_mut().len() {
1756            if next_scale != 0 {
1757                let delta_scale = r.read_se::<i32>()?;
1758                next_scale = ((last_scale as i32 + delta_scale + 256) % 256) as u8;
1759                *use_default = j == 0 && next_scale == 0;
1760                if *use_default {
1761                    return Ok(());
1762                }
1763            }
1764
1765            scaling_list.as_mut()[j] = if next_scale == 0 { last_scale } else { next_scale };
1766
1767            last_scale = scaling_list.as_mut()[j];
1768        }
1769
1770        Ok(())
1771    }
1772
1773    fn parse_sps_scaling_lists(r: &mut BitReader, sps: &mut Sps) -> Result<(), String> {
1774        let scaling_lists4x4 = &mut sps.scaling_lists_4x4;
1775        let scaling_lisst8x8 = &mut sps.scaling_lists_8x8;
1776
1777        // Parse scaling_list4x4
1778        for i in 0..6 {
1779            let seq_scaling_list_present_flag = r.read_bit()?;
1780            if seq_scaling_list_present_flag {
1781                let mut use_default = false;
1782
1783                Parser::parse_scaling_list(r, &mut scaling_lists4x4[i], &mut use_default)?;
1784
1785                if use_default {
1786                    Parser::fill_default_scaling_list_4x4(&mut scaling_lists4x4[i], i);
1787                }
1788            } else {
1789                Parser::fill_fallback_scaling_list_4x4(
1790                    scaling_lists4x4,
1791                    i,
1792                    &DEFAULT_4X4_INTRA,
1793                    &DEFAULT_4X4_INTER,
1794                );
1795            }
1796        }
1797
1798        // Parse scaling_list8x8
1799        let num_8x8 = if sps.chroma_format_idc != 3 { 2 } else { 6 };
1800        for i in 0..num_8x8 {
1801            let seq_scaling_list_present_flag = r.read_bit()?;
1802            if seq_scaling_list_present_flag {
1803                let mut use_default = false;
1804                Parser::parse_scaling_list(r, &mut scaling_lisst8x8[i], &mut use_default)?;
1805
1806                if use_default {
1807                    Parser::fill_default_scaling_list_8x8(&mut scaling_lisst8x8[i], i);
1808                }
1809            } else {
1810                Parser::fill_fallback_scaling_list_8x8(
1811                    scaling_lisst8x8,
1812                    i,
1813                    &DEFAULT_8X8_INTRA,
1814                    &DEFAULT_8X8_INTER,
1815                );
1816            }
1817        }
1818        Ok(())
1819    }
1820
1821    fn parse_pps_scaling_lists(r: &mut BitReader, pps: &mut Pps, sps: &Sps) -> Result<(), String> {
1822        let scaling_lists4x4 = &mut pps.scaling_lists_4x4;
1823        let scaling_lists8x8 = &mut pps.scaling_lists_8x8;
1824
1825        for i in 0..6 {
1826            let pic_scaling_list_present_flag = r.read_bit()?;
1827            if pic_scaling_list_present_flag {
1828                let mut use_default = false;
1829
1830                Parser::parse_scaling_list(r, &mut scaling_lists4x4[i], &mut use_default)?;
1831
1832                if use_default {
1833                    Parser::fill_default_scaling_list_4x4(&mut scaling_lists4x4[i], i);
1834                }
1835            } else if !sps.seq_scaling_matrix_present_flag {
1836                // Table 7-2: Fallback rule A
1837                Parser::fill_fallback_scaling_list_4x4(
1838                    scaling_lists4x4,
1839                    i,
1840                    &DEFAULT_4X4_INTRA,
1841                    &DEFAULT_4X4_INTER,
1842                );
1843            } else {
1844                // Table 7-2: Fallback rule B
1845                Parser::fill_fallback_scaling_list_4x4(
1846                    scaling_lists4x4,
1847                    i,
1848                    &sps.scaling_lists_4x4[0],
1849                    &sps.scaling_lists_4x4[3],
1850                );
1851            }
1852        }
1853
1854        if pps.transform_8x8_mode_flag {
1855            let num8x8 = if sps.chroma_format_idc != 3 { 2 } else { 6 };
1856
1857            for i in 0..num8x8 {
1858                let pic_scaling_list_present_flag = r.read_bit()?;
1859                if pic_scaling_list_present_flag {
1860                    let mut use_default = false;
1861
1862                    Parser::parse_scaling_list(r, &mut scaling_lists8x8[i], &mut use_default)?;
1863
1864                    if use_default {
1865                        Parser::fill_default_scaling_list_8x8(&mut scaling_lists8x8[i], i);
1866                    }
1867                } else if !sps.seq_scaling_matrix_present_flag {
1868                    // Table 7-2: Fallback rule A
1869                    Parser::fill_fallback_scaling_list_8x8(
1870                        scaling_lists8x8,
1871                        i,
1872                        &DEFAULT_8X8_INTRA,
1873                        &DEFAULT_8X8_INTER,
1874                    );
1875                } else {
1876                    // Table 7-2: Fallback rule B
1877                    Parser::fill_fallback_scaling_list_8x8(
1878                        scaling_lists8x8,
1879                        i,
1880                        &sps.scaling_lists_8x8[0],
1881                        &sps.scaling_lists_8x8[1],
1882                    );
1883                }
1884            }
1885        }
1886
1887        Ok(())
1888    }
1889
1890    fn parse_hrd(r: &mut BitReader, hrd: &mut HrdParams) -> Result<(), String> {
1891        hrd.cpb_cnt_minus1 = r.read_ue_max(31)?;
1892        hrd.bit_rate_scale = r.read_bits(4)?;
1893        hrd.cpb_size_scale = r.read_bits(4)?;
1894
1895        for sched_sel_idx in 0..=usize::from(hrd.cpb_cnt_minus1) {
1896            hrd.bit_rate_value_minus1[sched_sel_idx] = r.read_ue()?;
1897            hrd.cpb_size_value_minus1[sched_sel_idx] = r.read_ue()?;
1898            hrd.cbr_flag[sched_sel_idx] = r.read_bit()?;
1899        }
1900
1901        hrd.initial_cpb_removal_delay_length_minus1 = r.read_bits(5)?;
1902        hrd.cpb_removal_delay_length_minus1 = r.read_bits(5)?;
1903        hrd.dpb_output_delay_length_minus1 = r.read_bits(5)?;
1904        hrd.time_offset_length = r.read_bits(5)?;
1905        Ok(())
1906    }
1907
1908    fn parse_vui(r: &mut BitReader, sps: &mut Sps) -> Result<(), String> {
1909        let vui = &mut sps.vui_parameters;
1910
1911        vui.aspect_ratio_info_present_flag = r.read_bit()?;
1912        if vui.aspect_ratio_info_present_flag {
1913            vui.aspect_ratio_idc = r.read_bits(8)?;
1914            if vui.aspect_ratio_idc == 255 {
1915                vui.sar_width = r.read_bits(16)?;
1916                vui.sar_height = r.read_bits(16)?;
1917            }
1918        }
1919
1920        vui.overscan_info_present_flag = r.read_bit()?;
1921        if vui.overscan_info_present_flag {
1922            vui.overscan_appropriate_flag = r.read_bit()?;
1923        }
1924
1925        vui.video_signal_type_present_flag = r.read_bit()?;
1926        if vui.video_signal_type_present_flag {
1927            vui.video_format = r.read_bits(3)?;
1928            vui.video_full_range_flag = r.read_bit()?;
1929            vui.colour_description_present_flag = r.read_bit()?;
1930            if vui.colour_description_present_flag {
1931                vui.colour_primaries = r.read_bits(8)?;
1932                vui.transfer_characteristics = r.read_bits(8)?;
1933                vui.matrix_coefficients = r.read_bits(8)?;
1934            }
1935        }
1936
1937        vui.chroma_loc_info_present_flag = r.read_bit()?;
1938        if vui.chroma_loc_info_present_flag {
1939            vui.chroma_sample_loc_type_top_field = r.read_ue_max(5)?;
1940            vui.chroma_sample_loc_type_bottom_field = r.read_ue_max(5)?;
1941        }
1942
1943        vui.timing_info_present_flag = r.read_bit()?;
1944        if vui.timing_info_present_flag {
1945            vui.num_units_in_tick = r.read_bits::<u32>(31)? << 1;
1946            vui.num_units_in_tick |= r.read_bit()? as u32;
1947            if vui.num_units_in_tick == 0 {
1948                return Err("num_units_in_tick == 0, which is not allowed by E.2.1".into());
1949            }
1950
1951            vui.time_scale = r.read_bits::<u32>(31)? << 1;
1952            vui.time_scale |= r.read_bit()? as u32;
1953            if vui.time_scale == 0 {
1954                return Err("time_scale == 0, which is not allowed by E.2.1".into());
1955            }
1956
1957            vui.fixed_frame_rate_flag = r.read_bit()?;
1958        }
1959
1960        vui.nal_hrd_parameters_present_flag = r.read_bit()?;
1961        if vui.nal_hrd_parameters_present_flag {
1962            Parser::parse_hrd(r, &mut vui.nal_hrd_parameters)?;
1963        }
1964
1965        vui.vcl_hrd_parameters_present_flag = r.read_bit()?;
1966        if vui.vcl_hrd_parameters_present_flag {
1967            Parser::parse_hrd(r, &mut vui.vcl_hrd_parameters)?;
1968        }
1969
1970        if vui.nal_hrd_parameters_present_flag || vui.vcl_hrd_parameters_present_flag {
1971            vui.low_delay_hrd_flag = r.read_bit()?;
1972        }
1973
1974        vui.pic_struct_present_flag = r.read_bit()?;
1975        vui.bitstream_restriction_flag = r.read_bit()?;
1976
1977        if vui.bitstream_restriction_flag {
1978            vui.motion_vectors_over_pic_boundaries_flag = r.read_bit()?;
1979            vui.max_bytes_per_pic_denom = r.read_ue()?;
1980            vui.max_bits_per_mb_denom = r.read_ue_max(16)?;
1981            vui.log2_max_mv_length_horizontal = r.read_ue_max(16)?;
1982            vui.log2_max_mv_length_vertical = r.read_ue_max(16)?;
1983            vui.max_num_reorder_frames = r.read_ue()?;
1984            vui.max_dec_frame_buffering = r.read_ue()?;
1985        }
1986
1987        Ok(())
1988    }
1989
1990    /// Parse a SPS and add it to the list of active SPSes.
1991    ///
1992    /// Returns a reference to the new SPS.
1993    pub fn parse_sps(&mut self, nalu: &Nalu) -> Result<&Rc<Sps>, String> {
1994        if !matches!(nalu.header.type_, NaluType::Sps) {
1995            return Err(format!(
1996                "Invalid NALU type, expected {:?}, got {:?}",
1997                NaluType::Sps,
1998                nalu.header.type_
1999            ));
2000        }
2001
2002        let data = nalu.as_ref();
2003        // Skip the header
2004        let mut r = BitReader::new(&data[nalu.header.len()..], true);
2005        let mut sps = Sps {
2006            profile_idc: r.read_bits(8)?,
2007            constraint_set0_flag: r.read_bit()?,
2008            constraint_set1_flag: r.read_bit()?,
2009            constraint_set2_flag: r.read_bit()?,
2010            constraint_set3_flag: r.read_bit()?,
2011            constraint_set4_flag: r.read_bit()?,
2012            constraint_set5_flag: r.read_bit()?,
2013            ..Default::default()
2014        };
2015
2016        // skip reserved_zero_2bits
2017        r.skip_bits(2)?;
2018
2019        let level: u8 = r.read_bits(8)?;
2020        sps.level_idc = Level::try_from(level)?;
2021        sps.seq_parameter_set_id = r.read_ue_max(31)?;
2022
2023        if sps.profile_idc == 100
2024            || sps.profile_idc == 110
2025            || sps.profile_idc == 122
2026            || sps.profile_idc == 244
2027            || sps.profile_idc == 44
2028            || sps.profile_idc == 83
2029            || sps.profile_idc == 86
2030            || sps.profile_idc == 118
2031            || sps.profile_idc == 128
2032            || sps.profile_idc == 138
2033            || sps.profile_idc == 139
2034            || sps.profile_idc == 134
2035            || sps.profile_idc == 135
2036        {
2037            sps.chroma_format_idc = r.read_ue_max(3)?;
2038            if sps.chroma_format_idc == 3 {
2039                sps.separate_colour_plane_flag = r.read_bit()?;
2040            }
2041
2042            sps.bit_depth_luma_minus8 = r.read_ue_max(6)?;
2043            sps.bit_depth_chroma_minus8 = r.read_ue_max(6)?;
2044            sps.qpprime_y_zero_transform_bypass_flag = r.read_bit()?;
2045            sps.seq_scaling_matrix_present_flag = r.read_bit()?;
2046
2047            if sps.seq_scaling_matrix_present_flag {
2048                Parser::parse_sps_scaling_lists(&mut r, &mut sps)?;
2049            } else {
2050                Parser::fill_scaling_list_flat(
2051                    &mut sps.scaling_lists_4x4,
2052                    &mut sps.scaling_lists_8x8,
2053                );
2054            }
2055        } else {
2056            sps.chroma_format_idc = 1;
2057            Parser::fill_scaling_list_flat(&mut sps.scaling_lists_4x4, &mut sps.scaling_lists_8x8);
2058        }
2059
2060        sps.log2_max_frame_num_minus4 = r.read_ue_max(12)?;
2061
2062        sps.pic_order_cnt_type = r.read_ue_max(2)?;
2063
2064        if sps.pic_order_cnt_type == 0 {
2065            sps.log2_max_pic_order_cnt_lsb_minus4 = r.read_ue_max(12)?;
2066            sps.expected_delta_per_pic_order_cnt_cycle = 0;
2067        } else if sps.pic_order_cnt_type == 1 {
2068            sps.delta_pic_order_always_zero_flag = r.read_bit()?;
2069            sps.offset_for_non_ref_pic = r.read_se()?;
2070            sps.offset_for_top_to_bottom_field = r.read_se()?;
2071            sps.num_ref_frames_in_pic_order_cnt_cycle = r.read_ue_max(254)?;
2072
2073            let mut offset_acc = 0;
2074            for i in 0..usize::from(sps.num_ref_frames_in_pic_order_cnt_cycle) {
2075                sps.offset_for_ref_frame[i] = r.read_se()?;
2076
2077                // (7-12) in the spec.
2078                offset_acc += sps.offset_for_ref_frame[i];
2079            }
2080
2081            sps.expected_delta_per_pic_order_cnt_cycle = offset_acc;
2082        }
2083
2084        sps.max_num_ref_frames = r.read_ue_max(DPB_MAX_SIZE as u32)?;
2085        sps.gaps_in_frame_num_value_allowed_flag = r.read_bit()?;
2086        sps.pic_width_in_mbs_minus1 = r.read_ue()?;
2087        sps.pic_height_in_map_units_minus1 = r.read_ue()?;
2088        sps.frame_mbs_only_flag = r.read_bit()?;
2089
2090        if !sps.frame_mbs_only_flag {
2091            sps.mb_adaptive_frame_field_flag = r.read_bit()?;
2092        }
2093
2094        sps.direct_8x8_inference_flag = r.read_bit()?;
2095        sps.frame_cropping_flag = r.read_bit()?;
2096
2097        if sps.frame_cropping_flag {
2098            sps.frame_crop_left_offset = r.read_ue()?;
2099            sps.frame_crop_right_offset = r.read_ue()?;
2100            sps.frame_crop_top_offset = r.read_ue()?;
2101            sps.frame_crop_bottom_offset = r.read_ue()?;
2102
2103            // Validate that cropping info is valid.
2104            let (crop_unit_x, crop_unit_y) = sps.crop_unit_x_y();
2105
2106            let _ = sps
2107                .frame_crop_left_offset
2108                .checked_add(sps.frame_crop_right_offset)
2109                .and_then(|r| r.checked_mul(crop_unit_x))
2110                .and_then(|r| sps.width().checked_sub(r))
2111                .ok_or::<String>("Invalid frame crop width".into())?;
2112
2113            let _ = sps
2114                .frame_crop_top_offset
2115                .checked_add(sps.frame_crop_bottom_offset)
2116                .and_then(|r| r.checked_mul(crop_unit_y))
2117                .and_then(|r| sps.height().checked_sub(r))
2118                .ok_or::<String>("invalid frame crop height".into())?;
2119        }
2120
2121        sps.vui_parameters_present_flag = r.read_bit()?;
2122        if sps.vui_parameters_present_flag {
2123            Parser::parse_vui(&mut r, &mut sps)?;
2124        }
2125
2126        let key = sps.seq_parameter_set_id;
2127
2128        if self.active_spses.keys().len() >= MAX_SPS_COUNT as usize {
2129            return Err("Broken data: Number of active SPSs > MAX_SPS_COUNT".into());
2130        }
2131
2132        let sps = Rc::new(sps);
2133        self.active_spses.remove(&key);
2134        Ok(self.active_spses.entry(key).or_insert(sps))
2135    }
2136
2137    pub fn parse_pps(&mut self, nalu: &Nalu) -> Result<&Pps, String> {
2138        if !matches!(nalu.header.type_, NaluType::Pps) {
2139            return Err(format!(
2140                "Invalid NALU type, expected {:?}, got {:?}",
2141                NaluType::Pps,
2142                nalu.header.type_
2143            ));
2144        }
2145
2146        let data = nalu.as_ref();
2147        // Skip the header
2148        let mut r = BitReader::new(&data[nalu.header.len()..], true);
2149        let pic_parameter_set_id = r.read_ue_max(MAX_PPS_COUNT as u32 - 1)?;
2150        let seq_parameter_set_id = r.read_ue_max(MAX_SPS_COUNT as u32 - 1)?;
2151        let sps = self.get_sps(seq_parameter_set_id).ok_or::<String>(format!(
2152            "Could not get SPS for seq_parameter_set_id {}",
2153            seq_parameter_set_id
2154        ))?;
2155        let mut pps = Pps {
2156            pic_parameter_set_id,
2157            seq_parameter_set_id,
2158            sps: Rc::clone(sps),
2159            scaling_lists_4x4: [[0; 16]; 6],
2160            scaling_lists_8x8: [[0; 64]; 6],
2161            entropy_coding_mode_flag: Default::default(),
2162            bottom_field_pic_order_in_frame_present_flag: Default::default(),
2163            num_slice_groups_minus1: Default::default(),
2164            num_ref_idx_l0_default_active_minus1: Default::default(),
2165            num_ref_idx_l1_default_active_minus1: Default::default(),
2166            weighted_pred_flag: Default::default(),
2167            weighted_bipred_idc: Default::default(),
2168            pic_init_qp_minus26: Default::default(),
2169            pic_init_qs_minus26: Default::default(),
2170            chroma_qp_index_offset: Default::default(),
2171            deblocking_filter_control_present_flag: Default::default(),
2172            constrained_intra_pred_flag: Default::default(),
2173            redundant_pic_cnt_present_flag: Default::default(),
2174            transform_8x8_mode_flag: Default::default(),
2175            second_chroma_qp_index_offset: Default::default(),
2176            pic_scaling_matrix_present_flag: Default::default(),
2177        };
2178
2179        pps.entropy_coding_mode_flag = r.read_bit()?;
2180        pps.bottom_field_pic_order_in_frame_present_flag = r.read_bit()?;
2181        pps.num_slice_groups_minus1 = r.read_ue_max(7)?;
2182
2183        if pps.num_slice_groups_minus1 > 0 {
2184            return Err("Stream contain unsupported/unimplemented NALs".into());
2185        }
2186
2187        pps.num_ref_idx_l0_default_active_minus1 = r.read_ue_max(31)?;
2188        pps.num_ref_idx_l1_default_active_minus1 = r.read_ue_max(31)?;
2189
2190        pps.weighted_pred_flag = r.read_bit()?;
2191        pps.weighted_bipred_idc = r.read_bits(2)?;
2192
2193        let qp_bd_offset_y = i32::from(6 * (sps.bit_depth_luma_minus8));
2194        pps.pic_init_qp_minus26 = r.read_se_bounded(-(26 + qp_bd_offset_y), 25)?;
2195        pps.pic_init_qs_minus26 = r.read_se_bounded(-26, 25)?;
2196
2197        pps.chroma_qp_index_offset = r.read_se_bounded(-12, 12)?;
2198
2199        // When second_chroma_qp_index_offset is not present, it shall be
2200        // inferred to be equal to chroma_qp_index_offset.
2201        pps.second_chroma_qp_index_offset = pps.chroma_qp_index_offset;
2202
2203        pps.deblocking_filter_control_present_flag = r.read_bit()?;
2204        pps.constrained_intra_pred_flag = r.read_bit()?;
2205        pps.redundant_pic_cnt_present_flag = r.read_bit()?;
2206
2207        if r.has_more_rsbp_data() {
2208            pps.transform_8x8_mode_flag = r.read_bit()?;
2209            pps.pic_scaling_matrix_present_flag = r.read_bit()?;
2210
2211            if pps.pic_scaling_matrix_present_flag {
2212                Parser::parse_pps_scaling_lists(&mut r, &mut pps, sps)?;
2213            }
2214
2215            pps.second_chroma_qp_index_offset = r.read_se()?;
2216        }
2217
2218        if !pps.pic_scaling_matrix_present_flag {
2219            // If not set, specifies that the scaling lists used for the picture
2220            // shall be inferred to be equal to those specified by the sequence
2221            // parameter set. When pic_scaling_matrix_present_flag is not
2222            // present, it shall be inferred to be not set.
2223            pps.scaling_lists_4x4 = sps.scaling_lists_4x4;
2224            pps.scaling_lists_8x8 = sps.scaling_lists_8x8;
2225        }
2226
2227        let key = pps.pic_parameter_set_id;
2228
2229        if self.active_ppses.keys().len() >= MAX_PPS_COUNT as usize {
2230            return Err("Broken Data: number of active PPSs > MAX_PPS_COUNT".into());
2231        }
2232
2233        let pps = Rc::new(pps);
2234        self.active_ppses.remove(&key);
2235        Ok(self.active_ppses.entry(key).or_insert(pps))
2236    }
2237
2238    fn parse_ref_pic_list_modification(
2239        r: &mut BitReader,
2240        num_ref_idx_active_minus1: u8,
2241        ref_list_mods: &mut Vec<RefPicListModification>,
2242    ) -> Result<(), String> {
2243        if num_ref_idx_active_minus1 >= 32 {
2244            return Err("Broken Data: num_ref_idx_active_minus1 >= 32".into());
2245        }
2246
2247        loop {
2248            let mut pic_num_mod = RefPicListModification {
2249                modification_of_pic_nums_idc: r.read_ue_max(3)?,
2250                ..Default::default()
2251            };
2252
2253            match pic_num_mod.modification_of_pic_nums_idc {
2254                0 | 1 => {
2255                    pic_num_mod.abs_diff_pic_num_minus1 = r.read_ue()?;
2256                }
2257
2258                2 => {
2259                    pic_num_mod.long_term_pic_num = r.read_ue()?;
2260                }
2261
2262                3 => {
2263                    ref_list_mods.push(pic_num_mod);
2264                    break;
2265                }
2266
2267                _ => return Err("Broken Data: modification_of_pic_nums_idc > 3".into()),
2268            }
2269
2270            ref_list_mods.push(pic_num_mod);
2271        }
2272
2273        Ok(())
2274    }
2275
2276    fn parse_ref_pic_list_modifications(
2277        r: &mut BitReader,
2278        header: &mut SliceHeader,
2279    ) -> Result<(), String> {
2280        if !header.slice_type.is_i() && !header.slice_type.is_si() {
2281            header.ref_pic_list_modification_flag_l0 = r.read_bit()?;
2282            if header.ref_pic_list_modification_flag_l0 {
2283                Parser::parse_ref_pic_list_modification(
2284                    r,
2285                    header.num_ref_idx_l0_active_minus1,
2286                    &mut header.ref_pic_list_modification_l0,
2287                )?;
2288            }
2289        }
2290
2291        if header.slice_type.is_b() {
2292            header.ref_pic_list_modification_flag_l1 = r.read_bit()?;
2293            if header.ref_pic_list_modification_flag_l1 {
2294                Parser::parse_ref_pic_list_modification(
2295                    r,
2296                    header.num_ref_idx_l1_active_minus1,
2297                    &mut header.ref_pic_list_modification_l1,
2298                )?;
2299            }
2300        }
2301
2302        Ok(())
2303    }
2304
2305    fn parse_pred_weight_table(
2306        r: &mut BitReader,
2307        sps: &Sps,
2308        header: &mut SliceHeader,
2309    ) -> Result<(), String> {
2310        let pt = &mut header.pred_weight_table;
2311        pt.luma_log2_weight_denom = r.read_ue_max(7)?;
2312
2313        // When luma_weight_l0_flag is equal to 0, luma_weight_l0[i] shall be
2314        // inferred to be equal to 2 ^ luma_log2_weight_denom for
2315        // RefPicList0[i].
2316        let default_luma_weight = 1 << pt.luma_log2_weight_denom;
2317        for i in 0..=header.num_ref_idx_l0_active_minus1 {
2318            pt.luma_weight_l0[usize::from(i)] = default_luma_weight;
2319        }
2320
2321        // When luma_weight_l1_flag is equal to 1, luma_weight_l1[i] shall be
2322        // inferred to be equal to 2 ^ luma_log2_weight_denom for
2323        // RefPicList1[i].
2324        if header.slice_type.is_b() {
2325            for i in 0..=header.num_ref_idx_l1_active_minus1 {
2326                pt.luma_weight_l1[usize::from(i)] = default_luma_weight;
2327            }
2328        }
2329
2330        if sps.chroma_array_type() != 0 {
2331            pt.chroma_log2_weight_denom = r.read_ue_max(7)?;
2332            let default_chroma_weight = 1 << pt.chroma_log2_weight_denom;
2333
2334            // When chroma_weight_l0_flag is equal to 0, chroma_weight_l0[i]
2335            // shall be inferred to be equal to 2 ^ chroma_log2_weight_denom for
2336            // RefPicList0[i].
2337            for i in 0..=header.num_ref_idx_l0_active_minus1 {
2338                pt.chroma_weight_l0[usize::from(i)][0] = default_chroma_weight;
2339                pt.chroma_weight_l0[usize::from(i)][1] = default_chroma_weight;
2340            }
2341
2342            // When chroma_weight_l1_flag is equal to 0, chroma_weight_l1[i]
2343            // shall be inferred to be equal to 2 ^ chroma_log2_weight_denom for
2344            // RefPicList1[i].
2345            for i in 0..=header.num_ref_idx_l1_active_minus1 {
2346                pt.chroma_weight_l1[usize::from(i)][0] = default_chroma_weight;
2347                pt.chroma_weight_l1[usize::from(i)][1] = default_chroma_weight;
2348            }
2349        }
2350
2351        for i in 0..=header.num_ref_idx_l0_active_minus1 {
2352            let luma_weight_l0_flag = r.read_bit()?;
2353
2354            if luma_weight_l0_flag {
2355                pt.luma_weight_l0[usize::from(i)] = r.read_se_bounded(-128, 127)?;
2356                pt.luma_offset_l0[usize::from(i)] = r.read_se_bounded(-128, 127)?;
2357            }
2358
2359            if sps.chroma_array_type() != 0 {
2360                let chroma_weight_l0_flag = r.read_bit()?;
2361                if chroma_weight_l0_flag {
2362                    for j in 0..2 {
2363                        pt.chroma_weight_l0[usize::from(i)][j] = r.read_se_bounded(-128, 127)?;
2364                        pt.chroma_offset_l0[usize::from(i)][j] = r.read_se_bounded(-128, 127)?;
2365                    }
2366                }
2367            }
2368        }
2369
2370        if header.slice_type.is_b() {
2371            for i in 0..=header.num_ref_idx_l1_active_minus1 {
2372                let luma_weight_l1_flag = r.read_bit()?;
2373
2374                if luma_weight_l1_flag {
2375                    pt.luma_weight_l1[usize::from(i)] = r.read_se_bounded(-128, 127)?;
2376                    pt.luma_offset_l1[usize::from(i)] = r.read_se_bounded(-128, 127)?;
2377                }
2378
2379                if sps.chroma_array_type() != 0 {
2380                    let chroma_weight_l1_flag = r.read_bit()?;
2381                    if chroma_weight_l1_flag {
2382                        for j in 0..2 {
2383                            pt.chroma_weight_l1[usize::from(i)][j] =
2384                                r.read_se_bounded(-128, 127)?;
2385                            pt.chroma_offset_l1[usize::from(i)][j] =
2386                                r.read_se_bounded(-128, 127)?;
2387                        }
2388                    }
2389                }
2390            }
2391        }
2392
2393        Ok(())
2394    }
2395
2396    fn parse_dec_ref_pic_marking(
2397        r: &mut BitReader,
2398        nalu: &Nalu,
2399        header: &mut SliceHeader,
2400    ) -> Result<(), String> {
2401        let rpm = &mut header.dec_ref_pic_marking;
2402
2403        let num_bits_left = r.num_bits_left();
2404        if nalu.header.idr_pic_flag {
2405            rpm.no_output_of_prior_pics_flag = r.read_bit()?;
2406            rpm.long_term_reference_flag = r.read_bit()?;
2407        } else {
2408            rpm.adaptive_ref_pic_marking_mode_flag = r.read_bit()?;
2409
2410            if rpm.adaptive_ref_pic_marking_mode_flag {
2411                loop {
2412                    let mut marking = RefPicMarkingInner::default();
2413
2414                    let mem_mgmt_ctrl_op = r.read_ue_max::<u8>(6)?;
2415                    marking.memory_management_control_operation = mem_mgmt_ctrl_op;
2416
2417                    if mem_mgmt_ctrl_op == 0 {
2418                        break;
2419                    }
2420
2421                    if mem_mgmt_ctrl_op == 1 || mem_mgmt_ctrl_op == 3 {
2422                        marking.difference_of_pic_nums_minus1 = r.read_ue()?;
2423                    }
2424
2425                    if mem_mgmt_ctrl_op == 2 {
2426                        marking.long_term_pic_num = r.read_ue()?;
2427                    }
2428
2429                    if mem_mgmt_ctrl_op == 3 || mem_mgmt_ctrl_op == 6 {
2430                        marking.long_term_frame_idx = r.read_ue()?;
2431                    }
2432
2433                    if mem_mgmt_ctrl_op == 4 {
2434                        marking.max_long_term_frame_idx =
2435                            MaxLongTermFrameIdx::from_value_plus1(r.read_ue()?);
2436                    }
2437
2438                    rpm.inner.push(marking);
2439                }
2440            }
2441        }
2442        header.dec_ref_pic_marking_bit_size = num_bits_left - r.num_bits_left();
2443
2444        Ok(())
2445    }
2446
2447    pub fn parse_slice_header<'a>(&self, nalu: Nalu<'a>) -> Result<Slice<'a>, String> {
2448        if !matches!(
2449            nalu.header.type_,
2450            NaluType::Slice
2451                | NaluType::SliceDpa
2452                | NaluType::SliceDpb
2453                | NaluType::SliceDpc
2454                | NaluType::SliceIdr
2455                | NaluType::SliceExt
2456        ) {
2457            return Err(format!("Invalid NALU type: {:?} is not a slice NALU", nalu.header.type_));
2458        }
2459
2460        let data = nalu.as_ref();
2461        // Skip the header
2462        let mut r = BitReader::new(&data[nalu.header.len()..], true);
2463
2464        let mut header = SliceHeader { first_mb_in_slice: r.read_ue()?, ..Default::default() };
2465
2466        let slice_type = r.read_ue_max::<u8>(9)? % 5;
2467        header.slice_type = SliceType::try_from(slice_type)?;
2468
2469        header.pic_parameter_set_id = r.read_ue()?;
2470
2471        let pps = self.get_pps(header.pic_parameter_set_id).ok_or::<String>(format!(
2472            "Could not get PPS for pic_parameter_set_id {}",
2473            header.pic_parameter_set_id
2474        ))?;
2475
2476        let sps = &pps.sps;
2477
2478        if sps.separate_colour_plane_flag {
2479            header.colour_plane_id = r.read_bits(2)?;
2480        }
2481
2482        header.frame_num = r.read_bits(usize::from(sps.log2_max_frame_num_minus4) + 4)?;
2483
2484        if !sps.frame_mbs_only_flag {
2485            header.field_pic_flag = r.read_bit()?;
2486            if header.field_pic_flag {
2487                header.bottom_field_flag = r.read_bit()?;
2488            }
2489        }
2490
2491        if header.field_pic_flag {
2492            header.max_pic_num = 2 * sps.max_frame_num();
2493        } else {
2494            header.max_pic_num = sps.max_frame_num();
2495        }
2496
2497        if nalu.header.idr_pic_flag {
2498            header.idr_pic_id = r.read_ue_max(0xffff)?;
2499        }
2500
2501        let num_bits_left = r.num_bits_left();
2502        if sps.pic_order_cnt_type == 0 {
2503            header.pic_order_cnt_lsb =
2504                r.read_bits(usize::from(sps.log2_max_pic_order_cnt_lsb_minus4) + 4)?;
2505
2506            if pps.bottom_field_pic_order_in_frame_present_flag && !header.field_pic_flag {
2507                header.delta_pic_order_cnt_bottom = r.read_se()?;
2508            }
2509        }
2510
2511        if sps.pic_order_cnt_type == 1 && !sps.delta_pic_order_always_zero_flag {
2512            header.delta_pic_order_cnt[0] = r.read_se()?;
2513            if pps.bottom_field_pic_order_in_frame_present_flag && !header.field_pic_flag {
2514                header.delta_pic_order_cnt[1] = r.read_se()?;
2515            }
2516        }
2517        header.pic_order_cnt_bit_size = num_bits_left - r.num_bits_left();
2518
2519        if pps.redundant_pic_cnt_present_flag {
2520            header.redundant_pic_cnt = r.read_ue_max(127)?;
2521        }
2522
2523        if header.slice_type.is_b() {
2524            header.direct_spatial_mv_pred_flag = r.read_bit()?;
2525        }
2526
2527        if header.slice_type.is_p() || header.slice_type.is_sp() || header.slice_type.is_b() {
2528            header.num_ref_idx_active_override_flag = r.read_bit()?;
2529            if header.num_ref_idx_active_override_flag {
2530                header.num_ref_idx_l0_active_minus1 = r.read_ue()?;
2531                if header.slice_type.is_b() {
2532                    header.num_ref_idx_l1_active_minus1 = r.read_ue()?;
2533                }
2534            } else {
2535                header.num_ref_idx_l0_active_minus1 = pps.num_ref_idx_l0_default_active_minus1;
2536                if header.slice_type.is_b() {
2537                    header.num_ref_idx_l1_active_minus1 = pps.num_ref_idx_l1_default_active_minus1;
2538                }
2539            }
2540        }
2541
2542        if header.field_pic_flag {
2543            if header.num_ref_idx_l0_active_minus1 > 31 || header.num_ref_idx_l1_active_minus1 > 31
2544            {
2545                return Err("Broken Data".into());
2546            }
2547        } else if header.num_ref_idx_l0_active_minus1 > 15
2548            || header.num_ref_idx_l1_active_minus1 > 15
2549        {
2550            return Err("Broken Data".into());
2551        }
2552
2553        if let NaluType::SliceExt = nalu.header.type_ {
2554            return Err("Stream contain unsupported/unimplemented NALs".into());
2555        }
2556
2557        Parser::parse_ref_pic_list_modifications(&mut r, &mut header)?;
2558
2559        if (pps.weighted_pred_flag && (header.slice_type.is_p() || header.slice_type.is_sp()))
2560            || (pps.weighted_bipred_idc == 1 && header.slice_type.is_b())
2561        {
2562            Parser::parse_pred_weight_table(&mut r, sps, &mut header)?;
2563        }
2564
2565        if nalu.header.ref_idc != 0 {
2566            Parser::parse_dec_ref_pic_marking(&mut r, &nalu, &mut header)?;
2567        }
2568
2569        if pps.entropy_coding_mode_flag && !header.slice_type.is_i() && !header.slice_type.is_si() {
2570            header.cabac_init_idc = r.read_ue_max(2)?;
2571        }
2572
2573        header.slice_qp_delta = r.read_se_bounded(-87, 77)?;
2574
2575        if header.slice_type.is_sp() || header.slice_type.is_si() {
2576            if header.slice_type.is_sp() {
2577                header.sp_for_switch_flag = r.read_bit()?;
2578            }
2579
2580            header.slice_qs_delta = r.read_se_bounded(-51, 51)?;
2581        }
2582
2583        if pps.deblocking_filter_control_present_flag {
2584            header.disable_deblocking_filter_idc = r.read_ue_max(2)?;
2585
2586            if header.disable_deblocking_filter_idc != 1 {
2587                header.slice_alpha_c0_offset_div2 = r.read_se_bounded(-6, 6)?;
2588                header.slice_beta_offset_div2 = r.read_se_bounded(-6, 6)?;
2589            }
2590        }
2591
2592        if pps.num_slice_groups_minus1 > 0 {
2593            return Err("Stream contain unsupported/unimplemented NALs".into());
2594        }
2595
2596        let epb = r.num_epb();
2597        header.header_bit_size = (nalu.size - epb) * 8 - r.num_bits_left();
2598
2599        header.n_emulation_prevention_bytes = epb;
2600
2601        Ok(Slice { header, nalu })
2602    }
2603
2604    pub fn get_sps(&self, sps_id: u8) -> Option<&Rc<Sps>> {
2605        self.active_spses.get(&sps_id)
2606    }
2607
2608    pub fn get_pps(&self, pps_id: u8) -> Option<&Rc<Pps>> {
2609        self.active_ppses.get(&pps_id)
2610    }
2611}
2612
2613#[derive(Debug)]
2614pub struct NaluHeader {
2615    pub ref_idc: u8,
2616    pub type_: NaluType,
2617    pub idr_pic_flag: bool,
2618}
2619
2620impl Header for NaluHeader {
2621    fn parse<T: AsRef<[u8]>>(cursor: &mut Cursor<T>) -> Result<Self, String> {
2622        let mut byte_buf = [0u8; 1];
2623        cursor.read_exact(&mut byte_buf).map_err(|_| String::from("Broken Data"))?;
2624        let byte = byte_buf[0];
2625        let _ = cursor.seek(SeekFrom::Current(-1 * byte_buf.len() as i64));
2626
2627        let type_ = NaluType::try_from(byte & 0x1f)?;
2628
2629        if let NaluType::SliceExt = type_ {
2630            return Err("Stream contain unsupported/unimplemented NALs".into());
2631        }
2632
2633        let ref_idc = (byte & 0x60) >> 5;
2634        let idr_pic_flag = matches!(type_, NaluType::SliceIdr);
2635
2636        Ok(NaluHeader { ref_idc, type_, idr_pic_flag })
2637    }
2638
2639    fn is_end(&self) -> bool {
2640        matches!(self.type_, NaluType::SeqEnd | NaluType::StreamEnd)
2641    }
2642
2643    fn len(&self) -> usize {
2644        1
2645    }
2646}
2647
2648#[cfg(test)]
2649mod tests {
2650    use std::io::Cursor;
2651
2652    use crate::codec::h264::parser::Level;
2653    use crate::codec::h264::parser::MaxLongTermFrameIdx;
2654    use crate::codec::h264::parser::Nalu;
2655    use crate::codec::h264::parser::NaluType;
2656    use crate::codec::h264::parser::Parser;
2657
2658    const STREAM_TEST_25_FPS: &[u8] = include_bytes!("test_data/test-25fps.h264");
2659    const STREAM_TEST_25_FPS_NUM_NALUS: usize = 759;
2660
2661    const STREAM_TEST_25_FPS_SLICE_0: &[u8] =
2662        include_bytes!("test_data/test-25fps-h264-slice-data-0.bin");
2663    const STREAM_TEST_25_FPS_SLICE_2: &[u8] =
2664        include_bytes!("test_data/test-25fps-h264-slice-data-2.bin");
2665    const STREAM_TEST_25_FPS_SLICE_4: &[u8] =
2666        include_bytes!("test_data/test-25fps-h264-slice-data-4.bin");
2667
2668    /// This test is adapted from chromium, available at media/video/h264_parser_unittest.cc
2669    #[test]
2670    fn parse_nalus_from_stream_file() {
2671        let mut cursor = Cursor::new(STREAM_TEST_25_FPS);
2672        let mut num_nalus = 0;
2673        while Nalu::next(&mut cursor).is_ok() {
2674            num_nalus += 1;
2675        }
2676
2677        assert_eq!(num_nalus, STREAM_TEST_25_FPS_NUM_NALUS)
2678    }
2679
2680    /// The results were manually extracted from the GStreamer parser using GDB
2681    /// (gsth264parser.c) in order to compare both implementations using the
2682    /// following pipeline:
2683    /// gst-launch-1.0 filesrc location=test-25fps.h264 ! h264parse ! 'video/x-h264,stream-format=byte-stream' ! vah264dec ! fakevideosink
2684    #[test]
2685    fn parse_test25fps() {
2686        let mut cursor = Cursor::new(STREAM_TEST_25_FPS);
2687        let mut sps_ids = Vec::new();
2688        let mut pps_ids = Vec::new();
2689        let mut slices = Vec::new();
2690
2691        let mut parser = Parser::default();
2692
2693        while let Ok(nalu) = Nalu::next(&mut cursor) {
2694            match nalu.header.type_ {
2695                NaluType::Slice
2696                | NaluType::SliceDpa
2697                | NaluType::SliceDpb
2698                | NaluType::SliceDpc
2699                | NaluType::SliceIdr
2700                | NaluType::SliceExt => {
2701                    let slice = parser.parse_slice_header(nalu).unwrap();
2702                    slices.push(slice);
2703                }
2704                NaluType::Sps => {
2705                    let sps = parser.parse_sps(&nalu).unwrap();
2706                    sps_ids.push(sps.seq_parameter_set_id);
2707                }
2708                NaluType::Pps => {
2709                    let pps = parser.parse_pps(&nalu).unwrap();
2710                    pps_ids.push(pps.pic_parameter_set_id);
2711                }
2712                _ => {
2713                    continue;
2714                }
2715            }
2716        }
2717
2718        for sps_id in &sps_ids {
2719            // four identical SPSes in this stream
2720            let sps = parser.get_sps(*sps_id).unwrap();
2721
2722            assert_eq!(sps.seq_parameter_set_id, 0);
2723            assert_eq!(sps.profile_idc, 77);
2724            assert!(!sps.constraint_set0_flag);
2725            assert!(sps.constraint_set1_flag);
2726            assert!(!sps.constraint_set2_flag);
2727            assert!(!sps.constraint_set3_flag);
2728            assert!(!sps.constraint_set4_flag);
2729            assert!(!sps.constraint_set5_flag);
2730            assert_eq!(sps.level_idc, Level::L1_3);
2731            assert_eq!(sps.chroma_format_idc, 1);
2732            assert!(!sps.separate_colour_plane_flag);
2733            assert_eq!(sps.bit_depth_luma_minus8, 0);
2734            assert_eq!(sps.bit_depth_chroma_minus8, 0);
2735            assert!(!sps.qpprime_y_zero_transform_bypass_flag);
2736            assert!(!sps.seq_scaling_matrix_present_flag);
2737
2738            for outer in &sps.scaling_lists_4x4 {
2739                for inner in outer {
2740                    assert_eq!(*inner, 16);
2741                }
2742            }
2743
2744            for outer in &sps.scaling_lists_8x8 {
2745                for inner in outer {
2746                    assert_eq!(*inner, 16);
2747                }
2748            }
2749
2750            assert_eq!(sps.log2_max_frame_num_minus4, 1);
2751            assert_eq!(sps.pic_order_cnt_type, 0);
2752            assert_eq!(sps.log2_max_pic_order_cnt_lsb_minus4, 3);
2753            assert!(!sps.delta_pic_order_always_zero_flag);
2754            assert_eq!(sps.offset_for_non_ref_pic, 0);
2755            assert_eq!(sps.offset_for_top_to_bottom_field, 0);
2756            assert_eq!(sps.num_ref_frames_in_pic_order_cnt_cycle, 0);
2757
2758            for offset in sps.offset_for_ref_frame {
2759                assert_eq!(offset, 0);
2760            }
2761
2762            assert_eq!(sps.max_num_ref_frames, 2);
2763            assert!(!sps.gaps_in_frame_num_value_allowed_flag);
2764            assert_eq!(sps.pic_width_in_mbs_minus1, 19);
2765            assert_eq!(sps.pic_height_in_map_units_minus1, 14);
2766            assert!(sps.frame_mbs_only_flag);
2767            assert!(!sps.mb_adaptive_frame_field_flag);
2768            assert!(!sps.direct_8x8_inference_flag);
2769            assert!(!sps.frame_cropping_flag);
2770            assert_eq!(sps.frame_crop_left_offset, 0);
2771            assert_eq!(sps.frame_crop_right_offset, 0);
2772            assert_eq!(sps.frame_crop_top_offset, 0);
2773            assert_eq!(sps.frame_crop_bottom_offset, 0);
2774            assert_eq!(sps.chroma_array_type(), 1);
2775            assert_eq!(sps.max_frame_num(), 32);
2776            assert_eq!(sps.width(), 320);
2777            assert_eq!(sps.height(), 240);
2778        }
2779
2780        for pps_id in &pps_ids {
2781            // four identical SPSes in this stream
2782            let pps = parser.get_pps(*pps_id).unwrap();
2783            assert_eq!(pps.pic_parameter_set_id, 0);
2784            assert_eq!(pps.seq_parameter_set_id, 0);
2785            assert!(pps.bottom_field_pic_order_in_frame_present_flag);
2786            assert_eq!(pps.num_slice_groups_minus1, 0);
2787            assert_eq!(pps.num_ref_idx_l0_default_active_minus1, 0);
2788            assert_eq!(pps.num_ref_idx_l1_default_active_minus1, 0);
2789            assert!(!pps.weighted_pred_flag);
2790            assert_eq!(pps.weighted_bipred_idc, 0);
2791            assert_eq!(pps.pic_init_qp_minus26, 2);
2792            assert_eq!(pps.pic_init_qs_minus26, 0);
2793            assert_eq!(pps.chroma_qp_index_offset, 0);
2794            assert!(!pps.deblocking_filter_control_present_flag);
2795            assert!(!pps.constrained_intra_pred_flag);
2796            assert!(!pps.redundant_pic_cnt_present_flag);
2797            assert!(!pps.transform_8x8_mode_flag);
2798
2799            for outer in &pps.scaling_lists_4x4 {
2800                for inner in outer {
2801                    assert_eq!(*inner, 16);
2802                }
2803            }
2804
2805            for outer in &pps.scaling_lists_8x8 {
2806                for inner in outer {
2807                    assert_eq!(*inner, 16);
2808                }
2809            }
2810
2811            assert_eq!(pps.second_chroma_qp_index_offset, 0);
2812            assert!(!pps.pic_scaling_matrix_present_flag);
2813        }
2814
2815        // test an I slice
2816        let hdr = &slices[0].header;
2817        let nalu = &slices[0].nalu;
2818        assert_eq!(nalu.as_ref(), STREAM_TEST_25_FPS_SLICE_0);
2819
2820        assert_eq!(hdr.first_mb_in_slice, 0);
2821        assert!(hdr.slice_type.is_i());
2822        assert_eq!(hdr.colour_plane_id, 0);
2823        assert_eq!(hdr.frame_num, 0);
2824        assert!(!hdr.field_pic_flag);
2825        assert!(!hdr.bottom_field_flag);
2826        assert_eq!(hdr.idr_pic_id, 0);
2827        assert_eq!(hdr.pic_order_cnt_lsb, 0);
2828        assert_eq!(hdr.delta_pic_order_cnt_bottom, 0);
2829        assert_eq!(hdr.delta_pic_order_cnt[0], 0);
2830        assert_eq!(hdr.delta_pic_order_cnt[1], 0);
2831        assert_eq!(hdr.redundant_pic_cnt, 0);
2832        assert!(!hdr.direct_spatial_mv_pred_flag);
2833        assert_eq!(hdr.num_ref_idx_l0_active_minus1, 0);
2834        assert_eq!(hdr.num_ref_idx_l1_active_minus1, 0);
2835        assert!(!hdr.ref_pic_list_modification_flag_l0);
2836
2837        assert_eq!(hdr.ref_pic_list_modification_l0.len(), 0);
2838
2839        for rplm in &hdr.ref_pic_list_modification_l0 {
2840            assert_eq!(rplm.modification_of_pic_nums_idc, 0);
2841            assert_eq!(rplm.abs_diff_pic_num_minus1, 0);
2842            assert_eq!(rplm.long_term_pic_num, 0);
2843            assert_eq!(rplm.abs_diff_view_idx_minus1, 0);
2844        }
2845
2846        assert!(!hdr.ref_pic_list_modification_flag_l1);
2847        assert_eq!(hdr.ref_pic_list_modification_l1.len(), 0);
2848
2849        for rplm in &hdr.ref_pic_list_modification_l1 {
2850            assert_eq!(rplm.modification_of_pic_nums_idc, 0);
2851            assert_eq!(rplm.abs_diff_pic_num_minus1, 0);
2852            assert_eq!(rplm.long_term_pic_num, 0);
2853            assert_eq!(rplm.abs_diff_view_idx_minus1, 0);
2854        }
2855
2856        // Safe because this type does not have any references
2857        assert_eq!(hdr.pred_weight_table, unsafe { std::mem::zeroed() });
2858
2859        assert_eq!(hdr.dec_ref_pic_marking, Default::default());
2860
2861        assert_eq!(hdr.cabac_init_idc, 0);
2862        assert_eq!(hdr.slice_qp_delta, 12);
2863        assert_eq!(hdr.slice_qs_delta, 0);
2864        assert_eq!(hdr.disable_deblocking_filter_idc, 0);
2865        assert_eq!(hdr.slice_alpha_c0_offset_div2, 0);
2866        assert_eq!(hdr.slice_beta_offset_div2, 0);
2867        assert_eq!(hdr.max_pic_num, 32);
2868        assert_eq!(hdr.header_bit_size, 38);
2869        assert!(!hdr.num_ref_idx_active_override_flag);
2870
2871        // test a P slice
2872        let hdr = &slices[2].header;
2873        let nalu = &slices[2].nalu;
2874        assert_eq!(nalu.as_ref(), STREAM_TEST_25_FPS_SLICE_2);
2875
2876        assert_eq!(hdr.first_mb_in_slice, 0);
2877        assert!(hdr.slice_type.is_p());
2878        assert_eq!(hdr.colour_plane_id, 0);
2879        assert_eq!(hdr.frame_num, 1);
2880        assert!(!hdr.field_pic_flag);
2881        assert!(!hdr.bottom_field_flag);
2882        assert_eq!(hdr.idr_pic_id, 0);
2883        assert_eq!(hdr.pic_order_cnt_lsb, 4);
2884        assert_eq!(hdr.delta_pic_order_cnt_bottom, 0);
2885        assert_eq!(hdr.delta_pic_order_cnt[0], 0);
2886        assert_eq!(hdr.delta_pic_order_cnt[1], 0);
2887        assert_eq!(hdr.redundant_pic_cnt, 0);
2888        assert!(!hdr.direct_spatial_mv_pred_flag);
2889        assert_eq!(hdr.num_ref_idx_l0_active_minus1, 0);
2890        assert_eq!(hdr.num_ref_idx_l1_active_minus1, 0);
2891        assert!(!hdr.ref_pic_list_modification_flag_l0);
2892
2893        assert_eq!(hdr.ref_pic_list_modification_l0.len(), 0);
2894
2895        for rplm in &hdr.ref_pic_list_modification_l0 {
2896            assert_eq!(rplm.modification_of_pic_nums_idc, 0);
2897            assert_eq!(rplm.abs_diff_pic_num_minus1, 0);
2898            assert_eq!(rplm.long_term_pic_num, 0);
2899            assert_eq!(rplm.abs_diff_view_idx_minus1, 0);
2900        }
2901
2902        assert!(!hdr.ref_pic_list_modification_flag_l1);
2903        assert_eq!(hdr.ref_pic_list_modification_l1.len(), 0);
2904
2905        for rplm in &hdr.ref_pic_list_modification_l1 {
2906            assert_eq!(rplm.modification_of_pic_nums_idc, 0);
2907            assert_eq!(rplm.abs_diff_pic_num_minus1, 0);
2908            assert_eq!(rplm.long_term_pic_num, 0);
2909            assert_eq!(rplm.abs_diff_view_idx_minus1, 0);
2910        }
2911
2912        // Safe because this type does not have any references
2913        assert_eq!(hdr.pred_weight_table, unsafe { std::mem::zeroed() });
2914
2915        assert_eq!(hdr.dec_ref_pic_marking, Default::default());
2916
2917        assert_eq!(hdr.cabac_init_idc, 0);
2918        assert_eq!(hdr.slice_qp_delta, 0);
2919        assert_eq!(hdr.slice_qs_delta, 0);
2920        assert_eq!(hdr.disable_deblocking_filter_idc, 0);
2921        assert_eq!(hdr.slice_alpha_c0_offset_div2, 0);
2922        assert_eq!(hdr.slice_beta_offset_div2, 0);
2923        assert_eq!(hdr.max_pic_num, 32);
2924        assert_eq!(hdr.header_bit_size, 28);
2925        assert!(!hdr.num_ref_idx_active_override_flag);
2926
2927        // test a B slice
2928        let hdr = &slices[4].header;
2929        let nalu = &slices[4].nalu;
2930        assert_eq!(nalu.as_ref(), STREAM_TEST_25_FPS_SLICE_4);
2931
2932        assert_eq!(hdr.first_mb_in_slice, 0);
2933        assert!(hdr.slice_type.is_b());
2934        assert_eq!(hdr.colour_plane_id, 0);
2935        assert_eq!(hdr.frame_num, 2);
2936        assert!(!hdr.field_pic_flag);
2937        assert!(!hdr.bottom_field_flag);
2938        assert_eq!(hdr.idr_pic_id, 0);
2939        assert_eq!(hdr.pic_order_cnt_lsb, 2);
2940        assert_eq!(hdr.delta_pic_order_cnt_bottom, 0);
2941        assert_eq!(hdr.delta_pic_order_cnt[0], 0);
2942        assert_eq!(hdr.delta_pic_order_cnt[1], 0);
2943        assert_eq!(hdr.redundant_pic_cnt, 0);
2944        assert!(hdr.direct_spatial_mv_pred_flag);
2945        assert_eq!(hdr.num_ref_idx_l0_active_minus1, 0);
2946        assert_eq!(hdr.num_ref_idx_l1_active_minus1, 0);
2947        assert!(!hdr.ref_pic_list_modification_flag_l0);
2948
2949        assert_eq!(hdr.ref_pic_list_modification_l0.len(), 0);
2950
2951        for rplm in &hdr.ref_pic_list_modification_l0 {
2952            assert_eq!(rplm.modification_of_pic_nums_idc, 0);
2953            assert_eq!(rplm.abs_diff_pic_num_minus1, 0);
2954            assert_eq!(rplm.long_term_pic_num, 0);
2955            assert_eq!(rplm.abs_diff_view_idx_minus1, 0);
2956        }
2957
2958        assert!(!hdr.ref_pic_list_modification_flag_l1);
2959        assert_eq!(hdr.ref_pic_list_modification_l1.len(), 0);
2960
2961        for rplm in &hdr.ref_pic_list_modification_l1 {
2962            assert_eq!(rplm.modification_of_pic_nums_idc, 0);
2963            assert_eq!(rplm.abs_diff_pic_num_minus1, 0);
2964            assert_eq!(rplm.long_term_pic_num, 0);
2965            assert_eq!(rplm.abs_diff_view_idx_minus1, 0);
2966        }
2967
2968        // Safe because this type does not have any references
2969        assert_eq!(hdr.pred_weight_table, unsafe { std::mem::zeroed() });
2970
2971        assert_eq!(hdr.dec_ref_pic_marking, Default::default());
2972
2973        assert_eq!(hdr.cabac_init_idc, 0);
2974        assert_eq!(hdr.slice_qp_delta, 16);
2975        assert_eq!(hdr.slice_qs_delta, 0);
2976        assert_eq!(hdr.disable_deblocking_filter_idc, 0);
2977        assert_eq!(hdr.slice_alpha_c0_offset_div2, 0);
2978        assert_eq!(hdr.slice_beta_offset_div2, 0);
2979        assert_eq!(hdr.max_pic_num, 32);
2980        assert_eq!(hdr.header_bit_size, 41);
2981        assert!(!hdr.num_ref_idx_active_override_flag);
2982    }
2983
2984    #[test]
2985    fn invalid_sps_crop_width() {
2986        // This SPS contains invalid frame_crop_*_offset settings. This led to
2987        // unconditional panic in the parser in the past. This test make sure a
2988        // panic is avoided.
2989        let invalid_sps =
2990            vec![0x00, 0x00, 0x01, 0x07, 0x00, 0x00, 0x0a, 0xfb, 0xb0, 0x32, 0xc0, 0xca, 0x80];
2991
2992        let mut cursor = Cursor::new(invalid_sps.as_ref());
2993        let mut parser = Parser::default();
2994
2995        while let Ok(nalu) = Nalu::next(&mut cursor) {
2996            assert_eq!(nalu.header.type_, NaluType::Sps);
2997            parser.parse_sps(&nalu).unwrap_err();
2998        }
2999    }
3000
3001    #[test]
3002    fn max_long_term_frame_idx() {
3003        assert_eq!(
3004            MaxLongTermFrameIdx::from_value_plus1(0),
3005            MaxLongTermFrameIdx::NoLongTermFrameIndices
3006        );
3007        assert_eq!(MaxLongTermFrameIdx::NoLongTermFrameIndices.to_value_plus1(), 0);
3008
3009        assert_eq!(MaxLongTermFrameIdx::from_value_plus1(1), MaxLongTermFrameIdx::Idx(0));
3010        assert_eq!(MaxLongTermFrameIdx::Idx(0).to_value_plus1(), 1);
3011
3012        assert_eq!(MaxLongTermFrameIdx::from_value_plus1(25), MaxLongTermFrameIdx::Idx(24));
3013        assert_eq!(MaxLongTermFrameIdx::Idx(24).to_value_plus1(), 25);
3014
3015        // Check PartialOrd<u32> implementation.
3016        assert!(MaxLongTermFrameIdx::NoLongTermFrameIndices < 0);
3017        assert_ne!(MaxLongTermFrameIdx::NoLongTermFrameIndices, 0);
3018        assert_eq!(MaxLongTermFrameIdx::Idx(0), 0);
3019        assert!(MaxLongTermFrameIdx::Idx(0) < 1);
3020        assert_eq!(MaxLongTermFrameIdx::Idx(24), 24);
3021        assert!(MaxLongTermFrameIdx::Idx(24) < 25);
3022    }
3023}