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 use std::convert::TryFrom; 6 use std::fmt; 7 8 use log::debug; 9 10 use crate::bitstream_utils::BitReader; 11 use crate::codec::vp8::bool_decoder::BoolDecoder; 12 use crate::codec::vp8::bool_decoder::BoolDecoderError; 13 use crate::codec::vp8::bool_decoder::BoolDecoderResult; 14 use crate::codec::vp8::bool_decoder::BoolDecoderState; 15 use crate::codec::vp8::probs::COEFF_DEFAULT_PROBS; 16 use crate::codec::vp8::probs::COEFF_UPDATE_PROBS; 17 use crate::codec::vp8::probs::KF_UV_MODE_PROBS; 18 use crate::codec::vp8::probs::KF_Y_MODE_PROBS; 19 use crate::codec::vp8::probs::MV_DEFAULT_PROBS; 20 use crate::codec::vp8::probs::MV_UPDATE_PROBS; 21 use crate::codec::vp8::probs::NK_UV_MODE_PROBS; 22 use crate::codec::vp8::probs::NK_Y_MODE_PROBS; 23 24 /// Dequantization indices as parsed from the quant_indices() syntax. 25 #[derive(Clone, Debug, Default, PartialEq, Eq)] 26 pub struct QuantIndices { 27 /// The dequantization table index used for the luma AC coefficients (and 28 /// other coefficient groups if no delta value is present). 29 pub y_ac_qi: u8, 30 /// Indicates the delta value that is added to the baseline index to obtain 31 /// the luma DC coefficient dequantization index. 32 pub y_dc_delta: i8, 33 /// Indicates the delta value that is added to the baseline index to obtain 34 /// the Y2 block DC coefficient dequantization index. 35 pub y2_dc_delta: i8, 36 /// Indicates the delta value that is added to the baseline index to obtain 37 /// the Y2 block AC coefficient dequantization index. 38 pub y2_ac_delta: i8, 39 /// Indicates the delta value that is added to the baseline index to obtain 40 /// the chroma DC coefficient dequantization index. 41 pub uv_dc_delta: i8, 42 /// Indicates the delta value that is added to the baseline index to obtain 43 /// the chroma AC coefficient dequantization index. 44 pub uv_ac_delta: i8, 45 } 46 47 #[derive(Clone, Debug, Default, PartialEq, Eq)] 48 pub struct MbLfAdjustments { 49 /// Indicates if the MB-level loop filter adjustment (based on the used 50 /// reference frame and coding mode) is on for the current frame. 51 pub loop_filter_adj_enable: bool, 52 /// Indicates if the delta values used in adjustment are updated in the 53 /// current frame. 54 pub mode_ref_lf_delta_update: bool, 55 56 //if mode_ref_lf_delta_update == 1 57 /// Indicates the adjustment delta value corresponding to a certain used 58 /// reference frame. 59 pub ref_frame_delta: [i8; 4], 60 /// Indicates the adjustment delta value corresponding to a certain MB 61 /// prediction mode 62 pub mb_mode_delta: [i8; 4], 63 } 64 65 #[derive(Clone, Debug, Default, PartialEq, Eq)] 66 pub struct Segmentation { 67 /// Enables the segmentation feature for the current frame. 68 pub segmentation_enabled: bool, 69 /// Determines if the MB segmentation map is updated in the current frame. 70 pub update_mb_segmentation_map: bool, 71 /// indicates if the segment feature data is updated in the current frame. 72 pub update_segment_feature_data: bool, 73 74 // If update_segment_feature_data == 1 75 /// Indicates the feature data update mode, O for delta and 1 for the 76 /// absolute value. 77 pub segment_feature_mode: bool, 78 /// Indicates if the quantizer value is updated for the izh segment. 79 pub quantizer_update_value: [i8; 4], 80 /// Indicates the update value for the loop filter level. 81 pub lf_update_value: [i8; 4], 82 83 // if update_mb_segmentation_map == 1 84 /// The branch probabilities of the segment id decoding tree. 85 pub segment_prob: [u8; 3], 86 } 87 88 #[derive(Clone, Debug, Default, PartialEq, Eq)] 89 pub struct ModeProbs { 90 /// Branch probabilities of the luma intra prediction mode decoding tree, 91 /// kept live between frames. 92 pub intra_16x16_prob: [u8; 4], 93 /// Branch probabilities of the chroma intra prediction mode decoding tree, 94 /// kept live between frames. 95 pub intra_chroma_prob: [u8; 3], 96 } 97 98 #[derive(Clone, Debug, Default, PartialEq, Eq)] 99 pub struct Header { 100 /// Indicates if the current frame is a key frame or not. 101 pub key_frame: bool, 102 /// Determines the bitstream version. 103 pub version: u8, 104 /// Indicates if the current frame is meant to be displayed or not. 105 pub show_frame: bool, 106 /// The size in bytes of the Uncompressed Data Chunk 107 pub data_chunk_size: u8, 108 /// Determines the size of the first partition (control partition) excluding 109 /// the size of the Uncompressed Data Chunk 110 pub first_part_size: u32, 111 112 /// The frame's width, in pixels. 113 pub width: u16, 114 /// The frame's height, in pixels. 115 pub height: u16, 116 /// Horizontal scale code value. 117 pub horiz_scale_code: u8, 118 /// Vertical scale code value. 119 pub vert_scale_code: u8, 120 /// Defines the YUV color space of the sequence. 121 pub color_space: bool, 122 /// Specifies if the decoder is required to clamp the reconstructed pixel 123 /// values. 124 pub clamping_type: bool, 125 /// Determines whether the normal or the simple loop filter is used. 126 pub filter_type: bool, 127 /// Controls the deblocking filter. 128 pub loop_filter_level: u8, 129 /// Controls the deblocking filter. 130 pub sharpness_level: u8, 131 /// Determines the number of separate partitions containing the DCT 132 /// coefficients of the macroblocks. 133 log2_nbr_of_dct_partitions: u8, 134 135 pub partition_size: [u32; 8], 136 137 /// Dequantizer indices. 138 pub quant_indices: QuantIndices, 139 140 /// Determines whether updated token probabilities are used only for this 141 /// frame or until further update 142 pub refresh_entropy_probs: bool, 143 /// Determines if the current decoded frame refreshes the last frame 144 /// reference buffer 145 pub refresh_last: bool, 146 147 /// Determines if the current decoded frame refreshes the golden frame. 148 pub refresh_golden_frame: bool, 149 /// Determines if the current decoded frame refreshes the alternate 150 /// reference frame. 151 pub refresh_alternate_frame: bool, 152 /// Determines if the golden reference is replaced by another reference. 153 pub copy_buffer_to_golden: u8, 154 /// Determines if the alternate reference is replaced by another reference. 155 pub copy_buffer_to_alternate: u8, 156 /// Controls the sign of motion vectors when the golden frame is referenced. 157 pub sign_bias_golden: bool, 158 /// Controls the sign of motion vectors when the alternate frame is 159 /// referenced. 160 pub sign_bias_alternate: bool, 161 162 /// The new branch probability for the DCT/WHT tree. 163 pub coeff_prob: [[[[u8; 11]; 3]; 8]; 4], 164 /// MV decoding probability. 165 pub mv_prob: [[u8; 19]; 2], 166 167 /// Enables or disables the skipping of macroblocks containing no non-zero 168 /// coefficients. 169 pub mb_no_coeff_skip: bool, 170 /// The probability that the macroblock is not skipped (flag indicating 171 /// skipped macroblock is false). 172 pub prob_skip_false: u8, 173 /// The probability of an intra macroblock. 174 pub prob_intra: u8, 175 /// The probability that the last reference frame is used for inter 176 /// prediction. 177 pub prob_last: u8, 178 /// The probability that the golden reference frame is used for inter 179 /// prediction. 180 pub prob_golden: u8, 181 /// Branch probabilities kept live across frames. 182 pub mode_probs: ModeProbs, 183 184 /// Boolean decoder `range` for this frame. 185 pub bd_range: usize, 186 /// Boolean decoder `value` for this frame. 187 pub bd_value: usize, 188 /// Boolean decoder `count` for this frame. 189 pub bd_count: isize, 190 191 /// The size in bits of the Frame Header, thus excluding any Uncompressed 192 /// Data Chunk bytes. 193 pub header_size: u32, 194 } 195 196 #[derive(Debug)] 197 pub enum ParseUncompressedChunkError { 198 InvalidStartCode(u32), 199 IoError(String), 200 } 201 202 impl fmt::Display for ParseUncompressedChunkError { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result203 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 204 match self { 205 ParseUncompressedChunkError::InvalidStartCode(x) => { 206 write!(f, "invalid start code {}", x) 207 } 208 ParseUncompressedChunkError::IoError(x) => write!(f, "I/O error: {}", x), 209 } 210 } 211 } 212 213 #[derive(Debug)] 214 pub enum ComputePartitionSizesError { 215 EndOfHeader, 216 PartitionTooLarge, 217 } 218 219 impl fmt::Display for ComputePartitionSizesError { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result220 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 221 match self { 222 ComputePartitionSizesError::EndOfHeader => write!(f, "unexpected end of header"), 223 ComputePartitionSizesError::PartitionTooLarge => { 224 write!(f, "partition size not fitting in a u32") 225 } 226 } 227 } 228 } 229 230 impl Header { 231 /// Returns the number of separate partitions containing the DCT coefficients of the 232 /// macroblocks. num_dct_partitions(&self) -> usize233 pub fn num_dct_partitions(&self) -> usize { 234 1 << self.log2_nbr_of_dct_partitions 235 } 236 237 /// Returns the total size of the encoded frame in bytes, as computed from the header. frame_len(&self) -> usize238 pub fn frame_len(&self) -> usize { 239 // Uncompressed chunk size. 240 std::iter::once(self.data_chunk_size as usize) 241 // Size of first partition. 242 .chain(std::iter::once(self.first_part_size as usize)) 243 // Size of the partitions description area. 244 .chain(std::iter::once(self.num_dct_partitions().saturating_sub(1) * 3)) 245 // Size of other DCT partitions. 246 .chain(self.partition_size.iter().take(self.num_dct_partitions()).map(|s| *s as usize)) 247 .sum() 248 } 249 250 /// Create a new `Header` by parsing the uncompressed data chunk of a frame. parse_uncompressed_data_chunk( bitstream: &[u8], ) -> Result<Self, ParseUncompressedChunkError>251 fn parse_uncompressed_data_chunk( 252 bitstream: &[u8], 253 ) -> Result<Self, ParseUncompressedChunkError> { 254 debug!("Parsing VP8 uncompressed data chunk."); 255 256 let mut reader = BitReader::new(bitstream, false); 257 258 let frame_tag = 259 reader.read_le::<u32>(3).map_err(|err| ParseUncompressedChunkError::IoError(err))?; 260 261 let mut header = Header { 262 key_frame: (frame_tag & 0x1) == 0, 263 version: ((frame_tag >> 1) & 0x07) as u8, 264 show_frame: ((frame_tag >> 4) & 0x1) != 0, 265 first_part_size: (frame_tag >> 5) & 0x7ffff, 266 ..Default::default() 267 }; 268 269 if header.key_frame { 270 let start_code = reader 271 .read_le::<u32>(3) 272 .map_err(|err| ParseUncompressedChunkError::IoError(err))?; 273 274 if start_code != 0x2a019d { 275 return Err(ParseUncompressedChunkError::InvalidStartCode(start_code)); 276 } 277 278 let size_code = reader 279 .read_le::<u16>(2) 280 .map_err(|err| ParseUncompressedChunkError::IoError(err))?; 281 header.horiz_scale_code = (size_code >> 14) as u8; 282 header.width = size_code & 0x3fff; 283 284 let size_code = reader 285 .read_le::<u16>(2) 286 .map_err(|err| ParseUncompressedChunkError::IoError(err))?; 287 header.vert_scale_code = (size_code >> 14) as u8; 288 header.height = size_code & 0x3fff; 289 } 290 291 if reader.position() % 8 != 0 { 292 Err(ParseUncompressedChunkError::IoError("Misaligned VP8 header".into())) 293 } else { 294 header.data_chunk_size = (reader.position() / 8) as u8; 295 Ok(header) 296 } 297 } 298 compute_partition_sizes(&mut self, data: &[u8]) -> Result<(), ComputePartitionSizesError>299 fn compute_partition_sizes(&mut self, data: &[u8]) -> Result<(), ComputePartitionSizesError> { 300 let num_partitions = self.num_dct_partitions(); 301 let mut part_size_ofs = self.first_part_size as usize; 302 let mut ofs = part_size_ofs + 3 * (num_partitions - 1); 303 304 if ofs > data.len() { 305 return Err(ComputePartitionSizesError::EndOfHeader); 306 } 307 308 for i in 0..num_partitions - 1 { 309 let b0 = u32::from(data[part_size_ofs]); 310 let b1 = u32::from(data[part_size_ofs + 1]) << 8; 311 let b2 = u32::from(data[part_size_ofs + 2]) << 16; 312 313 let part_size = b0 | b1 | b2; 314 part_size_ofs += 3; 315 316 self.partition_size[i] = part_size; 317 ofs += part_size as usize; 318 } 319 320 if ofs > data.len() { 321 return Err(ComputePartitionSizesError::EndOfHeader); 322 } 323 324 self.partition_size[num_partitions - 1] = u32::try_from(data.len() - ofs) 325 .map_err(|_| ComputePartitionSizesError::PartitionTooLarge)?; 326 Ok(()) 327 } 328 } 329 330 /// A VP8 frame. 331 pub struct Frame<'a> { 332 /// The bitstream data for this frame. 333 bitstream: &'a [u8], 334 /// The actual length of the frame data within `bitstream`. 335 frame_len: usize, 336 /// The parsed frame header. 337 pub header: Header, 338 } 339 340 impl<'a> AsRef<[u8]> for Frame<'a> { as_ref(&self) -> &[u8]341 fn as_ref(&self) -> &[u8] { 342 &self.bitstream[..self.frame_len] 343 } 344 } 345 346 /// A VP8 parser based on GStreamer's vp8parser and Chromium's VP8 parser. 347 #[derive(Clone, Debug, PartialEq, Eq)] 348 pub struct Parser { 349 /// Segmentation data kept live across frames. 350 segmentation: Segmentation, 351 /// MbLfAdjustments data kept live across frames. 352 mb_lf_adjust: MbLfAdjustments, 353 /// Coeff probabilities data kept live across frames. 354 coeff_prob: [[[[u8; 11]; 3]; 8]; 4], 355 /// Motion vector probabilities data kept live across frames. 356 mv_prob: [[u8; 19]; 2], 357 /// Branch probabilities kept live across frames. 358 mode_probs: ModeProbs, 359 } 360 361 #[derive(Debug)] 362 pub enum ParseFrameError { 363 ParseUncompressedChunk(ParseUncompressedChunkError), 364 InvalidPartitionSize(usize, usize), 365 ParseFrameHeader(BoolDecoderError), 366 ComputePartitionSizes(ComputePartitionSizesError), 367 BitstreamTooShort(usize, usize), 368 } 369 370 impl fmt::Display for ParseFrameError { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result371 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 372 match self { 373 ParseFrameError::ParseUncompressedChunk(x) => { 374 write!(f, "error while parsing uncompressed chunk of frame: {}", x) 375 } 376 ParseFrameError::InvalidPartitionSize(x, y) => { 377 write!(f, "partition end {} is bigger than bitstream length {}", x, y) 378 } 379 ParseFrameError::ParseFrameHeader(x) => { 380 write!(f, "error while parsing frame header: {}", x) 381 } 382 ParseFrameError::ComputePartitionSizes(x) => { 383 write!(f, "error while computing frames partitions sizes: {}", x) 384 } 385 ParseFrameError::BitstreamTooShort(x, y) => { 386 write!(f, "bitstream is shorter ({} bytes) than computed length of frame {}", x, y) 387 } 388 } 389 } 390 } 391 392 impl From<ParseUncompressedChunkError> for ParseFrameError { from(err: ParseUncompressedChunkError) -> Self393 fn from(err: ParseUncompressedChunkError) -> Self { 394 ParseFrameError::ParseUncompressedChunk(err) 395 } 396 } 397 398 impl From<BoolDecoderError> for ParseFrameError { from(err: BoolDecoderError) -> Self399 fn from(err: BoolDecoderError) -> Self { 400 ParseFrameError::ParseFrameHeader(err) 401 } 402 } 403 404 impl From<ComputePartitionSizesError> for ParseFrameError { from(err: ComputePartitionSizesError) -> Self405 fn from(err: ComputePartitionSizesError) -> Self { 406 ParseFrameError::ComputePartitionSizes(err) 407 } 408 } 409 410 impl Parser { segmentation(&self) -> &Segmentation411 pub fn segmentation(&self) -> &Segmentation { 412 &self.segmentation 413 } 414 mb_lf_adjust(&self) -> &MbLfAdjustments415 pub fn mb_lf_adjust(&self) -> &MbLfAdjustments { 416 &self.mb_lf_adjust 417 } 418 mode_probs_init_defaults(mode_probs: &mut ModeProbs, key_frame: bool)419 fn mode_probs_init_defaults(mode_probs: &mut ModeProbs, key_frame: bool) { 420 if key_frame { 421 mode_probs.intra_16x16_prob = KF_Y_MODE_PROBS; 422 mode_probs.intra_chroma_prob = KF_UV_MODE_PROBS; 423 } else { 424 mode_probs.intra_16x16_prob = NK_Y_MODE_PROBS; 425 mode_probs.intra_chroma_prob = NK_UV_MODE_PROBS; 426 } 427 } 428 update_segmentation(bd: &mut BoolDecoder, seg: &mut Segmentation) -> BoolDecoderResult<()>429 fn update_segmentation(bd: &mut BoolDecoder, seg: &mut Segmentation) -> BoolDecoderResult<()> { 430 seg.update_mb_segmentation_map = false; 431 seg.update_segment_feature_data = false; 432 433 seg.segmentation_enabled = bd.read_bool()?; 434 if !seg.segmentation_enabled { 435 return Ok(()); 436 } 437 438 seg.update_mb_segmentation_map = bd.read_bool()?; 439 seg.update_segment_feature_data = bd.read_bool()?; 440 441 if seg.update_segment_feature_data { 442 seg.segment_feature_mode = bd.read_bool()?; 443 444 for value in seg.quantizer_update_value.iter_mut() { 445 let update = bd.read_bool()?; 446 if update { 447 *value = bd.read_sint(7)?; 448 } else { 449 // quantizer_update_value defaults to zero if update flag is 450 // zero (Section 9.3, 4.b) 451 *value = 0; 452 } 453 } 454 455 for value in seg.lf_update_value.iter_mut() { 456 let update = bd.read_bool()?; 457 if update { 458 *value = bd.read_sint(6)?; 459 } else { 460 // lf_update_value defaults to zero if update flag is 461 // zero (Section 9.3, 4.b) 462 *value = 0; 463 } 464 } 465 466 if seg.update_mb_segmentation_map { 467 for value in seg.segment_prob.iter_mut() { 468 let update = bd.read_bool()?; 469 if update { 470 *value = bd.read_uint(8)?; 471 } else { 472 // segment_prob defaults to 255 if update flag is 473 // zero (Section 9.3, 5) 474 *value = 255; 475 } 476 } 477 } 478 } 479 480 Ok(()) 481 } 482 parse_mb_lf_adjustments( bd: &mut BoolDecoder, adj: &mut MbLfAdjustments, ) -> BoolDecoderResult<()>483 fn parse_mb_lf_adjustments( 484 bd: &mut BoolDecoder, 485 adj: &mut MbLfAdjustments, 486 ) -> BoolDecoderResult<()> { 487 adj.mode_ref_lf_delta_update = false; 488 489 adj.loop_filter_adj_enable = bd.read_bool()?; 490 if !adj.loop_filter_adj_enable { 491 return Ok(()); 492 } 493 494 adj.mode_ref_lf_delta_update = bd.read_bool()?; 495 if !adj.mode_ref_lf_delta_update { 496 return Ok(()); 497 } 498 499 for value in adj.ref_frame_delta.iter_mut() { 500 let update = bd.read_bool()?; 501 if update { 502 *value = bd.read_sint(6)?; 503 } 504 } 505 506 for value in adj.mb_mode_delta.iter_mut() { 507 let update = bd.read_bool()?; 508 if update { 509 *value = bd.read_sint(6)?; 510 } 511 } 512 513 Ok(()) 514 } 515 parse_quant_indices(bd: &mut BoolDecoder, q: &mut QuantIndices) -> BoolDecoderResult<()>516 fn parse_quant_indices(bd: &mut BoolDecoder, q: &mut QuantIndices) -> BoolDecoderResult<()> { 517 q.y_ac_qi = bd.read_uint(7)?; 518 519 let y_dc_delta_present = bd.read_bool()?; 520 521 if y_dc_delta_present { 522 q.y_dc_delta = bd.read_sint(4)?; 523 } else { 524 q.y_dc_delta = 0; 525 } 526 527 let y2_dc_delta_present = bd.read_bool()?; 528 if y2_dc_delta_present { 529 q.y2_dc_delta = bd.read_sint(4)?; 530 } else { 531 q.y2_dc_delta = 0; 532 } 533 534 let y2_ac_delta_present = bd.read_bool()?; 535 if y2_ac_delta_present { 536 q.y2_ac_delta = bd.read_sint(4)?; 537 } else { 538 q.y2_ac_delta = 0; 539 } 540 541 let uv_dc_delta_present = bd.read_bool()?; 542 if uv_dc_delta_present { 543 q.uv_dc_delta = bd.read_sint(4)?; 544 } else { 545 q.uv_dc_delta = 0; 546 } 547 548 let uv_ac_delta_present = bd.read_bool()?; 549 if uv_ac_delta_present { 550 q.uv_ac_delta = bd.read_sint(4)?; 551 } else { 552 q.uv_ac_delta = 0; 553 } 554 555 Ok(()) 556 } 557 parse_token_prob_update( bd: &mut BoolDecoder, coeff_probs: &mut [[[[u8; 11]; 3]; 8]; 4], ) -> BoolDecoderResult<()>558 fn parse_token_prob_update( 559 bd: &mut BoolDecoder, 560 coeff_probs: &mut [[[[u8; 11]; 3]; 8]; 4], 561 ) -> BoolDecoderResult<()> { 562 for (i, vi) in coeff_probs.iter_mut().enumerate() { 563 for (j, vj) in vi.iter_mut().enumerate() { 564 for (k, vk) in vj.iter_mut().enumerate() { 565 for (l, prob) in vk.iter_mut().enumerate() { 566 let update = bd.read_bool_with_prob(COEFF_UPDATE_PROBS[i][j][k][l])?; 567 if update { 568 *prob = bd.read_uint(8)?; 569 } 570 } 571 } 572 } 573 } 574 575 Ok(()) 576 } 577 parse_mv_prob_update( bd: &mut BoolDecoder, mv_probs: &mut [[u8; 19]; 2], ) -> BoolDecoderResult<()>578 fn parse_mv_prob_update( 579 bd: &mut BoolDecoder, 580 mv_probs: &mut [[u8; 19]; 2], 581 ) -> BoolDecoderResult<()> { 582 for (i, vi) in mv_probs.iter_mut().enumerate() { 583 for (j, prob) in vi.iter_mut().enumerate() { 584 let update = bd.read_bool_with_prob(MV_UPDATE_PROBS[i][j])?; 585 if update { 586 let mv_prob_update = bd.read_uint::<u8>(7)?; 587 588 if mv_prob_update > 0 { 589 *prob = mv_prob_update << 1; 590 } else { 591 *prob = 1; 592 } 593 } 594 } 595 } 596 597 Ok(()) 598 } 599 parse_frame_header(&mut self, data: &[u8], frame: &mut Header) -> BoolDecoderResult<()>600 fn parse_frame_header(&mut self, data: &[u8], frame: &mut Header) -> BoolDecoderResult<()> { 601 debug!("Parsing VP8 frame header."); 602 let mut bd = BoolDecoder::new(data); 603 604 if frame.key_frame { 605 frame.color_space = bd.read_bool()?; 606 frame.clamping_type = bd.read_bool()?; 607 } 608 609 Parser::update_segmentation(&mut bd, &mut self.segmentation)?; 610 611 frame.filter_type = bd.read_bool()?; 612 frame.loop_filter_level = bd.read_uint(6)?; 613 frame.sharpness_level = bd.read_uint(3)?; 614 615 Parser::parse_mb_lf_adjustments(&mut bd, &mut self.mb_lf_adjust)?; 616 617 frame.log2_nbr_of_dct_partitions = bd.read_uint(2)?; 618 619 Parser::parse_quant_indices(&mut bd, &mut frame.quant_indices)?; 620 621 frame.copy_buffer_to_golden = 0; 622 frame.copy_buffer_to_alternate = 0; 623 624 if frame.key_frame { 625 frame.refresh_entropy_probs = bd.read_bool()?; 626 627 frame.refresh_last = true; 628 frame.refresh_golden_frame = true; 629 frame.refresh_alternate_frame = true; 630 631 Parser::mode_probs_init_defaults(&mut frame.mode_probs, true); 632 } else { 633 frame.refresh_golden_frame = bd.read_bool()?; 634 frame.refresh_alternate_frame = bd.read_bool()?; 635 636 if !frame.refresh_golden_frame { 637 frame.copy_buffer_to_golden = bd.read_uint(2)?; 638 } 639 640 if !frame.refresh_alternate_frame { 641 frame.copy_buffer_to_alternate = bd.read_uint(2)?; 642 } 643 644 frame.sign_bias_golden = bd.read_bool()?; 645 frame.sign_bias_alternate = bd.read_bool()?; 646 frame.refresh_entropy_probs = bd.read_bool()?; 647 frame.refresh_last = bd.read_bool()?; 648 649 frame.mode_probs = self.mode_probs.clone(); 650 } 651 652 frame.coeff_prob = self.coeff_prob; 653 frame.mv_prob = self.mv_prob; 654 655 Parser::parse_token_prob_update(&mut bd, &mut frame.coeff_prob)?; 656 657 frame.mb_no_coeff_skip = bd.read_bool()?; 658 if frame.mb_no_coeff_skip { 659 frame.prob_skip_false = bd.read_uint(8)?; 660 } 661 662 if !frame.key_frame { 663 frame.prob_intra = bd.read_uint(8)?; 664 frame.prob_last = bd.read_uint(8)?; 665 frame.prob_golden = bd.read_uint(8)?; 666 667 let intra_16x16_prob_update_flag = bd.read_bool()?; 668 if intra_16x16_prob_update_flag { 669 for prob in frame.mode_probs.intra_16x16_prob.iter_mut() { 670 *prob = bd.read_uint(8)?; 671 } 672 } 673 674 let intra_chroma_prob_update_flag = bd.read_bool()?; 675 if intra_chroma_prob_update_flag { 676 for prob in frame.mode_probs.intra_chroma_prob.iter_mut() { 677 *prob = bd.read_uint(8)?; 678 } 679 } 680 681 Parser::parse_mv_prob_update(&mut bd, &mut frame.mv_prob)?; 682 } 683 684 if frame.refresh_entropy_probs { 685 self.coeff_prob = frame.coeff_prob; 686 self.mv_prob = frame.mv_prob; 687 688 if !frame.key_frame { 689 self.mode_probs = frame.mode_probs.clone(); 690 } 691 } 692 693 frame.header_size = bd.pos() as u32; 694 695 let state: BoolDecoderState = bd.into(); 696 frame.bd_range = state.range; 697 frame.bd_value = state.value; 698 frame.bd_count = state.count; 699 700 Ok(()) 701 } 702 703 /// Parse a single frame from the chunk in `data`. parse_frame<'a>(&mut self, bitstream: &'a [u8]) -> Result<Frame<'a>, ParseFrameError>704 pub fn parse_frame<'a>(&mut self, bitstream: &'a [u8]) -> Result<Frame<'a>, ParseFrameError> { 705 let mut header = Header::parse_uncompressed_data_chunk(bitstream)?; 706 if header.key_frame { 707 // Reset on every key frame. 708 *self = Default::default(); 709 } 710 711 let first_part_end = header.data_chunk_size as usize + header.first_part_size as usize; 712 713 if first_part_end > bitstream.len() { 714 return Err(ParseFrameError::InvalidPartitionSize(first_part_end, bitstream.len())); 715 } 716 717 let compressed_area = &bitstream[header.data_chunk_size as usize..]; 718 719 self.parse_frame_header(compressed_area, &mut header)?; 720 header.compute_partition_sizes(compressed_area)?; 721 722 let frame_len = header.frame_len(); 723 if frame_len > bitstream.as_ref().len() { 724 return Err(ParseFrameError::BitstreamTooShort(bitstream.as_ref().len(), frame_len)); 725 } 726 727 Ok(Frame { bitstream, frame_len, header }) 728 } 729 } 730 731 impl Default for Parser { default() -> Self732 fn default() -> Self { 733 Self { 734 segmentation: Default::default(), 735 mb_lf_adjust: Default::default(), 736 coeff_prob: COEFF_DEFAULT_PROBS, 737 mv_prob: MV_DEFAULT_PROBS, 738 mode_probs: ModeProbs { 739 intra_16x16_prob: NK_Y_MODE_PROBS, 740 intra_chroma_prob: NK_UV_MODE_PROBS, 741 }, 742 } 743 } 744 } 745 746 #[cfg(test)] 747 mod tests { 748 use super::Parser; 749 750 // Test and test data extracted from GStreamer 751 // subprojects/gst-plugins-bad/tests/check/libs/vp8parser.c 752 const VP8_TEST_0_INTRA: &[u8] = include_bytes!("test_data/vp8-parser-test-0-intra.bin"); 753 const VP8_TEST_0_INTER: &[u8] = include_bytes!("test_data/vp8-parser-test-0-inter.bin"); 754 755 #[test] gst_intra()756 fn gst_intra() { 757 let mut parser = Parser::default(); 758 let frame = parser.parse_frame(VP8_TEST_0_INTRA).expect("Parsing a intra frame failed"); 759 760 assert!(frame.header.key_frame); 761 762 assert_eq!(frame.header.first_part_size, 234); 763 assert_eq!(frame.header.width, 176); 764 assert_eq!(frame.header.height, 144); 765 766 assert!(parser.mb_lf_adjust.loop_filter_adj_enable); 767 assert!(parser.mb_lf_adjust.mode_ref_lf_delta_update); 768 769 assert_eq!(parser.mb_lf_adjust.ref_frame_delta[0], 2); 770 assert_eq!(parser.mb_lf_adjust.ref_frame_delta[1], 0); 771 assert_eq!(parser.mb_lf_adjust.ref_frame_delta[2], -2); 772 assert_eq!(parser.mb_lf_adjust.ref_frame_delta[3], -2); 773 774 assert_eq!(parser.mb_lf_adjust.mb_mode_delta[0], 4); 775 assert_eq!(parser.mb_lf_adjust.mb_mode_delta[1], -2); 776 assert_eq!(parser.mb_lf_adjust.mb_mode_delta[2], 2); 777 assert_eq!(parser.mb_lf_adjust.mb_mode_delta[3], 4); 778 779 assert_eq!(frame.header.quant_indices.y_ac_qi, 4); 780 assert!(frame.header.mb_no_coeff_skip); 781 782 assert_eq!(frame.header.bd_range, 0xe8); 783 assert_eq!(frame.header.bd_value, 0x68); 784 assert_eq!(frame.header.bd_count, 1); 785 } 786 787 #[test] gst_inter()788 fn gst_inter() { 789 let mut parser = Parser::default(); 790 let frame = parser.parse_frame(VP8_TEST_0_INTER).expect("Parsing a inter frame failed"); 791 792 assert!(!frame.header.key_frame); 793 794 assert_eq!(frame.header.first_part_size, 98); 795 assert!(parser.mb_lf_adjust.loop_filter_adj_enable); 796 assert_eq!(frame.header.quant_indices.y_ac_qi, 4); 797 798 assert!(frame.header.refresh_entropy_probs); 799 assert!(frame.header.refresh_last); 800 assert!(frame.header.mb_no_coeff_skip); 801 802 assert_eq!(frame.header.prob_skip_false, 131); 803 assert_eq!(frame.header.prob_intra, 224); 804 assert_eq!(frame.header.prob_last, 233); 805 assert_eq!(frame.header.prob_golden, 1); 806 807 assert_eq!(frame.header.bd_range, 0x8e); 808 assert_eq!(frame.header.bd_value, 0x85); 809 assert_eq!(frame.header.bd_count, 5); 810 } 811 } 812