1 use nihav_core::codecs::*;
2 use nihav_core::io::bitreader::*;
3 use nihav_codec_support::codecs::{MV, ZERO_MV};
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 = ((u16::from(a) * u16::from(b)) >> 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 = u16::from(*w);
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)) == u32::from(*code) {
196 self.skip(u32::from(*bit))?;
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],
300 pub struct VP56DCPred {
314 const INVALID_REF: u8 = 42;
317 fn new() -> Self { Self::default() }
318 fn resize(&mut self, mb_w: usize) {
319 self.dc_y.resize(mb_w * 2 + 2, 0);
320 self.dc_u.resize(mb_w + 2, 0);
321 self.dc_v.resize(mb_w + 2, 0);
322 self.ref_y.resize(mb_w * 2 + 2, INVALID_REF);
323 self.ref_c.resize(mb_w + 2, INVALID_REF);
326 fn reset(&mut self) {
328 for el in self.ref_y.iter_mut().skip(1) { *el = INVALID_REF; }
329 for el in self.ref_c.iter_mut().skip(1) { *el = INVALID_REF; }
331 fn update_row(&mut self) {
337 self.ref_left = INVALID_REF;
339 fn next_mb(&mut self) {
345 pub struct VP56Decoder {
356 coeffs: [[i16; 64]; 6],
363 mb_info: Vec<MBInfo>,
366 last_dc: [[i16; 4]; 3],
367 top_ctx: [Vec<u8>; 4],
369 mc_buf: NAVideoBufferRef<u8>,
372 fn rescale_mb_mode_prob(prob: u32, total: u32) -> u8 {
373 (255 * prob / (1 + total)) as u8
376 fn map_mb_type(mbtype: VPMBType) -> usize {
378 VPMBType::InterNoMV => 0,
379 VPMBType::Intra => 1,
380 VPMBType::InterMV => 2,
381 VPMBType::InterNearest => 3,
382 VPMBType::InterNear => 4,
383 VPMBType::GoldenNoMV => 5,
384 VPMBType::GoldenMV => 6,
385 VPMBType::InterFourMV => 7,
386 VPMBType::GoldenNearest => 8,
387 VPMBType::GoldenNear => 9,
391 pub fn expand_token_bc(bc: &mut BoolCoder, val_probs: &[u8; 11], token: u8, version: u8) -> i16 {
392 let mut sign = false;
394 if token < TOKEN_LARGE {
396 sign = bc.read_bool();
398 level = i16::from(token);
400 let cat: usize = vp_tree!(bc, val_probs[6],
401 vp_tree!(bc, val_probs[7], 0, 1),
402 vp_tree!(bc, val_probs[8],
403 vp_tree!(bc, val_probs[9], 2, 3),
404 vp_tree!(bc, val_probs[10], 4, 5)));
406 sign = bc.read_bool();
409 let add_probs = &VP56_COEF_ADD_PROBS[cat];
410 for prob in add_probs.iter() {
411 if *prob == 128 { break; }
412 add = (add << 1) | (bc.read_prob(*prob) as i16);
415 sign = bc.read_bool();
417 level = VP56_COEF_BASE[cat] + add;
427 pub fn new(version: u8, has_alpha: bool, flip: bool) -> Self {
428 let vt = alloc_video_buffer(NAVideoInfo::new(24, 24, false, VP_YUVA420_FORMAT), 4).unwrap();
429 let mc_buf = vt.get_vbuf().unwrap();
431 version, has_alpha, flip,
432 shuf: VPShuffler::new(),
437 models: VP56Models::new(),
438 amodels: VP56Models::new(),
439 coeffs: [[0; 64]; 6],
440 last_mbt: VPMBType::InterNoMV,
447 fstate: FrameState::new(),
448 dc_pred: VP56DCPred::new(),
449 last_dc: [[0; 4]; 3],
450 top_ctx: [Vec::new(), Vec::new(), Vec::new(), Vec::new()],
455 fn set_dimensions(&mut self, width: usize, height: usize) {
457 self.height = height;
458 self.mb_w = (self.width + 15) >> 4;
459 self.mb_h = (self.height + 15) >> 4;
460 self.mb_info.resize(self.mb_w * self.mb_h, MBInfo::default());
461 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]];
463 pub fn init(&mut self, supp: &mut NADecoderSupport, vinfo: NAVideoInfo) -> DecoderResult<()> {
464 supp.pool_u8.set_dec_bufs(3);
465 supp.pool_u8.prealloc_video(NAVideoInfo::new(vinfo.get_width(), vinfo.get_height(), false, vinfo.get_format()), 4)?;
466 self.set_dimensions(vinfo.get_width(), vinfo.get_height());
467 self.dc_pred.resize(self.mb_w);
470 pub fn flush(&mut self) {
473 pub fn decode_frame(&mut self, supp: &mut NADecoderSupport, src: &[u8], br: &mut dyn VP56Parser) -> DecoderResult<(NABufferType, FrameType)> {
477 validate!(src.len() >= 7);
478 aoffset = ((src[0] as usize) << 16) | ((src[1] as usize) << 8) | (src[2] as usize);
479 validate!((aoffset > 0) && (aoffset < src.len() - 3));
480 bc = BoolCoder::new(&src[3..])?;
482 validate!(src.len() >= 4);
484 bc = BoolCoder::new(src)?;
486 let hdr = br.parse_header(&mut bc)?;
487 validate!((hdr.offset as usize) < aoffset); //XXX: take alpha 3 byte offset into account?
490 self.set_dimensions((hdr.mb_w as usize) * 16, (hdr.mb_h as usize) * 16);
492 let fmt = if !self.has_alpha {
497 let vinfo = NAVideoInfo::new(self.width, self.height, self.flip, fmt);
498 let ret = supp.pool_u8.get_free();
500 return Err(DecoderError::AllocError);
502 let mut buf = ret.unwrap();
503 if buf.get_info() != vinfo {
505 supp.pool_u8.reset();
506 supp.pool_u8.prealloc_video(vinfo, 4)?;
507 let ret = supp.pool_u8.get_free();
509 return Err(DecoderError::AllocError);
513 let mut dframe = NASimpleVideoFrame::from_video_buf(&mut buf).unwrap();
518 if !self.shuf.has_refs() {
519 return Err(DecoderError::MissingReference);
523 let psrc = &src[if self.has_alpha { 3 } else { 0 }..aoffset];
524 self.decode_planes(br, &mut dframe, &mut bc, &hdr, psrc, false)?;
527 let asrc = &src[aoffset + 3..];
528 let mut bc = BoolCoder::new(asrc)?;
529 let ahdr = br.parse_header(&mut bc)?;
530 validate!(ahdr.mb_w == hdr.mb_w && ahdr.mb_h == hdr.mb_h);
531 std::mem::swap(&mut self.models, &mut self.amodels);
532 let ret = self.decode_planes(br, &mut dframe, &mut bc, &ahdr, asrc, true);
533 std::mem::swap(&mut self.models, &mut self.amodels);
534 if let Err(err) = ret {
540 self.shuf.add_golden_frame(buf.clone());
542 self.shuf.add_frame(buf.clone());
544 Ok((NABufferType::Video(buf), if hdr.is_intra { FrameType::I } else { FrameType::P }))
546 fn decode_planes(&mut self, br: &mut dyn VP56Parser, dframe: &mut NASimpleVideoFrame<u8>, bc: &mut BoolCoder, hdr: &VP56Header, src: &[u8], alpha: bool) -> DecoderResult<()> {
549 let off = hdr.offset as usize;
550 if !hdr.use_huffman {
551 let bc2 = BoolCoder::new(&src[off..])?;
552 cr = CoeffReader::Bool(bc2);
554 let br = BitReader::new(&src[off..], BitReaderMode::BE);
555 cr = CoeffReader::Huff(br);
558 cr = CoeffReader::None;
562 br.reset_models(&mut self.models);
563 self.reset_mbtype_models();
565 self.decode_mode_prob_models(bc)?;
566 br.decode_mv_models(bc, &mut self.models.mv_models)?;
568 br.decode_coeff_models(bc, &mut self.models, hdr.is_intra)?;
571 self.models.vp6huff.dc_token_tree[i].build_codes(&self.models.coeff_models[i].dc_value_probs);
576 self.models.vp6huff.ac_token_tree[i][mode][band].build_codes(&self.models.coeff_models[i].ac_val_probs[mode][band]);
581 self.models.vp6huff.zero_run_tree[i].build_codes_zero_run(&self.models.vp6models.zero_run_probs[i]);
586 self.ilace_prob = bc.read_bits(8) as u8;
589 self.fstate = FrameState::new();
590 self.fstate.dc_quant = VP56_DC_QUANTS[hdr.quant as usize] * 4;
591 self.fstate.ac_quant = VP56_AC_QUANTS[hdr.quant as usize] * 4;
592 self.loop_thr = i16::from(VP56_FILTER_LIMITS[hdr.quant as usize]);
594 self.last_mbt = VPMBType::InterNoMV;
595 for vec in self.top_ctx.iter_mut() {
596 for el in vec.iter_mut() {
600 self.last_dc = [[0; 4]; 3];
601 self.last_dc[0][1] = 0x80;
602 self.last_dc[0][2] = 0x80;
603 self.dc_pred.reset();
605 self.ilace_mb = false;
606 for mb_y in 0..self.mb_h {
607 self.fstate.mb_y = mb_y;
608 self.fstate.coeff_cat = [[0; 64]; 4];
609 self.fstate.last_idx = [24; 4];
610 for mb_x in 0..self.mb_w {
611 self.fstate.mb_x = mb_x;
612 self.decode_mb(dframe, bc, &mut cr, br, &hdr, alpha)?;
613 self.dc_pred.next_mb();
615 self.dc_pred.update_row();
619 fn reset_mbtype_models(&mut self) {
620 const DEFAULT_XMITTED_PROBS: [[u8; 20]; 3] = [
621 [ 42, 69, 2, 1, 7, 1, 42, 44, 22, 6, 3, 1, 2, 0, 5, 1, 1, 0, 0, 0 ],
622 [ 8, 229, 1, 1, 8, 0, 0, 0, 0, 0, 2, 1, 1, 0, 0, 0, 1, 1, 0, 0 ],
623 [ 35, 122, 1, 1, 6, 1, 34, 46, 0, 0, 2, 1, 1, 0, 1, 0, 1, 1, 0, 0 ]
625 self.models.prob_xmitted.copy_from_slice(&DEFAULT_XMITTED_PROBS);
627 fn decode_mode_prob_models(&mut self, bc: &mut BoolCoder) -> DecoderResult<()> {
629 if bc.read_prob(174) {
630 let idx = bc.read_bits(4) as usize;
632 self.models.prob_xmitted[ctx][i ^ 1] = VP56_MODE_VQ[ctx][idx][i];
635 if bc.read_prob(254) {
637 if bc.read_prob(205) {
638 let sign = bc.read_bool();
639 let diff = vp_tree!(bc, 171,
640 vp_tree!(bc, 83, 2, 1),
644 vp_tree!(bc, 104, 6, 5),
651 validate!(diff < 256);
652 let diff = diff as u8;
654 validate!(self.models.prob_xmitted[ctx][set ^ 1] <= 255 - diff);
655 self.models.prob_xmitted[ctx][set ^ 1] += diff;
657 validate!(self.models.prob_xmitted[ctx][set ^ 1] >= diff);
658 self.models.prob_xmitted[ctx][set ^ 1] -= diff;
665 let prob_xmitted = &self.models.prob_xmitted[ctx];
667 let mdl = &mut self.models.mbtype_models[ctx][mode];
668 let mut cnt = [0u32; 10];
671 if i == mode { continue; }
672 cnt[i] = 100 * u32::from(prob_xmitted[i * 2]);
675 let sum = u32::from(prob_xmitted[mode * 2]) + u32::from(prob_xmitted[mode * 2 + 1]);
676 mdl.probs[9] = 255 - rescale_mb_mode_prob(u32::from(prob_xmitted[mode * 2 + 1]), sum);
678 let inter_mv0_weight = (cnt[0] as u32) + (cnt[2] as u32);
679 let inter_mv1_weight = (cnt[3] as u32) + (cnt[4] as u32);
680 let gold_mv0_weight = (cnt[5] as u32) + (cnt[6] as u32);
681 let gold_mv1_weight = (cnt[8] as u32) + (cnt[9] as u32);
682 let mix_weight = (cnt[1] as u32) + (cnt[7] as u32);
683 mdl.probs[0] = 1 + rescale_mb_mode_prob(inter_mv0_weight + inter_mv1_weight, total);
684 mdl.probs[1] = 1 + rescale_mb_mode_prob(inter_mv0_weight, inter_mv0_weight + inter_mv1_weight);
685 mdl.probs[2] = 1 + rescale_mb_mode_prob(mix_weight, mix_weight + gold_mv0_weight + gold_mv1_weight);
686 mdl.probs[3] = 1 + rescale_mb_mode_prob(cnt[0] as u32, inter_mv0_weight);
687 mdl.probs[4] = 1 + rescale_mb_mode_prob(cnt[3] as u32, inter_mv1_weight);
688 mdl.probs[5] = 1 + rescale_mb_mode_prob(cnt[1], mix_weight);
689 mdl.probs[6] = 1 + rescale_mb_mode_prob(gold_mv0_weight, gold_mv0_weight + gold_mv1_weight);
690 mdl.probs[7] = 1 + rescale_mb_mode_prob(cnt[5], gold_mv0_weight);
691 mdl.probs[8] = 1 + rescale_mb_mode_prob(cnt[8], gold_mv1_weight);
696 fn find_mv_pred(&self, ref_id: u8) -> (usize, MV, MV, MV) {
697 const CAND_POS: [(i8, i8); 12] = [
706 let mut nearest_mv = ZERO_MV;
707 let mut near_mv = ZERO_MV;
708 let mut pred_mv = ZERO_MV;
709 let mut num_mv: usize = 0;
711 for (i, (yoff, xoff)) in CAND_POS.iter().enumerate() {
712 let cx = (self.fstate.mb_x as isize) + (*xoff as isize);
713 let cy = (self.fstate.mb_y as isize) + (*yoff as isize);
714 if (cx < 0) || (cy < 0) {
717 let cx = cx as usize;
718 let cy = cy as usize;
719 if (cx >= self.mb_w) || (cy >= self.mb_h) {
722 let mb_pos = cx + cy * self.mb_w;
723 let mv = self.mb_info[mb_pos].mv;
724 if (self.mb_info[mb_pos].mb_type.get_ref_id() != ref_id) || (mv == ZERO_MV) {
730 if (self.version > 5) && (i < 2) {
733 } else if mv != nearest_mv {
740 (num_mv, nearest_mv, near_mv, pred_mv)
742 fn decode_mv(&self, bc: &mut BoolCoder, br: &mut dyn VP56Parser) -> MV {
743 let x = br.decode_mv(bc, &self.models.mv_models[0]);
744 let y = br.decode_mv(bc, &self.models.mv_models[1]);
747 fn decode_mb_type(&mut self, bc: &mut BoolCoder, ctx: usize) -> DecoderResult<VPMBType> {
748 let probs = &self.models.mbtype_models[ctx][map_mb_type(self.last_mbt)].probs;
749 if !bc.read_prob(probs[9]) {
750 self.last_mbt = vp_tree!(
752 vp_tree!(bc, probs[1],
753 vp_tree!(bc, probs[3], VPMBType::InterNoMV, VPMBType::InterMV),
754 vp_tree!(bc, probs[4], VPMBType::InterNearest, VPMBType::InterNear)
756 vp_tree!(bc, probs[2],
757 vp_tree!(bc, probs[5], VPMBType::Intra, VPMBType::InterFourMV),
758 vp_tree!(bc, probs[6],
759 vp_tree!(bc, probs[7], VPMBType::GoldenNoMV, VPMBType::GoldenMV),
760 vp_tree!(bc, probs[8], VPMBType::GoldenNearest, VPMBType::GoldenNear)
767 #[allow(clippy::cognitive_complexity)]
768 fn decode_mb(&mut self, frm: &mut NASimpleVideoFrame<u8>, bc: &mut BoolCoder, cr: &mut CoeffReader, br: &mut dyn VP56Parser, hdr: &VP56Header, alpha: bool) -> DecoderResult<()> {
769 const FOURMV_SUB_TYPE: [VPMBType; 4] = [ VPMBType::InterNoMV, VPMBType::InterMV, VPMBType::InterNearest, VPMBType::InterNear ];
771 let mb_x = self.fstate.mb_x;
772 let mb_y = self.fstate.mb_y;
773 self.coeffs = [[0; 64]; 6];
774 let mb_pos = mb_x + mb_y * self.mb_w;
775 let mut four_mv = [ZERO_MV; 4];
776 let mut four_mbt = [VPMBType::Intra; 4];
779 let iprob = self.ilace_prob;
780 let prob = if mb_x == 0 {
782 } else if !self.ilace_mb {
783 iprob + (((256 - u16::from(iprob)) >> 1) as u8)
787 self.ilace_mb = bc.read_prob(prob);
790 let (num_mv, nearest_mv, near_mv, pred_mv) = if hdr.is_intra {
791 (0, ZERO_MV, ZERO_MV, ZERO_MV)
792 } else { self.find_mv_pred(VP_REF_INTER) };
793 let mb_type = if hdr.is_intra {
796 self.decode_mb_type(bc, (num_mv + 1) % 3)?
798 self.mb_info[mb_pos].mb_type = mb_type;
799 if mb_type.get_ref_id() != VP_REF_GOLDEN {
802 VPMBType::InterNoMV => {
803 self.mb_info[mb_pos].mv = ZERO_MV;
805 VPMBType::InterMV => {
806 let diff_mv = self.decode_mv(bc, br);
807 self.mb_info[mb_pos].mv = pred_mv + diff_mv;
809 VPMBType::InterNearest => {
810 self.mb_info[mb_pos].mv = nearest_mv;
812 VPMBType::InterNear => {
813 self.mb_info[mb_pos].mv = near_mv;
815 VPMBType::InterFourMV => {
817 four_mbt[i] = FOURMV_SUB_TYPE[bc.read_bits(2) as usize];
821 VPMBType::InterNoMV => {},
822 VPMBType::InterMV => {
823 let diff_mv = self.decode_mv(bc, br);
824 four_mv[i] = pred_mv + diff_mv;
826 VPMBType::InterNearest => {
827 four_mv[i] = nearest_mv;
829 VPMBType::InterNear => {
830 four_mv[i] = near_mv;
835 self.mb_info[mb_pos].mv = four_mv[3];
840 let (_num_mv, nearest_mv, near_mv, pred_mv) = self.find_mv_pred(VP_REF_GOLDEN);
842 VPMBType::GoldenNoMV => {
843 self.mb_info[mb_pos].mv = ZERO_MV;
845 VPMBType::GoldenMV => {
846 let diff_mv = self.decode_mv(bc, br);
847 self.mb_info[mb_pos].mv = pred_mv + diff_mv;
849 VPMBType::GoldenNearest => {
850 self.mb_info[mb_pos].mv = nearest_mv;
852 VPMBType::GoldenNear => {
853 self.mb_info[mb_pos].mv = near_mv;
858 if !mb_type.is_intra() && (mb_type != VPMBType::InterFourMV) {
859 self.do_mc(br, frm, mb_type, self.mb_info[mb_pos].mv, alpha);
860 } else if mb_type == VPMBType::InterFourMV {
861 self.do_fourmv(br, frm, &four_mv, alpha);
865 self.fstate.plane = if !alpha { 0 } else { 3 };
866 self.fstate.ctx_idx = blk_no >> 1;
867 self.fstate.top_ctx = self.top_ctx[self.fstate.plane][mb_x * 2 + (blk_no & 1)];
869 CoeffReader::None => {
870 br.decode_block(bc, &mut self.coeffs[blk_no], &self.models.coeff_models[0], &self.models.vp6models, &mut self.fstate)?;
872 CoeffReader::Bool(ref mut bcc) => {
873 br.decode_block(bcc, &mut self.coeffs[blk_no], &self.models.coeff_models[0], &self.models.vp6models, &mut self.fstate)?;
875 CoeffReader::Huff(ref mut brc) => {
876 br.decode_block_huff(brc, &mut self.coeffs[blk_no], &self.models.vp6models, &self.models.vp6huff, &mut self.fstate)?;
879 self.top_ctx[self.fstate.plane][mb_x * 2 + (blk_no & 1)] = self.fstate.top_ctx;
880 self.predict_dc(mb_type, mb_pos, blk_no, alpha);
882 let bx = mb_x * 2 + (blk_no & 1);
883 let by = mb_y * 2 + (blk_no >> 1);
884 let has_ac = self.fstate.last_idx[self.fstate.ctx_idx] > 0;
885 if mb_type.is_intra() {
888 vp_put_block(&mut self.coeffs[blk_no], bx, by, self.fstate.plane, frm);
890 vp_put_block_dc(&mut self.coeffs[blk_no], bx, by, self.fstate.plane, frm);
893 vp_put_block_ilace(&mut self.coeffs[blk_no], bx, by, self.fstate.plane, frm);
898 vp_add_block(&mut self.coeffs[blk_no], bx, by, self.fstate.plane, frm);
900 vp_add_block_dc(&mut self.coeffs[blk_no], bx, by, self.fstate.plane, frm);
903 vp_add_block_ilace(&mut self.coeffs[blk_no], bx, by, self.fstate.plane, frm);
908 self.fstate.plane = blk_no - 3;
909 self.fstate.ctx_idx = blk_no - 2;
910 self.fstate.top_ctx = self.top_ctx[self.fstate.plane][mb_x];
912 CoeffReader::None => {
913 br.decode_block(bc, &mut self.coeffs[blk_no], &self.models.coeff_models[1], &self.models.vp6models, &mut self.fstate)?;
915 CoeffReader::Bool(ref mut bcc) => {
916 br.decode_block(bcc, &mut self.coeffs[blk_no], &self.models.coeff_models[1], &self.models.vp6models, &mut self.fstate)?;
918 CoeffReader::Huff(ref mut brc) => {
919 br.decode_block_huff(brc, &mut self.coeffs[blk_no], &self.models.vp6models, &self.models.vp6huff, &mut self.fstate)?;
922 self.top_ctx[self.fstate.plane][mb_x] = self.fstate.top_ctx;
923 self.predict_dc(mb_type, mb_pos, blk_no, alpha);
925 let has_ac = self.fstate.last_idx[self.fstate.ctx_idx] > 0;
926 if mb_type.is_intra() {
928 vp_put_block(&mut self.coeffs[blk_no], mb_x, mb_y, self.fstate.plane, frm);
930 vp_put_block_dc(&mut self.coeffs[blk_no], mb_x, mb_y, self.fstate.plane, frm);
934 vp_add_block(&mut self.coeffs[blk_no], mb_x, mb_y, self.fstate.plane, frm);
936 vp_add_block_dc(&mut self.coeffs[blk_no], mb_x, mb_y, self.fstate.plane, frm);
943 fn do_mc(&mut self, br: &dyn VP56Parser, frm: &mut NASimpleVideoFrame<u8>, mb_type: VPMBType, mv: MV, alpha: bool) {
944 let x = self.fstate.mb_x * 16;
945 let y = self.fstate.mb_y * 16;
946 let plane = if !alpha { 0 } else { 3 };
947 let src = if mb_type.get_ref_id() == VP_REF_INTER {
948 self.shuf.get_last().unwrap()
950 self.shuf.get_golden().unwrap()
953 br.mc_block(frm, self.mc_buf.clone(), src.clone(), plane, x + 0, y + 0, mv, self.loop_thr);
954 br.mc_block(frm, self.mc_buf.clone(), src.clone(), plane, x + 8, y + 0, mv, self.loop_thr);
955 br.mc_block(frm, self.mc_buf.clone(), src.clone(), plane, x + 0, y + 8, mv, self.loop_thr);
956 br.mc_block(frm, self.mc_buf.clone(), src.clone(), plane, x + 8, y + 8, mv, self.loop_thr);
958 let x = self.fstate.mb_x * 8;
959 let y = self.fstate.mb_y * 8;
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, 2, x, y, mv, self.loop_thr);
964 fn do_fourmv(&mut self, br: &dyn VP56Parser, frm: &mut NASimpleVideoFrame<u8>, mvs: &[MV; 4], alpha: bool) {
965 let x = self.fstate.mb_x * 16;
966 let y = self.fstate.mb_y * 16;
967 let plane = if !alpha { 0 } else { 3 };
968 let src = self.shuf.get_last().unwrap();
970 br.mc_block(frm, self.mc_buf.clone(), src.clone(),
971 plane, x + (blk_no & 1) * 8, y + (blk_no & 2) * 4,
972 mvs[blk_no], self.loop_thr);
975 let x = self.fstate.mb_x * 8;
976 let y = self.fstate.mb_y * 8;
977 let sum = mvs[0] + mvs[1] + mvs[2] + mvs[3];
978 let mv = MV { x: sum.x / 4, y: sum.y / 4 };
979 br.mc_block(frm, self.mc_buf.clone(), src.clone(), 1, x, y, mv, self.loop_thr);
980 br.mc_block(frm, self.mc_buf.clone(), src, 2, x, y, mv, self.loop_thr);
983 fn predict_dc(&mut self, mb_type: VPMBType, _mb_pos: usize, blk_no: usize, _alpha: bool) {
984 let is_luma = blk_no < 4;
985 let (plane, dcs) = match blk_no {
986 4 => (1, &mut self.dc_pred.dc_u),
987 5 => (2, &mut self.dc_pred.dc_v),
988 _ => (0, &mut self.dc_pred.dc_y),
990 let (dc_ref, dc_idx) = if is_luma {
991 (&mut self.dc_pred.ref_y, self.dc_pred.y_idx + (blk_no & 1))
993 (&mut self.dc_pred.ref_c, self.dc_pred.c_idx)
995 let ref_id = mb_type.get_ref_id();
998 let has_left_blk = is_luma && ((blk_no & 1) == 1);
999 if has_left_blk || self.dc_pred.ref_left == ref_id {
1000 dc_pred += match blk_no {
1001 0 | 1 => self.dc_pred.ldc_y[0],
1002 2 | 3 => self.dc_pred.ldc_y[1],
1003 4 => self.dc_pred.ldc_u,
1004 _ => self.dc_pred.ldc_v,
1008 if dc_ref[dc_idx] == ref_id {
1009 dc_pred += dcs[dc_idx];
1012 if self.version == 5 {
1013 if (count < 2) && (dc_ref[dc_idx - 1] == ref_id) {
1014 dc_pred += dcs[dc_idx - 1];
1017 if (count < 2) && (dc_ref[dc_idx + 1] == ref_id) {
1018 dc_pred += dcs[dc_idx + 1];
1023 dc_pred = self.last_dc[ref_id as usize][plane];
1024 } else if count == 2 {
1027 self.coeffs[blk_no][0] += dc_pred;
1029 let dc = self.coeffs[blk_no][0];
1030 if blk_no != 4 { // update top block reference only for the second chroma component
1031 dc_ref[dc_idx] = ref_id;
1035 self.dc_pred.ldc_y[0] = dc;
1038 self.dc_pred.ldc_y[1] = dc;
1041 self.dc_pred.ldc_u = dc;
1044 self.dc_pred.ldc_v = dc;
1045 self.dc_pred.ref_left = ref_id;
1050 self.last_dc[ref_id as usize][plane] = dc;
1051 self.coeffs[blk_no][0] = self.coeffs[blk_no][0].wrapping_mul(self.fstate.dc_quant);
1055 const VP56_DC_QUANTS: [i16; 64] = [
1056 47, 47, 47, 47, 45, 43, 43, 43,
1057 43, 43, 42, 41, 41, 40, 40, 40,
1058 40, 35, 35, 35, 35, 33, 33, 33,
1059 33, 32, 32, 32, 27, 27, 26, 26,
1060 25, 25, 24, 24, 23, 23, 19, 19,
1061 19, 19, 18, 18, 17, 16, 16, 16,
1062 16, 16, 15, 11, 11, 11, 10, 10,
1063 9, 8, 7, 5, 3, 3, 2, 2
1065 const VP56_AC_QUANTS: [i16; 64] = [
1066 94, 92, 90, 88, 86, 82, 78, 74,
1067 70, 66, 62, 58, 54, 53, 52, 51,
1068 50, 49, 48, 47, 46, 45, 44, 43,
1069 42, 40, 39, 37, 36, 35, 34, 33,
1070 32, 31, 30, 29, 28, 27, 26, 25,
1071 24, 23, 22, 21, 20, 19, 18, 17,
1072 16, 15, 14, 13, 12, 11, 10, 9,
1073 8, 7, 6, 5, 4, 3, 2, 1
1076 const VP56_FILTER_LIMITS: [u8; 64] = [
1077 14, 14, 13, 13, 12, 12, 10, 10,
1078 10, 10, 8, 8, 8, 8, 8, 8,
1079 8, 8, 8, 8, 8, 8, 8, 8,
1080 8, 8, 8, 8, 8, 8, 8, 8,
1081 8, 8, 8, 8, 7, 7, 7, 7,
1082 7, 7, 6, 6, 6, 6, 6, 6,
1083 5, 5, 5, 5, 4, 4, 4, 4,
1084 4, 4, 4, 3, 3, 3, 3, 2
1087 const VP56_MODE_VQ: [[[u8; 20]; 16]; 3] = [
1089 [ 9, 15, 32, 25, 7, 19, 9, 21, 1, 12, 14, 12, 3, 18, 14, 23, 3, 10, 0, 4 ],
1090 [ 48, 39, 1, 2, 11, 27, 29, 44, 7, 27, 1, 4, 0, 3, 1, 6, 1, 2, 0, 0 ],
1091 [ 21, 32, 1, 2, 4, 10, 32, 43, 6, 23, 2, 3, 1, 19, 1, 6, 12, 21, 0, 7 ],
1092 [ 69, 83, 0, 0, 0, 2, 10, 29, 3, 12, 0, 1, 0, 3, 0, 3, 2, 2, 0, 0 ],
1093 [ 11, 20, 1, 4, 18, 36, 43, 48, 13, 35, 0, 2, 0, 5, 3, 12, 1, 2, 0, 0 ],
1094 [ 70, 44, 0, 1, 2, 10, 37, 46, 8, 26, 0, 2, 0, 2, 0, 2, 0, 1, 0, 0 ],
1095 [ 8, 15, 0, 1, 8, 21, 74, 53, 22, 42, 0, 1, 0, 2, 0, 3, 1, 2, 0, 0 ],
1096 [ 141, 42, 0, 0, 1, 4, 11, 24, 1, 11, 0, 1, 0, 1, 0, 2, 0, 0, 0, 0 ],
1097 [ 8, 19, 4, 10, 24, 45, 21, 37, 9, 29, 0, 3, 1, 7, 11, 25, 0, 2, 0, 1 ],
1098 [ 46, 42, 0, 1, 2, 10, 54, 51, 10, 30, 0, 2, 0, 2, 0, 1, 0, 1, 0, 0 ],
1099 [ 28, 32, 0, 0, 3, 10, 75, 51, 14, 33, 0, 1, 0, 2, 0, 1, 1, 2, 0, 0 ],
1100 [ 100, 46, 0, 1, 3, 9, 21, 37, 5, 20, 0, 1, 0, 2, 1, 2, 0, 1, 0, 0 ],
1101 [ 27, 29, 0, 1, 9, 25, 53, 51, 12, 34, 0, 1, 0, 3, 1, 5, 0, 2, 0, 0 ],
1102 [ 80, 38, 0, 0, 1, 4, 69, 33, 5, 16, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0 ],
1103 [ 16, 20, 0, 0, 2, 8, 104, 49, 15, 33, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0 ],
1104 [ 194, 16, 0, 0, 1, 1, 1, 9, 1, 3, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0 ],
1106 [ 41, 22, 1, 0, 1, 31, 0, 0, 0, 0, 0, 1, 1, 7, 0, 1, 98, 25, 4, 10 ],
1107 [ 123, 37, 6, 4, 1, 27, 0, 0, 0, 0, 5, 8, 1, 7, 0, 1, 12, 10, 0, 2 ],
1108 [ 26, 14, 14, 12, 0, 24, 0, 0, 0, 0, 55, 17, 1, 9, 0, 36, 5, 7, 1, 3 ],
1109 [ 209, 5, 0, 0, 0, 27, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0 ],
1110 [ 2, 5, 4, 5, 0, 121, 0, 0, 0, 0, 0, 3, 2, 4, 1, 4, 2, 2, 0, 1 ],
1111 [ 175, 5, 0, 1, 0, 48, 0, 0, 0, 0, 0, 2, 0, 1, 0, 2, 0, 1, 0, 0 ],
1112 [ 83, 5, 2, 3, 0, 102, 0, 0, 0, 0, 1, 3, 0, 2, 0, 1, 0, 0, 0, 0 ],
1113 [ 233, 6, 0, 0, 0, 8, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0 ],
1114 [ 34, 16, 112, 21, 1, 28, 0, 0, 0, 0, 6, 8, 1, 7, 0, 3, 2, 5, 0, 2 ],
1115 [ 159, 35, 2, 2, 0, 25, 0, 0, 0, 0, 3, 6, 0, 5, 0, 1, 4, 4, 0, 1 ],
1116 [ 75, 39, 5, 7, 2, 48, 0, 0, 0, 0, 3, 11, 2, 16, 1, 4, 7, 10, 0, 2 ],
1117 [ 212, 21, 0, 1, 0, 9, 0, 0, 0, 0, 1, 2, 0, 2, 0, 0, 2, 2, 0, 0 ],
1118 [ 4, 2, 0, 0, 0, 172, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 2, 0, 0, 0 ],
1119 [ 187, 22, 1, 1, 0, 17, 0, 0, 0, 0, 3, 6, 0, 4, 0, 1, 4, 4, 0, 1 ],
1120 [ 133, 6, 1, 2, 1, 70, 0, 0, 0, 0, 0, 2, 0, 4, 0, 3, 1, 1, 0, 0 ],
1121 [ 251, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
1123 [ 2, 3, 2, 3, 0, 2, 0, 2, 0, 0, 11, 4, 1, 4, 0, 2, 3, 2, 0, 4 ],
1124 [ 49, 46, 3, 4, 7, 31, 42, 41, 0, 0, 2, 6, 1, 7, 1, 4, 2, 4, 0, 1 ],
1125 [ 26, 25, 1, 1, 2, 10, 67, 39, 0, 0, 1, 1, 0, 14, 0, 2, 31, 26, 1, 6 ],
1126 [ 103, 46, 1, 2, 2, 10, 33, 42, 0, 0, 1, 4, 0, 3, 0, 1, 1, 3, 0, 0 ],
1127 [ 14, 31, 9, 13, 14, 54, 22, 29, 0, 0, 2, 6, 4, 18, 6, 13, 1, 5, 0, 1 ],
1128 [ 85, 39, 0, 0, 1, 9, 69, 40, 0, 0, 0, 1, 0, 3, 0, 1, 2, 3, 0, 0 ],
1129 [ 31, 28, 0, 0, 3, 14, 130, 34, 0, 0, 0, 1, 0, 3, 0, 1, 3, 3, 0, 1 ],
1130 [ 171, 25, 0, 0, 1, 5, 25, 21, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0 ],
1131 [ 17, 21, 68, 29, 6, 15, 13, 22, 0, 0, 6, 12, 3, 14, 4, 10, 1, 7, 0, 3 ],
1132 [ 51, 39, 0, 1, 2, 12, 91, 44, 0, 0, 0, 2, 0, 3, 0, 1, 2, 3, 0, 1 ],
1133 [ 81, 25, 0, 0, 2, 9, 106, 26, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0 ],
1134 [ 140, 37, 0, 1, 1, 8, 24, 33, 0, 0, 1, 2, 0, 2, 0, 1, 1, 2, 0, 0 ],
1135 [ 14, 23, 1, 3, 11, 53, 90, 31, 0, 0, 0, 3, 1, 5, 2, 6, 1, 2, 0, 0 ],
1136 [ 123, 29, 0, 0, 1, 7, 57, 30, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0 ],
1137 [ 13, 14, 0, 0, 4, 20, 175, 20, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0 ],
1138 [ 202, 23, 0, 0, 1, 3, 2, 9, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0 ],