1use crate::decoder::quant::{parse_quantization, Quantization};
2use crate::decoder::tree::{
3 parse_intra_mode_row, parse_probability_tables, parse_probability_updates, MacroBlockHeader,
4 ProbabilityTables, ProbabilityUpdateSummary,
5};
6use crate::decoder::vp8i::{
7 B_DC_PRED, MAX_NUM_PARTITIONS, MB_FEATURE_TREE_PROBS, NUM_MB_SEGMENTS, NUM_MODE_LF_DELTAS,
8 NUM_REF_LF_DELTAS, VP8L_FRAME_HEADER_SIZE, VP8_FRAME_HEADER_SIZE,
9};
10use crate::decoder::DecoderError;
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq)]
13pub struct Vp8FrameHeader {
14 pub key_frame: bool,
15 pub profile: u8,
16 pub show: bool,
17 pub partition_length: usize,
18}
19
20#[derive(Debug, Clone, Copy, PartialEq, Eq)]
21pub struct Vp8PictureHeader {
22 pub width: u16,
23 pub height: u16,
24 pub xscale: u8,
25 pub yscale: u8,
26 pub colorspace: u8,
27 pub clamp_type: u8,
28}
29
30#[derive(Debug, Clone, Copy, PartialEq, Eq)]
31pub struct SegmentHeader {
32 pub use_segment: bool,
33 pub update_map: bool,
34 pub absolute_delta: bool,
35 pub quantizer: [i8; NUM_MB_SEGMENTS],
36 pub filter_strength: [i8; NUM_MB_SEGMENTS],
37 pub segment_probs: [u8; MB_FEATURE_TREE_PROBS],
38}
39
40impl Default for SegmentHeader {
41 fn default() -> Self {
42 Self {
43 use_segment: false,
44 update_map: false,
45 absolute_delta: true,
46 quantizer: [0; NUM_MB_SEGMENTS],
47 filter_strength: [0; NUM_MB_SEGMENTS],
48 segment_probs: [255; MB_FEATURE_TREE_PROBS],
49 }
50 }
51}
52
53#[derive(Debug, Clone, Copy, PartialEq, Eq)]
54pub enum FilterType {
55 Off,
56 Simple,
57 Complex,
58}
59
60#[derive(Debug, Clone, Copy, PartialEq, Eq)]
61pub struct FilterHeader {
62 pub simple: bool,
63 pub level: u8,
64 pub sharpness: u8,
65 pub use_lf_delta: bool,
66 pub ref_lf_delta: [i8; NUM_REF_LF_DELTAS],
67 pub mode_lf_delta: [i8; NUM_MODE_LF_DELTAS],
68 pub filter_type: FilterType,
69}
70
71#[derive(Debug, Clone, Copy, PartialEq, Eq)]
72pub struct LosslessInfo {
73 pub width: usize,
74 pub height: usize,
75 pub has_alpha: bool,
76}
77
78#[derive(Debug, Clone, PartialEq, Eq)]
79pub struct LossyHeader {
80 pub frame: Vp8FrameHeader,
81 pub picture: Vp8PictureHeader,
82 pub macroblock_width: usize,
83 pub macroblock_height: usize,
84 pub segment: SegmentHeader,
85 pub filter: FilterHeader,
86 pub token_partition_sizes: Vec<usize>,
87 pub quantization: Quantization,
88 pub probabilities: ProbabilityUpdateSummary,
89}
90
91#[derive(Debug, Clone, PartialEq, Eq)]
92pub struct MacroBlockHeaders {
93 pub frame: LossyHeader,
94 pub macroblocks: Vec<MacroBlockHeader>,
95}
96
97#[derive(Debug, Clone, PartialEq, Eq)]
98pub struct MacroBlockData {
99 pub header: MacroBlockHeader,
100 pub coeffs: [i16; 384],
101 pub non_zero_y: u32,
102 pub non_zero_uv: u32,
103}
104
105#[derive(Debug, Clone, PartialEq, Eq)]
106pub struct MacroBlockDataFrame {
107 pub frame: LossyHeader,
108 pub macroblocks: Vec<MacroBlockData>,
109}
110
111#[derive(Debug, Clone, Copy, Default)]
112struct NonZeroContext {
113 nz: u8,
114 nz_dc: u8,
115}
116
117#[derive(Debug, Clone)]
118pub struct Vp8BoolDecoder<'a> {
119 data: &'a [u8],
120 position: usize,
121 value: u64,
122 range: u32,
123 bits: i32,
124 eof: bool,
125}
126
127impl<'a> Vp8BoolDecoder<'a> {
128 pub fn new(data: &'a [u8]) -> Self {
129 let mut reader = Self {
130 data,
131 position: 0,
132 value: 0,
133 range: 255 - 1,
134 bits: -8,
135 eof: false,
136 };
137 reader.load_new_bytes();
138 reader
139 }
140
141 pub fn eof(&self) -> bool {
142 self.eof
143 }
144
145 fn load_new_bytes(&mut self) {
146 while self.bits < 0 {
147 if self.position < self.data.len() {
148 self.bits += 8;
149 self.value = (self.value << 8) | self.data[self.position] as u64;
150 self.position += 1;
151 } else if !self.eof {
152 self.value <<= 8;
153 self.bits += 8;
154 self.eof = true;
155 } else {
156 self.bits = 0;
157 }
158 }
159 }
160
161 pub fn get(&mut self) -> u32 {
162 self.get_bit(0x80)
163 }
164
165 pub fn get_value(&mut self, num_bits: usize) -> u32 {
166 let mut value = 0u32;
167 for bit_index in (0..num_bits).rev() {
168 value |= self.get() << bit_index;
169 }
170 value
171 }
172
173 pub fn get_signed_value(&mut self, num_bits: usize) -> i32 {
174 let value = self.get_value(num_bits) as i32;
175 if self.get() == 1 {
176 -value
177 } else {
178 value
179 }
180 }
181
182 pub fn get_signed(&mut self, value: i32) -> i32 {
183 if self.get() == 1 {
184 -value
185 } else {
186 value
187 }
188 }
189
190 pub fn get_bit(&mut self, prob: u8) -> u32 {
191 if self.bits < 0 {
192 self.load_new_bytes();
193 }
194
195 let pos = self.bits as u32;
196 let mut range = self.range;
197 let split = (range * prob as u32) >> 8;
198 let value = (self.value >> pos) as u32;
199 let bit = (value > split) as u32;
200 if bit == 1 {
201 range -= split;
202 self.value -= ((split + 1) as u64) << pos;
203 } else {
204 range = split + 1;
205 }
206
207 let shift = 7 ^ (31 - range.leading_zeros()) as i32;
208 range <<= shift as u32;
209 self.bits -= shift;
210 self.range = range - 1;
211 bit
212 }
213}
214
215pub fn check_lossy_signature(data: &[u8]) -> bool {
216 data.len() >= 3 && data[0] == 0x9d && data[1] == 0x01 && data[2] == 0x2a
217}
218
219pub fn get_info(data: &[u8], chunk_size: usize) -> Result<(usize, usize), DecoderError> {
220 if data.len() < VP8_FRAME_HEADER_SIZE {
221 return Err(DecoderError::NotEnoughData("VP8 frame header"));
222 }
223 if !check_lossy_signature(&data[3..]) {
224 return Err(DecoderError::Bitstream("bad VP8 signature"));
225 }
226
227 let bits = data[0] as u32 | ((data[1] as u32) << 8) | ((data[2] as u32) << 16);
228 let key_frame = (bits & 1) == 0;
229 let profile = ((bits >> 1) & 0x07) as u8;
230 let show = ((bits >> 4) & 1) == 1;
231 let partition_length = (bits >> 5) as usize;
232 let width = ((((data[7] as u16) << 8) | data[6] as u16) & 0x3fff) as usize;
233 let height = ((((data[9] as u16) << 8) | data[8] as u16) & 0x3fff) as usize;
234
235 if !key_frame {
236 return Err(DecoderError::Unsupported("interframes are not supported"));
237 }
238 if profile > 3 {
239 return Err(DecoderError::Bitstream("unknown VP8 profile"));
240 }
241 if !show {
242 return Err(DecoderError::Unsupported("invisible VP8 frame"));
243 }
244 if partition_length >= chunk_size {
245 return Err(DecoderError::Bitstream("bad VP8 partition length"));
246 }
247 if width == 0 || height == 0 {
248 return Err(DecoderError::Bitstream("invalid VP8 dimensions"));
249 }
250
251 Ok((width, height))
252}
253
254pub fn check_lossless_signature(data: &[u8]) -> bool {
255 data.len() >= VP8L_FRAME_HEADER_SIZE && data[0] == 0x2f && (data[4] >> 5) == 0
256}
257
258pub fn get_lossless_info(data: &[u8]) -> Result<LosslessInfo, DecoderError> {
259 if data.len() < VP8L_FRAME_HEADER_SIZE {
260 return Err(DecoderError::NotEnoughData("VP8L frame header"));
261 }
262 if !check_lossless_signature(data) {
263 return Err(DecoderError::Bitstream("bad VP8L signature"));
264 }
265
266 let bits = u32::from_le_bytes([data[1], data[2], data[3], data[4]]);
267 let width = ((bits & 0x3fff) + 1) as usize;
268 let height = (((bits >> 14) & 0x3fff) + 1) as usize;
269 let has_alpha = ((bits >> 28) & 1) == 1;
270 let version = (bits >> 29) & 0x07;
271
272 if version != 0 {
273 return Err(DecoderError::Bitstream("unsupported VP8L version"));
274 }
275
276 Ok(LosslessInfo {
277 width,
278 height,
279 has_alpha,
280 })
281}
282
283fn parse_segment_header(br: &mut Vp8BoolDecoder<'_>) -> Result<SegmentHeader, DecoderError> {
284 let mut header = SegmentHeader {
285 use_segment: br.get() == 1,
286 ..SegmentHeader::default()
287 };
288 if header.use_segment {
289 header.update_map = br.get() == 1;
290 if br.get() == 1 {
291 header.absolute_delta = br.get() == 1;
292 for value in &mut header.quantizer {
293 *value = if br.get() == 1 {
294 br.get_signed_value(7) as i8
295 } else {
296 0
297 };
298 }
299 for value in &mut header.filter_strength {
300 *value = if br.get() == 1 {
301 br.get_signed_value(6) as i8
302 } else {
303 0
304 };
305 }
306 }
307 if header.update_map {
308 for value in &mut header.segment_probs {
309 *value = if br.get() == 1 {
310 br.get_value(8) as u8
311 } else {
312 255
313 };
314 }
315 }
316 }
317
318 if br.eof() {
319 return Err(DecoderError::Bitstream("cannot parse segment header"));
320 }
321
322 Ok(header)
323}
324
325fn parse_filter_header(br: &mut Vp8BoolDecoder<'_>) -> Result<FilterHeader, DecoderError> {
326 let simple = br.get() == 1;
327 let level = br.get_value(6) as u8;
328 let sharpness = br.get_value(3) as u8;
329 let use_lf_delta = br.get() == 1;
330 let mut header = FilterHeader {
331 simple,
332 level,
333 sharpness,
334 use_lf_delta,
335 ref_lf_delta: [0; NUM_REF_LF_DELTAS],
336 mode_lf_delta: [0; NUM_MODE_LF_DELTAS],
337 filter_type: FilterType::Off,
338 };
339
340 if use_lf_delta && br.get() == 1 {
341 for value in &mut header.ref_lf_delta {
342 if br.get() == 1 {
343 *value = br.get_signed_value(6) as i8;
344 }
345 }
346 for value in &mut header.mode_lf_delta {
347 if br.get() == 1 {
348 *value = br.get_signed_value(6) as i8;
349 }
350 }
351 }
352
353 header.filter_type = if level == 0 {
354 FilterType::Off
355 } else if simple {
356 FilterType::Simple
357 } else {
358 FilterType::Complex
359 };
360
361 if br.eof() {
362 return Err(DecoderError::Bitstream("cannot parse filter header"));
363 }
364
365 Ok(header)
366}
367
368fn parse_token_partitions(
369 br: &mut Vp8BoolDecoder<'_>,
370 data: &[u8],
371) -> Result<Vec<usize>, DecoderError> {
372 let num_parts_minus_one = (1usize << br.get_value(2)) - 1;
373 if num_parts_minus_one >= MAX_NUM_PARTITIONS {
374 return Err(DecoderError::Bitstream("too many VP8 token partitions"));
375 }
376
377 let size_bytes = num_parts_minus_one * 3;
378 if data.len() < size_bytes {
379 return Err(DecoderError::NotEnoughData("VP8 token partition sizes"));
380 }
381
382 let mut partitions = Vec::with_capacity(num_parts_minus_one + 1);
383 let mut size_left = data.len() - size_bytes;
384 for chunk in data[..size_bytes].chunks_exact(3) {
385 let stored = chunk[0] as usize | ((chunk[1] as usize) << 8) | ((chunk[2] as usize) << 16);
386 let actual = stored.min(size_left);
387 partitions.push(actual);
388 size_left -= actual;
389 }
390 partitions.push(size_left);
391
392 if data.len() == size_bytes {
393 return Err(DecoderError::NotEnoughData("VP8 token partitions"));
394 }
395
396 Ok(partitions)
397}
398
399const CAT3: [u8; 4] = [173, 148, 140, 0];
400const CAT4: [u8; 5] = [176, 155, 140, 135, 0];
401const CAT5: [u8; 6] = [180, 157, 141, 134, 130, 0];
402const CAT6: [u8; 12] = [254, 254, 243, 230, 196, 177, 153, 140, 133, 130, 129, 0];
403const ZIGZAG: [usize; 16] = [0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15];
404
405fn transform_wht(input: &[i16; 16]) -> [i16; 16] {
406 let mut tmp = [0i32; 16];
407 for i in 0..4 {
408 let a0 = input[i] as i32 + input[12 + i] as i32;
409 let a1 = input[4 + i] as i32 + input[8 + i] as i32;
410 let a2 = input[4 + i] as i32 - input[8 + i] as i32;
411 let a3 = input[i] as i32 - input[12 + i] as i32;
412 tmp[i] = a0 + a1;
413 tmp[8 + i] = a0 - a1;
414 tmp[4 + i] = a3 + a2;
415 tmp[12 + i] = a3 - a2;
416 }
417
418 let mut out = [0i16; 16];
419 for i in 0..4 {
420 let base = i * 4;
421 let dc = tmp[base] + 3;
422 let a0 = dc + tmp[base + 3];
423 let a1 = tmp[base + 1] + tmp[base + 2];
424 let a2 = tmp[base + 1] - tmp[base + 2];
425 let a3 = dc - tmp[base + 3];
426 out[base] = ((a0 + a1) >> 3) as i16;
427 out[base + 1] = ((a3 + a2) >> 3) as i16;
428 out[base + 2] = ((a0 - a1) >> 3) as i16;
429 out[base + 3] = ((a3 - a2) >> 3) as i16;
430 }
431 out
432}
433
434fn get_large_value(br: &mut Vp8BoolDecoder<'_>, p: &[u8; 11]) -> i32 {
435 if br.get_bit(p[3]) == 0 {
436 if br.get_bit(p[4]) == 0 {
437 2
438 } else {
439 3 + br.get_bit(p[5]) as i32
440 }
441 } else if br.get_bit(p[6]) == 0 {
442 if br.get_bit(p[7]) == 0 {
443 5 + br.get_bit(159) as i32
444 } else {
445 7 + 2 * br.get_bit(165) as i32 + br.get_bit(145) as i32
446 }
447 } else {
448 let (cat, table): (usize, &[u8]) = if br.get_bit(p[8]) == 0 {
449 if br.get_bit(p[9]) == 0 {
450 (0, &CAT3)
451 } else {
452 (1, &CAT4)
453 }
454 } else if br.get_bit(p[10]) == 0 {
455 (2, &CAT5)
456 } else {
457 (3, &CAT6)
458 };
459 let mut value = 0i32;
460 for &prob in table {
461 if prob == 0 {
462 break;
463 }
464 value = value + value + br.get_bit(prob) as i32;
465 }
466 value + 3 + (8 << cat) as i32
467 }
468}
469
470fn get_coeffs(
471 br: &mut Vp8BoolDecoder<'_>,
472 probabilities: &ProbabilityTables,
473 coeff_type: usize,
474 ctx: usize,
475 dq: [u16; 2],
476 start: usize,
477 out: &mut [i16],
478) -> usize {
479 let mut n = start;
480 let mut p = probabilities.coeff_probs(coeff_type, n, ctx);
481 while n < 16 {
482 if br.get_bit(p[0]) == 0 {
483 return n;
484 }
485 while br.get_bit(p[1]) == 0 {
486 n += 1;
487 if n == 16 {
488 return 16;
489 }
490 p = probabilities.coeff_probs(coeff_type, n, 0);
491 }
492
493 let next_ctx;
494 let value = if br.get_bit(p[2]) == 0 {
495 next_ctx = 1;
496 1
497 } else {
498 next_ctx = 2;
499 get_large_value(br, p)
500 };
501 let dequant = if n > 0 { dq[1] } else { dq[0] } as i32;
502 out[ZIGZAG[n]] = (br.get_signed(value) * dequant) as i16;
503 n += 1;
504 p = probabilities.coeff_probs(coeff_type, n, next_ctx);
505 }
506 16
507}
508
509fn nz_code_bits(nz_coeffs: u32, nz: usize, dc_nz: bool) -> u32 {
510 (nz_coeffs << 2)
511 | if nz > 3 {
512 3
513 } else if nz > 1 {
514 2
515 } else if dc_nz {
516 1
517 } else {
518 0
519 }
520}
521
522fn parse_residuals(
523 header: MacroBlockHeader,
524 top: &mut NonZeroContext,
525 left: &mut NonZeroContext,
526 token_br: &mut Vp8BoolDecoder<'_>,
527 quantization: &Quantization,
528 probabilities: &ProbabilityTables,
529) -> MacroBlockData {
530 let mut coeffs = [0i16; 384];
531 if header.skip {
532 top.nz = 0;
533 left.nz = 0;
534 if !header.is_i4x4 {
535 top.nz_dc = 0;
536 left.nz_dc = 0;
537 }
538 return MacroBlockData {
539 header,
540 coeffs,
541 non_zero_y: 0,
542 non_zero_uv: 0,
543 };
544 }
545
546 let q = &quantization.matrices[header.segment as usize];
547 let mut offset = 0usize;
548 let first;
549 let coeff_type;
550 if !header.is_i4x4 {
551 let mut dc = [0i16; 16];
552 let ctx = (top.nz_dc + left.nz_dc) as usize;
553 let nz = get_coeffs(token_br, probabilities, 1, ctx, q.y2, 0, &mut dc);
554 let has_dc = nz > 0;
555 top.nz_dc = has_dc as u8;
556 left.nz_dc = has_dc as u8;
557 if nz > 1 {
558 let transformed = transform_wht(&dc);
559 for (block, value) in transformed.into_iter().enumerate() {
560 coeffs[block * 16] = value;
561 }
562 } else {
563 let dc0 = ((dc[0] as i32 + 3) >> 3) as i16;
564 for block in 0..16 {
565 coeffs[block * 16] = dc0;
566 }
567 }
568 first = 1;
569 coeff_type = 0;
570 } else {
571 first = 0;
572 coeff_type = 3;
573 }
574
575 let mut non_zero_y = 0u32;
576 let mut tnz = top.nz & 0x0f;
577 let mut lnz = left.nz & 0x0f;
578 for _y in 0..4 {
579 let mut l = lnz & 1;
580 let mut nz_coeffs = 0u32;
581 for _x in 0..4 {
582 let ctx = (l + (tnz & 1)) as usize;
583 let nz = get_coeffs(
584 token_br,
585 probabilities,
586 coeff_type,
587 ctx,
588 q.y1,
589 first,
590 &mut coeffs[offset..offset + 16],
591 );
592 l = (nz > first) as u8;
593 tnz = (tnz >> 1) | (l << 7);
594 nz_coeffs = nz_code_bits(nz_coeffs, nz, coeffs[offset] != 0);
595 offset += 16;
596 }
597 tnz >>= 4;
598 lnz = (lnz >> 1) | (l << 7);
599 non_zero_y = (non_zero_y << 8) | nz_coeffs;
600 }
601
602 let mut out_t_nz = tnz;
603 let mut out_l_nz = lnz >> 4;
604 let mut non_zero_uv = 0u32;
605 for ch in [0usize, 2usize] {
606 let mut nz_coeffs = 0u32;
607 let mut tnz = top.nz >> (4 + ch);
608 let mut lnz = left.nz >> (4 + ch);
609 for _y in 0..2 {
610 let mut l = lnz & 1;
611 for _x in 0..2 {
612 let ctx = (l + (tnz & 1)) as usize;
613 let nz = get_coeffs(
614 token_br,
615 probabilities,
616 2,
617 ctx,
618 q.uv,
619 0,
620 &mut coeffs[offset..offset + 16],
621 );
622 l = (nz > 0) as u8;
623 tnz = (tnz >> 1) | (l << 3);
624 nz_coeffs = nz_code_bits(nz_coeffs, nz, coeffs[offset] != 0);
625 offset += 16;
626 }
627 tnz >>= 2;
628 lnz = (lnz >> 1) | (l << 5);
629 }
630 non_zero_uv |= nz_coeffs << (4 * ch);
631 out_t_nz |= (tnz << 4) << ch;
632 out_l_nz |= (lnz & 0xf0) << ch;
633 }
634 top.nz = out_t_nz;
635 left.nz = out_l_nz;
636
637 MacroBlockData {
638 header,
639 coeffs,
640 non_zero_y,
641 non_zero_uv,
642 }
643}
644
645pub fn parse_lossy_headers(data: &[u8]) -> Result<LossyHeader, DecoderError> {
646 if data.len() < VP8_FRAME_HEADER_SIZE {
647 return Err(DecoderError::NotEnoughData("VP8 frame header"));
648 }
649
650 let frame_bits = data[0] as u32 | ((data[1] as u32) << 8) | ((data[2] as u32) << 16);
651 let frame = Vp8FrameHeader {
652 key_frame: (frame_bits & 1) == 0,
653 profile: ((frame_bits >> 1) & 0x07) as u8,
654 show: ((frame_bits >> 4) & 1) == 1,
655 partition_length: (frame_bits >> 5) as usize,
656 };
657 if !frame.key_frame {
658 return Err(DecoderError::Unsupported("interframes are not supported"));
659 }
660 if frame.profile > 3 {
661 return Err(DecoderError::Bitstream("unknown VP8 profile"));
662 }
663 if !frame.show {
664 return Err(DecoderError::Unsupported("invisible VP8 frame"));
665 }
666 if !check_lossy_signature(&data[3..]) {
667 return Err(DecoderError::Bitstream("bad VP8 signature"));
668 }
669
670 let picture = Vp8PictureHeader {
671 width: (((data[7] as u16) << 8) | data[6] as u16) & 0x3fff,
672 height: (((data[9] as u16) << 8) | data[8] as u16) & 0x3fff,
673 xscale: data[7] >> 6,
674 yscale: data[9] >> 6,
675 colorspace: 0,
676 clamp_type: 0,
677 };
678 if picture.width == 0 || picture.height == 0 {
679 return Err(DecoderError::Bitstream("invalid VP8 dimensions"));
680 }
681
682 let partition0_offset = VP8_FRAME_HEADER_SIZE;
683 let partition0_end = partition0_offset + frame.partition_length;
684 if partition0_end > data.len() {
685 return Err(DecoderError::NotEnoughData("VP8 partition 0"));
686 }
687
688 let mut br = Vp8BoolDecoder::new(&data[partition0_offset..partition0_end]);
689 let mut picture = picture;
690 picture.colorspace = br.get() as u8;
691 picture.clamp_type = br.get() as u8;
692
693 let segment = parse_segment_header(&mut br)?;
694 let filter = parse_filter_header(&mut br)?;
695 let token_partition_sizes = parse_token_partitions(&mut br, &data[partition0_end..])?;
696 let quantization = parse_quantization(&mut br, &segment)?;
697 let _ = br.get();
698 let probabilities = parse_probability_updates(&mut br)?;
699
700 Ok(LossyHeader {
701 frame,
702 picture,
703 macroblock_width: (picture.width as usize + 15) >> 4,
704 macroblock_height: (picture.height as usize + 15) >> 4,
705 segment,
706 filter,
707 token_partition_sizes,
708 quantization,
709 probabilities,
710 })
711}
712
713pub fn parse_macroblock_headers(data: &[u8]) -> Result<MacroBlockHeaders, DecoderError> {
714 let frame = parse_lossy_headers(data)?;
715
716 let partition0_offset = VP8_FRAME_HEADER_SIZE;
717 let partition0_end = partition0_offset + frame.frame.partition_length;
718 let mut br = Vp8BoolDecoder::new(&data[partition0_offset..partition0_end]);
719
720 let _ = br.get();
721 let _ = br.get();
722 let segment = parse_segment_header(&mut br)?;
723 let _ = parse_filter_header(&mut br)?;
724 let _ = parse_token_partitions(&mut br, &data[partition0_end..])?;
725 let _ = parse_quantization(&mut br, &segment)?;
726 let _ = br.get();
727 let probabilities = parse_probability_updates(&mut br)?;
728
729 let mut top_modes = vec![B_DC_PRED; frame.macroblock_width * 4];
730 let mut macroblocks = Vec::with_capacity(frame.macroblock_width * frame.macroblock_height);
731 for _mb_y in 0..frame.macroblock_height {
732 let mut left_modes = [B_DC_PRED; 4];
733 let row = parse_intra_mode_row(
734 &mut br,
735 frame.macroblock_width,
736 segment.update_map,
737 &segment.segment_probs,
738 probabilities.use_skip_probability,
739 probabilities.skip_probability.unwrap_or(0),
740 &mut top_modes,
741 &mut left_modes,
742 )?;
743 macroblocks.extend(row);
744 }
745
746 Ok(MacroBlockHeaders { frame, macroblocks })
747}
748
749pub fn parse_macroblock_data(data: &[u8]) -> Result<MacroBlockDataFrame, DecoderError> {
750 let frame = parse_lossy_headers(data)?;
751 let partition0_offset = VP8_FRAME_HEADER_SIZE;
752 let partition0_end = partition0_offset + frame.frame.partition_length;
753 let mut br = Vp8BoolDecoder::new(&data[partition0_offset..partition0_end]);
754
755 let _ = br.get();
756 let _ = br.get();
757 let segment = parse_segment_header(&mut br)?;
758 let _ = parse_filter_header(&mut br)?;
759 let token_partition_sizes = parse_token_partitions(&mut br, &data[partition0_end..])?;
760 let quantization = parse_quantization(&mut br, &segment)?;
761 let _ = br.get();
762 let probabilities = parse_probability_tables(&mut br)?;
763
764 let partition_size_bytes = (token_partition_sizes.len() - 1) * 3;
765 let mut token_offset = partition0_end + partition_size_bytes;
766 let mut token_readers = Vec::with_capacity(token_partition_sizes.len());
767 for size in &token_partition_sizes {
768 let end = token_offset + *size;
769 token_readers.push(Vp8BoolDecoder::new(&data[token_offset..end]));
770 token_offset = end;
771 }
772
773 let mut top_modes = vec![B_DC_PRED; frame.macroblock_width * 4];
774 let mut top_contexts = vec![NonZeroContext::default(); frame.macroblock_width];
775 let part_mask = token_readers.len() - 1;
776 let mut macroblocks = Vec::with_capacity(frame.macroblock_width * frame.macroblock_height);
777
778 for mb_y in 0..frame.macroblock_height {
779 let mut left_modes = [B_DC_PRED; 4];
780 let row = parse_intra_mode_row(
781 &mut br,
782 frame.macroblock_width,
783 segment.update_map,
784 &segment.segment_probs,
785 probabilities.summary.use_skip_probability,
786 probabilities.summary.skip_probability.unwrap_or(0),
787 &mut top_modes,
788 &mut left_modes,
789 )?;
790
791 let token_br = &mut token_readers[mb_y & part_mask];
792 let mut left_context = NonZeroContext::default();
793 for (mb_x, header) in row.into_iter().enumerate() {
794 let mb = parse_residuals(
795 header,
796 &mut top_contexts[mb_x],
797 &mut left_context,
798 token_br,
799 &quantization,
800 &probabilities,
801 );
802 macroblocks.push(mb);
803 }
804 }
805
806 Ok(MacroBlockDataFrame { frame, macroblocks })
807}