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