1 use nihav_core::codecs::*;
2 use nihav_core::data::GenericCache;
3 use nihav_core::io::bitreader::*;
4 use super::vpcommon::*;
6 pub const TOKEN_LARGE: u8 = 5;
7 pub const TOKEN_EOB: u8 = 42;
9 #[derive(Clone,Copy,Debug,Default)]
11 pub struct VP56Header {
15 pub multistream: bool,
16 pub use_huffman: bool,
28 #[derive(Clone,Copy,Default)]
29 pub struct VP56MVModel {
32 pub raw_probs: [u8; 8],
33 pub tree_probs: [u8; 7],
36 #[derive(Clone,Copy,Default)]
37 pub struct VP56MBTypeModel {
41 #[derive(Clone,Copy,Default)]
42 pub struct VP56CoeffModel {
43 pub dc_token_probs: [[[u8; 5]; 6]; 6],
44 pub dc_value_probs: [u8; 11],
45 pub ac_ctype_probs: [[[[u8; 5]; 5]; 6]; 3],
46 pub ac_type_probs: [[[[u8; 5]; 6]; 3]; 3],
47 pub ac_val_probs: [[[u8; 11]; 6]; 3],
50 pub struct VP6Models {
51 pub scan_order: [usize; 64],
52 pub scan: [usize; 64],
53 pub zigzag: [usize; 64],
54 pub zero_run_probs: [[u8; 14]; 2],
57 const MAX_HUFF_ELEMS: usize = 12;
58 #[derive(Clone,Copy,Default)]
60 pub codes: [u16; MAX_HUFF_ELEMS],
61 pub bits: [u8; MAX_HUFF_ELEMS],
64 #[derive(Clone,Copy,Default)]
72 fn prob2weight(a: u8, b: u8) -> u8 {
73 let w = (((a as u16) * (b as u16)) >> 8) as u8;
82 fn build_codes(&mut self, probs: &[u8; 11]) {
83 let mut weights = [0u8; 12];
85 weights[11] = prob2weight( probs[0], probs[ 1]);
86 weights[ 0] = prob2weight( probs[0], !probs[ 1]);
87 weights[ 1] = prob2weight(!probs[0], probs[ 2]);
88 let lvroot = prob2weight(!probs[0], !probs[ 2]);
89 let tworoot = prob2weight( lvroot, probs[ 3]);
90 let hlroot = prob2weight( lvroot, !probs[ 3]);
91 weights[ 2] = prob2weight( tworoot, probs[ 4]);
92 let root34 = prob2weight( tworoot, !probs[ 4]);
93 weights[ 3] = prob2weight( root34, probs[ 5]);
94 weights[ 4] = prob2weight( root34, !probs[ 5]);
95 let c1root = prob2weight( hlroot, probs[ 6]);
96 let c34root = prob2weight( hlroot, !probs[ 6]);
97 weights[ 5] = prob2weight( c1root, probs[ 7]);
98 weights[ 6] = prob2weight( c1root, !probs[ 7]);
99 let c3root = prob2weight( c34root, probs[ 8]);
100 let c4root = prob2weight( c34root, !probs[ 8]);
101 weights[ 7] = prob2weight( c3root, probs[ 9]);
102 weights[ 8] = prob2weight( c3root, !probs[ 9]);
103 weights[ 9] = prob2weight( c4root, probs[10]);
104 weights[10] = prob2weight( c4root, !probs[10]);
106 self.build(&weights);
108 fn build_codes_zero_run(&mut self, probs: &[u8; 14]) {
109 let mut weights = [0u8; 9];
111 let root = prob2weight( probs[0], probs[1]);
112 weights[0] = prob2weight( root, probs[2]);
113 weights[1] = prob2weight( root, !probs[2]);
115 let root = prob2weight( probs[0], !probs[1]);
116 weights[2] = prob2weight( root, probs[3]);
117 weights[3] = prob2weight( root, !probs[3]);
119 let root = prob2weight(!probs[0], probs[4]);
120 weights[8] = prob2weight(!probs[0], !probs[4]);
121 let root1 = prob2weight( root, probs[5]);
122 let root2 = prob2weight( root, !probs[5]);
123 weights[4] = prob2weight( root1, probs[6]);
124 weights[5] = prob2weight( root1, !probs[6]);
125 weights[6] = prob2weight( root2, probs[7]);
126 weights[7] = prob2weight( root2, !probs[7]);
128 self.build(&weights);
130 fn build(&mut self, weights: &[u8]) {
131 let mut nodes = [Node::default(); MAX_HUFF_ELEMS * 2];
134 for w in weights.iter().rev() {
135 let weight = *w as u16;
138 if nodes[i].weight > weight {
143 for j in (pos..nlen).rev() {
144 nodes[j + 1] = nodes[j];
146 nodes[pos].weight = weight;
147 nodes[pos].sym = (weights.len() - nlen - 1) as i8;
154 weight: nodes[low + 0].weight + nodes[low + 1].weight,
161 while (pos < nlen) && (nodes[pos].weight < nnode.weight) {
164 for j in (pos..nlen).rev() {
165 nodes[j + 1] = nodes[j];
170 self.get_codes(&nodes, nlen - 1, 0, 0);
171 for i in nlen..self.codes.len() {
172 self.codes[i] = self.codes[0];
173 self.bits[i] = self.bits[0];
176 fn get_codes(&mut self, nodes: &[Node], pos: usize, code: u16, len: u8) {
177 if nodes[pos].sym >= 0 {
178 self.codes[nodes[pos].sym as usize] = code;
179 self.bits [nodes[pos].sym as usize] = len;
181 self.get_codes(nodes, nodes[pos].ch0, (code << 1) | 0, len + 1);
182 self.get_codes(nodes, nodes[pos].ch1, (code << 1) | 1, len + 1);
188 fn read_huff(&mut self, huff: &VP6Huff) -> DecoderResult<u8>;
191 impl<'a> ReadHuff for BitReader<'a> {
192 fn read_huff(&mut self, huff: &VP6Huff) -> DecoderResult<u8> {
193 let peekval = self.peek(16);
194 for (i, (code, bit)) in huff.codes.iter().zip(huff.bits.iter()).enumerate() {
195 if (peekval >> (16 - *bit)) == (*code as u32) {
196 self.skip(*bit as u32)?;
200 Err(DecoderError::InvalidData)
204 #[derive(Clone,Copy,Default)]
205 pub struct VP6HuffModels {
206 pub dc_token_tree: [VP6Huff; 2],
207 pub ac_token_tree: [[[VP6Huff; 6]; 3]; 2],
208 pub zero_run_tree: [VP6Huff; 2],
217 zero_run_probs: [[0; 14]; 2],
222 pub struct VP56Models {
223 pub mv_models: [VP56MVModel; 2],
224 pub mbtype_models: [[VP56MBTypeModel; 10]; 3],
225 pub coeff_models: [VP56CoeffModel; 2],
226 pub prob_xmitted: [[u8; 20]; 3],
227 pub vp6models: VP6Models,
228 pub vp6huff: VP6HuffModels,
234 mv_models: [VP56MVModel::default(); 2],
235 mbtype_models: [[VP56MBTypeModel::default(); 10]; 3],
236 coeff_models: [VP56CoeffModel::default(); 2],
237 prob_xmitted: [[0; 20]; 3],
238 vp6models: VP6Models::new(),
239 vp6huff: VP6HuffModels::default(),
244 pub trait VP56Parser {
245 fn parse_header(&mut self, bc: &mut BoolCoder) -> DecoderResult<VP56Header>;
246 fn reset_models(&self, models: &mut VP56Models);
247 fn decode_mv(&self, bc: &mut BoolCoder, model: &VP56MVModel) -> i16;
248 fn decode_mv_models(&self, bc: &mut BoolCoder, models: &mut [VP56MVModel; 2]) -> DecoderResult<()>;
249 fn decode_coeff_models(&self, bc: &mut BoolCoder, models: &mut VP56Models, is_intra: bool) -> DecoderResult<()>;
250 fn decode_block(&self, bc: &mut BoolCoder, coeffs: &mut [i16; 64], model: &VP56CoeffModel, vp6model: &VP6Models, fstate: &mut FrameState) -> DecoderResult<()>;
251 fn decode_block_huff(&self, br: &mut BitReader, coeffs: &mut [i16; 64], vp6model: &VP6Models, model: &VP6HuffModels, fstate: &mut FrameState) -> DecoderResult<()>;
252 fn mc_block(&self, dst: &mut NASimpleVideoFrame<u8>, mc_buf: NAVideoBufferRef<u8>, src: NAVideoBufferRef<u8>, plane: usize, x: usize, y: usize, mv: MV, loop_thr: i16);
255 enum CoeffReader<'a> {
261 #[derive(Clone,Copy,Default)]
267 pub struct FrameState {
271 pub coeff_cat: [[u8; 64]; 4],
272 pub last_idx: [usize; 4],
277 pub dc_zero_run: [usize; 2],
278 pub ac_zero_run: [usize; 2],
287 coeff_cat: [[0; 64]; 4],
299 pub struct VP56Decoder {
309 coeffs: [[i16; 64]; 6],
316 mb_info: Vec<MBInfo>,
318 dc_y: GenericCache<i16>,
319 dc_u: GenericCache<i16>,
320 dc_v: GenericCache<i16>,
321 dc_a: GenericCache<i16>,
322 last_dc: [[i16; 4]; 3],
323 top_ctx: [Vec<u8>; 4],
325 mc_buf: NAVideoBufferRef<u8>,
328 fn rescale_mb_mode_prob(prob: u32, total: u32) -> u8 {
329 (255 * prob / (1 + total)) as u8
332 fn map_mb_type(mbtype: VPMBType) -> usize {
334 VPMBType::InterNoMV => 0,
335 VPMBType::Intra => 1,
336 VPMBType::InterMV => 2,
337 VPMBType::InterNearest => 3,
338 VPMBType::InterNear => 4,
339 VPMBType::GoldenNoMV => 5,
340 VPMBType::GoldenMV => 6,
341 VPMBType::InterFourMV => 7,
342 VPMBType::GoldenNearest => 8,
343 VPMBType::GoldenNear => 9,
347 pub fn expand_token_bc(bc: &mut BoolCoder, val_probs: &[u8; 11], token: u8, version: u8) -> i16 {
348 let mut sign = false;
350 if token < TOKEN_LARGE {
352 sign = bc.read_bool();
354 level = token as i16;
356 let cat: usize = vp_tree!(bc, val_probs[6],
357 vp_tree!(bc, val_probs[7], 0, 1),
358 vp_tree!(bc, val_probs[8],
359 vp_tree!(bc, val_probs[9], 2, 3),
360 vp_tree!(bc, val_probs[10], 4, 5)));
362 sign = bc.read_bool();
365 let add_probs = &VP56_COEF_ADD_PROBS[cat];
366 for prob in add_probs.iter() {
367 if *prob == 128 { break; }
368 add = (add << 1) | (bc.read_prob(*prob) as i16);
371 sign = bc.read_bool();
373 level = VP56_COEF_BASE[cat] + add;
383 pub fn new(version: u8, has_alpha: bool, flip: bool) -> Self {
384 let vt = alloc_video_buffer(NAVideoInfo::new(24, 24, false, YUV420_FORMAT), 4).unwrap();
385 let mc_buf = vt.get_vbuf().unwrap();
387 version, has_alpha, flip,
388 shuf: VPShuffler::new(),
393 models: VP56Models::new(),
394 coeffs: [[0; 64]; 6],
395 last_mbt: VPMBType::InterNoMV,
402 fstate: FrameState::new(),
403 dc_y: GenericCache::new(0, 0, 0),
404 dc_u: GenericCache::new(0, 0, 0),
405 dc_v: GenericCache::new(0, 0, 0),
406 dc_a: GenericCache::new(0, 0, 0),
407 last_dc: [[0; 4]; 3],
408 top_ctx: [Vec::new(), Vec::new(), Vec::new(), Vec::new()],
413 fn set_dimensions(&mut self, width: usize, height: usize) {
415 self.height = height;
416 self.mb_w = (self.width + 15) >> 4;
417 self.mb_h = (self.height + 15) >> 4;
418 self.mb_info.resize(self.mb_w * self.mb_h, MBInfo::default());
419 self.dc_y = GenericCache::new(2, 1 + self.mb_w * 2, 0);
420 self.dc_u = GenericCache::new(1, 1 + self.mb_w, 0);
421 self.dc_v = GenericCache::new(1, 1 + self.mb_w, 0);
422 self.dc_a = GenericCache::new(2, 1 + self.mb_w * 2, 0);
423 self.top_ctx = [vec![0; self.mb_w * 2], vec![0; self.mb_w], vec![0; self.mb_w], vec![0; self.mb_w * 2]];
425 pub fn init(&mut self, supp: &mut NADecoderSupport, vinfo: NAVideoInfo) -> DecoderResult<()> {
426 supp.pool_u8.set_dec_bufs(3);
427 supp.pool_u8.prealloc_video(NAVideoInfo::new(vinfo.get_width(), vinfo.get_height(), false, vinfo.get_format()), 4)?;
428 self.set_dimensions(vinfo.get_width(), vinfo.get_height());
431 pub fn flush(&mut self) {
434 pub fn decode_frame(&mut self, supp: &mut NADecoderSupport, src: &[u8], br: &mut dyn VP56Parser) -> DecoderResult<(NABufferType, FrameType)> {
438 validate!(src.len() >= 7);
439 aoffset = ((src[0] as usize) << 16) | ((src[1] as usize) << 8) | (src[2] as usize);
440 validate!((aoffset > 0) && (aoffset < src.len() - 3));
441 bc = BoolCoder::new(&src[3..])?;
443 validate!(src.len() >= 4);
445 bc = BoolCoder::new(src)?;
447 let hdr = br.parse_header(&mut bc)?;
448 validate!((hdr.offset as usize) < aoffset); //XXX: take alpha 3 byte offset into account?
451 self.set_dimensions((hdr.mb_w as usize) * 16, (hdr.mb_h as usize) * 16);
453 let vinfo = NAVideoInfo::new(self.width, self.height, self.flip, YUV420_FORMAT);
454 let ret = supp.pool_u8.get_free();
456 return Err(DecoderError::AllocError);
458 let mut buf = ret.unwrap();
459 if buf.get_info() != vinfo {
461 supp.pool_u8.reset();
462 supp.pool_u8.prealloc_video(vinfo, 4)?;
463 let ret = supp.pool_u8.get_free();
465 return Err(DecoderError::AllocError);
469 let mut dframe = NASimpleVideoFrame::from_video_buf(&mut buf).unwrap();
477 let off = (if self.has_alpha { 3 } else { 0 }) + (hdr.offset as usize);
478 if !hdr.use_huffman {
479 let bc2 = BoolCoder::new(&src[off..])?;
480 cr = CoeffReader::Bool(bc2);
482 let br = BitReader::new(&src[off..], aoffset - off, BitReaderMode::BE);
483 cr = CoeffReader::Huff(br);
486 cr = CoeffReader::None;
490 br.reset_models(&mut self.models);
491 self.reset_mbtype_models();
493 self.decode_mode_prob_models(&mut bc)?;
494 br.decode_mv_models(&mut bc, &mut self.models.mv_models)?;
496 br.decode_coeff_models(&mut bc, &mut self.models, hdr.is_intra)?;
499 self.models.vp6huff.dc_token_tree[i].build_codes(&self.models.coeff_models[i].dc_value_probs);
504 self.models.vp6huff.ac_token_tree[i][mode][band].build_codes(&self.models.coeff_models[i].ac_val_probs[mode][band]);
509 self.models.vp6huff.zero_run_tree[i].build_codes_zero_run(&self.models.vp6models.zero_run_probs[i]);
514 self.ilace_prob = bc.read_bits(8) as u8;
517 self.fstate = FrameState::new();
518 self.fstate.dc_quant = VP56_DC_QUANTS[hdr.quant as usize] * 4;
519 self.fstate.ac_quant = VP56_AC_QUANTS[hdr.quant as usize] * 4;
520 self.loop_thr = VP56_FILTER_LIMITS[hdr.quant as usize] as i16;
522 self.last_mbt = VPMBType::InterNoMV;
527 for vec in self.top_ctx.iter_mut() {
528 for el in vec.iter_mut() {
532 self.last_dc = [[0; 4]; 3];
533 self.last_dc[0][1] = 0x80;
534 self.last_dc[0][2] = 0x80;
536 self.ilace_mb = false;
537 for mb_y in 0..self.mb_h {
538 self.fstate.mb_y = mb_y;
539 self.fstate.coeff_cat = [[0; 64]; 4];
540 self.fstate.last_idx = [24; 4];
541 for mb_x in 0..self.mb_w {
542 self.fstate.mb_x = mb_x;
543 self.decode_mb(&mut dframe, &mut bc, &mut cr, br, &hdr, false)?;
545 self.dc_y.update_row();
546 self.dc_u.update_row();
547 self.dc_v.update_row();
548 self.dc_a.update_row();
552 let asrc = &src[aoffset + 3..];
553 let mut bc = BoolCoder::new(asrc)?;
554 let ahdr = br.parse_header(&mut bc)?;
555 validate!(ahdr.mb_w == hdr.mb_w && ahdr.mb_h == hdr.mb_h);
559 self.shuf.add_golden_frame(buf.clone());
561 self.shuf.add_frame(buf.clone());
563 Ok((NABufferType::Video(buf), if hdr.is_intra { FrameType::I } else { FrameType::P }))
565 fn reset_mbtype_models(&mut self) {
566 const DEFAULT_XMITTED_PROBS: [[u8; 20]; 3] = [
567 [ 42, 69, 2, 1, 7, 1, 42, 44, 22, 6, 3, 1, 2, 0, 5, 1, 1, 0, 0, 0 ],
568 [ 8, 229, 1, 1, 8, 0, 0, 0, 0, 0, 2, 1, 1, 0, 0, 0, 1, 1, 0, 0 ],
569 [ 35, 122, 1, 1, 6, 1, 34, 46, 0, 0, 2, 1, 1, 0, 1, 0, 1, 1, 0, 0 ]
571 self.models.prob_xmitted.copy_from_slice(&DEFAULT_XMITTED_PROBS);
573 fn decode_mode_prob_models(&mut self, bc: &mut BoolCoder) -> DecoderResult<()> {
575 if bc.read_prob(174) {
576 let idx = bc.read_bits(4) as usize;
578 self.models.prob_xmitted[ctx][i ^ 1] = VP56_MODE_VQ[ctx][idx][i];
581 if bc.read_prob(254) {
583 if bc.read_prob(205) {
584 let sign = bc.read_bool();
585 let diff = vp_tree!(bc, 171,
586 vp_tree!(bc, 83, 2, 1),
590 vp_tree!(bc, 104, 6, 5),
597 validate!(diff < 256);
598 let diff = diff as u8;
600 validate!(self.models.prob_xmitted[ctx][set ^ 1] <= 255 - diff);
601 self.models.prob_xmitted[ctx][set ^ 1] += diff;
603 validate!(self.models.prob_xmitted[ctx][set ^ 1] >= diff);
604 self.models.prob_xmitted[ctx][set ^ 1] -= diff;
611 let prob_xmitted = &self.models.prob_xmitted[ctx];
613 let mdl = &mut self.models.mbtype_models[ctx][mode];
614 let mut cnt = [0u32; 10];
617 if i == mode { continue; }
618 cnt[i] = 100 * (prob_xmitted[i * 2] as u32);
621 let sum = (prob_xmitted[mode * 2] as u32) + (prob_xmitted[mode * 2 + 1] as u32);
622 mdl.probs[9] = 255 - rescale_mb_mode_prob(prob_xmitted[mode * 2 + 1] as u32, sum);
624 let inter_mv0_weight = (cnt[0] as u32) + (cnt[2] as u32);
625 let inter_mv1_weight = (cnt[3] as u32) + (cnt[4] as u32);
626 let gold_mv0_weight = (cnt[5] as u32) + (cnt[6] as u32);
627 let gold_mv1_weight = (cnt[8] as u32) + (cnt[9] as u32);
628 let mix_weight = (cnt[1] as u32) + (cnt[7] as u32);
629 mdl.probs[0] = 1 + rescale_mb_mode_prob(inter_mv0_weight + inter_mv1_weight, total);
630 mdl.probs[1] = 1 + rescale_mb_mode_prob(inter_mv0_weight, inter_mv0_weight + inter_mv1_weight);
631 mdl.probs[2] = 1 + rescale_mb_mode_prob(mix_weight, mix_weight + gold_mv0_weight + gold_mv1_weight);
632 mdl.probs[3] = 1 + rescale_mb_mode_prob(cnt[0] as u32, inter_mv0_weight);
633 mdl.probs[4] = 1 + rescale_mb_mode_prob(cnt[3] as u32, inter_mv1_weight);
634 mdl.probs[5] = 1 + rescale_mb_mode_prob(cnt[1], mix_weight);
635 mdl.probs[6] = 1 + rescale_mb_mode_prob(gold_mv0_weight, gold_mv0_weight + gold_mv1_weight);
636 mdl.probs[7] = 1 + rescale_mb_mode_prob(cnt[5], gold_mv0_weight);
637 mdl.probs[8] = 1 + rescale_mb_mode_prob(cnt[8], gold_mv1_weight);
642 fn find_mv_pred(&self, ref_id: u8) -> (usize, MV, MV, MV) {
643 const CAND_POS: [(i8, i8); 12] = [
652 let mut nearest_mv = ZERO_MV;
653 let mut near_mv = ZERO_MV;
654 let mut pred_mv = ZERO_MV;
655 let mut num_mv: usize = 0;
657 for (i, (yoff, xoff)) in CAND_POS.iter().enumerate() {
658 let cx = (self.fstate.mb_x as isize) + (*xoff as isize);
659 let cy = (self.fstate.mb_y as isize) + (*yoff as isize);
660 if (cx < 0) || (cy < 0) {
663 let cx = cx as usize;
664 let cy = cy as usize;
665 if (cx >= self.mb_w) || (cy >= self.mb_h) {
668 let mb_pos = cx + cy * self.mb_w;
669 let mv = self.mb_info[mb_pos].mv;
670 if (self.mb_info[mb_pos].mb_type.get_ref_id() != ref_id) || (mv == ZERO_MV) {
676 if (self.version > 5) && (i < 2) {
679 } else if mv != nearest_mv {
686 (num_mv, nearest_mv, near_mv, pred_mv)
688 fn decode_mv(&self, bc: &mut BoolCoder, br: &mut dyn VP56Parser) -> MV {
689 let x = br.decode_mv(bc, &self.models.mv_models[0]);
690 let y = br.decode_mv(bc, &self.models.mv_models[1]);
693 fn decode_mb_type(&mut self, bc: &mut BoolCoder, ctx: usize) -> DecoderResult<VPMBType> {
694 let probs = &self.models.mbtype_models[ctx][map_mb_type(self.last_mbt)].probs;
695 if !bc.read_prob(probs[9]) {
696 self.last_mbt = vp_tree!(
698 vp_tree!(bc, probs[1],
699 vp_tree!(bc, probs[3], VPMBType::InterNoMV, VPMBType::InterMV),
700 vp_tree!(bc, probs[4], VPMBType::InterNearest, VPMBType::InterNear)
702 vp_tree!(bc, probs[2],
703 vp_tree!(bc, probs[5], VPMBType::Intra, VPMBType::InterFourMV),
704 vp_tree!(bc, probs[6],
705 vp_tree!(bc, probs[7], VPMBType::GoldenNoMV, VPMBType::GoldenMV),
706 vp_tree!(bc, probs[8], VPMBType::InterNearest, VPMBType::InterNear)
713 fn decode_mb(&mut self, frm: &mut NASimpleVideoFrame<u8>, bc: &mut BoolCoder, cr: &mut CoeffReader, br: &mut dyn VP56Parser, hdr: &VP56Header, alpha: bool) -> DecoderResult<()> {
714 const FOURMV_SUB_TYPE: [VPMBType; 4] = [ VPMBType::InterNoMV, VPMBType::InterMV, VPMBType::InterNearest, VPMBType::InterNear ];
716 let mb_x = self.fstate.mb_x;
717 let mb_y = self.fstate.mb_y;
718 self.coeffs = [[0; 64]; 6];
719 let mb_pos = mb_x + mb_y * self.mb_w;
720 let mut four_mv = [ZERO_MV; 4];
721 let mut four_mbt = [VPMBType::Intra; 4];
724 let iprob = self.ilace_prob;
725 let prob = if mb_x == 0 {
727 } else if !self.ilace_mb {
728 iprob + (((256 - (iprob as u16)) >> 1) as u8)
732 self.ilace_mb = bc.read_prob(prob);
735 let (num_mv, nearest_mv, near_mv, pred_mv) = if hdr.is_intra {
736 (0, ZERO_MV, ZERO_MV, ZERO_MV)
737 } else { self.find_mv_pred(VP_REF_INTER) };
738 let mb_type = if hdr.is_intra {
741 self.decode_mb_type(bc, (num_mv + 1) % 3)?
743 self.mb_info[mb_pos].mb_type = mb_type;
744 if mb_type.get_ref_id() != VP_REF_GOLDEN {
747 VPMBType::InterNoMV => {
748 self.mb_info[mb_pos].mv = ZERO_MV;
750 VPMBType::InterMV => {
751 let diff_mv = self.decode_mv(bc, br);
752 self.mb_info[mb_pos].mv = pred_mv + diff_mv;
754 VPMBType::InterNearest => {
755 self.mb_info[mb_pos].mv = nearest_mv;
757 VPMBType::InterNear => {
758 self.mb_info[mb_pos].mv = near_mv;
760 VPMBType::InterFourMV => {
762 four_mbt[i] = FOURMV_SUB_TYPE[bc.read_bits(2) as usize];
766 VPMBType::InterNoMV => {},
767 VPMBType::InterMV => {
768 let diff_mv = self.decode_mv(bc, br);
769 four_mv[i] = pred_mv + diff_mv;
771 VPMBType::InterNearest => {
772 four_mv[i] = nearest_mv;
774 VPMBType::InterNear => {
775 four_mv[i] = near_mv;
780 self.mb_info[mb_pos].mv = four_mv[3];
785 let (_num_mv, nearest_mv, near_mv, pred_mv) = self.find_mv_pred(VP_REF_GOLDEN);
787 VPMBType::GoldenNoMV => {
788 self.mb_info[mb_pos].mv = ZERO_MV;
790 VPMBType::GoldenMV => {
791 let diff_mv = self.decode_mv(bc, br);
792 self.mb_info[mb_pos].mv = pred_mv + diff_mv;
794 VPMBType::GoldenNearest => {
795 self.mb_info[mb_pos].mv = nearest_mv;
797 VPMBType::GoldenNear => {
798 self.mb_info[mb_pos].mv = near_mv;
803 if !mb_type.is_intra() && (mb_type != VPMBType::InterFourMV) {
804 self.do_mc(br, frm, mb_type, self.mb_info[mb_pos].mv, alpha);
805 } else if mb_type == VPMBType::InterFourMV {
806 self.do_fourmv(br, frm, &four_mv, alpha);
810 self.fstate.plane = if !alpha { 0 } else { 3 };
811 self.fstate.ctx_idx = blk_no >> 1;
812 self.fstate.top_ctx = self.top_ctx[self.fstate.plane][mb_x * 2 + (blk_no & 1)];
814 CoeffReader::None => {
815 br.decode_block(bc, &mut self.coeffs[blk_no], &self.models.coeff_models[0], &self.models.vp6models, &mut self.fstate)?;
817 CoeffReader::Bool(ref mut bcc) => {
818 br.decode_block(bcc, &mut self.coeffs[blk_no], &self.models.coeff_models[0], &self.models.vp6models, &mut self.fstate)?;
820 CoeffReader::Huff(ref mut brc) => {
821 br.decode_block_huff(brc, &mut self.coeffs[blk_no], &self.models.vp6models, &self.models.vp6huff, &mut self.fstate)?;
824 self.top_ctx[self.fstate.plane][mb_x * 2 + (blk_no & 1)] = self.fstate.top_ctx;
825 self.predict_dc(mb_type, mb_pos, blk_no, alpha);
827 let bx = mb_x * 2 + (blk_no & 1);
828 let by = mb_y * 2 + (blk_no >> 1);
829 let has_ac = self.fstate.last_idx[self.fstate.ctx_idx] > 0;
830 if mb_type.is_intra() {
833 vp_put_block(&mut self.coeffs[blk_no], bx, by, self.fstate.plane, frm);
835 vp_put_block_dc(&mut self.coeffs[blk_no], bx, by, self.fstate.plane, frm);
838 vp_put_block_ilace(&mut self.coeffs[blk_no], bx, by, self.fstate.plane, frm);
843 vp_add_block(&mut self.coeffs[blk_no], bx, by, self.fstate.plane, frm);
845 vp_add_block_dc(&mut self.coeffs[blk_no], bx, by, self.fstate.plane, frm);
848 vp_add_block_ilace(&mut self.coeffs[blk_no], bx, by, self.fstate.plane, frm);
854 self.fstate.plane = blk_no - 3;
855 self.fstate.ctx_idx = blk_no - 2;
856 self.fstate.top_ctx = self.top_ctx[self.fstate.plane][mb_x];
858 CoeffReader::None => {
859 br.decode_block(bc, &mut self.coeffs[blk_no], &self.models.coeff_models[1], &self.models.vp6models, &mut self.fstate)?;
861 CoeffReader::Bool(ref mut bcc) => {
862 br.decode_block(bcc, &mut self.coeffs[blk_no], &self.models.coeff_models[1], &self.models.vp6models, &mut self.fstate)?;
864 CoeffReader::Huff(ref mut brc) => {
865 br.decode_block_huff(brc, &mut self.coeffs[blk_no], &self.models.vp6models, &self.models.vp6huff, &mut self.fstate)?;
868 self.top_ctx[self.fstate.plane][mb_x] = self.fstate.top_ctx;
869 self.predict_dc(mb_type, mb_pos, blk_no, alpha);
871 let has_ac = self.fstate.last_idx[self.fstate.ctx_idx] > 0;
872 if mb_type.is_intra() {
874 vp_put_block(&mut self.coeffs[blk_no], mb_x, mb_y, self.fstate.plane, frm);
876 vp_put_block_dc(&mut self.coeffs[blk_no], mb_x, mb_y, self.fstate.plane, frm);
880 vp_add_block(&mut self.coeffs[blk_no], mb_x, mb_y, self.fstate.plane, frm);
882 vp_add_block_dc(&mut self.coeffs[blk_no], mb_x, mb_y, self.fstate.plane, frm);
889 fn do_mc(&mut self, br: &dyn VP56Parser, frm: &mut NASimpleVideoFrame<u8>, mb_type: VPMBType, mv: MV, alpha: bool) {
890 let x = self.fstate.mb_x * 16;
891 let y = self.fstate.mb_y * 16;
892 let plane = if !alpha { 0 } else { 3 };
893 let src = if mb_type.get_ref_id() == VP_REF_INTER {
894 self.shuf.get_last().unwrap()
896 self.shuf.get_golden().unwrap()
899 br.mc_block(frm, self.mc_buf.clone(), src.clone(), plane, x + 0, y + 0, mv, self.loop_thr);
900 br.mc_block(frm, self.mc_buf.clone(), src.clone(), plane, x + 8, y + 0, mv, self.loop_thr);
901 br.mc_block(frm, self.mc_buf.clone(), src.clone(), plane, x + 0, y + 8, mv, self.loop_thr);
902 br.mc_block(frm, self.mc_buf.clone(), src.clone(), plane, x + 8, y + 8, mv, self.loop_thr);
904 let x = self.fstate.mb_x * 8;
905 let y = self.fstate.mb_y * 8;
906 br.mc_block(frm, self.mc_buf.clone(), src.clone(), 1, x, y, mv, self.loop_thr);
907 br.mc_block(frm, self.mc_buf.clone(), src.clone(), 2, x, y, mv, self.loop_thr);
910 fn do_fourmv(&mut self, br: &dyn VP56Parser, frm: &mut NASimpleVideoFrame<u8>, mvs: &[MV; 4], alpha: bool) {
911 let x = self.fstate.mb_x * 16;
912 let y = self.fstate.mb_y * 16;
913 let plane = if !alpha { 0 } else { 3 };
914 let src = self.shuf.get_last().unwrap();
916 br.mc_block(frm, self.mc_buf.clone(), src.clone(),
917 plane, x + (blk_no & 1) * 8, y + (blk_no & 2) * 4,
918 mvs[blk_no], self.loop_thr);
921 let x = self.fstate.mb_x * 8;
922 let y = self.fstate.mb_y * 8;
923 let sum = mvs[0] + mvs[1] + mvs[2] + mvs[3];
924 let mv = MV { x: sum.x / 4, y: sum.y / 4 };
925 br.mc_block(frm, self.mc_buf.clone(), src.clone(), 1, x, y, mv, self.loop_thr);
926 br.mc_block(frm, self.mc_buf.clone(), src.clone(), 2, x, y, mv, self.loop_thr);
929 fn predict_dc(&mut self, mb_type: VPMBType, mb_pos: usize, blk_no: usize, alpha: bool) {
930 let mb_x = self.fstate.mb_x;
931 let is_luma = blk_no < 4;
932 let (plane, dcs) = if alpha { (0, &mut self.dc_a) } else {
934 4 => (1, &mut self.dc_u),
935 5 => (2, &mut self.dc_v),
936 _ => (0, &mut self.dc_y),
939 let dc_pos = if is_luma {
940 dcs.xpos + mb_x * 2 + (blk_no & 1) + (blk_no >> 1) * dcs.stride
944 let ref_id = mb_type.get_ref_id();
945 let has_left_blk = is_luma && ((blk_no & 1) != 0);
946 let has_top_blk = is_luma && ((blk_no & 2) != 0);
949 if has_left_blk || ((mb_x > 0) && (self.mb_info[mb_pos - 1].mb_type.get_ref_id() == ref_id)) {
950 dc_pred += dcs.data[dc_pos - 1];
953 if has_top_blk || ((mb_pos >= self.mb_w) && (self.mb_info[mb_pos - self.mb_w].mb_type.get_ref_id() == ref_id)) {
954 dc_pred += dcs.data[dc_pos - dcs.stride];
957 if self.version == 5 {
958 if (count < 2) && has_left_blk {
962 if (count < 2) && !has_left_blk && has_top_blk && (mb_x > 0) && (self.mb_info[mb_pos - 1].mb_type.get_ref_id() == ref_id) {
966 if (count < 2) && mb_pos == 0 && !is_luma {
969 if (count < 2) && !has_left_blk && !has_top_blk && is_luma && (mb_x > 0) && (self.mb_info[mb_pos - 1].mb_type.get_ref_id() == ref_id) {
970 dc_pred += dcs.data[dc_pos + dcs.stride - 1];
973 if (count < 2) && blk_no == 2 {
974 dc_pred += dcs.data[dc_pos - dcs.stride + 1];
977 if (count < 2) && !has_left_blk && (mb_pos >= self.mb_w) && (self.mb_info[mb_pos - self.mb_w].mb_type.get_ref_id() == ref_id) {
978 dc_pred += dcs.data[dc_pos - dcs.stride + 1];
981 if (count < 2) && has_left_blk && (mb_pos > self.mb_w) && (mb_x < self.mb_w - 1) && (self.mb_info[mb_pos - self.mb_w + 1].mb_type.get_ref_id() == ref_id) {
982 dc_pred += dcs.data[dc_pos - dcs.stride + 1];
987 dc_pred = self.last_dc[ref_id as usize][plane];
988 } else if count == 2 {
991 self.coeffs[blk_no][0] += dc_pred;
992 self.last_dc[ref_id as usize][plane] = self.coeffs[blk_no][0];
993 dcs.data[dc_pos] = self.coeffs[blk_no][0];
994 self.coeffs[blk_no][0] = self.coeffs[blk_no][0].wrapping_mul(self.fstate.dc_quant);
998 const VP56_DC_QUANTS: [i16; 64] = [
999 47, 47, 47, 47, 45, 43, 43, 43,
1000 43, 43, 42, 41, 41, 40, 40, 40,
1001 40, 35, 35, 35, 35, 33, 33, 33,
1002 33, 32, 32, 32, 27, 27, 26, 26,
1003 25, 25, 24, 24, 23, 23, 19, 19,
1004 19, 19, 18, 18, 17, 16, 16, 16,
1005 16, 16, 15, 11, 11, 11, 10, 10,
1006 9, 8, 7, 5, 3, 3, 2, 2
1008 const VP56_AC_QUANTS: [i16; 64] = [
1009 94, 92, 90, 88, 86, 82, 78, 74,
1010 70, 66, 62, 58, 54, 53, 52, 51,
1011 50, 49, 48, 47, 46, 45, 44, 43,
1012 42, 40, 39, 37, 36, 35, 34, 33,
1013 32, 31, 30, 29, 28, 27, 26, 25,
1014 24, 23, 22, 21, 20, 19, 18, 17,
1015 16, 15, 14, 13, 12, 11, 10, 9,
1016 8, 7, 6, 5, 4, 3, 2, 1
1019 const VP56_FILTER_LIMITS: [u8; 64] = [
1020 14, 14, 13, 13, 12, 12, 10, 10,
1021 10, 10, 8, 8, 8, 8, 8, 8,
1022 8, 8, 8, 8, 8, 8, 8, 8,
1023 8, 8, 8, 8, 8, 8, 8, 8,
1024 8, 8, 8, 8, 7, 7, 7, 7,
1025 7, 7, 6, 6, 6, 6, 6, 6,
1026 5, 5, 5, 5, 4, 4, 4, 4,
1027 4, 4, 4, 3, 3, 3, 3, 2
1030 const VP56_MODE_VQ: [[[u8; 20]; 16]; 3] = [
1032 [ 9, 15, 32, 25, 7, 19, 9, 21, 1, 12, 14, 12, 3, 18, 14, 23, 3, 10, 0, 4 ],
1033 [ 48, 39, 1, 2, 11, 27, 29, 44, 7, 27, 1, 4, 0, 3, 1, 6, 1, 2, 0, 0 ],
1034 [ 21, 32, 1, 2, 4, 10, 32, 43, 6, 23, 2, 3, 1, 19, 1, 6, 12, 21, 0, 7 ],
1035 [ 69, 83, 0, 0, 0, 2, 10, 29, 3, 12, 0, 1, 0, 3, 0, 3, 2, 2, 0, 0 ],
1036 [ 11, 20, 1, 4, 18, 36, 43, 48, 13, 35, 0, 2, 0, 5, 3, 12, 1, 2, 0, 0 ],
1037 [ 70, 44, 0, 1, 2, 10, 37, 46, 8, 26, 0, 2, 0, 2, 0, 2, 0, 1, 0, 0 ],
1038 [ 8, 15, 0, 1, 8, 21, 74, 53, 22, 42, 0, 1, 0, 2, 0, 3, 1, 2, 0, 0 ],
1039 [ 141, 42, 0, 0, 1, 4, 11, 24, 1, 11, 0, 1, 0, 1, 0, 2, 0, 0, 0, 0 ],
1040 [ 8, 19, 4, 10, 24, 45, 21, 37, 9, 29, 0, 3, 1, 7, 11, 25, 0, 2, 0, 1 ],
1041 [ 46, 42, 0, 1, 2, 10, 54, 51, 10, 30, 0, 2, 0, 2, 0, 1, 0, 1, 0, 0 ],
1042 [ 28, 32, 0, 0, 3, 10, 75, 51, 14, 33, 0, 1, 0, 2, 0, 1, 1, 2, 0, 0 ],
1043 [ 100, 46, 0, 1, 3, 9, 21, 37, 5, 20, 0, 1, 0, 2, 1, 2, 0, 1, 0, 0 ],
1044 [ 27, 29, 0, 1, 9, 25, 53, 51, 12, 34, 0, 1, 0, 3, 1, 5, 0, 2, 0, 0 ],
1045 [ 80, 38, 0, 0, 1, 4, 69, 33, 5, 16, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0 ],
1046 [ 16, 20, 0, 0, 2, 8, 104, 49, 15, 33, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0 ],
1047 [ 194, 16, 0, 0, 1, 1, 1, 9, 1, 3, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0 ],
1049 [ 41, 22, 1, 0, 1, 31, 0, 0, 0, 0, 0, 1, 1, 7, 0, 1, 98, 25, 4, 10 ],
1050 [ 123, 37, 6, 4, 1, 27, 0, 0, 0, 0, 5, 8, 1, 7, 0, 1, 12, 10, 0, 2 ],
1051 [ 26, 14, 14, 12, 0, 24, 0, 0, 0, 0, 55, 17, 1, 9, 0, 36, 5, 7, 1, 3 ],
1052 [ 209, 5, 0, 0, 0, 27, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0 ],
1053 [ 2, 5, 4, 5, 0, 121, 0, 0, 0, 0, 0, 3, 2, 4, 1, 4, 2, 2, 0, 1 ],
1054 [ 175, 5, 0, 1, 0, 48, 0, 0, 0, 0, 0, 2, 0, 1, 0, 2, 0, 1, 0, 0 ],
1055 [ 83, 5, 2, 3, 0, 102, 0, 0, 0, 0, 1, 3, 0, 2, 0, 1, 0, 0, 0, 0 ],
1056 [ 233, 6, 0, 0, 0, 8, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0 ],
1057 [ 34, 16, 112, 21, 1, 28, 0, 0, 0, 0, 6, 8, 1, 7, 0, 3, 2, 5, 0, 2 ],
1058 [ 159, 35, 2, 2, 0, 25, 0, 0, 0, 0, 3, 6, 0, 5, 0, 1, 4, 4, 0, 1 ],
1059 [ 75, 39, 5, 7, 2, 48, 0, 0, 0, 0, 3, 11, 2, 16, 1, 4, 7, 10, 0, 2 ],
1060 [ 212, 21, 0, 1, 0, 9, 0, 0, 0, 0, 1, 2, 0, 2, 0, 0, 2, 2, 0, 0 ],
1061 [ 4, 2, 0, 0, 0, 172, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 2, 0, 0, 0 ],
1062 [ 187, 22, 1, 1, 0, 17, 0, 0, 0, 0, 3, 6, 0, 4, 0, 1, 4, 4, 0, 1 ],
1063 [ 133, 6, 1, 2, 1, 70, 0, 0, 0, 0, 0, 2, 0, 4, 0, 3, 1, 1, 0, 0 ],
1064 [ 251, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
1066 [ 2, 3, 2, 3, 0, 2, 0, 2, 0, 0, 11, 4, 1, 4, 0, 2, 3, 2, 0, 4 ],
1067 [ 49, 46, 3, 4, 7, 31, 42, 41, 0, 0, 2, 6, 1, 7, 1, 4, 2, 4, 0, 1 ],
1068 [ 26, 25, 1, 1, 2, 10, 67, 39, 0, 0, 1, 1, 0, 14, 0, 2, 31, 26, 1, 6 ],
1069 [ 103, 46, 1, 2, 2, 10, 33, 42, 0, 0, 1, 4, 0, 3, 0, 1, 1, 3, 0, 0 ],
1070 [ 14, 31, 9, 13, 14, 54, 22, 29, 0, 0, 2, 6, 4, 18, 6, 13, 1, 5, 0, 1 ],
1071 [ 85, 39, 0, 0, 1, 9, 69, 40, 0, 0, 0, 1, 0, 3, 0, 1, 2, 3, 0, 0 ],
1072 [ 31, 28, 0, 0, 3, 14, 130, 34, 0, 0, 0, 1, 0, 3, 0, 1, 3, 3, 0, 1 ],
1073 [ 171, 25, 0, 0, 1, 5, 25, 21, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0 ],
1074 [ 17, 21, 68, 29, 6, 15, 13, 22, 0, 0, 6, 12, 3, 14, 4, 10, 1, 7, 0, 3 ],
1075 [ 51, 39, 0, 1, 2, 12, 91, 44, 0, 0, 0, 2, 0, 3, 0, 1, 2, 3, 0, 1 ],
1076 [ 81, 25, 0, 0, 2, 9, 106, 26, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0 ],
1077 [ 140, 37, 0, 1, 1, 8, 24, 33, 0, 0, 1, 2, 0, 2, 0, 1, 1, 2, 0, 0 ],
1078 [ 14, 23, 1, 3, 11, 53, 90, 31, 0, 0, 0, 3, 1, 5, 2, 6, 1, 2, 0, 0 ],
1079 [ 123, 29, 0, 0, 1, 7, 57, 30, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0 ],
1080 [ 13, 14, 0, 0, 4, 20, 175, 20, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0 ],
1081 [ 202, 23, 0, 0, 1, 3, 2, 9, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0 ],