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