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