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