• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2022 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 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