Skip to main content

moq_vaapi/codec/h264/
parser.rs

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