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 = (((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],
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 {
355 coeffs: [[i16; 64]; 6],
362 mb_info: Vec<MBInfo>,
365 last_dc: [[i16; 4]; 3],
366 top_ctx: [Vec<u8>; 4],
368 mc_buf: NAVideoBufferRef<u8>,
371 fn rescale_mb_mode_prob(prob: u32, total: u32) -> u8 {
372 (255 * prob / (1 + total)) as u8
375 fn map_mb_type(mbtype: VPMBType) -> usize {
377 VPMBType::InterNoMV => 0,
378 VPMBType::Intra => 1,
379 VPMBType::InterMV => 2,
380 VPMBType::InterNearest => 3,
381 VPMBType::InterNear => 4,
382 VPMBType::GoldenNoMV => 5,
383 VPMBType::GoldenMV => 6,
384 VPMBType::InterFourMV => 7,
385 VPMBType::GoldenNearest => 8,
386 VPMBType::GoldenNear => 9,
390 pub fn expand_token_bc(bc: &mut BoolCoder, val_probs: &[u8; 11], token: u8, version: u8) -> i16 {
391 let mut sign = false;
393 if token < TOKEN_LARGE {
395 sign = bc.read_bool();
397 level = token as i16;
399 let cat: usize = vp_tree!(bc, val_probs[6],
400 vp_tree!(bc, val_probs[7], 0, 1),
401 vp_tree!(bc, val_probs[8],
402 vp_tree!(bc, val_probs[9], 2, 3),
403 vp_tree!(bc, val_probs[10], 4, 5)));
405 sign = bc.read_bool();
408 let add_probs = &VP56_COEF_ADD_PROBS[cat];
409 for prob in add_probs.iter() {
410 if *prob == 128 { break; }
411 add = (add << 1) | (bc.read_prob(*prob) as i16);
414 sign = bc.read_bool();
416 level = VP56_COEF_BASE[cat] + add;
426 pub fn new(version: u8, has_alpha: bool, flip: bool) -> Self {
427 let vt = alloc_video_buffer(NAVideoInfo::new(24, 24, false, VP_YUVA420_FORMAT), 4).unwrap();
428 let mc_buf = vt.get_vbuf().unwrap();
430 version, has_alpha, flip,
431 shuf: VPShuffler::new(),
436 models: VP56Models::new(),
437 coeffs: [[0; 64]; 6],
438 last_mbt: VPMBType::InterNoMV,
445 fstate: FrameState::new(),
446 dc_pred: VP56DCPred::new(),
447 last_dc: [[0; 4]; 3],
448 top_ctx: [Vec::new(), Vec::new(), Vec::new(), Vec::new()],
453 fn set_dimensions(&mut self, width: usize, height: usize) {
455 self.height = height;
456 self.mb_w = (self.width + 15) >> 4;
457 self.mb_h = (self.height + 15) >> 4;
458 self.mb_info.resize(self.mb_w * self.mb_h, MBInfo::default());
459 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]];
461 pub fn init(&mut self, supp: &mut NADecoderSupport, vinfo: NAVideoInfo) -> DecoderResult<()> {
462 supp.pool_u8.set_dec_bufs(3);
463 supp.pool_u8.prealloc_video(NAVideoInfo::new(vinfo.get_width(), vinfo.get_height(), false, vinfo.get_format()), 4)?;
464 self.set_dimensions(vinfo.get_width(), vinfo.get_height());
465 self.dc_pred.resize(self.mb_w);
468 pub fn flush(&mut self) {
471 pub fn decode_frame(&mut self, supp: &mut NADecoderSupport, src: &[u8], br: &mut dyn VP56Parser) -> DecoderResult<(NABufferType, FrameType)> {
475 validate!(src.len() >= 7);
476 aoffset = ((src[0] as usize) << 16) | ((src[1] as usize) << 8) | (src[2] as usize);
477 validate!((aoffset > 0) && (aoffset < src.len() - 3));
478 bc = BoolCoder::new(&src[3..])?;
480 validate!(src.len() >= 4);
482 bc = BoolCoder::new(src)?;
484 let hdr = br.parse_header(&mut bc)?;
485 validate!((hdr.offset as usize) < aoffset); //XXX: take alpha 3 byte offset into account?
488 self.set_dimensions((hdr.mb_w as usize) * 16, (hdr.mb_h as usize) * 16);
490 let fmt = if !self.has_alpha {
495 let vinfo = NAVideoInfo::new(self.width, self.height, self.flip, fmt);
496 let ret = supp.pool_u8.get_free();
498 return Err(DecoderError::AllocError);
500 let mut buf = ret.unwrap();
501 if buf.get_info() != vinfo {
503 supp.pool_u8.reset();
504 supp.pool_u8.prealloc_video(vinfo, 4)?;
505 let ret = supp.pool_u8.get_free();
507 return Err(DecoderError::AllocError);
511 let mut dframe = NASimpleVideoFrame::from_video_buf(&mut buf).unwrap();
516 if !self.shuf.has_refs() {
517 return Err(DecoderError::MissingReference);
523 let off = (if self.has_alpha { 3 } else { 0 }) + (hdr.offset as usize);
524 if !hdr.use_huffman {
525 let bc2 = BoolCoder::new(&src[off..])?;
526 cr = CoeffReader::Bool(bc2);
528 let br = BitReader::new(&src[off..aoffset], BitReaderMode::BE);
529 cr = CoeffReader::Huff(br);
532 cr = CoeffReader::None;
536 br.reset_models(&mut self.models);
537 self.reset_mbtype_models();
539 self.decode_mode_prob_models(&mut bc)?;
540 br.decode_mv_models(&mut bc, &mut self.models.mv_models)?;
542 br.decode_coeff_models(&mut bc, &mut self.models, hdr.is_intra)?;
545 self.models.vp6huff.dc_token_tree[i].build_codes(&self.models.coeff_models[i].dc_value_probs);
550 self.models.vp6huff.ac_token_tree[i][mode][band].build_codes(&self.models.coeff_models[i].ac_val_probs[mode][band]);
555 self.models.vp6huff.zero_run_tree[i].build_codes_zero_run(&self.models.vp6models.zero_run_probs[i]);
560 self.ilace_prob = bc.read_bits(8) as u8;
563 self.fstate = FrameState::new();
564 self.fstate.dc_quant = VP56_DC_QUANTS[hdr.quant as usize] * 4;
565 self.fstate.ac_quant = VP56_AC_QUANTS[hdr.quant as usize] * 4;
566 self.loop_thr = VP56_FILTER_LIMITS[hdr.quant as usize] as i16;
568 self.last_mbt = VPMBType::InterNoMV;
569 for vec in self.top_ctx.iter_mut() {
570 for el in vec.iter_mut() {
574 self.last_dc = [[0; 4]; 3];
575 self.last_dc[0][1] = 0x80;
576 self.last_dc[0][2] = 0x80;
577 self.dc_pred.reset();
579 self.ilace_mb = false;
580 for mb_y in 0..self.mb_h {
581 self.fstate.mb_y = mb_y;
582 self.fstate.coeff_cat = [[0; 64]; 4];
583 self.fstate.last_idx = [24; 4];
584 for mb_x in 0..self.mb_w {
585 self.fstate.mb_x = mb_x;
586 self.decode_mb(&mut dframe, &mut bc, &mut cr, br, &hdr, false)?;
587 self.dc_pred.next_mb();
589 self.dc_pred.update_row();
593 let asrc = &src[aoffset + 3..];
594 let mut bc = BoolCoder::new(asrc)?;
595 let ahdr = br.parse_header(&mut bc)?;
596 validate!(ahdr.mb_w == hdr.mb_w && ahdr.mb_h == hdr.mb_h);
600 self.shuf.add_golden_frame(buf.clone());
602 self.shuf.add_frame(buf.clone());
604 Ok((NABufferType::Video(buf), if hdr.is_intra { FrameType::I } else { FrameType::P }))
606 fn reset_mbtype_models(&mut self) {
607 const DEFAULT_XMITTED_PROBS: [[u8; 20]; 3] = [
608 [ 42, 69, 2, 1, 7, 1, 42, 44, 22, 6, 3, 1, 2, 0, 5, 1, 1, 0, 0, 0 ],
609 [ 8, 229, 1, 1, 8, 0, 0, 0, 0, 0, 2, 1, 1, 0, 0, 0, 1, 1, 0, 0 ],
610 [ 35, 122, 1, 1, 6, 1, 34, 46, 0, 0, 2, 1, 1, 0, 1, 0, 1, 1, 0, 0 ]
612 self.models.prob_xmitted.copy_from_slice(&DEFAULT_XMITTED_PROBS);
614 fn decode_mode_prob_models(&mut self, bc: &mut BoolCoder) -> DecoderResult<()> {
616 if bc.read_prob(174) {
617 let idx = bc.read_bits(4) as usize;
619 self.models.prob_xmitted[ctx][i ^ 1] = VP56_MODE_VQ[ctx][idx][i];
622 if bc.read_prob(254) {
624 if bc.read_prob(205) {
625 let sign = bc.read_bool();
626 let diff = vp_tree!(bc, 171,
627 vp_tree!(bc, 83, 2, 1),
631 vp_tree!(bc, 104, 6, 5),
638 validate!(diff < 256);
639 let diff = diff as u8;
641 validate!(self.models.prob_xmitted[ctx][set ^ 1] <= 255 - diff);
642 self.models.prob_xmitted[ctx][set ^ 1] += diff;
644 validate!(self.models.prob_xmitted[ctx][set ^ 1] >= diff);
645 self.models.prob_xmitted[ctx][set ^ 1] -= diff;
652 let prob_xmitted = &self.models.prob_xmitted[ctx];
654 let mdl = &mut self.models.mbtype_models[ctx][mode];
655 let mut cnt = [0u32; 10];
658 if i == mode { continue; }
659 cnt[i] = 100 * (prob_xmitted[i * 2] as u32);
662 let sum = (prob_xmitted[mode * 2] as u32) + (prob_xmitted[mode * 2 + 1] as u32);
663 mdl.probs[9] = 255 - rescale_mb_mode_prob(prob_xmitted[mode * 2 + 1] as u32, sum);
665 let inter_mv0_weight = (cnt[0] as u32) + (cnt[2] as u32);
666 let inter_mv1_weight = (cnt[3] as u32) + (cnt[4] as u32);
667 let gold_mv0_weight = (cnt[5] as u32) + (cnt[6] as u32);
668 let gold_mv1_weight = (cnt[8] as u32) + (cnt[9] as u32);
669 let mix_weight = (cnt[1] as u32) + (cnt[7] as u32);
670 mdl.probs[0] = 1 + rescale_mb_mode_prob(inter_mv0_weight + inter_mv1_weight, total);
671 mdl.probs[1] = 1 + rescale_mb_mode_prob(inter_mv0_weight, inter_mv0_weight + inter_mv1_weight);
672 mdl.probs[2] = 1 + rescale_mb_mode_prob(mix_weight, mix_weight + gold_mv0_weight + gold_mv1_weight);
673 mdl.probs[3] = 1 + rescale_mb_mode_prob(cnt[0] as u32, inter_mv0_weight);
674 mdl.probs[4] = 1 + rescale_mb_mode_prob(cnt[3] as u32, inter_mv1_weight);
675 mdl.probs[5] = 1 + rescale_mb_mode_prob(cnt[1], mix_weight);
676 mdl.probs[6] = 1 + rescale_mb_mode_prob(gold_mv0_weight, gold_mv0_weight + gold_mv1_weight);
677 mdl.probs[7] = 1 + rescale_mb_mode_prob(cnt[5], gold_mv0_weight);
678 mdl.probs[8] = 1 + rescale_mb_mode_prob(cnt[8], gold_mv1_weight);
683 fn find_mv_pred(&self, ref_id: u8) -> (usize, MV, MV, MV) {
684 const CAND_POS: [(i8, i8); 12] = [
693 let mut nearest_mv = ZERO_MV;
694 let mut near_mv = ZERO_MV;
695 let mut pred_mv = ZERO_MV;
696 let mut num_mv: usize = 0;
698 for (i, (yoff, xoff)) in CAND_POS.iter().enumerate() {
699 let cx = (self.fstate.mb_x as isize) + (*xoff as isize);
700 let cy = (self.fstate.mb_y as isize) + (*yoff as isize);
701 if (cx < 0) || (cy < 0) {
704 let cx = cx as usize;
705 let cy = cy as usize;
706 if (cx >= self.mb_w) || (cy >= self.mb_h) {
709 let mb_pos = cx + cy * self.mb_w;
710 let mv = self.mb_info[mb_pos].mv;
711 if (self.mb_info[mb_pos].mb_type.get_ref_id() != ref_id) || (mv == ZERO_MV) {
717 if (self.version > 5) && (i < 2) {
720 } else if mv != nearest_mv {
727 (num_mv, nearest_mv, near_mv, pred_mv)
729 fn decode_mv(&self, bc: &mut BoolCoder, br: &mut dyn VP56Parser) -> MV {
730 let x = br.decode_mv(bc, &self.models.mv_models[0]);
731 let y = br.decode_mv(bc, &self.models.mv_models[1]);
734 fn decode_mb_type(&mut self, bc: &mut BoolCoder, ctx: usize) -> DecoderResult<VPMBType> {
735 let probs = &self.models.mbtype_models[ctx][map_mb_type(self.last_mbt)].probs;
736 if !bc.read_prob(probs[9]) {
737 self.last_mbt = vp_tree!(
739 vp_tree!(bc, probs[1],
740 vp_tree!(bc, probs[3], VPMBType::InterNoMV, VPMBType::InterMV),
741 vp_tree!(bc, probs[4], VPMBType::InterNearest, VPMBType::InterNear)
743 vp_tree!(bc, probs[2],
744 vp_tree!(bc, probs[5], VPMBType::Intra, VPMBType::InterFourMV),
745 vp_tree!(bc, probs[6],
746 vp_tree!(bc, probs[7], VPMBType::GoldenNoMV, VPMBType::GoldenMV),
747 vp_tree!(bc, probs[8], VPMBType::GoldenNearest, VPMBType::GoldenNear)
754 fn decode_mb(&mut self, frm: &mut NASimpleVideoFrame<u8>, bc: &mut BoolCoder, cr: &mut CoeffReader, br: &mut dyn VP56Parser, hdr: &VP56Header, alpha: bool) -> DecoderResult<()> {
755 const FOURMV_SUB_TYPE: [VPMBType; 4] = [ VPMBType::InterNoMV, VPMBType::InterMV, VPMBType::InterNearest, VPMBType::InterNear ];
757 let mb_x = self.fstate.mb_x;
758 let mb_y = self.fstate.mb_y;
759 self.coeffs = [[0; 64]; 6];
760 let mb_pos = mb_x + mb_y * self.mb_w;
761 let mut four_mv = [ZERO_MV; 4];
762 let mut four_mbt = [VPMBType::Intra; 4];
765 let iprob = self.ilace_prob;
766 let prob = if mb_x == 0 {
768 } else if !self.ilace_mb {
769 iprob + (((256 - (iprob as u16)) >> 1) as u8)
773 self.ilace_mb = bc.read_prob(prob);
776 let (num_mv, nearest_mv, near_mv, pred_mv) = if hdr.is_intra {
777 (0, ZERO_MV, ZERO_MV, ZERO_MV)
778 } else { self.find_mv_pred(VP_REF_INTER) };
779 let mb_type = if hdr.is_intra {
782 self.decode_mb_type(bc, (num_mv + 1) % 3)?
784 self.mb_info[mb_pos].mb_type = mb_type;
785 if mb_type.get_ref_id() != VP_REF_GOLDEN {
788 VPMBType::InterNoMV => {
789 self.mb_info[mb_pos].mv = ZERO_MV;
791 VPMBType::InterMV => {
792 let diff_mv = self.decode_mv(bc, br);
793 self.mb_info[mb_pos].mv = pred_mv + diff_mv;
795 VPMBType::InterNearest => {
796 self.mb_info[mb_pos].mv = nearest_mv;
798 VPMBType::InterNear => {
799 self.mb_info[mb_pos].mv = near_mv;
801 VPMBType::InterFourMV => {
803 four_mbt[i] = FOURMV_SUB_TYPE[bc.read_bits(2) as usize];
807 VPMBType::InterNoMV => {},
808 VPMBType::InterMV => {
809 let diff_mv = self.decode_mv(bc, br);
810 four_mv[i] = pred_mv + diff_mv;
812 VPMBType::InterNearest => {
813 four_mv[i] = nearest_mv;
815 VPMBType::InterNear => {
816 four_mv[i] = near_mv;
821 self.mb_info[mb_pos].mv = four_mv[3];
826 let (_num_mv, nearest_mv, near_mv, pred_mv) = self.find_mv_pred(VP_REF_GOLDEN);
828 VPMBType::GoldenNoMV => {
829 self.mb_info[mb_pos].mv = ZERO_MV;
831 VPMBType::GoldenMV => {
832 let diff_mv = self.decode_mv(bc, br);
833 self.mb_info[mb_pos].mv = pred_mv + diff_mv;
835 VPMBType::GoldenNearest => {
836 self.mb_info[mb_pos].mv = nearest_mv;
838 VPMBType::GoldenNear => {
839 self.mb_info[mb_pos].mv = near_mv;
844 if !mb_type.is_intra() && (mb_type != VPMBType::InterFourMV) {
845 self.do_mc(br, frm, mb_type, self.mb_info[mb_pos].mv, alpha);
846 } else if mb_type == VPMBType::InterFourMV {
847 self.do_fourmv(br, frm, &four_mv, alpha);
851 self.fstate.plane = if !alpha { 0 } else { 3 };
852 self.fstate.ctx_idx = blk_no >> 1;
853 self.fstate.top_ctx = self.top_ctx[self.fstate.plane][mb_x * 2 + (blk_no & 1)];
855 CoeffReader::None => {
856 br.decode_block(bc, &mut self.coeffs[blk_no], &self.models.coeff_models[0], &self.models.vp6models, &mut self.fstate)?;
858 CoeffReader::Bool(ref mut bcc) => {
859 br.decode_block(bcc, &mut self.coeffs[blk_no], &self.models.coeff_models[0], &self.models.vp6models, &mut self.fstate)?;
861 CoeffReader::Huff(ref mut brc) => {
862 br.decode_block_huff(brc, &mut self.coeffs[blk_no], &self.models.vp6models, &self.models.vp6huff, &mut self.fstate)?;
865 self.top_ctx[self.fstate.plane][mb_x * 2 + (blk_no & 1)] = self.fstate.top_ctx;
866 self.predict_dc(mb_type, mb_pos, blk_no, alpha);
868 let bx = mb_x * 2 + (blk_no & 1);
869 let by = mb_y * 2 + (blk_no >> 1);
870 let has_ac = self.fstate.last_idx[self.fstate.ctx_idx] > 0;
871 if mb_type.is_intra() {
874 vp_put_block(&mut self.coeffs[blk_no], bx, by, self.fstate.plane, frm);
876 vp_put_block_dc(&mut self.coeffs[blk_no], bx, by, self.fstate.plane, frm);
879 vp_put_block_ilace(&mut self.coeffs[blk_no], bx, by, self.fstate.plane, frm);
884 vp_add_block(&mut self.coeffs[blk_no], bx, by, self.fstate.plane, frm);
886 vp_add_block_dc(&mut self.coeffs[blk_no], bx, by, self.fstate.plane, frm);
889 vp_add_block_ilace(&mut self.coeffs[blk_no], bx, by, self.fstate.plane, frm);
895 self.fstate.plane = blk_no - 3;
896 self.fstate.ctx_idx = blk_no - 2;
897 self.fstate.top_ctx = self.top_ctx[self.fstate.plane][mb_x];
899 CoeffReader::None => {
900 br.decode_block(bc, &mut self.coeffs[blk_no], &self.models.coeff_models[1], &self.models.vp6models, &mut self.fstate)?;
902 CoeffReader::Bool(ref mut bcc) => {
903 br.decode_block(bcc, &mut self.coeffs[blk_no], &self.models.coeff_models[1], &self.models.vp6models, &mut self.fstate)?;
905 CoeffReader::Huff(ref mut brc) => {
906 br.decode_block_huff(brc, &mut self.coeffs[blk_no], &self.models.vp6models, &self.models.vp6huff, &mut self.fstate)?;
909 self.top_ctx[self.fstate.plane][mb_x] = self.fstate.top_ctx;
910 self.predict_dc(mb_type, mb_pos, blk_no, alpha);
912 let has_ac = self.fstate.last_idx[self.fstate.ctx_idx] > 0;
913 if mb_type.is_intra() {
915 vp_put_block(&mut self.coeffs[blk_no], mb_x, mb_y, self.fstate.plane, frm);
917 vp_put_block_dc(&mut self.coeffs[blk_no], mb_x, mb_y, self.fstate.plane, frm);
921 vp_add_block(&mut self.coeffs[blk_no], mb_x, mb_y, self.fstate.plane, frm);
923 vp_add_block_dc(&mut self.coeffs[blk_no], mb_x, mb_y, self.fstate.plane, frm);
930 fn do_mc(&mut self, br: &dyn VP56Parser, frm: &mut NASimpleVideoFrame<u8>, mb_type: VPMBType, mv: MV, alpha: bool) {
931 let x = self.fstate.mb_x * 16;
932 let y = self.fstate.mb_y * 16;
933 let plane = if !alpha { 0 } else { 3 };
934 let src = if mb_type.get_ref_id() == VP_REF_INTER {
935 self.shuf.get_last().unwrap()
937 self.shuf.get_golden().unwrap()
940 br.mc_block(frm, self.mc_buf.clone(), src.clone(), plane, x + 0, y + 0, mv, self.loop_thr);
941 br.mc_block(frm, self.mc_buf.clone(), src.clone(), plane, x + 8, y + 0, mv, self.loop_thr);
942 br.mc_block(frm, self.mc_buf.clone(), src.clone(), plane, x + 0, y + 8, mv, self.loop_thr);
943 br.mc_block(frm, self.mc_buf.clone(), src.clone(), plane, x + 8, y + 8, mv, self.loop_thr);
945 let x = self.fstate.mb_x * 8;
946 let y = self.fstate.mb_y * 8;
947 br.mc_block(frm, self.mc_buf.clone(), src.clone(), 1, x, y, mv, self.loop_thr);
948 br.mc_block(frm, self.mc_buf.clone(), src.clone(), 2, x, y, mv, self.loop_thr);
951 fn do_fourmv(&mut self, br: &dyn VP56Parser, frm: &mut NASimpleVideoFrame<u8>, mvs: &[MV; 4], alpha: bool) {
952 let x = self.fstate.mb_x * 16;
953 let y = self.fstate.mb_y * 16;
954 let plane = if !alpha { 0 } else { 3 };
955 let src = self.shuf.get_last().unwrap();
957 br.mc_block(frm, self.mc_buf.clone(), src.clone(),
958 plane, x + (blk_no & 1) * 8, y + (blk_no & 2) * 4,
959 mvs[blk_no], self.loop_thr);
962 let x = self.fstate.mb_x * 8;
963 let y = self.fstate.mb_y * 8;
964 let sum = mvs[0] + mvs[1] + mvs[2] + mvs[3];
965 let mv = MV { x: sum.x / 4, y: sum.y / 4 };
966 br.mc_block(frm, self.mc_buf.clone(), src.clone(), 1, x, y, mv, self.loop_thr);
967 br.mc_block(frm, self.mc_buf.clone(), src.clone(), 2, x, y, mv, self.loop_thr);
970 fn predict_dc(&mut self, mb_type: VPMBType, _mb_pos: usize, blk_no: usize, _alpha: bool) {
971 let is_luma = blk_no < 4;
972 let (plane, dcs) = match blk_no {
973 4 => (1, &mut self.dc_pred.dc_u),
974 5 => (2, &mut self.dc_pred.dc_v),
975 _ => (0, &mut self.dc_pred.dc_y),
977 let (dc_ref, dc_idx) = if is_luma {
978 (&mut self.dc_pred.ref_y, self.dc_pred.y_idx + (blk_no & 1))
980 (&mut self.dc_pred.ref_c, self.dc_pred.c_idx)
982 let ref_id = mb_type.get_ref_id();
985 let has_left_blk = is_luma && ((blk_no & 1) == 1);
986 if has_left_blk || self.dc_pred.ref_left == ref_id {
987 dc_pred += match blk_no {
988 0 | 1 => self.dc_pred.ldc_y[0],
989 2 | 3 => self.dc_pred.ldc_y[1],
990 4 => self.dc_pred.ldc_u,
991 _ => self.dc_pred.ldc_v,
995 if dc_ref[dc_idx] == ref_id {
996 dc_pred += dcs[dc_idx];
999 if self.version == 5 {
1000 if (count < 2) && (dc_ref[dc_idx - 1] == ref_id) {
1001 dc_pred += dcs[dc_idx - 1];
1004 if (count < 2) && (dc_ref[dc_idx + 1] == ref_id) {
1005 dc_pred += dcs[dc_idx + 1];
1010 dc_pred = self.last_dc[ref_id as usize][plane];
1011 } else if count == 2 {
1014 self.coeffs[blk_no][0] += dc_pred;
1016 let dc = self.coeffs[blk_no][0];
1017 if blk_no != 4 { // update top block reference only for the second chroma component
1018 dc_ref[dc_idx] = ref_id;
1022 self.dc_pred.ldc_y[0] = dc;
1025 self.dc_pred.ldc_y[1] = dc;
1028 self.dc_pred.ldc_u = dc;
1031 self.dc_pred.ldc_v = dc;
1032 self.dc_pred.ref_left = ref_id;
1037 self.last_dc[ref_id as usize][plane] = dc;
1038 self.coeffs[blk_no][0] = self.coeffs[blk_no][0].wrapping_mul(self.fstate.dc_quant);
1042 const VP56_DC_QUANTS: [i16; 64] = [
1043 47, 47, 47, 47, 45, 43, 43, 43,
1044 43, 43, 42, 41, 41, 40, 40, 40,
1045 40, 35, 35, 35, 35, 33, 33, 33,
1046 33, 32, 32, 32, 27, 27, 26, 26,
1047 25, 25, 24, 24, 23, 23, 19, 19,
1048 19, 19, 18, 18, 17, 16, 16, 16,
1049 16, 16, 15, 11, 11, 11, 10, 10,
1050 9, 8, 7, 5, 3, 3, 2, 2
1052 const VP56_AC_QUANTS: [i16; 64] = [
1053 94, 92, 90, 88, 86, 82, 78, 74,
1054 70, 66, 62, 58, 54, 53, 52, 51,
1055 50, 49, 48, 47, 46, 45, 44, 43,
1056 42, 40, 39, 37, 36, 35, 34, 33,
1057 32, 31, 30, 29, 28, 27, 26, 25,
1058 24, 23, 22, 21, 20, 19, 18, 17,
1059 16, 15, 14, 13, 12, 11, 10, 9,
1060 8, 7, 6, 5, 4, 3, 2, 1
1063 const VP56_FILTER_LIMITS: [u8; 64] = [
1064 14, 14, 13, 13, 12, 12, 10, 10,
1065 10, 10, 8, 8, 8, 8, 8, 8,
1066 8, 8, 8, 8, 8, 8, 8, 8,
1067 8, 8, 8, 8, 8, 8, 8, 8,
1068 8, 8, 8, 8, 7, 7, 7, 7,
1069 7, 7, 6, 6, 6, 6, 6, 6,
1070 5, 5, 5, 5, 4, 4, 4, 4,
1071 4, 4, 4, 3, 3, 3, 3, 2
1074 const VP56_MODE_VQ: [[[u8; 20]; 16]; 3] = [
1076 [ 9, 15, 32, 25, 7, 19, 9, 21, 1, 12, 14, 12, 3, 18, 14, 23, 3, 10, 0, 4 ],
1077 [ 48, 39, 1, 2, 11, 27, 29, 44, 7, 27, 1, 4, 0, 3, 1, 6, 1, 2, 0, 0 ],
1078 [ 21, 32, 1, 2, 4, 10, 32, 43, 6, 23, 2, 3, 1, 19, 1, 6, 12, 21, 0, 7 ],
1079 [ 69, 83, 0, 0, 0, 2, 10, 29, 3, 12, 0, 1, 0, 3, 0, 3, 2, 2, 0, 0 ],
1080 [ 11, 20, 1, 4, 18, 36, 43, 48, 13, 35, 0, 2, 0, 5, 3, 12, 1, 2, 0, 0 ],
1081 [ 70, 44, 0, 1, 2, 10, 37, 46, 8, 26, 0, 2, 0, 2, 0, 2, 0, 1, 0, 0 ],
1082 [ 8, 15, 0, 1, 8, 21, 74, 53, 22, 42, 0, 1, 0, 2, 0, 3, 1, 2, 0, 0 ],
1083 [ 141, 42, 0, 0, 1, 4, 11, 24, 1, 11, 0, 1, 0, 1, 0, 2, 0, 0, 0, 0 ],
1084 [ 8, 19, 4, 10, 24, 45, 21, 37, 9, 29, 0, 3, 1, 7, 11, 25, 0, 2, 0, 1 ],
1085 [ 46, 42, 0, 1, 2, 10, 54, 51, 10, 30, 0, 2, 0, 2, 0, 1, 0, 1, 0, 0 ],
1086 [ 28, 32, 0, 0, 3, 10, 75, 51, 14, 33, 0, 1, 0, 2, 0, 1, 1, 2, 0, 0 ],
1087 [ 100, 46, 0, 1, 3, 9, 21, 37, 5, 20, 0, 1, 0, 2, 1, 2, 0, 1, 0, 0 ],
1088 [ 27, 29, 0, 1, 9, 25, 53, 51, 12, 34, 0, 1, 0, 3, 1, 5, 0, 2, 0, 0 ],
1089 [ 80, 38, 0, 0, 1, 4, 69, 33, 5, 16, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0 ],
1090 [ 16, 20, 0, 0, 2, 8, 104, 49, 15, 33, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0 ],
1091 [ 194, 16, 0, 0, 1, 1, 1, 9, 1, 3, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0 ],
1093 [ 41, 22, 1, 0, 1, 31, 0, 0, 0, 0, 0, 1, 1, 7, 0, 1, 98, 25, 4, 10 ],
1094 [ 123, 37, 6, 4, 1, 27, 0, 0, 0, 0, 5, 8, 1, 7, 0, 1, 12, 10, 0, 2 ],
1095 [ 26, 14, 14, 12, 0, 24, 0, 0, 0, 0, 55, 17, 1, 9, 0, 36, 5, 7, 1, 3 ],
1096 [ 209, 5, 0, 0, 0, 27, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0 ],
1097 [ 2, 5, 4, 5, 0, 121, 0, 0, 0, 0, 0, 3, 2, 4, 1, 4, 2, 2, 0, 1 ],
1098 [ 175, 5, 0, 1, 0, 48, 0, 0, 0, 0, 0, 2, 0, 1, 0, 2, 0, 1, 0, 0 ],
1099 [ 83, 5, 2, 3, 0, 102, 0, 0, 0, 0, 1, 3, 0, 2, 0, 1, 0, 0, 0, 0 ],
1100 [ 233, 6, 0, 0, 0, 8, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0 ],
1101 [ 34, 16, 112, 21, 1, 28, 0, 0, 0, 0, 6, 8, 1, 7, 0, 3, 2, 5, 0, 2 ],
1102 [ 159, 35, 2, 2, 0, 25, 0, 0, 0, 0, 3, 6, 0, 5, 0, 1, 4, 4, 0, 1 ],
1103 [ 75, 39, 5, 7, 2, 48, 0, 0, 0, 0, 3, 11, 2, 16, 1, 4, 7, 10, 0, 2 ],
1104 [ 212, 21, 0, 1, 0, 9, 0, 0, 0, 0, 1, 2, 0, 2, 0, 0, 2, 2, 0, 0 ],
1105 [ 4, 2, 0, 0, 0, 172, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 2, 0, 0, 0 ],
1106 [ 187, 22, 1, 1, 0, 17, 0, 0, 0, 0, 3, 6, 0, 4, 0, 1, 4, 4, 0, 1 ],
1107 [ 133, 6, 1, 2, 1, 70, 0, 0, 0, 0, 0, 2, 0, 4, 0, 3, 1, 1, 0, 0 ],
1108 [ 251, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
1110 [ 2, 3, 2, 3, 0, 2, 0, 2, 0, 0, 11, 4, 1, 4, 0, 2, 3, 2, 0, 4 ],
1111 [ 49, 46, 3, 4, 7, 31, 42, 41, 0, 0, 2, 6, 1, 7, 1, 4, 2, 4, 0, 1 ],
1112 [ 26, 25, 1, 1, 2, 10, 67, 39, 0, 0, 1, 1, 0, 14, 0, 2, 31, 26, 1, 6 ],
1113 [ 103, 46, 1, 2, 2, 10, 33, 42, 0, 0, 1, 4, 0, 3, 0, 1, 1, 3, 0, 0 ],
1114 [ 14, 31, 9, 13, 14, 54, 22, 29, 0, 0, 2, 6, 4, 18, 6, 13, 1, 5, 0, 1 ],
1115 [ 85, 39, 0, 0, 1, 9, 69, 40, 0, 0, 0, 1, 0, 3, 0, 1, 2, 3, 0, 0 ],
1116 [ 31, 28, 0, 0, 3, 14, 130, 34, 0, 0, 0, 1, 0, 3, 0, 1, 3, 3, 0, 1 ],
1117 [ 171, 25, 0, 0, 1, 5, 25, 21, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0 ],
1118 [ 17, 21, 68, 29, 6, 15, 13, 22, 0, 0, 6, 12, 3, 14, 4, 10, 1, 7, 0, 3 ],
1119 [ 51, 39, 0, 1, 2, 12, 91, 44, 0, 0, 0, 2, 0, 3, 0, 1, 2, 3, 0, 1 ],
1120 [ 81, 25, 0, 0, 2, 9, 106, 26, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0 ],
1121 [ 140, 37, 0, 1, 1, 8, 24, 33, 0, 0, 1, 2, 0, 2, 0, 1, 1, 2, 0, 0 ],
1122 [ 14, 23, 1, 3, 11, 53, 90, 31, 0, 0, 0, 3, 1, 5, 2, 6, 1, 2, 0, 0 ],
1123 [ 123, 29, 0, 0, 1, 7, 57, 30, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0 ],
1124 [ 13, 14, 0, 0, 4, 20, 175, 20, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0 ],
1125 [ 202, 23, 0, 0, 1, 3, 2, 9, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0 ],