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, MvMode, PictureHeader, Profile, SequenceHeader};
24use crate::vc1_tables::{
25 TT_4X4, TT_4X8, TT_4X8_LEFT, TT_4X8_RIGHT, TT_8X4, TT_8X4_BOTTOM, TT_8X4_TOP, TT_8X8,
26 TTBLK_TO_TT, VC1_ZZ_4X4, VC1_ZZ_4X8, VC1_ZZ_8X4, Vc1AcTable, ac_tables, cbpcy_vlcs,
27 mvdata_vlcs, subblkpat_vlcs, ttblk_vlcs, ttmb_vlcs,
28};
29use crate::vlc::{
30 SCAN_INTRA, SCAN_VERT, VLC_ESCAPE, VlcTable, ZIGZAG, unpack_rl, wmv2_cbpc_p_vlc, wmv2_cbpy_vlc,
31 wmv2_tcoef_inter_vlc, wmv2_tcoef_intra_vlc,
32};
33use crate::vlc_tree::VlcTree;
34use crate::wmv2::{Wmv2FrameHeader, Wmv2FrameType, Wmv2Params};
35
36#[derive(Clone, Debug)]
39pub struct YuvFrame {
40 pub width: u32,
41 pub height: u32,
42 pub y: Vec<u8>,
43 pub cb: Vec<u8>,
44 pub cr: Vec<u8>,
45}
46
47impl YuvFrame {
48 pub fn new(width: u32, height: u32) -> Self {
49 let y_sz = (width * height) as usize;
50 let uv_sz = y_sz / 4;
51 YuvFrame {
52 width,
53 height,
54 y: vec![16u8; y_sz],
55 cb: vec![128u8; uv_sz],
56 cr: vec![128u8; uv_sz],
57 }
58 }
59
60 pub fn to_planar_u8(&self) -> Vec<u8> {
61 let mut out = Vec::with_capacity(self.y.len() + self.cb.len() + self.cr.len());
62 out.extend_from_slice(&self.y);
63 out.extend_from_slice(&self.cb);
64 out.extend_from_slice(&self.cr);
65 out
66 }
67
68 pub fn clear(&mut self) {
69 self.y.fill(16);
70 self.cb.fill(128);
71 self.cr.fill(128);
72 }
73}
74
75pub fn idct8x8(block: &mut [i32; 64]) {
81 let src = *block;
82 let mut temp = [0i32; 64];
83 for i in 0..8 {
84 let t1 = 12 * (src[i] + src[i + 32]) + 4;
85 let t2 = 12 * (src[i] - src[i + 32]) + 4;
86 let t3 = 16 * src[i + 16] + 6 * src[i + 48];
87 let t4 = 6 * src[i + 16] - 16 * src[i + 48];
88 let t5 = t1 + t3;
89 let t6 = t2 + t4;
90 let t7 = t2 - t4;
91 let t8 = t1 - t3;
92 let o1 = 16 * src[i + 8] + 15 * src[i + 24] + 9 * src[i + 40] + 4 * src[i + 56];
93 let o2 = 15 * src[i + 8] - 4 * src[i + 24] - 16 * src[i + 40] - 9 * src[i + 56];
94 let o3 = 9 * src[i + 8] - 16 * src[i + 24] + 4 * src[i + 40] + 15 * src[i + 56];
95 let o4 = 4 * src[i + 8] - 9 * src[i + 24] + 15 * src[i + 40] - 16 * src[i + 56];
96 let d = i * 8;
97 temp[d] = (t5 + o1) >> 3;
98 temp[d + 1] = (t6 + o2) >> 3;
99 temp[d + 2] = (t7 + o3) >> 3;
100 temp[d + 3] = (t8 + o4) >> 3;
101 temp[d + 4] = (t8 - o4) >> 3;
102 temp[d + 5] = (t7 - o3) >> 3;
103 temp[d + 6] = (t6 - o2) >> 3;
104 temp[d + 7] = (t5 - o1) >> 3;
105 }
106 for i in 0..8 {
107 let t1 = 12 * (temp[i] + temp[i + 32]) + 64;
108 let t2 = 12 * (temp[i] - temp[i + 32]) + 64;
109 let t3 = 16 * temp[i + 16] + 6 * temp[i + 48];
110 let t4 = 6 * temp[i + 16] - 16 * temp[i + 48];
111 let t5 = t1 + t3;
112 let t6 = t2 + t4;
113 let t7 = t2 - t4;
114 let t8 = t1 - t3;
115 let o1 = 16 * temp[i + 8] + 15 * temp[i + 24] + 9 * temp[i + 40] + 4 * temp[i + 56];
116 let o2 = 15 * temp[i + 8] - 4 * temp[i + 24] - 16 * temp[i + 40] - 9 * temp[i + 56];
117 let o3 = 9 * temp[i + 8] - 16 * temp[i + 24] + 4 * temp[i + 40] + 15 * temp[i + 56];
118 let o4 = 4 * temp[i + 8] - 9 * temp[i + 24] + 15 * temp[i + 40] - 16 * temp[i + 56];
119 block[i] = (t5 + o1) >> 7;
120 block[i + 8] = (t6 + o2) >> 7;
121 block[i + 16] = (t7 + o3) >> 7;
122 block[i + 24] = (t8 + o4) >> 7;
123 block[i + 32] = (t8 - o4 + 1) >> 7;
124 block[i + 40] = (t7 - o3 + 1) >> 7;
125 block[i + 48] = (t6 - o2 + 1) >> 7;
126 block[i + 56] = (t5 - o1 + 1) >> 7;
127 }
128}
129
130fn inv_trans_8x4_part(block: &mut [i32; 64], row0: usize) {
131 let mut src = [0i32; 32];
132 for r in 0..4 {
133 for c in 0..8 {
134 src[r * 8 + c] = block[(row0 + r) * 8 + c];
135 }
136 }
137 for r in 0..4 {
138 let o = r * 8;
139 let t1 = 12 * (src[o] + src[o + 4]) + 4;
140 let t2 = 12 * (src[o] - src[o + 4]) + 4;
141 let t3 = 16 * src[o + 2] + 6 * src[o + 6];
142 let t4 = 6 * src[o + 2] - 16 * src[o + 6];
143 let t5 = t1 + t3;
144 let t6 = t2 + t4;
145 let t7 = t2 - t4;
146 let t8 = t1 - t3;
147 let a = 16 * src[o + 1] + 15 * src[o + 3] + 9 * src[o + 5] + 4 * src[o + 7];
148 let b = 15 * src[o + 1] - 4 * src[o + 3] - 16 * src[o + 5] - 9 * src[o + 7];
149 let c = 9 * src[o + 1] - 16 * src[o + 3] + 4 * src[o + 5] + 15 * src[o + 7];
150 let d = 4 * src[o + 1] - 9 * src[o + 3] + 15 * src[o + 5] - 16 * src[o + 7];
151 src[o] = (t5 + a) >> 3;
152 src[o + 1] = (t6 + b) >> 3;
153 src[o + 2] = (t7 + c) >> 3;
154 src[o + 3] = (t8 + d) >> 3;
155 src[o + 4] = (t8 - d) >> 3;
156 src[o + 5] = (t7 - c) >> 3;
157 src[o + 6] = (t6 - b) >> 3;
158 src[o + 7] = (t5 - a) >> 3;
159 }
160 for c in 0..8 {
161 let t1 = 17 * (src[c] + src[c + 16]) + 64;
162 let t2 = 17 * (src[c] - src[c + 16]) + 64;
163 let t3 = 22 * src[c + 8] + 10 * src[c + 24];
164 let t4 = 22 * src[c + 24] - 10 * src[c + 8];
165 block[row0 * 8 + c] = (t1 + t3) >> 7;
166 block[(row0 + 1) * 8 + c] = (t2 - t4) >> 7;
167 block[(row0 + 2) * 8 + c] = (t2 + t4) >> 7;
168 block[(row0 + 3) * 8 + c] = (t1 - t3) >> 7;
169 }
170}
171
172fn inv_trans_4x8_part(block: &mut [i32; 64], col0: usize) {
173 let mut src = [0i32; 32];
174 for r in 0..8 {
175 for c in 0..4 {
176 src[r * 4 + c] = block[r * 8 + col0 + c];
177 }
178 }
179 for r in 0..8 {
180 let o = r * 4;
181 let t1 = 17 * (src[o] + src[o + 2]) + 4;
182 let t2 = 17 * (src[o] - src[o + 2]) + 4;
183 let t3 = 22 * src[o + 1] + 10 * src[o + 3];
184 let t4 = 22 * src[o + 3] - 10 * src[o + 1];
185 src[o] = (t1 + t3) >> 3;
186 src[o + 1] = (t2 - t4) >> 3;
187 src[o + 2] = (t2 + t4) >> 3;
188 src[o + 3] = (t1 - t3) >> 3;
189 }
190 for c in 0..4 {
191 let t1 = 12 * (src[c] + src[c + 16]) + 64;
192 let t2 = 12 * (src[c] - src[c + 16]) + 64;
193 let t3 = 16 * src[c + 8] + 6 * src[c + 24];
194 let t4 = 6 * src[c + 8] - 16 * src[c + 24];
195 let t5 = t1 + t3;
196 let t6 = t2 + t4;
197 let t7 = t2 - t4;
198 let t8 = t1 - t3;
199 let a = 16 * src[c + 4] + 15 * src[c + 12] + 9 * src[c + 20] + 4 * src[c + 28];
200 let b = 15 * src[c + 4] - 4 * src[c + 12] - 16 * src[c + 20] - 9 * src[c + 28];
201 let d = 9 * src[c + 4] - 16 * src[c + 12] + 4 * src[c + 20] + 15 * src[c + 28];
202 let e = 4 * src[c + 4] - 9 * src[c + 12] + 15 * src[c + 20] - 16 * src[c + 28];
203 block[col0 + c] = (t5 + a) >> 7;
204 block[8 + col0 + c] = (t6 + b) >> 7;
205 block[16 + col0 + c] = (t7 + d) >> 7;
206 block[24 + col0 + c] = (t8 + e) >> 7;
207 block[32 + col0 + c] = (t8 - e + 1) >> 7;
208 block[40 + col0 + c] = (t7 - d + 1) >> 7;
209 block[48 + col0 + c] = (t6 - b + 1) >> 7;
210 block[56 + col0 + c] = (t5 - a + 1) >> 7;
211 }
212}
213
214fn inv_trans_4x4_part(block: &mut [i32; 64], row0: usize, col0: usize) {
215 let mut src = [0i32; 16];
216 for r in 0..4 {
217 for c in 0..4 {
218 src[r * 4 + c] = block[(row0 + r) * 8 + col0 + c];
219 }
220 }
221 for r in 0..4 {
222 let o = r * 4;
223 let t1 = 17 * (src[o] + src[o + 2]) + 4;
224 let t2 = 17 * (src[o] - src[o + 2]) + 4;
225 let t3 = 22 * src[o + 1] + 10 * src[o + 3];
226 let t4 = 22 * src[o + 3] - 10 * src[o + 1];
227 src[o] = (t1 + t3) >> 3;
228 src[o + 1] = (t2 - t4) >> 3;
229 src[o + 2] = (t2 + t4) >> 3;
230 src[o + 3] = (t1 - t3) >> 3;
231 }
232 for c in 0..4 {
233 let t1 = 17 * (src[c] + src[c + 8]) + 64;
234 let t2 = 17 * (src[c] - src[c + 8]) + 64;
235 let t3 = 22 * src[c + 4] + 10 * src[c + 12];
236 let t4 = 22 * src[c + 12] - 10 * src[c + 4];
237 block[row0 * 8 + col0 + c] = (t1 + t3) >> 7;
238 block[(row0 + 1) * 8 + col0 + c] = (t2 - t4) >> 7;
239 block[(row0 + 2) * 8 + col0 + c] = (t2 + t4) >> 7;
240 block[(row0 + 3) * 8 + col0 + c] = (t1 - t3) >> 7;
241 }
242}
243
244pub fn apply_idct(block: &mut [i32; 64], tt: u8) {
245 use crate::vc1_tables::*;
246 match tt {
247 TT_8X8 => idct8x8(block),
248 TT_8X4 | TT_8X4_TOP | TT_8X4_BOTTOM => {
249 if tt != TT_8X4_BOTTOM {
250 inv_trans_8x4_part(block, 0);
251 }
252 if tt != TT_8X4_TOP {
253 inv_trans_8x4_part(block, 4);
254 }
255 }
256 TT_4X8 | TT_4X8_LEFT | TT_4X8_RIGHT => {
257 if tt != TT_4X8_RIGHT {
258 inv_trans_4x8_part(block, 0);
259 }
260 if tt != TT_4X8_LEFT {
261 inv_trans_4x8_part(block, 4);
262 }
263 }
264 TT_4X4 => {
265 inv_trans_4x4_part(block, 0, 0);
266 inv_trans_4x4_part(block, 0, 4);
267 inv_trans_4x4_part(block, 4, 0);
268 inv_trans_4x4_part(block, 4, 4);
269 }
270 _ => idct8x8(block),
271 }
272}
273
274#[inline(always)]
275fn vc1_transpose_scan_index(index: usize) -> usize {
276 (index >> 3) | ((index & 7) << 3)
277}
278
279#[inline(always)]
280fn vc1_scan_index(scan: &[usize], pos: usize, res_fasttx: bool) -> usize {
281 let index = scan[pos];
282 if res_fasttx {
283 vc1_transpose_scan_index(index)
284 } else {
285 index
286 }
287}
288
289fn apply_wmv3_idct(block: &mut [i32; 64], tt: u8, res_fasttx: bool) {
295 if res_fasttx {
296 apply_idct(block, tt);
297 return;
298 }
299
300 let mut b = [0i16; 64];
301 for (dst, src) in b.iter_mut().zip(block.iter()) {
302 *dst = *src as i16;
303 }
304
305 match tt {
306 TT_8X8 => ffidct::ff_simple_idct_int16_8bit(&mut b),
307 TT_8X4 | TT_8X4_TOP | TT_8X4_BOTTOM => {
308 if tt != TT_8X4_BOTTOM {
309 ffidct::ff_simple_idct84_int16_8bit(&mut b, 0);
310 }
311 if tt != TT_8X4_TOP {
312 ffidct::ff_simple_idct84_int16_8bit(&mut b, 4);
313 }
314 }
315 TT_4X8 | TT_4X8_LEFT | TT_4X8_RIGHT => {
316 if tt != TT_4X8_RIGHT {
317 ffidct::ff_simple_idct48_int16_8bit(&mut b, 0);
318 }
319 if tt != TT_4X8_LEFT {
320 ffidct::ff_simple_idct48_int16_8bit(&mut b, 4);
321 }
322 }
323 TT_4X4 => {
324 ffidct::ff_simple_idct44_int16_8bit(&mut b, 0, 0);
325 ffidct::ff_simple_idct44_int16_8bit(&mut b, 0, 4);
326 ffidct::ff_simple_idct44_int16_8bit(&mut b, 4, 0);
327 ffidct::ff_simple_idct44_int16_8bit(&mut b, 4, 4);
328 }
329 _ => ffidct::ff_simple_idct_int16_8bit(&mut b),
330 }
331
332 for (dst, src) in block.iter_mut().zip(b.iter()) {
333 *dst = *src as i32;
334 }
335}
336
337fn iquant_uniform(level: i32, pquant: i32, halfqp: bool) -> i32 {
341 if level == 0 {
342 return 0;
343 }
344 let step = 2 * pquant;
345 let base = step * level.abs() + pquant;
346 let delta = if halfqp { pquant } else { 0 };
347 let result = if level > 0 {
348 base + delta
349 } else {
350 -(base + delta)
351 };
352 result.clamp(-2048, 2047)
353}
354
355fn iquant_nonuniform(level: i32, pquant: i32) -> i32 {
356 if level == 0 {
357 return 0;
358 }
359 const STEP: [i32; 32] = [
361 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,
362 27, 29, 31, 33, 35, 37, 63,
363 ];
364 let step = STEP[(pquant as usize).min(31)];
365 let result = step * level.abs() + pquant;
366 if level > 0 {
367 result.clamp(-2048, 2047)
368 } else {
369 (-result).clamp(-2048, 2047)
370 }
371}
372
373const DC_STEP_LUMA: [i32; 32] = [
380 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, ];
386
387const DC_STEP_CHROMA: [i32; 32] = [
388 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, ];
394
395#[inline]
396fn dc_step(pquant: i32, is_luma: bool) -> i32 {
397 let idx = pquant.clamp(1, 31) as usize;
398 if is_luma {
399 DC_STEP_LUMA[idx]
400 } else {
401 DC_STEP_CHROMA[idx]
402 }
403}
404
405#[inline(always)]
414fn vc1_filter_line(plane: &mut [u8], src: usize, stride: isize, pq: i32) -> bool {
415 #[inline(always)]
416 fn at(plane: &[u8], src: usize, stride: isize, n: isize) -> i32 {
417 plane[(src as isize + n * stride) as usize] as i32
418 }
419
420 let mut a0 = (2 * (at(plane, src, stride, -2) - at(plane, src, stride, 1))
421 - 5 * (at(plane, src, stride, -1) - at(plane, src, stride, 0))
422 + 4)
423 >> 3;
424 let a0_sign = a0 >> 31;
425 a0 = (a0 ^ a0_sign) - a0_sign;
426
427 if a0 < pq {
428 let a1 = ((2 * (at(plane, src, stride, -4) - at(plane, src, stride, -1))
429 - 5 * (at(plane, src, stride, -3) - at(plane, src, stride, -2))
430 + 4)
431 >> 3)
432 .abs();
433 let a2 = ((2 * (at(plane, src, stride, 0) - at(plane, src, stride, 3))
434 - 5 * (at(plane, src, stride, 1) - at(plane, src, stride, 2))
435 + 4)
436 >> 3)
437 .abs();
438 if a1 < a0 || a2 < a0 {
439 let mut clip = at(plane, src, stride, -1) - at(plane, src, stride, 0);
440 let clip_sign = clip >> 31;
441 clip = ((clip ^ clip_sign) - clip_sign) >> 1;
442 if clip != 0 {
443 let a3 = a1.min(a2);
449 let mut d = (5 * (a0 - a3)) >> 3;
450 if (a0_sign ^ clip_sign) != 0 {
451 d = d.min(clip);
452 d = (d ^ clip_sign) - clip_sign;
453 let l = (src as isize - stride) as usize;
454 let r = src;
455 plane[l] = (plane[l] as i32 - d).clamp(0, 255) as u8;
456 plane[r] = (plane[r] as i32 + d).clamp(0, 255) as u8;
457 }
458 return true;
459 }
460 }
461 }
462 false
463}
464
465fn vc1_loop_filter_edge(
468 plane: &mut [u8],
469 src: usize,
470 step: isize,
471 stride: isize,
472 len: usize,
473 pq: i32,
474) {
475 let mut i = 0usize;
476 while i + 3 < len {
477 let p2 = (src as isize + (i as isize + 2) * step) as usize;
478 if vc1_filter_line(plane, p2, stride, pq) {
479 for off in [0isize, 1, 3] {
480 let p = (src as isize + (i as isize + off) * step) as usize;
481 vc1_filter_line(plane, p, stride, pq);
482 }
483 }
484 i += 4;
485 }
486}
487
488#[inline]
489fn vc1_filter_horizontal_boundary(
490 plane: &mut [u8],
491 width: usize,
492 height: usize,
493 x: usize,
494 y: usize,
495 len: usize,
496 pq: i32,
497) {
498 if y < 4 || y + 3 >= height || x >= width {
499 return;
500 }
501 let len = len.min(width - x) & !3;
502 if len >= 4 {
503 vc1_loop_filter_edge(plane, y * width + x, 1, width as isize, len, pq);
504 }
505}
506
507#[inline]
508fn vc1_filter_vertical_boundary(
509 plane: &mut [u8],
510 width: usize,
511 height: usize,
512 x: usize,
513 y: usize,
514 len: usize,
515 pq: i32,
516) {
517 if x < 4 || x + 3 >= width || y >= height {
518 return;
519 }
520 let len = len.min(height - y) & !3;
521 if len >= 4 {
522 vc1_loop_filter_edge(plane, y * width + x, width as isize, 1, len, pq);
523 }
524}
525
526fn vc1_i_v_loop_filter_mb(frame: &mut YuvFrame, mb_row: usize, mb_col: usize, pq: i32) {
532 let w = frame.width as usize;
533 let h = frame.height as usize;
534 let x = mb_col * 16;
535 let y = mb_row * 16;
536
537 if y > 0 {
538 vc1_filter_horizontal_boundary(&mut frame.y, w, h, x, y, 16, pq);
539 }
540 if y + 8 < h {
541 vc1_filter_horizontal_boundary(&mut frame.y, w, h, x, y + 8, 16, pq);
542 }
543
544 let cw = w / 2;
545 let ch = h / 2;
546 let cx = mb_col * 8;
547 let cy = mb_row * 8;
548 if cy > 0 {
549 vc1_filter_horizontal_boundary(&mut frame.cb, cw, ch, cx, cy, 8, pq);
550 vc1_filter_horizontal_boundary(&mut frame.cr, cw, ch, cx, cy, 8, pq);
551 }
552}
553
554fn vc1_i_h_loop_filter_mb(frame: &mut YuvFrame, mb_row: usize, mb_col: usize, pq: i32) {
559 let w = frame.width as usize;
560 let h = frame.height as usize;
561 let x = mb_col * 16;
562 let y = mb_row * 16;
563
564 if x > 0 {
565 vc1_filter_vertical_boundary(&mut frame.y, w, h, x, y, 16, pq);
566 }
567 if x + 8 < w {
568 vc1_filter_vertical_boundary(&mut frame.y, w, h, x + 8, y, 16, pq);
569 }
570
571 let cw = w / 2;
572 let ch = h / 2;
573 let cx = mb_col * 8;
574 let cy = mb_row * 8;
575 if cx > 0 {
576 vc1_filter_vertical_boundary(&mut frame.cb, cw, ch, cx, cy, 8, pq);
577 vc1_filter_vertical_boundary(&mut frame.cr, cw, ch, cx, cy, 8, pq);
578 }
579}
580
581fn vc1_apply_i_loop_filter(frame: &mut YuvFrame, pq: i32, mb_width: usize, mb_height: usize) {
590 if mb_width == 0 || mb_height == 0 {
591 return;
592 }
593
594 for cur_y in 0..mb_height {
595 for cur_x in 0..mb_width {
596 if cur_y >= 1 {
599 if cur_x >= 1 {
600 vc1_i_v_loop_filter_mb(frame, cur_y - 1, cur_x - 1, pq);
601 }
602 if cur_x + 1 == mb_width {
603 vc1_i_v_loop_filter_mb(frame, cur_y - 1, cur_x, pq);
604 }
605 }
606 if cur_y + 1 == mb_height {
607 if cur_x >= 1 {
608 vc1_i_v_loop_filter_mb(frame, cur_y, cur_x - 1, pq);
609 }
610 if cur_x + 1 == mb_width {
611 vc1_i_v_loop_filter_mb(frame, cur_y, cur_x, pq);
612 }
613 }
614
615 if cur_y >= 2 {
619 if cur_x >= 1 {
620 vc1_i_h_loop_filter_mb(frame, cur_y - 2, cur_x - 1, pq);
621 }
622 if cur_x + 1 == mb_width {
623 vc1_i_h_loop_filter_mb(frame, cur_y - 2, cur_x, pq);
624 }
625 }
626 if cur_y + 1 == mb_height {
627 if cur_y >= 1 {
628 if cur_x >= 1 {
629 vc1_i_h_loop_filter_mb(frame, cur_y - 1, cur_x - 1, pq);
630 }
631 if cur_x + 1 == mb_width {
632 vc1_i_h_loop_filter_mb(frame, cur_y - 1, cur_x, pq);
633 }
634 }
635 if cur_x >= 1 {
636 vc1_i_h_loop_filter_mb(frame, cur_y, cur_x - 1, pq);
637 }
638 if cur_x + 1 == mb_width {
639 vc1_i_h_loop_filter_mb(frame, cur_y, cur_x, pq);
640 }
641 }
642 }
643 }
644}
645
646fn read_dc_diff(br: &mut BitReader<'_>, dc_vlc: &VlcTable) -> i32 {
651 let dc_size = match dc_vlc.decode(br) {
652 Some(s @ 0..) => s as u8,
653 _ => return 0,
654 };
655 if dc_size == 0 {
656 return 0;
657 }
658 let raw = br.read_bits(dc_size).unwrap_or(0) as i32;
659 if raw & (1 << (dc_size - 1)) != 0 {
661 raw
662 } else {
663 raw - (1 << dc_size) + 1
664 }
665}
666
667#[derive(Clone)]
678pub struct DcPredBuffer {
679 mb_w: usize,
680 dc: Vec<[i32; 6]>,
683}
684
685impl DcPredBuffer {
686 pub fn new(mb_w: usize, mb_h: usize) -> Self {
687 DcPredBuffer {
688 mb_w,
689 dc: vec![[1024i32; 6]; mb_w * mb_h],
690 }
691 }
692
693 pub fn predict(&self, mb_row: usize, mb_col: usize, blk: usize) -> (i32, bool) {
697 let (dc_left, dc_top, dc_topleft) = self.dc_neighbours(mb_row, mb_col, blk);
707
708 let grad_h = (dc_left - dc_topleft).unsigned_abs();
711 let grad_v = (dc_top - dc_topleft).unsigned_abs();
712
713 if grad_v <= grad_h {
714 (dc_top, false)
716 } else {
717 (dc_left, true)
719 }
720 }
721
722 fn dc_neighbours(&self, mb_row: usize, mb_col: usize, blk: usize) -> (i32, i32, i32) {
723 let get = |r: isize, c: isize, b: usize| -> i32 {
725 if r < 0 || c < 0 {
726 return 1024;
727 } let idx = r as usize * self.mb_w + c as usize;
729 if idx >= self.dc.len() {
730 return 1024;
731 }
732 self.dc[idx][b]
733 };
734
735 let r = mb_row as isize;
736 let c = mb_col as isize;
737
738 match blk {
739 0 => {
741 let left = get(r, c - 1, 1); let top = get(r - 1, c, 2); let topleft = get(r - 1, c - 1, 3);
744 (left, top, topleft)
745 }
746 1 => {
747 let left = get(r, c, 0);
749 let top = get(r - 1, c, 3);
750 let topleft = get(r - 1, c - 1, 3);
751 (left, top, topleft)
752 }
753 2 => {
754 let left = get(r, c - 1, 3);
755 let top = get(r, c, 0); let topleft = get(r, c - 1, 1);
757 (left, top, topleft)
758 }
759 3 => {
760 let left = get(r, c, 2);
761 let top = get(r, c, 1);
762 let topleft = get(r, c, 0);
763 (left, top, topleft)
764 }
765 _ => {
767 let left = get(r, c - 1, blk);
768 let top = get(r - 1, c, blk);
769 let topleft = get(r - 1, c - 1, blk);
770 (left, top, topleft)
771 }
772 }
773 }
774
775 pub fn store(&mut self, mb_row: usize, mb_col: usize, blk: usize, dc_recon: i32) {
777 let idx = mb_row * self.mb_w + mb_col;
778 if idx < self.dc.len() {
779 self.dc[idx][blk] = dc_recon;
780 }
781 }
782}
783
784pub struct Wmv2DcPredBuffer {
789 mb_w: usize,
790 dc: Vec<[i32; 6]>,
791}
792
793impl Wmv2DcPredBuffer {
794 pub fn new(mb_w: usize, mb_h: usize) -> Self {
795 Wmv2DcPredBuffer {
796 mb_w,
797 dc: vec![[1024i32; 6]; mb_w * mb_h],
798 }
799 }
800
801 fn neighbours(&self, mb_row: usize, mb_col: usize, blk: usize) -> (i32, i32, i32) {
802 #[inline(always)]
811 fn get_luma(dc: &[[i32; 6]], mb_w: usize, bx: isize, by: isize) -> i32 {
812 if bx < 0 || by < 0 {
813 return 1024;
814 }
815 let mb_x = (bx >> 1) as usize;
816 let mb_y = (by >> 1) as usize;
817 let idx = mb_y * mb_w + mb_x;
818 if idx >= dc.len() {
819 return 1024;
820 }
821 let sub_x = (bx & 1) as usize;
822 let sub_y = (by & 1) as usize;
823 let b = (sub_y << 1) | sub_x; dc[idx][b]
825 }
826
827 #[inline(always)]
828 fn get_chroma(dc: &[[i32; 6]], mb_w: usize, mb_x: isize, mb_y: isize, blk: usize) -> i32 {
829 if mb_x < 0 || mb_y < 0 {
830 return 1024;
831 }
832 let idx = (mb_y as usize) * mb_w + (mb_x as usize);
833 if idx >= dc.len() {
834 return 1024;
835 }
836 dc[idx][blk]
837 }
838
839 if blk < 4 {
840 let bx = (mb_col as isize) * 2 + ((blk & 1) as isize);
841 let by = (mb_row as isize) * 2 + ((blk >> 1) as isize);
842 let a = get_luma(&self.dc, self.mb_w, bx - 1, by);
843 let b = get_luma(&self.dc, self.mb_w, bx - 1, by - 1);
844 let c = get_luma(&self.dc, self.mb_w, bx, by - 1);
845 (a, b, c)
846 } else {
847 let mx = mb_col as isize;
848 let my = mb_row as isize;
849 let a = get_chroma(&self.dc, self.mb_w, mx - 1, my, blk);
850 let b = get_chroma(&self.dc, self.mb_w, mx - 1, my - 1, blk);
851 let c = get_chroma(&self.dc, self.mb_w, mx, my - 1, blk);
852 (a, b, c)
853 }
854 }
855
856 pub fn predict(&self, mb_row: usize, mb_col: usize, blk: usize, scale: i32) -> (i32, i32) {
858 let (a0, b0, c0) = self.neighbours(mb_row, mb_col, blk);
859 let a = (a0 + (scale >> 1)) / scale;
861 let b = (b0 + (scale >> 1)) / scale;
862 let c = (c0 + (scale >> 1)) / scale;
863
864 if (a - b).abs() < (b - c).abs() {
866 (c, 1)
867 } else {
868 (a, 0)
869 }
870 }
871
872 pub fn store(&mut self, mb_row: usize, mb_col: usize, blk: usize, dc_coeff_scaled: i32) {
873 let idx = mb_row * self.mb_w + mb_col;
874 if idx < self.dc.len() {
875 self.dc[idx][blk] = dc_coeff_scaled;
876 }
877 }
878}
879
880#[inline]
890fn decode_escape_coeff(br: &mut BitReader<'_>, ac_vlc: &VlcTable) -> (u8, i32, bool) {
891 let mode = {
892 let b0 = br.read_bit().unwrap_or(false);
893 if !b0 {
894 1u8
895 } else {
896 let b1 = br.read_bit().unwrap_or(false);
897 if b1 { 3 } else { 2 }
898 }
899 };
900 match mode {
901 1 => {
902 let sym = ac_vlc.decode(br).unwrap_or(0);
904 if sym == VLC_ESCAPE {
905 return (0, 0, true);
906 }
907 let (run, base_level, last) = unpack_rl(sym);
908 let sign = br.read_bit().unwrap_or(false);
909 let offset = ac_vlc.max_level(run as usize, last) as i32 + 1;
910 let level = base_level as i32 + offset;
911 (run, if sign { -level } else { level }, last)
912 }
913 2 => {
914 let sym = ac_vlc.decode(br).unwrap_or(0);
916 if sym == VLC_ESCAPE {
917 return (0, 0, true);
918 }
919 let (base_run, level, last) = unpack_rl(sym);
920 let sign = br.read_bit().unwrap_or(false);
921 let offset = ac_vlc.max_run(level as usize, last) as i32 + 1;
922 let run = (base_run as i32 + offset).min(63) as u8;
923 let sl = level as i32;
924 (run, if sign { -sl } else { sl }, last)
925 }
926 _ => {
927 let last = br.read_bit().unwrap_or(false);
929 let run = br.read_bits(6).unwrap_or(0) as u8;
930 let level = br.read_bits(8).unwrap_or(1).max(1) as i32;
931 let sign = br.read_bit().unwrap_or(false);
932 (run, if sign { -level } else { level }, last)
933 }
934 }
935}
936
937fn decode_block(
942 br: &mut BitReader<'_>,
943 is_intra: bool,
944 is_luma: bool,
945 pquant: i32,
946 halfqp: bool,
947 uniform: bool,
948 tt: u8,
949 dc_luma: &VlcTable,
950 dc_chroma: &VlcTable,
951 ac_intra: &VlcTable,
952 ac_inter: &VlcTable,
953) -> [i32; 64] {
954 let mut blk = [0i32; 64];
955 let scan: &[usize; 64] = if is_intra { &SCAN_INTRA } else { &ZIGZAG };
956
957 if is_intra {
959 let dc_vlc = if is_luma { dc_luma } else { dc_chroma };
960 blk[0] = read_dc_diff(br, dc_vlc);
961 }
962
963 let ac_vlc = if is_intra { ac_intra } else { ac_inter };
965 let mut idx = if is_intra { 1usize } else { 0 };
966
967 while let Some(sym) = ac_vlc.decode(br) {
968 let (run, signed_level, last) = if sym == VLC_ESCAPE {
969 decode_escape_coeff(br, ac_vlc)
970 } else {
971 let (r, l, last) = unpack_rl(sym);
972 let sign = br.read_bit().unwrap_or(false);
973 (r, if sign { -(l as i32) } else { l as i32 }, last)
974 };
975
976 idx += run as usize;
977 if idx >= 64 {
978 break;
979 }
980
981 let mag = signed_level.abs();
982 let qval = if uniform {
983 iquant_uniform(mag, pquant, halfqp)
984 } else {
985 iquant_nonuniform(mag, pquant)
986 };
987 let signed_val = if signed_level < 0 { -qval } else { qval };
988
989 let scan_order: &[usize; 64] = match tt {
991 3 | 4 => &SCAN_VERT,
992 _ => scan,
993 };
994 let pos = scan_order.get(idx).copied().unwrap_or(idx);
995 blk[pos] = signed_val;
996 idx += 1;
997
998 if last || br.is_empty() {
999 break;
1000 }
1001 }
1002
1003 blk
1004}
1005
1006fn decode_block_ac(
1008 br: &mut BitReader<'_>,
1009 _is_luma: bool,
1010 pquant: i32,
1011 halfqp: bool,
1012 uniform: bool,
1013 tt: u8,
1014 ac_vlc: &VlcTable,
1015) -> [i32; 64] {
1016 let mut blk = [0i32; 64];
1017 let mut idx = 1usize; while let Some(sym) = ac_vlc.decode(br) {
1020 let (run, signed_level, last) = if sym == VLC_ESCAPE {
1021 decode_escape_coeff(br, ac_vlc)
1022 } else {
1023 let (r, l, last) = unpack_rl(sym);
1024 let sign = br.read_bit().unwrap_or(false);
1025 (r, if sign { -(l as i32) } else { l as i32 }, last)
1026 };
1027
1028 idx += run as usize;
1029 if idx >= 64 {
1030 break;
1031 }
1032
1033 let mag = signed_level.abs();
1034 let qval = if uniform {
1035 iquant_uniform(mag, pquant, halfqp)
1036 } else {
1037 iquant_nonuniform(mag, pquant)
1038 };
1039 let sval = if signed_level < 0 { -qval } else { qval };
1040
1041 let scan_order: &[usize; 64] = match tt {
1042 3 | 4 => &SCAN_VERT,
1043 _ => &SCAN_INTRA,
1044 };
1045 let pos = scan_order.get(idx).copied().unwrap_or(idx);
1046 blk[pos] = sval;
1047 idx += 1;
1048
1049 if last || br.is_empty() {
1050 break;
1051 }
1052 }
1053 blk
1054}
1055
1056#[derive(Clone)]
1064pub struct AcPredBuffer {
1065 mb_w: usize,
1066 row: Vec<[[i32; 7]; 6]>,
1068 col: Vec<[[i32; 7]; 6]>,
1070}
1071
1072impl AcPredBuffer {
1073 pub fn new(mb_w: usize, mb_h: usize) -> Self {
1074 let n = mb_w * mb_h;
1075 AcPredBuffer {
1076 mb_w,
1077 row: vec![[[0i32; 7]; 6]; n],
1078 col: vec![[[0i32; 7]; 6]; n],
1079 }
1080 }
1081
1082 pub fn clear(&mut self) {
1083 self.row.fill([[0i32; 7]; 6]);
1084 self.col.fill([[0i32; 7]; 6]);
1085 }
1086
1087 pub fn pred_row(&self, mb_row: usize, mb_col: usize, blk: usize) -> [i32; 7] {
1090 let (src_mb_r, src_mb_c, src_blk) = Self::left_neighbour(mb_row, mb_col, blk);
1091 if src_mb_r as isize >= 0 && src_mb_c as isize >= 0 {
1092 let idx = src_mb_r * self.mb_w + src_mb_c;
1093 if idx < self.row.len() {
1094 return self.row[idx][src_blk];
1095 }
1096 }
1097 [0i32; 7]
1098 }
1099
1100 pub fn pred_col(&self, mb_row: usize, mb_col: usize, blk: usize) -> [i32; 7] {
1103 let (src_mb_r, src_mb_c, src_blk) = Self::top_neighbour(mb_row, mb_col, blk);
1104 if src_mb_r as isize >= 0 && src_mb_c as isize >= 0 {
1105 let idx = src_mb_r * self.mb_w + src_mb_c;
1106 if idx < self.col.len() {
1107 return self.col[idx][src_blk];
1108 }
1109 }
1110 [0i32; 7]
1111 }
1112
1113 pub fn pred_left_col(&self, mb_row: usize, mb_col: usize, blk: usize) -> [i32; 7] {
1115 let (r, c, b) = Self::left_neighbour(mb_row, mb_col, blk);
1116 let idx = r.wrapping_mul(self.mb_w).wrapping_add(c);
1117 if c < self.mb_w && idx < self.col.len() {
1118 self.col[idx][b]
1119 } else {
1120 [0; 7]
1121 }
1122 }
1123
1124 pub fn pred_top_row(&self, mb_row: usize, mb_col: usize, blk: usize) -> [i32; 7] {
1126 let (r, c, b) = Self::top_neighbour(mb_row, mb_col, blk);
1127 let idx = r.wrapping_mul(self.mb_w).wrapping_add(c);
1128 if self.mb_w != 0 && c < self.mb_w && idx < self.row.len() {
1129 self.row[idx][b]
1130 } else {
1131 [0; 7]
1132 }
1133 }
1134
1135 pub fn store_row(&mut self, mb_row: usize, mb_col: usize, blk: usize, row: [i32; 7]) {
1136 let idx = mb_row * self.mb_w + mb_col;
1137 if idx < self.row.len() {
1138 self.row[idx][blk] = row;
1139 }
1140 }
1141
1142 pub fn store_col(&mut self, mb_row: usize, mb_col: usize, blk: usize, col: [i32; 7]) {
1143 let idx = mb_row * self.mb_w + mb_col;
1144 if idx < self.col.len() {
1145 self.col[idx][blk] = col;
1146 }
1147 }
1148
1149 fn left_neighbour(mb_row: usize, mb_col: usize, blk: usize) -> (usize, usize, usize) {
1151 match blk {
1152 0 => (mb_row, mb_col.wrapping_sub(1), 1),
1153 1 => (mb_row, mb_col, 0),
1154 2 => (mb_row, mb_col.wrapping_sub(1), 3),
1155 3 => (mb_row, mb_col, 2),
1156 _ => (mb_row, mb_col.wrapping_sub(1), blk),
1157 }
1158 }
1159
1160 fn top_neighbour(mb_row: usize, mb_col: usize, blk: usize) -> (usize, usize, usize) {
1161 match blk {
1162 0 => (mb_row.wrapping_sub(1), mb_col, 2),
1163 1 => (mb_row.wrapping_sub(1), mb_col, 3),
1164 2 => (mb_row, mb_col, 0),
1165 3 => (mb_row, mb_col, 1),
1166 _ => (mb_row.wrapping_sub(1), mb_col, blk),
1167 }
1168 }
1169}
1170
1171#[derive(Clone, Default)]
1179pub struct MvPredictor {
1180 mb_w: usize,
1181 mvs: Vec<(i32, i32)>,
1183 skipped: Vec<bool>,
1185}
1186
1187impl MvPredictor {
1188 pub fn new(mb_w: usize, mb_h: usize) -> Self {
1189 let n = mb_w * mb_h;
1190 MvPredictor {
1191 mb_w,
1192 mvs: vec![(0, 0); n],
1193 skipped: vec![true; n],
1194 }
1195 }
1196
1197 pub fn predict(&self, mb_row: usize, mb_col: usize) -> (i32, i32) {
1199 let get = |r: isize, c: isize| -> (i32, i32) {
1200 if r < 0 || c < 0 {
1201 return (0, 0);
1202 }
1203 let idx = r as usize * self.mb_w + c as usize;
1204 if idx >= self.mvs.len() || self.skipped[idx] {
1205 return (0, 0);
1206 }
1207 self.mvs[idx]
1208 };
1209
1210 let r = mb_row as isize;
1211 let c = mb_col as isize;
1212
1213 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 {
1218 get(r - 1, c - 1)
1219 } else {
1220 (cx, cy)
1221 };
1222
1223 (median3(ax, bx, cx), median3(ay, by, cy))
1224 }
1225
1226 pub fn store(&mut self, mb_row: usize, mb_col: usize, mv: (i32, i32), skipped: bool) {
1227 let idx = mb_row * self.mb_w + mb_col;
1228 if idx < self.mvs.len() {
1229 self.mvs[idx] = mv;
1230 self.skipped[idx] = skipped;
1231 }
1232 }
1233}
1234
1235#[inline]
1236fn median3(a: i32, b: i32, c: i32) -> i32 {
1237 if (a <= b && b <= c) || (c <= b && b <= a) {
1239 b
1240 } else if (b <= a && a <= c) || (c <= a && a <= b) {
1241 a
1242 } else {
1243 c
1244 }
1245}
1246
1247#[inline(always)]
1248fn mid_pred(a: i32, b: i32, c: i32) -> i32 {
1249 median3(a, b, c)
1251}
1252
1253#[inline]
1259fn vc1_h_s_overlap(left: &mut [i32; 64], right: &mut [i32; 64]) {
1260 let mut rnd1 = 4i32;
1261 let mut rnd2 = 3i32;
1262 for row in 0..8usize {
1263 let li = row * 8;
1264 let ri = row * 8;
1265 let a = left[li + 6];
1266 let b = left[li + 7];
1267 let c = right[ri];
1268 let d = right[ri + 1];
1269 let d1 = a - d;
1270 let d2 = a - d + b - c;
1271
1272 left[li + 6] = ((a * 8) - d1 + rnd1) >> 3;
1273 left[li + 7] = ((b * 8) - d2 + rnd2) >> 3;
1274 right[ri] = ((c * 8) + d2 + rnd1) >> 3;
1275 right[ri + 1] = ((d * 8) + d1 + rnd2) >> 3;
1276
1277 rnd2 = 7 - rnd2;
1280 rnd1 = 7 - rnd1;
1281 }
1282}
1283
1284#[inline]
1285fn vc1_v_s_overlap(top: &mut [i32; 64], bottom: &mut [i32; 64]) {
1286 let mut rnd1 = 4i32;
1287 let mut rnd2 = 3i32;
1288 for col in 0..8usize {
1289 let a = top[48 + col];
1290 let b = top[56 + col];
1291 let c = bottom[col];
1292 let d = bottom[8 + col];
1293 let d1 = a - d;
1294 let d2 = a - d + b - c;
1295
1296 top[48 + col] = ((a * 8) - d1 + rnd1) >> 3;
1297 top[56 + col] = ((b * 8) - d2 + rnd2) >> 3;
1298 bottom[col] = ((c * 8) + d2 + rnd1) >> 3;
1299 bottom[8 + col] = ((d * 8) + d1 + rnd2) >> 3;
1300
1301 rnd2 = 7 - rnd2;
1302 rnd1 = 7 - rnd1;
1303 }
1304}
1305
1306#[inline]
1307fn vc1_two_blocks_mut(
1308 blocks: &mut [[i32; 64]],
1309 a: usize,
1310 b: usize,
1311) -> (&mut [i32; 64], &mut [i32; 64]) {
1312 debug_assert_ne!(a, b);
1313 if a < b {
1314 let (left, right) = blocks.split_at_mut(b);
1315 (&mut left[a], &mut right[0])
1316 } else {
1317 let (left, right) = blocks.split_at_mut(a);
1318 (&mut right[0], &mut left[b])
1319 }
1320}
1321
1322#[inline]
1323fn vc1_recon_index(mb_width: usize, mb_row: usize, mb_col: usize, block: usize) -> usize {
1324 (mb_row * mb_width + mb_col) * 6 + block
1325}
1326
1327fn vc1_apply_signed_overlap(
1333 blocks: &mut [[i32; 64]],
1334 intra: &[[bool; 6]],
1335 mb_width: usize,
1336 mb_height: usize,
1337 scale_current_after: bool,
1338) {
1339 #[inline]
1340 fn h_if(blocks: &mut [[i32; 64]], intra: &[[bool; 6]], left: usize, right: usize) {
1341 let lmb = left / 6;
1342 let lblk = left % 6;
1343 let rmb = right / 6;
1344 let rblk = right % 6;
1345 if intra[lmb][lblk] && intra[rmb][rblk] {
1346 let (l, r) = vc1_two_blocks_mut(blocks, left, right);
1347 vc1_h_s_overlap(l, r);
1348 }
1349 }
1350
1351 #[inline]
1352 fn v_if(blocks: &mut [[i32; 64]], intra: &[[bool; 6]], top: usize, bottom: usize) {
1353 let tmb = top / 6;
1354 let tblk = top % 6;
1355 let bmb = bottom / 6;
1356 let bblk = bottom % 6;
1357 if intra[tmb][tblk] && intra[bmb][bblk] {
1358 let (t, b) = vc1_two_blocks_mut(blocks, top, bottom);
1359 vc1_v_s_overlap(t, b);
1360 }
1361 }
1362
1363 #[inline]
1364 fn finish_v_column(
1365 blocks: &mut [[i32; 64]],
1366 intra: &[[bool; 6]],
1367 mb_width: usize,
1368 mb_row: usize,
1369 target_col: usize,
1370 ) {
1371 let bottom = |blk: usize| vc1_recon_index(mb_width, mb_row, target_col, blk);
1372 if mb_row > 0 {
1373 let top = |blk: usize| vc1_recon_index(mb_width, mb_row - 1, target_col, blk);
1374 v_if(blocks, intra, top(2), bottom(0));
1375 v_if(blocks, intra, top(3), bottom(1));
1376 }
1377 v_if(blocks, intra, bottom(0), bottom(2));
1378 v_if(blocks, intra, bottom(1), bottom(3));
1379 if mb_row > 0 {
1380 let top = |blk: usize| vc1_recon_index(mb_width, mb_row - 1, target_col, blk);
1381 v_if(blocks, intra, top(4), bottom(4));
1382 v_if(blocks, intra, top(5), bottom(5));
1383 }
1384 }
1385
1386 for mb_row in 0..mb_height {
1393 for mb_col in 0..mb_width {
1394 let cur = |blk: usize| vc1_recon_index(mb_width, mb_row, mb_col, blk);
1395
1396 if mb_col > 0 {
1400 let left = |blk: usize| vc1_recon_index(mb_width, mb_row, mb_col - 1, blk);
1401 h_if(blocks, intra, left(1), cur(0));
1402 h_if(blocks, intra, cur(0), cur(1));
1403 h_if(blocks, intra, left(3), cur(2));
1404 h_if(blocks, intra, cur(2), cur(3));
1405 h_if(blocks, intra, left(4), cur(4));
1406 h_if(blocks, intra, left(5), cur(5));
1407 } else {
1408 h_if(blocks, intra, cur(0), cur(1));
1409 h_if(blocks, intra, cur(2), cur(3));
1410 }
1411
1412 if mb_col > 0 {
1416 finish_v_column(blocks, intra, mb_width, mb_row, mb_col - 1);
1417 }
1418 if mb_col + 1 == mb_width {
1419 finish_v_column(blocks, intra, mb_width, mb_row, mb_col);
1420 }
1421
1422 if scale_current_after {
1427 let base = vc1_recon_index(mb_width, mb_row, mb_col, 0);
1428 for blk in 0..6usize {
1429 for v in &mut blocks[base + blk] {
1430 *v *= 2;
1431 }
1432 }
1433 }
1434 }
1435 }
1436}
1437
1438fn vc1_apply_advanced_selective_i_overlap(
1448 blocks: &mut [[i32; 64]],
1449 mb_width: usize,
1450 mb_height: usize,
1451 overflags: &[u8],
1452) {
1453 #[inline]
1454 fn h_edge(
1455 blocks: &mut [[i32; 64]],
1456 mb_width: usize,
1457 mb_row: usize,
1458 mb_col: usize,
1459 left_blk: usize,
1460 right_blk: usize,
1461 ) {
1462 let left = vc1_recon_index(mb_width, mb_row, mb_col, left_blk);
1463 let right = vc1_recon_index(mb_width, mb_row, mb_col, right_blk);
1464 let (l, r) = vc1_two_blocks_mut(blocks, left, right);
1465 vc1_h_s_overlap(l, r);
1466 }
1467
1468 #[inline]
1469 fn h_cross(
1470 blocks: &mut [[i32; 64]],
1471 mb_width: usize,
1472 mb_row: usize,
1473 mb_col: usize,
1474 left_blk: usize,
1475 right_blk: usize,
1476 ) {
1477 let left = vc1_recon_index(mb_width, mb_row, mb_col - 1, left_blk);
1478 let right = vc1_recon_index(mb_width, mb_row, mb_col, right_blk);
1479 let (l, r) = vc1_two_blocks_mut(blocks, left, right);
1480 vc1_h_s_overlap(l, r);
1481 }
1482
1483 #[inline]
1484 fn v_edge(
1485 blocks: &mut [[i32; 64]],
1486 mb_width: usize,
1487 mb_row: usize,
1488 mb_col: usize,
1489 top_blk: usize,
1490 bottom_blk: usize,
1491 ) {
1492 let top = vc1_recon_index(mb_width, mb_row, mb_col, top_blk);
1493 let bottom = vc1_recon_index(mb_width, mb_row, mb_col, bottom_blk);
1494 let (t, b) = vc1_two_blocks_mut(blocks, top, bottom);
1495 vc1_v_s_overlap(t, b);
1496 }
1497
1498 #[inline]
1499 fn v_cross(
1500 blocks: &mut [[i32; 64]],
1501 mb_width: usize,
1502 mb_row: usize,
1503 mb_col: usize,
1504 top_blk: usize,
1505 bottom_blk: usize,
1506 ) {
1507 let top = vc1_recon_index(mb_width, mb_row - 1, mb_col, top_blk);
1508 let bottom = vc1_recon_index(mb_width, mb_row, mb_col, bottom_blk);
1509 let (t, b) = vc1_two_blocks_mut(blocks, top, bottom);
1510 vc1_v_s_overlap(t, b);
1511 }
1512
1513 #[inline]
1514 fn finish_v_column(
1515 blocks: &mut [[i32; 64]],
1516 mb_width: usize,
1517 mb_row: usize,
1518 col: usize,
1519 overflags: &[u8],
1520 ) {
1521 let cur = mb_row * mb_width + col;
1522 let cur_on = overflags.get(cur).copied().unwrap_or(0) != 0;
1523 if !cur_on {
1524 return;
1525 }
1526
1527 let top_on = mb_row > 0 && overflags.get(cur - mb_width).copied().unwrap_or(0) != 0;
1528 if top_on {
1531 v_cross(blocks, mb_width, mb_row, col, 2, 0);
1532 v_cross(blocks, mb_width, mb_row, col, 3, 1);
1533 }
1534 v_edge(blocks, mb_width, mb_row, col, 0, 2);
1535 v_edge(blocks, mb_width, mb_row, col, 1, 3);
1536 if top_on {
1537 v_cross(blocks, mb_width, mb_row, col, 4, 4);
1538 v_cross(blocks, mb_width, mb_row, col, 5, 5);
1539 }
1540 }
1541
1542 for mb_row in 0..mb_height {
1543 for mb_col in 0..mb_width {
1544 let cur = mb_row * mb_width + mb_col;
1545 let cur_on = overflags.get(cur).copied().unwrap_or(0) != 0;
1546
1547 if cur_on {
1548 let left_on = mb_col > 0 && overflags.get(cur - 1).copied().unwrap_or(0) != 0;
1549 if left_on {
1551 h_cross(blocks, mb_width, mb_row, mb_col, 1, 0);
1552 }
1553 h_edge(blocks, mb_width, mb_row, mb_col, 0, 1);
1554 if left_on {
1555 h_cross(blocks, mb_width, mb_row, mb_col, 3, 2);
1556 }
1557 h_edge(blocks, mb_width, mb_row, mb_col, 2, 3);
1558 if left_on {
1559 h_cross(blocks, mb_width, mb_row, mb_col, 4, 4);
1560 h_cross(blocks, mb_width, mb_row, mb_col, 5, 5);
1561 }
1562 }
1563
1564 if mb_col > 0 {
1567 finish_v_column(blocks, mb_width, mb_row, mb_col - 1, overflags);
1568 }
1569 if mb_col + 1 == mb_width {
1570 finish_v_column(blocks, mb_width, mb_row, mb_col, overflags);
1571 }
1572 }
1573 }
1574}
1575
1576#[inline(always)]
1577fn vc1_range_reduce_sample(v: u8) -> u8 {
1578 (((v as i32 - 128) >> 1) + 128) as u8
1579}
1580
1581fn vc1_range_reduce_reference(frame: &mut YuvFrame) {
1582 for v in &mut frame.y {
1583 *v = vc1_range_reduce_sample(*v);
1584 }
1585 for v in &mut frame.cb {
1586 *v = vc1_range_reduce_sample(*v);
1587 }
1588 for v in &mut frame.cr {
1589 *v = vc1_range_reduce_sample(*v);
1590 }
1591}
1592
1593#[inline]
1597fn vc1_loop_chroma_mv(mv: (i32, i32)) -> (i32, i32) {
1598 (
1599 (mv.0 + ((mv.0 & 3) == 3) as i32) >> 1,
1600 (mv.1 + ((mv.1 & 3) == 3) as i32) >> 1,
1601 )
1602}
1603
1604fn mc_luma(
1608 dst: &mut [u8],
1609 dst_stride: usize,
1610 src: &[u8],
1611 src_stride: usize,
1612 src_w: usize,
1613 src_h: usize,
1614 x: i32,
1615 y: i32,
1616 w: usize,
1617 h: usize,
1618) {
1619 let xh = x & 1 != 0;
1621 let yh = y & 1 != 0;
1622 let x0 = (x >> 1) as isize;
1623 let y0 = (y >> 1) as isize;
1624
1625 for dy in 0..h {
1626 for dx in 0..w {
1627 let sx = (x0 + dx as isize).clamp(0, src_w as isize - 1) as usize;
1628 let sy = (y0 + dy as isize).clamp(0, src_h as isize - 1) as usize;
1629 let sx1 = (sx + 1).min(src_w - 1);
1630 let sy1 = (sy + 1).min(src_h - 1);
1631
1632 let p00 = src[sy * src_stride + sx] as i32;
1633 let p10 = src[sy * src_stride + sx1] as i32;
1634 let p01 = src[sy1 * src_stride + sx] as i32;
1635 let p11 = src[sy1 * src_stride + sx1] as i32;
1636
1637 let val = match (xh, yh) {
1638 (false, false) => p00,
1639 (true, false) => (p00 + p10 + 1) >> 1,
1640 (false, true) => (p00 + p01 + 1) >> 1,
1641 (true, true) => (p00 + p10 + p01 + p11 + 2) >> 2,
1642 };
1643 dst[dy * dst_stride + dx] = val.clamp(0, 255) as u8;
1644 }
1645 }
1646}
1647
1648fn read_mquant(
1655 br: &mut BitReader<'_>,
1656 dquant: &crate::vc1::DQuantInfo,
1657 pquant: i32,
1658 mb_x: u32,
1659 mb_y: u32,
1660 mb_width: u32,
1661 mb_height: u32,
1662) -> Result<i32> {
1663 if !dquant.enabled {
1664 return Ok(pquant);
1665 }
1666
1667 let mut mquant = pquant;
1668 let mut edges = 0u8;
1669 match dquant.profile {
1670 3 => {
1671 if dquant.bi_level {
1673 let bilevel = br.read_bit().ok_or_else(|| {
1674 DecoderError::InvalidData("truncated WMV3 DQBILEVEL macroblock bit".into())
1675 })?;
1676 mquant = if bilevel {
1677 -(dquant.alt_pquant as i32)
1678 } else {
1679 pquant
1680 };
1681 } else {
1682 let mqdiff = br
1683 .read_bits(3)
1684 .ok_or_else(|| DecoderError::InvalidData("truncated WMV3 MQDIFF".into()))?
1685 as i32;
1686 mquant = if mqdiff != 7 {
1687 -pquant - mqdiff
1688 } else {
1689 -(br.read_bits(5)
1690 .ok_or_else(|| DecoderError::InvalidData("truncated WMV3 MQUANT".into()))?
1691 as i32)
1692 };
1693 }
1694 }
1695 0 => edges = 1u8 << dquant.edge.min(3),
1696 1 => edges = ((3u16 << dquant.edge.min(3)) % 15) as u8,
1697 2 => edges = 15,
1698 _ => {}
1699 }
1700
1701 if (edges & 1) != 0 && mb_x == 0 {
1702 mquant = -(dquant.alt_pquant as i32);
1703 }
1704 if (edges & 2) != 0 && mb_y == 0 {
1705 mquant = -(dquant.alt_pquant as i32);
1706 }
1707 if (edges & 4) != 0 && mb_x + 1 == mb_width {
1708 mquant = -(dquant.alt_pquant as i32);
1709 }
1710 if (edges & 8) != 0 && mb_y + 1 == mb_height {
1711 mquant = -(dquant.alt_pquant as i32);
1712 }
1713
1714 if mquant == 0 || !(-31..=31).contains(&mquant) {
1715 mquant = 1;
1716 }
1717 Ok(mquant)
1718}
1719
1720fn block_coords(
1729 mb_row: u32,
1730 mb_col: u32,
1731 blk: usize,
1732 width: u32,
1733 height: u32,
1734) -> (bool, usize, usize, usize, usize) {
1735 let (is_luma, bx, by) = match blk {
1737 0 => (true, (mb_col * 16) as usize, (mb_row * 16) as usize),
1738 1 => (true, (mb_col * 16 + 8) as usize, (mb_row * 16) as usize),
1739 2 => (true, (mb_col * 16) as usize, (mb_row * 16 + 8) as usize),
1740 3 => (true, (mb_col * 16 + 8) as usize, (mb_row * 16 + 8) as usize),
1741 _ => (false, (mb_col * 8) as usize, (mb_row * 8) as usize),
1742 };
1743 let stride = if is_luma {
1744 width as usize
1745 } else {
1746 (width / 2) as usize
1747 };
1748 let ph = if is_luma {
1749 height as usize
1750 } else {
1751 (height / 2) as usize
1752 };
1753 (is_luma, bx, by, stride, ph)
1754}
1755
1756fn write_intra_block(
1757 frame: &mut YuvFrame,
1758 mb_row: u32,
1759 mb_col: u32,
1760 blk: usize,
1761 coeff: &[i32; 64],
1762) {
1763 let (is_luma, bx, by, stride, ph) =
1764 block_coords(mb_row, mb_col, blk, frame.width, frame.height);
1765 let plane: &mut Vec<u8> = if is_luma {
1766 &mut frame.y
1767 } else if blk == 4 {
1768 &mut frame.cb
1769 } else {
1770 &mut frame.cr
1771 };
1772 for r in 0..8 {
1773 if by + r >= ph {
1774 break;
1775 }
1776 for c in 0..8 {
1777 if bx + c >= stride {
1778 break;
1779 }
1780 let idx = (by + r) * stride + (bx + c);
1781 plane[idx] = (128 + coeff[r * 8 + c]).clamp(0, 255) as u8;
1782 }
1783 }
1784}
1785
1786fn write_intra_block_unsigned(
1790 frame: &mut YuvFrame,
1791 mb_row: u32,
1792 mb_col: u32,
1793 blk: usize,
1794 coeff: &[i32; 64],
1795) {
1796 let (is_luma, bx, by, stride, ph) =
1797 block_coords(mb_row, mb_col, blk, frame.width, frame.height);
1798 let plane: &mut Vec<u8> = if is_luma {
1799 &mut frame.y
1800 } else if blk == 4 {
1801 &mut frame.cb
1802 } else {
1803 &mut frame.cr
1804 };
1805 for r in 0..8 {
1806 if by + r >= ph {
1807 break;
1808 }
1809 for c in 0..8 {
1810 if bx + c >= stride {
1811 break;
1812 }
1813 let idx = (by + r) * stride + (bx + c);
1814 plane[idx] = coeff[r * 8 + c].clamp(0, 255) as u8;
1815 }
1816 }
1817}
1818
1819#[inline]
1820fn write_block_to_frame(
1821 frame: &mut YuvFrame,
1822 mb_row: usize,
1823 mb_col: usize,
1824 blk: usize,
1825 coeff: &[i32; 64],
1826) {
1827 write_intra_block(frame, mb_row as u32, mb_col as u32, blk, coeff);
1828}
1829
1830fn write_intra_block_i16(
1832 frame: &mut YuvFrame,
1833 mb_row: u32,
1834 mb_col: u32,
1835 blk: usize,
1836 coeff: &[i16; 64],
1837) {
1838 let (is_luma, bx, by, stride, ph) =
1839 block_coords(mb_row, mb_col, blk, frame.width, frame.height);
1840 let plane: &mut Vec<u8> = if is_luma {
1841 &mut frame.y
1842 } else if blk == 4 {
1843 &mut frame.cb
1844 } else {
1845 &mut frame.cr
1846 };
1847 for r in 0..8usize {
1848 if by + r >= ph {
1849 break;
1850 }
1851 for c in 0..8usize {
1852 if bx + c >= stride {
1853 break;
1854 }
1855 let idx = (by + r) * stride + (bx + c);
1856 let v = coeff[r * 8 + c] as i32;
1857 plane[idx] = (v + 128).clamp(0, 255) as u8;
1858 }
1859 }
1860}
1861
1862fn add_residual_block_i16(
1863 frame: &mut YuvFrame,
1864 mb_row: u32,
1865 mb_col: u32,
1866 blk: usize,
1867 coeff: &[i16; 64],
1868) {
1869 let (is_luma, bx, by, stride, ph) =
1870 block_coords(mb_row, mb_col, blk, frame.width, frame.height);
1871 let plane: &mut Vec<u8> = if is_luma {
1872 &mut frame.y
1873 } else if blk == 4 {
1874 &mut frame.cb
1875 } else {
1876 &mut frame.cr
1877 };
1878 for r in 0..8usize {
1879 if by + r >= ph {
1880 break;
1881 }
1882 for c in 0..8usize {
1883 if bx + c >= stride {
1884 break;
1885 }
1886 let idx = (by + r) * stride + (bx + c);
1887 let v = plane[idx] as i32 + coeff[r * 8 + c] as i32;
1888 plane[idx] = v.clamp(0, 255) as u8;
1889 }
1890 }
1891}
1892
1893fn motion_compensate_mb(
1896 dst: &mut YuvFrame,
1897 reference: &YuvFrame,
1898 mb_row: usize,
1899 mb_col: usize,
1900 mvx: i32,
1901 mvy: i32,
1902) {
1903 let fw = dst.width as usize;
1904 let fh = dst.height as usize;
1905 if fw == 0 || fh == 0 {
1906 return;
1907 }
1908 let cw = fw / 2;
1909 let ch = fh / 2;
1910
1911 let dst_x = mb_col * 16;
1913 let dst_y = mb_row * 16;
1914 let src_x = dst_x as i32 * 2 + mvx; let src_y = dst_y as i32 * 2 + mvy;
1916
1917 if reference.y.len() == fw * fh && dst.y.len() == fw * fh {
1918 let mut tmp = [0u8; 256];
1919 mc_luma(&mut tmp, 16, &reference.y, fw, fw, fh, src_x, src_y, 16, 16);
1920 for r in 0..16 {
1921 if dst_y + r >= fh {
1922 break;
1923 }
1924 if dst_x >= fw {
1925 break;
1926 }
1927 let d_off = (dst_y + r) * fw + dst_x;
1928 let s_off = r * 16;
1929 let max = (fw - dst_x).min(16);
1930 dst.y[d_off..d_off + max].copy_from_slice(&tmp[s_off..s_off + max]);
1931 }
1932 }
1933
1934 if reference.cb.len() == cw * ch && dst.cb.len() == cw * ch {
1944 let dst_xc = mb_col * 8;
1945 let dst_yc = mb_row * 8;
1946
1947 let mx = mvx >> 2;
1948 let my = mvy >> 2;
1949 let xh = (mvx & 3) != 0;
1950 let yh = (mvy & 3) != 0;
1951
1952 let src_xc = (dst_xc as i32 + mx) * 2 + if xh { 1 } else { 0 };
1954 let src_yc = (dst_yc as i32 + my) * 2 + if yh { 1 } else { 0 };
1955
1956 let mut tmp_cb = [0u8; 64];
1957 let mut tmp_cr = [0u8; 64];
1958 mc_luma(
1959 &mut tmp_cb,
1960 8,
1961 &reference.cb,
1962 cw,
1963 cw,
1964 ch,
1965 src_xc,
1966 src_yc,
1967 8,
1968 8,
1969 );
1970 mc_luma(
1971 &mut tmp_cr,
1972 8,
1973 &reference.cr,
1974 cw,
1975 cw,
1976 ch,
1977 src_xc,
1978 src_yc,
1979 8,
1980 8,
1981 );
1982
1983 for r in 0..8 {
1984 if dst_yc + r >= ch {
1985 break;
1986 }
1987 if dst_xc >= cw {
1988 break;
1989 }
1990 let d_off = (dst_yc + r) * cw + dst_xc;
1991 let s_off = r * 8;
1992 let max = (cw - dst_xc).min(8);
1993 dst.cb[d_off..d_off + max].copy_from_slice(&tmp_cb[s_off..s_off + max]);
1994 dst.cr[d_off..d_off + max].copy_from_slice(&tmp_cr[s_off..s_off + max]);
1995 }
1996 }
1997}
1998
1999#[inline]
2002fn clip_u8(v: i32) -> u8 {
2003 if v < 0 {
2004 0
2005 } else if v > 255 {
2006 255
2007 } else {
2008 v as u8
2009 }
2010}
2011
2012#[inline]
2013fn rnd_avg_u8(a: u8, b: u8) -> u8 {
2014 ((a as u16 + b as u16 + 1) >> 1) as u8
2015}
2016
2017#[inline]
2018fn no_rnd_avg_u8(a: u8, b: u8) -> u8 {
2019 ((a as u16 + b as u16) >> 1) as u8
2020}
2021
2022fn wmv2_mspel8_h_lowpass(
2023 dst: &mut [u8],
2024 dst_off: usize,
2025 dst_stride: usize,
2026 src: &[u8],
2027 src_off: usize,
2028 src_stride: usize,
2029 h: usize,
2030) {
2031 for i in 0..h {
2032 let so = src_off + i * src_stride;
2033 let doff = dst_off + i * dst_stride;
2034 dst[doff] = clip_u8(
2036 (9 * (src[so] as i32 + src[so + 1] as i32) - (src[so - 1] as i32 + src[so + 2] as i32)
2037 + 8)
2038 >> 4,
2039 );
2040 dst[doff + 1] = clip_u8(
2041 (9 * (src[so + 1] as i32 + src[so + 2] as i32) - (src[so] as i32 + src[so + 3] as i32)
2042 + 8)
2043 >> 4,
2044 );
2045 dst[doff + 2] = clip_u8(
2046 (9 * (src[so + 2] as i32 + src[so + 3] as i32)
2047 - (src[so + 1] as i32 + src[so + 4] as i32)
2048 + 8)
2049 >> 4,
2050 );
2051 dst[doff + 3] = clip_u8(
2052 (9 * (src[so + 3] as i32 + src[so + 4] as i32)
2053 - (src[so + 2] as i32 + src[so + 5] as i32)
2054 + 8)
2055 >> 4,
2056 );
2057 dst[doff + 4] = clip_u8(
2058 (9 * (src[so + 4] as i32 + src[so + 5] as i32)
2059 - (src[so + 3] as i32 + src[so + 6] as i32)
2060 + 8)
2061 >> 4,
2062 );
2063 dst[doff + 5] = clip_u8(
2064 (9 * (src[so + 5] as i32 + src[so + 6] as i32)
2065 - (src[so + 4] as i32 + src[so + 7] as i32)
2066 + 8)
2067 >> 4,
2068 );
2069 dst[doff + 6] = clip_u8(
2070 (9 * (src[so + 6] as i32 + src[so + 7] as i32)
2071 - (src[so + 5] as i32 + src[so + 8] as i32)
2072 + 8)
2073 >> 4,
2074 );
2075 dst[doff + 7] = clip_u8(
2076 (9 * (src[so + 7] as i32 + src[so + 8] as i32)
2077 - (src[so + 6] as i32 + src[so + 9] as i32)
2078 + 8)
2079 >> 4,
2080 );
2081 }
2082}
2083
2084fn wmv2_mspel8_v_lowpass(
2085 dst: &mut [u8],
2086 dst_off: usize,
2087 dst_stride: usize,
2088 src: &[u8],
2089 src_off: usize,
2090 src_stride: usize,
2091 w: usize,
2092) {
2093 for i in 0..w {
2094 let so = src_off + i;
2095 let s_1 = src[so - src_stride] as i32;
2096 let s0 = src[so] as i32;
2097 let s1 = src[so + src_stride] as i32;
2098 let s2 = src[so + 2 * src_stride] as i32;
2099 let s3 = src[so + 3 * src_stride] as i32;
2100 let s4 = src[so + 4 * src_stride] as i32;
2101 let s5 = src[so + 5 * src_stride] as i32;
2102 let s6 = src[so + 6 * src_stride] as i32;
2103 let s7 = src[so + 7 * src_stride] as i32;
2104 let s8 = src[so + 8 * src_stride] as i32;
2105 let s9 = src[so + 9 * src_stride] as i32;
2106
2107 let do0 = dst_off + i + 0 * dst_stride;
2108 let do1 = dst_off + i + dst_stride;
2109 let do2 = dst_off + i + 2 * dst_stride;
2110 let do3 = dst_off + i + 3 * dst_stride;
2111 let do4 = dst_off + i + 4 * dst_stride;
2112 let do5 = dst_off + i + 5 * dst_stride;
2113 let do6 = dst_off + i + 6 * dst_stride;
2114 let do7 = dst_off + i + 7 * dst_stride;
2115
2116 dst[do0] = clip_u8((9 * (s0 + s1) - (s_1 + s2) + 8) >> 4);
2117 dst[do1] = clip_u8((9 * (s1 + s2) - (s0 + s3) + 8) >> 4);
2118 dst[do2] = clip_u8((9 * (s2 + s3) - (s1 + s4) + 8) >> 4);
2119 dst[do3] = clip_u8((9 * (s3 + s4) - (s2 + s5) + 8) >> 4);
2120 dst[do4] = clip_u8((9 * (s4 + s5) - (s3 + s6) + 8) >> 4);
2121 dst[do5] = clip_u8((9 * (s5 + s6) - (s4 + s7) + 8) >> 4);
2122 dst[do6] = clip_u8((9 * (s6 + s7) - (s5 + s8) + 8) >> 4);
2123 dst[do7] = clip_u8((9 * (s7 + s8) - (s6 + s9) + 8) >> 4);
2124 }
2125}
2126
2127#[inline]
2128fn put_pixels8x8(dst: &mut [u8], dst_off: usize, src: &[u8], src_off: usize, stride: usize) {
2129 for y in 0..8 {
2130 let d = dst_off + y * stride;
2131 let s = src_off + y * stride;
2132 dst[d..d + 8].copy_from_slice(&src[s..s + 8]);
2133 }
2134}
2135
2136#[inline]
2137fn put_pixels8_l2_8_no_rnd(
2138 dst: &mut [u8],
2139 dst_off: usize,
2140 src1: &[u8],
2141 src1_off: usize,
2142 src2: &[u8],
2143 src2_off: usize,
2144 dst_stride: usize,
2145 src1_stride: usize,
2146 src2_stride: usize,
2147 h: usize,
2148) {
2149 for y in 0..h {
2150 let d = dst_off + y * dst_stride;
2151 let s1 = src1_off + y * src1_stride;
2152 let s2 = src2_off + y * src2_stride;
2153 for x in 0..8 {
2154 dst[d + x] = no_rnd_avg_u8(src1[s1 + x], src2[s2 + x]);
2155 }
2156 }
2157}
2158
2159fn put_mspel8_mc10(dst: &mut [u8], dst_off: usize, src: &[u8], src_off: usize, stride: usize) {
2160 let mut half = [0u8; 64];
2161 wmv2_mspel8_h_lowpass(&mut half, 0, 8, src, src_off, stride, 8);
2162 put_pixels8_l2_8_no_rnd(dst, dst_off, src, src_off, &half, 0, stride, stride, 8, 8);
2163}
2164
2165fn put_mspel8_mc20(dst: &mut [u8], dst_off: usize, src: &[u8], src_off: usize, stride: usize) {
2166 wmv2_mspel8_h_lowpass(dst, dst_off, stride, src, src_off, stride, 8);
2167}
2168
2169fn put_mspel8_mc30(dst: &mut [u8], dst_off: usize, src: &[u8], src_off: usize, stride: usize) {
2170 let mut half = [0u8; 64];
2171 wmv2_mspel8_h_lowpass(&mut half, 0, 8, src, src_off, stride, 8);
2172 put_pixels8_l2_8_no_rnd(
2173 dst,
2174 dst_off,
2175 src,
2176 src_off + 1,
2177 &half,
2178 0,
2179 stride,
2180 stride,
2181 8,
2182 8,
2183 );
2184}
2185
2186fn put_mspel8_mc02(dst: &mut [u8], dst_off: usize, src: &[u8], src_off: usize, stride: usize) {
2187 wmv2_mspel8_v_lowpass(dst, dst_off, stride, src, src_off, stride, 8);
2188}
2189
2190fn put_mspel8_mc12(dst: &mut [u8], dst_off: usize, src: &[u8], src_off: usize, stride: usize) {
2191 let mut half_h = [0u8; 88];
2192 let mut half_v = [0u8; 64];
2193 let mut half_hv = [0u8; 64];
2194 wmv2_mspel8_h_lowpass(&mut half_h, 0, 8, src, src_off - stride, stride, 11);
2196 wmv2_mspel8_v_lowpass(&mut half_v, 0, 8, src, src_off, stride, 8);
2198 wmv2_mspel8_v_lowpass(&mut half_hv, 0, 8, &half_h, 8, 8, 8);
2200 put_pixels8_l2_8_no_rnd(dst, dst_off, &half_v, 0, &half_hv, 0, stride, 8, 8, 8);
2201}
2202
2203fn put_mspel8_mc22(dst: &mut [u8], dst_off: usize, src: &[u8], src_off: usize, stride: usize) {
2204 let mut half_h = [0u8; 88];
2205 wmv2_mspel8_h_lowpass(&mut half_h, 0, 8, src, src_off - stride, stride, 11);
2206 wmv2_mspel8_v_lowpass(dst, dst_off, stride, &half_h, 8, 8, 8);
2207}
2208
2209fn put_mspel8_mc32(dst: &mut [u8], dst_off: usize, src: &[u8], src_off: usize, stride: usize) {
2210 let mut half_h = [0u8; 88];
2211 let mut half_v = [0u8; 64];
2212 let mut half_hv = [0u8; 64];
2213 wmv2_mspel8_h_lowpass(&mut half_h, 0, 8, src, src_off - stride, stride, 11);
2214 wmv2_mspel8_v_lowpass(&mut half_v, 0, 8, src, src_off + 1, stride, 8);
2215 wmv2_mspel8_v_lowpass(&mut half_hv, 0, 8, &half_h, 8, 8, 8);
2216 put_pixels8_l2_8_no_rnd(dst, dst_off, &half_v, 0, &half_hv, 0, stride, 8, 8, 8);
2217}
2218
2219#[inline]
2220fn wmv2_put_mspel_pixels(
2221 dxy: usize,
2222 dst: &mut [u8],
2223 dst_off: usize,
2224 src: &[u8],
2225 src_off: usize,
2226 stride: usize,
2227) {
2228 match dxy {
2229 0 => put_pixels8x8(dst, dst_off, src, src_off, stride),
2230 1 => put_mspel8_mc10(dst, dst_off, src, src_off, stride),
2231 2 => put_mspel8_mc20(dst, dst_off, src, src_off, stride),
2232 3 => put_mspel8_mc30(dst, dst_off, src, src_off, stride),
2233 4 => put_mspel8_mc02(dst, dst_off, src, src_off, stride),
2234 5 => put_mspel8_mc12(dst, dst_off, src, src_off, stride),
2235 6 => put_mspel8_mc22(dst, dst_off, src, src_off, stride),
2236 7 => put_mspel8_mc32(dst, dst_off, src, src_off, stride),
2237 _ => put_pixels8x8(dst, dst_off, src, src_off, stride),
2238 }
2239}
2240
2241fn emulated_edge_mc(
2242 buf: &mut [u8],
2243 buf_stride: usize,
2244 src: &[u8],
2245 src_stride: usize,
2246 block_w: usize,
2247 block_h: usize,
2248 src_x: i32,
2249 src_y: i32,
2250 h_edge: usize,
2251 v_edge: usize,
2252) {
2253 let max_x = (h_edge as i32 - 1).max(0);
2254 let max_y = (v_edge as i32 - 1).max(0);
2255 for y in 0..block_h {
2256 let sy = (src_y + y as i32).clamp(0, max_y) as usize;
2257 let drow = y * buf_stride;
2258 let srow = sy * src_stride;
2259 for x in 0..block_w {
2260 let sx = (src_x + x as i32).clamp(0, max_x) as usize;
2261 buf[drow + x] = src[srow + sx];
2262 }
2263 }
2264}
2265
2266#[inline]
2267fn chroma_put_pixels(
2268 dst: &mut [u8],
2269 dst_off: usize,
2270 src: &[u8],
2271 src_off: usize,
2272 stride: usize,
2273 h: usize,
2274) {
2275 for y in 0..h {
2276 let d = dst_off + y * stride;
2277 let s = src_off + y * stride;
2278 dst[d..d + 8].copy_from_slice(&src[s..s + 8]);
2279 }
2280}
2281
2282#[inline]
2283fn chroma_put_x2(
2284 dst: &mut [u8],
2285 dst_off: usize,
2286 src: &[u8],
2287 src_off: usize,
2288 stride: usize,
2289 h: usize,
2290) {
2291 for y in 0..h {
2292 let d = dst_off + y * stride;
2293 let s = src_off + y * stride;
2294 for x in 0..8 {
2295 dst[d + x] = rnd_avg_u8(src[s + x], src[s + x + 1]);
2296 }
2297 }
2298}
2299
2300#[inline]
2301fn chroma_put_y2(
2302 dst: &mut [u8],
2303 dst_off: usize,
2304 src: &[u8],
2305 src_off: usize,
2306 stride: usize,
2307 h: usize,
2308) {
2309 for y in 0..h {
2310 let d = dst_off + y * stride;
2311 let s = src_off + y * stride;
2312 let s2 = s + stride;
2313 for x in 0..8 {
2314 dst[d + x] = rnd_avg_u8(src[s + x], src[s2 + x]);
2315 }
2316 }
2317}
2318
2319#[inline]
2320fn chroma_put_xy2(
2321 dst: &mut [u8],
2322 dst_off: usize,
2323 src: &[u8],
2324 src_off: usize,
2325 stride: usize,
2326 h: usize,
2327) {
2328 for y in 0..h {
2329 let d = dst_off + y * stride;
2330 let s = src_off + y * stride;
2331 let s2 = s + stride;
2332 for x in 0..8 {
2333 let a = src[s + x] as u16;
2334 let b = src[s + x + 1] as u16;
2335 let c = src[s2 + x] as u16;
2336 let e = src[s2 + x + 1] as u16;
2337 dst[d + x] = ((a + b + c + e + 2) >> 2) as u8;
2338 }
2339 }
2340}
2341
2342fn wmv2_mspel_motion_mb(
2344 dst: &mut YuvFrame,
2345 reference: &YuvFrame,
2346 mb_row: usize,
2347 mb_col: usize,
2348 motion_x: i32,
2349 motion_y: i32,
2350 hshift: u8,
2351) {
2352 let fw = dst.width as usize;
2353 let fh = dst.height as usize;
2354 if fw == 0 || fh == 0 {
2355 return;
2356 }
2357 let cw = fw / 2;
2358 let ch = fh / 2;
2359
2360 let mut dxy = ((motion_y & 1) << 1) | (motion_x & 1);
2362 dxy = 2 * dxy + hshift as i32;
2363
2364 let mut src_x = mb_col as i32 * 16 + (motion_x >> 1);
2365 let mut src_y = mb_row as i32 * 16 + (motion_y >> 1);
2366
2367 if src_x < -16 {
2369 src_x = -16;
2370 }
2371 if src_x > dst.width as i32 {
2372 src_x = dst.width as i32;
2373 }
2374 if src_y < -16 {
2375 src_y = -16;
2376 }
2377 if src_y > dst.height as i32 {
2378 src_y = dst.height as i32;
2379 }
2380
2381 if src_x <= -16 || src_x >= dst.width as i32 {
2382 dxy &= !3;
2383 }
2384 if src_y <= -16 || src_y >= dst.height as i32 {
2385 dxy &= !4;
2386 }
2387
2388 let linesize = fw;
2389 let mut src_plane: &[u8] = &reference.y;
2390 let src_off: usize;
2391
2392 if src_x < 1
2394 || src_y < 1
2395 || src_x + 17 >= dst.width as i32
2396 || src_y + 16 + 1 >= dst.height as i32
2397 {
2398 let mut edge = vec![0u8; linesize * 19];
2399 emulated_edge_mc(
2400 &mut edge,
2401 linesize,
2402 &reference.y,
2403 linesize,
2404 19,
2405 19,
2406 src_x - 1,
2407 src_y - 1,
2408 fw,
2409 fh,
2410 );
2411 src_plane = edge.as_slice();
2412 src_off = 1 + linesize;
2413 let dst_x = mb_col * 16;
2420 let dst_y = mb_row * 16;
2421 let dxyu = (dxy as usize).min(7);
2422
2423 let dst00 = dst_y * linesize + dst_x;
2425 let src00 = src_off;
2426 wmv2_put_mspel_pixels(dxyu, &mut dst.y, dst00, src_plane, src00, linesize);
2427 wmv2_put_mspel_pixels(dxyu, &mut dst.y, dst00 + 8, src_plane, src00 + 8, linesize);
2428 wmv2_put_mspel_pixels(
2429 dxyu,
2430 &mut dst.y,
2431 dst00 + 8 * linesize,
2432 src_plane,
2433 src00 + 8 * linesize,
2434 linesize,
2435 );
2436 wmv2_put_mspel_pixels(
2437 dxyu,
2438 &mut dst.y,
2439 dst00 + 8 + 8 * linesize,
2440 src_plane,
2441 src00 + 8 + 8 * linesize,
2442 linesize,
2443 );
2444
2445 if dst.cb.is_empty() || reference.cb.is_empty() {
2447 return;
2448 }
2449
2450 let mut cdxy = 0usize;
2451 if (motion_x & 3) != 0 {
2452 cdxy |= 1;
2453 }
2454 if (motion_y & 3) != 0 {
2455 cdxy |= 2;
2456 }
2457 let mx = motion_x >> 2;
2458 let my = motion_y >> 2;
2459
2460 let mut csrc_x = mb_col as i32 * 8 + mx;
2461 let mut csrc_y = mb_row as i32 * 8 + my;
2462
2463 if csrc_x < -8 {
2464 csrc_x = -8;
2465 }
2466 if csrc_x > (dst.width as i32 >> 1) {
2467 csrc_x = dst.width as i32 >> 1;
2468 }
2469 if csrc_y < -8 {
2470 csrc_y = -8;
2471 }
2472 if csrc_y > (dst.height as i32 >> 1) {
2473 csrc_y = dst.height as i32 >> 1;
2474 }
2475
2476 if csrc_x == (dst.width as i32 >> 1) {
2477 cdxy &= !1;
2478 }
2479 if csrc_y == (dst.height as i32 >> 1) {
2480 cdxy &= !2;
2481 }
2482
2483 let uvlinesize = cw;
2484
2485 let mut edge_uv = vec![0u8; uvlinesize * 9];
2486 emulated_edge_mc(
2488 &mut edge_uv,
2489 uvlinesize,
2490 &reference.cb,
2491 uvlinesize,
2492 9,
2493 9,
2494 csrc_x,
2495 csrc_y,
2496 cw,
2497 ch,
2498 );
2499 let dst_xc = mb_col * 8;
2500 let dst_yc = mb_row * 8;
2501 let dst_cb_off = dst_yc * uvlinesize + dst_xc;
2502 match cdxy {
2503 0 => chroma_put_pixels(&mut dst.cb, dst_cb_off, &edge_uv, 0, uvlinesize, 8),
2504 1 => chroma_put_x2(&mut dst.cb, dst_cb_off, &edge_uv, 0, uvlinesize, 8),
2505 2 => chroma_put_y2(&mut dst.cb, dst_cb_off, &edge_uv, 0, uvlinesize, 8),
2506 _ => chroma_put_xy2(&mut dst.cb, dst_cb_off, &edge_uv, 0, uvlinesize, 8),
2507 }
2508
2509 emulated_edge_mc(
2511 &mut edge_uv,
2512 uvlinesize,
2513 &reference.cr,
2514 uvlinesize,
2515 9,
2516 9,
2517 csrc_x,
2518 csrc_y,
2519 cw,
2520 ch,
2521 );
2522 let dst_cr_off = dst_yc * uvlinesize + dst_xc;
2523 match cdxy {
2524 0 => chroma_put_pixels(&mut dst.cr, dst_cr_off, &edge_uv, 0, uvlinesize, 8),
2525 1 => chroma_put_x2(&mut dst.cr, dst_cr_off, &edge_uv, 0, uvlinesize, 8),
2526 2 => chroma_put_y2(&mut dst.cr, dst_cr_off, &edge_uv, 0, uvlinesize, 8),
2527 _ => chroma_put_xy2(&mut dst.cr, dst_cr_off, &edge_uv, 0, uvlinesize, 8),
2528 }
2529 return;
2530 }
2531
2532 src_off = (src_y as usize) * linesize + (src_x as usize);
2534 let dst_x = mb_col * 16;
2535 let dst_y = mb_row * 16;
2536 let dxyu = (dxy as usize).min(7);
2537
2538 let dst00 = dst_y * linesize + dst_x;
2539 wmv2_put_mspel_pixels(dxyu, &mut dst.y, dst00, src_plane, src_off, linesize);
2540 wmv2_put_mspel_pixels(
2541 dxyu,
2542 &mut dst.y,
2543 dst00 + 8,
2544 src_plane,
2545 src_off + 8,
2546 linesize,
2547 );
2548 wmv2_put_mspel_pixels(
2549 dxyu,
2550 &mut dst.y,
2551 dst00 + 8 * linesize,
2552 src_plane,
2553 src_off + 8 * linesize,
2554 linesize,
2555 );
2556 wmv2_put_mspel_pixels(
2557 dxyu,
2558 &mut dst.y,
2559 dst00 + 8 + 8 * linesize,
2560 src_plane,
2561 src_off + 8 + 8 * linesize,
2562 linesize,
2563 );
2564
2565 if dst.cb.is_empty() || reference.cb.is_empty() {
2567 return;
2568 }
2569
2570 let mut cdxy = 0usize;
2571 if (motion_x & 3) != 0 {
2572 cdxy |= 1;
2573 }
2574 if (motion_y & 3) != 0 {
2575 cdxy |= 2;
2576 }
2577 let mx = motion_x >> 2;
2578 let my = motion_y >> 2;
2579
2580 let mut csrc_x = mb_col as i32 * 8 + mx;
2581 let mut csrc_y = mb_row as i32 * 8 + my;
2582
2583 if csrc_x < -8 {
2584 csrc_x = -8;
2585 }
2586 if csrc_x > (dst.width as i32 >> 1) {
2587 csrc_x = dst.width as i32 >> 1;
2588 }
2589 if csrc_y < -8 {
2590 csrc_y = -8;
2591 }
2592 if csrc_y > (dst.height as i32 >> 1) {
2593 csrc_y = dst.height as i32 >> 1;
2594 }
2595
2596 if csrc_x == (dst.width as i32 >> 1) {
2597 cdxy &= !1;
2598 }
2599 if csrc_y == (dst.height as i32 >> 1) {
2600 cdxy &= !2;
2601 }
2602
2603 let uvlinesize = cw;
2604 let need_emu_uv =
2605 csrc_x < 0 || csrc_y < 0 || csrc_x + 9 >= cw as i32 || csrc_y + 9 >= ch as i32;
2606 if need_emu_uv {
2607 let mut edge_uv = vec![0u8; uvlinesize * 9];
2608 let dst_xc = mb_col * 8;
2609 let dst_yc = mb_row * 8;
2610 let dst_cb_off = dst_yc * uvlinesize + dst_xc;
2611 emulated_edge_mc(
2612 &mut edge_uv,
2613 uvlinesize,
2614 &reference.cb,
2615 uvlinesize,
2616 9,
2617 9,
2618 csrc_x,
2619 csrc_y,
2620 cw,
2621 ch,
2622 );
2623 match cdxy {
2624 0 => chroma_put_pixels(&mut dst.cb, dst_cb_off, &edge_uv, 0, uvlinesize, 8),
2625 1 => chroma_put_x2(&mut dst.cb, dst_cb_off, &edge_uv, 0, uvlinesize, 8),
2626 2 => chroma_put_y2(&mut dst.cb, dst_cb_off, &edge_uv, 0, uvlinesize, 8),
2627 _ => chroma_put_xy2(&mut dst.cb, dst_cb_off, &edge_uv, 0, uvlinesize, 8),
2628 }
2629
2630 let dst_cr_off = dst_yc * uvlinesize + dst_xc;
2631 emulated_edge_mc(
2632 &mut edge_uv,
2633 uvlinesize,
2634 &reference.cr,
2635 uvlinesize,
2636 9,
2637 9,
2638 csrc_x,
2639 csrc_y,
2640 cw,
2641 ch,
2642 );
2643 match cdxy {
2644 0 => chroma_put_pixels(&mut dst.cr, dst_cr_off, &edge_uv, 0, uvlinesize, 8),
2645 1 => chroma_put_x2(&mut dst.cr, dst_cr_off, &edge_uv, 0, uvlinesize, 8),
2646 2 => chroma_put_y2(&mut dst.cr, dst_cr_off, &edge_uv, 0, uvlinesize, 8),
2647 _ => chroma_put_xy2(&mut dst.cr, dst_cr_off, &edge_uv, 0, uvlinesize, 8),
2648 }
2649 return;
2650 }
2651 let coff = (csrc_y as usize) * uvlinesize + (csrc_x as usize);
2652 let dst_xc = mb_col * 8;
2653 let dst_yc = mb_row * 8;
2654 let dst_cb_off = dst_yc * uvlinesize + dst_xc;
2655
2656 match cdxy {
2657 0 => chroma_put_pixels(&mut dst.cb, dst_cb_off, &reference.cb, coff, uvlinesize, 8),
2658 1 => chroma_put_x2(&mut dst.cb, dst_cb_off, &reference.cb, coff, uvlinesize, 8),
2659 2 => chroma_put_y2(&mut dst.cb, dst_cb_off, &reference.cb, coff, uvlinesize, 8),
2660 _ => chroma_put_xy2(&mut dst.cb, dst_cb_off, &reference.cb, coff, uvlinesize, 8),
2661 }
2662
2663 let dst_cr_off = dst_yc * uvlinesize + dst_xc;
2664 match cdxy {
2665 0 => chroma_put_pixels(&mut dst.cr, dst_cr_off, &reference.cr, coff, uvlinesize, 8),
2666 1 => chroma_put_x2(&mut dst.cr, dst_cr_off, &reference.cr, coff, uvlinesize, 8),
2667 2 => chroma_put_y2(&mut dst.cr, dst_cr_off, &reference.cr, coff, uvlinesize, 8),
2668 _ => chroma_put_xy2(&mut dst.cr, dst_cr_off, &reference.cr, coff, uvlinesize, 8),
2669 }
2670}
2671
2672fn add_residual_block(
2673 frame: &mut YuvFrame,
2674 mb_row: u32,
2675 mb_col: u32,
2676 blk: usize,
2677 coeff: &[i32; 64],
2678) {
2679 let (is_luma, bx, by, stride, ph) =
2680 block_coords(mb_row, mb_col, blk, frame.width, frame.height);
2681 let plane: &mut Vec<u8> = if is_luma {
2682 &mut frame.y
2683 } else if blk == 4 {
2684 &mut frame.cb
2685 } else {
2686 &mut frame.cr
2687 };
2688 for r in 0..8 {
2689 if by + r >= ph {
2690 break;
2691 }
2692 for c in 0..8 {
2693 if bx + c >= stride {
2694 break;
2695 }
2696 let idx = (by + r) * stride + (bx + c);
2697 plane[idx] = (plane[idx] as i32 + coeff[r * 8 + c]).clamp(0, 255) as u8;
2698 }
2699 }
2700}
2701
2702const FF_RL_MAX_RUN: usize = 64;
2707const FF_RL_MAX_LEVEL: usize = 64;
2708
2709#[derive(Clone)]
2710struct Wmv2Rl {
2711 n: usize,
2712 last: usize,
2713 vlc: VlcTree,
2714 run: &'static [u8],
2715 level: &'static [u8],
2716 max_level: [[u8; FF_RL_MAX_RUN + 1]; 2],
2717 max_run: [[u8; FF_RL_MAX_LEVEL + 1]; 2],
2718}
2719
2720impl Wmv2Rl {
2721 fn new(base: &crate::na_rl_tables::RlBase) -> Self {
2722 let mut t = VlcTree::new();
2723 for (idx, (code, len)) in base.vlc.iter().enumerate() {
2724 if *len != 0 {
2725 t.insert(*code, *len, idx as i32);
2726 }
2727 }
2728
2729 let mut max_level = [[0u8; FF_RL_MAX_RUN + 1]; 2];
2730 let mut max_run = [[0u8; FF_RL_MAX_LEVEL + 1]; 2];
2731
2732 for last_flag in 0..2usize {
2733 let (start, end) = if last_flag == 0 {
2734 (0usize, base.last)
2735 } else {
2736 (base.last, base.n)
2737 };
2738 for i in start..end {
2739 let r = base.run[i] as usize;
2740 let l = base.level[i] as usize;
2741 if r <= FF_RL_MAX_RUN && l <= FF_RL_MAX_LEVEL {
2742 if base.level[i] > max_level[last_flag][r] {
2743 max_level[last_flag][r] = base.level[i];
2744 }
2745 if base.run[i] > max_run[last_flag][l] {
2746 max_run[last_flag][l] = base.run[i];
2747 }
2748 }
2749 }
2750 }
2751
2752 Wmv2Rl {
2753 n: base.n,
2754 last: base.last,
2755 vlc: t,
2756 run: base.run,
2757 level: base.level,
2758 max_level,
2759 max_run,
2760 }
2761 }
2762
2763 #[inline(always)]
2764 fn decode_sym(&self, br: &mut BitReader<'_>, qscale: i32) -> Option<(i32, i32)> {
2765 let idx = self.vlc.decode(br)? as usize;
2766 if idx == self.n {
2767 return Some((0, 66));
2770 }
2771 let (qmul, qadd) = if qscale == 0 {
2772 (1i32, 0i32)
2773 } else {
2774 (qscale * 2, (qscale - 1) | 1)
2775 };
2776 let mut run = (self.run[idx] as i32) + 1;
2777 let level = (self.level[idx] as i32) * qmul + qadd;
2778 if idx >= self.last {
2779 run += 192;
2780 }
2781 Some((level, run))
2782 }
2783
2784 #[inline(always)]
2785 fn max_level_for(&self, last: usize, run: usize) -> i32 {
2786 self.max_level[last.min(1)][run.min(FF_RL_MAX_RUN)] as i32
2787 }
2788
2789 #[inline(always)]
2790 fn max_run_for(&self, last: usize, level: usize) -> i32 {
2791 self.max_run[last.min(1)][level.min(FF_RL_MAX_LEVEL)] as i32
2792 }
2793}
2794
2795#[derive(Clone, Copy, Debug, Default)]
2796struct Vc1MvData {
2797 dx: i32,
2798 dy: i32,
2799 intra: bool,
2800 has_coeffs: bool,
2801}
2802
2803#[inline(always)]
2804fn vc1_dc_scale(q: i32) -> i32 {
2805 const T: [i32; 32] = [
2806 0, 2, 4, 8, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18,
2807 18, 19, 19, 20, 20, 21, 21,
2808 ];
2809 T[q.abs().clamp(1, 31) as usize]
2810}
2811
2812#[inline(always)]
2813fn vc1_decode012_bits(br: &mut BitReader<'_>) -> Result<u8> {
2814 let first = br
2815 .read_bit()
2816 .ok_or_else(|| DecoderError::InvalidData("truncated VC-1 decode012".into()))?;
2817 if !first {
2818 Ok(0)
2819 } else {
2820 Ok(
2821 if br
2822 .read_bit()
2823 .ok_or_else(|| DecoderError::InvalidData("truncated VC-1 decode012".into()))?
2824 {
2825 2
2826 } else {
2827 1
2828 },
2829 )
2830 }
2831}
2832
2833#[inline(always)]
2834fn vc1_decode210_bits(br: &mut BitReader<'_>) -> Result<u8> {
2835 let first = br
2837 .read_bit()
2838 .ok_or_else(|| DecoderError::InvalidData("truncated VC-1 escape selector".into()))?;
2839 if first {
2840 Ok(0)
2841 } else {
2842 Ok(
2843 if br
2844 .read_bit()
2845 .ok_or_else(|| DecoderError::InvalidData("truncated VC-1 escape selector".into()))?
2846 {
2847 1
2848 } else {
2849 2
2850 },
2851 )
2852 }
2853}
2854
2855#[inline(always)]
2856fn vc1_read_unary_stop_one(br: &mut BitReader<'_>, max: u8) -> Result<u8> {
2857 let mut n = 0u8;
2858 while n < max {
2859 if br
2860 .read_bit()
2861 .ok_or_else(|| DecoderError::InvalidData("truncated VC-1 unary".into()))?
2862 {
2863 break;
2864 }
2865 n += 1;
2866 }
2867 Ok(n)
2868}
2869
2870#[inline(always)]
2871fn vc1_scale_level(level: i32, mquant: i32, halfqp: bool, pquantizer: bool) -> i32 {
2872 if level == 0 {
2873 return 0;
2874 }
2875 let quant = mquant.abs().clamp(1, 31);
2876 let scale = quant * 2
2877 + if mquant < 0 {
2878 0
2879 } else if halfqp {
2880 1
2881 } else {
2882 0
2883 };
2884 let mut out = level * scale;
2885 if !pquantizer {
2886 out += if out < 0 { -quant } else { quant };
2887 }
2888 out
2889}
2890
2891#[inline(always)]
2892fn vc1_rescale_dc_pred(v: i32, current_q: i32, neighbour_q: i32) -> i32 {
2893 const DQSCALE: [i32; 63] = [
2894 0x40000, 0x20000, 0x15555, 0x10000, 0x0CCCD, 0x0AAAB, 0x09249, 0x08000, 0x071C7, 0x06666,
2895 0x05D17, 0x05555, 0x04EC5, 0x04925, 0x04444, 0x04000, 0x03C3C, 0x038E4, 0x035E5, 0x03333,
2896 0x030C3, 0x02E8C, 0x02C86, 0x02AAB, 0x028F6, 0x02762, 0x025ED, 0x02492, 0x0234F, 0x02222,
2897 0x02108, 0x02000, 0x01F08, 0x01E1E, 0x01D42, 0x01C72, 0x01BAD, 0x01AF3, 0x01A42, 0x0199A,
2898 0x018FA, 0x01862, 0x017D0, 0x01746, 0x016C1, 0x01643, 0x015CA, 0x01555, 0x014E6, 0x0147B,
2899 0x01414, 0x013B1, 0x01352, 0x012F7, 0x0129E, 0x01249, 0x011F7, 0x011A8, 0x0115B, 0x01111,
2900 0x010C9, 0x01084, 0x01041,
2901 ];
2902 let q1 = current_q.abs().clamp(1, 31);
2903 let q2 = neighbour_q.abs().clamp(1, 31);
2904 if v == 0 || neighbour_q == 0 || q1 == q2 {
2905 return v;
2906 }
2907 let idx = vc1_dc_scale(q1) - 1;
2908 if !(0..63).contains(&idx) {
2909 return v;
2910 }
2911 (((v as i64) * vc1_dc_scale(q2) as i64 * DQSCALE[idx as usize] as i64 + 0x20000) >> 18) as i32
2912}
2913
2914#[inline(always)]
2915fn vc1_rescale_ac_pred(v: i32, current_q: i32, neighbour_q: i32, halfqp: bool) -> i32 {
2916 const DQSCALE: [i32; 63] = [
2917 0x40000, 0x20000, 0x15555, 0x10000, 0x0CCCD, 0x0AAAB, 0x09249, 0x08000, 0x071C7, 0x06666,
2918 0x05D17, 0x05555, 0x04EC5, 0x04925, 0x04444, 0x04000, 0x03C3C, 0x038E4, 0x035E5, 0x03333,
2919 0x030C3, 0x02E8C, 0x02C86, 0x02AAB, 0x028F6, 0x02762, 0x025ED, 0x02492, 0x0234F, 0x02222,
2920 0x02108, 0x02000, 0x01F08, 0x01E1E, 0x01D42, 0x01C72, 0x01BAD, 0x01AF3, 0x01A42, 0x0199A,
2921 0x018FA, 0x01862, 0x017D0, 0x01746, 0x016C1, 0x01643, 0x015CA, 0x01555, 0x014E6, 0x0147B,
2922 0x01414, 0x013B1, 0x01352, 0x012F7, 0x0129E, 0x01249, 0x011F7, 0x011A8, 0x0115B, 0x01111,
2923 0x010C9, 0x01084, 0x01041,
2924 ];
2925 if v == 0 || neighbour_q == 0 || current_q == neighbour_q {
2926 return v;
2927 }
2928 let q1 = current_q.abs() * 2
2929 + if current_q < 0 {
2930 0
2931 } else if halfqp {
2932 1
2933 } else {
2934 0
2935 }
2936 - 1;
2937 let q2 = neighbour_q.abs() * 2
2938 + if neighbour_q < 0 {
2939 0
2940 } else if halfqp {
2941 1
2942 } else {
2943 0
2944 }
2945 - 1;
2946 if !(1..=63).contains(&q1) || q2 < 1 {
2947 return v;
2948 }
2949 (((v as i64) * (q2 as i64) * (DQSCALE[(q1 - 1) as usize] as i64) + 0x20000) >> 18) as i32
2950}
2951
2952#[inline(always)]
2953fn vc1_bfraction_scale(num: i32, den: i32) -> i32 {
2954 match (num, den) {
2960 (1, 2) => 128,
2961 (1, 3) => 85,
2962 (2, 3) => 170,
2963 (1, 4) => 64,
2964 (3, 4) => 192,
2965 (1, 5) => 51,
2966 (2, 5) => 102,
2967 (3, 5) => 153,
2968 (4, 5) => 204,
2969 (1, 6) => 43,
2970 (5, 6) => 215,
2971 (1, 7) => 37,
2972 (2, 7) => 74,
2973 (3, 7) => 111,
2974 (4, 7) => 148,
2975 (5, 7) => 185,
2976 (6, 7) => 222,
2977 (1, 8) => 32,
2978 (3, 8) => 96,
2979 (5, 8) => 160,
2980 (7, 8) => 224,
2981 _ => 0,
2982 }
2983}
2984
2985#[inline(always)]
2986fn vc1_scale_b_mv(value: i32, num: i32, den: i32, inverse: bool, quarter_sample: bool) -> i32 {
2987 let mut n = vc1_bfraction_scale(num, den);
2988 if inverse {
2989 n -= 256;
2990 }
2991 if quarter_sample {
2994 (value * n + 128) >> 8
2995 } else {
2996 2 * ((value * n + 255) >> 9)
2997 }
2998}
2999
3000#[inline(always)]
3001fn vc1_sample_clamped(src: &[u8], stride: usize, w: usize, h: usize, x: i32, y: i32) -> i32 {
3002 if w == 0 || h == 0 || src.is_empty() {
3003 return 0;
3004 }
3005 let xx = x.clamp(0, w as i32 - 1) as usize;
3006 let yy = y.clamp(0, h as i32 - 1) as usize;
3007 src[yy * stride + xx] as i32
3008}
3009
3010#[inline(always)]
3011fn vc1_mspel_raw4(a: i32, b: i32, c: i32, d: i32, mode: i32) -> i32 {
3012 match mode {
3013 1 => -4 * a + 53 * b + 18 * c - 3 * d,
3014 2 => -a + 9 * b + 9 * c - d,
3015 3 => -3 * a + 18 * b + 53 * c - 4 * d,
3016 _ => b,
3017 }
3018}
3019
3020#[inline(always)]
3021fn vc1_mspel_one(a: i32, b: i32, c: i32, d: i32, mode: i32, r: i32) -> i32 {
3022 match mode {
3023 1 | 3 => (vc1_mspel_raw4(a, b, c, d, mode) + 32 - r) >> 6,
3024 2 => (vc1_mspel_raw4(a, b, c, d, mode) + 8 - r) >> 4,
3025 _ => b,
3026 }
3027}
3028
3029fn vc1_mspel_block(
3030 dst: &mut [u8],
3031 dst_stride: usize,
3032 src: &[u8],
3033 src_stride: usize,
3034 sw: usize,
3035 sh: usize,
3036 src_x: i32,
3037 src_y: i32,
3038 bw: usize,
3039 bh: usize,
3040 hmode: i32,
3041 vmode: i32,
3042 rnd: bool,
3043) {
3044 let rnd_i = rnd as i32;
3045
3046 let x0 = src_x as i64;
3052 let y0 = src_y as i64;
3053 let interior_hv =
3054 x0 >= 1 && y0 >= 1 && x0 + bw as i64 + 1 < sw as i64 && y0 + bh as i64 + 1 < sh as i64;
3055 let interior_v =
3056 x0 >= 0 && y0 >= 1 && x0 + bw as i64 <= sw as i64 && y0 + bh as i64 + 1 < sh as i64;
3057 let interior_h =
3058 x0 >= 1 && y0 >= 0 && x0 + bw as i64 + 1 < sw as i64 && y0 + bh as i64 <= sh as i64;
3059 let interior_copy =
3060 x0 >= 0 && y0 >= 0 && x0 + bw as i64 <= sw as i64 && y0 + bh as i64 <= sh as i64;
3061
3062 if hmode != 0 && vmode != 0 {
3063 let shift_value = [0i32, 5, 1, 5];
3064 let shift = (shift_value[hmode as usize] + shift_value[vmode as usize]) >> 1;
3065 let r1 = (1 << (shift - 1)) + rnd_i - 1;
3066 let tw = bw + 3;
3067 let mut tmp_storage = [0i32; 19 * 16];
3071 let tmp = &mut tmp_storage[..tw * bh];
3072
3073 if interior_hv {
3074 let sx = src_x as usize;
3075 let sy = src_y as usize;
3076 for y in 0..bh {
3077 let yy = sy + y;
3078 for tx in 0..tw {
3079 let x = sx + tx - 1;
3080 let raw = vc1_mspel_raw4(
3081 src[(yy - 1) * src_stride + x] as i32,
3082 src[yy * src_stride + x] as i32,
3083 src[(yy + 1) * src_stride + x] as i32,
3084 src[(yy + 2) * src_stride + x] as i32,
3085 vmode,
3086 );
3087 tmp[y * tw + tx] = (raw + r1) >> shift;
3088 }
3089 }
3090 } else {
3091 for y in 0..bh {
3092 for tx in 0..tw {
3093 let x = src_x + tx as i32 - 1;
3094 let yy = src_y + y as i32;
3095 let raw = vc1_mspel_raw4(
3096 vc1_sample_clamped(src, src_stride, sw, sh, x, yy - 1),
3097 vc1_sample_clamped(src, src_stride, sw, sh, x, yy),
3098 vc1_sample_clamped(src, src_stride, sw, sh, x, yy + 1),
3099 vc1_sample_clamped(src, src_stride, sw, sh, x, yy + 2),
3100 vmode,
3101 );
3102 tmp[y * tw + tx] = (raw + r1) >> shift;
3103 }
3104 }
3105 }
3106
3107 let r2 = 64 - rnd_i;
3108 for y in 0..bh {
3109 for x in 0..bw {
3110 let i = y * tw + x;
3111 let raw = vc1_mspel_raw4(tmp[i], tmp[i + 1], tmp[i + 2], tmp[i + 3], hmode);
3112 dst[y * dst_stride + x] = ((raw + r2) >> 7).clamp(0, 255) as u8;
3113 }
3114 }
3115 } else if vmode != 0 {
3116 let r = 1 - rnd_i;
3117 if interior_v {
3118 let sx = src_x as usize;
3119 let sy = src_y as usize;
3120 for y in 0..bh {
3121 let yy = sy + y;
3122 for x in 0..bw {
3123 let xx = sx + x;
3124 let v = vc1_mspel_one(
3125 src[(yy - 1) * src_stride + xx] as i32,
3126 src[yy * src_stride + xx] as i32,
3127 src[(yy + 1) * src_stride + xx] as i32,
3128 src[(yy + 2) * src_stride + xx] as i32,
3129 vmode,
3130 r,
3131 );
3132 dst[y * dst_stride + x] = v.clamp(0, 255) as u8;
3133 }
3134 }
3135 } else {
3136 for y in 0..bh {
3137 for x in 0..bw {
3138 let xx = src_x + x as i32;
3139 let yy = src_y + y as i32;
3140 let v = vc1_mspel_one(
3141 vc1_sample_clamped(src, src_stride, sw, sh, xx, yy - 1),
3142 vc1_sample_clamped(src, src_stride, sw, sh, xx, yy),
3143 vc1_sample_clamped(src, src_stride, sw, sh, xx, yy + 1),
3144 vc1_sample_clamped(src, src_stride, sw, sh, xx, yy + 2),
3145 vmode,
3146 r,
3147 );
3148 dst[y * dst_stride + x] = v.clamp(0, 255) as u8;
3149 }
3150 }
3151 }
3152 } else if hmode != 0 {
3153 let r = rnd_i;
3154 if interior_h {
3155 let sx = src_x as usize;
3156 let sy = src_y as usize;
3157 for y in 0..bh {
3158 let yy = sy + y;
3159 let row = yy * src_stride;
3160 for x in 0..bw {
3161 let xx = sx + x;
3162 let v = vc1_mspel_one(
3163 src[row + xx - 1] as i32,
3164 src[row + xx] as i32,
3165 src[row + xx + 1] as i32,
3166 src[row + xx + 2] as i32,
3167 hmode,
3168 r,
3169 );
3170 dst[y * dst_stride + x] = v.clamp(0, 255) as u8;
3171 }
3172 }
3173 } else {
3174 for y in 0..bh {
3175 for x in 0..bw {
3176 let xx = src_x + x as i32;
3177 let yy = src_y + y as i32;
3178 let v = vc1_mspel_one(
3179 vc1_sample_clamped(src, src_stride, sw, sh, xx - 1, yy),
3180 vc1_sample_clamped(src, src_stride, sw, sh, xx, yy),
3181 vc1_sample_clamped(src, src_stride, sw, sh, xx + 1, yy),
3182 vc1_sample_clamped(src, src_stride, sw, sh, xx + 2, yy),
3183 hmode,
3184 r,
3185 );
3186 dst[y * dst_stride + x] = v.clamp(0, 255) as u8;
3187 }
3188 }
3189 }
3190 } else if interior_copy {
3191 let sx = src_x as usize;
3192 let sy = src_y as usize;
3193 for y in 0..bh {
3194 let src_off = (sy + y) * src_stride + sx;
3195 let dst_off = y * dst_stride;
3196 dst[dst_off..dst_off + bw].copy_from_slice(&src[src_off..src_off + bw]);
3197 }
3198 } else {
3199 for y in 0..bh {
3200 for x in 0..bw {
3201 dst[y * dst_stride + x] =
3202 vc1_sample_clamped(src, src_stride, sw, sh, src_x + x as i32, src_y + y as i32)
3203 as u8;
3204 }
3205 }
3206 }
3207}
3208
3209fn vc1_bilinear_qpel_block(
3210 dst: &mut [u8],
3211 dst_stride: usize,
3212 src: &[u8],
3213 src_stride: usize,
3214 sw: usize,
3215 sh: usize,
3216 src_x: i32,
3217 src_y: i32,
3218 bw: usize,
3219 bh: usize,
3220 fx: i32,
3221 fy: i32,
3222 denom: i32,
3223 rnd: bool,
3224) {
3225 let add = if denom == 8 && rnd {
3229 28
3230 } else {
3231 (denom * denom) / 2 - rnd as i32
3232 };
3233 let denom2 = denom * denom;
3234 let x0 = src_x as i64;
3235 let y0 = src_y as i64;
3236 let interior =
3237 x0 >= 0 && y0 >= 0 && x0 + (bw as i64) < sw as i64 && y0 + (bh as i64) < sh as i64;
3238
3239 if interior {
3240 let sx = src_x as usize;
3241 let sy = src_y as usize;
3242 let wa = (denom - fx) * (denom - fy);
3243 let wb = fx * (denom - fy);
3244 let wc = (denom - fx) * fy;
3245 let wd = fx * fy;
3246 for y in 0..bh {
3247 let row0 = (sy + y) * src_stride + sx;
3248 let row1 = row0 + src_stride;
3249 let dst_row = y * dst_stride;
3250 for x in 0..bw {
3251 let v = src[row0 + x] as i32 * wa
3252 + src[row0 + x + 1] as i32 * wb
3253 + src[row1 + x] as i32 * wc
3254 + src[row1 + x + 1] as i32 * wd;
3255 dst[dst_row + x] = ((v + add) / denom2).clamp(0, 255) as u8;
3256 }
3257 }
3258 } else {
3259 for y in 0..bh {
3260 for x in 0..bw {
3261 let xx = src_x + x as i32;
3262 let yy = src_y + y as i32;
3263 let a = vc1_sample_clamped(src, src_stride, sw, sh, xx, yy);
3264 let b = vc1_sample_clamped(src, src_stride, sw, sh, xx + 1, yy);
3265 let c = vc1_sample_clamped(src, src_stride, sw, sh, xx, yy + 1);
3266 let d = vc1_sample_clamped(src, src_stride, sw, sh, xx + 1, yy + 1);
3267 let v = a * (denom - fx) * (denom - fy)
3268 + b * fx * (denom - fy)
3269 + c * (denom - fx) * fy
3270 + d * fx * fy;
3271 dst[y * dst_stride + x] = ((v + add) / denom2).clamp(0, 255) as u8;
3272 }
3273 }
3274 }
3275}
3276
3277fn vc1_ic_value(v: u8, lumscale: u8, lumshift: u8, chroma: bool) -> u8 {
3278 let (scale, shift) = if lumscale == 0 {
3279 let mut sh = (255 - 2 * lumshift as i32) << 6;
3280 if lumshift > 31 {
3281 sh += 128 << 6;
3282 }
3283 (-64, sh)
3284 } else {
3285 let sh = if lumshift > 31 {
3286 (lumshift as i32 - 64) << 6
3287 } else {
3288 (lumshift as i32) << 6
3289 };
3290 (lumscale as i32 + 32, sh)
3291 };
3292 if chroma {
3299 ((scale * (v as i32 - 128) + (128 << 6) + 32) >> 6).clamp(0, 255) as u8
3300 } else {
3301 ((scale * v as i32 + shift + 32) >> 6).clamp(0, 255) as u8
3302 }
3303}
3304
3305fn vc1_apply_ic_reference(frame: &mut YuvFrame, lumscale: u8, lumshift: u8) {
3312 for v in &mut frame.y {
3313 *v = vc1_ic_value(*v, lumscale, lumshift, false);
3314 }
3315 for v in &mut frame.cb {
3316 *v = vc1_ic_value(*v, lumscale, lumshift, true);
3317 }
3318 for v in &mut frame.cr {
3319 *v = vc1_ic_value(*v, lumscale, lumshift, true);
3320 }
3321}
3322
3323pub struct MacroblockDecoder {
3324 pub width: u32,
3325 pub height: u32,
3326 pub width_mb: u32,
3327 pub height_mb: u32,
3328 pub ref_frame: Option<YuvFrame>,
3330 vc1_ac: [Vc1AcTable; 8],
3332 vc1_cbpcy: [VlcTable; 4],
3333 vc1_mvdata: [VlcTable; 4],
3334 vc1_ttmb: [VlcTable; 3],
3335 vc1_ttblk: [VlcTable; 3],
3336 vc1_subblkpat: [VlcTable; 3],
3337 vc1_esc3_level_length: u8,
3338 vc1_esc3_run_length: u8,
3339 vc1_coded_block: Vec<u8>,
3340 vc1_dc: Vec<[i32; 6]>,
3341 vc1_intra_blocks: Vec<[bool; 6]>,
3342 vc1_recon_blocks: Vec<[i32; 64]>,
3345 vc1_block_cbp: Vec<[u8; 6]>,
3347 vc1_block_tt: Vec<[u8; 6]>,
3349 vc1_qscale: Vec<i32>,
3350 vc1_overflags: Vec<u8>,
3352 vc1_current_mvs: Vec<(i32, i32)>,
3353 vc1_mv4: Vec<[(i32, i32); 4]>,
3354 vc1_chroma_mvs: Vec<(i32, i32)>,
3356 mv_pred: MvPredictor,
3357 vc1_bwd_anchor_mvs: Option<Vec<(i32, i32)>>,
3358 vc1_fwd_anchor_mvs: Option<Vec<(i32, i32)>>,
3359 vc1_rnd: bool,
3360 wmv2_inter: [VlcTable; 2], wmv2_intra: [VlcTable; 2],
3363 wmv2_cbpy: VlcTable,
3364 wmv2_cbpc: VlcTable,
3365 wmv2_ref: Option<YuvFrame>,
3367 wmv2_mb_i_vlc: VlcTree,
3369 wmv2_dc_vlc: [[VlcTree; 2]; 2], wmv2_coded_block: Vec<u8>, wmv2_dc_pred: Wmv2DcPredBuffer,
3372 wmv2_mspel_bit: bool,
3374 wmv2_abt_flag: bool,
3375 wmv2_j_type_bit: bool,
3376 wmv2_top_left_mv_flag: bool,
3377 wmv2_per_mb_rl_bit: bool,
3378 wmv2_j_type: bool,
3380 wmv2_per_mb_rl_table: bool,
3381 wmv2_rl_table_index: u8,
3382 wmv2_rl_chroma_table_index: u8,
3383 wmv2_dc_table_index: usize,
3384
3385 wmv2_cbp_table_index: usize,
3387 wmv2_mv_table_index: usize,
3388 wmv2_mspel: bool,
3389 wmv2_hshift: u8,
3390 wmv2_per_mb_abt: bool,
3391 wmv2_abt_type: u8,
3392 wmv2_skip_type: u8,
3393 wmv2_slice_height: usize,
3394 wmv2_mb_skip: Vec<bool>,
3395 wmv2_motion: Vec<(i32, i32)>,
3396
3397 wmv2_mb_non_intra_vlc: [VlcTree; 4],
3399 wmv2_mv_vlc: [VlcTree; 2],
3400 wmv2_rl: [Wmv2Rl; 6],
3402 wmv2_esc3_level_length: u8,
3404 wmv2_esc3_run_length: u8,
3405 wmv2_ac_val: Vec<[i16; 16]>,
3407 ac_pred: AcPredBuffer,
3408 fwd_ref: Option<YuvFrame>,
3410 bwd_ref: Option<YuvFrame>,
3412 vc1_b_fwd_ic: Option<(u8, u8)>,
3418}
3419
3420impl MacroblockDecoder {
3421 pub fn new(width: u32, height: u32) -> Self {
3422 let mb_w = width.div_ceil(16) as usize;
3423 let mb_h = height.div_ceil(16) as usize;
3424
3425 let wmv2_mb_i_vlc: VlcTree = {
3427 let mut t = VlcTree::new();
3428 for (sym, (code, len)) in FF_MSMP4_MB_I_TABLE.iter().enumerate() {
3429 t.insert(*code, *len, sym as i32);
3430 }
3431 t
3432 };
3433
3434 let wmv2_dc_vlc: [[VlcTree; 2]; 2] = std::array::from_fn(|ti| {
3435 std::array::from_fn(|ch| {
3436 let mut t = VlcTree::new();
3437 for (sym, (code, len)) in FF_MSMP4_DC_TABLES[ti][ch].iter().enumerate() {
3438 t.insert(*code, *len, sym as i32);
3439 }
3440 t
3441 })
3442 });
3443
3444 let wmv2_mb_non_intra_vlc: [VlcTree; 4] = std::array::from_fn(|ti| {
3446 let mut t = VlcTree::new();
3447 for (sym, (code, len)) in FF_MB_NON_INTRA_TABLES[ti].iter().enumerate() {
3448 if *len != 0 {
3449 t.insert(*code, *len, sym as i32);
3450 }
3451 }
3452 t
3453 });
3454
3455 let build_mv_from_lengths = |lens: &[u8; 1100], syms: &[u16; 1100]| -> VlcTree {
3459 let mut t = VlcTree::new();
3460 let mut code: u32 = 0;
3461 for i in 0..1100usize {
3462 let len = lens[i] as i32;
3463 if len == 0 {
3464 continue;
3465 }
3466 let l = len.unsigned_abs() as u8;
3467 let right_aligned = if l == 0 { 0 } else { code >> (32 - l) };
3469 if len > 0 {
3470 t.insert(right_aligned, l, syms[i] as i32);
3471 }
3472 code = code.wrapping_add(1u32 << (32 - l));
3473 }
3474 t
3475 };
3476 let wmv2_mv_vlc: [VlcTree; 2] = [
3477 build_mv_from_lengths(&FF_MSMP4_MV_TABLE0_LENS, &FF_MSMP4_MV_TABLE0),
3478 build_mv_from_lengths(&FF_MSMP4_MV_TABLE1_LENS, &FF_MSMP4_MV_TABLE1),
3479 ];
3480
3481 let wmv2_rl: [Wmv2Rl; 6] = std::array::from_fn(|i| Wmv2Rl::new(&FF_RL_BASES[i]));
3483 let wmv2_ac_val: Vec<[i16; 16]> = vec![[0i16; 16]; mb_w * mb_h * 6];
3484
3485 MacroblockDecoder {
3486 width,
3487 height,
3488 width_mb: width.div_ceil(16),
3489 height_mb: height.div_ceil(16),
3490 ref_frame: None,
3491 vc1_ac: ac_tables(),
3492 vc1_cbpcy: cbpcy_vlcs(),
3493 vc1_mvdata: mvdata_vlcs(),
3494 vc1_ttmb: ttmb_vlcs(),
3495 vc1_ttblk: ttblk_vlcs(),
3496 vc1_subblkpat: subblkpat_vlcs(),
3497 vc1_esc3_level_length: 0,
3498 vc1_esc3_run_length: 0,
3499 vc1_coded_block: vec![0u8; (2 * mb_w) * (2 * mb_h)],
3500 vc1_dc: vec![[0i32; 6]; mb_w * mb_h],
3501 vc1_intra_blocks: vec![[false; 6]; mb_w * mb_h],
3502 vc1_recon_blocks: vec![[0i32; 64]; mb_w * mb_h * 6],
3503 vc1_block_cbp: vec![[0u8; 6]; mb_w * mb_h],
3504 vc1_block_tt: vec![[0u8; 6]; mb_w * mb_h],
3505 vc1_qscale: vec![0i32; mb_w * mb_h],
3506 vc1_overflags: vec![0u8; mb_w * mb_h],
3507 vc1_current_mvs: vec![(0, 0); mb_w * mb_h],
3508 vc1_mv4: vec![[(0, 0); 4]; mb_w * mb_h],
3509 vc1_chroma_mvs: vec![(0, 0); mb_w * mb_h],
3510 mv_pred: MvPredictor::new(mb_w, mb_h),
3511 vc1_bwd_anchor_mvs: None,
3512 vc1_fwd_anchor_mvs: None,
3513 vc1_rnd: false,
3514 ac_pred: AcPredBuffer::new(mb_w, mb_h),
3515 fwd_ref: None,
3516 bwd_ref: None,
3517 vc1_b_fwd_ic: None,
3518 wmv2_inter: [wmv2_tcoef_inter_vlc(0), wmv2_tcoef_inter_vlc(1)],
3519 wmv2_intra: [wmv2_tcoef_intra_vlc(0), wmv2_tcoef_intra_vlc(1)],
3520 wmv2_cbpy: wmv2_cbpy_vlc(),
3521 wmv2_cbpc: wmv2_cbpc_p_vlc(),
3522 wmv2_ref: None,
3523
3524 wmv2_mb_i_vlc,
3526 wmv2_dc_vlc,
3527 wmv2_coded_block: vec![0u8; (2 * mb_w) * (2 * mb_h)],
3528 wmv2_dc_pred: Wmv2DcPredBuffer::new(mb_w, mb_h),
3529
3530 wmv2_mspel_bit: false,
3532 wmv2_abt_flag: false,
3533 wmv2_j_type_bit: false,
3534 wmv2_top_left_mv_flag: false,
3535 wmv2_per_mb_rl_bit: false,
3536
3537 wmv2_j_type: false,
3539 wmv2_per_mb_rl_table: false,
3540 wmv2_rl_table_index: 0,
3541 wmv2_rl_chroma_table_index: 0,
3542 wmv2_dc_table_index: 0,
3543
3544 wmv2_cbp_table_index: 0,
3545 wmv2_mv_table_index: 0,
3546 wmv2_mspel: false,
3547 wmv2_hshift: 0,
3548 wmv2_per_mb_abt: false,
3549 wmv2_abt_type: 0,
3550 wmv2_skip_type: 0,
3551 wmv2_slice_height: mb_h.max(1),
3552 wmv2_mb_skip: vec![false; mb_w * mb_h],
3553 wmv2_motion: vec![(0, 0); mb_w * mb_h],
3554
3555 wmv2_mb_non_intra_vlc,
3556 wmv2_mv_vlc,
3557
3558 wmv2_rl,
3559 wmv2_esc3_level_length: 0,
3560 wmv2_esc3_run_length: 0,
3561 wmv2_ac_val,
3562 }
3563 }
3564
3565 pub fn decode_frame(
3566 &mut self,
3567 payload: &[u8],
3568 pic_hdr: &PictureHeader,
3569 seq: &SequenceHeader,
3570 frame: &mut YuvFrame,
3571 ) -> Result<()> {
3572 if let Some(rnd) = pic_hdr.rnd {
3573 self.vc1_rnd = rnd;
3576 } else {
3577 match pic_hdr.frame_type {
3578 FrameType::I | FrameType::BI => self.vc1_rnd = true,
3579 FrameType::P => self.vc1_rnd = !self.vc1_rnd,
3580 _ => {}
3581 }
3582 }
3583
3584 match pic_hdr.frame_type {
3585 FrameType::I | FrameType::BI => {
3586 self.decode_intra(payload, pic_hdr, seq, frame)?;
3587 self.vc1_finish_i_reconstruction(frame, pic_hdr, seq);
3588 if seq.loop_filter {
3589 vc1_apply_i_loop_filter(
3590 frame,
3591 pic_hdr.pquant as i32,
3592 self.width_mb as usize,
3593 self.height_mb as usize,
3594 );
3595 }
3596 }
3597 FrameType::P => {
3598 self.decode_p(payload, pic_hdr, seq, frame)?;
3599 self.vc1_finish_p_reconstruction(frame, pic_hdr, seq);
3600 if seq.loop_filter {
3601 self.vc1_apply_p_loop_filter(frame, pic_hdr.pquant as i32);
3602 }
3603 }
3604 FrameType::B => {
3605 self.decode_b(payload, pic_hdr, seq, frame)?;
3606 if seq.loop_filter {
3609 vc1_apply_i_loop_filter(
3610 frame,
3611 pic_hdr.pquant as i32,
3612 self.width_mb as usize,
3613 self.height_mb as usize,
3614 );
3615 }
3616 }
3617 FrameType::Skipped => {
3618 if let Some(ref rf) = self.ref_frame {
3619 frame.y.copy_from_slice(&rf.y);
3620 frame.cb.copy_from_slice(&rf.cb);
3621 frame.cr.copy_from_slice(&rf.cr);
3622 }
3623 }
3624 }
3625
3626 match pic_hdr.frame_type {
3630 FrameType::B | FrameType::BI => {}
3631 _ => {
3632 self.fwd_ref = self.bwd_ref.take();
3633 self.bwd_ref = Some(frame.clone());
3634 self.ref_frame = Some(frame.clone());
3635 self.vc1_fwd_anchor_mvs = self.vc1_bwd_anchor_mvs.take();
3636 self.vc1_bwd_anchor_mvs = Some(self.vc1_current_mvs.clone());
3637
3638 self.vc1_b_fwd_ic = if pic_hdr.frame_type == FrameType::P
3643 && pic_hdr.mv_mode == MvMode::IntensityComp
3644 {
3645 Some((pic_hdr.lumscale, pic_hdr.lumshift))
3646 } else {
3647 None
3648 };
3649 }
3650 }
3651 Ok(())
3652 }
3653
3654 fn vc1_reset_picture_state(&mut self) {
3657 self.vc1_coded_block.fill(0);
3658 self.vc1_dc.fill([0; 6]);
3659 self.vc1_intra_blocks.fill([false; 6]);
3660 self.vc1_recon_blocks.fill([0; 64]);
3661 self.vc1_block_cbp.fill([0; 6]);
3662 self.vc1_block_tt.fill([0; 6]);
3663 self.vc1_qscale.fill(0);
3664 self.vc1_overflags.fill(0);
3665 self.vc1_current_mvs.fill((0, 0));
3666 self.vc1_mv4.fill([(0, 0); 4]);
3667 self.vc1_chroma_mvs.fill((0, 0));
3668 self.vc1_esc3_level_length = 0;
3669 self.vc1_esc3_run_length = 0;
3670 self.ac_pred.clear();
3671 }
3672
3673 fn vc1_finish_i_reconstruction(
3674 &mut self,
3675 frame: &mut YuvFrame,
3676 pic: &PictureHeader,
3677 seq: &SequenceHeader,
3678 ) {
3679 let mb_w = self.width_mb as usize;
3680 let mb_h = self.height_mb as usize;
3681
3682 if seq.profile == Profile::Advanced {
3683 if seq.overlap {
3689 if pic.pquant >= 9 || pic.condover == 1 {
3690 vc1_apply_signed_overlap(
3691 &mut self.vc1_recon_blocks,
3692 &self.vc1_intra_blocks,
3693 mb_w,
3694 mb_h,
3695 false,
3696 );
3697 } else if pic.condover == 2 {
3698 vc1_apply_advanced_selective_i_overlap(
3699 &mut self.vc1_recon_blocks,
3700 mb_w,
3701 mb_h,
3702 &self.vc1_overflags,
3703 );
3704 }
3705 }
3706
3707 for r in 0..mb_h {
3708 for c in 0..mb_w {
3709 for blk in 0..6usize {
3710 let ri = vc1_recon_index(mb_w, r, c, blk);
3711 write_intra_block(
3712 frame,
3713 r as u32,
3714 c as u32,
3715 blk,
3716 &self.vc1_recon_blocks[ri],
3717 );
3718 }
3719 }
3720 }
3721 return;
3722 }
3723
3724 let overlap = seq.overlap && pic.pquant >= 9;
3725
3726 if overlap {
3727 vc1_apply_signed_overlap(
3728 &mut self.vc1_recon_blocks,
3729 &self.vc1_intra_blocks,
3730 mb_w,
3731 mb_h,
3732 pic.rangeredfrm,
3733 );
3734 }
3735
3736 for r in 0..mb_h {
3741 for c in 0..mb_w {
3742 for blk in 0..6usize {
3743 let ri = vc1_recon_index(mb_w, r, c, blk);
3744 let block = &mut self.vc1_recon_blocks[ri];
3745 if pic.rangeredfrm && !overlap {
3746 for v in block.iter_mut() {
3747 *v = (*v - 64) * 2;
3748 }
3749 }
3750 if overlap {
3751 write_intra_block(frame, r as u32, c as u32, blk, block);
3752 } else {
3753 write_intra_block_unsigned(frame, r as u32, c as u32, blk, block);
3754 }
3755 }
3756 }
3757 }
3758 }
3759
3760 fn vc1_finish_p_reconstruction(
3761 &mut self,
3762 frame: &mut YuvFrame,
3763 pic: &PictureHeader,
3764 seq: &SequenceHeader,
3765 ) {
3766 let mb_w = self.width_mb as usize;
3767 let mb_h = self.height_mb as usize;
3768
3769 if seq.overlap && pic.pquant >= 9 {
3774 vc1_apply_signed_overlap(
3775 &mut self.vc1_recon_blocks,
3776 &self.vc1_intra_blocks,
3777 mb_w,
3778 mb_h,
3779 false,
3780 );
3781 }
3782
3783 for r in 0..mb_h {
3784 for c in 0..mb_w {
3785 let mbi = r * mb_w + c;
3786 for blk in 0..6usize {
3787 if !self.vc1_intra_blocks[mbi][blk] {
3788 continue;
3789 }
3790 let ri = vc1_recon_index(mb_w, r, c, blk);
3791 write_intra_block(frame, r as u32, c as u32, blk, &self.vc1_recon_blocks[ri]);
3792 }
3793 }
3794 }
3795 }
3796
3797 #[inline]
3798 fn vc1_p_loop_meta(
3799 &self,
3800 plane: usize,
3801 block_x: usize,
3802 block_y: usize,
3803 ) -> (bool, u8, u8, (i32, i32)) {
3804 let mb_w = self.width_mb as usize;
3805 if plane == 0 {
3806 let mb_col = block_x / 2;
3807 let mb_row = block_y / 2;
3808 let blk = (block_y & 1) * 2 + (block_x & 1);
3809 let mbi = mb_row * mb_w + mb_col;
3810 (
3811 self.vc1_intra_blocks[mbi][blk],
3812 self.vc1_block_cbp[mbi][blk],
3813 self.vc1_block_tt[mbi][blk],
3814 self.vc1_mv4[mbi][blk],
3815 )
3816 } else {
3817 let blk = if plane == 1 { 4 } else { 5 };
3818 let mbi = block_y * mb_w + block_x;
3819 (
3820 self.vc1_intra_blocks[mbi][blk],
3821 self.vc1_block_cbp[mbi][blk],
3822 self.vc1_block_tt[mbi][blk],
3823 self.vc1_chroma_mvs[mbi],
3824 )
3825 }
3826 }
3827
3828 #[inline]
3829 fn vc1_p_v_loop_filter_block(
3830 &self,
3831 plane: &mut [u8],
3832 width: usize,
3833 height: usize,
3834 plane_no: usize,
3835 bx: usize,
3836 by: usize,
3837 pq: i32,
3838 ) {
3839 let blocks_w = if plane_no == 0 {
3840 self.width_mb as usize * 2
3841 } else {
3842 self.width_mb as usize
3843 };
3844 let blocks_h = if plane_no == 0 {
3845 self.height_mb as usize * 2
3846 } else {
3847 self.height_mb as usize
3848 };
3849 if bx >= blocks_w || by >= blocks_h {
3850 return;
3851 }
3852
3853 let x0 = bx * 8;
3854 let y0 = by * 8;
3855 if x0 >= width || y0 >= height {
3856 return;
3857 }
3858 let top = self.vc1_p_loop_meta(plane_no, bx, by);
3859
3860 if by + 1 < blocks_h && (by + 1) * 8 < height {
3862 let bottom = self.vc1_p_loop_meta(plane_no, bx, by + 1);
3863 let edge_y = (by + 1) * 8;
3864 if top.0 || bottom.0 || top.3 != bottom.3 {
3865 vc1_filter_horizontal_boundary(plane, width, height, x0, edge_y, 8, pq);
3866 } else {
3867 let idx = (top.1 | (bottom.1 >> 2)) & 3;
3868 if (idx & 1) != 0 {
3869 vc1_filter_horizontal_boundary(plane, width, height, x0 + 4, edge_y, 4, pq);
3870 }
3871 if (idx & 2) != 0 {
3872 vc1_filter_horizontal_boundary(plane, width, height, x0, edge_y, 4, pq);
3873 }
3874 }
3875 }
3876
3877 if matches!(top.2, TT_4X4 | TT_8X4) {
3879 let edge_y = y0 + 4;
3880 if edge_y < height {
3881 if (top.1 & 5) != 0 {
3882 vc1_filter_horizontal_boundary(plane, width, height, x0 + 4, edge_y, 4, pq);
3883 }
3884 if (top.1 & 10) != 0 {
3885 vc1_filter_horizontal_boundary(plane, width, height, x0, edge_y, 4, pq);
3886 }
3887 }
3888 }
3889 }
3890
3891 #[inline]
3892 fn vc1_p_h_loop_filter_block(
3893 &self,
3894 plane: &mut [u8],
3895 width: usize,
3896 height: usize,
3897 plane_no: usize,
3898 bx: usize,
3899 by: usize,
3900 pq: i32,
3901 ) {
3902 let blocks_w = if plane_no == 0 {
3903 self.width_mb as usize * 2
3904 } else {
3905 self.width_mb as usize
3906 };
3907 let blocks_h = if plane_no == 0 {
3908 self.height_mb as usize * 2
3909 } else {
3910 self.height_mb as usize
3911 };
3912 if bx >= blocks_w || by >= blocks_h {
3913 return;
3914 }
3915
3916 let x0 = bx * 8;
3917 let y0 = by * 8;
3918 if x0 >= width || y0 >= height {
3919 return;
3920 }
3921 let left = self.vc1_p_loop_meta(plane_no, bx, by);
3922
3923 if bx + 1 < blocks_w && (bx + 1) * 8 < width {
3925 let right = self.vc1_p_loop_meta(plane_no, bx + 1, by);
3926 let edge_x = (bx + 1) * 8;
3927 if left.0 || right.0 || left.3 != right.3 {
3928 vc1_filter_vertical_boundary(plane, width, height, edge_x, y0, 8, pq);
3929 } else {
3930 let idx = (left.1 | (right.1 >> 1)) & 5;
3931 if (idx & 1) != 0 {
3932 vc1_filter_vertical_boundary(plane, width, height, edge_x, y0 + 4, 4, pq);
3933 }
3934 if (idx & 4) != 0 {
3935 vc1_filter_vertical_boundary(plane, width, height, edge_x, y0, 4, pq);
3936 }
3937 }
3938 }
3939
3940 if matches!(left.2, TT_4X4 | TT_4X8) {
3942 let edge_x = x0 + 4;
3943 if edge_x < width {
3944 if (left.1 & 3) != 0 {
3945 vc1_filter_vertical_boundary(plane, width, height, edge_x, y0 + 4, 4, pq);
3946 }
3947 if (left.1 & 12) != 0 {
3948 vc1_filter_vertical_boundary(plane, width, height, edge_x, y0, 4, pq);
3949 }
3950 }
3951 }
3952 }
3953
3954 fn vc1_p_v_loop_filter_mb(&self, frame: &mut YuvFrame, mb_row: usize, mb_col: usize, pq: i32) {
3955 let w = frame.width as usize;
3956 let h = frame.height as usize;
3957 for local_y in 0..2 {
3958 for local_x in 0..2 {
3959 self.vc1_p_v_loop_filter_block(
3960 &mut frame.y,
3961 w,
3962 h,
3963 0,
3964 mb_col * 2 + local_x,
3965 mb_row * 2 + local_y,
3966 pq,
3967 );
3968 }
3969 }
3970
3971 let cw = w / 2;
3972 let ch = h / 2;
3973 self.vc1_p_v_loop_filter_block(&mut frame.cb, cw, ch, 1, mb_col, mb_row, pq);
3974 self.vc1_p_v_loop_filter_block(&mut frame.cr, cw, ch, 2, mb_col, mb_row, pq);
3975 }
3976
3977 fn vc1_p_h_loop_filter_mb(&self, frame: &mut YuvFrame, mb_row: usize, mb_col: usize, pq: i32) {
3978 let w = frame.width as usize;
3979 let h = frame.height as usize;
3980 for local_y in 0..2 {
3981 for local_x in 0..2 {
3982 self.vc1_p_h_loop_filter_block(
3983 &mut frame.y,
3984 w,
3985 h,
3986 0,
3987 mb_col * 2 + local_x,
3988 mb_row * 2 + local_y,
3989 pq,
3990 );
3991 }
3992 }
3993
3994 let cw = w / 2;
3995 let ch = h / 2;
3996 self.vc1_p_h_loop_filter_block(&mut frame.cb, cw, ch, 1, mb_col, mb_row, pq);
3997 self.vc1_p_h_loop_filter_block(&mut frame.cr, cw, ch, 2, mb_col, mb_row, pq);
3998 }
3999
4000 fn vc1_apply_p_loop_filter(&self, frame: &mut YuvFrame, pq: i32) {
4005 let mb_width = self.width_mb as usize;
4006 let mb_height = self.height_mb as usize;
4007 if mb_width == 0 || mb_height == 0 {
4008 return;
4009 }
4010
4011 for cur_y in 0..mb_height {
4012 for cur_x in 0..mb_width {
4013 if cur_y >= 2 {
4015 if cur_x >= 1 {
4016 self.vc1_p_v_loop_filter_mb(frame, cur_y - 2, cur_x - 1, pq);
4017 }
4018 if cur_x + 1 == mb_width {
4019 self.vc1_p_v_loop_filter_mb(frame, cur_y - 2, cur_x, pq);
4020 }
4021 }
4022 if cur_y + 1 == mb_height {
4023 if cur_x >= 1 {
4024 if cur_y >= 1 {
4025 self.vc1_p_v_loop_filter_mb(frame, cur_y - 1, cur_x - 1, pq);
4026 }
4027 self.vc1_p_v_loop_filter_mb(frame, cur_y, cur_x - 1, pq);
4028 }
4029 if cur_x + 1 == mb_width {
4030 if cur_y >= 1 {
4031 self.vc1_p_v_loop_filter_mb(frame, cur_y - 1, cur_x, pq);
4032 }
4033 self.vc1_p_v_loop_filter_mb(frame, cur_y, cur_x, pq);
4034 }
4035 }
4036
4037 if cur_y >= 2 {
4039 if cur_x >= 2 {
4040 self.vc1_p_h_loop_filter_mb(frame, cur_y - 2, cur_x - 2, pq);
4041 }
4042 if cur_x + 1 == mb_width {
4043 if cur_x >= 1 {
4044 self.vc1_p_h_loop_filter_mb(frame, cur_y - 2, cur_x - 1, pq);
4045 }
4046 self.vc1_p_h_loop_filter_mb(frame, cur_y - 2, cur_x, pq);
4047 }
4048 }
4049 if cur_y + 1 == mb_height {
4050 if cur_y >= 1 {
4051 if cur_x >= 2 {
4052 self.vc1_p_h_loop_filter_mb(frame, cur_y - 1, cur_x - 2, pq);
4053 }
4054 if cur_x + 1 == mb_width {
4055 if cur_x >= 1 {
4056 self.vc1_p_h_loop_filter_mb(frame, cur_y - 1, cur_x - 1, pq);
4057 }
4058 self.vc1_p_h_loop_filter_mb(frame, cur_y - 1, cur_x, pq);
4059 }
4060 }
4061 if cur_x >= 2 {
4062 self.vc1_p_h_loop_filter_mb(frame, cur_y, cur_x - 2, pq);
4063 }
4064 if cur_x + 1 == mb_width {
4065 if cur_x >= 1 {
4066 self.vc1_p_h_loop_filter_mb(frame, cur_y, cur_x - 1, pq);
4067 }
4068 self.vc1_p_h_loop_filter_mb(frame, cur_y, cur_x, pq);
4069 }
4070 }
4071 }
4072 }
4073 }
4074
4075 #[inline]
4076 fn vc1_coding_sets(pic: &PictureHeader) -> (usize, usize) {
4077 let intra = match pic.transacfrm2 {
4078 0 => {
4079 if pic.pqindex <= 8 {
4080 6
4081 } else {
4082 2
4083 }
4084 }
4085 1 => 0,
4086 _ => 4,
4087 };
4088 let inter = match pic.transacfrm {
4089 0 => {
4090 if pic.pqindex <= 8 {
4091 7
4092 } else {
4093 3
4094 }
4095 }
4096 1 => 1,
4097 _ => 5,
4098 };
4099 (intra, inter)
4100 }
4101
4102 #[inline]
4103 fn vc1_read_dc_diff(
4104 &self,
4105 br: &mut BitReader<'_>,
4106 pic: &PictureHeader,
4107 chroma: bool,
4108 quant: i32,
4109 ) -> Result<i32> {
4110 let table = &self.wmv2_dc_vlc[pic.dctab as usize][chroma as usize];
4111 let mut d = table
4112 .decode(br)
4113 .ok_or_else(|| DecoderError::InvalidData("invalid WMV3 DC VLC".into()))?;
4114 if d != 0 {
4115 let m = if quant == 1 || quant == 2 {
4116 3 - quant
4117 } else {
4118 0
4119 };
4120 if d == 119 {
4121 d = br
4122 .read_bits((8 + m) as u8)
4123 .ok_or_else(|| DecoderError::InvalidData("truncated WMV3 DC escape".into()))?
4124 as i32;
4125 } else if m != 0 {
4126 let ext = br.read_bits(m as u8).ok_or_else(|| {
4127 DecoderError::InvalidData("truncated WMV3 DC extension".into())
4128 })? as i32;
4129 d = (d << m) + ext - ((1 << m) - 1);
4130 }
4131 if br
4132 .read_bit()
4133 .ok_or_else(|| DecoderError::InvalidData("truncated WMV3 DC sign".into()))?
4134 {
4135 d = -d;
4136 }
4137 }
4138 Ok(d)
4139 }
4140
4141 fn vc1_decode_ac_coeff(
4142 &mut self,
4143 br: &mut BitReader<'_>,
4144 set: usize,
4145 pq: i32,
4146 dquantfrm: bool,
4147 ) -> Result<(usize, i32, bool)> {
4148 let set = set.min(7);
4149 let idx = self.vc1_ac[set]
4150 .decode_index(br)
4151 .ok_or_else(|| DecoderError::InvalidData("invalid WMV3 AC VLC".into()))?;
4152 let (run, level, last, sign) = if !self.vc1_ac[set].is_escape(idx) {
4153 let (r, l) = self.vc1_ac[set]
4154 .run_level(idx)
4155 .ok_or_else(|| DecoderError::InvalidData("invalid WMV3 AC symbol".into()))?;
4156 let sign = br
4157 .read_bit()
4158 .ok_or_else(|| DecoderError::InvalidData("truncated WMV3 AC sign".into()))?;
4159 (r as usize, l as i32, self.vc1_ac[set].is_last(idx), sign)
4160 } else {
4161 let escape = vc1_decode210_bits(br)?;
4162 if escape != 2 {
4163 let idx2 = self.vc1_ac[set].decode_index(br).ok_or_else(|| {
4164 DecoderError::InvalidData("invalid WMV3 escaped AC VLC".into())
4165 })?;
4166 if self.vc1_ac[set].is_escape(idx2) {
4167 return Err(DecoderError::InvalidData("nested WMV3 AC escape".into()));
4168 }
4169 let (r0, l0) = self.vc1_ac[set].run_level(idx2).ok_or_else(|| {
4170 DecoderError::InvalidData("invalid WMV3 escaped AC symbol".into())
4171 })?;
4172 let last = self.vc1_ac[set].is_last(idx2);
4173 let (r, l) = if escape == 0 {
4174 (
4175 r0 as usize,
4176 l0 as i32 + self.vc1_ac[set].max_level(last, r0 as usize) as i32,
4177 )
4178 } else {
4179 (
4180 r0 as usize + self.vc1_ac[set].max_run(last, l0 as usize) as usize + 1,
4181 l0 as i32,
4182 )
4183 };
4184 let sign = br.read_bit().ok_or_else(|| {
4185 DecoderError::InvalidData("truncated WMV3 escaped AC sign".into())
4186 })?;
4187 (r, l, last, sign)
4188 } else {
4189 let last = br.read_bit().ok_or_else(|| {
4190 DecoderError::InvalidData("truncated WMV3 escape3 last".into())
4191 })?;
4192 if self.vc1_esc3_level_length == 0 {
4193 let ll = if pq < 8 || dquantfrm {
4194 let n = br.read_bits(3).ok_or_else(|| {
4195 DecoderError::InvalidData("truncated WMV3 escape3 level length".into())
4196 })? as u8;
4197 if n == 0 {
4198 br.read_bits(2).ok_or_else(|| {
4199 DecoderError::InvalidData(
4200 "truncated WMV3 escape3 extended level length".into(),
4201 )
4202 })? as u8
4203 + 8
4204 } else {
4205 n
4206 }
4207 } else {
4208 vc1_read_unary_stop_one(br, 6)? + 2
4209 };
4210 self.vc1_esc3_level_length = ll;
4211 self.vc1_esc3_run_length = 3 + br.read_bits(2).ok_or_else(|| {
4212 DecoderError::InvalidData("truncated WMV3 escape3 run length".into())
4213 })? as u8;
4214 }
4215 let r = br
4216 .read_bits(self.vc1_esc3_run_length)
4217 .ok_or_else(|| DecoderError::InvalidData("truncated WMV3 escape3 run".into()))?
4218 as usize;
4219 let sign = br.read_bit().ok_or_else(|| {
4220 DecoderError::InvalidData("truncated WMV3 escape3 sign".into())
4221 })?;
4222 let l = br.read_bits(self.vc1_esc3_level_length).ok_or_else(|| {
4223 DecoderError::InvalidData("truncated WMV3 escape3 level".into())
4224 })? as i32;
4225 (r, l, last, sign)
4226 }
4227 };
4228 Ok((run, if sign { -level } else { level }, last))
4229 }
4230
4231 #[inline]
4232 fn vc1_mb_index(&self, r: usize, c: usize) -> Option<usize> {
4233 if r < self.height_mb as usize && c < self.width_mb as usize {
4234 Some(r * self.width_mb as usize + c)
4235 } else {
4236 None
4237 }
4238 }
4239
4240 fn vc1_luma_slot(&self, gx: isize, gy: isize) -> Option<(usize, usize)> {
4241 if gx < 0 || gy < 0 {
4242 return None;
4243 }
4244 let gx = gx as usize;
4245 let gy = gy as usize;
4246 let c = gx / 2;
4247 let r = gy / 2;
4248 let idx = self.vc1_mb_index(r, c)?;
4249 let blk = (gy & 1) * 2 + (gx & 1);
4250 Some((idx, blk))
4251 }
4252
4253 fn vc1_dc_neighbours(
4254 &self,
4255 r: usize,
4256 c: usize,
4257 blk: usize,
4258 ) -> (Option<i32>, Option<i32>, Option<i32>) {
4259 if blk < 4 {
4260 let gx = (c * 2 + (blk & 1)) as isize;
4261 let gy = (r * 2 + (blk >> 1)) as isize;
4262 let get = |x: isize, y: isize| self.vc1_luma_slot(x, y).map(|(i, b)| self.vc1_dc[i][b]);
4263 (get(gx, gy - 1), get(gx - 1, gy - 1), get(gx - 1, gy))
4264 } else {
4265 let get = |rr: isize, cc: isize| -> Option<i32> {
4266 if rr < 0 || cc < 0 {
4267 return None;
4268 }
4269 self.vc1_mb_index(rr as usize, cc as usize)
4270 .map(|i| self.vc1_dc[i][blk])
4271 };
4272 (
4273 get(r as isize - 1, c as isize),
4274 get(r as isize - 1, c as isize - 1),
4275 get(r as isize, c as isize - 1),
4276 )
4277 }
4278 }
4279
4280 fn vc1_i_dc_pred(
4281 &self,
4282 r: usize,
4283 c: usize,
4284 blk: usize,
4285 seq: &SequenceHeader,
4286 pq: i32,
4287 ) -> (i32, bool) {
4288 const DCPRED: [i32; 32] = [
4289 -1, 1024, 512, 341, 256, 205, 171, 146, 128, 114, 102, 93, 85, 79, 73, 68, 64, 60, 57,
4290 54, 51, 49, 47, 45, 43, 41, 39, 38, 37, 35, 34, 33,
4291 ];
4292 let (oa, ob, oc) = self.vc1_dc_neighbours(r, c, blk);
4293 let boundary = if pq < 9 || !seq.overlap {
4294 DCPRED[vc1_dc_scale(pq) as usize]
4295 } else {
4296 0
4297 };
4298 let a = oa.unwrap_or(boundary);
4299 let b = ob.unwrap_or(boundary);
4300 let cc = oc.unwrap_or(boundary);
4301 if (a - b).abs() <= (b - cc).abs() {
4302 (cc, true)
4303 } else {
4304 (a, false)
4305 }
4306 }
4307
4308 fn vc1_intra_neighbour(
4309 &self,
4310 r: usize,
4311 c: usize,
4312 blk: usize,
4313 top: bool,
4314 ) -> Option<(usize, usize)> {
4315 if blk < 4 {
4316 let gx = (c * 2 + (blk & 1)) as isize;
4317 let gy = (r * 2 + (blk >> 1)) as isize;
4318 let (x, y) = if top { (gx, gy - 1) } else { (gx - 1, gy) };
4319 self.vc1_luma_slot(x, y)
4320 } else {
4321 let (rr, cc) = if top {
4322 (r as isize - 1, c as isize)
4323 } else {
4324 (r as isize, c as isize - 1)
4325 };
4326 if rr < 0 || cc < 0 {
4327 return None;
4328 }
4329 self.vc1_mb_index(rr as usize, cc as usize)
4330 .map(|i| (i, blk))
4331 }
4332 }
4333
4334 fn vc1_inter_dc_pred(
4335 &self,
4336 r: usize,
4337 c: usize,
4338 blk: usize,
4339 mquant: i32,
4340 _halfqp: bool,
4341 ) -> (i32, bool, bool, bool, i32) {
4342 let cur_idx = self.vc1_mb_index(r, c).unwrap_or(0);
4343 let top_slot = self.vc1_intra_neighbour(r, c, blk, true);
4344 let left_slot = self.vc1_intra_neighbour(r, c, blk, false);
4345 let diag_slot = if blk < 4 {
4346 let gx = (c * 2 + (blk & 1)) as isize;
4347 let gy = (r * 2 + (blk >> 1)) as isize;
4348 self.vc1_luma_slot(gx - 1, gy - 1)
4349 } else if r > 0 && c > 0 {
4350 self.vc1_mb_index(r - 1, c - 1).map(|i| (i, blk))
4351 } else {
4352 None
4353 };
4354 let a_av = top_slot
4355 .map(|(i, b)| self.vc1_intra_blocks[i][b])
4356 .unwrap_or(false);
4357 let c_av = left_slot
4358 .map(|(i, b)| self.vc1_intra_blocks[i][b])
4359 .unwrap_or(false);
4360 let mut a = top_slot
4361 .filter(|(i, b)| self.vc1_intra_blocks[*i][*b])
4362 .map(|(i, b)| self.vc1_dc[i][b])
4363 .unwrap_or(0);
4364 let mut cc = left_slot
4365 .filter(|(i, b)| self.vc1_intra_blocks[*i][*b])
4366 .map(|(i, b)| self.vc1_dc[i][b])
4367 .unwrap_or(0);
4368 let mut b = diag_slot.map(|(i, b)| self.vc1_dc[i][b]).unwrap_or(0);
4369 if a_av && let Some((i, _)) = top_slot {
4370 a = vc1_rescale_dc_pred(a, mquant, self.vc1_qscale[i]);
4371 }
4372 if c_av && let Some((i, _)) = left_slot {
4373 cc = vc1_rescale_dc_pred(cc, mquant, self.vc1_qscale[i]);
4374 }
4375 if a_av
4378 && c_av
4379 && blk != 3
4380 && let Some((i, _)) = diag_slot
4381 {
4382 b = vc1_rescale_dc_pred(b, mquant, self.vc1_qscale[i]);
4383 }
4384 let (pred, left) = if c_av && (!a_av || (a - b).abs() <= (b - cc).abs()) {
4385 (cc, true)
4386 } else if a_av {
4387 (a, false)
4388 } else {
4389 (0, true)
4390 };
4391 let q2 = if left {
4392 left_slot
4393 .map(|(i, _)| self.vc1_qscale[i])
4394 .unwrap_or(self.vc1_qscale[cur_idx])
4395 } else {
4396 top_slot
4397 .map(|(i, _)| self.vc1_qscale[i])
4398 .unwrap_or(self.vc1_qscale[cur_idx])
4399 };
4400 (pred, left, a_av, c_av, q2)
4401 }
4402
4403 fn vc1_decode_intra_coeffs(
4404 &mut self,
4405 br: &mut BitReader<'_>,
4406 pic: &PictureHeader,
4407 seq: &SequenceHeader,
4408 r: usize,
4409 c: usize,
4410 blk: usize,
4411 coded: bool,
4412 mquant: i32,
4413 acpred: bool,
4414 pure_i: bool,
4415 set: usize,
4416 ) -> Result<[i32; 64]> {
4417 let quant = mquant.abs().clamp(1, 31);
4418 let dc_diff = self.vc1_read_dc_diff(br, pic, blk >= 4, quant)?;
4419 let (pred, mut left, a_av, c_av, q2) = if pure_i && seq.profile != Profile::Advanced {
4420 let (p, l) = self.vc1_i_dc_pred(r, c, blk, seq, quant);
4424 (p, l, true, true, mquant)
4425 } else {
4426 self.vc1_inter_dc_pred(r, c, blk, mquant, pic.halfqp)
4430 };
4431
4432 if !pure_i {
4436 if !a_av {
4437 left = true;
4438 }
4439 if !c_av {
4440 left = false;
4441 }
4442 }
4443 let use_pred = acpred
4444 && if pure_i && seq.profile != Profile::Advanced {
4445 true
4446 } else {
4447 a_av || c_av
4448 };
4449
4450 let dc = pred + dc_diff;
4451 let mbi = self.vc1_mb_index(r, c).unwrap();
4452 self.vc1_dc[mbi][blk] = dc;
4453 self.vc1_intra_blocks[mbi][blk] = true;
4454
4455 let mut coeff = [0i32; 64];
4456 coeff[0] = dc * vc1_dc_scale(quant);
4457
4458 if coded {
4459 let scan: &[usize; 64] = if pure_i {
4465 if acpred {
4470 if left {
4471 &FF_WMV1_SCANTABLE[3]
4472 } else {
4473 &FF_WMV1_SCANTABLE[2]
4474 }
4475 } else {
4476 &FF_WMV1_SCANTABLE[1]
4477 }
4478 } else {
4479 &FF_WMV1_SCANTABLE[0]
4480 };
4481
4482 let mut pos = 1usize;
4483 let mut last = false;
4484 while !last && pos < 64 {
4485 let (run, level, l) =
4486 self.vc1_decode_ac_coeff(br, set, pic.pquant as i32, pic.dquant.enabled)?;
4487 let at = pos.saturating_add(run);
4488 if at > 63 {
4489 break;
4490 }
4491 let dst = vc1_scan_index(scan, at, seq.uses_transposed_scans());
4492 coeff[dst] = level;
4493 pos = at + 1;
4494 last = l;
4495 }
4496 }
4497
4498 if use_pred {
4499 if left {
4500 let mut p = if seq.uses_transposed_scans() {
4504 self.ac_pred.pred_row(r, c, blk)
4505 } else {
4506 self.ac_pred.pred_left_col(r, c, blk)
4507 };
4508 if q2 != 0 && q2 != mquant {
4509 for v in &mut p {
4510 *v = vc1_rescale_ac_pred(*v, mquant, q2, pic.halfqp);
4511 }
4512 }
4513 let sh = if seq.uses_transposed_scans() { 0 } else { 3 };
4514 for k in 1..8 {
4515 coeff[k << sh] += p[k - 1];
4516 }
4517 } else {
4518 let mut p = if seq.uses_transposed_scans() {
4522 self.ac_pred.pred_col(r, c, blk)
4523 } else {
4524 self.ac_pred.pred_top_row(r, c, blk)
4525 };
4526 if q2 != 0 && q2 != mquant {
4527 for v in &mut p {
4528 *v = vc1_rescale_ac_pred(*v, mquant, q2, pic.halfqp);
4529 }
4530 }
4531 let sh = if seq.uses_transposed_scans() { 3 } else { 0 };
4532 for k in 1..8 {
4533 coeff[k << sh] += p[k - 1];
4534 }
4535 }
4536 }
4537
4538 self.ac_pred.store_row(
4542 r,
4543 c,
4544 blk,
4545 [
4546 coeff[1], coeff[2], coeff[3], coeff[4], coeff[5], coeff[6], coeff[7],
4547 ],
4548 );
4549 self.ac_pred.store_col(
4550 r,
4551 c,
4552 blk,
4553 [
4554 coeff[8], coeff[16], coeff[24], coeff[32], coeff[40], coeff[48], coeff[56],
4555 ],
4556 );
4557
4558 for k in 1..64 {
4559 if coeff[k] != 0 {
4560 coeff[k] = vc1_scale_level(coeff[k], mquant, pic.halfqp, pic.pqual_mode != 0);
4561 }
4562 }
4563 Ok(coeff)
4564 }
4565
4566 fn vc1_coded_block_pred(&mut self, r: usize, c: usize, blk: usize, diff: bool) -> bool {
4567 let bw = self.width_mb as usize * 2;
4568 let x = c * 2 + (blk & 1);
4569 let y = r * 2 + (blk >> 1);
4570 let idx = y * bw + x;
4571 let a = if x > 0 {
4572 self.vc1_coded_block[idx - 1]
4573 } else {
4574 0
4575 };
4576 let b = if x > 0 && y > 0 {
4577 self.vc1_coded_block[idx - bw - 1]
4578 } else {
4579 0
4580 };
4581 let cc = if y > 0 {
4582 self.vc1_coded_block[idx - bw]
4583 } else {
4584 0
4585 };
4586 let pred = if b == cc { a } else { cc };
4587 let v = pred ^ diff as u8;
4588 self.vc1_coded_block[idx] = v;
4589 v != 0
4590 }
4591
4592 fn vc1_read_mvdata(
4593 &self,
4594 br: &mut BitReader<'_>,
4595 pic: &PictureHeader,
4596 quarter_sample: bool,
4597 ) -> Result<Vc1MvData> {
4598 let vlc_bit = br.bits_read();
4599 let sym = self.vc1_mvdata[(pic.mvtab as usize).min(3)]
4600 .decode(br)
4601 .ok_or_else(|| {
4602 DecoderError::InvalidData(format!(
4603 "invalid WMV3 MVDATA VLC at bit {vlc_bit} (left={})",
4604 br.bits_left()
4605 ))
4606 })?;
4607 let mut index = 1 + sym;
4608 let has_coeffs = index > 36;
4609 if has_coeffs {
4610 index -= 37;
4611 }
4612 if index == 0 {
4613 return Ok(Vc1MvData {
4614 dx: 0,
4615 dy: 0,
4616 intra: false,
4617 has_coeffs,
4618 });
4619 }
4620
4621 let (_, _, _, _, kx, ky) = self.vc1_mv_params(pic);
4622 if index == 35 {
4623 let xb = (kx - 1 + quarter_sample as i32) as u8;
4624 let yb = (ky - 1 + quarter_sample as i32) as u8;
4625 let xbit = br.bits_read();
4626 let dx = br.read_bits(xb).ok_or_else(|| {
4627 DecoderError::InvalidData(format!(
4628 "truncated WMV3 MVDATA x escape at bit {xbit}: need {xb}, left={}",
4629 br.bits_left()
4630 ))
4631 })? as i32;
4632 let ybit = br.bits_read();
4633 let dy = br.read_bits(yb).ok_or_else(|| {
4634 DecoderError::InvalidData(format!(
4635 "truncated WMV3 MVDATA y escape at bit {ybit}: need {yb}, left={}",
4636 br.bits_left()
4637 ))
4638 })? as i32;
4639 return Ok(Vc1MvData {
4640 dx,
4641 dy,
4642 intra: false,
4643 has_coeffs,
4644 });
4645 }
4646 if index == 36 {
4647 return Ok(Vc1MvData {
4648 dx: 0,
4649 dy: 0,
4650 intra: true,
4651 has_coeffs,
4652 });
4653 }
4654
4655 const SIZE: [i32; 6] = [0, 2, 3, 4, 5, 8];
4656 const OFF: [i32; 6] = [0, 1, 3, 7, 15, 31];
4657 let dec = |br: &mut BitReader<'_>, g: i32, axis: char| -> Result<i32> {
4658 let gi = g as usize;
4659 let mut out = OFF[gi];
4660 let n = SIZE[gi] - ((!quarter_sample && gi == 5) as i32);
4661 if n > 0 {
4662 let bit = br.bits_read();
4663 let v = br.read_bits(n as u8).ok_or_else(|| {
4664 DecoderError::InvalidData(format!(
4665 "truncated WMV3 MVDATA {axis} component at bit {bit}: index={index} group={gi} need={n}, left={}",
4666 br.bits_left()
4667 ))
4668 })? as i32;
4669 let sign = -(v & 1);
4670 out = (sign ^ ((v >> 1) + out)) - sign;
4671 }
4672 Ok(out)
4673 };
4674 Ok(Vc1MvData {
4675 dx: dec(br, index % 6, 'x')?,
4676 dy: dec(br, index / 6, 'y')?,
4677 intra: false,
4678 has_coeffs,
4679 })
4680 }
4681
4682 #[inline]
4683 fn vc1_mv_params(&self, pic: &PictureHeader) -> (bool, bool, i32, i32, i32, i32) {
4684 let mode = if pic.mv_mode == MvMode::IntensityComp {
4685 pic.mv_mode2
4686 } else {
4687 pic.mv_mode
4688 };
4689 let quarter = !matches!(mode, MvMode::OneMvHpel | MvMode::OneMvHpelBilin);
4690 let mspel = mode != MvMode::OneMvHpelBilin;
4691
4692 let r = pic.mvrange as i32;
4698 let mut kx = r + 9 + (r >> 1);
4699 let mut ky = r + 8;
4700 if self.width < 120 {
4701 kx = 9;
4702 }
4703 if self.height < 60 {
4704 ky = 8;
4705 }
4706 (quarter, mspel, 1 << (kx - 1), 1 << (ky - 1), kx, ky)
4707 }
4708
4709 fn vc1_predict_p_mv(
4710 &mut self,
4711 br: &mut BitReader<'_>,
4712 pic: &PictureHeader,
4713 seq: &SequenceHeader,
4714 r: usize,
4715 c: usize,
4716 n: usize,
4717 dmv: (i32, i32),
4718 mv1: bool,
4719 intra: bool,
4720 ) -> Result<(i32, i32)> {
4721 let (quarter, _, rx, ry, _, _) = self.vc1_mv_params(pic);
4722 let mut dx = dmv.0;
4723 let mut dy = dmv.1;
4724 if !quarter {
4725 dx *= 2;
4726 dy *= 2;
4727 }
4728
4729 let idx = self.vc1_mb_index(r, c).unwrap();
4730 if intra {
4731 self.vc1_mv4[idx][n] = (0, 0);
4732 if mv1 {
4733 self.vc1_mv4[idx] = [(0, 0); 4];
4734 self.vc1_current_mvs[idx] = (0, 0);
4735 }
4736 return Ok((0, 0));
4737 }
4738
4739 let gx = (c * 2 + (n & 1)) as isize;
4740 let gy = (r * 2 + (n >> 1)) as isize;
4741
4742 let b8_stride = self.width_mb as isize * 2 + 1;
4749 let ff_xy = b8_stride * gy + gx - 2;
4750 let slot_from_ff_index = |ff_index: isize| -> Option<(usize, usize)> {
4751 let shifted = ff_index + 2;
4752 let yy = shifted.div_euclid(b8_stride);
4753 let xx = shifted.rem_euclid(b8_stride);
4754 if yy < 0 || xx >= self.width_mb as isize * 2 {
4755 None
4756 } else {
4757 self.vc1_luma_slot(xx, yy)
4758 }
4759 };
4760
4761 let a_slot = slot_from_ff_index(ff_xy - b8_stride);
4765 let c_slot = slot_from_ff_index(ff_xy - 1);
4766 let boff: isize = if mv1 {
4767 if c + 1 >= self.width_mb as usize {
4768 -1
4769 } else {
4770 2
4771 }
4772 } else {
4773 match n {
4774 0 => {
4775 if seq.res_rtm_flag {
4776 if c > 0 { -1 } else { 1 }
4777 } else if c > 0 {
4778 -1
4779 } else {
4780 2 * self.width_mb as isize - b8_stride - 1
4783 }
4784 }
4785 1 => {
4786 if c + 1 >= self.width_mb as usize {
4787 -1
4788 } else {
4789 1
4790 }
4791 }
4792 2 => 1,
4793 _ => -1,
4794 }
4795 };
4796 let b_slot = slot_from_ff_index(ff_xy - b8_stride + boff);
4797
4798 let a = a_slot.map(|(mi, bi)| self.vc1_mv4[mi][bi]);
4799 let b = b_slot.map(|(mi, bi)| self.vc1_mv4[mi][bi]);
4800 let cc = c_slot.map(|(mi, bi)| self.vc1_mv4[mi][bi]);
4801 let vals = [
4802 a.unwrap_or((0, 0)),
4803 b.unwrap_or((0, 0)),
4804 cc.unwrap_or((0, 0)),
4805 ];
4806 let valid = (a.is_some() as usize) + (b.is_some() as usize) + (cc.is_some() as usize);
4807 let (mut px, mut py) = if valid > 1 {
4808 (
4809 median3(vals[0].0, vals[1].0, vals[2].0),
4810 median3(vals[0].1, vals[1].1, vals[2].1),
4811 )
4812 } else if let Some(v) = a {
4813 v
4814 } else if let Some(v) = cc {
4815 v
4816 } else {
4817 b.unwrap_or((0, 0))
4818 };
4819
4820 let lim = if mv1 { -60 } else { -28 };
4822 let qx = ((c as i32) << 6) + if !mv1 && matches!(n, 1 | 3) { 32 } else { 0 };
4823 let qy = ((r as i32) << 6) + if !mv1 && matches!(n, 2 | 3) { 32 } else { 0 };
4824 let xx = ((self.width_mb as i32) << 6) - 4;
4825 let yy = ((self.height_mb as i32) << 6) - 4;
4826 if qx + px < lim {
4827 px = lim - qx;
4828 }
4829 if qy + py < lim {
4830 py = lim - qy;
4831 }
4832 if qx + px > xx {
4833 px = xx - qx;
4834 }
4835 if qy + py > yy {
4836 py = yy - qy;
4837 }
4838
4839 if let (Some(av), Some(cv)) = (a, cc) {
4847 let a_intra = a_slot
4848 .map(|(mi, bi)| self.vc1_intra_blocks[mi][bi])
4849 .unwrap_or(false);
4850 let c_intra = c_slot
4851 .map(|(mi, bi)| self.vc1_intra_blocks[mi][bi])
4852 .unwrap_or(false);
4853
4854 let mut sum = if a_intra {
4855 px.abs() + py.abs()
4856 } else {
4857 (px - av.0).abs() + (py - av.1).abs()
4858 };
4859
4860 let mut need_hybrid_bit = sum > 32;
4861 if !need_hybrid_bit {
4862 sum = if c_intra {
4863 px.abs() + py.abs()
4864 } else {
4865 (px - cv.0).abs() + (py - cv.1).abs()
4866 };
4867 need_hybrid_bit = sum > 32;
4868 }
4869
4870 if need_hybrid_bit {
4871 if br
4872 .read_bit()
4873 .ok_or_else(|| DecoderError::InvalidData("truncated WMV3 HYBRIDPRED".into()))?
4874 {
4875 (px, py) = av;
4876 } else {
4877 (px, py) = cv;
4878 }
4879 }
4880 }
4881
4882 let mv = (
4883 ((px + dx + rx) & ((rx << 1) - 1)) - rx,
4884 ((py + dy + ry) & ((ry << 1) - 1)) - ry,
4885 );
4886 self.vc1_mv4[idx][n] = mv;
4887 if mv1 {
4888 self.vc1_mv4[idx] = [mv; 4];
4889 self.vc1_current_mvs[idx] = mv;
4890 } else if n == 0 {
4891 self.vc1_current_mvs[idx] = mv;
4892 }
4893 Ok(mv)
4894 }
4895
4896 fn vc1_decode_p_residual(
4897 &mut self,
4898 br: &mut BitReader<'_>,
4899 pic: &PictureHeader,
4900 seq: &SequenceHeader,
4901 mquant: i32,
4902 ttmb: i32,
4903 first_block: bool,
4904 ) -> Result<([i32; 64], u8, u8)> {
4905 let tt_index = ((pic.pquant > 4) as usize) + ((pic.pquant > 12) as usize);
4906 let mut tt = if ttmb < 0 {
4907 let sym = self.vc1_ttblk[tt_index]
4908 .decode(br)
4909 .ok_or_else(|| DecoderError::InvalidData("invalid WMV3 TTBLK".into()))?
4910 as usize;
4911 TTBLK_TO_TT[tt_index][sym.min(7)]
4912 } else {
4913 (ttmb as u8) & 7
4914 };
4915
4916 let mut sub = 0u8;
4917 if tt == TT_4X4 {
4918 let sym = self.vc1_subblkpat[tt_index]
4919 .decode(br)
4920 .ok_or_else(|| DecoderError::InvalidData("invalid WMV3 SUBBLKPAT".into()))?
4921 as u8;
4922 sub = (!(sym.wrapping_add(1))) & 0x0f;
4923 }
4924 if tt != TT_8X8
4925 && tt != TT_4X4
4926 && ((pic.ttmbf || (ttmb >= 0 && ((ttmb as u8) & 8) != 0 && !first_block))
4927 || (!seq.res_rtm_flag && !first_block))
4928 {
4929 sub = vc1_decode012_bits(br)?;
4930 if sub != 0 {
4931 sub ^= 3;
4932 }
4933 if matches!(tt, TT_8X4_TOP | TT_8X4_BOTTOM) {
4934 tt = TT_8X4;
4935 }
4936 if matches!(tt, TT_4X8_LEFT | TT_4X8_RIGHT) {
4937 tt = TT_4X8;
4938 }
4939 }
4940 if tt == TT_8X4_TOP || tt == TT_8X4_BOTTOM {
4941 sub = 2 - (tt == TT_8X4_TOP) as u8;
4942 tt = TT_8X4;
4943 }
4944 if tt == TT_4X8_LEFT || tt == TT_4X8_RIGHT {
4945 sub = 2 - (tt == TT_4X8_LEFT) as u8;
4946 tt = TT_4X8;
4947 }
4948
4949 let (_, set) = Self::vc1_coding_sets(pic);
4950 let mut out = [0i32; 64];
4951 let mut decode_part = |this: &mut Self,
4952 scan: &[usize],
4953 base: usize,
4954 limit: usize,
4955 already_last: bool,
4956 transpose_scan: bool|
4957 -> Result<()> {
4958 if already_last {
4959 return Ok(());
4960 }
4961 let mut pos = 0usize;
4962 let mut last = false;
4963 while !last && pos < limit {
4964 let (run, lev, l) =
4965 this.vc1_decode_ac_coeff(br, set, pic.pquant as i32, pic.dquant.enabled)?;
4966 let at = pos.saturating_add(run);
4967 if at >= limit {
4968 break;
4969 }
4970 let scan_index = if transpose_scan {
4971 vc1_transpose_scan_index(scan[at])
4972 } else {
4973 scan[at]
4974 };
4975 let idx = base + scan_index;
4976 if idx < 64 {
4977 out[idx] = vc1_scale_level(lev, mquant, pic.halfqp, pic.pqual_mode != 0);
4978 }
4979 pos = at + 1;
4980 last = l;
4981 }
4982 Ok(())
4983 };
4984
4985 let pat = match tt {
4986 TT_8X8 => {
4987 decode_part(
4988 self,
4989 &FF_WMV1_SCANTABLE[0],
4990 0,
4991 64,
4992 false,
4993 seq.uses_transposed_scans(),
4994 )?;
4995 0x0f
4996 }
4997 TT_4X4 => {
4998 for j in 0..4usize {
4999 let base = (j & 1) * 4 + (j & 2) * 16;
5000 decode_part(
5001 self,
5002 &VC1_ZZ_4X4,
5003 base,
5004 16,
5005 (sub & (1 << (3 - j))) != 0,
5006 false,
5007 )?;
5008 }
5009 (!sub) & 0x0f
5010 }
5011 TT_8X4 => {
5012 let scan: &[usize] = if seq.profile == Profile::Advanced {
5013 &VC1_ZZ_8X4
5014 } else {
5015 &FF_WMV2_SCANTABLE_A
5016 };
5017 for j in 0..2usize {
5018 decode_part(self, scan, j * 32, 32, (sub & (1 << (1 - j))) != 0, false)?;
5019 }
5020 (!((sub & 2) * 6 + (sub & 1) * 3)) & 0x0f
5021 }
5022 TT_4X8 => {
5023 let scan: &[usize] = if seq.profile == Profile::Advanced {
5024 &VC1_ZZ_4X8
5025 } else {
5026 &FF_WMV2_SCANTABLE_B
5027 };
5028 for j in 0..2usize {
5029 decode_part(self, scan, j * 4, 32, (sub & (1 << (1 - j))) != 0, false)?;
5030 }
5031 (!(sub * 5)) & 0x0f
5032 }
5033 _ => 0,
5034 };
5035
5036 apply_wmv3_idct(&mut out, tt, seq.uses_transposed_scans());
5037 Ok((out, tt, pat))
5038 }
5039
5040 fn vc1_mc_single(
5041 &self,
5042 frame: &mut YuvFrame,
5043 r: usize,
5044 c: usize,
5045 reference: &YuvFrame,
5046 mv: (i32, i32),
5047 pic: &PictureHeader,
5048 seq: &SequenceHeader,
5049 block: Option<usize>,
5050 interpolated_next: bool,
5051 ) {
5052 let (quarter, mspel, _, _, _, _) = self.vc1_mv_params(pic);
5053 let mx = mv.0;
5054 let my = mv.1;
5055 if !quarter {
5056 }
5059
5060 let (bx, by, bw, bh) = if let Some(n) = block {
5061 (c * 16 + (n & 1) * 8, r * 16 + (n >> 1) * 8, 8usize, 8usize)
5062 } else {
5063 (c * 16, r * 16, 16usize, 16usize)
5064 };
5065
5066 let src_y = reference.y.as_slice();
5070
5071 let sx = bx as i32 + (mx >> 2);
5072 let sy = by as i32 + (my >> 2);
5073 let fx = mx & 3;
5074 let fy = my & 3;
5075 let mut tmp_storage = [0u8; 16 * 16];
5078 let tmp = &mut tmp_storage[..bw * bh];
5079 if mspel {
5080 vc1_mspel_block(
5081 tmp,
5082 bw,
5083 src_y,
5084 self.width as usize,
5085 self.width as usize,
5086 self.height as usize,
5087 sx,
5088 sy,
5089 bw,
5090 bh,
5091 fx,
5092 fy,
5093 self.vc1_rnd,
5094 );
5095 } else {
5096 vc1_bilinear_qpel_block(
5097 tmp,
5098 bw,
5099 src_y,
5100 self.width as usize,
5101 self.width as usize,
5102 self.height as usize,
5103 sx,
5104 sy,
5105 bw,
5106 bh,
5107 fx & 2,
5108 fy & 2,
5109 4,
5110 self.vc1_rnd,
5111 );
5112 }
5113 for y in 0..bh {
5114 let dy = by + y;
5115 if dy >= self.height as usize {
5116 break;
5117 }
5118 for x in 0..bw {
5119 let dx = bx + x;
5120 if dx >= self.width as usize {
5121 break;
5122 }
5123 frame.y[dy * self.width as usize + dx] = tmp[y * bw + x];
5124 }
5125 }
5126
5127 if block.is_some() {
5128 return;
5129 }
5130
5131 self.vc1_mc_chroma(frame, r, c, reference, mv, seq, interpolated_next);
5132 }
5133
5134 fn vc1_mc_chroma(
5135 &self,
5136 frame: &mut YuvFrame,
5137 r: usize,
5138 c: usize,
5139 reference: &YuvFrame,
5140 mv: (i32, i32),
5141 seq: &SequenceHeader,
5142 interpolated_next: bool,
5143 ) {
5144 let mx = mv.0;
5145 let my = mv.1;
5146 let cw = self.width as usize / 2;
5147 let ch = self.height as usize / 2;
5148 if cw == 0 || ch == 0 {
5149 return;
5150 }
5151 let mut uvmx = (mx + ((mx & 3) == 3) as i32) >> 1;
5152 let mut uvmy = (my + ((my & 3) == 3) as i32) >> 1;
5153 if seq.fastuvmc {
5154 if interpolated_next {
5155 uvmx += if uvmx < 0 { -(uvmx & 1) } else { uvmx & 1 };
5161 uvmy += if uvmy < 0 { -(uvmy & 1) } else { uvmy & 1 };
5162 } else {
5163 uvmx += if uvmx < 0 { uvmx & 1 } else { -(uvmx & 1) };
5164 uvmy += if uvmy < 0 { uvmy & 1 } else { -(uvmy & 1) };
5165 }
5166 }
5167 let csx = (c * 8) as i32 + (uvmx >> 2);
5168 let csy = (r * 8) as i32 + (uvmy >> 2);
5169 let cfx = (uvmx & 3) << 1;
5170 let cfy = (uvmy & 3) << 1;
5171
5172 let cb = reference.cb.as_slice();
5173 let cr = reference.cr.as_slice();
5174 let mut tb = [0u8; 64];
5175 let mut tr = [0u8; 64];
5176 vc1_bilinear_qpel_block(
5177 &mut tb,
5178 8,
5179 cb,
5180 cw,
5181 cw,
5182 ch,
5183 csx,
5184 csy,
5185 8,
5186 8,
5187 cfx,
5188 cfy,
5189 8,
5190 self.vc1_rnd,
5191 );
5192 vc1_bilinear_qpel_block(
5193 &mut tr,
5194 8,
5195 cr,
5196 cw,
5197 cw,
5198 ch,
5199 csx,
5200 csy,
5201 8,
5202 8,
5203 cfx,
5204 cfy,
5205 8,
5206 self.vc1_rnd,
5207 );
5208 for y in 0..8 {
5209 for x in 0..8 {
5210 let dx = c * 8 + x;
5211 let dy = r * 8 + y;
5212 if dx < cw && dy < ch {
5213 frame.cb[dy * cw + dx] = tb[y * 8 + x];
5214 frame.cr[dy * cw + dx] = tr[y * 8 + x];
5215 }
5216 }
5217 }
5218 }
5219
5220 fn vc1_mc_4mv_chroma(
5221 &self,
5222 frame: &mut YuvFrame,
5223 r: usize,
5224 c: usize,
5225 reference: &YuvFrame,
5226 mvs: [(i32, i32); 4],
5227 intra: [bool; 4],
5228 pic: &PictureHeader,
5229 seq: &SequenceHeader,
5230 ) -> (i32, i32) {
5231 let mut valid = [(0i32, 0i32); 4];
5235 let mut count = 0usize;
5236 for i in 0..4 {
5237 if !intra[i] {
5238 valid[count] = mvs[i];
5239 count += 1;
5240 }
5241 }
5242 if count < 2 {
5243 for i in 0..4 {
5246 if !intra[i] {
5247 self.vc1_mc_single(frame, r, c, reference, mvs[i], pic, seq, Some(i), false);
5248 }
5249 }
5250 return (0, 0);
5251 }
5252 #[inline]
5253 fn median4(a: i32, b: i32, c: i32, d: i32) -> i32 {
5254 if a < b {
5255 if c < d {
5256 (b.min(d) + a.max(c)) / 2
5257 } else {
5258 (b.min(c) + a.max(d)) / 2
5259 }
5260 } else if c < d {
5261 (a.min(d) + b.max(c)) / 2
5262 } else {
5263 (a.min(c) + b.max(d)) / 2
5264 }
5265 }
5266 let mv = match count {
5267 2 => ((valid[0].0 + valid[1].0) / 2, (valid[0].1 + valid[1].1) / 2),
5268 3 => (
5269 median3(valid[0].0, valid[1].0, valid[2].0),
5270 median3(valid[0].1, valid[1].1, valid[2].1),
5271 ),
5272 _ => (
5273 median4(valid[0].0, valid[1].0, valid[2].0, valid[3].0),
5274 median4(valid[0].1, valid[1].1, valid[2].1, valid[3].1),
5275 ),
5276 };
5277 self.vc1_mc_chroma(frame, r, c, reference, mv, seq, false);
5281 for i in 0..4 {
5283 if !intra[i] {
5284 self.vc1_mc_single(frame, r, c, reference, mvs[i], pic, seq, Some(i), false);
5285 }
5286 }
5287 vc1_loop_chroma_mv(mv)
5288 }
5289
5290 fn vc1_b_predict(
5291 &self,
5292 r: usize,
5293 c: usize,
5294 dmv: [(i32, i32); 2],
5295 direct: bool,
5296 mode: u8,
5297 intra: bool,
5298 pic: &PictureHeader,
5299 seq: &SequenceHeader,
5300 fwd_hist: &[(i32, i32)],
5301 bwd_hist: &[(i32, i32)],
5302 ) -> [(i32, i32); 2] {
5303 let (quarter, _, rx, ry, _, _) = self.vc1_mv_params(pic);
5304 let idx = r * self.width_mb as usize + c;
5305 if intra {
5306 return [(0, 0); 2];
5307 }
5308
5309 let base = self
5315 .vc1_bwd_anchor_mvs
5316 .as_ref()
5317 .and_then(|v| v.get(idx))
5318 .copied()
5319 .unwrap_or((0, 0));
5320 let mut out = [
5321 (
5322 vc1_scale_b_mv(base.0, pic.bfrac_num, pic.bfrac_den, false, quarter),
5323 vc1_scale_b_mv(base.1, pic.bfrac_num, pic.bfrac_den, false, quarter),
5324 ),
5325 (
5326 vc1_scale_b_mv(base.0, pic.bfrac_num, pic.bfrac_den, true, quarter),
5327 vc1_scale_b_mv(base.1, pic.bfrac_num, pic.bfrac_den, true, quarter),
5328 ),
5329 ];
5330
5331 let qx6 = (c as i32) << 6;
5335 let qy6 = (r as i32) << 6;
5336 let x6 = ((self.width_mb as i32) << 6) - 4;
5337 let y6 = ((self.height_mb as i32) << 6) - 4;
5338 for mv in &mut out {
5339 mv.0 = mv.0.clamp(-60 - qx6, x6 - qx6);
5340 mv.1 = mv.1.clamp(-60 - qy6, y6 - qy6);
5341 }
5342 if direct {
5343 return out;
5344 }
5345
5346 let pred = |hist: &[(i32, i32)]| -> (i32, i32) {
5347 let w = self.width_mb as usize;
5348 if r > 0 {
5349 let a = hist[idx - w];
5350 if w == 1 {
5351 return a;
5352 }
5353 let b = if c + 1 < w {
5354 hist[idx - w + 1]
5355 } else {
5356 hist[idx - w - 1]
5357 };
5358 let cc = if c > 0 { hist[idx - 1] } else { (0, 0) };
5362 (median3(a.0, b.0, cc.0), median3(a.1, b.1, cc.1))
5363 } else if c > 0 {
5364 hist[idx - 1]
5365 } else {
5366 (0, 0)
5367 }
5368 };
5369
5370 for dir in 0..2 {
5374 let active =
5375 (dir == 0 && (mode == 0 || mode == 2)) || (dir == 1 && (mode == 1 || mode == 2));
5376 if !active {
5377 continue;
5378 }
5379 let p = if dir == 0 {
5380 pred(fwd_hist)
5381 } else {
5382 pred(bwd_hist)
5383 };
5384 let (mut dx, mut dy) = dmv[dir];
5385 if !quarter {
5386 dx *= 2;
5387 dy *= 2;
5388 }
5389
5390 let sh = if seq.profile == Profile::Advanced {
5394 6
5395 } else {
5396 5
5397 };
5398 let lim = 4 - (1 << sh);
5399 let qx = (c as i32) << sh;
5400 let qy = (r as i32) << sh;
5401 let xx = ((self.width_mb as i32) << sh) - 4;
5402 let yy = ((self.height_mb as i32) << sh) - 4;
5403 let mut px = p.0;
5404 let mut py = p.1;
5405 if qx + px < lim {
5406 px = lim - qx;
5407 }
5408 if qy + py < lim {
5409 py = lim - qy;
5410 }
5411 if qx + px > xx {
5412 px = xx - qx;
5413 }
5414 if qy + py > yy {
5415 py = yy - qy;
5416 }
5417 out[dir] = (
5418 ((px + dx + rx) & ((rx << 1) - 1)) - rx,
5419 ((py + dy + ry) & ((ry << 1) - 1)) - ry,
5420 );
5421 }
5422 out
5423 }
5424
5425 fn decode_intra(
5428 &mut self,
5429 payload: &[u8],
5430 pic: &PictureHeader,
5431 seq: &SequenceHeader,
5432 _frame: &mut YuvFrame,
5433 ) -> Result<()> {
5434 let mut br = BitReader::new_at(payload, pic.header_bits);
5435 self.vc1_reset_picture_state();
5436 let (intra_set, chroma_set) = Self::vc1_coding_sets(pic);
5437 let mb_w = self.width_mb as usize;
5438 let mb_h = self.height_mb as usize;
5439 let advanced = seq.profile == Profile::Advanced;
5440
5441 if advanced && !pic.overflags_raw {
5442 if let Some(ref flags) = pic.overflags_plane {
5443 let n = self.vc1_overflags.len().min(flags.len());
5444 self.vc1_overflags[..n].copy_from_slice(&flags[..n]);
5445 }
5446 }
5447
5448 for r in 0..mb_h {
5449 for c in 0..mb_w {
5450 let cbp = self
5451 .wmv2_mb_i_vlc
5452 .decode(&mut br)
5453 .ok_or_else(|| DecoderError::InvalidData("invalid WMV3 I CBPCY".into()))?
5454 as u8;
5455 let mbi = r * mb_w + c;
5456
5457 let acpred = if advanced {
5458 if pic.acpred_raw {
5459 br.read_bit().ok_or_else(|| {
5460 DecoderError::InvalidData(
5461 "truncated VC-1 Advanced raw ACPRED bit".into(),
5462 )
5463 })?
5464 } else {
5465 pic.acpred_plane
5466 .as_ref()
5467 .and_then(|plane| plane.get(mbi))
5468 .copied()
5469 .unwrap_or(0)
5470 != 0
5471 }
5472 } else {
5473 br.read_bit()
5474 .ok_or_else(|| DecoderError::InvalidData("truncated WMV3 ACPRED".into()))?
5475 };
5476
5477 if advanced && pic.condover == 2 && pic.overflags_raw {
5478 self.vc1_overflags[mbi] = br.read_bit().ok_or_else(|| {
5479 DecoderError::InvalidData(
5480 "truncated VC-1 Advanced raw OVERFLAGS bit".into(),
5481 )
5482 })? as u8;
5483 }
5484
5485 let mquant = if advanced {
5489 read_mquant(
5490 &mut br,
5491 &pic.dquant,
5492 pic.pquant as i32,
5493 c as u32,
5494 r as u32,
5495 self.width_mb,
5496 self.height_mb,
5497 )?
5498 } else {
5499 pic.pquant as i32
5500 };
5501 self.vc1_qscale[mbi] = mquant;
5502
5503 for blk in 0..6usize {
5504 let mut coded = ((cbp >> (5 - blk)) & 1) != 0;
5505 if blk < 4 {
5506 coded = self.vc1_coded_block_pred(r, c, blk, coded);
5507 }
5508 let mut coeff = self.vc1_decode_intra_coeffs(
5509 &mut br,
5510 pic,
5511 seq,
5512 r,
5513 c,
5514 blk,
5515 coded,
5516 mquant,
5517 acpred,
5518 true,
5519 if blk < 4 { intra_set } else { chroma_set },
5520 )?;
5521 apply_wmv3_idct(&mut coeff, TT_8X8, seq.uses_transposed_scans());
5522 let ri = vc1_recon_index(mb_w, r, c, blk);
5523 self.vc1_recon_blocks[ri] = coeff;
5524 self.vc1_intra_blocks[mbi][blk] = true;
5525 self.vc1_block_cbp[mbi][blk] = 0x0f;
5526 }
5527 }
5528 }
5529 Ok(())
5530 }
5531
5532 fn decode_p(
5533 &mut self,
5534 payload: &[u8],
5535 pic: &PictureHeader,
5536 seq: &SequenceHeader,
5537 frame: &mut YuvFrame,
5538 ) -> Result<()> {
5539 let mut reference = match self.ref_frame.clone() {
5540 Some(v) => v,
5541 None => return Ok(()),
5542 };
5543
5544 if pic.rangeredfrm {
5549 vc1_range_reduce_reference(&mut reference);
5550 }
5551
5552 if pic.mv_mode == MvMode::IntensityComp {
5555 vc1_apply_ic_reference(&mut reference, pic.lumscale, pic.lumshift);
5556 }
5557
5558 let mut br = BitReader::new_at(payload, pic.header_bits);
5559 self.vc1_reset_picture_state();
5560 let (intra_set, _) = Self::vc1_coding_sets(pic);
5561 let (quarter, _, _, _, _, _) = self.vc1_mv_params(pic);
5562 let mixed = pic.mv_mode == MvMode::MixedMv
5563 || (pic.mv_mode == MvMode::IntensityComp && pic.mv_mode2 == MvMode::MixedMv);
5564 let skip_plane = pic.skipmb_plane.as_ref();
5565 let mvtype_plane = pic.mvtypemb_plane.as_ref();
5566 let mb_w = self.width_mb as usize;
5567
5568 for r in 0..self.height_mb as usize {
5569 for c in 0..mb_w {
5570 let mbi = r * mb_w + c;
5571 let fourmv = if mixed {
5572 if pic.mvtypemb_raw {
5573 br.read_bit().ok_or_else(|| {
5574 DecoderError::InvalidData("truncated WMV3 MVTYPE".into())
5575 })?
5576 } else {
5577 mvtype_plane.and_then(|p| p.get(mbi)).copied().unwrap_or(0) != 0
5578 }
5579 } else {
5580 false
5581 };
5582 let skipped = if pic.skipmb_raw {
5583 br.read_bit()
5584 .ok_or_else(|| DecoderError::InvalidData("truncated WMV3 SKIPMB".into()))?
5585 } else {
5586 skip_plane.and_then(|p| p.get(mbi)).copied().unwrap_or(0) != 0
5587 };
5588
5589 if !fourmv {
5590 if skipped {
5591 let mv =
5592 self.vc1_predict_p_mv(&mut br, pic, seq, r, c, 0, (0, 0), true, false)?;
5593 self.vc1_chroma_mvs[mbi] = vc1_loop_chroma_mv(mv);
5594 self.vc1_mc_single(frame, r, c, &reference, mv, pic, seq, None, false);
5595 continue;
5596 }
5597
5598 let md = self.vc1_read_mvdata(&mut br, pic, quarter)?;
5599 let mv = self.vc1_predict_p_mv(
5600 &mut br,
5601 pic,
5602 seq,
5603 r,
5604 c,
5605 0,
5606 (md.dx, md.dy),
5607 true,
5608 md.intra,
5609 )?;
5610 let mut mquant = pic.pquant as i32;
5611 let mut cbp = 0u8;
5612 let mut acpred = false;
5613
5614 if md.intra && !md.has_coeffs {
5615 mquant = read_mquant(
5616 &mut br,
5617 &pic.dquant,
5618 pic.pquant as i32,
5619 c as u32,
5620 r as u32,
5621 self.width_mb,
5622 self.height_mb,
5623 )?;
5624 acpred = br.read_bit().ok_or_else(|| {
5625 DecoderError::InvalidData("truncated WMV3 ACPRED".into())
5626 })?;
5627 } else if md.has_coeffs {
5628 if md.intra {
5629 acpred = br.read_bit().ok_or_else(|| {
5630 DecoderError::InvalidData("truncated WMV3 ACPRED".into())
5631 })?;
5632 }
5633 cbp = self.vc1_cbpcy[(pic.cbptab as usize).min(3)]
5634 .decode(&mut br)
5635 .ok_or_else(|| {
5636 DecoderError::InvalidData("invalid WMV3 P CBPCY".into())
5637 })? as u8;
5638 mquant = read_mquant(
5639 &mut br,
5640 &pic.dquant,
5641 pic.pquant as i32,
5642 c as u32,
5643 r as u32,
5644 self.width_mb,
5645 self.height_mb,
5646 )?;
5647 }
5648
5649 self.vc1_qscale[mbi] = mquant;
5650 if md.intra {
5651 self.vc1_intra_blocks[mbi] = [true; 6];
5652 self.vc1_chroma_mvs[mbi] = (0, 0);
5653 } else {
5654 self.vc1_chroma_mvs[mbi] = vc1_loop_chroma_mv(mv);
5655 self.vc1_mc_single(frame, r, c, &reference, mv, pic, seq, None, false);
5656 }
5657
5658 let mut ttmb = pic.ttfrm as i32;
5659 if !pic.ttmbf && !md.intra && md.has_coeffs {
5660 ttmb = self.vc1_ttmb
5661 [((pic.pquant > 4) as usize) + ((pic.pquant > 12) as usize)]
5662 .decode(&mut br)
5663 .ok_or_else(|| DecoderError::InvalidData("invalid WMV3 TTMB".into()))?;
5664 }
5665
5666 let mut first = true;
5667 for blk in 0..6usize {
5668 let coded = ((cbp >> (5 - blk)) & 1) != 0;
5669 if md.intra {
5670 let mut co = self.vc1_decode_intra_coeffs(
5671 &mut br,
5672 pic,
5673 seq,
5674 r,
5675 c,
5676 blk,
5677 coded,
5678 mquant,
5679 acpred,
5680 false,
5681 if blk < 4 {
5682 intra_set
5683 } else {
5684 Self::vc1_coding_sets(pic).1
5685 },
5686 )?;
5687 apply_wmv3_idct(&mut co, TT_8X8, seq.uses_transposed_scans());
5688 if pic.rangeredfrm {
5689 for v in &mut co {
5690 *v *= 2;
5691 }
5692 }
5693 self.vc1_recon_blocks[vc1_recon_index(mb_w, r, c, blk)] = co;
5694 self.vc1_block_cbp[mbi][blk] = 0x0f;
5695 } else if coded {
5696 let (co, tt, pat) =
5697 self.vc1_decode_p_residual(&mut br, pic, seq, mquant, ttmb, first)?;
5698 add_residual_block(frame, r as u32, c as u32, blk, &co);
5699 self.vc1_block_tt[mbi][blk] = tt;
5700 self.vc1_block_cbp[mbi][blk] = pat;
5701 if !pic.ttmbf && ttmb < 8 {
5702 ttmb = -1;
5703 }
5704 first = false;
5705 }
5706 }
5707 } else {
5708 if skipped {
5709 let mut mvs = [(0, 0); 4];
5710 for (i, mv) in mvs.iter_mut().enumerate() {
5711 *mv = self.vc1_predict_p_mv(
5712 &mut br,
5713 pic,
5714 seq,
5715 r,
5716 c,
5717 i,
5718 (0, 0),
5719 false,
5720 false,
5721 )?;
5722 self.vc1_mc_single(
5729 frame,
5730 r,
5731 c,
5732 &reference,
5733 *mv,
5734 pic,
5735 seq,
5736 Some(i),
5737 false,
5738 );
5739 }
5740 self.vc1_current_mvs[mbi] = mvs[0];
5741 self.vc1_chroma_mvs[mbi] = self
5742 .vc1_mc_4mv_chroma(frame, r, c, &reference, mvs, [false; 4], pic, seq);
5743 continue;
5744 }
5745
5746 let cbp0 = self.vc1_cbpcy[(pic.cbptab as usize).min(3)]
5747 .decode(&mut br)
5748 .ok_or_else(|| DecoderError::InvalidData("invalid WMV3 4MV CBPCY".into()))?
5749 as u8;
5750 let mut intra = [false; 4];
5751 let mut coded = [false; 6];
5752 let mut mvs = [(0, 0); 4];
5753 for i in 0..4usize {
5754 let present = ((cbp0 >> (5 - i)) & 1) != 0;
5755 let md = if present {
5756 self.vc1_read_mvdata(&mut br, pic, quarter)?
5757 } else {
5758 Vc1MvData::default()
5759 };
5760 intra[i] = md.intra;
5761 coded[i] = if present { md.has_coeffs } else { false };
5762 mvs[i] = self.vc1_predict_p_mv(
5763 &mut br,
5764 pic,
5765 seq,
5766 r,
5767 c,
5768 i,
5769 (md.dx, md.dy),
5770 false,
5771 md.intra,
5772 )?;
5773 if !md.intra {
5780 self.vc1_mc_single(
5781 frame,
5782 r,
5783 c,
5784 &reference,
5785 mvs[i],
5786 pic,
5787 seq,
5788 Some(i),
5789 false,
5790 );
5791 }
5792 }
5793 coded[4] = (cbp0 & 2) != 0;
5794 coded[5] = (cbp0 & 1) != 0;
5795
5796 let ni = intra.iter().filter(|x| **x).count();
5797 let chroma_intra = ni >= 3;
5798 self.vc1_intra_blocks[mbi] = [
5799 intra[0],
5800 intra[1],
5801 intra[2],
5802 intra[3],
5803 chroma_intra,
5804 chroma_intra,
5805 ];
5806 let coded_inter = (0..4).any(|i| coded[i] && !intra[i])
5807 || (!chroma_intra && (coded[4] || coded[5]));
5808 let mut mquant = pic.pquant as i32;
5809 if ni > 0 || coded_inter {
5810 mquant = read_mquant(
5811 &mut br,
5812 &pic.dquant,
5813 pic.pquant as i32,
5814 c as u32,
5815 r as u32,
5816 self.width_mb,
5817 self.height_mb,
5818 )?;
5819 }
5820 self.vc1_qscale[mbi] = mquant;
5821
5822 let need_acpred =
5823 self.vc1_intra_blocks[mbi].iter().enumerate().any(|(i, v)| {
5824 *v && (self
5825 .vc1_intra_neighbour(r, c, i, true)
5826 .map(|(mi, b)| self.vc1_intra_blocks[mi][b])
5827 .unwrap_or(false)
5828 || self
5829 .vc1_intra_neighbour(r, c, i, false)
5830 .map(|(mi, b)| self.vc1_intra_blocks[mi][b])
5831 .unwrap_or(false))
5832 });
5833 let acpred = if need_acpred {
5834 br.read_bit().ok_or_else(|| {
5835 DecoderError::InvalidData("truncated WMV3 4MV ACPRED".into())
5836 })?
5837 } else {
5838 false
5839 };
5840
5841 let mut ttmb = pic.ttfrm as i32;
5842 if !pic.ttmbf && coded_inter {
5843 ttmb = self.vc1_ttmb
5844 [((pic.pquant > 4) as usize) + ((pic.pquant > 12) as usize)]
5845 .decode(&mut br)
5846 .ok_or_else(|| {
5847 DecoderError::InvalidData("invalid WMV3 4MV TTMB".into())
5848 })?;
5849 }
5850
5851 self.vc1_chroma_mvs[mbi] =
5852 self.vc1_mc_4mv_chroma(frame, r, c, &reference, mvs, intra, pic, seq);
5853
5854 let mut first = true;
5855 for blk in 0..6usize {
5856 let is_intra = if blk < 4 { intra[blk] } else { chroma_intra };
5857 if is_intra {
5858 let mut co = self.vc1_decode_intra_coeffs(
5859 &mut br,
5860 pic,
5861 seq,
5862 r,
5863 c,
5864 blk,
5865 coded[blk],
5866 mquant,
5867 acpred,
5868 false,
5869 if blk < 4 {
5870 intra_set
5871 } else {
5872 Self::vc1_coding_sets(pic).1
5873 },
5874 )?;
5875 apply_wmv3_idct(&mut co, TT_8X8, seq.uses_transposed_scans());
5876 if pic.rangeredfrm {
5877 for v in &mut co {
5878 *v *= 2;
5879 }
5880 }
5881 self.vc1_recon_blocks[vc1_recon_index(mb_w, r, c, blk)] = co;
5882 self.vc1_block_cbp[mbi][blk] = 0x0f;
5883 } else if coded[blk] {
5884 let (co, tt, pat) =
5885 self.vc1_decode_p_residual(&mut br, pic, seq, mquant, ttmb, first)?;
5886 add_residual_block(frame, r as u32, c as u32, blk, &co);
5887 self.vc1_block_tt[mbi][blk] = tt;
5888 self.vc1_block_cbp[mbi][blk] = pat;
5889 if !pic.ttmbf && ttmb < 8 {
5890 ttmb = -1;
5891 }
5892 first = false;
5893 }
5894 }
5895 self.vc1_current_mvs[mbi] = mvs[0];
5896 }
5897 }
5898 }
5899 Ok(())
5900 }
5901
5902 fn decode_b(
5903 &mut self,
5904 payload: &[u8],
5905 pic: &PictureHeader,
5906 seq: &SequenceHeader,
5907 frame: &mut YuvFrame,
5908 ) -> Result<()> {
5909 let mut fwd = match self.fwd_ref.clone() {
5910 Some(v) => v,
5911 None => return Ok(()),
5912 };
5913 let mut bwd = match self.bwd_ref.clone() {
5914 Some(v) => v,
5915 None => return Ok(()),
5916 };
5917 if pic.rangeredfrm {
5921 vc1_range_reduce_reference(&mut fwd);
5922 vc1_range_reduce_reference(&mut bwd);
5923 }
5924 if let Some((lumscale, lumshift)) = self.vc1_b_fwd_ic {
5931 vc1_apply_ic_reference(&mut fwd, lumscale, lumshift);
5932 }
5933 let mut br = BitReader::new_at(payload, pic.header_bits);
5934 self.vc1_reset_picture_state();
5935 let (intra_set, _) = Self::vc1_coding_sets(pic);
5936 let (quarter, _, _, _, _, _) = self.vc1_mv_params(pic);
5937 let nmb = self.width_mb as usize * self.height_mb as usize;
5938 let mut fhist = vec![(0, 0); nmb];
5939 let mut bhist = vec![(0, 0); nmb];
5940 for r in 0..self.height_mb as usize {
5941 for c in 0..self.width_mb as usize {
5942 let idx = r * self.width_mb as usize + c;
5943 let direct = if pic.directmb_raw {
5944 br.read_bit().ok_or_else(|| {
5945 DecoderError::InvalidData("truncated WMV3 DIRECTMB".into())
5946 })?
5947 } else {
5948 pic.directmb_plane
5949 .as_ref()
5950 .and_then(|p| p.get(idx))
5951 .copied()
5952 .unwrap_or(0)
5953 != 0
5954 };
5955 let skipped = if pic.skipmb_raw {
5956 br.read_bit().ok_or_else(|| {
5957 DecoderError::InvalidData("truncated WMV3 B SKIPMB".into())
5958 })?
5959 } else {
5960 pic.skipmb_plane
5961 .as_ref()
5962 .and_then(|p| p.get(idx))
5963 .copied()
5964 .unwrap_or(0)
5965 != 0
5966 };
5967 let mut dmv = [(0, 0); 2];
5968 let mut md = Vc1MvData::default();
5969 if !direct && !skipped {
5970 md = self.vc1_read_mvdata(&mut br, pic, quarter)?;
5971 dmv[0] = (md.dx, md.dy);
5972 dmv[1] = dmv[0];
5973 }
5974 let mut mode = 1u8;
5975 if !direct && (skipped || !md.intra) {
5976 let t = vc1_decode012_bits(&mut br)?;
5977 mode = match t {
5978 0 => {
5979 if pic.bfrac_num * 2 >= pic.bfrac_den {
5980 1
5981 } else {
5982 0
5983 }
5984 }
5985 1 => {
5986 if pic.bfrac_num * 2 >= pic.bfrac_den {
5987 0
5988 } else {
5989 1
5990 }
5991 }
5992 _ => {
5993 dmv[0] = (0, 0);
5994 2
5995 }
5996 };
5997 }
5998 if skipped {
5999 if direct {
6000 mode = 2;
6001 }
6002 let mv = self
6003 .vc1_b_predict(r, c, dmv, direct, mode, false, pic, seq, &fhist, &bhist);
6004 fhist[idx] = mv[0];
6005 bhist[idx] = mv[1];
6006 if direct || mode == 2 {
6007 self.vc1_mc_blend(frame, r, c, &fwd, &bwd, mv[0], mv[1], pic, seq);
6008 } else if mode == 0 {
6009 self.vc1_mc_single(frame, r, c, &fwd, mv[0], pic, seq, None, false);
6010 } else {
6011 self.vc1_mc_single(frame, r, c, &bwd, mv[1], pic, seq, None, false);
6012 }
6013 continue;
6014 }
6015 let mut cbp = 0u8;
6016 let mut mquant = pic.pquant as i32;
6017 let mut acpred = false;
6018 let mut ttmb = pic.ttfrm as i32;
6019 let mv;
6020 if direct {
6021 cbp = self.vc1_cbpcy[(pic.cbptab as usize).min(3)]
6022 .decode(&mut br)
6023 .ok_or_else(|| {
6024 DecoderError::InvalidData("invalid WMV3 direct CBPCY".into())
6025 })? as u8;
6026 mquant = read_mquant(
6027 &mut br,
6028 &pic.dquant,
6029 pic.pquant as i32,
6030 c as u32,
6031 r as u32,
6032 self.width_mb,
6033 self.height_mb,
6034 )?;
6035 if !pic.ttmbf {
6036 ttmb = self.vc1_ttmb
6037 [((pic.pquant > 4) as usize) + ((pic.pquant > 12) as usize)]
6038 .decode(&mut br)
6039 .ok_or_else(|| {
6040 DecoderError::InvalidData("invalid WMV3 B TTMB".into())
6041 })?;
6042 }
6043 dmv = [(0, 0); 2];
6044 mv = self.vc1_b_predict(r, c, dmv, true, 2, false, pic, seq, &fhist, &bhist);
6045 self.vc1_mc_blend(frame, r, c, &fwd, &bwd, mv[0], mv[1], pic, seq);
6046 } else if !md.has_coeffs && !md.intra {
6047 mv = self
6048 .vc1_b_predict(r, c, dmv, false, mode, md.intra, pic, seq, &fhist, &bhist);
6049 if mode == 2 {
6050 self.vc1_mc_blend(frame, r, c, &fwd, &bwd, mv[0], mv[1], pic, seq);
6051 } else if mode == 0 {
6052 self.vc1_mc_single(frame, r, c, &fwd, mv[0], pic, seq, None, false);
6053 } else {
6054 self.vc1_mc_single(frame, r, c, &bwd, mv[1], pic, seq, None, false);
6055 }
6056 fhist[idx] = mv[0];
6057 bhist[idx] = mv[1];
6058 continue;
6059 } else if md.intra && !md.has_coeffs {
6060 mquant = read_mquant(
6061 &mut br,
6062 &pic.dquant,
6063 pic.pquant as i32,
6064 c as u32,
6065 r as u32,
6066 self.width_mb,
6067 self.height_mb,
6068 )?;
6069 acpred = br.read_bit().ok_or_else(|| {
6070 DecoderError::InvalidData("truncated WMV3 B ACPRED".into())
6071 })?;
6072 mv = self
6073 .vc1_b_predict(r, c, dmv, false, mode, md.intra, pic, seq, &fhist, &bhist);
6074 } else {
6075 if mode == 2 {
6076 let md2 = self.vc1_read_mvdata(&mut br, pic, quarter)?;
6077 dmv[0] = (md2.dx, md2.dy);
6078 if !md2.has_coeffs {
6079 let mv2 = self.vc1_b_predict(
6080 r, c, dmv, false, mode, md2.intra, pic, seq, &fhist, &bhist,
6081 );
6082 self.vc1_mc_blend(frame, r, c, &fwd, &bwd, mv2[0], mv2[1], pic, seq);
6083 fhist[idx] = mv2[0];
6084 bhist[idx] = mv2[1];
6085 continue;
6086 }
6087 md.has_coeffs = md2.has_coeffs;
6088 md.intra = md2.intra;
6089 }
6090 mv = self
6091 .vc1_b_predict(r, c, dmv, false, mode, md.intra, pic, seq, &fhist, &bhist);
6092 if !md.intra {
6093 if mode == 2 {
6094 self.vc1_mc_blend(frame, r, c, &fwd, &bwd, mv[0], mv[1], pic, seq);
6095 } else if mode == 0 {
6096 self.vc1_mc_single(frame, r, c, &fwd, mv[0], pic, seq, None, false);
6097 } else {
6098 self.vc1_mc_single(frame, r, c, &bwd, mv[1], pic, seq, None, false);
6099 }
6100 }
6101 if md.intra {
6102 acpred = br.read_bit().ok_or_else(|| {
6103 DecoderError::InvalidData("truncated WMV3 B ACPRED".into())
6104 })?;
6105 }
6106 cbp = self.vc1_cbpcy[(pic.cbptab as usize).min(3)]
6107 .decode(&mut br)
6108 .ok_or_else(|| DecoderError::InvalidData("invalid WMV3 B CBPCY".into()))?
6109 as u8;
6110 mquant = read_mquant(
6111 &mut br,
6112 &pic.dquant,
6113 pic.pquant as i32,
6114 c as u32,
6115 r as u32,
6116 self.width_mb,
6117 self.height_mb,
6118 )?;
6119 if !pic.ttmbf && !md.intra && md.has_coeffs {
6120 ttmb = self.vc1_ttmb
6121 [((pic.pquant > 4) as usize) + ((pic.pquant > 12) as usize)]
6122 .decode(&mut br)
6123 .ok_or_else(|| {
6124 DecoderError::InvalidData("invalid WMV3 B TTMB".into())
6125 })?;
6126 }
6127 }
6128 self.vc1_qscale[idx] = mquant;
6129 fhist[idx] = mv[0];
6130 bhist[idx] = mv[1];
6131 let mut first = true;
6132 for blk in 0..6 {
6133 let coded = ((cbp >> (5 - blk)) & 1) != 0;
6134 if md.intra {
6135 self.vc1_intra_blocks[idx][blk] = true;
6136 let mut co = self.vc1_decode_intra_coeffs(
6137 &mut br,
6138 pic,
6139 seq,
6140 r,
6141 c,
6142 blk,
6143 coded,
6144 mquant,
6145 acpred,
6146 false,
6147 if blk < 4 {
6148 intra_set
6149 } else {
6150 Self::vc1_coding_sets(pic).1
6151 },
6152 )?;
6153 apply_wmv3_idct(&mut co, TT_8X8, seq.uses_transposed_scans());
6154 if pic.rangeredfrm {
6155 for v in &mut co {
6156 *v *= 2;
6157 }
6158 }
6159 write_intra_block(frame, r as u32, c as u32, blk, &co);
6160 } else if coded {
6161 let (co, _, _) =
6162 self.vc1_decode_p_residual(&mut br, pic, seq, mquant, ttmb, first)?;
6163 add_residual_block(frame, r as u32, c as u32, blk, &co);
6164 if !pic.ttmbf && ttmb < 8 {
6165 ttmb = -1;
6166 }
6167 first = false;
6168 }
6169 }
6170 }
6171 }
6172 Ok(())
6173 }
6174
6175 fn vc1_mc_blend(
6176 &self,
6177 frame: &mut YuvFrame,
6178 r: usize,
6179 c: usize,
6180 fwd: &YuvFrame,
6181 bwd: &YuvFrame,
6182 fmv: (i32, i32),
6183 bmv: (i32, i32),
6184 pic: &PictureHeader,
6185 seq: &SequenceHeader,
6186 ) {
6187 self.vc1_mc_single(frame, r, c, fwd, fmv, pic, seq, None, false);
6192
6193 let x0 = c * 16;
6194 let y0 = r * 16;
6195 let mut fy = [0u8; 16 * 16];
6196 for y in 0..16 {
6197 let py = y0 + y;
6198 if py >= self.height as usize {
6199 break;
6200 }
6201 for x in 0..16 {
6202 let px = x0 + x;
6203 if px >= self.width as usize {
6204 break;
6205 }
6206 fy[y * 16 + x] = frame.y[py * self.width as usize + px];
6207 }
6208 }
6209
6210 let cw = self.width as usize / 2;
6211 let ch = self.height as usize / 2;
6212 let cx0 = c * 8;
6213 let cy0 = r * 8;
6214 let mut fu = [0u8; 8 * 8];
6215 let mut fv = [0u8; 8 * 8];
6216 for y in 0..8 {
6217 let py = cy0 + y;
6218 if py >= ch {
6219 break;
6220 }
6221 for x in 0..8 {
6222 let px = cx0 + x;
6223 if px >= cw {
6224 break;
6225 }
6226 let i = py * cw + px;
6227 fu[y * 8 + x] = frame.cb[i];
6228 fv[y * 8 + x] = frame.cr[i];
6229 }
6230 }
6231
6232 self.vc1_mc_single(frame, r, c, bwd, bmv, pic, seq, None, true);
6233
6234 for y in 0..16 {
6235 let py = y0 + y;
6236 if py >= self.height as usize {
6237 break;
6238 }
6239 for x in 0..16 {
6240 let px = x0 + x;
6241 if px >= self.width as usize {
6242 break;
6243 }
6244 let i = py * self.width as usize + px;
6245 let sum = fy[y * 16 + x] as u16 + frame.y[i] as u16;
6246 frame.y[i] = ((sum + 1) >> 1) as u8;
6251 }
6252 }
6253 for y in 0..8 {
6254 let py = cy0 + y;
6255 if py >= ch {
6256 break;
6257 }
6258 for x in 0..8 {
6259 let px = cx0 + x;
6260 if px >= cw {
6261 break;
6262 }
6263 let i = py * cw + px;
6264 let us = fu[y * 8 + x] as u16 + frame.cb[i] as u16;
6265 let vs = fv[y * 8 + x] as u16 + frame.cr[i] as u16;
6266 frame.cb[i] = ((us + 1) >> 1) as u8;
6267 frame.cr[i] = ((vs + 1) >> 1) as u8;
6268 }
6269 }
6270 }
6271}
6272
6273#[inline(always)]
6295fn wmv2_dc_scale(pquant: i32, is_luma: bool) -> i32 {
6296 const Y: [i32; 32] = [
6298 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,
6299 18, 19, 19, 20, 20, 21, 21,
6300 ];
6301 const C: [i32; 32] = [
6302 0, 8, 8, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18,
6303 18, 19, 19, 20, 20, 21, 21, 22,
6304 ];
6305 let idx = pquant.clamp(1, 31) as usize;
6306 if is_luma { Y[idx] } else { C[idx] }
6307}
6308
6309#[inline(always)]
6310fn decode012(br: &mut BitReader<'_>) -> u8 {
6311 match br.read_bit() {
6313 Some(false) => 0,
6314 Some(true) => br.read_bit().map(|b| if b { 2 } else { 1 }).unwrap_or(0),
6315 None => 0,
6316 }
6317}
6318
6319#[inline(always)]
6320fn wmv2_get_cbp_table_index(qscale: i32, cbp_index: u8) -> usize {
6321 const MAP: [[u8; 3]; 3] = [[0, 2, 1], [1, 0, 2], [2, 1, 0]];
6323 let a = if qscale > 10 { 1 } else { 0 };
6324 let b = if qscale > 20 { 1 } else { 0 };
6325 let row = (a + b) as usize;
6326 MAP[row][(cbp_index as usize).min(2)] as usize
6327}
6328
6329impl MacroblockDecoder {
6330 pub fn wmv2_set_extradata(&mut self, extradata: &[u8]) {
6336 if extradata.len() < 4 {
6337 return;
6338 }
6339 let mut br = BitReader::new(&extradata[..4]);
6340 let _fps = br.read_bits(5).unwrap_or(0);
6341 let _bit_rate = br.read_bits(11).unwrap_or(0) * 1024;
6342 self.wmv2_mspel_bit = br.read_bit().unwrap_or(false);
6343 let _loop_filter = br.read_bit().unwrap_or(false);
6344 self.wmv2_abt_flag = br.read_bit().unwrap_or(false);
6345 self.wmv2_j_type_bit = br.read_bit().unwrap_or(false);
6346 self.wmv2_top_left_mv_flag = br.read_bit().unwrap_or(false);
6347 self.wmv2_per_mb_rl_bit = br.read_bit().unwrap_or(false);
6348 let code = br.read_bits(3).unwrap_or(0) as usize;
6349 if code == 0 {
6350 return;
6351 }
6352 let mb_h = self.height_mb as usize;
6353 self.wmv2_slice_height = mb_h / code;
6354 }
6355
6356 pub fn wmv2_copy_ref(&self, out: &mut YuvFrame) -> bool {
6357 let Some(r) = self.wmv2_ref.as_ref() else {
6358 return false;
6359 };
6360 if out.width != r.width || out.height != r.height {
6361 *out = r.clone();
6362 return true;
6363 }
6364 if out.y.len() == r.y.len() {
6365 out.y.copy_from_slice(&r.y);
6366 } else {
6367 out.y = r.y.clone();
6368 }
6369 if out.cb.len() == r.cb.len() {
6370 out.cb.copy_from_slice(&r.cb);
6371 } else {
6372 out.cb = r.cb.clone();
6373 }
6374 if out.cr.len() == r.cr.len() {
6375 out.cr.copy_from_slice(&r.cr);
6376 } else {
6377 out.cr = r.cr.clone();
6378 }
6379 true
6380 }
6381
6382 pub fn decode_wmv2_frame(
6383 &mut self,
6384 payload: &[u8],
6385 hdr: &Wmv2FrameHeader,
6386 params: &Wmv2Params,
6387 frame: &mut YuvFrame,
6388 ) -> Result<()> {
6389 if self.width != params.width || self.height != params.height {
6391 *self = MacroblockDecoder::new(params.width, params.height);
6392 }
6393
6394 if hdr.frame_skipped {
6395 let _ = self.wmv2_copy_ref(frame);
6396 return Ok(());
6397 }
6398 match hdr.frame_type {
6399 Wmv2FrameType::I => self.wmv2_decode_intra(payload, hdr, frame),
6400 Wmv2FrameType::P => self.wmv2_decode_p(payload, hdr, frame),
6401 }
6402 }
6403
6404 pub fn probe_wmv2_payload(&self, payload: &[u8], hdr: &Wmv2FrameHeader) -> usize {
6410 let mut br = BitReader::new_at(payload, hdr.header_bits);
6411
6412 if hdr.frame_type == Wmv2FrameType::I {
6414 let mut br = BitReader::new_at(payload, hdr.header_bits);
6415 let j_type = if self.wmv2_j_type_bit {
6417 br.read_bit().unwrap_or(false)
6418 } else {
6419 false
6420 };
6421 if j_type {
6422 return 1;
6423 }
6424 let per_mb_rl_table = if self.wmv2_per_mb_rl_bit {
6425 br.read_bit().unwrap_or(false)
6426 } else {
6427 false
6428 };
6429 if !per_mb_rl_table {
6430 let _ = decode012(&mut br);
6431 let _ = decode012(&mut br);
6432 }
6433 let dc_table_index = br.read_bit().unwrap_or(false) as usize;
6434 let code = match self.wmv2_mb_i_vlc.decode(&mut br) {
6435 Some(v) => v as u32,
6436 None => return 0,
6437 };
6438 let _ = code;
6439 let _ac_pred = br.read_bit().unwrap_or(false);
6440 let _ = _ac_pred;
6441 if per_mb_rl_table && code != 0 {
6442 let _ = decode012(&mut br);
6443 }
6444 const DC_MAX: i32 = 119;
6446 for blk in 0..6usize {
6447 let is_chroma = blk >= 4;
6448 let tbl = &self.wmv2_dc_vlc[dc_table_index][if is_chroma { 1 } else { 0 }];
6449 let level = match tbl.decode(&mut br) {
6450 Some(v) => v,
6451 None => return 0,
6452 };
6453 if level == DC_MAX {
6454 let _ = br.read_bits(8);
6455 let _ = br.read_bit();
6456 } else if level != 0 {
6457 let _ = br.read_bit();
6458 }
6459 }
6460 return 1;
6461 }
6462
6463 if hdr.frame_type == Wmv2FrameType::P {
6465 let mut br = BitReader::new_at(payload, hdr.header_bits);
6466 let mb_w = self.width_mb as usize;
6467 let mb_h = self.height_mb as usize;
6468 let qscale = hdr.pquant as i32;
6469
6470 let skip_type = br.read_bits(2).unwrap_or(0) as u8;
6472 let first_skip = match skip_type {
6473 0 => false,
6474 1 => br.read_bit().unwrap_or(false),
6475 2 => {
6476 let all = br.read_bit().unwrap_or(false);
6477 if all {
6478 true
6479 } else {
6480 br.read_bit().unwrap_or(false)
6481 }
6482 }
6483 3 => {
6484 let all = br.read_bit().unwrap_or(false);
6485 if all {
6486 true
6487 } else {
6488 br.read_bit().unwrap_or(false)
6489 }
6490 }
6491 _ => false,
6492 };
6493
6494 if skip_type == 1 {
6497 let _ = mb_w * mb_h;
6498 }
6499
6500 let cbp_index = decode012(&mut br);
6501 let cbp_table_index = wmv2_get_cbp_table_index(qscale, cbp_index);
6502
6503 let _mspel = if self.wmv2_mspel_bit {
6504 br.read_bit().unwrap_or(false)
6505 } else {
6506 false
6507 };
6508 if self.wmv2_abt_flag {
6509 let per_mb_abt = br.read_bit().unwrap_or(false) ^ true;
6510 if !per_mb_abt {
6511 let _ = decode012(&mut br);
6512 }
6513 }
6514 let per_mb_rl_table = if self.wmv2_per_mb_rl_bit {
6515 br.read_bit().unwrap_or(false)
6516 } else {
6517 false
6518 };
6519 if !per_mb_rl_table {
6520 let _ = decode012(&mut br);
6521 }
6522 let dc_table_index = br.read_bit().unwrap_or(false) as usize;
6523 let mv_table_index = br.read_bit().unwrap_or(false) as usize;
6524
6525 if first_skip {
6526 return 1;
6527 }
6528
6529 let code = match self.wmv2_mb_non_intra_vlc[cbp_table_index.min(3)].decode(&mut br) {
6530 Some(v) => v,
6531 None => return 0,
6532 };
6533 let mb_intra = (code & 0x40) == 0;
6534 let cbp = (code & 0x3f) as u8;
6535
6536 if mb_intra {
6537 let _ac_pred = br.read_bit().unwrap_or(false);
6538 if per_mb_rl_table && cbp != 0 {
6539 let _ = decode012(&mut br);
6540 }
6541 const DC_MAX: i32 = 119;
6543 let tbl = &self.wmv2_dc_vlc[dc_table_index][0];
6544 let level = match tbl.decode(&mut br) {
6545 Some(v) => v,
6546 None => return 0,
6547 };
6548 if level == DC_MAX {
6549 let _ = br.read_bits(8);
6550 let _ = br.read_bit();
6551 } else if level != 0 {
6552 let _ = br.read_bit();
6553 }
6554 } else {
6555 let tbl = &self.wmv2_mv_vlc[mv_table_index.min(1)];
6557 let sym = match tbl.decode(&mut br) {
6558 Some(v) => v as u16,
6559 None => return 0,
6560 };
6561 if sym == 0 {
6562 let _ = br.read_bits(12);
6563 }
6564 }
6565 return 1;
6566 }
6567
6568 let max_mb = (self.width_mb as usize * self.height_mb as usize).min(64);
6569 let mut score: usize = 0;
6570
6571 let ac_intra = &self.wmv2_intra[0];
6573 let ac_inter = &self.wmv2_inter[0];
6574
6575 for _ in 0..max_mb {
6576 if br.is_empty() {
6577 break;
6578 }
6579
6580 let cbpc_sym = match self.wmv2_cbpc.decode(&mut br) {
6581 Some(v) => v,
6582 None => break,
6583 };
6584 if cbpc_sym == -1 {
6585 score += 1;
6586 continue;
6587 }
6588 if !(0..=3).contains(&cbpc_sym) {
6589 break;
6590 }
6591
6592 let is_intra = match br.read_bit() {
6593 Some(b) => b,
6594 None => break,
6595 };
6596
6597 let cbpy_raw = match self.wmv2_cbpy.decode(&mut br) {
6598 Some(v @ 0..=15) => v as u8,
6599 _ => break,
6600 };
6601
6602 let cbpy = if is_intra { cbpy_raw } else { cbpy_raw ^ 0x0F };
6603 let cbp: u8 = (cbpy << 2) | (cbpc_sym as u8 & 0x03);
6604
6605 if cbp != 0 {
6606 let vlc = if is_intra { ac_intra } else { ac_inter };
6607 let sym = match vlc.decode(&mut br) {
6608 Some(s) => s,
6609 None => break,
6610 };
6611 if sym == VLC_ESCAPE {
6612 let _ = decode_escape_coeff(&mut br, vlc);
6614 } else {
6615 let _ = br.read_bit();
6617 }
6618 }
6619
6620 score += 1;
6621 }
6622
6623 score
6624 }
6625
6626 #[inline(always)]
6629 fn wmv2_coded_block_pred(&self, mb_row: usize, mb_col: usize, blk: usize) -> u8 {
6630 let bw = (self.width_mb as usize) * 2;
6632 let bx = mb_col * 2 + (blk & 1);
6633 let by = mb_row * 2 + (blk >> 1);
6634 let idx = by * bw + bx;
6635 let a = if bx > 0 {
6636 self.wmv2_coded_block[idx - 1]
6637 } else {
6638 0
6639 };
6640 let b = if bx > 0 && by > 0 {
6641 self.wmv2_coded_block[idx - 1 - bw]
6642 } else {
6643 0
6644 };
6645 let c = if by > 0 {
6646 self.wmv2_coded_block[idx - bw]
6647 } else {
6648 0
6649 };
6650 if b == c { a } else { c }
6651 }
6652
6653 #[inline(always)]
6654 fn wmv2_coded_block_store(&mut self, mb_row: usize, mb_col: usize, blk: usize, v: u8) {
6655 let bw = (self.width_mb as usize) * 2;
6656 let bx = mb_col * 2 + (blk & 1);
6657 let by = mb_row * 2 + (blk >> 1);
6658 let idx = by * bw + bx;
6659 if idx < self.wmv2_coded_block.len() {
6660 self.wmv2_coded_block[idx] = v;
6661 }
6662 }
6663
6664 #[inline(always)]
6665 fn wmv2_decode_dc_diff(&self, br: &mut BitReader<'_>, is_chroma: bool) -> i32 {
6666 const DC_MAX: i32 = 119;
6668 let tbl = &self.wmv2_dc_vlc[self.wmv2_dc_table_index][if is_chroma { 1 } else { 0 }];
6669 let mut level = tbl.decode(br).unwrap_or(0);
6670 if level == DC_MAX {
6671 let v = br.read_bits(8).unwrap_or(0) as i32;
6672 let sign = br.read_bit().unwrap_or(false);
6673 return if sign { -v } else { v };
6674 }
6675 if level != 0 {
6676 let sign = br.read_bit().unwrap_or(false);
6677 if sign {
6678 level = -level;
6679 }
6680 }
6681 level
6682 }
6683
6684 #[inline(always)]
6685 fn wmv2_reset_picture_state(&mut self) {
6686 self.wmv2_esc3_level_length = 0;
6687 self.wmv2_esc3_run_length = 0;
6688 for v in self.wmv2_ac_val.iter_mut() {
6689 *v = [0i16; 16];
6690 }
6691 }
6692
6693 #[inline(always)]
6694 fn wmv2_ac_val_idx(&self, mb_row: usize, mb_col: usize, blk: usize) -> usize {
6695 let mb_w = self.width_mb as usize;
6696 (mb_row * mb_w + mb_col) * 6 + blk
6697 }
6698
6699 #[inline(always)]
6700 fn wmv2_get_ac_val(&self, mb_row: usize, mb_col: usize, blk: usize) -> [i16; 16] {
6701 let idx = self.wmv2_ac_val_idx(mb_row, mb_col, blk);
6702 if idx < self.wmv2_ac_val.len() {
6703 self.wmv2_ac_val[idx]
6704 } else {
6705 [0i16; 16]
6706 }
6707 }
6708
6709 #[inline(always)]
6710 fn wmv2_set_ac_val(&mut self, mb_row: usize, mb_col: usize, blk: usize, v: [i16; 16]) {
6711 let idx = self.wmv2_ac_val_idx(mb_row, mb_col, blk);
6712 if idx < self.wmv2_ac_val.len() {
6713 self.wmv2_ac_val[idx] = v;
6714 }
6715 }
6716
6717 #[inline(always)]
6718 fn wmv2_pred_ac(
6719 &mut self,
6720 mb_row: usize,
6721 mb_col: usize,
6722 blk: usize,
6723 dc_pred_dir: i32,
6724 ac_pred: bool,
6725 block: &mut [i16; 64],
6726 ) {
6727 let mut cur = self.wmv2_get_ac_val(mb_row, mb_col, blk);
6732
6733 if ac_pred {
6734 if dc_pred_dir == 0 {
6735 let (src_r, src_c, src_b) = match blk {
6737 1 => (mb_row, mb_col, 0),
6738 3 => (mb_row, mb_col, 2),
6739 0 => (mb_row, mb_col.saturating_sub(1), 1),
6740 2 => (mb_row, mb_col.saturating_sub(1), 3),
6741 4 | 5 => (mb_row, mb_col.saturating_sub(1), blk),
6742 _ => (mb_row, mb_col.saturating_sub(1), blk),
6743 };
6744 if (blk == 1 || blk == 3) || mb_col > 0 {
6745 let src = self.wmv2_get_ac_val(src_r, src_c, src_b);
6746 for i in 1..8usize {
6747 let idx = i << 3;
6748 block[idx] = block[idx].wrapping_add(src[i]);
6749 }
6750 }
6751 } else {
6752 let (src_r, src_c, src_b) = match blk {
6754 2 => (mb_row, mb_col, 0),
6755 3 => (mb_row, mb_col, 1),
6756 0 => (mb_row.saturating_sub(1), mb_col, 2),
6757 1 => (mb_row.saturating_sub(1), mb_col, 3),
6758 4 | 5 => (mb_row.saturating_sub(1), mb_col, blk),
6759 _ => (mb_row.saturating_sub(1), mb_col, blk),
6760 };
6761 if (blk == 2 || blk == 3) || mb_row > 0 {
6762 let src = self.wmv2_get_ac_val(src_r, src_c, src_b);
6763 for i in 1..8usize {
6764 block[i] = block[i].wrapping_add(src[8 + i]);
6765 }
6766 }
6767 }
6768 }
6769
6770 for i in 1..8usize {
6772 cur[i] = block[i << 3];
6773 }
6774 cur[9..16].copy_from_slice(&block[1..8]);
6775 self.wmv2_set_ac_val(mb_row, mb_col, blk, cur);
6776 }
6777
6778 #[inline(always)]
6779 fn wmv2_unquantize_h263_intra(&self, block: &mut [i16; 64], qscale: i32, dc_scale: i32) {
6780 let qmul = qscale << 1;
6782 let qadd = (qscale - 1) | 1;
6783
6784 block[0] = ((block[0] as i32) * dc_scale) as i16;
6785 for i in 1..64usize {
6786 let mut level = block[i] as i32;
6787 if level != 0 {
6788 if level < 0 {
6789 level = level * qmul - qadd;
6790 } else {
6791 level = level * qmul + qadd;
6792 }
6793 block[i] = level as i16;
6794 }
6795 }
6796 }
6797
6798 fn wmv2_decode_block_intra_ref(
6799 &mut self,
6800 br: &mut BitReader<'_>,
6801 mb_row: usize,
6802 mb_col: usize,
6803 blk: usize,
6804 coded: bool,
6805 qscale: i32,
6806 ac_pred: bool,
6807 ) -> Result<[i16; 64]> {
6808 let is_luma = blk < 4;
6809 let dc_scale = wmv2_dc_scale(qscale, is_luma);
6810
6811 let diff = self.wmv2_decode_dc_diff(br, !is_luma);
6813 let (pred_level, dir) = self.wmv2_dc_pred.predict(mb_row, mb_col, blk, dc_scale);
6814 let level = pred_level + diff;
6815 self.wmv2_dc_pred
6816 .store(mb_row, mb_col, blk, level * dc_scale);
6817
6818 let mut block = [0i16; 64];
6819 block[0] = level as i16;
6820
6821 let rl = if is_luma {
6823 &self.wmv2_rl[(self.wmv2_rl_table_index as usize).min(2)]
6824 } else {
6825 &self.wmv2_rl[3 + (self.wmv2_rl_chroma_table_index as usize).min(2)]
6826 };
6827
6828 let scan = if ac_pred {
6830 if dir == 0 {
6831 &FF_WMV1_SCANTABLE[3] } else {
6833 &FF_WMV1_SCANTABLE[2] }
6835 } else {
6836 &FF_WMV1_SCANTABLE[1] };
6838
6839 let mut i: i32 = 0;
6840 let qmul: i32 = 1;
6841 let run_diff: i32 = 1; if coded {
6844 loop {
6845 let (mut level_uq, mut run) = rl
6846 .decode_sym(br, 0)
6847 .ok_or_else(|| DecoderError::InvalidData("WMV2: tcoeff VLC underrun".into()))?;
6848
6849 if level_uq == 0 {
6850 let b0 = br.peek_bits(1).unwrap_or(0);
6852 if b0 == 1 {
6853 br.skip_bits(1);
6855 let (lvl2, run2) = rl.decode_sym(br, 0).ok_or_else(|| {
6856 DecoderError::InvalidData("WMV2: escape1 VLC underrun".into())
6857 })?;
6858 level_uq = lvl2;
6859 run = run2;
6860 i += run;
6861 let last = ((run >> 7) & 1) as usize;
6862 let base_run = ((run - 1) & 63) as usize;
6863 level_uq += rl.max_level_for(last, base_run) * qmul;
6864 let sign = br.read_bit().unwrap_or(false);
6865 if sign {
6866 level_uq = -level_uq;
6867 }
6868 } else {
6869 let b1 = br.peek_bits(2).unwrap_or(0) & 1;
6870 if b1 == 1 {
6871 br.skip_bits(2);
6873 let (lvl2, run2) = rl.decode_sym(br, 0).ok_or_else(|| {
6874 DecoderError::InvalidData("WMV2: escape2 VLC underrun".into())
6875 })?;
6876 level_uq = lvl2;
6877 run = run2;
6878 let last = ((run >> 7) & 1) as usize;
6879 let base_level = (level_uq / qmul).unsigned_abs() as usize;
6880 i += run + rl.max_run_for(last, base_level) + run_diff;
6881 let sign = br.read_bit().unwrap_or(false);
6882 if sign {
6883 level_uq = -level_uq;
6884 }
6885 } else {
6886 br.skip_bits(2);
6888 let last = br.read_bit().unwrap_or(false);
6889 if self.wmv2_esc3_level_length == 0 {
6890 let ll: u8 = if qscale < 8 {
6892 let mut x = br.read_bits(3).unwrap_or(0) as u8;
6893 if x == 0 {
6894 x = 8 + br.read_bits(1).unwrap_or(0) as u8;
6895 }
6896 x
6897 } else {
6898 let mut x: u8 = 2;
6899 while x < 8 && br.peek_bits(1).unwrap_or(1) == 0 {
6900 br.skip_bits(1);
6901 x += 1;
6902 }
6903 if x < 8 {
6904 br.skip_bits(1);
6905 }
6906 x
6907 };
6908 self.wmv2_esc3_level_length = ll;
6909 self.wmv2_esc3_run_length =
6910 (br.read_bits(2).unwrap_or(0) as u8) + 3;
6911 }
6912 let run_abs =
6913 br.read_bits(self.wmv2_esc3_run_length).unwrap_or(0) as i32;
6914 let sign = br.read_bit().unwrap_or(false);
6915 let mut lvl_abs =
6916 br.read_bits(self.wmv2_esc3_level_length).unwrap_or(0) as i32;
6917 if sign {
6918 lvl_abs = -lvl_abs;
6919 }
6920 level_uq = lvl_abs;
6921 i += run_abs + 1;
6922 if last {
6923 i += 192;
6924 }
6925 }
6926 }
6927 } else {
6928 i += run;
6929 let sign = br.read_bit().unwrap_or(false);
6930 if sign {
6931 level_uq = -level_uq;
6932 }
6933 }
6934
6935 if i > 62 {
6936 i -= 192;
6937 if (i & !63) != 0 {
6938 i = 63;
6939 }
6940 if i < 0 {
6941 return Err(DecoderError::InvalidData(
6942 "WMV2: negative coeff index (bitstream damaged)".into(),
6943 ));
6944 }
6945 let pos = scan[i as usize];
6946 if pos < 64 {
6947 block[pos] = level_uq as i16;
6948 }
6949 break;
6950 }
6951
6952 if i < 0 {
6953 return Err(DecoderError::InvalidData(
6954 "WMV2: negative coeff index (bitstream damaged)".into(),
6955 ));
6956 }
6957 let pos = scan[i as usize];
6958 if pos < 64 {
6959 block[pos] = level_uq as i16;
6960 }
6961 }
6962 }
6963
6964 self.wmv2_pred_ac(mb_row, mb_col, blk, dir, ac_pred, &mut block);
6966
6967 self.wmv2_unquantize_h263_intra(&mut block, qscale, dc_scale);
6969
6970 Ok(block)
6971 }
6972 fn wmv2_decode_block_inter_ref(
6973 &mut self,
6974 br: &mut BitReader<'_>,
6975 blk: usize,
6976 coded: bool,
6977 qscale: i32,
6978 scan: &[usize; 64],
6979 ) -> Result<[i16; 64]> {
6980 let mut block = [0i16; 64];
6981 if !coded {
6982 return Ok(block);
6983 }
6984
6985 let rl = &self.wmv2_rl[3 + (self.wmv2_rl_table_index as usize).min(2)];
6986
6987 let qmul = qscale << 1;
6988 let qadd = (qscale - 1) | 1;
6989 let run_diff: i32 = 1; let mut i: i32 = -1;
6992
6993 loop {
6994 let (mut level_uq, mut run) = rl.decode_sym(br, qscale).ok_or_else(|| {
6995 DecoderError::InvalidData("WMV2: inter tcoeff VLC underrun".into())
6996 })?;
6997
6998 if level_uq == 0 {
6999 let b0 = br.peek_bits(1).unwrap_or(0);
7001 if b0 == 1 {
7002 br.skip_bits(1);
7004 let (lvl2, run2) = rl.decode_sym(br, qscale).ok_or_else(|| {
7005 DecoderError::InvalidData("WMV2: inter escape1 VLC underrun".into())
7006 })?;
7007 level_uq = lvl2;
7008 run = run2;
7009 i += run;
7010 let last = ((run >> 7) & 1) as usize;
7011 let base_run = ((run - 1) & 63) as usize;
7012 level_uq += rl.max_level_for(last, base_run) * qmul;
7013 let sign = br.read_bit().unwrap_or(false);
7014 if sign {
7015 level_uq = -level_uq;
7016 }
7017 } else {
7018 let b1 = br.peek_bits(2).unwrap_or(0) & 1;
7019 if b1 == 1 {
7020 br.skip_bits(2);
7022 let (lvl2, run2) = rl.decode_sym(br, qscale).ok_or_else(|| {
7023 DecoderError::InvalidData("WMV2: inter escape2 VLC underrun".into())
7024 })?;
7025 level_uq = lvl2;
7026 run = run2;
7027 let last = ((run >> 7) & 1) as usize;
7028 let base_level = (level_uq / qmul).unsigned_abs() as usize;
7029 i += run + rl.max_run_for(last, base_level) + run_diff;
7030 let sign = br.read_bit().unwrap_or(false);
7031 if sign {
7032 level_uq = -level_uq;
7033 }
7034 } else {
7035 br.skip_bits(2);
7037 let last = br.read_bit().unwrap_or(false);
7038 if self.wmv2_esc3_level_length == 0 {
7039 let ll: u8 = if qscale < 8 {
7040 let mut x = br.read_bits(3).unwrap_or(0) as u8;
7041 if x == 0 {
7042 x = 8 + br.read_bits(1).unwrap_or(0) as u8;
7043 }
7044 x
7045 } else {
7046 let mut x: u8 = 2;
7047 while x < 8 && br.peek_bits(1).unwrap_or(1) == 0 {
7048 br.skip_bits(1);
7049 x += 1;
7050 }
7051 if x < 8 {
7052 br.skip_bits(1);
7053 }
7054 x
7055 };
7056 self.wmv2_esc3_level_length = ll;
7057 self.wmv2_esc3_run_length = (br.read_bits(2).unwrap_or(0) as u8) + 3;
7058 }
7059 let run_abs = br.read_bits(self.wmv2_esc3_run_length).unwrap_or(0) as i32;
7060 let sign = br.read_bit().unwrap_or(false);
7061 let mut lvl_abs =
7062 br.read_bits(self.wmv2_esc3_level_length).unwrap_or(0) as i32;
7063 if sign {
7064 lvl_abs = -lvl_abs;
7065 }
7066 if lvl_abs > 0 {
7067 level_uq = lvl_abs * qmul + qadd;
7068 } else {
7069 level_uq = lvl_abs * qmul - qadd;
7070 }
7071 i += run_abs + 1;
7072 if last {
7073 i += 192;
7074 }
7075 }
7076 }
7077 } else {
7078 i += run;
7079 let sign = br.read_bit().unwrap_or(false);
7080 if sign {
7081 level_uq = -level_uq;
7082 }
7083 }
7084
7085 if i > 62 {
7086 i -= 192;
7087 if (i & !63) != 0 {
7088 i = 63;
7089 }
7090 if i < 0 {
7091 return Err(DecoderError::InvalidData(
7092 "WMV2: negative coeff index (bitstream damaged)".into(),
7093 ));
7094 }
7095 let pos = scan[i as usize];
7096 if pos < 64 {
7097 block[pos] = level_uq as i16;
7098 }
7099 break;
7100 }
7101
7102 if i < 0 {
7103 return Err(DecoderError::InvalidData(
7104 "WMV2: negative coeff index (bitstream damaged)".into(),
7105 ));
7106 }
7107 let pos = scan[i as usize];
7108 if pos < 64 {
7109 block[pos] = level_uq as i16;
7110 }
7111 }
7112
7113 let _ = blk;
7114 Ok(block)
7115 }
7116 fn wmv2_parse_mb_skip(
7117 &mut self,
7118 br: &mut BitReader<'_>,
7119 mb_w: usize,
7120 mb_h: usize,
7121 ) -> Result<()> {
7122 let skip_type = br
7124 .read_bits(2)
7125 .ok_or_else(|| DecoderError::InvalidData("WMV2: missing skip_type".into()))?
7126 as u8;
7127 self.wmv2_skip_type = skip_type;
7128 if self.wmv2_mb_skip.len() != mb_w * mb_h {
7129 self.wmv2_mb_skip.resize(mb_w * mb_h, false);
7130 }
7131 for v in self.wmv2_mb_skip.iter_mut() {
7132 *v = false;
7133 }
7134
7135 match skip_type {
7136 0 => {
7137 }
7139 1 => {
7140 if br.bits_left() < (mb_w * mb_h) as isize {
7142 return Err(DecoderError::InvalidData("WMV2: skip map truncated".into()));
7143 }
7144 for y in 0..mb_h {
7145 for x in 0..mb_w {
7146 let b = br.read_bit().unwrap_or(false);
7147 self.wmv2_mb_skip[y * mb_w + x] = b;
7148 }
7149 }
7150 }
7151 2 => {
7152 for y in 0..mb_h {
7154 let all = br.read_bit().ok_or_else(|| {
7155 DecoderError::InvalidData("WMV2: skip row flag missing".into())
7156 })?;
7157 if all {
7158 for x in 0..mb_w {
7159 self.wmv2_mb_skip[y * mb_w + x] = true;
7160 }
7161 } else {
7162 for x in 0..mb_w {
7163 let b = br.read_bit().unwrap_or(false);
7164 self.wmv2_mb_skip[y * mb_w + x] = b;
7165 }
7166 }
7167 }
7168 }
7169 3 => {
7170 for x in 0..mb_w {
7172 let all = br.read_bit().ok_or_else(|| {
7173 DecoderError::InvalidData("WMV2: skip col flag missing".into())
7174 })?;
7175 if all {
7176 for y in 0..mb_h {
7177 self.wmv2_mb_skip[y * mb_w + x] = true;
7178 }
7179 } else {
7180 for y in 0..mb_h {
7181 let b = br.read_bit().unwrap_or(false);
7182 self.wmv2_mb_skip[y * mb_w + x] = b;
7183 }
7184 }
7185 }
7186 }
7187 _ => {}
7188 }
7189
7190 let coded = self.wmv2_mb_skip.iter().filter(|s| !**s).count();
7192 if coded as isize > br.bits_left() {
7193 return Err(DecoderError::InvalidData(
7194 "WMV2: coded MB count exceeds remaining bits".into(),
7195 ));
7196 }
7197 Ok(())
7198 }
7199
7200 #[inline(always)]
7201 fn wmv2_motion_get(&self, mb_row: isize, mb_col: isize) -> (i32, i32) {
7202 if mb_row < 0 || mb_col < 0 {
7203 return (0, 0);
7204 }
7205 let mb_w = self.width_mb as isize;
7206 let mb_h = self.height_mb as isize;
7207 if mb_row >= mb_h || mb_col >= mb_w {
7208 return (0, 0);
7209 }
7210 let idx = (mb_row as usize) * (mb_w as usize) + (mb_col as usize);
7211 if idx < self.wmv2_motion.len() {
7212 self.wmv2_motion[idx]
7213 } else {
7214 (0, 0)
7215 }
7216 }
7217
7218 #[inline(always)]
7219 fn wmv2_motion_set(&mut self, mb_row: usize, mb_col: usize, mv: (i32, i32)) {
7220 let mb_w = self.width_mb as usize;
7221 let idx = mb_row * mb_w + mb_col;
7222 if self.wmv2_motion.len() != mb_w * (self.height_mb as usize) {
7223 self.wmv2_motion
7224 .resize(mb_w * (self.height_mb as usize), (0, 0));
7225 }
7226 if idx < self.wmv2_motion.len() {
7227 self.wmv2_motion[idx] = mv;
7228 }
7229 }
7230
7231 #[inline(always)]
7232 fn wmv2_pred_motion(
7233 &self,
7234 br: &mut BitReader<'_>,
7235 mb_row: usize,
7236 mb_col: usize,
7237 first_slice_line: bool,
7238 ) -> (i32, i32) {
7239 let a = self.wmv2_motion_get(mb_row as isize, mb_col as isize - 1);
7241 let b = self.wmv2_motion_get(mb_row as isize - 1, mb_col as isize);
7242 let c = self.wmv2_motion_get(mb_row as isize - 1, mb_col as isize + 1);
7243
7244 let diff =
7245 if mb_col != 0 && !first_slice_line && !self.wmv2_mspel && self.wmv2_top_left_mv_flag {
7246 let dx = (a.0 - b.0).abs();
7247 let dy = (a.1 - b.1).abs();
7248 dx.max(dy)
7249 } else {
7250 0
7251 };
7252
7253 let t = if diff >= 8 {
7254 if br.read_bit().unwrap_or(false) { 1 } else { 0 }
7255 } else {
7256 2
7257 };
7258
7259 match t {
7260 0 => a,
7261 1 => b,
7262 _ => {
7263 if first_slice_line {
7264 a
7265 } else {
7266 (mid_pred(a.0, b.0, c.0), mid_pred(a.1, b.1, c.1))
7267 }
7268 }
7269 }
7270 }
7271
7272 #[inline(always)]
7273 fn wmv2_decode_motion_ref(&self, br: &mut BitReader<'_>, pred: (i32, i32)) -> (i32, i32) {
7274 let tbl = &self.wmv2_mv_vlc[self.wmv2_mv_table_index.min(1)];
7276 let sym = tbl.decode(br).unwrap_or(0) as u16;
7277 let (mut mx, mut my) = if sym != 0 {
7278 ((sym >> 8) as i32, (sym & 0xff) as i32)
7279 } else {
7280 (
7282 br.read_bits(6).unwrap_or(0) as i32,
7283 br.read_bits(6).unwrap_or(0) as i32,
7284 )
7285 };
7286
7287 mx += pred.0 - 32;
7288 my += pred.1 - 32;
7289 if mx <= -64 {
7291 mx += 64;
7292 } else if mx >= 64 {
7293 mx -= 64;
7294 }
7295 if my <= -64 {
7296 my += 64;
7297 } else if my >= 64 {
7298 my -= 64;
7299 }
7300 (mx, my)
7301 }
7302
7303 fn wmv2_decode_intra(
7306 &mut self,
7307 payload: &[u8],
7308 hdr: &Wmv2FrameHeader,
7309 frame: &mut YuvFrame,
7310 ) -> Result<()> {
7311 let mut br = BitReader::new_at(payload, hdr.header_bits);
7313
7314 self.wmv2_j_type = if self.wmv2_j_type_bit {
7317 br.read_bit().unwrap_or(false)
7318 } else {
7319 false
7320 };
7321 if self.wmv2_j_type {
7322 return Ok(());
7324 }
7325
7326 self.wmv2_per_mb_rl_table = if self.wmv2_per_mb_rl_bit {
7327 br.read_bit().unwrap_or(false)
7328 } else {
7329 false
7330 };
7331 if !self.wmv2_per_mb_rl_table {
7332 self.wmv2_rl_chroma_table_index = decode012(&mut br);
7333 self.wmv2_rl_table_index = decode012(&mut br);
7334 }
7335 self.wmv2_dc_table_index = br.read_bit().unwrap_or(false) as usize;
7336
7337 let mb_w = self.width_mb as usize;
7338 let mb_h = self.height_mb as usize;
7339
7340 self.wmv2_dc_pred = Wmv2DcPredBuffer::new(mb_w, mb_h);
7342 for v in self.wmv2_coded_block.iter_mut() {
7343 *v = 0;
7344 }
7345
7346 self.wmv2_reset_picture_state();
7347
7348 let qscale = hdr.pquant as i32;
7349 for mb_row in 0..mb_h {
7353 for mb_col in 0..mb_w {
7354 if br.is_empty() {
7355 break;
7356 }
7357
7358 let code = self.wmv2_mb_i_vlc.decode(&mut br).unwrap_or(0) as u32;
7360
7361 let mut cbp: u8 = 0;
7363 for i in 0..6usize {
7364 let mut val = ((code >> (5 - i)) & 1) as u8;
7365 if i < 4 {
7366 let pred = self.wmv2_coded_block_pred(mb_row, mb_col, i);
7367 val ^= pred;
7368 self.wmv2_coded_block_store(mb_row, mb_col, i, val);
7369 }
7370 cbp |= val << (5 - i);
7371 }
7372
7373 let ac_pred = br.read_bit().unwrap_or(false);
7375
7376 if self.wmv2_per_mb_rl_table && cbp != 0 {
7378 let rl_idx = decode012(&mut br);
7379 self.wmv2_rl_table_index = rl_idx;
7380 self.wmv2_rl_chroma_table_index = rl_idx;
7381 }
7382
7383 for blk in 0..6usize {
7384 let coded = ((cbp >> (5 - blk)) & 1) != 0;
7385 let mut block = self.wmv2_decode_block_intra_ref(
7386 &mut br, mb_row, mb_col, blk, coded, qscale, ac_pred,
7387 )?;
7388
7389 let (is_luma, bx, by, stride, _ph) =
7390 block_coords(mb_row as u32, mb_col as u32, blk, frame.width, frame.height);
7391 let plane: &mut Vec<u8> = if is_luma {
7392 &mut frame.y
7393 } else if blk == 4 {
7394 &mut frame.cb
7395 } else {
7396 &mut frame.cr
7397 };
7398 let dst_off = by * stride + bx;
7399 wmv2dsp::wmv2_idct_put(plane, dst_off, stride, &mut block);
7400 }
7401 }
7402 }
7403
7404 self.wmv2_ref = Some(frame.clone());
7405 Ok(())
7406 }
7407 fn wmv2_decode_p(
7410 &mut self,
7411 payload: &[u8],
7412 hdr: &Wmv2FrameHeader,
7413 frame: &mut YuvFrame,
7414 ) -> Result<()> {
7415 let mut br = BitReader::new_at(payload, hdr.header_bits);
7417
7418 let mb_w = self.width_mb as usize;
7419 let mb_h = self.height_mb as usize;
7420 let qscale = hdr.pquant as i32;
7421
7422 self.wmv2_j_type = false;
7424 self.wmv2_parse_mb_skip(&mut br, mb_w, mb_h)?;
7425 let cbp_index = decode012(&mut br);
7426 self.wmv2_cbp_table_index = wmv2_get_cbp_table_index(qscale, cbp_index);
7427
7428 self.wmv2_mspel = if self.wmv2_mspel_bit {
7429 br.read_bit().unwrap_or(false)
7430 } else {
7431 false
7432 };
7433
7434 if self.wmv2_abt_flag {
7435 self.wmv2_per_mb_abt = br.read_bit().unwrap_or(false) ^ true;
7436 if !self.wmv2_per_mb_abt {
7437 self.wmv2_abt_type = decode012(&mut br);
7438 }
7439 } else {
7440 self.wmv2_per_mb_abt = false;
7441 self.wmv2_abt_type = 0;
7442 }
7443
7444 self.wmv2_per_mb_rl_table = if self.wmv2_per_mb_rl_bit {
7445 br.read_bit().unwrap_or(false)
7446 } else {
7447 false
7448 };
7449 if !self.wmv2_per_mb_rl_table {
7450 self.wmv2_rl_table_index = decode012(&mut br);
7451 self.wmv2_rl_chroma_table_index = self.wmv2_rl_table_index;
7452 }
7453 if br.bits_left() < 2 {
7454 return Err(DecoderError::InvalidData(
7455 "WMV2: truncated secondary header".into(),
7456 ));
7457 }
7458 self.wmv2_dc_table_index = br.read_bit().unwrap_or(false) as usize;
7459 self.wmv2_mv_table_index = br.read_bit().unwrap_or(false) as usize;
7460
7461 self.wmv2_dc_pred = Wmv2DcPredBuffer::new(mb_w, mb_h);
7463 if self.wmv2_motion.len() != mb_w * mb_h {
7464 self.wmv2_motion.resize(mb_w * mb_h, (0, 0));
7465 }
7466 for v in self.wmv2_motion.iter_mut() {
7467 *v = (0, 0);
7468 }
7469
7470 self.wmv2_reset_picture_state();
7471
7472 let reference = match &self.wmv2_ref {
7473 Some(r) => r.clone(),
7474 None => YuvFrame::new(frame.width, frame.height),
7475 };
7476
7477 for mb_row in 0..mb_h {
7478 let first_slice_line =
7479 self.wmv2_slice_height != 0 && (mb_row % self.wmv2_slice_height == 0);
7480 for mb_col in 0..mb_w {
7481 if br.bits_left() <= 0 {
7482 break;
7483 }
7484 let mi = mb_row * mb_w + mb_col;
7485 if mi < self.wmv2_mb_skip.len() && self.wmv2_mb_skip[mi] {
7486 if self.wmv2_mspel {
7487 wmv2_mspel_motion_mb(frame, &reference, mb_row, mb_col, 0, 0, 0);
7488 } else {
7489 motion_compensate_mb(frame, &reference, mb_row, mb_col, 0, 0);
7490 }
7491 self.wmv2_motion_set(mb_row, mb_col, (0, 0));
7492 continue;
7493 }
7494
7495 let code = self.wmv2_mb_non_intra_vlc[self.wmv2_cbp_table_index.min(3)]
7496 .decode(&mut br)
7497 .ok_or_else(|| {
7498 DecoderError::InvalidData("WMV2: MB header VLC underrun".into())
7499 })?;
7500
7501 let mb_intra = (code & 0x40) == 0;
7502 let cbp = (code & 0x3f) as u8;
7503
7504 if !mb_intra {
7505 let pred = self.wmv2_pred_motion(&mut br, mb_row, mb_col, first_slice_line);
7506
7507 if cbp != 0 && self.wmv2_per_mb_rl_table {
7508 self.wmv2_rl_table_index = decode012(&mut br);
7509 self.wmv2_rl_chroma_table_index = self.wmv2_rl_table_index;
7510 }
7511
7512 let mut per_block_abt = false;
7513 let mut abt_type = self.wmv2_abt_type;
7514 if cbp != 0 && self.wmv2_abt_flag && self.wmv2_per_mb_abt {
7515 per_block_abt = br.read_bit().unwrap_or(false);
7516 if !per_block_abt {
7517 abt_type = decode012(&mut br);
7518 }
7519 }
7520
7521 let (mx, my) = self.wmv2_decode_motion_ref(&mut br, pred);
7522 self.wmv2_hshift = if (((mx | my) & 1) != 0) && self.wmv2_mspel {
7523 br.read_bit().unwrap_or(false) as u8
7524 } else {
7525 0
7526 };
7527 self.wmv2_motion_set(mb_row, mb_col, (mx, my));
7528
7529 if self.wmv2_mspel {
7530 wmv2_mspel_motion_mb(
7531 frame,
7532 &reference,
7533 mb_row,
7534 mb_col,
7535 mx,
7536 my,
7537 self.wmv2_hshift,
7538 );
7539 } else {
7540 motion_compensate_mb(frame, &reference, mb_row, mb_col, mx, my);
7541 }
7542
7543 for blk in 0..6usize {
7544 if (cbp >> (5 - blk)) & 1 == 0 {
7545 continue;
7546 }
7547
7548 let mut cur_abt = abt_type;
7549 if per_block_abt {
7550 cur_abt = decode012(&mut br);
7551 }
7552
7553 if cur_abt == 0 {
7556 let scan = &FF_WMV1_SCANTABLE[0];
7557
7558 let mut block =
7559 self.wmv2_decode_block_inter_ref(&mut br, blk, true, qscale, scan)?;
7560
7561 let (is_luma, bx, by, stride, _ph) = block_coords(
7562 mb_row as u32,
7563 mb_col as u32,
7564 blk,
7565 frame.width,
7566 frame.height,
7567 );
7568
7569 let plane: &mut Vec<u8> = if is_luma {
7570 &mut frame.y
7571 } else if blk == 4 {
7572 &mut frame.cb
7573 } else {
7574 &mut frame.cr
7575 };
7576
7577 let dst_off = by * stride + bx;
7578
7579 wmv2dsp::wmv2_idct_add(plane, dst_off, stride, &mut block);
7580 } else {
7581 const SUB_CBP_TABLE: [u8; 3] = [2, 3, 1];
7582
7583 let scantable = if cur_abt == 1 {
7584 &FF_WMV2_SCANTABLE_A
7585 } else {
7586 &FF_WMV2_SCANTABLE_B
7587 };
7588
7589 let sub_cbp = SUB_CBP_TABLE[decode012(&mut br) as usize];
7590
7591 let mut block1 = [0i16; 64];
7592
7593 let mut block2 = [0i16; 64];
7594
7595 if (sub_cbp & 1) != 0 {
7596 block1 = self.wmv2_decode_block_inter_ref(
7597 &mut br, blk, true, qscale, scantable,
7598 )?;
7599 }
7600
7601 if (sub_cbp & 2) != 0 {
7602 block2 = self.wmv2_decode_block_inter_ref(
7603 &mut br, blk, true, qscale, scantable,
7604 )?;
7605 }
7606
7607 let (is_luma, bx, by, stride, _ph) = block_coords(
7608 mb_row as u32,
7609 mb_col as u32,
7610 blk,
7611 frame.width,
7612 frame.height,
7613 );
7614
7615 let plane: &mut Vec<u8> = if is_luma {
7616 &mut frame.y
7617 } else if blk == 4 {
7618 &mut frame.cb
7619 } else {
7620 &mut frame.cr
7621 };
7622
7623 let dst_off = by * stride + bx;
7624
7625 match cur_abt {
7626 1 => {
7627 ffidct::ff_simple_idct84_add(
7630 plane,
7631 dst_off,
7632 stride,
7633 &mut block1,
7634 );
7635
7636 ffidct::ff_simple_idct84_add(
7637 plane,
7638 dst_off + 4 * stride,
7639 stride,
7640 &mut block2,
7641 );
7642 }
7643
7644 2 => {
7645 ffidct::ff_simple_idct48_add(
7648 plane,
7649 dst_off,
7650 stride,
7651 &mut block1,
7652 );
7653
7654 ffidct::ff_simple_idct48_add(
7655 plane,
7656 dst_off + 4,
7657 stride,
7658 &mut block2,
7659 );
7660 }
7661
7662 _ => {}
7663 }
7664 }
7665 }
7666 } else {
7667 let ac_pred = br.read_bit().unwrap_or(false);
7669 if self.wmv2_per_mb_rl_table && cbp != 0 {
7670 let rl_idx = decode012(&mut br);
7671 self.wmv2_rl_table_index = rl_idx;
7672 self.wmv2_rl_chroma_table_index = rl_idx;
7673 }
7674
7675 for blk in 0..6usize {
7676 let coded = ((cbp >> (5 - blk)) & 1) != 0;
7677 let mut block = self.wmv2_decode_block_intra_ref(
7678 &mut br, mb_row, mb_col, blk, coded, qscale, ac_pred,
7679 )?;
7680
7681 let (is_luma, bx, by, stride, _ph) = block_coords(
7682 mb_row as u32,
7683 mb_col as u32,
7684 blk,
7685 frame.width,
7686 frame.height,
7687 );
7688 let plane: &mut Vec<u8> = if is_luma {
7689 &mut frame.y
7690 } else if blk == 4 {
7691 &mut frame.cb
7692 } else {
7693 &mut frame.cr
7694 };
7695 let dst_off = by * stride + bx;
7696 wmv2dsp::wmv2_idct_put(plane, dst_off, stride, &mut block);
7697 }
7698 self.wmv2_motion_set(mb_row, mb_col, (0, 0));
7699 }
7700 }
7701 }
7702
7703 self.wmv2_ref = Some(frame.clone());
7704 Ok(())
7705 }
7706}
7707
7708fn wmv2_decode_ac_block(
7715 br: &mut BitReader<'_>,
7716 ac_vlc: &VlcTable,
7717 pquant: i32,
7718 coeff: &mut [i32; 64],
7719 is_intra: bool,
7720) {
7721 let scan = &ZIGZAG;
7724 let mut idx = if is_intra { 1usize } else { 0 };
7725
7726 while let Some(sym) = ac_vlc.decode(br) {
7727 let (run, signed_level, last) = if sym == VLC_ESCAPE {
7728 decode_escape_coeff(br, ac_vlc)
7733 } else {
7734 let (r, l, last) = unpack_rl(sym);
7735 let sign = br.read_bit().unwrap_or(false);
7736 (r, if sign { -(l as i32) } else { l as i32 }, last)
7737 };
7738
7739 idx = idx.saturating_add(run as usize);
7740 if idx >= 64 {
7741 break;
7742 }
7743
7744 let q = iquant_uniform(signed_level, pquant, false);
7746 coeff[scan[idx]] = q;
7747
7748 idx += 1;
7749 if last || br.is_empty() {
7750 break;
7751 }
7752 }
7753}
7754
7755fn wmv2_read_mv(
7760 br: &mut BitReader<'_>,
7761 mv_pred: &MvPredictor,
7762 mb_row: usize,
7763 mb_col: usize,
7764 mv_range: i32,
7765) -> (i32, i32) {
7766 let (px, py) = mv_pred.predict(mb_row, mb_col);
7767 let dx = wmv2_read_mv_component(br, mv_range);
7768 let dy = wmv2_read_mv_component(br, mv_range);
7769 (px + dx, py + dy)
7770}
7771
7772fn wmv2_read_mv_component(br: &mut BitReader<'_>, mv_range: i32) -> i32 {
7775 let mag = {
7781 let mut m = 0i32;
7782 loop {
7783 if br.read_bit().unwrap_or(true) {
7784 break;
7785 }
7786 m += 1;
7787 if m >= mv_range {
7788 break;
7789 }
7790 }
7791 m
7792 };
7793 if mag == 0 {
7794 return 0;
7795 }
7796 let sign = br.read_bit().unwrap_or(false);
7797 if sign { -mag } else { mag }
7798}