vp6: fix motion compensation bugs
[nihav.git] / nihav-duck / src / codecs / vp6.rs
1 use nihav_core::codecs::*;
2 use nihav_core::io::bitreader::*;
3 use nihav_core::codecs::blockdsp::edge_emu;
4 use super::vpcommon::*;
5 use super::vp56::*;
6
7 const VERSION_VP60: u8 = 6;
8 //const VERSION_VP61: u8 = 7;
9 const VERSION_VP62: u8 = 8;
10
11 const VP6_SIMPLE_PROFILE: u8 = 0;
12 const VP6_ADVANCED_PROFILE: u8 = 3;
13
14 #[derive(Default)]
15 struct VP6BR {
16 vpversion: u8,
17 profile: u8,
18 interlaced: bool,
19 do_pm: bool,
20 loop_mode: u8,
21 autosel_pm: bool,
22 var_thresh: u16,
23 mv_thresh: u8,
24 bicubic: bool,
25 filter_alpha: usize,
26 }
27
28 impl VP6BR {
29 fn new() -> Self {
30 Self::default()
31 }
32 }
33
34 impl VP56Parser for VP6BR {
35 fn parse_header(&mut self, bc: &mut BoolCoder) -> DecoderResult<VP56Header> {
36 let mut hdr = VP56Header::default();
37 // horrible hack to match VP6 header parsing
38 let src = bc.src;
39 let mut br = BitReader::new(src, src.len(), BitReaderMode::BE);
40
41 hdr.is_intra = !br.read_bool()?;
42 hdr.is_golden = hdr.is_intra;
43 hdr.quant = br.read(6)? as u8;
44 hdr.multistream = br.read_bool()?;
45 if hdr.is_intra {
46 hdr.version = br.read(5)? as u8;
47 validate!((hdr.version >= VERSION_VP60) && (hdr.version <= VERSION_VP62));
48 hdr.profile = br.read(2)? as u8;
49 validate!((hdr.profile == VP6_SIMPLE_PROFILE) || (hdr.profile == VP6_ADVANCED_PROFILE));
50 hdr.interlaced = br.read_bool()?;
51 } else {
52 hdr.version = self.vpversion;
53 hdr.profile = self.profile;
54 }
55 if hdr.multistream || (hdr.profile == VP6_SIMPLE_PROFILE) {
56 hdr.offset = br.read(16)? as u16;
57 validate!(hdr.offset > if hdr.is_intra { 6 } else { 2 });
58 }
59 let bytes = br.tell() >> 3;
60 std::mem::drop(br);
61 bc.skip_bytes(bytes);
62 self.loop_mode = 0;
63 if hdr.is_intra {
64 hdr.mb_h = bc.read_bits(8) as u8;
65 hdr.mb_w = bc.read_bits(8) as u8;
66 hdr.disp_h = bc.read_bits(8) as u8;
67 hdr.disp_w = bc.read_bits(8) as u8;
68 validate!((hdr.mb_h > 0) && (hdr.mb_w > 0) && (hdr.disp_w > 0) && (hdr.disp_h > 0));
69 validate!((hdr.disp_w <= hdr.mb_w) && (hdr.disp_h <= hdr.mb_h));
70 hdr.scale = bc.read_bits(2) as u8;
71 } else {
72 hdr.is_golden = bc.read_bool();
73 if hdr.profile == VP6_ADVANCED_PROFILE {
74 self.loop_mode = bc.read_bool() as u8;
75 if self.loop_mode != 0 {
76 self.loop_mode += bc.read_bool() as u8;
77 validate!(self.loop_mode <= 1);
78 }
79 if hdr.version == VERSION_VP62 {
80 self.do_pm = bc.read_bool();
81 }
82 }
83 }
84
85 if (hdr.profile == VP6_ADVANCED_PROFILE) && (hdr.is_intra || self.do_pm) {
86 self.autosel_pm = bc.read_bool();
87 if self.autosel_pm {
88 self.var_thresh = bc.read_bits(5) as u16;
89 if hdr.version != VERSION_VP62 {
90 self.var_thresh <<= 5;
91 }
92 self.mv_thresh = bc.read_bits(3) as u8;
93 } else {
94 self.bicubic = bc.read_bool();
95 }
96 if hdr.version == VERSION_VP62 {
97 self.filter_alpha = bc.read_bits(4) as usize;
98 } else {
99 self.filter_alpha = 16;
100 }
101 }
102
103 hdr.use_huffman = bc.read_bool();
104
105 self.vpversion = hdr.version;
106 self.profile = hdr.profile;
107 self.interlaced = hdr.interlaced;
108 Ok(hdr)
109 }
110 fn decode_mv(&self, bc: &mut BoolCoder, model: &VP56MVModel) -> i16 {
111 const LONG_VECTOR_ORDER: [usize; 7] = [ 0, 1, 2, 7, 6, 5, 4 ];
112
113 let val = if !bc.read_prob(model.nz_prob) { // short vector
114 vp_tree!(bc, model.tree_probs[0],
115 vp_tree!(bc, model.tree_probs[1],
116 vp_tree!(bc, model.tree_probs[2], 0, 1),
117 vp_tree!(bc, model.tree_probs[3], 2, 3)),
118 vp_tree!(bc, model.tree_probs[4],
119 vp_tree!(bc, model.tree_probs[5], 4, 5),
120 vp_tree!(bc, model.tree_probs[6], 6, 7)))
121 } else {
122 let mut raw = 0;
123 for ord in LONG_VECTOR_ORDER.iter() {
124 raw |= (bc.read_prob(model.raw_probs[*ord]) as i16) << *ord;
125 }
126 if (raw & 0xF0) != 0 {
127 raw |= (bc.read_prob(model.raw_probs[3]) as i16) << 3;
128 } else {
129 raw |= 1 << 3;
130 }
131 raw
132 };
133 if (val != 0) && bc.read_prob(model.sign_prob) {
134 -val
135 } else {
136 val
137 }
138 }
139 fn reset_models(&self, models: &mut VP56Models) {
140 const NZ_PROBS: [u8; 2] = [ 162, 164 ];
141 const RAW_PROBS: [[u8; 8]; 2] = [
142 [ 247, 210, 135, 68, 138, 220, 239, 246 ],
143 [ 244, 184, 201, 44, 173, 221, 239, 253 ]
144 ];
145 const TREE_PROBS: [[u8; 7]; 2] = [
146 [ 225, 146, 172, 147, 214, 39, 156 ],
147 [ 204, 170, 119, 235, 140, 230, 228 ]
148 ];
149 const ZERO_RUN_PROBS: [[u8; 14]; 2] = [
150 [ 198, 197, 196, 146, 198, 204, 169, 142, 130, 136, 149, 149, 191, 249 ],
151 [ 135, 201, 181, 154, 98, 117, 132, 126, 146, 169, 184, 240, 246, 254 ]
152 ];
153
154 for (i, mdl) in models.mv_models.iter_mut().enumerate() {
155 mdl.nz_prob = NZ_PROBS[i];
156 mdl.sign_prob = 128;
157 mdl.raw_probs.copy_from_slice(&RAW_PROBS[i]);
158 mdl.tree_probs.copy_from_slice(&TREE_PROBS[i]);
159 }
160 models.vp6models.zero_run_probs.copy_from_slice(&ZERO_RUN_PROBS);
161 reset_scan(&mut models.vp6models, self.interlaced);
162 }
163 fn decode_mv_models(&self, bc: &mut BoolCoder, models: &mut [VP56MVModel; 2]) -> DecoderResult<()> {
164 const HAS_NZ_PROB: [u8; 2] = [ 237, 231 ];
165 const HAS_SIGN_PROB: [u8; 2] = [ 246, 243 ];
166 const HAS_TREE_PROB: [[u8; 7]; 2] = [
167 [ 253, 253, 254, 254, 254, 254, 254 ],
168 [ 245, 253, 254, 254, 254, 254, 254 ]
169 ];
170 const HAS_RAW_PROB: [[u8; 8]; 2] = [
171 [ 254, 254, 254, 254, 254, 250, 250, 252 ],
172 [ 254, 254, 254, 254, 254, 251, 251, 254 ]
173 ];
174
175 for comp in 0..2 {
176 if bc.read_prob(HAS_NZ_PROB[comp]) {
177 models[comp].nz_prob = bc.read_probability();
178 }
179 if bc.read_prob(HAS_SIGN_PROB[comp]) {
180 models[comp].sign_prob = bc.read_probability();
181 }
182 }
183 for comp in 0..2 {
184 for (i, prob) in HAS_TREE_PROB[comp].iter().enumerate() {
185 if bc.read_prob(*prob) {
186 models[comp].tree_probs[i] = bc.read_probability();
187 }
188 }
189 }
190 for comp in 0..2 {
191 for (i, prob) in HAS_RAW_PROB[comp].iter().enumerate() {
192 if bc.read_prob(*prob) {
193 models[comp].raw_probs[i] = bc.read_probability();
194 }
195 }
196 }
197 Ok(())
198 }
199 fn decode_coeff_models(&self, bc: &mut BoolCoder, models: &mut VP56Models, is_intra: bool) -> DecoderResult<()> {
200 const COEF_PROBS: [[u8; 11]; 2] = [
201 [ 146, 255, 181, 207, 232, 243, 238, 251, 244, 250, 249 ],
202 [ 179, 255, 214, 240, 250, 255, 244, 255, 255, 255, 255 ]
203 ];
204 const SCAN_UPD_PROBS: [u8; 64] = [
205 0, 132, 132, 159, 153, 151, 161, 170,
206 164, 162, 136, 110, 103, 114, 129, 118,
207 124, 125, 132, 136, 114, 110, 142, 135,
208 134, 123, 143, 126, 153, 183, 166, 161,
209 171, 180, 179, 164, 203, 218, 225, 217,
210 215, 206, 203, 217, 229, 241, 248, 243,
211 253, 255, 253, 255, 255, 255, 255, 255,
212 255, 255, 255, 255, 255, 255, 255, 255
213 ];
214 const ZERO_RUN_PROBS: [[u8; 14]; 2] = [
215 [ 219, 246, 238, 249, 232, 239, 249, 255, 248, 253, 239, 244, 241, 248 ],
216 [ 198, 232, 251, 253, 219, 241, 253, 255, 248, 249, 244, 238, 251, 255 ]
217 ];
218
219 let mut def_prob = [128u8; 11];
220 for plane in 0..2 {
221 for i in 0..11 {
222 if bc.read_prob(COEF_PROBS[plane][i]) {
223 def_prob[i] = bc.read_probability();
224 models.coeff_models[plane].dc_value_probs[i] = def_prob[i];
225 } else if is_intra {
226 models.coeff_models[plane].dc_value_probs[i] = def_prob[i];
227 }
228 }
229 }
230
231 if bc.read_bool() {
232 for i in 1..64 {
233 if bc.read_prob(SCAN_UPD_PROBS[i]) {
234 models.vp6models.scan_order[i] = bc.read_bits(4) as usize;
235 }
236 }
237 update_scan(&mut models.vp6models);
238 } else {
239 reset_scan(&mut models.vp6models, self.interlaced);
240 }
241
242 for comp in 0..2 {
243 for i in 0..14 {
244 if bc.read_prob(ZERO_RUN_PROBS[comp][i]) {
245 models.vp6models.zero_run_probs[comp][i] = bc.read_probability();
246 }
247 }
248 }
249
250 for ctype in 0..3 {
251 for plane in 0..2 {
252 for group in 0..6 {
253 for i in 0..11 {
254 if bc.read_prob(VP6_AC_PROBS[ctype][plane][group][i]) {
255 def_prob[i] = bc.read_probability();
256 models.coeff_models[plane].ac_val_probs[ctype][group][i] = def_prob[i];
257 } else if is_intra {
258 models.coeff_models[plane].ac_val_probs[ctype][group][i] = def_prob[i];
259 }
260 }
261 }
262 }
263 }
264 for plane in 0..2 {
265 let mdl = &mut models.coeff_models[plane];
266 for i in 0..3 {
267 for k in 0..5 {
268 mdl.dc_token_probs[0][i][k] = rescale_prob(mdl.dc_value_probs[k], &VP6_DC_WEIGHTS[k][i], 255);
269 }
270 }
271 }
272 Ok(())
273 }
274 fn decode_block(&self, bc: &mut BoolCoder, coeffs: &mut [i16; 64], model: &VP56CoeffModel, vp6model: &VP6Models, fstate: &mut FrameState) -> DecoderResult<()> {
275 let left_ctx = fstate.coeff_cat[fstate.ctx_idx][0] as usize;
276 let top_ctx = fstate.top_ctx as usize;
277 let dc_mode = top_ctx + left_ctx;
278 let token = decode_token_bc(bc, &model.dc_token_probs[0][dc_mode], model.dc_value_probs[5], true, true);
279 let val = expand_token_bc(bc, &model.dc_value_probs, token, 6);
280 coeffs[0] = val;
281 fstate.last_idx[fstate.ctx_idx] = 0;
282
283 let mut idx = 1;
284 let mut last_val = val;
285 while idx < 64 {
286 let ac_band = VP6_IDX_TO_AC_BAND[idx];
287 let ac_mode = last_val.abs().min(2) as usize;
288 let has_nnz = (idx == 1) || (last_val != 0);
289 let token = decode_token_bc(bc, &model.ac_val_probs[ac_mode][ac_band], model.ac_val_probs[ac_mode][ac_band][5], false, has_nnz);
290 if token == 42 { break; }
291 let val = expand_token_bc(bc, &model.ac_val_probs[ac_mode][ac_band], token, 6);
292 coeffs[vp6model.zigzag[idx]] = val.wrapping_mul(fstate.ac_quant);
293 idx += 1;
294 last_val = val;
295 if val == 0 {
296 idx += decode_zero_run_bc(bc, &vp6model.zero_run_probs[if idx >= 7 { 1 } else { 0 }]);
297 validate!(idx <= 64);
298 }
299 }
300 fstate.coeff_cat[fstate.ctx_idx][0] = if coeffs[0] != 0 { 1 } else { 0 };
301 fstate.top_ctx = fstate.coeff_cat[fstate.ctx_idx][0];
302 fstate.last_idx[fstate.ctx_idx] = idx;
303 Ok(())
304 }
305 fn decode_block_huff(&self, br: &mut BitReader, coeffs: &mut [i16; 64], vp6model: &VP6Models, model: &VP6HuffModels, fstate: &mut FrameState) -> DecoderResult<()> {
306 let plane = if (fstate.plane == 0) || (fstate.plane == 3) { 0 } else { 1 };
307 let mut last_val;
308
309 if fstate.dc_zero_run[plane] == 0 {
310 let (val, eob) = decode_token_huff(br, &model.dc_token_tree[plane])?;
311 if eob {
312 return Ok(());
313 }
314 last_val = val;
315 coeffs[0] = val;
316 if val == 0 {
317 fstate.dc_zero_run[plane] = decode_eob_run_huff(br)?;
318 }
319 } else {
320 last_val = 0;
321 fstate.dc_zero_run[plane] -= 1;
322 }
323
324 if fstate.ac_zero_run[plane] > 0 {
325 fstate.ac_zero_run[plane] -= 1;
326 fstate.last_idx[fstate.ctx_idx] = 0;
327 return Ok(());
328 }
329
330 let mut idx = 1;
331 while idx < 64 {
332 let ac_band = VP6_IDX_TO_AC_BAND[idx].min(3);
333 let ac_mode = last_val.abs().min(2) as usize;
334 let (val, eob) = decode_token_huff(br, &model.ac_token_tree[plane][ac_mode][ac_band])?;
335 if eob {
336 if idx == 1 {
337 fstate.ac_zero_run[plane] = decode_eob_run_huff(br)?;
338 }
339 break;
340 }
341 coeffs[vp6model.zigzag[idx]] = val.wrapping_mul(fstate.ac_quant);
342 idx += 1;
343 last_val = val;
344 if val == 0 {
345 idx += decode_zero_run_huff(br, &model.zero_run_tree[if idx >= 7 { 1 } else { 0 }])?;
346 validate!(idx <= 64);
347 }
348 }
349
350 fstate.last_idx[fstate.ctx_idx] = idx;
351
352 Ok(())
353 }
354 fn mc_block(&self, dst: &mut NASimpleVideoFrame<u8>, mut mc_buf: NAVideoBufferRef<u8>, src: NAVideoBufferRef<u8>, plane: usize, x: usize, y: usize, mv: MV, loop_str: i16) {
355 let is_luma = (plane != 1) && (plane != 2);
356 let (sx, sy, mx, my, msx, msy) = if is_luma {
357 (mv.x >> 2, mv.y >> 2, (mv.x & 3) << 1, (mv.y & 3) << 1, mv.x / 4, mv.y / 4)
358 } else {
359 (mv.x >> 3, mv.y >> 3, mv.x & 7, mv.y & 7, mv.x / 8, mv.y / 8)
360 };
361 let tmp_blk = mc_buf.get_data_mut().unwrap();
362 get_block(tmp_blk, 16, src.clone(), plane, x, y, sx, sy);
363 if (msx & 7) != 0 {
364 let foff = (8 - (sx & 7)) as usize;
365 let off = 2 + foff;
366 vp31_loop_filter(tmp_blk, off, 1, 16, 12, loop_str);
367 }
368 if (msy & 7) != 0 {
369 let foff = (8 - (sy & 7)) as usize;
370 let off = (2 + foff) * 16;
371 vp31_loop_filter(tmp_blk, off, 16, 1, 12, loop_str);
372 }
373 let copy_mode = (mx == 0) && (my == 0);
374 let mut bicubic = !copy_mode && is_luma && self.bicubic;
375 if is_luma && !copy_mode && (self.profile == VP6_ADVANCED_PROFILE) {
376 if !self.autosel_pm {
377 bicubic = true;
378 } else {
379 let mv_limit = 1 << (self.mv_thresh + 1);
380 if (mv.x.abs() <= mv_limit) && (mv.y.abs() <= mv_limit) {
381 let mut var_off = 16 * 2 + 2;
382 if mv.x < 0 { var_off += 1; }
383 if mv.y < 0 { var_off += 16; }
384 let var = calc_variance(&tmp_blk[var_off..], 16);
385 if var >= self.var_thresh {
386 bicubic = true;
387 }
388 }
389 }
390 }
391 let dstride = dst.stride[plane];
392 let dbuf = &mut dst.data[dst.offset[plane] + x + y * dstride..];
393 if copy_mode {
394 let src = &tmp_blk[2 * 16 + 2..];
395 for (dline, sline) in dbuf.chunks_mut(dst.stride[plane]).zip(src.chunks(16)).take(8) {
396 for i in 0..8 { dline[i] = sline[i]; }
397 }
398 } else if bicubic {
399 let coeff_h = &VP6_BICUBIC_COEFFS[self.filter_alpha][mx as usize];
400 let coeff_v = &VP6_BICUBIC_COEFFS[self.filter_alpha][my as usize];
401 mc_bicubic(dbuf, dstride, tmp_blk, 16 * 2 + 2, 16, coeff_h, coeff_v);
402 } else {
403 mc_bilinear(dbuf, dstride, tmp_blk, 16 * 2 + 2, 16, mx as u16, my as u16);
404 }
405 }
406 }
407
408 fn update_scan(model: &mut VP6Models) {
409 let mut idx = 1;
410 for band in 0..16 {
411 for i in 1..64 {
412 if model.scan_order[i] == band {
413 model.scan[idx] = i;
414 idx += 1;
415 }
416 }
417 }
418 for i in 1..64 {
419 model.zigzag[i] = ZIGZAG[model.scan[i]];
420 }
421 }
422
423 fn reset_scan(model: &mut VP6Models, interlaced: bool) {
424 const VP6_DEFAULT_SCAN_ORDER: [usize; 64] = [
425 0, 0, 1, 1, 1, 2, 2, 2,
426 2, 2, 2, 3, 3, 4, 4, 4,
427 5, 5, 5, 5, 6, 6, 7, 7,
428 7, 7, 7, 8, 8, 9, 9, 9,
429 9, 9, 9, 10, 10, 11, 11, 11,
430 11, 11, 11, 12, 12, 12, 12, 12,
431 12, 13, 13, 13, 13, 13, 14, 14,
432 14, 14, 15, 15, 15, 15, 15, 15
433 ];
434 const VP6_INTERLACED_SCAN_ORDER: [usize; 64] = [
435 0, 1, 0, 1, 1, 2, 5, 3,
436 2, 2, 2, 2, 4, 7, 8, 10,
437 9, 7, 5, 4, 2, 3, 5, 6,
438 8, 9, 11, 12, 13, 12, 11, 10,
439 9, 7, 5, 4, 6, 7, 9, 11,
440 12, 12, 13, 13, 14, 12, 11, 9,
441 7, 9, 11, 12, 14, 14, 14, 15,
442 13, 11, 13, 15, 15, 15, 15, 15
443 ];
444
445 if !interlaced {
446 model.scan_order.copy_from_slice(&VP6_DEFAULT_SCAN_ORDER);
447 } else {
448 model.scan_order.copy_from_slice(&VP6_INTERLACED_SCAN_ORDER);
449 }
450 for i in 0..64 { model.scan[i] = i; }
451 model.zigzag.copy_from_slice(&ZIGZAG);
452 }
453
454 fn decode_token_bc(bc: &mut BoolCoder, probs: &[u8], prob34: u8, is_dc: bool, has_nnz: bool) -> u8 {
455 if has_nnz && !bc.read_prob(probs[0]) {
456 if is_dc || bc.read_prob(probs[1]) {
457 0
458 } else {
459 TOKEN_EOB
460 }
461 } else {
462 vp_tree!(bc, probs[2],
463 1,
464 vp_tree!(bc, probs[3],
465 vp_tree!(bc, probs[4],
466 2,
467 vp_tree!(bc, prob34, 3, 4)),
468 TOKEN_LARGE))
469 }
470 }
471
472 fn decode_zero_run_bc(bc: &mut BoolCoder, probs: &[u8; 14]) -> usize {
473 let val = vp_tree!(bc, probs[0],
474 vp_tree!(bc, probs[1],
475 vp_tree!(bc, probs[2], 0, 1),
476 vp_tree!(bc, probs[3], 2, 3)),
477 vp_tree!(bc, probs[4],
478 vp_tree!(bc, probs[5],
479 vp_tree!(bc, probs[6], 4, 5),
480 vp_tree!(bc, probs[7], 6, 7)),
481 42));
482 if val != 42 {
483 val
484 } else {
485 let mut nval = 8;
486 for i in 0..6 {
487 nval += (bc.read_prob(probs[i + 8]) as usize) << i;
488 }
489 nval
490 }
491 }
492
493 fn decode_token_huff(br: &mut BitReader, huff: &VP6Huff) -> DecoderResult<(i16, bool)> {
494 const COEF_ADD_BITS: [u8; 6] = [ 1, 2, 3, 4, 5, 11 ];
495 let tok = br.read_huff(huff)?;
496 match tok {
497 0 => Ok((0, false)),
498 1 | 2 | 3 | 4 => {
499 if !br.read_bool()? {
500 Ok((tok as i16, false))
501 } else {
502 Ok((-(tok as i16), false))
503 }
504 },
505 5 | 6 | 7 | 8 | 9 | 10 => {
506 let base = (tok - 5) as usize;
507 let add_bits = br.read(COEF_ADD_BITS[base])? as i16;
508 let val = VP56_COEF_BASE[base] + add_bits;
509 if !br.read_bool()? {
510 Ok((val, false))
511 } else {
512 Ok((-val, false))
513 }
514 },
515 _ => Ok((0, true)),
516 }
517 }
518
519 fn decode_eob_run_huff(br: &mut BitReader) -> DecoderResult<usize> {
520 let val = br.read(2)?;
521 match val {
522 0 => Ok(0),
523 1 => Ok(1),
524 2 => {
525 let val = br.read(2)?;
526 Ok((val as usize) + 2)
527 },
528 _ => {
529 if br.read_bool()? {
530 Ok((br.read(6)? as usize) + 10)
531 } else {
532 Ok((br.read(2)? as usize) + 6)
533 }
534 },
535 }
536 }
537
538 fn decode_zero_run_huff(br: &mut BitReader, huff: &VP6Huff) -> DecoderResult<usize> {
539 let val = br.read_huff(huff)?;
540 if val < 8 {
541 Ok(val as usize)
542 } else {
543 Ok((br.read(6)? as usize) + 8)
544 }
545 }
546
547
548 fn get_block(dst: &mut [u8], dstride: usize, src: NAVideoBufferRef<u8>, comp: usize,
549 dx: usize, dy: usize, mv_x: i16, mv_y: i16)
550 {
551 let (w, h) = src.get_dimensions(comp);
552 let sx = (dx as isize) + (mv_x as isize);
553 let sy = (dy as isize) + (mv_y as isize);
554
555 if (sx - 2 < 0) || (sx + 8 + 2 > (w as isize)) ||
556 (sy - 2 < 0) || (sy + 8 + 2 > (h as isize)) {
557 edge_emu(&src, sx - 2, sy - 2, 8 + 2 + 2, 8 + 2 + 2,
558 dst, dstride, comp);
559 } else {
560 let sstride = src.get_stride(comp);
561 let soff = src.get_offset(comp);
562 let sdta = src.get_data();
563 let sbuf: &[u8] = sdta.as_slice();
564 let saddr = soff + ((sx - 2) as usize) + ((sy - 2) as usize) * sstride;
565 let src = &sbuf[saddr..];
566 for (dline, sline) in dst.chunks_mut(dstride).zip(src.chunks(sstride)).take(12) {
567 for i in 0..12 {
568 dline[i] = sline[i];
569 }
570 }
571 }
572 }
573
574 fn calc_variance(src: &[u8], stride: usize) -> u16 {
575 let mut sum = 0;
576 let mut ssum = 0;
577 for line in src.chunks(stride * 2).take(4) {
578 for el in line.iter().take(8).step_by(2) {
579 let pix = *el as u32;
580 sum += pix;
581 ssum += pix * pix;
582 }
583 }
584 ((ssum * 16 - sum * sum) >> 8) as u16
585 }
586
587 macro_rules! mc_filter {
588 (bilinear; $a: expr, $b: expr, $c: expr) => {
589 ((($a as u16) * (8 - $c) + ($b as u16) * $c + 4) >> 3) as u8
590 };
591 (bicubic; $src: expr, $off: expr, $step: expr, $coeffs: expr) => {
592 ((($src[$off - $step] as i32) * ($coeffs[0] as i32) +
593 ($src[$off] as i32) * ($coeffs[1] as i32) +
594 ($src[$off + $step] as i32) * ($coeffs[2] as i32) +
595 ($src[$off + $step * 2] as i32) * ($coeffs[3] as i32) + 64) >> 7).min(255).max(0) as u8
596 }
597 }
598
599 //#[allow(snake_case)]
600 fn mc_bilinear(dst: &mut [u8], dstride: usize, src: &[u8], mut soff: usize, sstride: usize, mx: u16, my: u16) {
601 if my == 0 {
602 for dline in dst.chunks_mut(dstride).take(8) {
603 for i in 0..8 {
604 dline[i] = mc_filter!(bilinear; src[soff + i], src[soff + i + 1], mx);
605 }
606 soff += sstride;
607 }
608 } else if mx == 0 {
609 for dline in dst.chunks_mut(dstride).take(8) {
610 for i in 0..8 {
611 dline[i] = mc_filter!(bilinear; src[soff + i], src[soff + i + sstride], my);
612 }
613 soff += sstride;
614 }
615 } else {
616 let mut tmp = [0u8; 8];
617 for i in 0..8 {
618 tmp[i] = mc_filter!(bilinear; src[soff + i], src[soff + i + 1], mx);
619 }
620 soff += sstride;
621 for dline in dst.chunks_mut(dstride).take(8) {
622 for i in 0..8 {
623 let cur = mc_filter!(bilinear; src[soff + i], src[soff + i + 1], mx);
624 dline[i] = mc_filter!(bilinear; tmp[i], cur, my);
625 tmp[i] = cur;
626 }
627 soff += sstride;
628 }
629 }
630 }
631
632 fn mc_bicubic(dst: &mut [u8], dstride: usize, src: &[u8], mut soff: usize, sstride: usize, coeffs_w: &[i16; 4], coeffs_h: &[i16; 4]) {
633 if coeffs_h[1] == 128 {
634 for dline in dst.chunks_mut(dstride).take(8) {
635 for i in 0..8 {
636 dline[i] = mc_filter!(bicubic; src, soff + i, 1, coeffs_w);
637 }
638 soff += sstride;
639 }
640 } else if coeffs_w[1] == 128 { // horizontal-only interpolation
641 for dline in dst.chunks_mut(dstride).take(8) {
642 for i in 0..8 {
643 dline[i] = mc_filter!(bicubic; src, soff + i, sstride, coeffs_h);
644 }
645 soff += sstride;
646 }
647 } else {
648 let mut buf = [0u8; 16 * 11];
649 soff -= sstride;
650 for dline in buf.chunks_mut(16) {
651 for i in 0..8 {
652 dline[i] = mc_filter!(bicubic; src, soff + i, 1, coeffs_w);
653 }
654 soff += sstride;
655 }
656 let mut soff = 16;
657 for dline in dst.chunks_mut(dstride).take(8) {
658 for i in 0..8 {
659 dline[i] = mc_filter!(bicubic; buf, soff + i, 16, coeffs_h);
660 }
661 soff += 16;
662 }
663 }
664 }
665
666 struct VP6Decoder {
667 dec: VP56Decoder,
668 info: NACodecInfoRef,
669 br: VP6BR,
670 has_alpha: bool,
671 }
672
673 impl VP6Decoder {
674 fn new(has_alpha: bool) -> Self {
675 Self {
676 dec: VP56Decoder::new(6, has_alpha, true),
677 info: NACodecInfoRef::default(),
678 br: VP6BR::new(),
679 has_alpha,
680 }
681 }
682 }
683
684 impl NADecoder for VP6Decoder {
685 fn init(&mut self, supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
686 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
687 let fmt = if !self.has_alpha {
688 YUV420_FORMAT
689 } else {
690 NAPixelFormaton::new(ColorModel::YUV(YUVSubmodel::YUVJ),
691 Some(NAPixelChromaton::new(0, 0, false, 8, 0, 0, 1)),
692 Some(NAPixelChromaton::new(1, 1, false, 8, 0, 1, 1)),
693 Some(NAPixelChromaton::new(1, 1, false, 8, 0, 2, 1)),
694 Some(NAPixelChromaton::new(0, 0, false, 8, 0, 3, 1)),
695 None,
696 0, 4)
697 };
698 let myvinfo = NAVideoInfo::new(vinfo.get_width(), vinfo.get_height(), false, fmt);
699 let myinfo = NACodecTypeInfo::Video(myvinfo.clone());
700 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
701 self.dec.init(supp, myvinfo)?;
702 Ok(())
703 } else {
704 Err(DecoderError::InvalidData)
705 }
706 }
707 fn decode(&mut self, supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
708 let src = pkt.get_buffer();
709
710 let (bufinfo, ftype) = self.dec.decode_frame(supp, src.as_slice(), &mut self.br)?;
711
712 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo);
713 frm.set_keyframe(ftype == FrameType::I);
714 frm.set_frame_type(ftype);
715 Ok(frm.into_ref())
716 }
717 fn flush(&mut self) {
718 self.dec.flush();
719 }
720 }
721
722 pub fn get_decoder_vp6() -> Box<NADecoder + Send> {
723 Box::new(VP6Decoder::new(false))
724 }
725
726 pub fn get_decoder_vp6_alpha() -> Box<NADecoder + Send> {
727 Box::new(VP6Decoder::new(true))
728 }
729
730 #[cfg(test)]
731 mod test {
732 use nihav_core::codecs::RegisteredDecoders;
733 use nihav_core::demuxers::RegisteredDemuxers;
734 use nihav_core::test::dec_video::*;
735 use crate::codecs::duck_register_all_codecs;
736 use nihav_commonfmt::demuxers::generic_register_all_demuxers;
737
738 #[test]
739 fn test_vp6() {
740 let mut dmx_reg = RegisteredDemuxers::new();
741 generic_register_all_demuxers(&mut dmx_reg);
742 let mut dec_reg = RegisteredDecoders::new();
743 duck_register_all_codecs(&mut dec_reg);
744
745 //let file = "assets/Duck/predator2_vp60.avi";
746 //let file = "assets/Duck/predator2_vp61.avi";
747 //let file = "assets/Duck/vp6_crash.avi";
748 let file = "assets/Duck/vp6_interlaced.avi";
749 //let file = "assets/Duck/vp6_vid.avi";
750 //let file = "assets/Duck/selection_720x576_300kBit_vp60i.avi";
751 //let file = "assets/Duck/selection_720x576_300kBit_flipped_vp60i.avi";
752 test_file_decoding("avi", file, Some(17), true, false, None/*Some("vp6")*/, &dmx_reg, &dec_reg);
753 //panic!("end");
754 }
755 }
756
757 const VP6_AC_PROBS: [[[[u8; 11]; 6]; 2]; 3] = [
758 [
759 [
760 [ 227, 246, 230, 247, 244, 255, 255, 255, 255, 255, 255 ],
761 [ 255, 255, 209, 231, 231, 249, 249, 253, 255, 255, 255 ],
762 [ 255, 255, 225, 242, 241, 251, 253, 255, 255, 255, 255 ],
763 [ 255, 255, 241, 253, 252, 255, 255, 255, 255, 255, 255 ],
764 [ 255, 255, 248, 255, 255, 255, 255, 255, 255, 255, 255 ],
765 [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ]
766 ], [
767 [ 240, 255, 248, 255, 255, 255, 255, 255, 255, 255, 255 ],
768 [ 255, 255, 240, 253, 255, 255, 255, 255, 255, 255, 255 ],
769 [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],
770 [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],
771 [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],
772 [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ]
773 ]
774 ], [
775 [
776 [ 206, 203, 227, 239, 247, 255, 253, 255, 255, 255, 255 ],
777 [ 207, 199, 220, 236, 243, 252, 252, 255, 255, 255, 255 ],
778 [ 212, 219, 230, 243, 244, 253, 252, 255, 255, 255, 255 ],
779 [ 236, 237, 247, 252, 253, 255, 255, 255, 255, 255, 255 ],
780 [ 240, 240, 248, 255, 255, 255, 255, 255, 255, 255, 255 ],
781 [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ]
782 ], [
783 [ 230, 233, 249, 255, 255, 255, 255, 255, 255, 255, 255 ],
784 [ 238, 238, 250, 255, 255, 255, 255, 255, 255, 255, 255 ],
785 [ 248, 251, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],
786 [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],
787 [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],
788 [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ]
789 ]
790 ], [
791 [
792 [ 225, 239, 227, 231, 244, 253, 243, 255, 255, 253, 255 ],
793 [ 232, 234, 224, 228, 242, 249, 242, 252, 251, 251, 255 ],
794 [ 235, 249, 238, 240, 251, 255, 249, 255, 253, 253, 255 ],
795 [ 249, 253, 251, 250, 255, 255, 255, 255, 255, 255, 255 ],
796 [ 251, 250, 249, 255, 255, 255, 255, 255, 255, 255, 255 ],
797 [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ]
798 ], [
799 [ 243, 244, 250, 250, 255, 255, 255, 255, 255, 255, 255 ],
800 [ 249, 248, 250, 253, 255, 255, 255, 255, 255, 255, 255 ],
801 [ 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],
802 [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],
803 [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],
804 [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ]
805 ]
806 ]
807 ];
808
809 const VP6_DC_WEIGHTS: [[[i16; 2]; 3]; 5] = [
810 [ [ 122, 133 ], [ 133, 51 ], [ 142, -16 ] ],
811 [ [ 0, 1 ], [ 0, 1 ], [ 0, 1 ] ],
812 [ [ 78, 171 ], [ 169, 71 ], [ 221, -30 ] ],
813 [ [ 139, 117 ], [ 214, 44 ], [ 246, -3 ] ],
814 [ [ 168, 79 ], [ 210, 38 ], [ 203, 17 ] ]
815 ];
816
817 const VP6_IDX_TO_AC_BAND: [usize; 64] = [
818 0, 0, 1, 1, 1, 2, 2, 2,
819 2, 2, 2, 3, 3, 3, 3, 3,
820 3, 3, 3, 3, 3, 3, 4, 4,
821 4, 4, 4, 4, 4, 4, 4, 4,
822 4, 4, 4, 4, 4, 5, 5, 5,
823 5, 5, 5, 5, 5, 5, 5, 5,
824 5, 5, 5, 5, 5, 5, 5, 5,
825 5, 5, 5, 5, 5, 5, 5, 5
826 ];
827
828 const VP6_BICUBIC_COEFFS: [[[i16; 4]; 8]; 17] = [
829 [
830 [ 0, 128, 0, 0 ],
831 [ -3, 122, 9, 0 ],
832 [ -4, 109, 24, -1 ],
833 [ -5, 91, 45, -3 ],
834 [ -4, 68, 68, -4 ],
835 [ -3, 45, 91, -5 ],
836 [ -1, 24, 109, -4 ],
837 [ 0, 9, 122, -3 ]
838 ], [
839 [ 0, 128, 0, 0 ],
840 [ -4, 124, 9, -1 ],
841 [ -5, 110, 25, -2 ],
842 [ -6, 91, 46, -3 ],
843 [ -5, 69, 69, -5 ],
844 [ -3, 46, 91, -6 ],
845 [ -2, 25, 110, -5 ],
846 [ -1, 9, 124, -4 ]
847 ], [
848 [ 0, 128, 0, 0 ],
849 [ -4, 123, 10, -1 ],
850 [ -6, 110, 26, -2 ],
851 [ -7, 92, 47, -4 ],
852 [ -6, 70, 70, -6 ],
853 [ -4, 47, 92, -7 ],
854 [ -2, 26, 110, -6 ],
855 [ -1, 10, 123, -4 ]
856 ], [
857 [ 0, 128, 0, 0 ],
858 [ -5, 124, 10, -1 ],
859 [ -7, 110, 27, -2 ],
860 [ -7, 91, 48, -4 ],
861 [ -6, 70, 70, -6 ],
862 [ -4, 48, 92, -8 ],
863 [ -2, 27, 110, -7 ],
864 [ -1, 10, 124, -5 ]
865 ], [
866 [ 0, 128, 0, 0 ],
867 [ -6, 124, 11, -1 ],
868 [ -8, 111, 28, -3 ],
869 [ -8, 92, 49, -5 ],
870 [ -7, 71, 71, -7 ],
871 [ -5, 49, 92, -8 ],
872 [ -3, 28, 111, -8 ],
873 [ -1, 11, 124, -6 ]
874 ], [
875 [ 0, 128, 0, 0 ],
876 [ -6, 123, 12, -1 ],
877 [ -9, 111, 29, -3 ],
878 [ -9, 93, 50, -6 ],
879 [ -8, 72, 72, -8 ],
880 [ -6, 50, 93, -9 ],
881 [ -3, 29, 111, -9 ],
882 [ -1, 12, 123, -6 ]
883 ], [
884 [ 0, 128, 0, 0 ],
885 [ -7, 124, 12, -1 ],
886 [ -10, 111, 30, -3 ],
887 [ -10, 93, 51, -6 ],
888 [ -9, 73, 73, -9 ],
889 [ -6, 51, 93, -10 ],
890 [ -3, 30, 111, -10 ],
891 [ -1, 12, 124, -7 ]
892 ], [
893 [ 0, 128, 0, 0 ],
894 [ -7, 123, 13, -1 ],
895 [ -11, 112, 31, -4 ],
896 [ -11, 94, 52, -7 ],
897 [ -10, 74, 74, -10 ],
898 [ -7, 52, 94, -11 ],
899 [ -4, 31, 112, -11 ],
900 [ -1, 13, 123, -7 ]
901 ], [
902 [ 0, 128, 0, 0 ],
903 [ -8, 124, 13, -1 ],
904 [ -12, 112, 32, -4 ],
905 [ -12, 94, 53, -7 ],
906 [ -10, 74, 74, -10 ],
907 [ -7, 53, 94, -12 ],
908 [ -4, 32, 112, -12 ],
909 [ -1, 13, 124, -8 ]
910 ], [
911 [ 0, 128, 0, 0 ],
912 [ -9, 124, 14, -1 ],
913 [ -13, 112, 33, -4 ],
914 [ -13, 95, 54, -8 ],
915 [ -11, 75, 75, -11 ],
916 [ -8, 54, 95, -13 ],
917 [ -4, 33, 112, -13 ],
918 [ -1, 14, 124, -9 ]
919 ], [
920 [ 0, 128, 0, 0 ],
921 [ -9, 123, 15, -1 ],
922 [ -14, 113, 34, -5 ],
923 [ -14, 95, 55, -8 ],
924 [ -12, 76, 76, -12 ],
925 [ -8, 55, 95, -14 ],
926 [ -5, 34, 112, -13 ],
927 [ -1, 15, 123, -9 ]
928 ], [
929 [ 0, 128, 0, 0 ],
930 [ -10, 124, 15, -1 ],
931 [ -14, 113, 34, -5 ],
932 [ -15, 96, 56, -9 ],
933 [ -13, 77, 77, -13 ],
934 [ -9, 56, 96, -15 ],
935 [ -5, 34, 113, -14 ],
936 [ -1, 15, 124, -10 ]
937 ], [
938 [ 0, 128, 0, 0 ],
939 [ -10, 123, 16, -1 ],
940 [ -15, 113, 35, -5 ],
941 [ -16, 98, 56, -10 ],
942 [ -14, 78, 78, -14 ],
943 [ -10, 56, 98, -16 ],
944 [ -5, 35, 113, -15 ],
945 [ -1, 16, 123, -10 ]
946 ], [
947 [ 0, 128, 0, 0 ],
948 [ -11, 124, 17, -2 ],
949 [ -16, 113, 36, -5 ],
950 [ -17, 98, 57, -10 ],
951 [ -14, 78, 78, -14 ],
952 [ -10, 57, 98, -17 ],
953 [ -5, 36, 113, -16 ],
954 [ -2, 17, 124, -11 ]
955 ], [
956 [ 0, 128, 0, 0 ],
957 [ -12, 125, 17, -2 ],
958 [ -17, 114, 37, -6 ],
959 [ -18, 99, 58, -11 ],
960 [ -15, 79, 79, -15 ],
961 [ -11, 58, 99, -18 ],
962 [ -6, 37, 114, -17 ],
963 [ -2, 17, 125, -12 ]
964 ], [
965 [ 0, 128, 0, 0 ],
966 [ -12, 124, 18, -2 ],
967 [ -18, 114, 38, -6 ],
968 [ -19, 99, 59, -11 ],
969 [ -16, 80, 80, -16 ],
970 [ -11, 59, 99, -19 ],
971 [ -6, 38, 114, -18 ],
972 [ -2, 18, 124, -12 ]
973 ], [
974 [ 0, 128, 0, 0 ],
975 [ -4, 118, 16, -2 ],
976 [ -7, 106, 34, -5 ],
977 [ -8, 90, 53, -7 ],
978 [ -8, 72, 72, -8 ],
979 [ -7, 53, 90, -8 ],
980 [ -5, 34, 106, -7 ],
981 [ -2, 16, 118, -4 ]
982 ]
983 ];