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, YUV420_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 vinfo = NAVideoInfo::new(self.width, self.height, self.flip, YUV420_FORMAT);
490 let ret = supp.pool_u8.get_free();
492 return Err(DecoderError::AllocError);
494 let mut buf = ret.unwrap();
495 if buf.get_info() != vinfo {
497 supp.pool_u8.reset();
498 supp.pool_u8.prealloc_video(vinfo, 4)?;
499 let ret = supp.pool_u8.get_free();
501 return Err(DecoderError::AllocError);
505 let mut dframe = NASimpleVideoFrame::from_video_buf(&mut buf).unwrap();
510 if !self.shuf.has_refs() {
511 return Err(DecoderError::MissingReference);
517 let off = (if self.has_alpha { 3 } else { 0 }) + (hdr.offset as usize);
518 if !hdr.use_huffman {
519 let bc2 = BoolCoder::new(&src[off..])?;
520 cr = CoeffReader::Bool(bc2);
522 let br = BitReader::new(&src[off..], aoffset - off, BitReaderMode::BE);
523 cr = CoeffReader::Huff(br);
526 cr = CoeffReader::None;
530 br.reset_models(&mut self.models);
531 self.reset_mbtype_models();
533 self.decode_mode_prob_models(&mut bc)?;
534 br.decode_mv_models(&mut bc, &mut self.models.mv_models)?;
536 br.decode_coeff_models(&mut bc, &mut self.models, hdr.is_intra)?;
539 self.models.vp6huff.dc_token_tree[i].build_codes(&self.models.coeff_models[i].dc_value_probs);
544 self.models.vp6huff.ac_token_tree[i][mode][band].build_codes(&self.models.coeff_models[i].ac_val_probs[mode][band]);
549 self.models.vp6huff.zero_run_tree[i].build_codes_zero_run(&self.models.vp6models.zero_run_probs[i]);
554 self.ilace_prob = bc.read_bits(8) as u8;
557 self.fstate = FrameState::new();
558 self.fstate.dc_quant = VP56_DC_QUANTS[hdr.quant as usize] * 4;
559 self.fstate.ac_quant = VP56_AC_QUANTS[hdr.quant as usize] * 4;
560 self.loop_thr = VP56_FILTER_LIMITS[hdr.quant as usize] as i16;
562 self.last_mbt = VPMBType::InterNoMV;
563 for vec in self.top_ctx.iter_mut() {
564 for el in vec.iter_mut() {
568 self.last_dc = [[0; 4]; 3];
569 self.last_dc[0][1] = 0x80;
570 self.last_dc[0][2] = 0x80;
571 self.dc_pred.reset();
573 self.ilace_mb = false;
574 for mb_y in 0..self.mb_h {
575 self.fstate.mb_y = mb_y;
576 self.fstate.coeff_cat = [[0; 64]; 4];
577 self.fstate.last_idx = [24; 4];
578 for mb_x in 0..self.mb_w {
579 self.fstate.mb_x = mb_x;
580 self.decode_mb(&mut dframe, &mut bc, &mut cr, br, &hdr, false)?;
581 self.dc_pred.next_mb();
583 self.dc_pred.update_row();
587 let asrc = &src[aoffset + 3..];
588 let mut bc = BoolCoder::new(asrc)?;
589 let ahdr = br.parse_header(&mut bc)?;
590 validate!(ahdr.mb_w == hdr.mb_w && ahdr.mb_h == hdr.mb_h);
594 self.shuf.add_golden_frame(buf.clone());
596 self.shuf.add_frame(buf.clone());
598 Ok((NABufferType::Video(buf), if hdr.is_intra { FrameType::I } else { FrameType::P }))
600 fn reset_mbtype_models(&mut self) {
601 const DEFAULT_XMITTED_PROBS: [[u8; 20]; 3] = [
602 [ 42, 69, 2, 1, 7, 1, 42, 44, 22, 6, 3, 1, 2, 0, 5, 1, 1, 0, 0, 0 ],
603 [ 8, 229, 1, 1, 8, 0, 0, 0, 0, 0, 2, 1, 1, 0, 0, 0, 1, 1, 0, 0 ],
604 [ 35, 122, 1, 1, 6, 1, 34, 46, 0, 0, 2, 1, 1, 0, 1, 0, 1, 1, 0, 0 ]
606 self.models.prob_xmitted.copy_from_slice(&DEFAULT_XMITTED_PROBS);
608 fn decode_mode_prob_models(&mut self, bc: &mut BoolCoder) -> DecoderResult<()> {
610 if bc.read_prob(174) {
611 let idx = bc.read_bits(4) as usize;
613 self.models.prob_xmitted[ctx][i ^ 1] = VP56_MODE_VQ[ctx][idx][i];
616 if bc.read_prob(254) {
618 if bc.read_prob(205) {
619 let sign = bc.read_bool();
620 let diff = vp_tree!(bc, 171,
621 vp_tree!(bc, 83, 2, 1),
625 vp_tree!(bc, 104, 6, 5),
632 validate!(diff < 256);
633 let diff = diff as u8;
635 validate!(self.models.prob_xmitted[ctx][set ^ 1] <= 255 - diff);
636 self.models.prob_xmitted[ctx][set ^ 1] += diff;
638 validate!(self.models.prob_xmitted[ctx][set ^ 1] >= diff);
639 self.models.prob_xmitted[ctx][set ^ 1] -= diff;
646 let prob_xmitted = &self.models.prob_xmitted[ctx];
648 let mdl = &mut self.models.mbtype_models[ctx][mode];
649 let mut cnt = [0u32; 10];
652 if i == mode { continue; }
653 cnt[i] = 100 * (prob_xmitted[i * 2] as u32);
656 let sum = (prob_xmitted[mode * 2] as u32) + (prob_xmitted[mode * 2 + 1] as u32);
657 mdl.probs[9] = 255 - rescale_mb_mode_prob(prob_xmitted[mode * 2 + 1] as u32, sum);
659 let inter_mv0_weight = (cnt[0] as u32) + (cnt[2] as u32);
660 let inter_mv1_weight = (cnt[3] as u32) + (cnt[4] as u32);
661 let gold_mv0_weight = (cnt[5] as u32) + (cnt[6] as u32);
662 let gold_mv1_weight = (cnt[8] as u32) + (cnt[9] as u32);
663 let mix_weight = (cnt[1] as u32) + (cnt[7] as u32);
664 mdl.probs[0] = 1 + rescale_mb_mode_prob(inter_mv0_weight + inter_mv1_weight, total);
665 mdl.probs[1] = 1 + rescale_mb_mode_prob(inter_mv0_weight, inter_mv0_weight + inter_mv1_weight);
666 mdl.probs[2] = 1 + rescale_mb_mode_prob(mix_weight, mix_weight + gold_mv0_weight + gold_mv1_weight);
667 mdl.probs[3] = 1 + rescale_mb_mode_prob(cnt[0] as u32, inter_mv0_weight);
668 mdl.probs[4] = 1 + rescale_mb_mode_prob(cnt[3] as u32, inter_mv1_weight);
669 mdl.probs[5] = 1 + rescale_mb_mode_prob(cnt[1], mix_weight);
670 mdl.probs[6] = 1 + rescale_mb_mode_prob(gold_mv0_weight, gold_mv0_weight + gold_mv1_weight);
671 mdl.probs[7] = 1 + rescale_mb_mode_prob(cnt[5], gold_mv0_weight);
672 mdl.probs[8] = 1 + rescale_mb_mode_prob(cnt[8], gold_mv1_weight);
677 fn find_mv_pred(&self, ref_id: u8) -> (usize, MV, MV, MV) {
678 const CAND_POS: [(i8, i8); 12] = [
687 let mut nearest_mv = ZERO_MV;
688 let mut near_mv = ZERO_MV;
689 let mut pred_mv = ZERO_MV;
690 let mut num_mv: usize = 0;
692 for (i, (yoff, xoff)) in CAND_POS.iter().enumerate() {
693 let cx = (self.fstate.mb_x as isize) + (*xoff as isize);
694 let cy = (self.fstate.mb_y as isize) + (*yoff as isize);
695 if (cx < 0) || (cy < 0) {
698 let cx = cx as usize;
699 let cy = cy as usize;
700 if (cx >= self.mb_w) || (cy >= self.mb_h) {
703 let mb_pos = cx + cy * self.mb_w;
704 let mv = self.mb_info[mb_pos].mv;
705 if (self.mb_info[mb_pos].mb_type.get_ref_id() != ref_id) || (mv == ZERO_MV) {
711 if (self.version > 5) && (i < 2) {
714 } else if mv != nearest_mv {
721 (num_mv, nearest_mv, near_mv, pred_mv)
723 fn decode_mv(&self, bc: &mut BoolCoder, br: &mut dyn VP56Parser) -> MV {
724 let x = br.decode_mv(bc, &self.models.mv_models[0]);
725 let y = br.decode_mv(bc, &self.models.mv_models[1]);
728 fn decode_mb_type(&mut self, bc: &mut BoolCoder, ctx: usize) -> DecoderResult<VPMBType> {
729 let probs = &self.models.mbtype_models[ctx][map_mb_type(self.last_mbt)].probs;
730 if !bc.read_prob(probs[9]) {
731 self.last_mbt = vp_tree!(
733 vp_tree!(bc, probs[1],
734 vp_tree!(bc, probs[3], VPMBType::InterNoMV, VPMBType::InterMV),
735 vp_tree!(bc, probs[4], VPMBType::InterNearest, VPMBType::InterNear)
737 vp_tree!(bc, probs[2],
738 vp_tree!(bc, probs[5], VPMBType::Intra, VPMBType::InterFourMV),
739 vp_tree!(bc, probs[6],
740 vp_tree!(bc, probs[7], VPMBType::GoldenNoMV, VPMBType::GoldenMV),
741 vp_tree!(bc, probs[8], VPMBType::GoldenNearest, VPMBType::GoldenNear)
748 fn decode_mb(&mut self, frm: &mut NASimpleVideoFrame<u8>, bc: &mut BoolCoder, cr: &mut CoeffReader, br: &mut dyn VP56Parser, hdr: &VP56Header, alpha: bool) -> DecoderResult<()> {
749 const FOURMV_SUB_TYPE: [VPMBType; 4] = [ VPMBType::InterNoMV, VPMBType::InterMV, VPMBType::InterNearest, VPMBType::InterNear ];
751 let mb_x = self.fstate.mb_x;
752 let mb_y = self.fstate.mb_y;
753 self.coeffs = [[0; 64]; 6];
754 let mb_pos = mb_x + mb_y * self.mb_w;
755 let mut four_mv = [ZERO_MV; 4];
756 let mut four_mbt = [VPMBType::Intra; 4];
759 let iprob = self.ilace_prob;
760 let prob = if mb_x == 0 {
762 } else if !self.ilace_mb {
763 iprob + (((256 - (iprob as u16)) >> 1) as u8)
767 self.ilace_mb = bc.read_prob(prob);
770 let (num_mv, nearest_mv, near_mv, pred_mv) = if hdr.is_intra {
771 (0, ZERO_MV, ZERO_MV, ZERO_MV)
772 } else { self.find_mv_pred(VP_REF_INTER) };
773 let mb_type = if hdr.is_intra {
776 self.decode_mb_type(bc, (num_mv + 1) % 3)?
778 self.mb_info[mb_pos].mb_type = mb_type;
779 if mb_type.get_ref_id() != VP_REF_GOLDEN {
782 VPMBType::InterNoMV => {
783 self.mb_info[mb_pos].mv = ZERO_MV;
785 VPMBType::InterMV => {
786 let diff_mv = self.decode_mv(bc, br);
787 self.mb_info[mb_pos].mv = pred_mv + diff_mv;
789 VPMBType::InterNearest => {
790 self.mb_info[mb_pos].mv = nearest_mv;
792 VPMBType::InterNear => {
793 self.mb_info[mb_pos].mv = near_mv;
795 VPMBType::InterFourMV => {
797 four_mbt[i] = FOURMV_SUB_TYPE[bc.read_bits(2) as usize];
801 VPMBType::InterNoMV => {},
802 VPMBType::InterMV => {
803 let diff_mv = self.decode_mv(bc, br);
804 four_mv[i] = pred_mv + diff_mv;
806 VPMBType::InterNearest => {
807 four_mv[i] = nearest_mv;
809 VPMBType::InterNear => {
810 four_mv[i] = near_mv;
815 self.mb_info[mb_pos].mv = four_mv[3];
820 let (_num_mv, nearest_mv, near_mv, pred_mv) = self.find_mv_pred(VP_REF_GOLDEN);
822 VPMBType::GoldenNoMV => {
823 self.mb_info[mb_pos].mv = ZERO_MV;
825 VPMBType::GoldenMV => {
826 let diff_mv = self.decode_mv(bc, br);
827 self.mb_info[mb_pos].mv = pred_mv + diff_mv;
829 VPMBType::GoldenNearest => {
830 self.mb_info[mb_pos].mv = nearest_mv;
832 VPMBType::GoldenNear => {
833 self.mb_info[mb_pos].mv = near_mv;
838 if !mb_type.is_intra() && (mb_type != VPMBType::InterFourMV) {
839 self.do_mc(br, frm, mb_type, self.mb_info[mb_pos].mv, alpha);
840 } else if mb_type == VPMBType::InterFourMV {
841 self.do_fourmv(br, frm, &four_mv, alpha);
845 self.fstate.plane = if !alpha { 0 } else { 3 };
846 self.fstate.ctx_idx = blk_no >> 1;
847 self.fstate.top_ctx = self.top_ctx[self.fstate.plane][mb_x * 2 + (blk_no & 1)];
849 CoeffReader::None => {
850 br.decode_block(bc, &mut self.coeffs[blk_no], &self.models.coeff_models[0], &self.models.vp6models, &mut self.fstate)?;
852 CoeffReader::Bool(ref mut bcc) => {
853 br.decode_block(bcc, &mut self.coeffs[blk_no], &self.models.coeff_models[0], &self.models.vp6models, &mut self.fstate)?;
855 CoeffReader::Huff(ref mut brc) => {
856 br.decode_block_huff(brc, &mut self.coeffs[blk_no], &self.models.vp6models, &self.models.vp6huff, &mut self.fstate)?;
859 self.top_ctx[self.fstate.plane][mb_x * 2 + (blk_no & 1)] = self.fstate.top_ctx;
860 self.predict_dc(mb_type, mb_pos, blk_no, alpha);
862 let bx = mb_x * 2 + (blk_no & 1);
863 let by = mb_y * 2 + (blk_no >> 1);
864 let has_ac = self.fstate.last_idx[self.fstate.ctx_idx] > 0;
865 if mb_type.is_intra() {
868 vp_put_block(&mut self.coeffs[blk_no], bx, by, self.fstate.plane, frm);
870 vp_put_block_dc(&mut self.coeffs[blk_no], bx, by, self.fstate.plane, frm);
873 vp_put_block_ilace(&mut self.coeffs[blk_no], bx, by, self.fstate.plane, frm);
878 vp_add_block(&mut self.coeffs[blk_no], bx, by, self.fstate.plane, frm);
880 vp_add_block_dc(&mut self.coeffs[blk_no], bx, by, self.fstate.plane, frm);
883 vp_add_block_ilace(&mut self.coeffs[blk_no], bx, by, self.fstate.plane, frm);
889 self.fstate.plane = blk_no - 3;
890 self.fstate.ctx_idx = blk_no - 2;
891 self.fstate.top_ctx = self.top_ctx[self.fstate.plane][mb_x];
893 CoeffReader::None => {
894 br.decode_block(bc, &mut self.coeffs[blk_no], &self.models.coeff_models[1], &self.models.vp6models, &mut self.fstate)?;
896 CoeffReader::Bool(ref mut bcc) => {
897 br.decode_block(bcc, &mut self.coeffs[blk_no], &self.models.coeff_models[1], &self.models.vp6models, &mut self.fstate)?;
899 CoeffReader::Huff(ref mut brc) => {
900 br.decode_block_huff(brc, &mut self.coeffs[blk_no], &self.models.vp6models, &self.models.vp6huff, &mut self.fstate)?;
903 self.top_ctx[self.fstate.plane][mb_x] = self.fstate.top_ctx;
904 self.predict_dc(mb_type, mb_pos, blk_no, alpha);
906 let has_ac = self.fstate.last_idx[self.fstate.ctx_idx] > 0;
907 if mb_type.is_intra() {
909 vp_put_block(&mut self.coeffs[blk_no], mb_x, mb_y, self.fstate.plane, frm);
911 vp_put_block_dc(&mut self.coeffs[blk_no], mb_x, mb_y, self.fstate.plane, frm);
915 vp_add_block(&mut self.coeffs[blk_no], mb_x, mb_y, self.fstate.plane, frm);
917 vp_add_block_dc(&mut self.coeffs[blk_no], mb_x, mb_y, self.fstate.plane, frm);
924 fn do_mc(&mut self, br: &dyn VP56Parser, frm: &mut NASimpleVideoFrame<u8>, mb_type: VPMBType, mv: MV, alpha: bool) {
925 let x = self.fstate.mb_x * 16;
926 let y = self.fstate.mb_y * 16;
927 let plane = if !alpha { 0 } else { 3 };
928 let src = if mb_type.get_ref_id() == VP_REF_INTER {
929 self.shuf.get_last().unwrap()
931 self.shuf.get_golden().unwrap()
934 br.mc_block(frm, self.mc_buf.clone(), src.clone(), plane, x + 0, y + 0, mv, self.loop_thr);
935 br.mc_block(frm, self.mc_buf.clone(), src.clone(), plane, x + 8, y + 0, mv, self.loop_thr);
936 br.mc_block(frm, self.mc_buf.clone(), src.clone(), plane, x + 0, y + 8, mv, self.loop_thr);
937 br.mc_block(frm, self.mc_buf.clone(), src.clone(), plane, x + 8, y + 8, mv, self.loop_thr);
939 let x = self.fstate.mb_x * 8;
940 let y = self.fstate.mb_y * 8;
941 br.mc_block(frm, self.mc_buf.clone(), src.clone(), 1, x, y, mv, self.loop_thr);
942 br.mc_block(frm, self.mc_buf.clone(), src.clone(), 2, x, y, mv, self.loop_thr);
945 fn do_fourmv(&mut self, br: &dyn VP56Parser, frm: &mut NASimpleVideoFrame<u8>, mvs: &[MV; 4], alpha: bool) {
946 let x = self.fstate.mb_x * 16;
947 let y = self.fstate.mb_y * 16;
948 let plane = if !alpha { 0 } else { 3 };
949 let src = self.shuf.get_last().unwrap();
951 br.mc_block(frm, self.mc_buf.clone(), src.clone(),
952 plane, x + (blk_no & 1) * 8, y + (blk_no & 2) * 4,
953 mvs[blk_no], self.loop_thr);
956 let x = self.fstate.mb_x * 8;
957 let y = self.fstate.mb_y * 8;
958 let sum = mvs[0] + mvs[1] + mvs[2] + mvs[3];
959 let mv = MV { x: sum.x / 4, y: sum.y / 4 };
960 br.mc_block(frm, self.mc_buf.clone(), src.clone(), 1, x, y, mv, self.loop_thr);
961 br.mc_block(frm, self.mc_buf.clone(), src.clone(), 2, x, y, mv, self.loop_thr);
964 fn predict_dc(&mut self, mb_type: VPMBType, _mb_pos: usize, blk_no: usize, _alpha: bool) {
965 let is_luma = blk_no < 4;
966 let (plane, dcs) = match blk_no {
967 4 => (1, &mut self.dc_pred.dc_u),
968 5 => (2, &mut self.dc_pred.dc_v),
969 _ => (0, &mut self.dc_pred.dc_y),
971 let (dc_ref, dc_idx) = if is_luma {
972 (&mut self.dc_pred.ref_y, self.dc_pred.y_idx + (blk_no & 1))
974 (&mut self.dc_pred.ref_c, self.dc_pred.c_idx)
976 let ref_id = mb_type.get_ref_id();
979 let has_left_blk = is_luma && ((blk_no & 1) == 1);
980 if has_left_blk || self.dc_pred.ref_left == ref_id {
981 dc_pred += match blk_no {
982 0 | 1 => self.dc_pred.ldc_y[0],
983 2 | 3 => self.dc_pred.ldc_y[1],
984 4 => self.dc_pred.ldc_u,
985 _ => self.dc_pred.ldc_v,
989 if dc_ref[dc_idx] == ref_id {
990 dc_pred += dcs[dc_idx];
993 if self.version == 5 {
994 if (count < 2) && (dc_ref[dc_idx - 1] == ref_id) {
995 dc_pred += dcs[dc_idx - 1];
998 if (count < 2) && (dc_ref[dc_idx + 1] == ref_id) {
999 dc_pred += dcs[dc_idx + 1];
1004 dc_pred = self.last_dc[ref_id as usize][plane];
1005 } else if count == 2 {
1008 self.coeffs[blk_no][0] += dc_pred;
1010 let dc = self.coeffs[blk_no][0];
1011 if blk_no != 4 { // update top block reference only for the second chroma component
1012 dc_ref[dc_idx] = ref_id;
1016 self.dc_pred.ldc_y[0] = dc;
1019 self.dc_pred.ldc_y[1] = dc;
1022 self.dc_pred.ldc_u = dc;
1025 self.dc_pred.ldc_v = dc;
1026 self.dc_pred.ref_left = ref_id;
1031 self.last_dc[ref_id as usize][plane] = dc;
1032 self.coeffs[blk_no][0] = self.coeffs[blk_no][0].wrapping_mul(self.fstate.dc_quant);
1036 const VP56_DC_QUANTS: [i16; 64] = [
1037 47, 47, 47, 47, 45, 43, 43, 43,
1038 43, 43, 42, 41, 41, 40, 40, 40,
1039 40, 35, 35, 35, 35, 33, 33, 33,
1040 33, 32, 32, 32, 27, 27, 26, 26,
1041 25, 25, 24, 24, 23, 23, 19, 19,
1042 19, 19, 18, 18, 17, 16, 16, 16,
1043 16, 16, 15, 11, 11, 11, 10, 10,
1044 9, 8, 7, 5, 3, 3, 2, 2
1046 const VP56_AC_QUANTS: [i16; 64] = [
1047 94, 92, 90, 88, 86, 82, 78, 74,
1048 70, 66, 62, 58, 54, 53, 52, 51,
1049 50, 49, 48, 47, 46, 45, 44, 43,
1050 42, 40, 39, 37, 36, 35, 34, 33,
1051 32, 31, 30, 29, 28, 27, 26, 25,
1052 24, 23, 22, 21, 20, 19, 18, 17,
1053 16, 15, 14, 13, 12, 11, 10, 9,
1054 8, 7, 6, 5, 4, 3, 2, 1
1057 const VP56_FILTER_LIMITS: [u8; 64] = [
1058 14, 14, 13, 13, 12, 12, 10, 10,
1059 10, 10, 8, 8, 8, 8, 8, 8,
1060 8, 8, 8, 8, 8, 8, 8, 8,
1061 8, 8, 8, 8, 8, 8, 8, 8,
1062 8, 8, 8, 8, 7, 7, 7, 7,
1063 7, 7, 6, 6, 6, 6, 6, 6,
1064 5, 5, 5, 5, 4, 4, 4, 4,
1065 4, 4, 4, 3, 3, 3, 3, 2
1068 const VP56_MODE_VQ: [[[u8; 20]; 16]; 3] = [
1070 [ 9, 15, 32, 25, 7, 19, 9, 21, 1, 12, 14, 12, 3, 18, 14, 23, 3, 10, 0, 4 ],
1071 [ 48, 39, 1, 2, 11, 27, 29, 44, 7, 27, 1, 4, 0, 3, 1, 6, 1, 2, 0, 0 ],
1072 [ 21, 32, 1, 2, 4, 10, 32, 43, 6, 23, 2, 3, 1, 19, 1, 6, 12, 21, 0, 7 ],
1073 [ 69, 83, 0, 0, 0, 2, 10, 29, 3, 12, 0, 1, 0, 3, 0, 3, 2, 2, 0, 0 ],
1074 [ 11, 20, 1, 4, 18, 36, 43, 48, 13, 35, 0, 2, 0, 5, 3, 12, 1, 2, 0, 0 ],
1075 [ 70, 44, 0, 1, 2, 10, 37, 46, 8, 26, 0, 2, 0, 2, 0, 2, 0, 1, 0, 0 ],
1076 [ 8, 15, 0, 1, 8, 21, 74, 53, 22, 42, 0, 1, 0, 2, 0, 3, 1, 2, 0, 0 ],
1077 [ 141, 42, 0, 0, 1, 4, 11, 24, 1, 11, 0, 1, 0, 1, 0, 2, 0, 0, 0, 0 ],
1078 [ 8, 19, 4, 10, 24, 45, 21, 37, 9, 29, 0, 3, 1, 7, 11, 25, 0, 2, 0, 1 ],
1079 [ 46, 42, 0, 1, 2, 10, 54, 51, 10, 30, 0, 2, 0, 2, 0, 1, 0, 1, 0, 0 ],
1080 [ 28, 32, 0, 0, 3, 10, 75, 51, 14, 33, 0, 1, 0, 2, 0, 1, 1, 2, 0, 0 ],
1081 [ 100, 46, 0, 1, 3, 9, 21, 37, 5, 20, 0, 1, 0, 2, 1, 2, 0, 1, 0, 0 ],
1082 [ 27, 29, 0, 1, 9, 25, 53, 51, 12, 34, 0, 1, 0, 3, 1, 5, 0, 2, 0, 0 ],
1083 [ 80, 38, 0, 0, 1, 4, 69, 33, 5, 16, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0 ],
1084 [ 16, 20, 0, 0, 2, 8, 104, 49, 15, 33, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0 ],
1085 [ 194, 16, 0, 0, 1, 1, 1, 9, 1, 3, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0 ],
1087 [ 41, 22, 1, 0, 1, 31, 0, 0, 0, 0, 0, 1, 1, 7, 0, 1, 98, 25, 4, 10 ],
1088 [ 123, 37, 6, 4, 1, 27, 0, 0, 0, 0, 5, 8, 1, 7, 0, 1, 12, 10, 0, 2 ],
1089 [ 26, 14, 14, 12, 0, 24, 0, 0, 0, 0, 55, 17, 1, 9, 0, 36, 5, 7, 1, 3 ],
1090 [ 209, 5, 0, 0, 0, 27, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0 ],
1091 [ 2, 5, 4, 5, 0, 121, 0, 0, 0, 0, 0, 3, 2, 4, 1, 4, 2, 2, 0, 1 ],
1092 [ 175, 5, 0, 1, 0, 48, 0, 0, 0, 0, 0, 2, 0, 1, 0, 2, 0, 1, 0, 0 ],
1093 [ 83, 5, 2, 3, 0, 102, 0, 0, 0, 0, 1, 3, 0, 2, 0, 1, 0, 0, 0, 0 ],
1094 [ 233, 6, 0, 0, 0, 8, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0 ],
1095 [ 34, 16, 112, 21, 1, 28, 0, 0, 0, 0, 6, 8, 1, 7, 0, 3, 2, 5, 0, 2 ],
1096 [ 159, 35, 2, 2, 0, 25, 0, 0, 0, 0, 3, 6, 0, 5, 0, 1, 4, 4, 0, 1 ],
1097 [ 75, 39, 5, 7, 2, 48, 0, 0, 0, 0, 3, 11, 2, 16, 1, 4, 7, 10, 0, 2 ],
1098 [ 212, 21, 0, 1, 0, 9, 0, 0, 0, 0, 1, 2, 0, 2, 0, 0, 2, 2, 0, 0 ],
1099 [ 4, 2, 0, 0, 0, 172, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 2, 0, 0, 0 ],
1100 [ 187, 22, 1, 1, 0, 17, 0, 0, 0, 0, 3, 6, 0, 4, 0, 1, 4, 4, 0, 1 ],
1101 [ 133, 6, 1, 2, 1, 70, 0, 0, 0, 0, 0, 2, 0, 4, 0, 3, 1, 1, 0, 0 ],
1102 [ 251, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
1104 [ 2, 3, 2, 3, 0, 2, 0, 2, 0, 0, 11, 4, 1, 4, 0, 2, 3, 2, 0, 4 ],
1105 [ 49, 46, 3, 4, 7, 31, 42, 41, 0, 0, 2, 6, 1, 7, 1, 4, 2, 4, 0, 1 ],
1106 [ 26, 25, 1, 1, 2, 10, 67, 39, 0, 0, 1, 1, 0, 14, 0, 2, 31, 26, 1, 6 ],
1107 [ 103, 46, 1, 2, 2, 10, 33, 42, 0, 0, 1, 4, 0, 3, 0, 1, 1, 3, 0, 0 ],
1108 [ 14, 31, 9, 13, 14, 54, 22, 29, 0, 0, 2, 6, 4, 18, 6, 13, 1, 5, 0, 1 ],
1109 [ 85, 39, 0, 0, 1, 9, 69, 40, 0, 0, 0, 1, 0, 3, 0, 1, 2, 3, 0, 0 ],
1110 [ 31, 28, 0, 0, 3, 14, 130, 34, 0, 0, 0, 1, 0, 3, 0, 1, 3, 3, 0, 1 ],
1111 [ 171, 25, 0, 0, 1, 5, 25, 21, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0 ],
1112 [ 17, 21, 68, 29, 6, 15, 13, 22, 0, 0, 6, 12, 3, 14, 4, 10, 1, 7, 0, 3 ],
1113 [ 51, 39, 0, 1, 2, 12, 91, 44, 0, 0, 0, 2, 0, 3, 0, 1, 2, 3, 0, 1 ],
1114 [ 81, 25, 0, 0, 2, 9, 106, 26, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0 ],
1115 [ 140, 37, 0, 1, 1, 8, 24, 33, 0, 0, 1, 2, 0, 2, 0, 1, 1, 2, 0, 0 ],
1116 [ 14, 23, 1, 3, 11, 53, 90, 31, 0, 0, 0, 3, 1, 5, 2, 6, 1, 2, 0, 0 ],
1117 [ 123, 29, 0, 0, 1, 7, 57, 30, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0 ],
1118 [ 13, 14, 0, 0, 4, 20, 175, 20, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0 ],
1119 [ 202, 23, 0, 0, 1, 3, 2, 9, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0 ],