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::*;
8 const VERSION_VP60: u8 = 6;
9 //const VERSION_VP61: u8 = 7;
10 const VERSION_VP62: u8 = 8;
12 const VP6_SIMPLE_PROFILE: u8 = 0;
13 const VP6_ADVANCED_PROFILE: u8 = 3;
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
40 let mut br = BitReader::new(src, BitReaderMode::BE);
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()?;
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()?;
53 hdr.version = self.vpversion;
54 hdr.profile = self.profile;
55 hdr.interlaced = self.interlaced;
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 });
61 let bytes = br.tell() >> 3;
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;
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);
81 if hdr.version == VERSION_VP62 {
82 self.do_pm = bc.read_bool();
87 if (hdr.profile == VP6_ADVANCED_PROFILE) && (hdr.is_intra || self.do_pm) {
88 self.autosel_pm = bc.read_bool();
90 self.var_thresh = bc.read_bits(5) as u16;
91 if hdr.version != VERSION_VP62 {
92 self.var_thresh <<= 5;
94 self.mv_thresh = bc.read_bits(3) as u8;
96 self.bicubic = bc.read_bool();
98 if hdr.version == VERSION_VP62 {
99 self.filter_alpha = bc.read_bits(4) as usize;
101 self.filter_alpha = 16;
105 hdr.use_huffman = bc.read_bool();
107 self.vpversion = hdr.version;
108 self.profile = hdr.profile;
109 self.interlaced = hdr.interlaced;
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 ];
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)))
125 for ord in LONG_VECTOR_ORDER.iter() {
126 raw |= (bc.read_prob(model.raw_probs[*ord]) as i16) << *ord;
128 if (raw & 0xF0) != 0 {
129 raw |= (bc.read_prob(model.raw_probs[3]) as i16) << 3;
135 if (val != 0) && bc.read_prob(model.sign_prob) {
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 ]
147 const TREE_PROBS: [[u8; 7]; 2] = [
148 [ 225, 146, 172, 147, 214, 39, 156 ],
149 [ 204, 170, 119, 235, 140, 230, 228 ]
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 ]
156 for (i, mdl) in models.mv_models.iter_mut().enumerate() {
157 mdl.nz_prob = NZ_PROBS[i];
159 mdl.raw_probs.copy_from_slice(&RAW_PROBS[i]);
160 mdl.tree_probs.copy_from_slice(&TREE_PROBS[i]);
162 models.vp6models.zero_run_probs.copy_from_slice(&ZERO_RUN_PROBS);
163 reset_scan(&mut models.vp6models, self.interlaced);
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 ]
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 ]
178 if bc.read_prob(HAS_NZ_PROB[comp]) {
179 models[comp].nz_prob = bc.read_probability();
181 if bc.read_prob(HAS_SIGN_PROB[comp]) {
182 models[comp].sign_prob = bc.read_probability();
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();
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();
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 ]
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
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 ]
221 let mut def_prob = [128u8; 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];
228 models.coeff_models[plane].dc_value_probs[i] = def_prob[i];
235 if bc.read_prob(SCAN_UPD_PROBS[i]) {
236 models.vp6models.scan_order[i] = bc.read_bits(4) as usize;
239 update_scan(&mut models.vp6models);
241 reset_scan(&mut models.vp6models, self.interlaced);
246 if bc.read_prob(ZERO_RUN_PROBS[comp][i]) {
247 models.vp6models.zero_run_probs[comp][i] = bc.read_probability();
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];
260 models.coeff_models[plane].ac_val_probs[ctype][group][i] = def_prob[i];
267 let mdl = &mut models.coeff_models[plane];
270 mdl.dc_token_probs[0][i][k] = rescale_prob(mdl.dc_value_probs[k], &VP6_DC_WEIGHTS[k][i], 255);
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);
283 fstate.last_idx[fstate.ctx_idx] = 0;
286 let mut last_val = val;
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);
298 idx += decode_zero_run_bc(bc, &vp6model.zero_run_probs[if idx >= 7 { 1 } else { 0 }]);
299 validate!(idx <= 64);
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;
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 };
311 if fstate.dc_zero_run[plane] == 0 {
312 let (val, eob) = decode_token_huff(br, &model.dc_token_tree[plane])?;
319 fstate.dc_zero_run[plane] = decode_eob_run_huff(br)?;
323 fstate.dc_zero_run[plane] -= 1;
326 if fstate.ac_zero_run[plane] > 0 {
327 fstate.ac_zero_run[plane] -= 1;
328 fstate.last_idx[fstate.ctx_idx] = 0;
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])?;
339 fstate.ac_zero_run[plane] = decode_eob_run_huff(br)?;
343 coeffs[vp6model.zigzag[idx]] = val.wrapping_mul(fstate.ac_quant);
347 idx += decode_zero_run_huff(br, &model.zero_run_tree[if idx >= 7 { 1 } else { 0 }])?;
348 validate!(idx <= 64);
352 fstate.last_idx[fstate.ctx_idx] = idx;
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)
361 (mv.x >> 3, mv.y >> 3, mv.x & 7, mv.y & 7, mv.x / 8, mv.y / 8)
363 let tmp_blk = mc_buf.get_data_mut().unwrap();
364 get_block(tmp_blk, 16, src.clone(), plane, x, y, sx, sy);
366 let foff = (8 - (sx & 7)) as usize;
368 vp31_loop_filter(tmp_blk, off, 1, 16, 12, loop_str);
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);
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 {
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 {
393 let dstride = dst.stride[plane];
394 let dbuf = &mut dst.data[dst.offset[plane] + x + y * dstride..];
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]);
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);
405 mc_bilinear(dbuf, dstride, tmp_blk, 16 * 2 + 2, 16, mx as u16, my as u16);
410 fn update_scan(model: &mut VP6Models) {
414 if model.scan_order[i] == band {
421 model.zigzag[i] = ZIGZAG[model.scan[i]];
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
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
448 model.scan_order.copy_from_slice(&VP6_DEFAULT_SCAN_ORDER);
450 model.scan_order.copy_from_slice(&VP6_INTERLACED_SCAN_ORDER);
452 for i in 0..64 { model.scan[i] = i; }
453 model.zigzag.copy_from_slice(&ZIGZAG);
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]) {
464 vp_tree!(bc, probs[2],
466 vp_tree!(bc, probs[3],
467 vp_tree!(bc, probs[4],
469 vp_tree!(bc, prob34, 3, 4)),
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)),
489 nval += (bc.read_prob(probs[i + 8]) as usize) << i;
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)?;
501 if !br.read_bool()? {
502 Ok((i16::from(tok), false))
504 Ok((-i16::from(tok), false))
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()? {
521 fn decode_eob_run_huff(br: &mut BitReader) -> DecoderResult<usize> {
522 let val = br.read(2)?;
527 let val = br.read(2)?;
528 Ok((val as usize) + 2)
532 Ok((br.read(6)? as usize) + 10)
534 Ok((br.read(2)? as usize) + 6)
540 fn decode_zero_run_huff(br: &mut BitReader, huff: &VP6Huff) -> DecoderResult<usize> {
541 let val = br.read_huff(huff)?;
545 Ok((br.read(6)? as usize) + 8)
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)
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);
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);
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]);
574 fn calc_variance(src: &[u8], stride: usize) -> u16 {
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);
584 ((ssum * 16 - sum * sum) >> 8) as u16
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
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
599 //#[allow(snake_case)]
600 fn mc_bilinear(dst: &mut [u8], dstride: usize, src: &[u8], mut soff: usize, sstride: usize, mx: u16, my: u16) {
602 for dline in dst.chunks_mut(dstride).take(8) {
604 dline[i] = mc_filter!(bilinear; src[soff + i], src[soff + i + 1], mx);
609 for dline in dst.chunks_mut(dstride).take(8) {
611 dline[i] = mc_filter!(bilinear; src[soff + i], src[soff + i + sstride], my);
616 let mut tmp = [0u8; 8];
618 tmp[i] = mc_filter!(bilinear; src[soff + i], src[soff + i + 1], mx);
621 for dline in dst.chunks_mut(dstride).take(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);
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) {
637 dline[i] = mc_filter!(bicubic; src, soff + i, 1, coeffs_w);
641 } else if coeffs_w[1] == 128 { // horizontal-only interpolation
642 for dline in dst.chunks_mut(dstride).take(8) {
644 dline[i] = mc_filter!(bicubic; src, soff + i, sstride, coeffs_h);
649 let mut buf = [0u8; 16 * 11];
651 for dline in buf.chunks_mut(16) {
653 dline[i] = mc_filter!(bicubic; src, soff + i, 1, coeffs_w);
658 for dline in dst.chunks_mut(dstride).take(8) {
660 dline[i] = mc_filter!(bicubic; buf, soff + i, 16, coeffs_h);
669 info: NACodecInfoRef,
675 fn new(has_alpha: bool) -> Self {
677 dec: VP56Decoder::new(6, has_alpha, true),
678 info: NACodecInfoRef::default(),
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 {
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)?;
699 Err(DecoderError::InvalidData)
702 fn decode(&mut self, supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
703 let src = pkt.get_buffer();
705 let (bufinfo, ftype) = self.dec.decode_frame(supp, src.as_slice(), &mut self.br)?;
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);
712 fn flush(&mut self) {
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 }
723 pub fn get_decoder_vp6() -> Box<NADecoder + Send> {
724 Box::new(VP6Decoder::new(false))
727 pub fn get_decoder_vp6_alpha() -> Box<NADecoder + Send> {
728 Box::new(VP6Decoder::new(true))
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_codecs;
737 use nihav_commonfmt::generic_register_all_demuxers;
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_codecs(&mut dec_reg);
746 test_decoding("avi", "vp6", "assets/Duck/selection_720x576_300kBit_vp60i.avi", Some(16),
748 ExpectedTestResult::MD5([0x042c3e96, 0x8a9b26a2, 0x4dcbaf66, 0x1b788d03]));
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_codecs(&mut dec_reg);
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]]));
765 // todo find good sample for vp6a test
768 const VP6_AC_PROBS: [[[[u8; 11]; 6]; 2]; 3] = [
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 ]
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 ]
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 ]
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 ]
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 ]
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 ]
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 ] ]
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
839 const VP6_BICUBIC_COEFFS: [[[i16; 4]; 8]; 17] = [
897 [ -10, 111, 30, -3 ],
901 [ -3, 30, 111, -10 ],
906 [ -11, 112, 31, -4 ],
908 [ -10, 74, 74, -10 ],
910 [ -4, 31, 112, -11 ],
915 [ -12, 112, 32, -4 ],
917 [ -10, 74, 74, -10 ],
919 [ -4, 32, 112, -12 ],
924 [ -13, 112, 33, -4 ],
926 [ -11, 75, 75, -11 ],
928 [ -4, 33, 112, -13 ],
933 [ -14, 113, 34, -5 ],
935 [ -12, 76, 76, -12 ],
937 [ -5, 34, 112, -13 ],
941 [ -10, 124, 15, -1 ],
942 [ -14, 113, 34, -5 ],
944 [ -13, 77, 77, -13 ],
946 [ -5, 34, 113, -14 ],
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 ],
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 ],
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 ],
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 ],