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