1use crate::bitreader::BitReader;
12use crate::error::{DecoderError, Result};
13use crate::na_msmpeg4_mv_tables::{
14 FF_MSMP4_MV_TABLE0, FF_MSMP4_MV_TABLE0_LENS, FF_MSMP4_MV_TABLE1, FF_MSMP4_MV_TABLE1_LENS,
15};
16use crate::na_msmpeg4_tables::FF_MB_NON_INTRA_TABLES;
17use crate::na_rl_tables::{
18 FF_RL_BASES, FF_WMV1_SCANTABLE, FF_WMV2_SCANTABLE_A, FF_WMV2_SCANTABLE_B,
19};
20use crate::na_simple_idct as ffidct;
21use crate::na_wmv2_tables::{FF_MSMP4_DC_TABLES, FF_MSMP4_MB_I_TABLE};
22use crate::na_wmv2dsp as wmv2dsp;
23use crate::vc1::{FrameType, PictureHeader, SequenceHeader};
24use crate::vlc::{
25 cbpcy_i_vlc, cbpcy_p_vlc, dc_chroma_vlc, dc_luma_vlc, inter_tcoef_vlc, intra_tcoef_vlc,
26 mv_diff_vlc, ttblk_vlc, ttmb_vlc, unpack_rl, wmv2_cbpc_p_vlc, wmv2_cbpy_vlc,
27 wmv2_tcoef_inter_vlc, wmv2_tcoef_intra_vlc, VlcTable, SCAN_INTRA, SCAN_VERT, VLC_ESCAPE,
28 ZIGZAG,
29};
30use crate::vlc_tree::VlcTree;
31use crate::wmv2::{Wmv2FrameHeader, Wmv2FrameType, Wmv2Params};
32
33#[derive(Clone, Debug)]
36pub struct YuvFrame {
37 pub width: u32,
38 pub height: u32,
39 pub y: Vec<u8>,
40 pub cb: Vec<u8>,
41 pub cr: Vec<u8>,
42}
43
44impl YuvFrame {
45 pub fn new(width: u32, height: u32) -> Self {
46 let y_sz = (width * height) as usize;
47 let uv_sz = y_sz / 4;
48 YuvFrame {
49 width,
50 height,
51 y: vec![16u8; y_sz],
52 cb: vec![128u8; uv_sz],
53 cr: vec![128u8; uv_sz],
54 }
55 }
56
57 pub fn to_planar_u8(&self) -> Vec<u8> {
58 let mut out = Vec::with_capacity(self.y.len() + self.cb.len() + self.cr.len());
59 out.extend_from_slice(&self.y);
60 out.extend_from_slice(&self.cb);
61 out.extend_from_slice(&self.cr);
62 out
63 }
64
65 pub fn clear(&mut self) {
66 self.y.fill(16);
67 self.cb.fill(128);
68 self.cr.fill(128);
69 }
70}
71
72#[inline(always)]
83fn idct_row8(b: &mut [i32; 8]) {
84 let t1 = 12 * b[2] + 6 * b[6];
86 let t2 = 6 * b[2] - 12 * b[6];
87 let mut s0 = b[0] + b[4];
88 let mut s1 = b[0] - b[4];
89 let s2 = s1 + (t2 >> 3);
90 let s3 = s0 - (t1 >> 3);
91 s0 += t1 >> 3;
92 s1 -= t2 >> 3;
93
94 let t0 = 16 * b[1] + 15 * b[3] + 9 * b[5] + 4 * b[7];
96 let t1 = 15 * b[1] - 4 * b[3] - 16 * b[5] - 9 * b[7];
97 let t2 = 9 * b[1] - 16 * b[3] + 4 * b[5] + 15 * b[7];
98 let t3 = 4 * b[1] - 9 * b[3] + 15 * b[5] - 16 * b[7];
99
100 b[0] = s0 + (t0 >> 3);
101 b[1] = s2 + (t2 >> 3);
102 b[2] = s1 + (t3 >> 3);
103 b[3] = s3 + (t1 >> 3);
104 b[4] = s3 - (t1 >> 3);
105 b[5] = s1 - (t3 >> 3);
106 b[6] = s2 - (t2 >> 3);
107 b[7] = s0 - (t0 >> 3);
108}
109
110#[inline(always)]
112fn idct_row4(b: &[i32; 4]) -> [i32; 4] {
113 let t0 = 17 * b[0] + 17 * b[2];
114 let t1 = 17 * b[0] - 17 * b[2];
115 let t2 = 22 * b[1] + 10 * b[3];
116 let t3 = 10 * b[1] - 22 * b[3];
117 [t0 + t2, t1 + t3, t1 - t3, t0 - t2]
118}
119
120pub fn idct8x8(blk: &mut [i32; 64]) {
121 for r in 0..8 {
123 let o = r * 8;
124 let mut row = [
125 blk[o],
126 blk[o + 1],
127 blk[o + 2],
128 blk[o + 3],
129 blk[o + 4],
130 blk[o + 5],
131 blk[o + 6],
132 blk[o + 7],
133 ];
134 idct_row8(&mut row);
135 blk[o..o + 8].copy_from_slice(&row);
136 }
137 for c in 0..8 {
139 let mut col = [
140 blk[c],
141 blk[c + 8],
142 blk[c + 16],
143 blk[c + 24],
144 blk[c + 32],
145 blk[c + 40],
146 blk[c + 48],
147 blk[c + 56],
148 ];
149 idct_row8(&mut col);
150 for r in 0..8 {
151 blk[c + r * 8] = (col[r] + 64) >> 7;
152 }
153 }
154}
155
156fn idct8x4(blk: &mut [i32; 64]) {
157 for r in 0..4 {
159 let o = r * 8;
160 let mut row = [
161 blk[o],
162 blk[o + 1],
163 blk[o + 2],
164 blk[o + 3],
165 blk[o + 4],
166 blk[o + 5],
167 blk[o + 6],
168 blk[o + 7],
169 ];
170 idct_row8(&mut row);
171 blk[o..o + 8].copy_from_slice(&row);
172 }
173 for c in 0..8 {
175 let col4 = [blk[c], blk[c + 8], blk[c + 16], blk[c + 24]];
176 let out = idct_row4(&col4);
177 for r in 0..4 {
178 blk[c + r * 8] = (out[r] + 64) >> 7;
179 }
180 let _ = col4[0]; }
182}
183
184fn idct4x8(blk: &mut [i32; 64]) {
185 for r in 0..8 {
187 let o = r * 8;
188 let col4 = [blk[o], blk[o + 1], blk[o + 2], blk[o + 3]];
189 let out = idct_row4(&col4);
190 for c in 0..4 {
191 blk[o + c] = out[c];
192 }
193 }
194 for c in 0..4 {
196 let mut col = [
197 blk[c],
198 blk[c + 8],
199 blk[c + 16],
200 blk[c + 24],
201 blk[c + 32],
202 blk[c + 40],
203 blk[c + 48],
204 blk[c + 56],
205 ];
206 idct_row8(&mut col);
207 for r in 0..8 {
208 blk[c + r * 8] = (col[r] + 64) >> 7;
209 }
210 }
211}
212
213fn idct4x4(blk: &mut [i32; 64]) {
214 for r in 0..4 {
216 let o = r * 8;
217 let col4 = [blk[o], blk[o + 1], blk[o + 2], blk[o + 3]];
218 let out = idct_row4(&col4);
219 for c in 0..4 {
220 blk[o + c] = out[c];
221 }
222 }
223 for c in 0..4 {
225 let col4 = [blk[c], blk[c + 8], blk[c + 16], blk[c + 24]];
226 let out = idct_row4(&col4);
227 for r in 0..4 {
228 blk[c + r * 8] = (out[r] + 64) >> 7;
229 }
230 }
231}
232
233pub fn apply_idct(blk: &mut [i32; 64], tt: u8) {
236 match tt {
237 0 => idct8x8(blk),
238 1 | 2 => idct8x4(blk),
239 3 | 4 => idct4x8(blk),
240 5 | 6 => idct4x4(blk),
241 _ => idct8x8(blk),
242 }
243}
244
245fn iquant_uniform(level: i32, pquant: i32, halfqp: bool) -> i32 {
249 if level == 0 {
250 return 0;
251 }
252 let step = 2 * pquant;
253 let base = step * level.abs() + pquant;
254 let delta = if halfqp { pquant } else { 0 };
255 let result = if level > 0 {
256 base + delta
257 } else {
258 -(base + delta)
259 };
260 result.clamp(-2048, 2047)
261}
262
263fn iquant_nonuniform(level: i32, pquant: i32) -> i32 {
264 if level == 0 {
265 return 0;
266 }
267 const STEP: [i32; 32] = [
269 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
270 27, 29, 31, 33, 35, 37, 63,
271 ];
272 let step = STEP[(pquant as usize).min(31)];
273 let result = step * level.abs() + pquant;
274 if level > 0 {
275 result.clamp(-2048, 2047)
276 } else {
277 (-result).clamp(-2048, 2047)
278 }
279}
280
281const DC_STEP_LUMA: [i32; 32] = [
288 0, 128, 256, 384, 512, 640, 768, 896, 1024, 1152, 1280, 1408, 1536, 1664, 1792, 1920, 2048, 2176, 2304, 2432, 2560, 2688, 2816, 2944, 3072, 3328, 3584, 3840, 4096, 4352, 4608, 8192, ];
294
295const DC_STEP_CHROMA: [i32; 32] = [
296 0, 128, 128, 128, 256, 256, 384, 384, 512, 512, 640, 640, 768, 768, 896, 896, 1024, 1024, 1152, 1152, 1280, 1280, 1408, 1408, 1536, 1664, 1792, 1920, 2048, 2176, 2304, 4096, ];
302
303#[inline]
304fn dc_step(pquant: i32, is_luma: bool) -> i32 {
305 let idx = pquant.clamp(1, 31) as usize;
306 if is_luma {
307 DC_STEP_LUMA[idx]
308 } else {
309 DC_STEP_CHROMA[idx]
310 }
311}
312
313#[inline(always)]
324fn lf_filter4(p: &mut [u8], a: usize, b: usize, c: usize, d: usize) {
325 let p1 = p[a] as i32;
326 let p2 = p[b] as i32;
327 let p3 = p[c] as i32;
328 let p4 = p[d] as i32;
329 let mut delta = (p1 - 2 * p2 + 2 * p3 - p4 + 4) >> 3;
330 delta = delta.clamp(-p2, 255 - p3);
331 p[b] = (p2 + delta) as u8;
332 p[c] = (p3 - delta) as u8;
333}
334
335fn loop_filter_plane(plane: &mut Vec<u8>, stride: usize, height: usize) {
339 let w = stride;
340 let h = height;
341 if w < 16 || h < 16 {
342 return;
343 } for x in (8..w - 1).step_by(8) {
348 for y in 0..h {
349 let base = y * w;
350 if x + 1 < w {
352 lf_filter4(plane, base + x - 2, base + x - 1, base + x, base + x + 1);
353 }
354 }
355 }
356
357 for y in (8..h - 1).step_by(8) {
360 for x in 0..w {
361 let a = (y - 2) * w + x;
363 let b = (y - 1) * w + x;
364 let c = y * w + x;
365 let d = (y + 1) * w + x;
366 lf_filter4(plane, a, b, c, d);
367 }
368 }
369}
370
371pub fn apply_loop_filter(frame: &mut YuvFrame) {
373 let w = frame.width as usize;
374 let h = frame.height as usize;
375 let cw = (w + 1) / 2;
376 let ch = (h + 1) / 2;
377 loop_filter_plane(&mut frame.y, w, h);
378 loop_filter_plane(&mut frame.cb, cw, ch);
379 loop_filter_plane(&mut frame.cr, cw, ch);
380}
381
382fn read_dc_diff(br: &mut BitReader<'_>, dc_vlc: &VlcTable) -> i32 {
387 let dc_size = match dc_vlc.decode(br) {
388 Some(s) if s >= 0 => s as u8,
389 _ => return 0,
390 };
391 if dc_size == 0 {
392 return 0;
393 }
394 let raw = br.read_bits(dc_size).unwrap_or(0) as i32;
395 if raw & (1 << (dc_size - 1)) != 0 {
397 raw
398 } else {
399 raw - (1 << dc_size) + 1
400 }
401}
402
403#[derive(Clone)]
414pub struct DcPredBuffer {
415 mb_w: usize,
416 dc: Vec<[i32; 6]>,
419}
420
421impl DcPredBuffer {
422 pub fn new(mb_w: usize, mb_h: usize) -> Self {
423 DcPredBuffer {
424 mb_w,
425 dc: vec![[1024i32; 6]; mb_w * mb_h],
426 }
427 }
428
429 pub fn predict(&self, mb_row: usize, mb_col: usize, blk: usize) -> (i32, bool) {
433 let (dc_left, dc_top, dc_topleft) = self.dc_neighbours(mb_row, mb_col, blk);
443
444 let grad_h = (dc_left - dc_topleft).unsigned_abs();
447 let grad_v = (dc_top - dc_topleft).unsigned_abs();
448
449 if grad_v <= grad_h {
450 (dc_top, false)
452 } else {
453 (dc_left, true)
455 }
456 }
457
458 fn dc_neighbours(&self, mb_row: usize, mb_col: usize, blk: usize) -> (i32, i32, i32) {
459 let get = |r: isize, c: isize, b: usize| -> i32 {
461 if r < 0 || c < 0 {
462 return 1024;
463 } let idx = r as usize * self.mb_w + c as usize;
465 if idx >= self.dc.len() {
466 return 1024;
467 }
468 self.dc[idx][b]
469 };
470
471 let r = mb_row as isize;
472 let c = mb_col as isize;
473
474 match blk {
475 0 => {
477 let left = get(r, c - 1, 1); let top = get(r - 1, c, 2); let topleft = get(r - 1, c - 1, 3);
480 (left, top, topleft)
481 }
482 1 => {
483 let left = get(r, c, 0);
485 let top = get(r - 1, c, 3);
486 let topleft = get(r - 1, c - 1, 3);
487 (left, top, topleft)
488 }
489 2 => {
490 let left = get(r, c - 1, 3);
491 let top = get(r, c, 0); let topleft = get(r, c - 1, 1);
493 (left, top, topleft)
494 }
495 3 => {
496 let left = get(r, c, 2);
497 let top = get(r, c, 1);
498 let topleft = get(r, c, 0);
499 (left, top, topleft)
500 }
501 _ => {
503 let left = get(r, c - 1, blk);
504 let top = get(r - 1, c, blk);
505 let topleft = get(r - 1, c - 1, blk);
506 (left, top, topleft)
507 }
508 }
509 }
510
511 pub fn store(&mut self, mb_row: usize, mb_col: usize, blk: usize, dc_recon: i32) {
513 let idx = mb_row * self.mb_w + mb_col;
514 if idx < self.dc.len() {
515 self.dc[idx][blk] = dc_recon;
516 }
517 }
518}
519
520pub struct Wmv2DcPredBuffer {
525 mb_w: usize,
526 dc: Vec<[i32; 6]>,
527}
528
529impl Wmv2DcPredBuffer {
530 pub fn new(mb_w: usize, mb_h: usize) -> Self {
531 Wmv2DcPredBuffer {
532 mb_w,
533 dc: vec![[1024i32; 6]; mb_w * mb_h],
534 }
535 }
536
537 fn neighbours(&self, mb_row: usize, mb_col: usize, blk: usize) -> (i32, i32, i32) {
538 #[inline(always)]
547 fn get_luma(dc: &Vec<[i32; 6]>, mb_w: usize, bx: isize, by: isize) -> i32 {
548 if bx < 0 || by < 0 {
549 return 1024;
550 }
551 let mb_x = (bx >> 1) as usize;
552 let mb_y = (by >> 1) as usize;
553 let idx = mb_y * mb_w + mb_x;
554 if idx >= dc.len() {
555 return 1024;
556 }
557 let sub_x = (bx & 1) as usize;
558 let sub_y = (by & 1) as usize;
559 let b = (sub_y << 1) | sub_x; dc[idx][b]
561 }
562
563 #[inline(always)]
564 fn get_chroma(
565 dc: &Vec<[i32; 6]>,
566 mb_w: usize,
567 mb_x: isize,
568 mb_y: isize,
569 blk: usize,
570 ) -> i32 {
571 if mb_x < 0 || mb_y < 0 {
572 return 1024;
573 }
574 let idx = (mb_y as usize) * mb_w + (mb_x as usize);
575 if idx >= dc.len() {
576 return 1024;
577 }
578 dc[idx][blk]
579 }
580
581 if blk < 4 {
582 let bx = (mb_col as isize) * 2 + ((blk & 1) as isize);
583 let by = (mb_row as isize) * 2 + ((blk >> 1) as isize);
584 let a = get_luma(&self.dc, self.mb_w, bx - 1, by);
585 let b = get_luma(&self.dc, self.mb_w, bx - 1, by - 1);
586 let c = get_luma(&self.dc, self.mb_w, bx, by - 1);
587 (a, b, c)
588 } else {
589 let mx = mb_col as isize;
590 let my = mb_row as isize;
591 let a = get_chroma(&self.dc, self.mb_w, mx - 1, my, blk);
592 let b = get_chroma(&self.dc, self.mb_w, mx - 1, my - 1, blk);
593 let c = get_chroma(&self.dc, self.mb_w, mx, my - 1, blk);
594 (a, b, c)
595 }
596 }
597
598 pub fn predict(&self, mb_row: usize, mb_col: usize, blk: usize, scale: i32) -> (i32, i32) {
600 let (a0, b0, c0) = self.neighbours(mb_row, mb_col, blk);
601 let a = (a0 + (scale >> 1)) / scale;
603 let b = (b0 + (scale >> 1)) / scale;
604 let c = (c0 + (scale >> 1)) / scale;
605
606 if (a - b).abs() < (b - c).abs() {
608 (c, 1)
609 } else {
610 (a, 0)
611 }
612 }
613
614 pub fn store(&mut self, mb_row: usize, mb_col: usize, blk: usize, dc_coeff_scaled: i32) {
615 let idx = mb_row * self.mb_w + mb_col;
616 if idx < self.dc.len() {
617 self.dc[idx][blk] = dc_coeff_scaled;
618 }
619 }
620}
621
622#[inline]
632fn decode_escape_coeff(br: &mut BitReader<'_>, ac_vlc: &VlcTable) -> (u8, i32, bool) {
633 let mode = {
634 let b0 = br.read_bit().unwrap_or(false);
635 if !b0 {
636 1u8
637 } else {
638 let b1 = br.read_bit().unwrap_or(false);
639 if b1 {
640 3
641 } else {
642 2
643 }
644 }
645 };
646 match mode {
647 1 => {
648 let sym = ac_vlc.decode(br).unwrap_or(0);
650 if sym == VLC_ESCAPE {
651 return (0, 0, true);
652 }
653 let (run, base_level, last) = unpack_rl(sym);
654 let sign = br.read_bit().unwrap_or(false);
655 let offset = ac_vlc.max_level(run as usize, last) as i32 + 1;
656 let level = base_level as i32 + offset;
657 (run, if sign { -level } else { level }, last)
658 }
659 2 => {
660 let sym = ac_vlc.decode(br).unwrap_or(0);
662 if sym == VLC_ESCAPE {
663 return (0, 0, true);
664 }
665 let (base_run, level, last) = unpack_rl(sym);
666 let sign = br.read_bit().unwrap_or(false);
667 let offset = ac_vlc.max_run(level as usize, last) as i32 + 1;
668 let run = (base_run as i32 + offset).min(63) as u8;
669 let sl = level as i32;
670 (run, if sign { -sl } else { sl }, last)
671 }
672 _ => {
673 let last = br.read_bit().unwrap_or(false);
675 let run = br.read_bits(6).unwrap_or(0) as u8;
676 let level = br.read_bits(8).unwrap_or(1).max(1) as i32;
677 let sign = br.read_bit().unwrap_or(false);
678 (run, if sign { -level } else { level }, last)
679 }
680 }
681}
682
683fn decode_block(
688 br: &mut BitReader<'_>,
689 is_intra: bool,
690 is_luma: bool,
691 pquant: i32,
692 halfqp: bool,
693 uniform: bool,
694 tt: u8,
695 dc_luma: &VlcTable,
696 dc_chroma: &VlcTable,
697 ac_intra: &VlcTable,
698 ac_inter: &VlcTable,
699) -> [i32; 64] {
700 let mut blk = [0i32; 64];
701 let scan: &[usize; 64] = if is_intra { &SCAN_INTRA } else { &ZIGZAG };
702
703 if is_intra {
705 let dc_vlc = if is_luma { dc_luma } else { dc_chroma };
706 blk[0] = read_dc_diff(br, dc_vlc);
707 }
708
709 let ac_vlc = if is_intra { ac_intra } else { ac_inter };
711 let mut idx = if is_intra { 1usize } else { 0 };
712
713 loop {
714 let sym = match ac_vlc.decode(br) {
715 Some(s) => s,
716 None => break,
717 };
718
719 let (run, signed_level, last) = if sym == VLC_ESCAPE {
720 decode_escape_coeff(br, ac_vlc)
721 } else {
722 let (r, l, last) = unpack_rl(sym);
723 let sign = br.read_bit().unwrap_or(false);
724 (r, if sign { -(l as i32) } else { l as i32 }, last)
725 };
726
727 idx += run as usize;
728 if idx >= 64 {
729 break;
730 }
731
732 let mag = signed_level.abs();
733 let qval = if uniform {
734 iquant_uniform(mag, pquant, halfqp)
735 } else {
736 iquant_nonuniform(mag, pquant)
737 };
738 let signed_val = if signed_level < 0 { -qval } else { qval };
739
740 let scan_order: &[usize; 64] = match tt {
742 3 | 4 => &SCAN_VERT,
743 _ => scan,
744 };
745 let pos = scan_order.get(idx).copied().unwrap_or(idx);
746 blk[pos] = signed_val;
747 idx += 1;
748
749 if last || br.is_empty() {
750 break;
751 }
752 }
753
754 blk
755}
756
757fn decode_block_ac(
759 br: &mut BitReader<'_>,
760 _is_luma: bool,
761 pquant: i32,
762 halfqp: bool,
763 uniform: bool,
764 tt: u8,
765 ac_vlc: &VlcTable,
766) -> [i32; 64] {
767 let mut blk = [0i32; 64];
768 let mut idx = 1usize; loop {
771 let sym = match ac_vlc.decode(br) {
772 Some(s) => s,
773 None => break,
774 };
775
776 let (run, signed_level, last) = if sym == VLC_ESCAPE {
777 decode_escape_coeff(br, ac_vlc)
778 } else {
779 let (r, l, last) = unpack_rl(sym);
780 let sign = br.read_bit().unwrap_or(false);
781 (r, if sign { -(l as i32) } else { l as i32 }, last)
782 };
783
784 idx += run as usize;
785 if idx >= 64 {
786 break;
787 }
788
789 let mag = signed_level.abs();
790 let qval = if uniform {
791 iquant_uniform(mag, pquant, halfqp)
792 } else {
793 iquant_nonuniform(mag, pquant)
794 };
795 let sval = if signed_level < 0 { -qval } else { qval };
796
797 let scan_order: &[usize; 64] = match tt {
798 3 | 4 => &SCAN_VERT,
799 _ => &SCAN_INTRA,
800 };
801 let pos = scan_order.get(idx).copied().unwrap_or(idx);
802 blk[pos] = sval;
803 idx += 1;
804
805 if last || br.is_empty() {
806 break;
807 }
808 }
809 blk
810}
811
812#[derive(Clone)]
820pub struct AcPredBuffer {
821 mb_w: usize,
822 row: Vec<[[i32; 7]; 6]>,
824 col: Vec<[[i32; 7]; 6]>,
826}
827
828impl AcPredBuffer {
829 pub fn new(mb_w: usize, mb_h: usize) -> Self {
830 let n = mb_w * mb_h;
831 AcPredBuffer {
832 mb_w,
833 row: vec![[[0i32; 7]; 6]; n],
834 col: vec![[[0i32; 7]; 6]; n],
835 }
836 }
837
838 pub fn pred_row(&self, mb_row: usize, mb_col: usize, blk: usize) -> [i32; 7] {
841 let (src_mb_r, src_mb_c, src_blk) = Self::left_neighbour(mb_row, mb_col, blk);
842 if src_mb_r as isize >= 0 && src_mb_c as isize >= 0 {
843 let idx = src_mb_r * self.mb_w + src_mb_c;
844 if idx < self.row.len() {
845 return self.row[idx][src_blk];
846 }
847 }
848 [0i32; 7]
849 }
850
851 pub fn pred_col(&self, mb_row: usize, mb_col: usize, blk: usize) -> [i32; 7] {
854 let (src_mb_r, src_mb_c, src_blk) = Self::top_neighbour(mb_row, mb_col, blk);
855 if src_mb_r as isize >= 0 && src_mb_c as isize >= 0 {
856 let idx = src_mb_r * self.mb_w + src_mb_c;
857 if idx < self.col.len() {
858 return self.col[idx][src_blk];
859 }
860 }
861 [0i32; 7]
862 }
863
864 pub fn store_row(&mut self, mb_row: usize, mb_col: usize, blk: usize, row: [i32; 7]) {
865 let idx = mb_row * self.mb_w + mb_col;
866 if idx < self.row.len() {
867 self.row[idx][blk] = row;
868 }
869 }
870
871 pub fn store_col(&mut self, mb_row: usize, mb_col: usize, blk: usize, col: [i32; 7]) {
872 let idx = mb_row * self.mb_w + mb_col;
873 if idx < self.col.len() {
874 self.col[idx][blk] = col;
875 }
876 }
877
878 fn left_neighbour(mb_row: usize, mb_col: usize, blk: usize) -> (usize, usize, usize) {
880 match blk {
881 0 => (mb_row, mb_col.wrapping_sub(1), 1),
882 1 => (mb_row, mb_col, 0),
883 2 => (mb_row, mb_col.wrapping_sub(1), 3),
884 3 => (mb_row, mb_col, 2),
885 _ => (mb_row, mb_col.wrapping_sub(1), blk),
886 }
887 }
888
889 fn top_neighbour(mb_row: usize, mb_col: usize, blk: usize) -> (usize, usize, usize) {
890 match blk {
891 0 => (mb_row.wrapping_sub(1), mb_col, 2),
892 1 => (mb_row.wrapping_sub(1), mb_col, 3),
893 2 => (mb_row, mb_col, 0),
894 3 => (mb_row, mb_col, 1),
895 _ => (mb_row.wrapping_sub(1), mb_col, blk),
896 }
897 }
898}
899
900#[derive(Clone, Default)]
908pub struct MvPredictor {
909 mb_w: usize,
910 mvs: Vec<(i32, i32)>,
912 skipped: Vec<bool>,
914}
915
916impl MvPredictor {
917 pub fn new(mb_w: usize, mb_h: usize) -> Self {
918 let n = mb_w * mb_h;
919 MvPredictor {
920 mb_w,
921 mvs: vec![(0, 0); n],
922 skipped: vec![true; n],
923 }
924 }
925
926 pub fn predict(&self, mb_row: usize, mb_col: usize) -> (i32, i32) {
928 let get = |r: isize, c: isize| -> (i32, i32) {
929 if r < 0 || c < 0 {
930 return (0, 0);
931 }
932 let idx = r as usize * self.mb_w + c as usize;
933 if idx >= self.mvs.len() || self.skipped[idx] {
934 return (0, 0);
935 }
936 self.mvs[idx]
937 };
938
939 let r = mb_row as isize;
940 let c = mb_col as isize;
941
942 let (ax, ay) = get(r, c - 1); let (bx, by) = get(r - 1, c); let (cx, cy) = get(r - 1, c + 1); let (cx, cy) = if c + 1 >= self.mb_w as isize {
947 get(r - 1, c - 1)
948 } else {
949 (cx, cy)
950 };
951
952 (median3(ax, bx, cx), median3(ay, by, cy))
953 }
954
955 pub fn store(&mut self, mb_row: usize, mb_col: usize, mv: (i32, i32), skipped: bool) {
956 let idx = mb_row * self.mb_w + mb_col;
957 if idx < self.mvs.len() {
958 self.mvs[idx] = mv;
959 self.skipped[idx] = skipped;
960 }
961 }
962}
963
964#[inline]
965fn median3(a: i32, b: i32, c: i32) -> i32 {
966 if (a <= b && b <= c) || (c <= b && b <= a) {
968 b
969 } else if (b <= a && a <= c) || (c <= a && a <= b) {
970 a
971 } else {
972 c
973 }
974}
975
976#[inline(always)]
977fn mid_pred(a: i32, b: i32, c: i32) -> i32 {
978 median3(a, b, c)
980}
981
982#[allow(dead_code)]
986fn overlap_filter_h(a: &mut [i16], b: &mut [i16]) {
987 for i in 0..4 {
990 let x0 = a[i] as i32;
991 let x1 = b[i] as i32;
992 a[i] = ((9 * x0 + 3 * x1 + 8) >> 4) as i16;
993 b[i] = ((3 * x0 + 9 * x1 + 8) >> 4) as i16;
994 }
995}
996
997#[allow(dead_code)]
998fn overlap_filter_v(a: &mut i16, b: &mut i16) {
999 let x0 = *a as i32;
1000 let x1 = *b as i32;
1001 *a = ((9 * x0 + 3 * x1 + 8) >> 4) as i16;
1002 *b = ((3 * x0 + 9 * x1 + 8) >> 4) as i16;
1003}
1004
1005pub fn apply_overlap_filter(frame: &mut YuvFrame) {
1006 let w = frame.width as usize;
1007 let h = frame.height as usize;
1008 let cw = w / 2;
1009 let ch = h / 2;
1010
1011 let mut y_i16: Vec<i16> = frame.y.iter().map(|&v| v as i16).collect();
1013
1014 for row in 0..h {
1016 for col in (8..w).step_by(8) {
1017 for k in 0..4 {
1018 let ia = row * w + col - 4 + k;
1019 let ib = row * w + col + k;
1020 if ib < y_i16.len() {
1021 let a = y_i16[ia] as i32;
1022 let b = y_i16[ib] as i32;
1023 y_i16[ia] = ((9 * a + 3 * b + 8) >> 4) as i16;
1024 y_i16[ib] = ((3 * a + 9 * b + 8) >> 4) as i16;
1025 }
1026 }
1027 }
1028 }
1029
1030 for row in (8..h).step_by(8) {
1032 for col in 0..w {
1033 let a = y_i16[(row - 1) * w + col] as i32;
1034 let b = y_i16[row * w + col] as i32;
1035 y_i16[(row - 1) * w + col] = ((9 * a + 3 * b + 8) >> 4) as i16;
1036 y_i16[row * w + col] = ((3 * a + 9 * b + 8) >> 4) as i16;
1037 }
1038 }
1039
1040 for (dst, src) in frame.y.iter_mut().zip(y_i16.iter()) {
1042 *dst = (*src).clamp(0, 255) as u8;
1043 }
1044
1045 let mut cb_i16: Vec<i16> = frame.cb.iter().map(|&v| v as i16).collect();
1047 let mut cr_i16: Vec<i16> = frame.cr.iter().map(|&v| v as i16).collect();
1048 for plane in [&mut cb_i16, &mut cr_i16] {
1049 for row in 0..ch {
1050 for col in (8..cw).step_by(8) {
1051 for k in 0..4 {
1052 let a = plane[row * cw + col - 4 + k] as i32;
1053 let b = plane[row * cw + col + k] as i32;
1054 plane[row * cw + col - 4 + k] = ((9 * a + 3 * b + 8) >> 4) as i16;
1055 plane[row * cw + col + k] = ((3 * a + 9 * b + 8) >> 4) as i16;
1056 }
1057 }
1058 }
1059 for row in (8..ch).step_by(8) {
1060 for col in 0..cw {
1061 let a = plane[(row - 1) * cw + col] as i32;
1062 let b = plane[row * cw + col] as i32;
1063 plane[(row - 1) * cw + col] = ((9 * a + 3 * b + 8) >> 4) as i16;
1064 plane[row * cw + col] = ((3 * a + 9 * b + 8) >> 4) as i16;
1065 }
1066 }
1067 }
1068 for (dst, src) in frame.cb.iter_mut().zip(cb_i16.iter()) {
1069 *dst = (*src).clamp(0, 255) as u8;
1070 }
1071 for (dst, src) in frame.cr.iter_mut().zip(cr_i16.iter()) {
1072 *dst = (*src).clamp(0, 255) as u8;
1073 }
1074}
1075
1076fn mc_luma(
1080 dst: &mut [u8],
1081 dst_stride: usize,
1082 src: &[u8],
1083 src_stride: usize,
1084 src_w: usize,
1085 src_h: usize,
1086 x: i32,
1087 y: i32,
1088 w: usize,
1089 h: usize,
1090) {
1091 let xh = x & 1 != 0;
1093 let yh = y & 1 != 0;
1094 let x0 = (x >> 1) as isize;
1095 let y0 = (y >> 1) as isize;
1096
1097 for dy in 0..h {
1098 for dx in 0..w {
1099 let sx = (x0 + dx as isize).clamp(0, src_w as isize - 1) as usize;
1100 let sy = (y0 + dy as isize).clamp(0, src_h as isize - 1) as usize;
1101 let sx1 = (sx + 1).min(src_w - 1);
1102 let sy1 = (sy + 1).min(src_h - 1);
1103
1104 let p00 = src[sy * src_stride + sx] as i32;
1105 let p10 = src[sy * src_stride + sx1] as i32;
1106 let p01 = src[sy1 * src_stride + sx] as i32;
1107 let p11 = src[sy1 * src_stride + sx1] as i32;
1108
1109 let val = match (xh, yh) {
1110 (false, false) => p00,
1111 (true, false) => (p00 + p10 + 1) >> 1,
1112 (false, true) => (p00 + p01 + 1) >> 1,
1113 (true, true) => (p00 + p10 + p01 + p11 + 2) >> 2,
1114 };
1115 dst[dy * dst_stride + dx] = val.clamp(0, 255) as u8;
1116 }
1117 }
1118}
1119
1120fn read_mquant(br: &mut BitReader<'_>, dquant: u8, pquant: i32) -> i32 {
1128 match dquant {
1129 0 => pquant, 1 => {
1131 if br.read_bit().unwrap_or(false) {
1133 let mqdiff = br.read_bits(2).unwrap_or(0) as i32;
1134 let delta = match mqdiff {
1136 0 => 2,
1137 1 => -2,
1138 2 => 4,
1139 _ => -4,
1140 };
1141 (pquant + delta).clamp(1, 31)
1142 } else {
1143 pquant
1144 }
1145 }
1146 _ => {
1147 let mqdiff = br.read_bits(3).unwrap_or(0);
1149 if mqdiff == 7 {
1150 br.read_bits(5).unwrap_or(pquant as u32) as i32
1152 } else {
1153 (pquant + mqdiff as i32).clamp(1, 31)
1155 }
1156 }
1157 }
1158}
1159
1160pub fn apply_rangered_expand(frame: &mut YuvFrame) {
1167 for p in frame.y.iter_mut() {
1169 *p = ((*p as i32 - 128) * 2 + 128).clamp(0, 255) as u8;
1170 }
1171 for p in frame.cb.iter_mut() {
1172 *p = ((*p as i32 - 128) * 2 + 128).clamp(0, 255) as u8;
1173 }
1174 for p in frame.cr.iter_mut() {
1175 *p = ((*p as i32 - 128) * 2 + 128).clamp(0, 255) as u8;
1176 }
1177}
1178
1179pub fn apply_rangered_compress(frame: &mut YuvFrame) {
1182 for p in frame.y.iter_mut() {
1183 *p = ((*p as i32 - 128).div_euclid(2) + 128).clamp(0, 255) as u8;
1184 }
1185 for p in frame.cb.iter_mut() {
1186 *p = ((*p as i32 - 128).div_euclid(2) + 128).clamp(0, 255) as u8;
1187 }
1188 for p in frame.cr.iter_mut() {
1189 *p = ((*p as i32 - 128).div_euclid(2) + 128).clamp(0, 255) as u8;
1190 }
1191}
1192
1193fn block_coords(
1197 mb_row: u32,
1198 mb_col: u32,
1199 blk: usize,
1200 width: u32,
1201 height: u32,
1202) -> (bool, usize, usize, usize, usize) {
1203 let (is_luma, bx, by) = match blk {
1205 0 => (true, (mb_col * 16) as usize, (mb_row * 16) as usize),
1206 1 => (true, (mb_col * 16 + 8) as usize, (mb_row * 16) as usize),
1207 2 => (true, (mb_col * 16) as usize, (mb_row * 16 + 8) as usize),
1208 3 => (true, (mb_col * 16 + 8) as usize, (mb_row * 16 + 8) as usize),
1209 _ => (false, (mb_col * 8) as usize, (mb_row * 8) as usize),
1210 };
1211 let stride = if is_luma {
1212 width as usize
1213 } else {
1214 (width / 2) as usize
1215 };
1216 let ph = if is_luma {
1217 height as usize
1218 } else {
1219 (height / 2) as usize
1220 };
1221 (is_luma, bx, by, stride, ph)
1222}
1223
1224fn write_intra_block(
1225 frame: &mut YuvFrame,
1226 mb_row: u32,
1227 mb_col: u32,
1228 blk: usize,
1229 coeff: &[i32; 64],
1230) {
1231 let (is_luma, bx, by, stride, ph) =
1232 block_coords(mb_row, mb_col, blk, frame.width, frame.height);
1233 let plane: &mut Vec<u8> = if is_luma {
1234 &mut frame.y
1235 } else if blk == 4 {
1236 &mut frame.cb
1237 } else {
1238 &mut frame.cr
1239 };
1240 for r in 0..8 {
1241 if by + r >= ph {
1242 break;
1243 }
1244 for c in 0..8 {
1245 if bx + c >= stride {
1246 break;
1247 }
1248 let idx = (by + r) * stride + (bx + c);
1249 plane[idx] = (128 + coeff[r * 8 + c]).clamp(0, 255) as u8;
1250 }
1251 }
1252}
1253
1254#[inline]
1255fn write_block_to_frame(
1256 frame: &mut YuvFrame,
1257 mb_row: usize,
1258 mb_col: usize,
1259 blk: usize,
1260 coeff: &[i32; 64],
1261) {
1262 write_intra_block(frame, mb_row as u32, mb_col as u32, blk, coeff);
1263}
1264
1265fn write_intra_block_i16(
1267 frame: &mut YuvFrame,
1268 mb_row: u32,
1269 mb_col: u32,
1270 blk: usize,
1271 coeff: &[i16; 64],
1272) {
1273 let (is_luma, bx, by, stride, ph) =
1274 block_coords(mb_row, mb_col, blk, frame.width, frame.height);
1275 let plane: &mut Vec<u8> = if is_luma {
1276 &mut frame.y
1277 } else if blk == 4 {
1278 &mut frame.cb
1279 } else {
1280 &mut frame.cr
1281 };
1282 for r in 0..8usize {
1283 if by + r >= ph {
1284 break;
1285 }
1286 for c in 0..8usize {
1287 if bx + c >= stride {
1288 break;
1289 }
1290 let idx = (by + r) * stride + (bx + c);
1291 let v = coeff[r * 8 + c] as i32;
1292 plane[idx] = (v + 128).clamp(0, 255) as u8;
1293 }
1294 }
1295}
1296
1297fn add_residual_block_i16(
1298 frame: &mut YuvFrame,
1299 mb_row: u32,
1300 mb_col: u32,
1301 blk: usize,
1302 coeff: &[i16; 64],
1303) {
1304 let (is_luma, bx, by, stride, ph) =
1305 block_coords(mb_row, mb_col, blk, frame.width, frame.height);
1306 let plane: &mut Vec<u8> = if is_luma {
1307 &mut frame.y
1308 } else if blk == 4 {
1309 &mut frame.cb
1310 } else {
1311 &mut frame.cr
1312 };
1313 for r in 0..8usize {
1314 if by + r >= ph {
1315 break;
1316 }
1317 for c in 0..8usize {
1318 if bx + c >= stride {
1319 break;
1320 }
1321 let idx = (by + r) * stride + (bx + c);
1322 let v = plane[idx] as i32 + coeff[r * 8 + c] as i32;
1323 plane[idx] = v.clamp(0, 255) as u8;
1324 }
1325 }
1326}
1327
1328fn motion_compensate_mb(
1331 dst: &mut YuvFrame,
1332 reference: &YuvFrame,
1333 mb_row: usize,
1334 mb_col: usize,
1335 mvx: i32,
1336 mvy: i32,
1337) {
1338 let fw = dst.width as usize;
1339 let fh = dst.height as usize;
1340 if fw == 0 || fh == 0 {
1341 return;
1342 }
1343 let cw = fw / 2;
1344 let ch = fh / 2;
1345
1346 let dst_x = mb_col * 16;
1348 let dst_y = mb_row * 16;
1349 let src_x = dst_x as i32 * 2 + mvx; let src_y = dst_y as i32 * 2 + mvy;
1351
1352 if reference.y.len() == fw * fh && dst.y.len() == fw * fh {
1353 let mut tmp = [0u8; 256];
1354 mc_luma(&mut tmp, 16, &reference.y, fw, fw, fh, src_x, src_y, 16, 16);
1355 for r in 0..16 {
1356 if dst_y + r >= fh {
1357 break;
1358 }
1359 if dst_x >= fw {
1360 break;
1361 }
1362 let d_off = (dst_y + r) * fw + dst_x;
1363 let s_off = r * 16;
1364 let max = (fw - dst_x).min(16);
1365 dst.y[d_off..d_off + max].copy_from_slice(&tmp[s_off..s_off + max]);
1366 }
1367 }
1368
1369 if reference.cb.len() == cw * ch && dst.cb.len() == cw * ch {
1379 let dst_xc = mb_col * 8;
1380 let dst_yc = mb_row * 8;
1381
1382 let mx = mvx >> 2;
1383 let my = mvy >> 2;
1384 let xh = (mvx & 3) != 0;
1385 let yh = (mvy & 3) != 0;
1386
1387 let src_xc = (dst_xc as i32 + mx) * 2 + if xh { 1 } else { 0 };
1389 let src_yc = (dst_yc as i32 + my) * 2 + if yh { 1 } else { 0 };
1390
1391 let mut tmp_cb = [0u8; 64];
1392 let mut tmp_cr = [0u8; 64];
1393 mc_luma(
1394 &mut tmp_cb,
1395 8,
1396 &reference.cb,
1397 cw,
1398 cw,
1399 ch,
1400 src_xc,
1401 src_yc,
1402 8,
1403 8,
1404 );
1405 mc_luma(
1406 &mut tmp_cr,
1407 8,
1408 &reference.cr,
1409 cw,
1410 cw,
1411 ch,
1412 src_xc,
1413 src_yc,
1414 8,
1415 8,
1416 );
1417
1418 for r in 0..8 {
1419 if dst_yc + r >= ch {
1420 break;
1421 }
1422 if dst_xc >= cw {
1423 break;
1424 }
1425 let d_off = (dst_yc + r) * cw + dst_xc;
1426 let s_off = r * 8;
1427 let max = (cw - dst_xc).min(8);
1428 dst.cb[d_off..d_off + max].copy_from_slice(&tmp_cb[s_off..s_off + max]);
1429 dst.cr[d_off..d_off + max].copy_from_slice(&tmp_cr[s_off..s_off + max]);
1430 }
1431 }
1432}
1433
1434#[inline]
1437fn clip_u8(v: i32) -> u8 {
1438 if v < 0 {
1439 0
1440 } else if v > 255 {
1441 255
1442 } else {
1443 v as u8
1444 }
1445}
1446
1447#[inline]
1448fn rnd_avg_u8(a: u8, b: u8) -> u8 {
1449 ((a as u16 + b as u16 + 1) >> 1) as u8
1450}
1451
1452#[inline]
1453fn no_rnd_avg_u8(a: u8, b: u8) -> u8 {
1454 ((a as u16 + b as u16) >> 1) as u8
1455}
1456
1457fn wmv2_mspel8_h_lowpass(
1458 dst: &mut [u8],
1459 dst_off: usize,
1460 dst_stride: usize,
1461 src: &[u8],
1462 src_off: usize,
1463 src_stride: usize,
1464 h: usize,
1465) {
1466 for i in 0..h {
1467 let so = src_off + i * src_stride;
1468 let doff = dst_off + i * dst_stride;
1469 dst[doff + 0] = clip_u8(
1471 ((9 * (src[so + 0] as i32 + src[so + 1] as i32)
1472 - (src[so - 1] as i32 + src[so + 2] as i32)
1473 + 8)
1474 >> 4),
1475 );
1476 dst[doff + 1] = clip_u8(
1477 ((9 * (src[so + 1] as i32 + src[so + 2] as i32)
1478 - (src[so + 0] as i32 + src[so + 3] as i32)
1479 + 8)
1480 >> 4),
1481 );
1482 dst[doff + 2] = clip_u8(
1483 ((9 * (src[so + 2] as i32 + src[so + 3] as i32)
1484 - (src[so + 1] as i32 + src[so + 4] as i32)
1485 + 8)
1486 >> 4),
1487 );
1488 dst[doff + 3] = clip_u8(
1489 ((9 * (src[so + 3] as i32 + src[so + 4] as i32)
1490 - (src[so + 2] as i32 + src[so + 5] as i32)
1491 + 8)
1492 >> 4),
1493 );
1494 dst[doff + 4] = clip_u8(
1495 ((9 * (src[so + 4] as i32 + src[so + 5] as i32)
1496 - (src[so + 3] as i32 + src[so + 6] as i32)
1497 + 8)
1498 >> 4),
1499 );
1500 dst[doff + 5] = clip_u8(
1501 ((9 * (src[so + 5] as i32 + src[so + 6] as i32)
1502 - (src[so + 4] as i32 + src[so + 7] as i32)
1503 + 8)
1504 >> 4),
1505 );
1506 dst[doff + 6] = clip_u8(
1507 ((9 * (src[so + 6] as i32 + src[so + 7] as i32)
1508 - (src[so + 5] as i32 + src[so + 8] as i32)
1509 + 8)
1510 >> 4),
1511 );
1512 dst[doff + 7] = clip_u8(
1513 ((9 * (src[so + 7] as i32 + src[so + 8] as i32)
1514 - (src[so + 6] as i32 + src[so + 9] as i32)
1515 + 8)
1516 >> 4),
1517 );
1518 }
1519}
1520
1521fn wmv2_mspel8_v_lowpass(
1522 dst: &mut [u8],
1523 dst_off: usize,
1524 dst_stride: usize,
1525 src: &[u8],
1526 src_off: usize,
1527 src_stride: usize,
1528 w: usize,
1529) {
1530 for i in 0..w {
1531 let so = src_off + i;
1532 let s_1 = src[so - src_stride] as i32;
1533 let s0 = src[so] as i32;
1534 let s1 = src[so + src_stride] as i32;
1535 let s2 = src[so + 2 * src_stride] as i32;
1536 let s3 = src[so + 3 * src_stride] as i32;
1537 let s4 = src[so + 4 * src_stride] as i32;
1538 let s5 = src[so + 5 * src_stride] as i32;
1539 let s6 = src[so + 6 * src_stride] as i32;
1540 let s7 = src[so + 7 * src_stride] as i32;
1541 let s8 = src[so + 8 * src_stride] as i32;
1542 let s9 = src[so + 9 * src_stride] as i32;
1543
1544 let do0 = dst_off + i + 0 * dst_stride;
1545 let do1 = dst_off + i + 1 * dst_stride;
1546 let do2 = dst_off + i + 2 * dst_stride;
1547 let do3 = dst_off + i + 3 * dst_stride;
1548 let do4 = dst_off + i + 4 * dst_stride;
1549 let do5 = dst_off + i + 5 * dst_stride;
1550 let do6 = dst_off + i + 6 * dst_stride;
1551 let do7 = dst_off + i + 7 * dst_stride;
1552
1553 dst[do0] = clip_u8(((9 * (s0 + s1) - (s_1 + s2) + 8) >> 4));
1554 dst[do1] = clip_u8(((9 * (s1 + s2) - (s0 + s3) + 8) >> 4));
1555 dst[do2] = clip_u8(((9 * (s2 + s3) - (s1 + s4) + 8) >> 4));
1556 dst[do3] = clip_u8(((9 * (s3 + s4) - (s2 + s5) + 8) >> 4));
1557 dst[do4] = clip_u8(((9 * (s4 + s5) - (s3 + s6) + 8) >> 4));
1558 dst[do5] = clip_u8(((9 * (s5 + s6) - (s4 + s7) + 8) >> 4));
1559 dst[do6] = clip_u8(((9 * (s6 + s7) - (s5 + s8) + 8) >> 4));
1560 dst[do7] = clip_u8(((9 * (s7 + s8) - (s6 + s9) + 8) >> 4));
1561 }
1562}
1563
1564#[inline]
1565fn put_pixels8x8(dst: &mut [u8], dst_off: usize, src: &[u8], src_off: usize, stride: usize) {
1566 for y in 0..8 {
1567 let d = dst_off + y * stride;
1568 let s = src_off + y * stride;
1569 dst[d..d + 8].copy_from_slice(&src[s..s + 8]);
1570 }
1571}
1572
1573#[inline]
1574fn put_pixels8_l2_8_no_rnd(
1575 dst: &mut [u8],
1576 dst_off: usize,
1577 src1: &[u8],
1578 src1_off: usize,
1579 src2: &[u8],
1580 src2_off: usize,
1581 dst_stride: usize,
1582 src1_stride: usize,
1583 src2_stride: usize,
1584 h: usize,
1585) {
1586 for y in 0..h {
1587 let d = dst_off + y * dst_stride;
1588 let s1 = src1_off + y * src1_stride;
1589 let s2 = src2_off + y * src2_stride;
1590 for x in 0..8 {
1591 dst[d + x] = no_rnd_avg_u8(src1[s1 + x], src2[s2 + x]);
1592 }
1593 }
1594}
1595
1596fn put_mspel8_mc10(dst: &mut [u8], dst_off: usize, src: &[u8], src_off: usize, stride: usize) {
1597 let mut half = [0u8; 64];
1598 wmv2_mspel8_h_lowpass(&mut half, 0, 8, src, src_off, stride, 8);
1599 put_pixels8_l2_8_no_rnd(dst, dst_off, src, src_off, &half, 0, stride, stride, 8, 8);
1600}
1601
1602fn put_mspel8_mc20(dst: &mut [u8], dst_off: usize, src: &[u8], src_off: usize, stride: usize) {
1603 wmv2_mspel8_h_lowpass(dst, dst_off, stride, src, src_off, stride, 8);
1604}
1605
1606fn put_mspel8_mc30(dst: &mut [u8], dst_off: usize, src: &[u8], src_off: usize, stride: usize) {
1607 let mut half = [0u8; 64];
1608 wmv2_mspel8_h_lowpass(&mut half, 0, 8, src, src_off, stride, 8);
1609 put_pixels8_l2_8_no_rnd(
1610 dst,
1611 dst_off,
1612 src,
1613 src_off + 1,
1614 &half,
1615 0,
1616 stride,
1617 stride,
1618 8,
1619 8,
1620 );
1621}
1622
1623fn put_mspel8_mc02(dst: &mut [u8], dst_off: usize, src: &[u8], src_off: usize, stride: usize) {
1624 wmv2_mspel8_v_lowpass(dst, dst_off, stride, src, src_off, stride, 8);
1625}
1626
1627fn put_mspel8_mc12(dst: &mut [u8], dst_off: usize, src: &[u8], src_off: usize, stride: usize) {
1628 let mut half_h = [0u8; 88];
1629 let mut half_v = [0u8; 64];
1630 let mut half_hv = [0u8; 64];
1631 wmv2_mspel8_h_lowpass(&mut half_h, 0, 8, src, src_off - stride, stride, 11);
1633 wmv2_mspel8_v_lowpass(&mut half_v, 0, 8, src, src_off, stride, 8);
1635 wmv2_mspel8_v_lowpass(&mut half_hv, 0, 8, &half_h, 8, 8, 8);
1637 put_pixels8_l2_8_no_rnd(dst, dst_off, &half_v, 0, &half_hv, 0, stride, 8, 8, 8);
1638}
1639
1640fn put_mspel8_mc22(dst: &mut [u8], dst_off: usize, src: &[u8], src_off: usize, stride: usize) {
1641 let mut half_h = [0u8; 88];
1642 wmv2_mspel8_h_lowpass(&mut half_h, 0, 8, src, src_off - stride, stride, 11);
1643 wmv2_mspel8_v_lowpass(dst, dst_off, stride, &half_h, 8, 8, 8);
1644}
1645
1646fn put_mspel8_mc32(dst: &mut [u8], dst_off: usize, src: &[u8], src_off: usize, stride: usize) {
1647 let mut half_h = [0u8; 88];
1648 let mut half_v = [0u8; 64];
1649 let mut half_hv = [0u8; 64];
1650 wmv2_mspel8_h_lowpass(&mut half_h, 0, 8, src, src_off - stride, stride, 11);
1651 wmv2_mspel8_v_lowpass(&mut half_v, 0, 8, src, src_off + 1, stride, 8);
1652 wmv2_mspel8_v_lowpass(&mut half_hv, 0, 8, &half_h, 8, 8, 8);
1653 put_pixels8_l2_8_no_rnd(dst, dst_off, &half_v, 0, &half_hv, 0, stride, 8, 8, 8);
1654}
1655
1656#[inline]
1657fn wmv2_put_mspel_pixels(
1658 dxy: usize,
1659 dst: &mut [u8],
1660 dst_off: usize,
1661 src: &[u8],
1662 src_off: usize,
1663 stride: usize,
1664) {
1665 match dxy {
1666 0 => put_pixels8x8(dst, dst_off, src, src_off, stride),
1667 1 => put_mspel8_mc10(dst, dst_off, src, src_off, stride),
1668 2 => put_mspel8_mc20(dst, dst_off, src, src_off, stride),
1669 3 => put_mspel8_mc30(dst, dst_off, src, src_off, stride),
1670 4 => put_mspel8_mc02(dst, dst_off, src, src_off, stride),
1671 5 => put_mspel8_mc12(dst, dst_off, src, src_off, stride),
1672 6 => put_mspel8_mc22(dst, dst_off, src, src_off, stride),
1673 7 => put_mspel8_mc32(dst, dst_off, src, src_off, stride),
1674 _ => put_pixels8x8(dst, dst_off, src, src_off, stride),
1675 }
1676}
1677
1678fn emulated_edge_mc(
1679 buf: &mut [u8],
1680 buf_stride: usize,
1681 src: &[u8],
1682 src_stride: usize,
1683 block_w: usize,
1684 block_h: usize,
1685 src_x: i32,
1686 src_y: i32,
1687 h_edge: usize,
1688 v_edge: usize,
1689) {
1690 let max_x = (h_edge as i32 - 1).max(0);
1691 let max_y = (v_edge as i32 - 1).max(0);
1692 for y in 0..block_h {
1693 let sy = (src_y + y as i32).clamp(0, max_y) as usize;
1694 let drow = y * buf_stride;
1695 let srow = sy * src_stride;
1696 for x in 0..block_w {
1697 let sx = (src_x + x as i32).clamp(0, max_x) as usize;
1698 buf[drow + x] = src[srow + sx];
1699 }
1700 }
1701}
1702
1703#[inline]
1704fn chroma_put_pixels(
1705 dst: &mut [u8],
1706 dst_off: usize,
1707 src: &[u8],
1708 src_off: usize,
1709 stride: usize,
1710 h: usize,
1711) {
1712 for y in 0..h {
1713 let d = dst_off + y * stride;
1714 let s = src_off + y * stride;
1715 dst[d..d + 8].copy_from_slice(&src[s..s + 8]);
1716 }
1717}
1718
1719#[inline]
1720fn chroma_put_x2(
1721 dst: &mut [u8],
1722 dst_off: usize,
1723 src: &[u8],
1724 src_off: usize,
1725 stride: usize,
1726 h: usize,
1727) {
1728 for y in 0..h {
1729 let d = dst_off + y * stride;
1730 let s = src_off + y * stride;
1731 for x in 0..8 {
1732 dst[d + x] = rnd_avg_u8(src[s + x], src[s + x + 1]);
1733 }
1734 }
1735}
1736
1737#[inline]
1738fn chroma_put_y2(
1739 dst: &mut [u8],
1740 dst_off: usize,
1741 src: &[u8],
1742 src_off: usize,
1743 stride: usize,
1744 h: usize,
1745) {
1746 for y in 0..h {
1747 let d = dst_off + y * stride;
1748 let s = src_off + y * stride;
1749 let s2 = s + stride;
1750 for x in 0..8 {
1751 dst[d + x] = rnd_avg_u8(src[s + x], src[s2 + x]);
1752 }
1753 }
1754}
1755
1756#[inline]
1757fn chroma_put_xy2(
1758 dst: &mut [u8],
1759 dst_off: usize,
1760 src: &[u8],
1761 src_off: usize,
1762 stride: usize,
1763 h: usize,
1764) {
1765 for y in 0..h {
1766 let d = dst_off + y * stride;
1767 let s = src_off + y * stride;
1768 let s2 = s + stride;
1769 for x in 0..8 {
1770 let a = src[s + x] as u16;
1771 let b = src[s + x + 1] as u16;
1772 let c = src[s2 + x] as u16;
1773 let e = src[s2 + x + 1] as u16;
1774 dst[d + x] = ((a + b + c + e + 2) >> 2) as u8;
1775 }
1776 }
1777}
1778
1779fn wmv2_mspel_motion_mb(
1781 dst: &mut YuvFrame,
1782 reference: &YuvFrame,
1783 mb_row: usize,
1784 mb_col: usize,
1785 motion_x: i32,
1786 motion_y: i32,
1787 hshift: u8,
1788) {
1789 let fw = dst.width as usize;
1790 let fh = dst.height as usize;
1791 if fw == 0 || fh == 0 {
1792 return;
1793 }
1794 let cw = fw / 2;
1795 let ch = fh / 2;
1796
1797 let mut dxy = (((motion_y & 1) << 1) | (motion_x & 1)) as i32;
1799 dxy = 2 * dxy + hshift as i32;
1800
1801 let mut src_x = mb_col as i32 * 16 + (motion_x >> 1);
1802 let mut src_y = mb_row as i32 * 16 + (motion_y >> 1);
1803
1804 if src_x < -16 {
1806 src_x = -16;
1807 }
1808 if src_x > dst.width as i32 {
1809 src_x = dst.width as i32;
1810 }
1811 if src_y < -16 {
1812 src_y = -16;
1813 }
1814 if src_y > dst.height as i32 {
1815 src_y = dst.height as i32;
1816 }
1817
1818 if src_x <= -16 || src_x >= dst.width as i32 {
1819 dxy &= !3;
1820 }
1821 if src_y <= -16 || src_y >= dst.height as i32 {
1822 dxy &= !4;
1823 }
1824
1825 let linesize = fw;
1826 let mut src_plane: &[u8] = &reference.y;
1827 let mut src_off: usize;
1828
1829 if src_x < 1
1831 || src_y < 1
1832 || src_x + 17 >= dst.width as i32
1833 || src_y + 16 + 1 >= dst.height as i32
1834 {
1835 let mut edge = vec![0u8; linesize * 19];
1836 emulated_edge_mc(
1837 &mut edge,
1838 linesize,
1839 &reference.y,
1840 linesize,
1841 19,
1842 19,
1843 src_x - 1,
1844 src_y - 1,
1845 fw,
1846 fh,
1847 );
1848 src_plane = edge.as_slice();
1849 src_off = 1 + linesize;
1850 let dst_x = mb_col * 16;
1857 let dst_y = mb_row * 16;
1858 let dxyu = (dxy as usize).min(7);
1859
1860 let dst00 = dst_y * linesize + dst_x;
1862 let src00 = src_off;
1863 wmv2_put_mspel_pixels(dxyu, &mut dst.y, dst00, src_plane, src00, linesize);
1864 wmv2_put_mspel_pixels(dxyu, &mut dst.y, dst00 + 8, src_plane, src00 + 8, linesize);
1865 wmv2_put_mspel_pixels(
1866 dxyu,
1867 &mut dst.y,
1868 dst00 + 8 * linesize,
1869 src_plane,
1870 src00 + 8 * linesize,
1871 linesize,
1872 );
1873 wmv2_put_mspel_pixels(
1874 dxyu,
1875 &mut dst.y,
1876 dst00 + 8 + 8 * linesize,
1877 src_plane,
1878 src00 + 8 + 8 * linesize,
1879 linesize,
1880 );
1881
1882 if dst.cb.is_empty() || reference.cb.is_empty() {
1884 return;
1885 }
1886
1887 let mut cdxy = 0usize;
1888 if (motion_x & 3) != 0 {
1889 cdxy |= 1;
1890 }
1891 if (motion_y & 3) != 0 {
1892 cdxy |= 2;
1893 }
1894 let mx = motion_x >> 2;
1895 let my = motion_y >> 2;
1896
1897 let mut csrc_x = mb_col as i32 * 8 + mx;
1898 let mut csrc_y = mb_row as i32 * 8 + my;
1899
1900 if csrc_x < -8 {
1901 csrc_x = -8;
1902 }
1903 if csrc_x > (dst.width as i32 >> 1) {
1904 csrc_x = dst.width as i32 >> 1;
1905 }
1906 if csrc_y < -8 {
1907 csrc_y = -8;
1908 }
1909 if csrc_y > (dst.height as i32 >> 1) {
1910 csrc_y = dst.height as i32 >> 1;
1911 }
1912
1913 if csrc_x == (dst.width as i32 >> 1) {
1914 cdxy &= !1;
1915 }
1916 if csrc_y == (dst.height as i32 >> 1) {
1917 cdxy &= !2;
1918 }
1919
1920 let uvlinesize = cw;
1921
1922 let mut edge_uv = vec![0u8; uvlinesize * 9];
1923 emulated_edge_mc(
1925 &mut edge_uv,
1926 uvlinesize,
1927 &reference.cb,
1928 uvlinesize,
1929 9,
1930 9,
1931 csrc_x,
1932 csrc_y,
1933 cw,
1934 ch,
1935 );
1936 let dst_xc = mb_col * 8;
1937 let dst_yc = mb_row * 8;
1938 let dst_cb_off = dst_yc * uvlinesize + dst_xc;
1939 match cdxy {
1940 0 => chroma_put_pixels(&mut dst.cb, dst_cb_off, &edge_uv, 0, uvlinesize, 8),
1941 1 => chroma_put_x2(&mut dst.cb, dst_cb_off, &edge_uv, 0, uvlinesize, 8),
1942 2 => chroma_put_y2(&mut dst.cb, dst_cb_off, &edge_uv, 0, uvlinesize, 8),
1943 _ => chroma_put_xy2(&mut dst.cb, dst_cb_off, &edge_uv, 0, uvlinesize, 8),
1944 }
1945
1946 emulated_edge_mc(
1948 &mut edge_uv,
1949 uvlinesize,
1950 &reference.cr,
1951 uvlinesize,
1952 9,
1953 9,
1954 csrc_x,
1955 csrc_y,
1956 cw,
1957 ch,
1958 );
1959 let dst_cr_off = dst_yc * uvlinesize + dst_xc;
1960 match cdxy {
1961 0 => chroma_put_pixels(&mut dst.cr, dst_cr_off, &edge_uv, 0, uvlinesize, 8),
1962 1 => chroma_put_x2(&mut dst.cr, dst_cr_off, &edge_uv, 0, uvlinesize, 8),
1963 2 => chroma_put_y2(&mut dst.cr, dst_cr_off, &edge_uv, 0, uvlinesize, 8),
1964 _ => chroma_put_xy2(&mut dst.cr, dst_cr_off, &edge_uv, 0, uvlinesize, 8),
1965 }
1966 return;
1967 }
1968
1969 src_off = (src_y as usize) * linesize + (src_x as usize);
1971 let dst_x = mb_col * 16;
1972 let dst_y = mb_row * 16;
1973 let dxyu = (dxy as usize).min(7);
1974
1975 let dst00 = dst_y * linesize + dst_x;
1976 wmv2_put_mspel_pixels(dxyu, &mut dst.y, dst00, src_plane, src_off, linesize);
1977 wmv2_put_mspel_pixels(
1978 dxyu,
1979 &mut dst.y,
1980 dst00 + 8,
1981 src_plane,
1982 src_off + 8,
1983 linesize,
1984 );
1985 wmv2_put_mspel_pixels(
1986 dxyu,
1987 &mut dst.y,
1988 dst00 + 8 * linesize,
1989 src_plane,
1990 src_off + 8 * linesize,
1991 linesize,
1992 );
1993 wmv2_put_mspel_pixels(
1994 dxyu,
1995 &mut dst.y,
1996 dst00 + 8 + 8 * linesize,
1997 src_plane,
1998 src_off + 8 + 8 * linesize,
1999 linesize,
2000 );
2001
2002 if dst.cb.is_empty() || reference.cb.is_empty() {
2004 return;
2005 }
2006
2007 let mut cdxy = 0usize;
2008 if (motion_x & 3) != 0 {
2009 cdxy |= 1;
2010 }
2011 if (motion_y & 3) != 0 {
2012 cdxy |= 2;
2013 }
2014 let mx = motion_x >> 2;
2015 let my = motion_y >> 2;
2016
2017 let mut csrc_x = mb_col as i32 * 8 + mx;
2018 let mut csrc_y = mb_row as i32 * 8 + my;
2019
2020 if csrc_x < -8 {
2021 csrc_x = -8;
2022 }
2023 if csrc_x > (dst.width as i32 >> 1) {
2024 csrc_x = dst.width as i32 >> 1;
2025 }
2026 if csrc_y < -8 {
2027 csrc_y = -8;
2028 }
2029 if csrc_y > (dst.height as i32 >> 1) {
2030 csrc_y = dst.height as i32 >> 1;
2031 }
2032
2033 if csrc_x == (dst.width as i32 >> 1) {
2034 cdxy &= !1;
2035 }
2036 if csrc_y == (dst.height as i32 >> 1) {
2037 cdxy &= !2;
2038 }
2039
2040 let uvlinesize = cw;
2041 let need_emu_uv =
2042 csrc_x < 0 || csrc_y < 0 || csrc_x + 9 >= cw as i32 || csrc_y + 9 >= ch as i32;
2043 if need_emu_uv {
2044 let mut edge_uv = vec![0u8; uvlinesize * 9];
2045 let dst_xc = mb_col * 8;
2046 let dst_yc = mb_row * 8;
2047 let dst_cb_off = dst_yc * uvlinesize + dst_xc;
2048 emulated_edge_mc(
2049 &mut edge_uv,
2050 uvlinesize,
2051 &reference.cb,
2052 uvlinesize,
2053 9,
2054 9,
2055 csrc_x,
2056 csrc_y,
2057 cw,
2058 ch,
2059 );
2060 match cdxy {
2061 0 => chroma_put_pixels(&mut dst.cb, dst_cb_off, &edge_uv, 0, uvlinesize, 8),
2062 1 => chroma_put_x2(&mut dst.cb, dst_cb_off, &edge_uv, 0, uvlinesize, 8),
2063 2 => chroma_put_y2(&mut dst.cb, dst_cb_off, &edge_uv, 0, uvlinesize, 8),
2064 _ => chroma_put_xy2(&mut dst.cb, dst_cb_off, &edge_uv, 0, uvlinesize, 8),
2065 }
2066
2067 let dst_cr_off = dst_yc * uvlinesize + dst_xc;
2068 emulated_edge_mc(
2069 &mut edge_uv,
2070 uvlinesize,
2071 &reference.cr,
2072 uvlinesize,
2073 9,
2074 9,
2075 csrc_x,
2076 csrc_y,
2077 cw,
2078 ch,
2079 );
2080 match cdxy {
2081 0 => chroma_put_pixels(&mut dst.cr, dst_cr_off, &edge_uv, 0, uvlinesize, 8),
2082 1 => chroma_put_x2(&mut dst.cr, dst_cr_off, &edge_uv, 0, uvlinesize, 8),
2083 2 => chroma_put_y2(&mut dst.cr, dst_cr_off, &edge_uv, 0, uvlinesize, 8),
2084 _ => chroma_put_xy2(&mut dst.cr, dst_cr_off, &edge_uv, 0, uvlinesize, 8),
2085 }
2086 return;
2087 }
2088 let coff = (csrc_y as usize) * uvlinesize + (csrc_x as usize);
2089 let dst_xc = mb_col * 8;
2090 let dst_yc = mb_row * 8;
2091 let dst_cb_off = dst_yc * uvlinesize + dst_xc;
2092
2093 match cdxy {
2094 0 => chroma_put_pixels(&mut dst.cb, dst_cb_off, &reference.cb, coff, uvlinesize, 8),
2095 1 => chroma_put_x2(&mut dst.cb, dst_cb_off, &reference.cb, coff, uvlinesize, 8),
2096 2 => chroma_put_y2(&mut dst.cb, dst_cb_off, &reference.cb, coff, uvlinesize, 8),
2097 _ => chroma_put_xy2(&mut dst.cb, dst_cb_off, &reference.cb, coff, uvlinesize, 8),
2098 }
2099
2100 let dst_cr_off = dst_yc * uvlinesize + dst_xc;
2101 match cdxy {
2102 0 => chroma_put_pixels(&mut dst.cr, dst_cr_off, &reference.cr, coff, uvlinesize, 8),
2103 1 => chroma_put_x2(&mut dst.cr, dst_cr_off, &reference.cr, coff, uvlinesize, 8),
2104 2 => chroma_put_y2(&mut dst.cr, dst_cr_off, &reference.cr, coff, uvlinesize, 8),
2105 _ => chroma_put_xy2(&mut dst.cr, dst_cr_off, &reference.cr, coff, uvlinesize, 8),
2106 }
2107}
2108
2109fn add_residual_block(
2110 frame: &mut YuvFrame,
2111 mb_row: u32,
2112 mb_col: u32,
2113 blk: usize,
2114 coeff: &[i32; 64],
2115) {
2116 let (is_luma, bx, by, stride, ph) =
2117 block_coords(mb_row, mb_col, blk, frame.width, frame.height);
2118 let plane: &mut Vec<u8> = if is_luma {
2119 &mut frame.y
2120 } else if blk == 4 {
2121 &mut frame.cb
2122 } else {
2123 &mut frame.cr
2124 };
2125 for r in 0..8 {
2126 if by + r >= ph {
2127 break;
2128 }
2129 for c in 0..8 {
2130 if bx + c >= stride {
2131 break;
2132 }
2133 let idx = (by + r) * stride + (bx + c);
2134 plane[idx] = (plane[idx] as i32 + coeff[r * 8 + c]).clamp(0, 255) as u8;
2135 }
2136 }
2137}
2138
2139const FF_RL_MAX_RUN: usize = 64;
2144const FF_RL_MAX_LEVEL: usize = 64;
2145
2146#[derive(Clone)]
2147struct Wmv2Rl {
2148 n: usize,
2149 last: usize,
2150 vlc: VlcTree,
2151 run: &'static [u8],
2152 level: &'static [u8],
2153 max_level: [[u8; FF_RL_MAX_RUN + 1]; 2],
2154 max_run: [[u8; FF_RL_MAX_LEVEL + 1]; 2],
2155}
2156
2157impl Wmv2Rl {
2158 fn new(base: &crate::na_rl_tables::RlBase) -> Self {
2159 let mut t = VlcTree::new();
2160 for (idx, (code, len)) in base.vlc.iter().enumerate() {
2161 if *len != 0 {
2162 t.insert(*code, *len, idx as i32);
2163 }
2164 }
2165
2166 let mut max_level = [[0u8; FF_RL_MAX_RUN + 1]; 2];
2167 let mut max_run = [[0u8; FF_RL_MAX_LEVEL + 1]; 2];
2168
2169 for last_flag in 0..2usize {
2170 let (start, end) = if last_flag == 0 {
2171 (0usize, base.last)
2172 } else {
2173 (base.last, base.n)
2174 };
2175 for i in start..end {
2176 let r = base.run[i] as usize;
2177 let l = base.level[i] as usize;
2178 if r <= FF_RL_MAX_RUN && l <= FF_RL_MAX_LEVEL {
2179 if base.level[i] > max_level[last_flag][r] {
2180 max_level[last_flag][r] = base.level[i];
2181 }
2182 if base.run[i] > max_run[last_flag][l] {
2183 max_run[last_flag][l] = base.run[i];
2184 }
2185 }
2186 }
2187 }
2188
2189 Wmv2Rl {
2190 n: base.n,
2191 last: base.last,
2192 vlc: t,
2193 run: base.run,
2194 level: base.level,
2195 max_level,
2196 max_run,
2197 }
2198 }
2199
2200 #[inline(always)]
2201 fn decode_sym(&self, br: &mut BitReader<'_>, qscale: i32) -> Option<(i32, i32)> {
2202 let idx = self.vlc.decode(br)? as usize;
2203 if idx == self.n {
2204 return Some((0, 66));
2207 }
2208 let (qmul, qadd) = if qscale == 0 {
2209 (1i32, 0i32)
2210 } else {
2211 (qscale * 2, (qscale - 1) | 1)
2212 };
2213 let mut run = (self.run[idx] as i32) + 1;
2214 let level = (self.level[idx] as i32) * qmul + qadd;
2215 if idx >= self.last {
2216 run += 192;
2217 }
2218 Some((level, run))
2219 }
2220
2221 #[inline(always)]
2222 fn max_level_for(&self, last: usize, run: usize) -> i32 {
2223 self.max_level[last.min(1)][run.min(FF_RL_MAX_RUN)] as i32
2224 }
2225
2226 #[inline(always)]
2227 fn max_run_for(&self, last: usize, level: usize) -> i32 {
2228 self.max_run[last.min(1)][level.min(FF_RL_MAX_LEVEL)] as i32
2229 }
2230}
2231
2232pub struct MacroblockDecoder {
2233 pub width: u32,
2234 pub height: u32,
2235 pub width_mb: u32,
2236 pub height_mb: u32,
2237 pub ref_frame: Option<YuvFrame>,
2239 dc_luma: VlcTable,
2241 dc_chroma: VlcTable,
2242 ac_inter: [VlcTable; 4],
2243 ac_intra: [VlcTable; 4],
2244 cbpcy_i: VlcTable,
2245 cbpcy_p: [VlcTable; 2], ttmb: VlcTable,
2247 ttblk: VlcTable,
2248 mv_vlc: [VlcTable; 4], dc_pred: DcPredBuffer,
2250 mv_pred: MvPredictor,
2251 wmv2_inter: [VlcTable; 2], wmv2_intra: [VlcTable; 2],
2254 wmv2_cbpy: VlcTable,
2255 wmv2_cbpc: VlcTable,
2256 wmv2_ref: Option<YuvFrame>,
2258 wmv2_mb_i_vlc: VlcTree,
2260 wmv2_dc_vlc: [[VlcTree; 2]; 2], wmv2_coded_block: Vec<u8>, wmv2_dc_pred: Wmv2DcPredBuffer,
2263 wmv2_mspel_bit: bool,
2265 wmv2_abt_flag: bool,
2266 wmv2_j_type_bit: bool,
2267 wmv2_top_left_mv_flag: bool,
2268 wmv2_per_mb_rl_bit: bool,
2269 wmv2_j_type: bool,
2271 wmv2_per_mb_rl_table: bool,
2272 wmv2_rl_table_index: u8,
2273 wmv2_rl_chroma_table_index: u8,
2274 wmv2_dc_table_index: usize,
2275
2276 wmv2_cbp_table_index: usize,
2278 wmv2_mv_table_index: usize,
2279 wmv2_mspel: bool,
2280 wmv2_hshift: u8,
2281 wmv2_per_mb_abt: bool,
2282 wmv2_abt_type: u8,
2283 wmv2_skip_type: u8,
2284 wmv2_slice_height: usize,
2285 wmv2_mb_skip: Vec<bool>,
2286 wmv2_motion: Vec<(i32, i32)>,
2287
2288 wmv2_mb_non_intra_vlc: [VlcTree; 4],
2290 wmv2_mv_vlc: [VlcTree; 2],
2291 wmv2_rl: [Wmv2Rl; 6],
2293 wmv2_esc3_level_length: u8,
2295 wmv2_esc3_run_length: u8,
2296 wmv2_ac_val: Vec<[i16; 16]>,
2298 ref_rangeredfrm: bool,
2300 ac_pred: AcPredBuffer,
2301 fwd_ref: Option<YuvFrame>,
2303 bwd_ref: Option<YuvFrame>,
2305}
2306
2307impl MacroblockDecoder {
2308 pub fn new(width: u32, height: u32) -> Self {
2309 let mb_w = ((width + 15) / 16) as usize;
2310 let mb_h = ((height + 15) / 16) as usize;
2311
2312 let wmv2_mb_i_vlc: VlcTree = {
2314 let mut t = VlcTree::new();
2315 for (sym, (code, len)) in FF_MSMP4_MB_I_TABLE.iter().enumerate() {
2316 t.insert(*code, *len, sym as i32);
2317 }
2318 t
2319 };
2320
2321 let wmv2_dc_vlc: [[VlcTree; 2]; 2] = std::array::from_fn(|ti| {
2322 std::array::from_fn(|ch| {
2323 let mut t = VlcTree::new();
2324 for (sym, (code, len)) in FF_MSMP4_DC_TABLES[ti][ch].iter().enumerate() {
2325 t.insert(*code, *len, sym as i32);
2326 }
2327 t
2328 })
2329 });
2330
2331 let wmv2_mb_non_intra_vlc: [VlcTree; 4] = std::array::from_fn(|ti| {
2333 let mut t = VlcTree::new();
2334 for (sym, (code, len)) in FF_MB_NON_INTRA_TABLES[ti].iter().enumerate() {
2335 if *len != 0 {
2336 t.insert(*code, *len, sym as i32);
2337 }
2338 }
2339 t
2340 });
2341
2342 let build_mv_from_lengths = |lens: &[u8; 1100], syms: &[u16; 1100]| -> VlcTree {
2346 let mut t = VlcTree::new();
2347 let mut code: u32 = 0;
2348 for i in 0..1100usize {
2349 let len = lens[i] as i32;
2350 if len == 0 {
2351 continue;
2352 }
2353 let l = len.abs() as u8;
2354 let right_aligned = if l == 0 { 0 } else { code >> (32 - l) };
2356 if len > 0 {
2357 t.insert(right_aligned, l, syms[i] as i32);
2358 }
2359 code = code.wrapping_add(1u32 << (32 - l));
2360 }
2361 t
2362 };
2363 let wmv2_mv_vlc: [VlcTree; 2] = [
2364 build_mv_from_lengths(&FF_MSMP4_MV_TABLE0_LENS, &FF_MSMP4_MV_TABLE0),
2365 build_mv_from_lengths(&FF_MSMP4_MV_TABLE1_LENS, &FF_MSMP4_MV_TABLE1),
2366 ];
2367
2368 let wmv2_rl: [Wmv2Rl; 6] = std::array::from_fn(|i| Wmv2Rl::new(&FF_RL_BASES[i]));
2370 let wmv2_ac_val: Vec<[i16; 16]> = vec![[0i16; 16]; mb_w * mb_h * 6];
2371
2372 MacroblockDecoder {
2373 width,
2374 height,
2375 width_mb: (width + 15) / 16,
2376 height_mb: (height + 15) / 16,
2377 ref_frame: None,
2378 dc_luma: dc_luma_vlc(),
2379 dc_chroma: dc_chroma_vlc(),
2380 ac_inter: [
2381 inter_tcoef_vlc(0),
2382 inter_tcoef_vlc(1),
2383 inter_tcoef_vlc(2),
2384 inter_tcoef_vlc(3),
2385 ],
2386 ac_intra: [
2387 intra_tcoef_vlc(0),
2388 intra_tcoef_vlc(1),
2389 intra_tcoef_vlc(2),
2390 intra_tcoef_vlc(3),
2391 ],
2392 cbpcy_i: cbpcy_i_vlc(),
2393 cbpcy_p: [cbpcy_p_vlc(0), cbpcy_p_vlc(1)],
2394 ttmb: ttmb_vlc(),
2395 ttblk: ttblk_vlc(),
2396 mv_vlc: [
2397 mv_diff_vlc(0),
2398 mv_diff_vlc(1),
2399 mv_diff_vlc(2),
2400 mv_diff_vlc(3),
2401 ],
2402 dc_pred: DcPredBuffer::new(mb_w, mb_h),
2403 mv_pred: MvPredictor::new(mb_w, mb_h),
2404 ref_rangeredfrm: false,
2405 ac_pred: AcPredBuffer::new(mb_w, mb_h),
2406 fwd_ref: None,
2407 bwd_ref: None,
2408 wmv2_inter: [wmv2_tcoef_inter_vlc(0), wmv2_tcoef_inter_vlc(1)],
2409 wmv2_intra: [wmv2_tcoef_intra_vlc(0), wmv2_tcoef_intra_vlc(1)],
2410 wmv2_cbpy: wmv2_cbpy_vlc(),
2411 wmv2_cbpc: wmv2_cbpc_p_vlc(),
2412 wmv2_ref: None,
2413
2414 wmv2_mb_i_vlc,
2416 wmv2_dc_vlc,
2417 wmv2_coded_block: vec![0u8; (2 * mb_w) * (2 * mb_h)],
2418 wmv2_dc_pred: Wmv2DcPredBuffer::new(mb_w, mb_h),
2419
2420 wmv2_mspel_bit: false,
2422 wmv2_abt_flag: false,
2423 wmv2_j_type_bit: false,
2424 wmv2_top_left_mv_flag: false,
2425 wmv2_per_mb_rl_bit: false,
2426
2427 wmv2_j_type: false,
2429 wmv2_per_mb_rl_table: false,
2430 wmv2_rl_table_index: 0,
2431 wmv2_rl_chroma_table_index: 0,
2432 wmv2_dc_table_index: 0,
2433
2434 wmv2_cbp_table_index: 0,
2435 wmv2_mv_table_index: 0,
2436 wmv2_mspel: false,
2437 wmv2_hshift: 0,
2438 wmv2_per_mb_abt: false,
2439 wmv2_abt_type: 0,
2440 wmv2_skip_type: 0,
2441 wmv2_slice_height: mb_h.max(1),
2442 wmv2_mb_skip: vec![false; mb_w * mb_h],
2443 wmv2_motion: vec![(0, 0); mb_w * mb_h],
2444
2445 wmv2_mb_non_intra_vlc,
2446 wmv2_mv_vlc,
2447
2448 wmv2_rl,
2449 wmv2_esc3_level_length: 0,
2450 wmv2_esc3_run_length: 0,
2451 wmv2_ac_val,
2452 }
2453 }
2454
2455 pub fn decode_frame(
2456 &mut self,
2457 payload: &[u8],
2458 pic_hdr: &PictureHeader,
2459 seq: &SequenceHeader,
2460 frame: &mut YuvFrame,
2461 ) -> Result<()> {
2462 match pic_hdr.frame_type {
2463 FrameType::I | FrameType::BI => {
2464 self.decode_intra(payload, pic_hdr, seq, frame)?;
2465 if seq.overlap && pic_hdr.pquant >= 9 {
2466 apply_overlap_filter(frame);
2467 }
2468 if seq.loop_filter {
2469 apply_loop_filter(frame);
2470 }
2471 }
2472 FrameType::P => {
2473 if seq.rangered {
2474 let cur_rr = pic_hdr.rangeredfrm;
2475 let ref_rr = self.ref_rangeredfrm;
2476 if ref_rr && !cur_rr {
2477 if let Some(ref mut rf) = self.ref_frame {
2478 apply_rangered_compress(rf);
2479 }
2480 }
2481 }
2482 self.decode_p(payload, pic_hdr, seq, frame)?;
2483 if seq.loop_filter {
2484 apply_loop_filter(frame);
2485 }
2486 }
2487 FrameType::B => {
2488 self.decode_b(payload, pic_hdr, seq, frame)?;
2489 if seq.loop_filter {
2490 apply_loop_filter(frame);
2491 }
2492 }
2493 FrameType::Skipped => {
2494 if let Some(ref rf) = self.ref_frame {
2495 frame.y.copy_from_slice(&rf.y);
2496 frame.cb.copy_from_slice(&rf.cb);
2497 frame.cr.copy_from_slice(&rf.cr);
2498 }
2499 }
2500 }
2501
2502 if seq.rangered && pic_hdr.rangeredfrm {
2504 apply_rangered_expand(frame);
2505 }
2506 self.ref_rangeredfrm = pic_hdr.rangeredfrm;
2507
2508 match pic_hdr.frame_type {
2512 FrameType::B | FrameType::BI => {
2513 }
2515 _ => {
2516 self.fwd_ref = self.bwd_ref.take();
2518 self.bwd_ref = Some(frame.clone());
2519 self.ref_frame = Some(frame.clone());
2520 }
2521 }
2522 Ok(())
2523 }
2524
2525 fn decode_intra(
2528 &mut self,
2529 payload: &[u8],
2530 pic_hdr: &PictureHeader,
2531 seq: &SequenceHeader,
2532 frame: &mut YuvFrame,
2533 ) -> Result<()> {
2534 let mut br = BitReader::new_at(payload, pic_hdr.header_bits);
2537 let pquant = pic_hdr.pquant as i32;
2538 let halfqp = pic_hdr.halfqp;
2539 let uniform = seq.quantizer_mode != crate::vc1::QuantizerMode::NonUniform;
2540
2541 let mb_w = self.width_mb as usize;
2543 let mb_h = self.height_mb as usize;
2544 self.dc_pred = DcPredBuffer::new(mb_w, mb_h);
2545 self.ac_pred = AcPredBuffer::new(mb_w, mb_h);
2546
2547 for mb_row in 0..self.height_mb {
2548 for mb_col in 0..self.width_mb {
2549 if br.is_empty() {
2550 return Ok(());
2551 }
2552
2553 let cbp = self.cbpcy_i.decode(&mut br).unwrap_or(0) as u8;
2555
2556 let mb_pquant = read_mquant(&mut br, seq.dquant, pquant);
2558
2559 let mb_tt = if seq.vstransform {
2561 self.ttmb.decode(&mut br).unwrap_or(0) as u8
2562 } else {
2563 0
2564 };
2565
2566 for blk in 0..6usize {
2567 let is_luma = blk < 4;
2568
2569 let dc_vlc = if is_luma {
2571 &self.dc_luma
2572 } else {
2573 &self.dc_chroma
2574 };
2575 let dc_diff = read_dc_diff(&mut br, dc_vlc);
2576
2577 let dc_scale = dc_step(mb_pquant, is_luma);
2579 let (dc_pred_val, _use_left) =
2580 self.dc_pred.predict(mb_row as usize, mb_col as usize, blk);
2581
2582 let dc_recon = dc_pred_val + dc_diff * dc_scale;
2583 self.dc_pred
2584 .store(mb_row as usize, mb_col as usize, blk, dc_recon);
2585
2586 let coded = (cbp >> (5 - blk)) & 1 != 0;
2587 let blk_tt = if coded && mb_tt == 6 {
2588 self.ttblk.decode(&mut br).unwrap_or(0) as u8
2589 } else {
2590 mb_tt
2591 };
2592
2593 let mut coeff = if coded {
2594 decode_block_ac(
2595 &mut br,
2596 is_luma,
2597 mb_pquant,
2598 halfqp,
2599 uniform,
2600 blk_tt,
2601 &self.ac_intra[seq.transacfrm2 as usize],
2602 )
2603 } else {
2604 [0i32; 64]
2605 };
2606
2607 coeff[0] = dc_recon;
2609
2610 if _use_left {
2615 let pred = self.ac_pred.pred_row(mb_row as usize, mb_col as usize, blk);
2617 for i in 0..7 {
2618 coeff[i + 1] += pred[i];
2619 }
2620 let our_row = [
2622 coeff[1], coeff[2], coeff[3], coeff[4], coeff[5], coeff[6], coeff[7],
2623 ];
2624 self.ac_pred
2625 .store_row(mb_row as usize, mb_col as usize, blk, our_row);
2626 } else {
2627 let pred = self.ac_pred.pred_col(mb_row as usize, mb_col as usize, blk);
2629 for i in 0..7 {
2630 coeff[(i + 1) * 8] += pred[i];
2631 }
2632 let our_col = [
2633 coeff[8], coeff[16], coeff[24], coeff[32], coeff[40], coeff[48],
2634 coeff[56],
2635 ];
2636 self.ac_pred
2637 .store_col(mb_row as usize, mb_col as usize, blk, our_col);
2638 }
2639
2640 apply_idct(&mut coeff, blk_tt);
2641 write_intra_block(frame, mb_row, mb_col, blk, &coeff);
2642 }
2643 }
2644 }
2645 Ok(())
2646 }
2647
2648 fn decode_p(
2651 &mut self,
2652 payload: &[u8],
2653 pic_hdr: &PictureHeader,
2654 seq: &SequenceHeader,
2655 frame: &mut YuvFrame,
2656 ) -> Result<()> {
2657 if let Some(ref rf) = self.ref_frame {
2659 frame.y.copy_from_slice(&rf.y);
2660 frame.cb.copy_from_slice(&rf.cb);
2661 frame.cr.copy_from_slice(&rf.cr);
2662 }
2663
2664 let mut br = BitReader::new_at(payload, pic_hdr.header_bits);
2665 let pquant = pic_hdr.pquant as i32;
2666 let halfqp = pic_hdr.halfqp;
2667 let uniform = seq.quantizer_mode != crate::vc1::QuantizerMode::NonUniform;
2668 let mv_vlc = &self.mv_vlc[seq.mvtab as usize];
2669
2670 let mv_scale = 1i32 << (pic_hdr.mvrange as i32 + 1);
2672
2673 let ref_y = self
2674 .ref_frame
2675 .as_ref()
2676 .map(|f| f.y.clone())
2677 .unwrap_or_default();
2678 let ref_cb = self
2679 .ref_frame
2680 .as_ref()
2681 .map(|f| f.cb.clone())
2682 .unwrap_or_default();
2683 let ref_cr = self
2684 .ref_frame
2685 .as_ref()
2686 .map(|f| f.cr.clone())
2687 .unwrap_or_default();
2688 let fw = self.width as usize;
2689 let fh = self.height as usize;
2690
2691 let mb_w = self.width_mb as usize;
2693 let mb_h = self.height_mb as usize;
2694 self.mv_pred = MvPredictor::new(mb_w, mb_h);
2695
2696 let skip_plane = pic_hdr.skipmb_plane.clone().unwrap_or_default();
2698
2699 for mb_row in 0..self.height_mb {
2700 for mb_col in 0..self.width_mb {
2701 if br.is_empty() {
2702 return Ok(());
2703 }
2704
2705 let mb_idx = mb_row as usize * mb_w + mb_col as usize;
2706
2707 let skipped = if skip_plane.is_empty() {
2709 br.read_bit().unwrap_or(false)
2710 } else {
2711 skip_plane.get(mb_idx).copied().unwrap_or(0) != 0
2712 };
2713
2714 if skipped {
2715 let (pvx, pvy) = self.mv_pred.predict(mb_row as usize, mb_col as usize);
2717 self.mv_pred
2718 .store(mb_row as usize, mb_col as usize, (pvx, pvy), true);
2719 continue;
2720 }
2721
2722 let (pvx, pvy) = self.mv_pred.predict(mb_row as usize, mb_col as usize);
2724
2725 let dmvx = Self::read_mv_diff(&mut br, mv_vlc, mv_scale);
2727 let dmvy = Self::read_mv_diff(&mut br, mv_vlc, mv_scale);
2728 let mvx = pvx + dmvx;
2729 let mvy = pvy + dmvy;
2730
2731 self.mv_pred
2733 .store(mb_row as usize, mb_col as usize, (mvx, mvy), false);
2734
2735 {
2737 let dst_x = (mb_col * 16) as usize;
2738 let dst_y = (mb_row * 16) as usize;
2739 let src_x = (dst_x as i32 * 2 + mvx) as i32; let src_y = (dst_y as i32 * 2 + mvy) as i32;
2741 let mut tmp = [0u8; 256];
2742 if ref_y.len() == fw * fh {
2743 mc_luma(&mut tmp, 16, &ref_y, fw, fw, fh, src_x, src_y, 16, 16);
2744 let dst = &mut frame.y[dst_y * fw + dst_x..];
2745 for r in 0..16 {
2746 dst[r * fw..r * fw + 16].copy_from_slice(&tmp[r * 16..r * 16 + 16]);
2747 }
2748 }
2749 }
2750
2751 {
2753 let cw = fw / 2;
2754 let ch = fh / 2;
2755 let dst_x = (mb_col * 8) as usize;
2756 let dst_y = (mb_row * 8) as usize;
2757 let cmvx_raw = mvx / 2;
2759 let cmvy_raw = mvy / 2;
2760 let (cmvx, cmvy) = if seq.fastuvmc {
2763 let round = |v: i32| -> i32 {
2765 if v >= 0 {
2766 v & !1
2767 } else {
2768 -((-v) & !1)
2769 }
2770 };
2771 (round(cmvx_raw), round(cmvy_raw))
2772 } else {
2773 (cmvx_raw, cmvy_raw)
2774 };
2775 let src_x = (dst_x as i32 * 2 + cmvx) as i32;
2776 let src_y = (dst_y as i32 * 2 + cmvy) as i32;
2777 let mut tmp_cb = [0u8; 64];
2778 let mut tmp_cr = [0u8; 64];
2779 if ref_cb.len() == cw * ch {
2780 mc_luma(&mut tmp_cb, 8, &ref_cb, cw, cw, ch, src_x, src_y, 8, 8);
2781 mc_luma(&mut tmp_cr, 8, &ref_cr, cw, cw, ch, src_x, src_y, 8, 8);
2782 let dcb = &mut frame.cb[dst_y * cw + dst_x..];
2783 let dcr = &mut frame.cr[dst_y * cw + dst_x..];
2784 for r in 0..8 {
2785 dcb[r * cw..r * cw + 8].copy_from_slice(&tmp_cb[r * 8..r * 8 + 8]);
2786 dcr[r * cw..r * cw + 8].copy_from_slice(&tmp_cr[r * 8..r * 8 + 8]);
2787 }
2788 }
2789 }
2790
2791 let cbp = self.cbpcy_p[(seq.cbptab as usize).min(1)]
2793 .decode(&mut br)
2794 .unwrap_or(0) as u8;
2795 let mb_pquant = read_mquant(&mut br, seq.dquant, pquant);
2797 let mb_tt = if seq.vstransform {
2798 self.ttmb.decode(&mut br).unwrap_or(0) as u8
2799 } else {
2800 0
2801 };
2802
2803 for blk in 0..6usize {
2804 if (cbp >> (5 - blk)) & 1 == 0 {
2805 continue;
2806 }
2807 let is_luma = blk < 4;
2808 let blk_tt = if mb_tt == 6 {
2809 self.ttblk.decode(&mut br).unwrap_or(0) as u8
2810 } else {
2811 mb_tt
2812 };
2813
2814 let mut coeff = decode_block(
2815 &mut br,
2816 false,
2817 is_luma,
2818 mb_pquant,
2819 halfqp,
2820 uniform,
2821 blk_tt,
2822 &self.dc_luma,
2823 &self.dc_chroma,
2824 &self.ac_intra[seq.transacfrm2 as usize],
2825 &self.ac_inter[seq.transacfrm as usize],
2826 );
2827 apply_idct(&mut coeff, blk_tt);
2828 add_residual_block(frame, mb_row as u32, mb_col as u32, blk, &coeff);
2829 }
2830 }
2831 }
2832 Ok(())
2833 }
2834
2835 fn decode_b(
2842 &mut self,
2843 payload: &[u8],
2844 pic_hdr: &PictureHeader,
2845 seq: &SequenceHeader,
2846 frame: &mut YuvFrame,
2847 ) -> Result<()> {
2848 let fwd = match &self.fwd_ref {
2849 Some(f) => f.clone(),
2850 None => return Ok(()), };
2852 let bwd = match &self.bwd_ref {
2853 Some(f) => f.clone(),
2854 None => return Ok(()), };
2856
2857 let mut br = BitReader::new(payload);
2858 let pquant = pic_hdr.pquant as i32;
2859 let halfqp = pic_hdr.halfqp;
2860 let uniform = seq.quantizer_mode != crate::vc1::QuantizerMode::NonUniform;
2861 let mv_vlc = &self.mv_vlc[seq.mvtab as usize];
2862 let mv_scale = 1i32 << (pic_hdr.mvrange as i32 + 1);
2863
2864 let fw = self.width as usize;
2865 let fh = self.height as usize;
2866 let mb_w = self.width_mb as usize;
2867 let mb_h = self.height_mb as usize;
2868 self.mv_pred = MvPredictor::new(mb_w, mb_h);
2869
2870 let direct_plane = pic_hdr.directmb_plane.clone().unwrap_or_default();
2872 let skip_plane = pic_hdr.skipmb_plane.clone().unwrap_or_default();
2873
2874 let direct_scale_num = pic_hdr.bfrac_num;
2876 let direct_scale_den = pic_hdr.bfrac_den;
2877
2878 for mb_row in 0..self.height_mb {
2879 for mb_col in 0..self.width_mb {
2880 if br.is_empty() {
2881 return Ok(());
2882 }
2883
2884 let mb_idx = mb_row as usize * mb_w + mb_col as usize;
2885 let is_direct = direct_plane.get(mb_idx).copied().unwrap_or(0) != 0;
2886 let is_skip = skip_plane.get(mb_idx).copied().unwrap_or(0) != 0;
2887
2888 if is_skip || is_direct {
2889 let (pvx, pvy) = self.mv_pred.predict(mb_row as usize, mb_col as usize);
2891 let fvx = pvx * direct_scale_num / direct_scale_den;
2893 let fvy = pvy * direct_scale_num / direct_scale_den;
2894 let bvx = fvx - pvx;
2895 let bvy = fvy - pvy;
2896
2897 self.mc_blend_mb(
2898 frame, mb_row, mb_col, &fwd, &bwd, fvx, fvy, bvx, bvy, fw, fh,
2899 );
2900 self.mv_pred
2901 .store(mb_row as usize, mb_col as usize, (pvx, pvy), is_skip);
2902 continue;
2903 }
2904
2905 let mb_type = br.read_bits(2).unwrap_or(2);
2908
2909 if mb_type == 0 {
2910 let cbp = self.cbpcy_i.decode(&mut br).unwrap_or(0) as u8;
2912 let mb_pquant = read_mquant(&mut br, seq.dquant, pquant);
2913 let mb_tt = if seq.vstransform {
2914 self.ttmb.decode(&mut br).unwrap_or(0) as u8
2915 } else {
2916 0
2917 };
2918 for blk in 0..6usize {
2919 let coded = (cbp >> (5 - blk)) & 1 != 0;
2920 if coded {
2921 let blk_tt = if mb_tt == 6 {
2922 self.ttblk.decode(&mut br).unwrap_or(0) as u8
2923 } else {
2924 mb_tt
2925 };
2926 let mut coeff = decode_block(
2927 &mut br,
2928 true,
2929 blk < 4,
2930 mb_pquant,
2931 halfqp,
2932 uniform,
2933 blk_tt,
2934 &self.dc_luma,
2935 &self.dc_chroma,
2936 &self.ac_intra[seq.transacfrm2 as usize],
2937 &self.ac_inter[seq.transacfrm as usize],
2938 );
2939 apply_idct(&mut coeff, blk_tt);
2940 write_intra_block(frame, mb_row, mb_col, blk, &coeff);
2941 }
2942 }
2943 self.mv_pred
2944 .store(mb_row as usize, mb_col as usize, (0, 0), false);
2945 continue;
2946 }
2947
2948 let use_fwd = mb_type == 2 || mb_type == 3;
2950 let use_bwd = mb_type == 1 || mb_type == 3;
2951
2952 let (pvx, pvy) = self.mv_pred.predict(mb_row as usize, mb_col as usize);
2953
2954 let (fvx, fvy) = if use_fwd {
2955 let dx = Self::read_mv_diff(&mut br, mv_vlc, mv_scale);
2956 let dy = Self::read_mv_diff(&mut br, mv_vlc, mv_scale);
2957 (pvx + dx, pvy + dy)
2958 } else {
2959 (0, 0)
2960 };
2961
2962 let (bvx, bvy) = if use_bwd {
2963 let dx = Self::read_mv_diff(&mut br, mv_vlc, mv_scale);
2964 let dy = Self::read_mv_diff(&mut br, mv_vlc, mv_scale);
2965 (pvx + dx, pvy + dy)
2966 } else {
2967 (0, 0)
2968 };
2969
2970 self.mv_pred.store(
2971 mb_row as usize,
2972 mb_col as usize,
2973 if use_fwd { (fvx, fvy) } else { (bvx, bvy) },
2974 false,
2975 );
2976
2977 if use_fwd && use_bwd {
2978 self.mc_blend_mb(
2979 frame, mb_row, mb_col, &fwd, &bwd, fvx, fvy, bvx, bvy, fw, fh,
2980 );
2981 } else if use_fwd {
2982 self.mc_single_mb(frame, mb_row, mb_col, &fwd, fvx, fvy, fw, fh);
2983 } else {
2984 self.mc_single_mb(frame, mb_row, mb_col, &bwd, bvx, bvy, fw, fh);
2985 }
2986
2987 let cbp = self.cbpcy_p[(seq.cbptab as usize).min(1)]
2989 .decode(&mut br)
2990 .unwrap_or(0) as u8;
2991 let mb_pquant = read_mquant(&mut br, seq.dquant, pquant);
2992 let mb_tt = if seq.vstransform {
2993 self.ttmb.decode(&mut br).unwrap_or(0) as u8
2994 } else {
2995 0
2996 };
2997 for blk in 0..6usize {
2998 if (cbp >> (5 - blk)) & 1 == 0 {
2999 continue;
3000 }
3001 let blk_tt = if mb_tt == 6 {
3002 self.ttblk.decode(&mut br).unwrap_or(0) as u8
3003 } else {
3004 mb_tt
3005 };
3006 let mut coeff = decode_block(
3007 &mut br,
3008 false,
3009 blk < 4,
3010 mb_pquant,
3011 halfqp,
3012 uniform,
3013 blk_tt,
3014 &self.dc_luma,
3015 &self.dc_chroma,
3016 &self.ac_intra[seq.transacfrm2 as usize],
3017 &self.ac_inter[seq.transacfrm as usize],
3018 );
3019 apply_idct(&mut coeff, blk_tt);
3020 add_residual_block(frame, mb_row as u32, mb_col as u32, blk, &coeff);
3021 }
3022 }
3023 }
3024 Ok(())
3025 }
3026
3027 fn mc_single_mb(
3029 &self,
3030 frame: &mut YuvFrame,
3031 mb_row: u32,
3032 mb_col: u32,
3033 refp: &YuvFrame,
3034 mvx: i32,
3035 mvy: i32,
3036 fw: usize,
3037 fh: usize,
3038 ) {
3039 let dst_x = (mb_col * 16) as usize;
3040 let dst_y = (mb_row * 16) as usize;
3041 let src_x = dst_x as i32 * 2 + mvx;
3042 let src_y = dst_y as i32 * 2 + mvy;
3043 let mut tmp = [0u8; 256];
3044 mc_luma(&mut tmp, 16, &refp.y, fw, fw, fh, src_x, src_y, 16, 16);
3045 let dst = &mut frame.y[dst_y * fw + dst_x..];
3046 for r in 0..16 {
3047 dst[r * fw..r * fw + 16].copy_from_slice(&tmp[r * 16..r * 16 + 16]);
3048 }
3049
3050 let cw = fw / 2;
3051 let ch = fh / 2;
3052 let cdst_x = (mb_col * 8) as usize;
3053 let cdst_y = (mb_row * 8) as usize;
3054 let csrc_x = cdst_x as i32 * 2 + mvx / 2;
3055 let csrc_y = cdst_y as i32 * 2 + mvy / 2;
3056 let mut tmp_cb = [0u8; 64];
3057 let mut tmp_cr = [0u8; 64];
3058 mc_luma(&mut tmp_cb, 8, &refp.cb, cw, cw, ch, csrc_x, csrc_y, 8, 8);
3059 mc_luma(&mut tmp_cr, 8, &refp.cr, cw, cw, ch, csrc_x, csrc_y, 8, 8);
3060 let dcb = &mut frame.cb[cdst_y * cw + cdst_x..];
3061 let dcr = &mut frame.cr[cdst_y * cw + cdst_x..];
3062 for r in 0..8 {
3063 dcb[r * cw..r * cw + 8].copy_from_slice(&tmp_cb[r * 8..r * 8 + 8]);
3064 dcr[r * cw..r * cw + 8].copy_from_slice(&tmp_cr[r * 8..r * 8 + 8]);
3065 }
3066 }
3067
3068 fn mc_blend_mb(
3070 &self,
3071 frame: &mut YuvFrame,
3072 mb_row: u32,
3073 mb_col: u32,
3074 fwd: &YuvFrame,
3075 bwd: &YuvFrame,
3076 fvx: i32,
3077 fvy: i32,
3078 bvx: i32,
3079 bvy: i32,
3080 fw: usize,
3081 fh: usize,
3082 ) {
3083 let dst_x = (mb_col * 16) as usize;
3084 let dst_y = (mb_row * 16) as usize;
3085 let fsrc_x = dst_x as i32 * 2 + fvx;
3086 let fsrc_y = dst_y as i32 * 2 + fvy;
3087 let bsrc_x = dst_x as i32 * 2 + bvx;
3088 let bsrc_y = dst_y as i32 * 2 + bvy;
3089
3090 let mut ftmp = [0u8; 256];
3091 let mut btmp = [0u8; 256];
3092 mc_luma(&mut ftmp, 16, &fwd.y, fw, fw, fh, fsrc_x, fsrc_y, 16, 16);
3093 mc_luma(&mut btmp, 16, &bwd.y, fw, fw, fh, bsrc_x, bsrc_y, 16, 16);
3094 let dst = &mut frame.y[dst_y * fw + dst_x..];
3095 for r in 0..16 {
3096 for c in 0..16 {
3097 dst[r * fw + c] =
3098 ((ftmp[r * 16 + c] as u16 + btmp[r * 16 + c] as u16 + 1) >> 1) as u8;
3099 }
3100 }
3101
3102 let cw = fw / 2;
3103 let ch = fh / 2;
3104 let cdst_x = (mb_col * 8) as usize;
3105 let cdst_y = (mb_row * 8) as usize;
3106 let cfsrc_x = cdst_x as i32 * 2 + fvx / 2;
3107 let cfsrc_y = cdst_y as i32 * 2 + fvy / 2;
3108 let cbsrc_x = cdst_x as i32 * 2 + bvx / 2;
3109 let cbsrc_y = cdst_y as i32 * 2 + bvy / 2;
3110 let mut fcb = [0u8; 64];
3111 let mut fcrb = [0u8; 64];
3112 let mut bcb = [0u8; 64];
3113 let mut bcrb = [0u8; 64];
3114 mc_luma(&mut fcb, 8, &fwd.cb, cw, cw, ch, cfsrc_x, cfsrc_y, 8, 8);
3115 mc_luma(&mut fcrb, 8, &fwd.cr, cw, cw, ch, cfsrc_x, cfsrc_y, 8, 8);
3116 mc_luma(&mut bcb, 8, &bwd.cb, cw, cw, ch, cbsrc_x, cbsrc_y, 8, 8);
3117 mc_luma(&mut bcrb, 8, &bwd.cr, cw, cw, ch, cbsrc_x, cbsrc_y, 8, 8);
3118 let dcb = &mut frame.cb[cdst_y * cw + cdst_x..];
3119 let dcr = &mut frame.cr[cdst_y * cw + cdst_x..];
3120 for r in 0..8 {
3121 for c in 0..8 {
3122 dcb[r * cw + c] = ((fcb[r * 8 + c] as u16 + bcb[r * 8 + c] as u16 + 1) >> 1) as u8;
3123 dcr[r * cw + c] =
3124 ((fcrb[r * 8 + c] as u16 + bcrb[r * 8 + c] as u16 + 1) >> 1) as u8;
3125 }
3126 }
3127 }
3128
3129 fn read_mv_diff(br: &mut BitReader<'_>, mv_vlc: &VlcTable, scale: i32) -> i32 {
3130 let sym = mv_vlc.decode(br).unwrap_or(0);
3131 if sym == i32::MIN {
3132 br.read_bits_signed(17).unwrap_or(0)
3134 } else {
3135 sym * scale / 4 }
3137 }
3138}
3139
3140#[inline(always)]
3162fn wmv2_dc_scale(pquant: i32, is_luma: bool) -> i32 {
3163 const Y: [i32; 32] = [
3165 0, 8, 8, 8, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18,
3166 18, 19, 19, 20, 20, 21, 21,
3167 ];
3168 const C: [i32; 32] = [
3169 0, 8, 8, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18,
3170 18, 19, 19, 20, 20, 21, 21, 22,
3171 ];
3172 let idx = pquant.clamp(1, 31) as usize;
3173 if is_luma {
3174 Y[idx]
3175 } else {
3176 C[idx]
3177 }
3178}
3179
3180#[inline(always)]
3181fn decode012(br: &mut BitReader<'_>) -> u8 {
3182 match br.read_bit() {
3184 Some(false) => 0,
3185 Some(true) => br.read_bit().map(|b| if b { 2 } else { 1 }).unwrap_or(0),
3186 None => 0,
3187 }
3188}
3189
3190#[inline(always)]
3191fn wmv2_get_cbp_table_index(qscale: i32, cbp_index: u8) -> usize {
3192 const MAP: [[u8; 3]; 3] = [[0, 2, 1], [1, 0, 2], [2, 1, 0]];
3194 let a = if qscale > 10 { 1 } else { 0 };
3195 let b = if qscale > 20 { 1 } else { 0 };
3196 let row = (a + b) as usize;
3197 MAP[row][(cbp_index as usize).min(2)] as usize
3198}
3199
3200impl MacroblockDecoder {
3201 pub fn wmv2_set_extradata(&mut self, extradata: &[u8]) {
3207 if extradata.len() < 4 {
3208 return;
3209 }
3210 let mut br = BitReader::new(&extradata[..4]);
3211 let _fps = br.read_bits(5).unwrap_or(0);
3212 let _bit_rate = br.read_bits(11).unwrap_or(0) * 1024;
3213 self.wmv2_mspel_bit = br.read_bit().unwrap_or(false);
3214 let _loop_filter = br.read_bit().unwrap_or(false);
3215 self.wmv2_abt_flag = br.read_bit().unwrap_or(false);
3216 self.wmv2_j_type_bit = br.read_bit().unwrap_or(false);
3217 self.wmv2_top_left_mv_flag = br.read_bit().unwrap_or(false);
3218 self.wmv2_per_mb_rl_bit = br.read_bit().unwrap_or(false);
3219 let code = br.read_bits(3).unwrap_or(0) as usize;
3220 if code == 0 {
3221 return;
3222 }
3223 let mb_h = self.height_mb as usize;
3224 self.wmv2_slice_height = mb_h / code;
3225 }
3226
3227 pub fn wmv2_copy_ref(&self, out: &mut YuvFrame) -> bool {
3228 let Some(r) = self.wmv2_ref.as_ref() else {
3229 return false;
3230 };
3231 if out.width != r.width || out.height != r.height {
3232 *out = r.clone();
3233 return true;
3234 }
3235 if out.y.len() == r.y.len() {
3236 out.y.copy_from_slice(&r.y);
3237 } else {
3238 out.y = r.y.clone();
3239 }
3240 if out.cb.len() == r.cb.len() {
3241 out.cb.copy_from_slice(&r.cb);
3242 } else {
3243 out.cb = r.cb.clone();
3244 }
3245 if out.cr.len() == r.cr.len() {
3246 out.cr.copy_from_slice(&r.cr);
3247 } else {
3248 out.cr = r.cr.clone();
3249 }
3250 true
3251 }
3252
3253 pub fn decode_wmv2_frame(
3254 &mut self,
3255 payload: &[u8],
3256 hdr: &Wmv2FrameHeader,
3257 params: &Wmv2Params,
3258 frame: &mut YuvFrame,
3259 ) -> Result<()> {
3260 if self.width != params.width || self.height != params.height {
3262 *self = MacroblockDecoder::new(params.width, params.height);
3263 }
3264
3265 if hdr.frame_skipped {
3266 let _ = self.wmv2_copy_ref(frame);
3267 return Ok(());
3268 }
3269 match hdr.frame_type {
3270 Wmv2FrameType::I => self.wmv2_decode_intra(payload, hdr, frame),
3271 Wmv2FrameType::P => self.wmv2_decode_p(payload, hdr, frame),
3272 }
3273 }
3274
3275 pub fn probe_wmv2_payload(&self, payload: &[u8], hdr: &Wmv2FrameHeader) -> usize {
3281 let mut br = BitReader::new_at(payload, hdr.header_bits);
3282
3283 if hdr.frame_type == Wmv2FrameType::I {
3285 let mut br = BitReader::new_at(payload, hdr.header_bits);
3286 let j_type = if self.wmv2_j_type_bit {
3288 br.read_bit().unwrap_or(false)
3289 } else {
3290 false
3291 };
3292 if j_type {
3293 return 1;
3294 }
3295 let per_mb_rl_table = if self.wmv2_per_mb_rl_bit {
3296 br.read_bit().unwrap_or(false)
3297 } else {
3298 false
3299 };
3300 if !per_mb_rl_table {
3301 let _ = decode012(&mut br);
3302 let _ = decode012(&mut br);
3303 }
3304 let dc_table_index = br.read_bit().unwrap_or(false) as usize;
3305 let code = match self.wmv2_mb_i_vlc.decode(&mut br) {
3306 Some(v) => v as u32,
3307 None => return 0,
3308 };
3309 let _ = code;
3310 let _ac_pred = br.read_bit().unwrap_or(false);
3311 let _ = _ac_pred;
3312 if per_mb_rl_table && code != 0 {
3313 let _ = decode012(&mut br);
3314 }
3315 const DC_MAX: i32 = 119;
3317 for blk in 0..6usize {
3318 let is_chroma = blk >= 4;
3319 let tbl = &self.wmv2_dc_vlc[dc_table_index][if is_chroma { 1 } else { 0 }];
3320 let mut level = match tbl.decode(&mut br) {
3321 Some(v) => v,
3322 None => return 0,
3323 };
3324 if level == DC_MAX {
3325 let _ = br.read_bits(8);
3326 let _ = br.read_bit();
3327 } else if level != 0 {
3328 let _ = br.read_bit();
3329 }
3330 }
3331 return 1;
3332 }
3333
3334 if hdr.frame_type == Wmv2FrameType::P {
3336 let mut br = BitReader::new_at(payload, hdr.header_bits);
3337 let mb_w = self.width_mb as usize;
3338 let mb_h = self.height_mb as usize;
3339 let qscale = hdr.pquant as i32;
3340
3341 let skip_type = br.read_bits(2).unwrap_or(0) as u8;
3343 let first_skip = match skip_type {
3344 0 => false,
3345 1 => br.read_bit().unwrap_or(false),
3346 2 => {
3347 let all = br.read_bit().unwrap_or(false);
3348 if all {
3349 true
3350 } else {
3351 br.read_bit().unwrap_or(false)
3352 }
3353 }
3354 3 => {
3355 let all = br.read_bit().unwrap_or(false);
3356 if all {
3357 true
3358 } else {
3359 br.read_bit().unwrap_or(false)
3360 }
3361 }
3362 _ => false,
3363 };
3364
3365 if skip_type == 1 {
3368 let _ = mb_w * mb_h;
3369 }
3370
3371 let cbp_index = decode012(&mut br);
3372 let cbp_table_index = wmv2_get_cbp_table_index(qscale, cbp_index);
3373
3374 let _mspel = if self.wmv2_mspel_bit {
3375 br.read_bit().unwrap_or(false)
3376 } else {
3377 false
3378 };
3379 if self.wmv2_abt_flag {
3380 let per_mb_abt = br.read_bit().unwrap_or(false) ^ true;
3381 if !per_mb_abt {
3382 let _ = decode012(&mut br);
3383 }
3384 }
3385 let per_mb_rl_table = if self.wmv2_per_mb_rl_bit {
3386 br.read_bit().unwrap_or(false)
3387 } else {
3388 false
3389 };
3390 if !per_mb_rl_table {
3391 let _ = decode012(&mut br);
3392 }
3393 let dc_table_index = br.read_bit().unwrap_or(false) as usize;
3394 let mv_table_index = br.read_bit().unwrap_or(false) as usize;
3395
3396 if first_skip {
3397 return 1;
3398 }
3399
3400 let code = match self.wmv2_mb_non_intra_vlc[cbp_table_index.min(3)].decode(&mut br) {
3401 Some(v) => v as i32,
3402 None => return 0,
3403 };
3404 let mb_intra = (code & 0x40) == 0;
3405 let cbp = (code & 0x3f) as u8;
3406
3407 if mb_intra {
3408 let _ac_pred = br.read_bit().unwrap_or(false);
3409 if per_mb_rl_table && cbp != 0 {
3410 let _ = decode012(&mut br);
3411 }
3412 const DC_MAX: i32 = 119;
3414 let tbl = &self.wmv2_dc_vlc[dc_table_index][0];
3415 let mut level = match tbl.decode(&mut br) {
3416 Some(v) => v,
3417 None => return 0,
3418 };
3419 if level == DC_MAX {
3420 let _ = br.read_bits(8);
3421 let _ = br.read_bit();
3422 } else if level != 0 {
3423 let _ = br.read_bit();
3424 }
3425 } else {
3426 let tbl = &self.wmv2_mv_vlc[mv_table_index.min(1)];
3428 let sym = match tbl.decode(&mut br) {
3429 Some(v) => v as u16,
3430 None => return 0,
3431 };
3432 if sym == 0 {
3433 let _ = br.read_bits(12);
3434 }
3435 }
3436 return 1;
3437 }
3438
3439 let max_mb = (self.width_mb as usize * self.height_mb as usize).min(64);
3440 let mut score: usize = 0;
3441
3442 let ac_intra = &self.wmv2_intra[0];
3444 let ac_inter = &self.wmv2_inter[0];
3445
3446 for _ in 0..max_mb {
3447 if br.is_empty() {
3448 break;
3449 }
3450
3451 let cbpc_sym = match self.wmv2_cbpc.decode(&mut br) {
3452 Some(v) => v,
3453 None => break,
3454 };
3455 if cbpc_sym == -1 {
3456 score += 1;
3457 continue;
3458 }
3459 if cbpc_sym < 0 || cbpc_sym > 3 {
3460 break;
3461 }
3462
3463 let is_intra = match br.read_bit() {
3464 Some(b) => b,
3465 None => break,
3466 };
3467
3468 let cbpy_raw = match self.wmv2_cbpy.decode(&mut br) {
3469 Some(v) if v >= 0 && v <= 15 => v as u8,
3470 _ => break,
3471 };
3472
3473 let cbpy = if is_intra { cbpy_raw } else { cbpy_raw ^ 0x0F };
3474 let cbp: u8 = (cbpy << 2) | (cbpc_sym as u8 & 0x03);
3475
3476 if cbp != 0 {
3477 let vlc = if is_intra { ac_intra } else { ac_inter };
3478 let sym = match vlc.decode(&mut br) {
3479 Some(s) => s,
3480 None => break,
3481 };
3482 if sym == VLC_ESCAPE {
3483 let _ = decode_escape_coeff(&mut br, vlc);
3485 } else {
3486 let _ = br.read_bit();
3488 }
3489 }
3490
3491 score += 1;
3492 }
3493
3494 score
3495 }
3496
3497 #[inline(always)]
3500 fn wmv2_coded_block_pred(&self, mb_row: usize, mb_col: usize, blk: usize) -> u8 {
3501 let bw = (self.width_mb as usize) * 2;
3503 let bx = mb_col * 2 + (blk & 1);
3504 let by = mb_row * 2 + (blk >> 1);
3505 let idx = by * bw + bx;
3506 let a = if bx > 0 {
3507 self.wmv2_coded_block[idx - 1]
3508 } else {
3509 0
3510 };
3511 let b = if bx > 0 && by > 0 {
3512 self.wmv2_coded_block[idx - 1 - bw]
3513 } else {
3514 0
3515 };
3516 let c = if by > 0 {
3517 self.wmv2_coded_block[idx - bw]
3518 } else {
3519 0
3520 };
3521 if b == c {
3522 a
3523 } else {
3524 c
3525 }
3526 }
3527
3528 #[inline(always)]
3529 fn wmv2_coded_block_store(&mut self, mb_row: usize, mb_col: usize, blk: usize, v: u8) {
3530 let bw = (self.width_mb as usize) * 2;
3531 let bx = mb_col * 2 + (blk & 1);
3532 let by = mb_row * 2 + (blk >> 1);
3533 let idx = by * bw + bx;
3534 if idx < self.wmv2_coded_block.len() {
3535 self.wmv2_coded_block[idx] = v;
3536 }
3537 }
3538
3539 #[inline(always)]
3540 fn wmv2_decode_dc_diff(&self, br: &mut BitReader<'_>, is_chroma: bool) -> i32 {
3541 const DC_MAX: i32 = 119;
3543 let tbl = &self.wmv2_dc_vlc[self.wmv2_dc_table_index][if is_chroma { 1 } else { 0 }];
3544 let mut level = tbl.decode(br).unwrap_or(0);
3545 if level == DC_MAX {
3546 let v = br.read_bits(8).unwrap_or(0) as i32;
3547 let sign = br.read_bit().unwrap_or(false);
3548 return if sign { -v } else { v };
3549 }
3550 if level != 0 {
3551 let sign = br.read_bit().unwrap_or(false);
3552 if sign {
3553 level = -level;
3554 }
3555 }
3556 level
3557 }
3558
3559 #[inline(always)]
3560 fn wmv2_reset_picture_state(&mut self) {
3561 self.wmv2_esc3_level_length = 0;
3562 self.wmv2_esc3_run_length = 0;
3563 for v in self.wmv2_ac_val.iter_mut() {
3564 *v = [0i16; 16];
3565 }
3566 }
3567
3568 #[inline(always)]
3569 fn wmv2_ac_val_idx(&self, mb_row: usize, mb_col: usize, blk: usize) -> usize {
3570 let mb_w = self.width_mb as usize;
3571 (mb_row * mb_w + mb_col) * 6 + blk
3572 }
3573
3574 #[inline(always)]
3575 fn wmv2_get_ac_val(&self, mb_row: usize, mb_col: usize, blk: usize) -> [i16; 16] {
3576 let idx = self.wmv2_ac_val_idx(mb_row, mb_col, blk);
3577 if idx < self.wmv2_ac_val.len() {
3578 self.wmv2_ac_val[idx]
3579 } else {
3580 [0i16; 16]
3581 }
3582 }
3583
3584 #[inline(always)]
3585 fn wmv2_set_ac_val(&mut self, mb_row: usize, mb_col: usize, blk: usize, v: [i16; 16]) {
3586 let idx = self.wmv2_ac_val_idx(mb_row, mb_col, blk);
3587 if idx < self.wmv2_ac_val.len() {
3588 self.wmv2_ac_val[idx] = v;
3589 }
3590 }
3591
3592 #[inline(always)]
3593 fn wmv2_pred_ac(
3594 &mut self,
3595 mb_row: usize,
3596 mb_col: usize,
3597 blk: usize,
3598 dc_pred_dir: i32,
3599 ac_pred: bool,
3600 block: &mut [i16; 64],
3601 ) {
3602 let mut cur = self.wmv2_get_ac_val(mb_row, mb_col, blk);
3607
3608 if ac_pred {
3609 if dc_pred_dir == 0 {
3610 let (src_r, src_c, src_b) = match blk {
3612 1 => (mb_row, mb_col, 0),
3613 3 => (mb_row, mb_col, 2),
3614 0 => (mb_row, mb_col.saturating_sub(1), 1),
3615 2 => (mb_row, mb_col.saturating_sub(1), 3),
3616 4 | 5 => (mb_row, mb_col.saturating_sub(1), blk),
3617 _ => (mb_row, mb_col.saturating_sub(1), blk),
3618 };
3619 if (blk == 1 || blk == 3) || mb_col > 0 {
3620 let src = self.wmv2_get_ac_val(src_r, src_c, src_b);
3621 for i in 1..8usize {
3622 let idx = i << 3;
3623 block[idx] = block[idx].wrapping_add(src[i]);
3624 }
3625 }
3626 } else {
3627 let (src_r, src_c, src_b) = match blk {
3629 2 => (mb_row, mb_col, 0),
3630 3 => (mb_row, mb_col, 1),
3631 0 => (mb_row.saturating_sub(1), mb_col, 2),
3632 1 => (mb_row.saturating_sub(1), mb_col, 3),
3633 4 | 5 => (mb_row.saturating_sub(1), mb_col, blk),
3634 _ => (mb_row.saturating_sub(1), mb_col, blk),
3635 };
3636 if (blk == 2 || blk == 3) || mb_row > 0 {
3637 let src = self.wmv2_get_ac_val(src_r, src_c, src_b);
3638 for i in 1..8usize {
3639 block[i] = block[i].wrapping_add(src[8 + i]);
3640 }
3641 }
3642 }
3643 }
3644
3645 for i in 1..8usize {
3647 cur[i] = block[i << 3];
3648 }
3649 for i in 1..8usize {
3650 cur[8 + i] = block[i];
3651 }
3652 self.wmv2_set_ac_val(mb_row, mb_col, blk, cur);
3653 }
3654
3655 #[inline(always)]
3656 fn wmv2_unquantize_h263_intra(&self, block: &mut [i16; 64], qscale: i32, dc_scale: i32) {
3657 let qmul = qscale << 1;
3659 let qadd = (qscale - 1) | 1;
3660
3661 block[0] = ((block[0] as i32) * dc_scale) as i16;
3662 for i in 1..64usize {
3663 let mut level = block[i] as i32;
3664 if level != 0 {
3665 if level < 0 {
3666 level = level * qmul - qadd;
3667 } else {
3668 level = level * qmul + qadd;
3669 }
3670 block[i] = level as i16;
3671 }
3672 }
3673 }
3674
3675 fn wmv2_decode_block_intra_ref(
3676 &mut self,
3677 br: &mut BitReader<'_>,
3678 mb_row: usize,
3679 mb_col: usize,
3680 blk: usize,
3681 coded: bool,
3682 qscale: i32,
3683 ac_pred: bool,
3684 ) -> Result<[i16; 64]> {
3685 let is_luma = blk < 4;
3686 let dc_scale = wmv2_dc_scale(qscale, is_luma);
3687
3688 let diff = self.wmv2_decode_dc_diff(br, !is_luma);
3690 let (pred_level, dir) = self.wmv2_dc_pred.predict(mb_row, mb_col, blk, dc_scale);
3691 let level = pred_level + diff;
3692 self.wmv2_dc_pred
3693 .store(mb_row, mb_col, blk, level * dc_scale);
3694
3695 let mut block = [0i16; 64];
3696 block[0] = level as i16;
3697
3698 let rl = if is_luma {
3700 &self.wmv2_rl[(self.wmv2_rl_table_index as usize).min(2)]
3701 } else {
3702 &self.wmv2_rl[3 + (self.wmv2_rl_chroma_table_index as usize).min(2)]
3703 };
3704
3705 let scan = if ac_pred {
3707 if dir == 0 {
3708 &FF_WMV1_SCANTABLE[3] } else {
3710 &FF_WMV1_SCANTABLE[2] }
3712 } else {
3713 &FF_WMV1_SCANTABLE[1] };
3715
3716 let mut i: i32 = 0;
3717 let qmul: i32 = 1;
3718 let run_diff: i32 = 1; if coded {
3721 loop {
3722 let (mut level_uq, mut run) = rl
3723 .decode_sym(br, 0)
3724 .ok_or_else(|| DecoderError::InvalidData("WMV2: tcoeff VLC underrun".into()))?;
3725
3726 if level_uq == 0 {
3727 let b0 = br.peek_bits(1).unwrap_or(0);
3729 if b0 == 1 {
3730 br.skip_bits(1);
3732 let (lvl2, run2) = rl.decode_sym(br, 0).ok_or_else(|| {
3733 DecoderError::InvalidData("WMV2: escape1 VLC underrun".into())
3734 })?;
3735 level_uq = lvl2;
3736 run = run2;
3737 i += run;
3738 let last = ((run >> 7) & 1) as usize;
3739 let base_run = ((run - 1) & 63) as usize;
3740 level_uq += rl.max_level_for(last, base_run) * qmul;
3741 let sign = br.read_bit().unwrap_or(false);
3742 if sign {
3743 level_uq = -level_uq;
3744 }
3745 } else {
3746 let b1 = br.peek_bits(2).unwrap_or(0) & 1;
3747 if b1 == 1 {
3748 br.skip_bits(2);
3750 let (lvl2, run2) = rl.decode_sym(br, 0).ok_or_else(|| {
3751 DecoderError::InvalidData("WMV2: escape2 VLC underrun".into())
3752 })?;
3753 level_uq = lvl2;
3754 run = run2;
3755 let last = ((run >> 7) & 1) as usize;
3756 let base_level = (level_uq / qmul).abs() as usize;
3757 i += run + rl.max_run_for(last, base_level) + run_diff;
3758 let sign = br.read_bit().unwrap_or(false);
3759 if sign {
3760 level_uq = -level_uq;
3761 }
3762 } else {
3763 br.skip_bits(2);
3765 let last = br.read_bit().unwrap_or(false);
3766 if self.wmv2_esc3_level_length == 0 {
3767 let ll: u8 = if qscale < 8 {
3769 let mut x = br.read_bits(3).unwrap_or(0) as u8;
3770 if x == 0 {
3771 x = 8 + br.read_bits(1).unwrap_or(0) as u8;
3772 }
3773 x
3774 } else {
3775 let mut x: u8 = 2;
3776 while x < 8 && br.peek_bits(1).unwrap_or(1) == 0 {
3777 br.skip_bits(1);
3778 x += 1;
3779 }
3780 if x < 8 {
3781 br.skip_bits(1);
3782 }
3783 x
3784 };
3785 self.wmv2_esc3_level_length = ll;
3786 self.wmv2_esc3_run_length =
3787 (br.read_bits(2).unwrap_or(0) as u8) + 3;
3788 }
3789 let run_abs =
3790 br.read_bits(self.wmv2_esc3_run_length).unwrap_or(0) as i32;
3791 let sign = br.read_bit().unwrap_or(false);
3792 let mut lvl_abs =
3793 br.read_bits(self.wmv2_esc3_level_length).unwrap_or(0) as i32;
3794 if sign {
3795 lvl_abs = -lvl_abs;
3796 }
3797 level_uq = lvl_abs;
3798 i += run_abs + 1;
3799 if last {
3800 i += 192;
3801 }
3802 }
3803 }
3804 } else {
3805 i += run;
3806 let sign = br.read_bit().unwrap_or(false);
3807 if sign {
3808 level_uq = -level_uq;
3809 }
3810 }
3811
3812 if i > 62 {
3813 i -= 192;
3814 if (i & !63) != 0 {
3815 i = 63;
3816 }
3817 if i < 0 {
3818 return Err(DecoderError::InvalidData(
3819 "WMV2: negative coeff index (bitstream damaged)".into(),
3820 ));
3821 }
3822 let pos = scan[i as usize] as usize;
3823 if pos < 64 {
3824 block[pos] = level_uq as i16;
3825 }
3826 break;
3827 }
3828
3829 if i < 0 {
3830 return Err(DecoderError::InvalidData(
3831 "WMV2: negative coeff index (bitstream damaged)".into(),
3832 ));
3833 }
3834 let pos = scan[i as usize] as usize;
3835 if pos < 64 {
3836 block[pos] = level_uq as i16;
3837 }
3838 }
3839 }
3840
3841 self.wmv2_pred_ac(mb_row, mb_col, blk, dir, ac_pred, &mut block);
3843
3844 self.wmv2_unquantize_h263_intra(&mut block, qscale, dc_scale);
3846
3847 Ok(block)
3848 }
3849 fn wmv2_decode_block_inter_ref(
3850 &mut self,
3851 br: &mut BitReader<'_>,
3852 blk: usize,
3853 coded: bool,
3854 qscale: i32,
3855 scan: &[usize; 64],
3856 ) -> Result<[i16; 64]> {
3857 let mut block = [0i16; 64];
3858 if !coded {
3859 return Ok(block);
3860 }
3861
3862 let rl = &self.wmv2_rl[3 + (self.wmv2_rl_table_index as usize).min(2)];
3863
3864 let qmul = qscale << 1;
3865 let qadd = (qscale - 1) | 1;
3866 let run_diff: i32 = 1; let mut i: i32 = -1;
3869
3870 loop {
3871 let (mut level_uq, mut run) = rl.decode_sym(br, qscale).ok_or_else(|| {
3872 DecoderError::InvalidData("WMV2: inter tcoeff VLC underrun".into())
3873 })?;
3874
3875 if level_uq == 0 {
3876 let b0 = br.peek_bits(1).unwrap_or(0);
3878 if b0 == 1 {
3879 br.skip_bits(1);
3881 let (lvl2, run2) = rl.decode_sym(br, qscale).ok_or_else(|| {
3882 DecoderError::InvalidData("WMV2: inter escape1 VLC underrun".into())
3883 })?;
3884 level_uq = lvl2;
3885 run = run2;
3886 i += run;
3887 let last = ((run >> 7) & 1) as usize;
3888 let base_run = ((run - 1) & 63) as usize;
3889 level_uq += rl.max_level_for(last, base_run) * qmul;
3890 let sign = br.read_bit().unwrap_or(false);
3891 if sign {
3892 level_uq = -level_uq;
3893 }
3894 } else {
3895 let b1 = br.peek_bits(2).unwrap_or(0) & 1;
3896 if b1 == 1 {
3897 br.skip_bits(2);
3899 let (lvl2, run2) = rl.decode_sym(br, qscale).ok_or_else(|| {
3900 DecoderError::InvalidData("WMV2: inter escape2 VLC underrun".into())
3901 })?;
3902 level_uq = lvl2;
3903 run = run2;
3904 let last = ((run >> 7) & 1) as usize;
3905 let base_level = (level_uq / qmul).abs() as usize;
3906 i += run + rl.max_run_for(last, base_level) + run_diff;
3907 let sign = br.read_bit().unwrap_or(false);
3908 if sign {
3909 level_uq = -level_uq;
3910 }
3911 } else {
3912 br.skip_bits(2);
3914 let last = br.read_bit().unwrap_or(false);
3915 if self.wmv2_esc3_level_length == 0 {
3916 let ll: u8 = if qscale < 8 {
3917 let mut x = br.read_bits(3).unwrap_or(0) as u8;
3918 if x == 0 {
3919 x = 8 + br.read_bits(1).unwrap_or(0) as u8;
3920 }
3921 x
3922 } else {
3923 let mut x: u8 = 2;
3924 while x < 8 && br.peek_bits(1).unwrap_or(1) == 0 {
3925 br.skip_bits(1);
3926 x += 1;
3927 }
3928 if x < 8 {
3929 br.skip_bits(1);
3930 }
3931 x
3932 };
3933 self.wmv2_esc3_level_length = ll;
3934 self.wmv2_esc3_run_length = (br.read_bits(2).unwrap_or(0) as u8) + 3;
3935 }
3936 let run_abs = br.read_bits(self.wmv2_esc3_run_length).unwrap_or(0) as i32;
3937 let sign = br.read_bit().unwrap_or(false);
3938 let mut lvl_abs =
3939 br.read_bits(self.wmv2_esc3_level_length).unwrap_or(0) as i32;
3940 if sign {
3941 lvl_abs = -lvl_abs;
3942 }
3943 if lvl_abs > 0 {
3944 level_uq = lvl_abs * qmul + qadd;
3945 } else {
3946 level_uq = lvl_abs * qmul - qadd;
3947 }
3948 i += run_abs + 1;
3949 if last {
3950 i += 192;
3951 }
3952 }
3953 }
3954 } else {
3955 i += run;
3956 let sign = br.read_bit().unwrap_or(false);
3957 if sign {
3958 level_uq = -level_uq;
3959 }
3960 }
3961
3962 if i > 62 {
3963 i -= 192;
3964 if (i & !63) != 0 {
3965 i = 63;
3966 }
3967 if i < 0 {
3968 return Err(DecoderError::InvalidData(
3969 "WMV2: negative coeff index (bitstream damaged)".into(),
3970 ));
3971 }
3972 let pos = scan[i as usize] as usize;
3973 if pos < 64 {
3974 block[pos] = level_uq as i16;
3975 }
3976 break;
3977 }
3978
3979 if i < 0 {
3980 return Err(DecoderError::InvalidData(
3981 "WMV2: negative coeff index (bitstream damaged)".into(),
3982 ));
3983 }
3984 let pos = scan[i as usize] as usize;
3985 if pos < 64 {
3986 block[pos] = level_uq as i16;
3987 }
3988 }
3989
3990 let _ = blk;
3991 Ok(block)
3992 }
3993 fn wmv2_parse_mb_skip(
3994 &mut self,
3995 br: &mut BitReader<'_>,
3996 mb_w: usize,
3997 mb_h: usize,
3998 ) -> Result<()> {
3999 let skip_type = br
4001 .read_bits(2)
4002 .ok_or_else(|| DecoderError::InvalidData("WMV2: missing skip_type".into()))?
4003 as u8;
4004 self.wmv2_skip_type = skip_type;
4005 if self.wmv2_mb_skip.len() != mb_w * mb_h {
4006 self.wmv2_mb_skip.resize(mb_w * mb_h, false);
4007 }
4008 for v in self.wmv2_mb_skip.iter_mut() {
4009 *v = false;
4010 }
4011
4012 match skip_type {
4013 0 => {
4014 }
4016 1 => {
4017 if br.bits_left() < (mb_w * mb_h) as isize {
4019 return Err(DecoderError::InvalidData("WMV2: skip map truncated".into()));
4020 }
4021 for y in 0..mb_h {
4022 for x in 0..mb_w {
4023 let b = br.read_bit().unwrap_or(false);
4024 self.wmv2_mb_skip[y * mb_w + x] = b;
4025 }
4026 }
4027 }
4028 2 => {
4029 for y in 0..mb_h {
4031 let all = br.read_bit().ok_or_else(|| {
4032 DecoderError::InvalidData("WMV2: skip row flag missing".into())
4033 })?;
4034 if all {
4035 for x in 0..mb_w {
4036 self.wmv2_mb_skip[y * mb_w + x] = true;
4037 }
4038 } else {
4039 for x in 0..mb_w {
4040 let b = br.read_bit().unwrap_or(false);
4041 self.wmv2_mb_skip[y * mb_w + x] = b;
4042 }
4043 }
4044 }
4045 }
4046 3 => {
4047 for x in 0..mb_w {
4049 let all = br.read_bit().ok_or_else(|| {
4050 DecoderError::InvalidData("WMV2: skip col flag missing".into())
4051 })?;
4052 if all {
4053 for y in 0..mb_h {
4054 self.wmv2_mb_skip[y * mb_w + x] = true;
4055 }
4056 } else {
4057 for y in 0..mb_h {
4058 let b = br.read_bit().unwrap_or(false);
4059 self.wmv2_mb_skip[y * mb_w + x] = b;
4060 }
4061 }
4062 }
4063 }
4064 _ => {}
4065 }
4066
4067 let coded = self.wmv2_mb_skip.iter().filter(|s| !**s).count();
4069 if coded as isize > br.bits_left() {
4070 return Err(DecoderError::InvalidData(
4071 "WMV2: coded MB count exceeds remaining bits".into(),
4072 ));
4073 }
4074 Ok(())
4075 }
4076
4077 #[inline(always)]
4078 fn wmv2_motion_get(&self, mb_row: isize, mb_col: isize) -> (i32, i32) {
4079 if mb_row < 0 || mb_col < 0 {
4080 return (0, 0);
4081 }
4082 let mb_w = self.width_mb as isize;
4083 let mb_h = self.height_mb as isize;
4084 if mb_row >= mb_h || mb_col >= mb_w {
4085 return (0, 0);
4086 }
4087 let idx = (mb_row as usize) * (mb_w as usize) + (mb_col as usize);
4088 if idx < self.wmv2_motion.len() {
4089 self.wmv2_motion[idx]
4090 } else {
4091 (0, 0)
4092 }
4093 }
4094
4095 #[inline(always)]
4096 fn wmv2_motion_set(&mut self, mb_row: usize, mb_col: usize, mv: (i32, i32)) {
4097 let mb_w = self.width_mb as usize;
4098 let idx = mb_row * mb_w + mb_col;
4099 if self.wmv2_motion.len() != mb_w * (self.height_mb as usize) {
4100 self.wmv2_motion
4101 .resize(mb_w * (self.height_mb as usize), (0, 0));
4102 }
4103 if idx < self.wmv2_motion.len() {
4104 self.wmv2_motion[idx] = mv;
4105 }
4106 }
4107
4108 #[inline(always)]
4109 fn wmv2_pred_motion(
4110 &self,
4111 br: &mut BitReader<'_>,
4112 mb_row: usize,
4113 mb_col: usize,
4114 first_slice_line: bool,
4115 ) -> (i32, i32) {
4116 let a = self.wmv2_motion_get(mb_row as isize, mb_col as isize - 1);
4118 let b = self.wmv2_motion_get(mb_row as isize - 1, mb_col as isize);
4119 let c = self.wmv2_motion_get(mb_row as isize - 1, mb_col as isize + 1);
4120
4121 let diff =
4122 if mb_col != 0 && !first_slice_line && !self.wmv2_mspel && self.wmv2_top_left_mv_flag {
4123 let dx = (a.0 - b.0).abs();
4124 let dy = (a.1 - b.1).abs();
4125 dx.max(dy)
4126 } else {
4127 0
4128 };
4129
4130 let t = if diff >= 8 {
4131 if br.read_bit().unwrap_or(false) {
4132 1
4133 } else {
4134 0
4135 }
4136 } else {
4137 2
4138 };
4139
4140 match t {
4141 0 => a,
4142 1 => b,
4143 _ => {
4144 if first_slice_line {
4145 a
4146 } else {
4147 (mid_pred(a.0, b.0, c.0), mid_pred(a.1, b.1, c.1))
4148 }
4149 }
4150 }
4151 }
4152
4153 #[inline(always)]
4154 fn wmv2_decode_motion_ref(&self, br: &mut BitReader<'_>, pred: (i32, i32)) -> (i32, i32) {
4155 let tbl = &self.wmv2_mv_vlc[self.wmv2_mv_table_index.min(1)];
4157 let sym = tbl.decode(br).unwrap_or(0) as u16;
4158 let (mut mx, mut my) = if sym != 0 {
4159 ((sym >> 8) as i32, (sym & 0xff) as i32)
4160 } else {
4161 (
4163 br.read_bits(6).unwrap_or(0) as i32,
4164 br.read_bits(6).unwrap_or(0) as i32,
4165 )
4166 };
4167
4168 mx += pred.0 - 32;
4169 my += pred.1 - 32;
4170 if mx <= -64 {
4172 mx += 64;
4173 } else if mx >= 64 {
4174 mx -= 64;
4175 }
4176 if my <= -64 {
4177 my += 64;
4178 } else if my >= 64 {
4179 my -= 64;
4180 }
4181 (mx, my)
4182 }
4183
4184 fn wmv2_decode_intra(
4187 &mut self,
4188 payload: &[u8],
4189 hdr: &Wmv2FrameHeader,
4190 frame: &mut YuvFrame,
4191 ) -> Result<()> {
4192 let mut br = BitReader::new_at(payload, hdr.header_bits);
4194
4195 self.wmv2_j_type = if self.wmv2_j_type_bit {
4198 br.read_bit().unwrap_or(false)
4199 } else {
4200 false
4201 };
4202 if self.wmv2_j_type {
4203 return Ok(());
4205 }
4206
4207 self.wmv2_per_mb_rl_table = if self.wmv2_per_mb_rl_bit {
4208 br.read_bit().unwrap_or(false)
4209 } else {
4210 false
4211 };
4212 if !self.wmv2_per_mb_rl_table {
4213 self.wmv2_rl_chroma_table_index = decode012(&mut br);
4214 self.wmv2_rl_table_index = decode012(&mut br);
4215 }
4216 self.wmv2_dc_table_index = br.read_bit().unwrap_or(false) as usize;
4217
4218 let mb_w = self.width_mb as usize;
4219 let mb_h = self.height_mb as usize;
4220
4221 self.wmv2_dc_pred = Wmv2DcPredBuffer::new(mb_w, mb_h);
4223 for v in self.wmv2_coded_block.iter_mut() {
4224 *v = 0;
4225 }
4226
4227 self.wmv2_reset_picture_state();
4228
4229 let qscale = hdr.pquant as i32;
4230 for mb_row in 0..mb_h {
4234 for mb_col in 0..mb_w {
4235 if br.is_empty() {
4236 break;
4237 }
4238
4239 let code = self.wmv2_mb_i_vlc.decode(&mut br).unwrap_or(0) as u32;
4241
4242 let mut cbp: u8 = 0;
4244 for i in 0..6usize {
4245 let mut val = ((code >> (5 - i)) & 1) as u8;
4246 if i < 4 {
4247 let pred = self.wmv2_coded_block_pred(mb_row, mb_col, i);
4248 val ^= pred;
4249 self.wmv2_coded_block_store(mb_row, mb_col, i, val);
4250 }
4251 cbp |= val << (5 - i);
4252 }
4253
4254 let ac_pred = br.read_bit().unwrap_or(false);
4256
4257 if self.wmv2_per_mb_rl_table && cbp != 0 {
4259 let rl_idx = decode012(&mut br);
4260 self.wmv2_rl_table_index = rl_idx;
4261 self.wmv2_rl_chroma_table_index = rl_idx;
4262 }
4263
4264 for blk in 0..6usize {
4265 let coded = ((cbp >> (5 - blk)) & 1) != 0;
4266 let mut block = self.wmv2_decode_block_intra_ref(
4267 &mut br, mb_row, mb_col, blk, coded, qscale, ac_pred,
4268 )?;
4269
4270 let (is_luma, bx, by, stride, _ph) =
4271 block_coords(mb_row as u32, mb_col as u32, blk, frame.width, frame.height);
4272 let plane: &mut Vec<u8> = if is_luma {
4273 &mut frame.y
4274 } else if blk == 4 {
4275 &mut frame.cb
4276 } else {
4277 &mut frame.cr
4278 };
4279 let dst_off = by * stride + bx;
4280 wmv2dsp::wmv2_idct_put(plane, dst_off, stride, &mut block);
4281 }
4282 }
4283 }
4284
4285 self.wmv2_ref = Some(frame.clone());
4286 Ok(())
4287 }
4288 fn wmv2_decode_p(
4291 &mut self,
4292 payload: &[u8],
4293 hdr: &Wmv2FrameHeader,
4294 frame: &mut YuvFrame,
4295 ) -> Result<()> {
4296 let mut br = BitReader::new_at(payload, hdr.header_bits);
4298
4299 let mb_w = self.width_mb as usize;
4300 let mb_h = self.height_mb as usize;
4301 let qscale = hdr.pquant as i32;
4302
4303 self.wmv2_j_type = false;
4305 self.wmv2_parse_mb_skip(&mut br, mb_w, mb_h)?;
4306 let cbp_index = decode012(&mut br);
4307 self.wmv2_cbp_table_index = wmv2_get_cbp_table_index(qscale, cbp_index);
4308
4309 self.wmv2_mspel = if self.wmv2_mspel_bit {
4310 br.read_bit().unwrap_or(false)
4311 } else {
4312 false
4313 };
4314
4315 if self.wmv2_abt_flag {
4316 self.wmv2_per_mb_abt = br.read_bit().unwrap_or(false) ^ true;
4317 if !self.wmv2_per_mb_abt {
4318 self.wmv2_abt_type = decode012(&mut br);
4319 }
4320 } else {
4321 self.wmv2_per_mb_abt = false;
4322 self.wmv2_abt_type = 0;
4323 }
4324
4325 self.wmv2_per_mb_rl_table = if self.wmv2_per_mb_rl_bit {
4326 br.read_bit().unwrap_or(false)
4327 } else {
4328 false
4329 };
4330 if !self.wmv2_per_mb_rl_table {
4331 self.wmv2_rl_table_index = decode012(&mut br);
4332 self.wmv2_rl_chroma_table_index = self.wmv2_rl_table_index;
4333 }
4334 if br.bits_left() < 2 {
4335 return Err(DecoderError::InvalidData(
4336 "WMV2: truncated secondary header".into(),
4337 ));
4338 }
4339 self.wmv2_dc_table_index = br.read_bit().unwrap_or(false) as usize;
4340 self.wmv2_mv_table_index = br.read_bit().unwrap_or(false) as usize;
4341
4342 self.wmv2_dc_pred = Wmv2DcPredBuffer::new(mb_w, mb_h);
4344 if self.wmv2_motion.len() != mb_w * mb_h {
4345 self.wmv2_motion.resize(mb_w * mb_h, (0, 0));
4346 }
4347 for v in self.wmv2_motion.iter_mut() {
4348 *v = (0, 0);
4349 }
4350
4351 self.wmv2_reset_picture_state();
4352
4353 let reference = match &self.wmv2_ref {
4354 Some(r) => r.clone(),
4355 None => YuvFrame::new(frame.width, frame.height),
4356 };
4357
4358 for mb_row in 0..mb_h {
4359 let first_slice_line =
4360 self.wmv2_slice_height != 0 && (mb_row % self.wmv2_slice_height == 0);
4361 for mb_col in 0..mb_w {
4362 if br.bits_left() <= 0 {
4363 break;
4364 }
4365 let mi = mb_row * mb_w + mb_col;
4366 if mi < self.wmv2_mb_skip.len() && self.wmv2_mb_skip[mi] {
4367 if self.wmv2_mspel {
4368 wmv2_mspel_motion_mb(frame, &reference, mb_row, mb_col, 0, 0, 0);
4369 } else {
4370 motion_compensate_mb(frame, &reference, mb_row, mb_col, 0, 0);
4371 }
4372 self.wmv2_motion_set(mb_row, mb_col, (0, 0));
4373 continue;
4374 }
4375
4376 let code = self.wmv2_mb_non_intra_vlc[self.wmv2_cbp_table_index.min(3)]
4377 .decode(&mut br)
4378 .ok_or_else(|| {
4379 DecoderError::InvalidData("WMV2: MB header VLC underrun".into())
4380 })? as i32;
4381
4382 let mb_intra = (code & 0x40) == 0;
4383 let cbp = (code & 0x3f) as u8;
4384
4385 if !mb_intra {
4386 let pred = self.wmv2_pred_motion(&mut br, mb_row, mb_col, first_slice_line);
4387
4388 if cbp != 0 {
4389 if self.wmv2_per_mb_rl_table {
4390 self.wmv2_rl_table_index = decode012(&mut br);
4391 self.wmv2_rl_chroma_table_index = self.wmv2_rl_table_index;
4392 }
4393 }
4394
4395 let mut per_block_abt = false;
4396 let mut abt_type = self.wmv2_abt_type;
4397 if cbp != 0 && self.wmv2_abt_flag && self.wmv2_per_mb_abt {
4398 per_block_abt = br.read_bit().unwrap_or(false);
4399 if !per_block_abt {
4400 abt_type = decode012(&mut br);
4401 }
4402 }
4403
4404 let (mx, my) = self.wmv2_decode_motion_ref(&mut br, pred);
4405 self.wmv2_hshift = if (((mx | my) & 1) != 0) && self.wmv2_mspel {
4406 br.read_bit().unwrap_or(false) as u8
4407 } else {
4408 0
4409 };
4410 self.wmv2_motion_set(mb_row, mb_col, (mx, my));
4411
4412 if self.wmv2_mspel {
4413 wmv2_mspel_motion_mb(
4414 frame,
4415 &reference,
4416 mb_row,
4417 mb_col,
4418 mx,
4419 my,
4420 self.wmv2_hshift,
4421 );
4422 } else {
4423 motion_compensate_mb(frame, &reference, mb_row, mb_col, mx, my);
4424 }
4425
4426 for blk in 0..6usize {
4427 if (cbp >> (5 - blk)) & 1 == 0 {
4428 continue;
4429 }
4430
4431 let mut cur_abt = abt_type;
4432 if per_block_abt {
4433 cur_abt = decode012(&mut br);
4434 }
4435
4436 if cur_abt == 0 {
4439 let scan = &FF_WMV1_SCANTABLE[0];
4440
4441 let mut block =
4442 self.wmv2_decode_block_inter_ref(&mut br, blk, true, qscale, scan)?;
4443
4444 let (is_luma, bx, by, stride, _ph) = block_coords(
4445 mb_row as u32,
4446 mb_col as u32,
4447 blk,
4448 frame.width,
4449 frame.height,
4450 );
4451
4452 let plane: &mut Vec<u8> = if is_luma {
4453 &mut frame.y
4454 } else if blk == 4 {
4455 &mut frame.cb
4456 } else {
4457 &mut frame.cr
4458 };
4459
4460 let dst_off = by * stride + bx;
4461
4462 wmv2dsp::wmv2_idct_add(plane, dst_off, stride, &mut block);
4463 } else {
4464 const SUB_CBP_TABLE: [u8; 3] = [2, 3, 1];
4465
4466 let scantable = if cur_abt == 1 {
4467 &FF_WMV2_SCANTABLE_A
4468 } else {
4469 &FF_WMV2_SCANTABLE_B
4470 };
4471
4472 let sub_cbp = SUB_CBP_TABLE[decode012(&mut br) as usize];
4473
4474 let mut block1 = [0i16; 64];
4475
4476 let mut block2 = [0i16; 64];
4477
4478 if (sub_cbp & 1) != 0 {
4479 block1 = self.wmv2_decode_block_inter_ref(
4480 &mut br, blk, true, qscale, scantable,
4481 )?;
4482 }
4483
4484 if (sub_cbp & 2) != 0 {
4485 block2 = self.wmv2_decode_block_inter_ref(
4486 &mut br, blk, true, qscale, scantable,
4487 )?;
4488 }
4489
4490 let (is_luma, bx, by, stride, _ph) = block_coords(
4491 mb_row as u32,
4492 mb_col as u32,
4493 blk,
4494 frame.width,
4495 frame.height,
4496 );
4497
4498 let plane: &mut Vec<u8> = if is_luma {
4499 &mut frame.y
4500 } else if blk == 4 {
4501 &mut frame.cb
4502 } else {
4503 &mut frame.cr
4504 };
4505
4506 let dst_off = by * stride + bx;
4507
4508 match cur_abt {
4509 1 => {
4510 ffidct::ff_simple_idct84_add(
4513 plane,
4514 dst_off,
4515 stride,
4516 &mut block1,
4517 );
4518
4519 ffidct::ff_simple_idct84_add(
4520 plane,
4521 dst_off + 4 * stride,
4522 stride,
4523 &mut block2,
4524 );
4525 }
4526
4527 2 => {
4528 ffidct::ff_simple_idct48_add(
4531 plane,
4532 dst_off,
4533 stride,
4534 &mut block1,
4535 );
4536
4537 ffidct::ff_simple_idct48_add(
4538 plane,
4539 dst_off + 4,
4540 stride,
4541 &mut block2,
4542 );
4543 }
4544
4545 _ => {}
4546 }
4547 }
4548 }
4549 } else {
4550 let ac_pred = br.read_bit().unwrap_or(false);
4552 if self.wmv2_per_mb_rl_table && cbp != 0 {
4553 let rl_idx = decode012(&mut br);
4554 self.wmv2_rl_table_index = rl_idx;
4555 self.wmv2_rl_chroma_table_index = rl_idx;
4556 }
4557
4558 for blk in 0..6usize {
4559 let coded = ((cbp >> (5 - blk)) & 1) != 0;
4560 let mut block = self.wmv2_decode_block_intra_ref(
4561 &mut br, mb_row, mb_col, blk, coded, qscale, ac_pred,
4562 )?;
4563
4564 let (is_luma, bx, by, stride, _ph) = block_coords(
4565 mb_row as u32,
4566 mb_col as u32,
4567 blk,
4568 frame.width,
4569 frame.height,
4570 );
4571 let plane: &mut Vec<u8> = if is_luma {
4572 &mut frame.y
4573 } else if blk == 4 {
4574 &mut frame.cb
4575 } else {
4576 &mut frame.cr
4577 };
4578 let dst_off = by * stride + bx;
4579 wmv2dsp::wmv2_idct_put(plane, dst_off, stride, &mut block);
4580 }
4581 self.wmv2_motion_set(mb_row, mb_col, (0, 0));
4582 }
4583 }
4584 }
4585
4586 self.wmv2_ref = Some(frame.clone());
4587 Ok(())
4588 }
4589}
4590
4591fn wmv2_decode_ac_block(
4598 br: &mut BitReader<'_>,
4599 ac_vlc: &VlcTable,
4600 pquant: i32,
4601 coeff: &mut [i32; 64],
4602 is_intra: bool,
4603) {
4604 let scan = &ZIGZAG;
4607 let mut idx = if is_intra { 1usize } else { 0 };
4608
4609 loop {
4610 let sym = match ac_vlc.decode(br) {
4611 Some(s) => s,
4612 None => break,
4613 };
4614
4615 let (run, signed_level, last) = if sym == VLC_ESCAPE {
4616 decode_escape_coeff(br, ac_vlc)
4621 } else {
4622 let (r, l, last) = unpack_rl(sym);
4623 let sign = br.read_bit().unwrap_or(false);
4624 (r, if sign { -(l as i32) } else { l as i32 }, last)
4625 };
4626
4627 idx = idx.saturating_add(run as usize);
4628 if idx >= 64 {
4629 break;
4630 }
4631
4632 let q = iquant_uniform(signed_level, pquant, false);
4634 coeff[scan[idx]] = q;
4635
4636 idx += 1;
4637 if last || br.is_empty() {
4638 break;
4639 }
4640 }
4641}
4642
4643fn wmv2_read_mv(
4648 br: &mut BitReader<'_>,
4649 mv_pred: &MvPredictor,
4650 mb_row: usize,
4651 mb_col: usize,
4652 mv_range: i32,
4653) -> (i32, i32) {
4654 let (px, py) = mv_pred.predict(mb_row, mb_col);
4655 let dx = wmv2_read_mv_component(br, mv_range);
4656 let dy = wmv2_read_mv_component(br, mv_range);
4657 (px + dx, py + dy)
4658}
4659
4660fn wmv2_read_mv_component(br: &mut BitReader<'_>, mv_range: i32) -> i32 {
4663 let mag = {
4669 let mut m = 0i32;
4670 loop {
4671 if br.read_bit().unwrap_or(true) {
4672 break;
4673 }
4674 m += 1;
4675 if m >= mv_range {
4676 break;
4677 }
4678 }
4679 m
4680 };
4681 if mag == 0 {
4682 return 0;
4683 }
4684 let sign = br.read_bit().unwrap_or(false);
4685 if sign {
4686 -mag
4687 } else {
4688 mag
4689 }
4690}