1 use nihav_core::codecs::*;
2 use nihav_core::io::bitreader::*;
3 use super::vpcommon::*;
5 pub const TOKEN_LARGE: u8 = 5;
6 pub const TOKEN_EOB: u8 = 42;
8 #[derive(Clone,Copy,Debug,Default)]
10 pub struct VP56Header {
14 pub multistream: bool,
15 pub use_huffman: bool,
27 #[derive(Clone,Copy,Default)]
28 pub struct VP56MVModel {
31 pub raw_probs: [u8; 8],
32 pub tree_probs: [u8; 7],
35 #[derive(Clone,Copy,Default)]
36 pub struct VP56MBTypeModel {
40 #[derive(Clone,Copy,Default)]
41 pub struct VP56CoeffModel {
42 pub dc_token_probs: [[[u8; 5]; 6]; 6],
43 pub dc_value_probs: [u8; 11],
44 pub ac_ctype_probs: [[[[u8; 5]; 5]; 6]; 3],
45 pub ac_type_probs: [[[[u8; 5]; 6]; 3]; 3],
46 pub ac_val_probs: [[[u8; 11]; 6]; 3],
49 pub struct VP6Models {
50 pub scan_order: [usize; 64],
51 pub scan: [usize; 64],
52 pub zigzag: [usize; 64],
53 pub zero_run_probs: [[u8; 14]; 2],
56 const MAX_HUFF_ELEMS: usize = 12;
57 #[derive(Clone,Copy,Default)]
59 pub codes: [u16; MAX_HUFF_ELEMS],
60 pub bits: [u8; MAX_HUFF_ELEMS],
63 #[derive(Clone,Copy,Default)]
71 fn prob2weight(a: u8, b: u8) -> u8 {
72 let w = (((a as u16) * (b as u16)) >> 8) as u8;
81 fn build_codes(&mut self, probs: &[u8; 11]) {
82 let mut weights = [0u8; 12];
84 weights[11] = prob2weight( probs[0], probs[ 1]);
85 weights[ 0] = prob2weight( probs[0], !probs[ 1]);
86 weights[ 1] = prob2weight(!probs[0], probs[ 2]);
87 let lvroot = prob2weight(!probs[0], !probs[ 2]);
88 let tworoot = prob2weight( lvroot, probs[ 3]);
89 let hlroot = prob2weight( lvroot, !probs[ 3]);
90 weights[ 2] = prob2weight( tworoot, probs[ 4]);
91 let root34 = prob2weight( tworoot, !probs[ 4]);
92 weights[ 3] = prob2weight( root34, probs[ 5]);
93 weights[ 4] = prob2weight( root34, !probs[ 5]);
94 let c1root = prob2weight( hlroot, probs[ 6]);
95 let c34root = prob2weight( hlroot, !probs[ 6]);
96 weights[ 5] = prob2weight( c1root, probs[ 7]);
97 weights[ 6] = prob2weight( c1root, !probs[ 7]);
98 let c3root = prob2weight( c34root, probs[ 8]);
99 let c4root = prob2weight( c34root, !probs[ 8]);
100 weights[ 7] = prob2weight( c3root, probs[ 9]);
101 weights[ 8] = prob2weight( c3root, !probs[ 9]);
102 weights[ 9] = prob2weight( c4root, probs[10]);
103 weights[10] = prob2weight( c4root, !probs[10]);
105 self.build(&weights);
107 fn build_codes_zero_run(&mut self, probs: &[u8; 14]) {
108 let mut weights = [0u8; 9];
110 let root = prob2weight( probs[0], probs[1]);
111 weights[0] = prob2weight( root, probs[2]);
112 weights[1] = prob2weight( root, !probs[2]);
114 let root = prob2weight( probs[0], !probs[1]);
115 weights[2] = prob2weight( root, probs[3]);
116 weights[3] = prob2weight( root, !probs[3]);
118 let root = prob2weight(!probs[0], probs[4]);
119 weights[8] = prob2weight(!probs[0], !probs[4]);
120 let root1 = prob2weight( root, probs[5]);
121 let root2 = prob2weight( root, !probs[5]);
122 weights[4] = prob2weight( root1, probs[6]);
123 weights[5] = prob2weight( root1, !probs[6]);
124 weights[6] = prob2weight( root2, probs[7]);
125 weights[7] = prob2weight( root2, !probs[7]);
127 self.build(&weights);
129 fn build(&mut self, weights: &[u8]) {
130 let mut nodes = [Node::default(); MAX_HUFF_ELEMS * 2];
133 for w in weights.iter().rev() {
134 let weight = *w as u16;
137 if nodes[i].weight > weight {
142 for j in (pos..nlen).rev() {
143 nodes[j + 1] = nodes[j];
145 nodes[pos].weight = weight;
146 nodes[pos].sym = (weights.len() - nlen - 1) as i8;
153 weight: nodes[low + 0].weight + nodes[low + 1].weight,
160 while (pos < nlen) && (nodes[pos].weight < nnode.weight) {
163 for j in (pos..nlen).rev() {
164 nodes[j + 1] = nodes[j];
169 self.get_codes(&nodes, nlen - 1, 0, 0);
170 for i in nlen..self.codes.len() {
171 self.codes[i] = self.codes[0];
172 self.bits[i] = self.bits[0];
175 fn get_codes(&mut self, nodes: &[Node], pos: usize, code: u16, len: u8) {
176 if nodes[pos].sym >= 0 {
177 self.codes[nodes[pos].sym as usize] = code;
178 self.bits [nodes[pos].sym as usize] = len;
180 self.get_codes(nodes, nodes[pos].ch0, (code << 1) | 0, len + 1);
181 self.get_codes(nodes, nodes[pos].ch1, (code << 1) | 1, len + 1);
187 fn read_huff(&mut self, huff: &VP6Huff) -> DecoderResult<u8>;
190 impl<'a> ReadHuff for BitReader<'a> {
191 fn read_huff(&mut self, huff: &VP6Huff) -> DecoderResult<u8> {
192 let peekval = self.peek(16);
193 for (i, (code, bit)) in huff.codes.iter().zip(huff.bits.iter()).enumerate() {
194 if (peekval >> (16 - *bit)) == (*code as u32) {
195 self.skip(*bit as u32)?;
199 Err(DecoderError::InvalidData)
203 #[derive(Clone,Copy,Default)]
204 pub struct VP6HuffModels {
205 pub dc_token_tree: [VP6Huff; 2],
206 pub ac_token_tree: [[[VP6Huff; 6]; 3]; 2],
207 pub zero_run_tree: [VP6Huff; 2],
216 zero_run_probs: [[0; 14]; 2],
221 pub struct VP56Models {
222 pub mv_models: [VP56MVModel; 2],
223 pub mbtype_models: [[VP56MBTypeModel; 10]; 3],
224 pub coeff_models: [VP56CoeffModel; 2],
225 pub prob_xmitted: [[u8; 20]; 3],
226 pub vp6models: VP6Models,
227 pub vp6huff: VP6HuffModels,
233 mv_models: [VP56MVModel::default(); 2],
234 mbtype_models: [[VP56MBTypeModel::default(); 10]; 3],
235 coeff_models: [VP56CoeffModel::default(); 2],
236 prob_xmitted: [[0; 20]; 3],
237 vp6models: VP6Models::new(),
238 vp6huff: VP6HuffModels::default(),
243 pub trait VP56Parser {
244 fn parse_header(&mut self, bc: &mut BoolCoder) -> DecoderResult<VP56Header>;
245 fn reset_models(&self, models: &mut VP56Models);
246 fn decode_mv(&self, bc: &mut BoolCoder, model: &VP56MVModel) -> i16;
247 fn decode_mv_models(&self, bc: &mut BoolCoder, models: &mut [VP56MVModel; 2]) -> DecoderResult<()>;
248 fn decode_coeff_models(&self, bc: &mut BoolCoder, models: &mut VP56Models, is_intra: bool) -> DecoderResult<()>;
249 fn decode_block(&self, bc: &mut BoolCoder, coeffs: &mut [i16; 64], model: &VP56CoeffModel, vp6model: &VP6Models, fstate: &mut FrameState) -> DecoderResult<()>;
250 fn decode_block_huff(&self, br: &mut BitReader, coeffs: &mut [i16; 64], vp6model: &VP6Models, model: &VP6HuffModels, fstate: &mut FrameState) -> DecoderResult<()>;
251 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);
254 enum CoeffReader<'a> {
260 #[derive(Clone,Copy,Default)]
266 pub struct FrameState {
270 pub coeff_cat: [[u8; 64]; 4],
271 pub last_idx: [usize; 4],
276 pub dc_zero_run: [usize; 2],
277 pub ac_zero_run: [usize; 2],
286 coeff_cat: [[0; 64]; 4],
299 pub struct VP56DCPred {
313 const INVALID_REF: u8 = 42;
316 fn new() -> Self { Self::default() }
317 fn resize(&mut self, mb_w: usize) {
318 self.dc_y.resize(mb_w * 2 + 2, 0);
319 self.dc_u.resize(mb_w + 2, 0);
320 self.dc_v.resize(mb_w + 2, 0);
321 self.ref_y.resize(mb_w * 2 + 2, INVALID_REF);
322 self.ref_c.resize(mb_w + 2, INVALID_REF);
325 fn reset(&mut self) {
327 for el in self.ref_y.iter_mut().skip(1) { *el = INVALID_REF; }
328 for el in self.ref_c.iter_mut().skip(1) { *el = INVALID_REF; }
330 fn update_row(&mut self) {
336 self.ref_left = INVALID_REF;
338 fn next_mb(&mut self) {
344 pub struct VP56Decoder {
354 coeffs: [[i16; 64]; 6],
361 mb_info: Vec<MBInfo>,
364 last_dc: [[i16; 4]; 3],
365 top_ctx: [Vec<u8>; 4],
367 mc_buf: NAVideoBufferRef<u8>,
370 fn rescale_mb_mode_prob(prob: u32, total: u32) -> u8 {
371 (255 * prob / (1 + total)) as u8
374 fn map_mb_type(mbtype: VPMBType) -> usize {
376 VPMBType::InterNoMV => 0,
377 VPMBType::Intra => 1,
378 VPMBType::InterMV => 2,
379 VPMBType::InterNearest => 3,
380 VPMBType::InterNear => 4,
381 VPMBType::GoldenNoMV => 5,
382 VPMBType::GoldenMV => 6,
383 VPMBType::InterFourMV => 7,
384 VPMBType::GoldenNearest => 8,
385 VPMBType::GoldenNear => 9,
389 pub fn expand_token_bc(bc: &mut BoolCoder, val_probs: &[u8; 11], token: u8, version: u8) -> i16 {
390 let mut sign = false;
392 if token < TOKEN_LARGE {
394 sign = bc.read_bool();
396 level = token as i16;
398 let cat: usize = vp_tree!(bc, val_probs[6],
399 vp_tree!(bc, val_probs[7], 0, 1),
400 vp_tree!(bc, val_probs[8],
401 vp_tree!(bc, val_probs[9], 2, 3),
402 vp_tree!(bc, val_probs[10], 4, 5)));
404 sign = bc.read_bool();
407 let add_probs = &VP56_COEF_ADD_PROBS[cat];
408 for prob in add_probs.iter() {
409 if *prob == 128 { break; }
410 add = (add << 1) | (bc.read_prob(*prob) as i16);
413 sign = bc.read_bool();
415 level = VP56_COEF_BASE[cat] + add;
425 pub fn new(version: u8, has_alpha: bool, flip: bool) -> Self {
426 let vt = alloc_video_buffer(NAVideoInfo::new(24, 24, false, VP_YUVA420_FORMAT), 4).unwrap();
427 let mc_buf = vt.get_vbuf().unwrap();
429 version, has_alpha, flip,
430 shuf: VPShuffler::new(),
435 models: VP56Models::new(),
436 coeffs: [[0; 64]; 6],
437 last_mbt: VPMBType::InterNoMV,
444 fstate: FrameState::new(),
445 dc_pred: VP56DCPred::new(),
446 last_dc: [[0; 4]; 3],
447 top_ctx: [Vec::new(), Vec::new(), Vec::new(), Vec::new()],
452 fn set_dimensions(&mut self, width: usize, height: usize) {
454 self.height = height;
455 self.mb_w = (self.width + 15) >> 4;
456 self.mb_h = (self.height + 15) >> 4;
457 self.mb_info.resize(self.mb_w * self.mb_h, MBInfo::default());
458 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]];
460 pub fn init(&mut self, supp: &mut NADecoderSupport, vinfo: NAVideoInfo) -> DecoderResult<()> {
461 supp.pool_u8.set_dec_bufs(3);
462 supp.pool_u8.prealloc_video(NAVideoInfo::new(vinfo.get_width(), vinfo.get_height(), false, vinfo.get_format()), 4)?;
463 self.set_dimensions(vinfo.get_width(), vinfo.get_height());
464 self.dc_pred.resize(self.mb_w);
467 pub fn flush(&mut self) {
470 pub fn decode_frame(&mut self, supp: &mut NADecoderSupport, src: &[u8], br: &mut dyn VP56Parser) -> DecoderResult<(NABufferType, FrameType)> {
474 validate!(src.len() >= 7);
475 aoffset = ((src[0] as usize) << 16) | ((src[1] as usize) << 8) | (src[2] as usize);
476 validate!((aoffset > 0) && (aoffset < src.len() - 3));
477 bc = BoolCoder::new(&src[3..])?;
479 validate!(src.len() >= 4);
481 bc = BoolCoder::new(src)?;
483 let hdr = br.parse_header(&mut bc)?;
484 validate!((hdr.offset as usize) < aoffset); //XXX: take alpha 3 byte offset into account?
487 self.set_dimensions((hdr.mb_w as usize) * 16, (hdr.mb_h as usize) * 16);
489 let fmt = if !self.has_alpha {
494 let vinfo = NAVideoInfo::new(self.width, self.height, self.flip, fmt);
495 let ret = supp.pool_u8.get_free();
497 return Err(DecoderError::AllocError);
499 let mut buf = ret.unwrap();
500 if buf.get_info() != vinfo {
502 supp.pool_u8.reset();
503 supp.pool_u8.prealloc_video(vinfo, 4)?;
504 let ret = supp.pool_u8.get_free();
506 return Err(DecoderError::AllocError);
510 let mut dframe = NASimpleVideoFrame::from_video_buf(&mut buf).unwrap();
515 if !self.shuf.has_refs() {
516 return Err(DecoderError::MissingReference);
522 let off = (if self.has_alpha { 3 } else { 0 }) + (hdr.offset as usize);
523 if !hdr.use_huffman {
524 let bc2 = BoolCoder::new(&src[off..])?;
525 cr = CoeffReader::Bool(bc2);
527 let br = BitReader::new(&src[off..aoffset], BitReaderMode::BE);
528 cr = CoeffReader::Huff(br);
531 cr = CoeffReader::None;
535 br.reset_models(&mut self.models);
536 self.reset_mbtype_models();
538 self.decode_mode_prob_models(&mut bc)?;
539 br.decode_mv_models(&mut bc, &mut self.models.mv_models)?;
541 br.decode_coeff_models(&mut bc, &mut self.models, hdr.is_intra)?;
544 self.models.vp6huff.dc_token_tree[i].build_codes(&self.models.coeff_models[i].dc_value_probs);
549 self.models.vp6huff.ac_token_tree[i][mode][band].build_codes(&self.models.coeff_models[i].ac_val_probs[mode][band]);
554 self.models.vp6huff.zero_run_tree[i].build_codes_zero_run(&self.models.vp6models.zero_run_probs[i]);
559 self.ilace_prob = bc.read_bits(8) as u8;
562 self.fstate = FrameState::new();
563 self.fstate.dc_quant = VP56_DC_QUANTS[hdr.quant as usize] * 4;
564 self.fstate.ac_quant = VP56_AC_QUANTS[hdr.quant as usize] * 4;
565 self.loop_thr = VP56_FILTER_LIMITS[hdr.quant as usize] as i16;
567 self.last_mbt = VPMBType::InterNoMV;
568 for vec in self.top_ctx.iter_mut() {
569 for el in vec.iter_mut() {
573 self.last_dc = [[0; 4]; 3];
574 self.last_dc[0][1] = 0x80;
575 self.last_dc[0][2] = 0x80;
576 self.dc_pred.reset();
578 self.ilace_mb = false;
579 for mb_y in 0..self.mb_h {
580 self.fstate.mb_y = mb_y;
581 self.fstate.coeff_cat = [[0; 64]; 4];
582 self.fstate.last_idx = [24; 4];
583 for mb_x in 0..self.mb_w {
584 self.fstate.mb_x = mb_x;
585 self.decode_mb(&mut dframe, &mut bc, &mut cr, br, &hdr, false)?;
586 self.dc_pred.next_mb();
588 self.dc_pred.update_row();
592 let asrc = &src[aoffset + 3..];
593 let mut bc = BoolCoder::new(asrc)?;
594 let ahdr = br.parse_header(&mut bc)?;
595 validate!(ahdr.mb_w == hdr.mb_w && ahdr.mb_h == hdr.mb_h);
599 self.shuf.add_golden_frame(buf.clone());
601 self.shuf.add_frame(buf.clone());
603 Ok((NABufferType::Video(buf), if hdr.is_intra { FrameType::I } else { FrameType::P }))
605 fn reset_mbtype_models(&mut self) {
606 const DEFAULT_XMITTED_PROBS: [[u8; 20]; 3] = [
607 [ 42, 69, 2, 1, 7, 1, 42, 44, 22, 6, 3, 1, 2, 0, 5, 1, 1, 0, 0, 0 ],
608 [ 8, 229, 1, 1, 8, 0, 0, 0, 0, 0, 2, 1, 1, 0, 0, 0, 1, 1, 0, 0 ],
609 [ 35, 122, 1, 1, 6, 1, 34, 46, 0, 0, 2, 1, 1, 0, 1, 0, 1, 1, 0, 0 ]
611 self.models.prob_xmitted.copy_from_slice(&DEFAULT_XMITTED_PROBS);
613 fn decode_mode_prob_models(&mut self, bc: &mut BoolCoder) -> DecoderResult<()> {
615 if bc.read_prob(174) {
616 let idx = bc.read_bits(4) as usize;
618 self.models.prob_xmitted[ctx][i ^ 1] = VP56_MODE_VQ[ctx][idx][i];
621 if bc.read_prob(254) {
623 if bc.read_prob(205) {
624 let sign = bc.read_bool();
625 let diff = vp_tree!(bc, 171,
626 vp_tree!(bc, 83, 2, 1),
630 vp_tree!(bc, 104, 6, 5),
637 validate!(diff < 256);
638 let diff = diff as u8;
640 validate!(self.models.prob_xmitted[ctx][set ^ 1] <= 255 - diff);
641 self.models.prob_xmitted[ctx][set ^ 1] += diff;
643 validate!(self.models.prob_xmitted[ctx][set ^ 1] >= diff);
644 self.models.prob_xmitted[ctx][set ^ 1] -= diff;
651 let prob_xmitted = &self.models.prob_xmitted[ctx];
653 let mdl = &mut self.models.mbtype_models[ctx][mode];
654 let mut cnt = [0u32; 10];
657 if i == mode { continue; }
658 cnt[i] = 100 * (prob_xmitted[i * 2] as u32);
661 let sum = (prob_xmitted[mode * 2] as u32) + (prob_xmitted[mode * 2 + 1] as u32);
662 mdl.probs[9] = 255 - rescale_mb_mode_prob(prob_xmitted[mode * 2 + 1] as u32, sum);
664 let inter_mv0_weight = (cnt[0] as u32) + (cnt[2] as u32);
665 let inter_mv1_weight = (cnt[3] as u32) + (cnt[4] as u32);
666 let gold_mv0_weight = (cnt[5] as u32) + (cnt[6] as u32);
667 let gold_mv1_weight = (cnt[8] as u32) + (cnt[9] as u32);
668 let mix_weight = (cnt[1] as u32) + (cnt[7] as u32);
669 mdl.probs[0] = 1 + rescale_mb_mode_prob(inter_mv0_weight + inter_mv1_weight, total);
670 mdl.probs[1] = 1 + rescale_mb_mode_prob(inter_mv0_weight, inter_mv0_weight + inter_mv1_weight);
671 mdl.probs[2] = 1 + rescale_mb_mode_prob(mix_weight, mix_weight + gold_mv0_weight + gold_mv1_weight);
672 mdl.probs[3] = 1 + rescale_mb_mode_prob(cnt[0] as u32, inter_mv0_weight);
673 mdl.probs[4] = 1 + rescale_mb_mode_prob(cnt[3] as u32, inter_mv1_weight);
674 mdl.probs[5] = 1 + rescale_mb_mode_prob(cnt[1], mix_weight);
675 mdl.probs[6] = 1 + rescale_mb_mode_prob(gold_mv0_weight, gold_mv0_weight + gold_mv1_weight);
676 mdl.probs[7] = 1 + rescale_mb_mode_prob(cnt[5], gold_mv0_weight);
677 mdl.probs[8] = 1 + rescale_mb_mode_prob(cnt[8], gold_mv1_weight);
682 fn find_mv_pred(&self, ref_id: u8) -> (usize, MV, MV, MV) {
683 const CAND_POS: [(i8, i8); 12] = [
692 let mut nearest_mv = ZERO_MV;
693 let mut near_mv = ZERO_MV;
694 let mut pred_mv = ZERO_MV;
695 let mut num_mv: usize = 0;
697 for (i, (yoff, xoff)) in CAND_POS.iter().enumerate() {
698 let cx = (self.fstate.mb_x as isize) + (*xoff as isize);
699 let cy = (self.fstate.mb_y as isize) + (*yoff as isize);
700 if (cx < 0) || (cy < 0) {
703 let cx = cx as usize;
704 let cy = cy as usize;
705 if (cx >= self.mb_w) || (cy >= self.mb_h) {
708 let mb_pos = cx + cy * self.mb_w;
709 let mv = self.mb_info[mb_pos].mv;
710 if (self.mb_info[mb_pos].mb_type.get_ref_id() != ref_id) || (mv == ZERO_MV) {
716 if (self.version > 5) && (i < 2) {
719 } else if mv != nearest_mv {
726 (num_mv, nearest_mv, near_mv, pred_mv)
728 fn decode_mv(&self, bc: &mut BoolCoder, br: &mut dyn VP56Parser) -> MV {
729 let x = br.decode_mv(bc, &self.models.mv_models[0]);
730 let y = br.decode_mv(bc, &self.models.mv_models[1]);
733 fn decode_mb_type(&mut self, bc: &mut BoolCoder, ctx: usize) -> DecoderResult<VPMBType> {
734 let probs = &self.models.mbtype_models[ctx][map_mb_type(self.last_mbt)].probs;
735 if !bc.read_prob(probs[9]) {
736 self.last_mbt = vp_tree!(
738 vp_tree!(bc, probs[1],
739 vp_tree!(bc, probs[3], VPMBType::InterNoMV, VPMBType::InterMV),
740 vp_tree!(bc, probs[4], VPMBType::InterNearest, VPMBType::InterNear)
742 vp_tree!(bc, probs[2],
743 vp_tree!(bc, probs[5], VPMBType::Intra, VPMBType::InterFourMV),
744 vp_tree!(bc, probs[6],
745 vp_tree!(bc, probs[7], VPMBType::GoldenNoMV, VPMBType::GoldenMV),
746 vp_tree!(bc, probs[8], VPMBType::GoldenNearest, VPMBType::GoldenNear)
753 fn decode_mb(&mut self, frm: &mut NASimpleVideoFrame<u8>, bc: &mut BoolCoder, cr: &mut CoeffReader, br: &mut dyn VP56Parser, hdr: &VP56Header, alpha: bool) -> DecoderResult<()> {
754 const FOURMV_SUB_TYPE: [VPMBType; 4] = [ VPMBType::InterNoMV, VPMBType::InterMV, VPMBType::InterNearest, VPMBType::InterNear ];
756 let mb_x = self.fstate.mb_x;
757 let mb_y = self.fstate.mb_y;
758 self.coeffs = [[0; 64]; 6];
759 let mb_pos = mb_x + mb_y * self.mb_w;
760 let mut four_mv = [ZERO_MV; 4];
761 let mut four_mbt = [VPMBType::Intra; 4];
764 let iprob = self.ilace_prob;
765 let prob = if mb_x == 0 {
767 } else if !self.ilace_mb {
768 iprob + (((256 - (iprob as u16)) >> 1) as u8)
772 self.ilace_mb = bc.read_prob(prob);
775 let (num_mv, nearest_mv, near_mv, pred_mv) = if hdr.is_intra {
776 (0, ZERO_MV, ZERO_MV, ZERO_MV)
777 } else { self.find_mv_pred(VP_REF_INTER) };
778 let mb_type = if hdr.is_intra {
781 self.decode_mb_type(bc, (num_mv + 1) % 3)?
783 self.mb_info[mb_pos].mb_type = mb_type;
784 if mb_type.get_ref_id() != VP_REF_GOLDEN {
787 VPMBType::InterNoMV => {
788 self.mb_info[mb_pos].mv = ZERO_MV;
790 VPMBType::InterMV => {
791 let diff_mv = self.decode_mv(bc, br);
792 self.mb_info[mb_pos].mv = pred_mv + diff_mv;
794 VPMBType::InterNearest => {
795 self.mb_info[mb_pos].mv = nearest_mv;
797 VPMBType::InterNear => {
798 self.mb_info[mb_pos].mv = near_mv;
800 VPMBType::InterFourMV => {
802 four_mbt[i] = FOURMV_SUB_TYPE[bc.read_bits(2) as usize];
806 VPMBType::InterNoMV => {},
807 VPMBType::InterMV => {
808 let diff_mv = self.decode_mv(bc, br);
809 four_mv[i] = pred_mv + diff_mv;
811 VPMBType::InterNearest => {
812 four_mv[i] = nearest_mv;
814 VPMBType::InterNear => {
815 four_mv[i] = near_mv;
820 self.mb_info[mb_pos].mv = four_mv[3];
825 let (_num_mv, nearest_mv, near_mv, pred_mv) = self.find_mv_pred(VP_REF_GOLDEN);
827 VPMBType::GoldenNoMV => {
828 self.mb_info[mb_pos].mv = ZERO_MV;
830 VPMBType::GoldenMV => {
831 let diff_mv = self.decode_mv(bc, br);
832 self.mb_info[mb_pos].mv = pred_mv + diff_mv;
834 VPMBType::GoldenNearest => {
835 self.mb_info[mb_pos].mv = nearest_mv;
837 VPMBType::GoldenNear => {
838 self.mb_info[mb_pos].mv = near_mv;
843 if !mb_type.is_intra() && (mb_type != VPMBType::InterFourMV) {
844 self.do_mc(br, frm, mb_type, self.mb_info[mb_pos].mv, alpha);
845 } else if mb_type == VPMBType::InterFourMV {
846 self.do_fourmv(br, frm, &four_mv, alpha);
850 self.fstate.plane = if !alpha { 0 } else { 3 };
851 self.fstate.ctx_idx = blk_no >> 1;
852 self.fstate.top_ctx = self.top_ctx[self.fstate.plane][mb_x * 2 + (blk_no & 1)];
854 CoeffReader::None => {
855 br.decode_block(bc, &mut self.coeffs[blk_no], &self.models.coeff_models[0], &self.models.vp6models, &mut self.fstate)?;
857 CoeffReader::Bool(ref mut bcc) => {
858 br.decode_block(bcc, &mut self.coeffs[blk_no], &self.models.coeff_models[0], &self.models.vp6models, &mut self.fstate)?;
860 CoeffReader::Huff(ref mut brc) => {
861 br.decode_block_huff(brc, &mut self.coeffs[blk_no], &self.models.vp6models, &self.models.vp6huff, &mut self.fstate)?;
864 self.top_ctx[self.fstate.plane][mb_x * 2 + (blk_no & 1)] = self.fstate.top_ctx;
865 self.predict_dc(mb_type, mb_pos, blk_no, alpha);
867 let bx = mb_x * 2 + (blk_no & 1);
868 let by = mb_y * 2 + (blk_no >> 1);
869 let has_ac = self.fstate.last_idx[self.fstate.ctx_idx] > 0;
870 if mb_type.is_intra() {
873 vp_put_block(&mut self.coeffs[blk_no], bx, by, self.fstate.plane, frm);
875 vp_put_block_dc(&mut self.coeffs[blk_no], bx, by, self.fstate.plane, frm);
878 vp_put_block_ilace(&mut self.coeffs[blk_no], bx, by, self.fstate.plane, frm);
883 vp_add_block(&mut self.coeffs[blk_no], bx, by, self.fstate.plane, frm);
885 vp_add_block_dc(&mut self.coeffs[blk_no], bx, by, self.fstate.plane, frm);
888 vp_add_block_ilace(&mut self.coeffs[blk_no], bx, by, self.fstate.plane, frm);
894 self.fstate.plane = blk_no - 3;
895 self.fstate.ctx_idx = blk_no - 2;
896 self.fstate.top_ctx = self.top_ctx[self.fstate.plane][mb_x];
898 CoeffReader::None => {
899 br.decode_block(bc, &mut self.coeffs[blk_no], &self.models.coeff_models[1], &self.models.vp6models, &mut self.fstate)?;
901 CoeffReader::Bool(ref mut bcc) => {
902 br.decode_block(bcc, &mut self.coeffs[blk_no], &self.models.coeff_models[1], &self.models.vp6models, &mut self.fstate)?;
904 CoeffReader::Huff(ref mut brc) => {
905 br.decode_block_huff(brc, &mut self.coeffs[blk_no], &self.models.vp6models, &self.models.vp6huff, &mut self.fstate)?;
908 self.top_ctx[self.fstate.plane][mb_x] = self.fstate.top_ctx;
909 self.predict_dc(mb_type, mb_pos, blk_no, alpha);
911 let has_ac = self.fstate.last_idx[self.fstate.ctx_idx] > 0;
912 if mb_type.is_intra() {
914 vp_put_block(&mut self.coeffs[blk_no], mb_x, mb_y, self.fstate.plane, frm);
916 vp_put_block_dc(&mut self.coeffs[blk_no], mb_x, mb_y, self.fstate.plane, frm);
920 vp_add_block(&mut self.coeffs[blk_no], mb_x, mb_y, self.fstate.plane, frm);
922 vp_add_block_dc(&mut self.coeffs[blk_no], mb_x, mb_y, self.fstate.plane, frm);
929 fn do_mc(&mut self, br: &dyn VP56Parser, frm: &mut NASimpleVideoFrame<u8>, mb_type: VPMBType, mv: MV, alpha: bool) {
930 let x = self.fstate.mb_x * 16;
931 let y = self.fstate.mb_y * 16;
932 let plane = if !alpha { 0 } else { 3 };
933 let src = if mb_type.get_ref_id() == VP_REF_INTER {
934 self.shuf.get_last().unwrap()
936 self.shuf.get_golden().unwrap()
939 br.mc_block(frm, self.mc_buf.clone(), src.clone(), plane, x + 0, y + 0, mv, self.loop_thr);
940 br.mc_block(frm, self.mc_buf.clone(), src.clone(), plane, x + 8, y + 0, mv, self.loop_thr);
941 br.mc_block(frm, self.mc_buf.clone(), src.clone(), plane, x + 0, y + 8, mv, self.loop_thr);
942 br.mc_block(frm, self.mc_buf.clone(), src.clone(), plane, x + 8, y + 8, mv, self.loop_thr);
944 let x = self.fstate.mb_x * 8;
945 let y = self.fstate.mb_y * 8;
946 br.mc_block(frm, self.mc_buf.clone(), src.clone(), 1, x, y, mv, self.loop_thr);
947 br.mc_block(frm, self.mc_buf.clone(), src.clone(), 2, x, y, mv, self.loop_thr);
950 fn do_fourmv(&mut self, br: &dyn VP56Parser, frm: &mut NASimpleVideoFrame<u8>, mvs: &[MV; 4], alpha: bool) {
951 let x = self.fstate.mb_x * 16;
952 let y = self.fstate.mb_y * 16;
953 let plane = if !alpha { 0 } else { 3 };
954 let src = self.shuf.get_last().unwrap();
956 br.mc_block(frm, self.mc_buf.clone(), src.clone(),
957 plane, x + (blk_no & 1) * 8, y + (blk_no & 2) * 4,
958 mvs[blk_no], self.loop_thr);
961 let x = self.fstate.mb_x * 8;
962 let y = self.fstate.mb_y * 8;
963 let sum = mvs[0] + mvs[1] + mvs[2] + mvs[3];
964 let mv = MV { x: sum.x / 4, y: sum.y / 4 };
965 br.mc_block(frm, self.mc_buf.clone(), src.clone(), 1, x, y, mv, self.loop_thr);
966 br.mc_block(frm, self.mc_buf.clone(), src.clone(), 2, x, y, mv, self.loop_thr);
969 fn predict_dc(&mut self, mb_type: VPMBType, _mb_pos: usize, blk_no: usize, _alpha: bool) {
970 let is_luma = blk_no < 4;
971 let (plane, dcs) = match blk_no {
972 4 => (1, &mut self.dc_pred.dc_u),
973 5 => (2, &mut self.dc_pred.dc_v),
974 _ => (0, &mut self.dc_pred.dc_y),
976 let (dc_ref, dc_idx) = if is_luma {
977 (&mut self.dc_pred.ref_y, self.dc_pred.y_idx + (blk_no & 1))
979 (&mut self.dc_pred.ref_c, self.dc_pred.c_idx)
981 let ref_id = mb_type.get_ref_id();
984 let has_left_blk = is_luma && ((blk_no & 1) == 1);
985 if has_left_blk || self.dc_pred.ref_left == ref_id {
986 dc_pred += match blk_no {
987 0 | 1 => self.dc_pred.ldc_y[0],
988 2 | 3 => self.dc_pred.ldc_y[1],
989 4 => self.dc_pred.ldc_u,
990 _ => self.dc_pred.ldc_v,
994 if dc_ref[dc_idx] == ref_id {
995 dc_pred += dcs[dc_idx];
998 if self.version == 5 {
999 if (count < 2) && (dc_ref[dc_idx - 1] == ref_id) {
1000 dc_pred += dcs[dc_idx - 1];
1003 if (count < 2) && (dc_ref[dc_idx + 1] == ref_id) {
1004 dc_pred += dcs[dc_idx + 1];
1009 dc_pred = self.last_dc[ref_id as usize][plane];
1010 } else if count == 2 {
1013 self.coeffs[blk_no][0] += dc_pred;
1015 let dc = self.coeffs[blk_no][0];
1016 if blk_no != 4 { // update top block reference only for the second chroma component
1017 dc_ref[dc_idx] = ref_id;
1021 self.dc_pred.ldc_y[0] = dc;
1024 self.dc_pred.ldc_y[1] = dc;
1027 self.dc_pred.ldc_u = dc;
1030 self.dc_pred.ldc_v = dc;
1031 self.dc_pred.ref_left = ref_id;
1036 self.last_dc[ref_id as usize][plane] = dc;
1037 self.coeffs[blk_no][0] = self.coeffs[blk_no][0].wrapping_mul(self.fstate.dc_quant);
1041 const VP56_DC_QUANTS: [i16; 64] = [
1042 47, 47, 47, 47, 45, 43, 43, 43,
1043 43, 43, 42, 41, 41, 40, 40, 40,
1044 40, 35, 35, 35, 35, 33, 33, 33,
1045 33, 32, 32, 32, 27, 27, 26, 26,
1046 25, 25, 24, 24, 23, 23, 19, 19,
1047 19, 19, 18, 18, 17, 16, 16, 16,
1048 16, 16, 15, 11, 11, 11, 10, 10,
1049 9, 8, 7, 5, 3, 3, 2, 2
1051 const VP56_AC_QUANTS: [i16; 64] = [
1052 94, 92, 90, 88, 86, 82, 78, 74,
1053 70, 66, 62, 58, 54, 53, 52, 51,
1054 50, 49, 48, 47, 46, 45, 44, 43,
1055 42, 40, 39, 37, 36, 35, 34, 33,
1056 32, 31, 30, 29, 28, 27, 26, 25,
1057 24, 23, 22, 21, 20, 19, 18, 17,
1058 16, 15, 14, 13, 12, 11, 10, 9,
1059 8, 7, 6, 5, 4, 3, 2, 1
1062 const VP56_FILTER_LIMITS: [u8; 64] = [
1063 14, 14, 13, 13, 12, 12, 10, 10,
1064 10, 10, 8, 8, 8, 8, 8, 8,
1065 8, 8, 8, 8, 8, 8, 8, 8,
1066 8, 8, 8, 8, 8, 8, 8, 8,
1067 8, 8, 8, 8, 7, 7, 7, 7,
1068 7, 7, 6, 6, 6, 6, 6, 6,
1069 5, 5, 5, 5, 4, 4, 4, 4,
1070 4, 4, 4, 3, 3, 3, 3, 2
1073 const VP56_MODE_VQ: [[[u8; 20]; 16]; 3] = [
1075 [ 9, 15, 32, 25, 7, 19, 9, 21, 1, 12, 14, 12, 3, 18, 14, 23, 3, 10, 0, 4 ],
1076 [ 48, 39, 1, 2, 11, 27, 29, 44, 7, 27, 1, 4, 0, 3, 1, 6, 1, 2, 0, 0 ],
1077 [ 21, 32, 1, 2, 4, 10, 32, 43, 6, 23, 2, 3, 1, 19, 1, 6, 12, 21, 0, 7 ],
1078 [ 69, 83, 0, 0, 0, 2, 10, 29, 3, 12, 0, 1, 0, 3, 0, 3, 2, 2, 0, 0 ],
1079 [ 11, 20, 1, 4, 18, 36, 43, 48, 13, 35, 0, 2, 0, 5, 3, 12, 1, 2, 0, 0 ],
1080 [ 70, 44, 0, 1, 2, 10, 37, 46, 8, 26, 0, 2, 0, 2, 0, 2, 0, 1, 0, 0 ],
1081 [ 8, 15, 0, 1, 8, 21, 74, 53, 22, 42, 0, 1, 0, 2, 0, 3, 1, 2, 0, 0 ],
1082 [ 141, 42, 0, 0, 1, 4, 11, 24, 1, 11, 0, 1, 0, 1, 0, 2, 0, 0, 0, 0 ],
1083 [ 8, 19, 4, 10, 24, 45, 21, 37, 9, 29, 0, 3, 1, 7, 11, 25, 0, 2, 0, 1 ],
1084 [ 46, 42, 0, 1, 2, 10, 54, 51, 10, 30, 0, 2, 0, 2, 0, 1, 0, 1, 0, 0 ],
1085 [ 28, 32, 0, 0, 3, 10, 75, 51, 14, 33, 0, 1, 0, 2, 0, 1, 1, 2, 0, 0 ],
1086 [ 100, 46, 0, 1, 3, 9, 21, 37, 5, 20, 0, 1, 0, 2, 1, 2, 0, 1, 0, 0 ],
1087 [ 27, 29, 0, 1, 9, 25, 53, 51, 12, 34, 0, 1, 0, 3, 1, 5, 0, 2, 0, 0 ],
1088 [ 80, 38, 0, 0, 1, 4, 69, 33, 5, 16, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0 ],
1089 [ 16, 20, 0, 0, 2, 8, 104, 49, 15, 33, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0 ],
1090 [ 194, 16, 0, 0, 1, 1, 1, 9, 1, 3, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0 ],
1092 [ 41, 22, 1, 0, 1, 31, 0, 0, 0, 0, 0, 1, 1, 7, 0, 1, 98, 25, 4, 10 ],
1093 [ 123, 37, 6, 4, 1, 27, 0, 0, 0, 0, 5, 8, 1, 7, 0, 1, 12, 10, 0, 2 ],
1094 [ 26, 14, 14, 12, 0, 24, 0, 0, 0, 0, 55, 17, 1, 9, 0, 36, 5, 7, 1, 3 ],
1095 [ 209, 5, 0, 0, 0, 27, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0 ],
1096 [ 2, 5, 4, 5, 0, 121, 0, 0, 0, 0, 0, 3, 2, 4, 1, 4, 2, 2, 0, 1 ],
1097 [ 175, 5, 0, 1, 0, 48, 0, 0, 0, 0, 0, 2, 0, 1, 0, 2, 0, 1, 0, 0 ],
1098 [ 83, 5, 2, 3, 0, 102, 0, 0, 0, 0, 1, 3, 0, 2, 0, 1, 0, 0, 0, 0 ],
1099 [ 233, 6, 0, 0, 0, 8, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0 ],
1100 [ 34, 16, 112, 21, 1, 28, 0, 0, 0, 0, 6, 8, 1, 7, 0, 3, 2, 5, 0, 2 ],
1101 [ 159, 35, 2, 2, 0, 25, 0, 0, 0, 0, 3, 6, 0, 5, 0, 1, 4, 4, 0, 1 ],
1102 [ 75, 39, 5, 7, 2, 48, 0, 0, 0, 0, 3, 11, 2, 16, 1, 4, 7, 10, 0, 2 ],
1103 [ 212, 21, 0, 1, 0, 9, 0, 0, 0, 0, 1, 2, 0, 2, 0, 0, 2, 2, 0, 0 ],
1104 [ 4, 2, 0, 0, 0, 172, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 2, 0, 0, 0 ],
1105 [ 187, 22, 1, 1, 0, 17, 0, 0, 0, 0, 3, 6, 0, 4, 0, 1, 4, 4, 0, 1 ],
1106 [ 133, 6, 1, 2, 1, 70, 0, 0, 0, 0, 0, 2, 0, 4, 0, 3, 1, 1, 0, 0 ],
1107 [ 251, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
1109 [ 2, 3, 2, 3, 0, 2, 0, 2, 0, 0, 11, 4, 1, 4, 0, 2, 3, 2, 0, 4 ],
1110 [ 49, 46, 3, 4, 7, 31, 42, 41, 0, 0, 2, 6, 1, 7, 1, 4, 2, 4, 0, 1 ],
1111 [ 26, 25, 1, 1, 2, 10, 67, 39, 0, 0, 1, 1, 0, 14, 0, 2, 31, 26, 1, 6 ],
1112 [ 103, 46, 1, 2, 2, 10, 33, 42, 0, 0, 1, 4, 0, 3, 0, 1, 1, 3, 0, 0 ],
1113 [ 14, 31, 9, 13, 14, 54, 22, 29, 0, 0, 2, 6, 4, 18, 6, 13, 1, 5, 0, 1 ],
1114 [ 85, 39, 0, 0, 1, 9, 69, 40, 0, 0, 0, 1, 0, 3, 0, 1, 2, 3, 0, 0 ],
1115 [ 31, 28, 0, 0, 3, 14, 130, 34, 0, 0, 0, 1, 0, 3, 0, 1, 3, 3, 0, 1 ],
1116 [ 171, 25, 0, 0, 1, 5, 25, 21, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0 ],
1117 [ 17, 21, 68, 29, 6, 15, 13, 22, 0, 0, 6, 12, 3, 14, 4, 10, 1, 7, 0, 3 ],
1118 [ 51, 39, 0, 1, 2, 12, 91, 44, 0, 0, 0, 2, 0, 3, 0, 1, 2, 3, 0, 1 ],
1119 [ 81, 25, 0, 0, 2, 9, 106, 26, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0 ],
1120 [ 140, 37, 0, 1, 1, 8, 24, 33, 0, 0, 1, 2, 0, 2, 0, 1, 1, 2, 0, 0 ],
1121 [ 14, 23, 1, 3, 11, 53, 90, 31, 0, 0, 0, 3, 1, 5, 2, 6, 1, 2, 0, 0 ],
1122 [ 123, 29, 0, 0, 1, 7, 57, 30, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0 ],
1123 [ 13, 14, 0, 0, 4, 20, 175, 20, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0 ],
1124 [ 202, 23, 0, 0, 1, 3, 2, 9, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0 ],