1 use nihav_core::codecs::*;
2 use nihav_core::data::GenericCache;
3 use nihav_core::io::bitreader::*;
4 use super::vpcommon::*;
6 pub const TOKEN_LARGE: u8 = 5;
7 pub const TOKEN_EOB: u8 = 42;
9 #[derive(Clone,Copy,Debug,Default)]
11 pub struct VP56Header {
15 pub multistream: bool,
16 pub use_huffman: bool,
28 #[derive(Clone,Copy,Default)]
29 pub struct VP56MVModel {
32 pub raw_probs: [u8; 8],
33 pub tree_probs: [u8; 7],
36 #[derive(Clone,Copy,Default)]
37 pub struct VP56MBTypeModel {
41 #[derive(Clone,Copy,Default)]
42 pub struct VP56CoeffModel {
43 pub dc_token_probs: [[[u8; 5]; 6]; 6],
44 pub dc_value_probs: [u8; 11],
45 pub ac_ctype_probs: [[[[u8; 5]; 5]; 6]; 3],
46 pub ac_type_probs: [[[[u8; 5]; 6]; 3]; 3],
47 pub ac_val_probs: [[[u8; 11]; 6]; 3],
50 pub struct VP6Models {
51 pub scan_order: [usize; 64],
52 pub scan: [usize; 64],
53 pub zigzag: [usize; 64],
54 pub zero_run_probs: [[u8; 14]; 2],
57 const MAX_HUFF_ELEMS: usize = 12;
58 #[derive(Clone,Copy,Default)]
60 pub codes: [u16; MAX_HUFF_ELEMS],
61 pub bits: [u8; MAX_HUFF_ELEMS],
64 #[derive(Clone,Copy,Default)]
72 fn prob2weight(a: u8, b: u8) -> u8 {
73 let w = (((a as u16) * (b as u16)) >> 8) as u8;
82 fn build_codes(&mut self, probs: &[u8; 11]) {
83 let mut weights = [0u8; 12];
85 weights[11] = prob2weight( probs[0], probs[ 1]);
86 weights[ 0] = prob2weight( probs[0], !probs[ 1]);
87 weights[ 1] = prob2weight(!probs[0], probs[ 2]);
88 let lvroot = prob2weight(!probs[0], !probs[ 2]);
89 let tworoot = prob2weight( lvroot, probs[ 3]);
90 let hlroot = prob2weight( lvroot, !probs[ 3]);
91 weights[ 2] = prob2weight( tworoot, probs[ 4]);
92 let root34 = prob2weight( tworoot, !probs[ 4]);
93 weights[ 3] = prob2weight( root34, probs[ 5]);
94 weights[ 4] = prob2weight( root34, !probs[ 5]);
95 let c1root = prob2weight( hlroot, probs[ 6]);
96 let c34root = prob2weight( hlroot, !probs[ 6]);
97 weights[ 5] = prob2weight( c1root, probs[ 7]);
98 weights[ 6] = prob2weight( c1root, !probs[ 7]);
99 let c3root = prob2weight( c34root, probs[ 8]);
100 let c4root = prob2weight( c34root, !probs[ 8]);
101 weights[ 7] = prob2weight( c3root, probs[ 9]);
102 weights[ 8] = prob2weight( c3root, !probs[ 9]);
103 weights[ 9] = prob2weight( c4root, probs[10]);
104 weights[10] = prob2weight( c4root, !probs[10]);
106 self.build(&weights);
108 fn build_codes_zero_run(&mut self, probs: &[u8; 14]) {
109 let mut weights = [0u8; 9];
111 let root = prob2weight( probs[0], probs[1]);
112 weights[0] = prob2weight( root, probs[2]);
113 weights[1] = prob2weight( root, !probs[2]);
115 let root = prob2weight( probs[0], !probs[1]);
116 weights[2] = prob2weight( root, probs[3]);
117 weights[3] = prob2weight( root, !probs[3]);
119 let root = prob2weight(!probs[0], probs[4]);
120 weights[8] = prob2weight(!probs[0], !probs[4]);
121 let root1 = prob2weight( root, probs[5]);
122 let root2 = prob2weight( root, !probs[5]);
123 weights[4] = prob2weight( root1, probs[6]);
124 weights[5] = prob2weight( root1, !probs[6]);
125 weights[6] = prob2weight( root2, probs[7]);
126 weights[7] = prob2weight( root2, !probs[7]);
128 self.build(&weights);
130 fn build(&mut self, weights: &[u8]) {
131 let mut nodes = [Node::default(); MAX_HUFF_ELEMS * 2];
134 for w in weights.iter().rev() {
135 let weight = *w as u16;
138 if nodes[i].weight > weight {
143 for j in (pos..nlen).rev() {
144 nodes[j + 1] = nodes[j];
146 nodes[pos].weight = weight;
147 nodes[pos].sym = (weights.len() - nlen - 1) as i8;
154 weight: nodes[low + 0].weight + nodes[low + 1].weight,
161 while (pos < nlen) && (nodes[pos].weight < nnode.weight) {
164 for j in (pos..nlen).rev() {
165 nodes[j + 1] = nodes[j];
170 self.get_codes(&nodes, nlen - 1, 0, 0);
171 for i in nlen..self.codes.len() {
172 self.codes[i] = self.codes[0];
173 self.bits[i] = self.bits[0];
176 fn get_codes(&mut self, nodes: &[Node], pos: usize, code: u16, len: u8) {
177 if nodes[pos].sym >= 0 {
178 self.codes[nodes[pos].sym as usize] = code;
179 self.bits [nodes[pos].sym as usize] = len;
181 self.get_codes(nodes, nodes[pos].ch0, (code << 1) | 0, len + 1);
182 self.get_codes(nodes, nodes[pos].ch1, (code << 1) | 1, len + 1);
188 fn read_huff(&mut self, huff: &VP6Huff) -> DecoderResult<u8>;
191 impl<'a> ReadHuff for BitReader<'a> {
192 fn read_huff(&mut self, huff: &VP6Huff) -> DecoderResult<u8> {
193 let peekval = self.peek(16);
194 for (i, (code, bit)) in huff.codes.iter().zip(huff.bits.iter()).enumerate() {
195 if (peekval >> (16 - *bit)) == (*code as u32) {
196 self.skip(*bit as u32)?;
200 Err(DecoderError::InvalidData)
204 #[derive(Clone,Copy,Default)]
205 pub struct VP6HuffModels {
206 pub dc_token_tree: [VP6Huff; 2],
207 pub ac_token_tree: [[[VP6Huff; 6]; 3]; 2],
208 pub zero_run_tree: [VP6Huff; 2],
217 zero_run_probs: [[0; 14]; 2],
222 pub struct VP56Models {
223 pub mv_models: [VP56MVModel; 2],
224 pub mbtype_models: [[VP56MBTypeModel; 10]; 3],
225 pub coeff_models: [VP56CoeffModel; 2],
226 pub prob_xmitted: [[u8; 20]; 3],
227 pub vp6models: VP6Models,
228 pub vp6huff: VP6HuffModels,
234 mv_models: [VP56MVModel::default(); 2],
235 mbtype_models: [[VP56MBTypeModel::default(); 10]; 3],
236 coeff_models: [VP56CoeffModel::default(); 2],
237 prob_xmitted: [[0; 20]; 3],
238 vp6models: VP6Models::new(),
239 vp6huff: VP6HuffModels::default(),
244 pub trait VP56Parser {
245 fn parse_header(&mut self, bc: &mut BoolCoder) -> DecoderResult<VP56Header>;
246 fn reset_models(&self, models: &mut VP56Models);
247 fn decode_mv(&self, bc: &mut BoolCoder, model: &VP56MVModel) -> i16;
248 fn decode_mv_models(&self, bc: &mut BoolCoder, models: &mut [VP56MVModel; 2]) -> DecoderResult<()>;
249 fn decode_coeff_models(&self, bc: &mut BoolCoder, models: &mut VP56Models, is_intra: bool) -> DecoderResult<()>;
250 fn decode_block(&self, bc: &mut BoolCoder, coeffs: &mut [i16; 64], model: &VP56CoeffModel, vp6model: &VP6Models, fstate: &mut FrameState) -> DecoderResult<()>;
251 fn decode_block_huff(&self, br: &mut BitReader, coeffs: &mut [i16; 64], vp6model: &VP6Models, model: &VP6HuffModels, fstate: &mut FrameState) -> DecoderResult<()>;
252 fn mc_block(&self, dst: &mut NASimpleVideoFrame<u8>, mc_buf: NAVideoBufferRef<u8>, src: NAVideoBufferRef<u8>, plane: usize, x: usize, y: usize, mv: MV, loop_thr: i16);
255 enum CoeffReader<'a> {
261 #[derive(Clone,Copy,Default)]
267 pub struct FrameState {
271 pub coeff_cat: [[u8; 64]; 4],
272 pub last_idx: [usize; 4],
277 pub dc_zero_run: [usize; 2],
278 pub ac_zero_run: [usize; 2],
287 coeff_cat: [[0; 64]; 4],
299 pub struct VP56Decoder {
309 coeffs: [[i16; 64]; 6],
316 mb_info: Vec<MBInfo>,
318 dc_y: GenericCache<i16>,
319 dc_u: GenericCache<i16>,
320 dc_v: GenericCache<i16>,
321 dc_a: GenericCache<i16>,
322 last_dc: [[i16; 4]; 3],
323 top_ctx: [Vec<u8>; 4],
325 mc_buf: NAVideoBufferRef<u8>,
328 fn rescale_mb_mode_prob(prob: u32, total: u32) -> u8 {
329 (255 * prob / (1 + total)) as u8
332 fn map_mb_type(mbtype: VPMBType) -> usize {
334 VPMBType::InterNoMV => 0,
335 VPMBType::Intra => 1,
336 VPMBType::InterMV => 2,
337 VPMBType::InterNearest => 3,
338 VPMBType::InterNear => 4,
339 VPMBType::GoldenNoMV => 5,
340 VPMBType::GoldenMV => 6,
341 VPMBType::InterFourMV => 7,
342 VPMBType::GoldenNearest => 8,
343 VPMBType::GoldenNear => 9,
347 pub fn expand_token_bc(bc: &mut BoolCoder, val_probs: &[u8; 11], token: u8, version: u8) -> i16 {
348 let mut sign = false;
350 if token < TOKEN_LARGE {
352 sign = bc.read_bool();
354 level = token as i16;
356 let cat: usize = vp_tree!(bc, val_probs[6],
357 vp_tree!(bc, val_probs[7], 0, 1),
358 vp_tree!(bc, val_probs[8],
359 vp_tree!(bc, val_probs[9], 2, 3),
360 vp_tree!(bc, val_probs[10], 4, 5)));
362 sign = bc.read_bool();
365 let add_probs = &VP56_COEF_ADD_PROBS[cat];
366 for prob in add_probs.iter() {
367 if *prob == 128 { break; }
368 add = (add << 1) | (bc.read_prob(*prob) as i16);
371 sign = bc.read_bool();
373 level = VP56_COEF_BASE[cat] + add;
383 pub fn new(version: u8, has_alpha: bool, flip: bool) -> Self {
384 let vt = alloc_video_buffer(NAVideoInfo::new(24, 24, false, YUV420_FORMAT), 4).unwrap();
385 let mc_buf = vt.get_vbuf().unwrap();
387 version, has_alpha, flip,
388 shuf: VPShuffler::new(),
393 models: VP56Models::new(),
394 coeffs: [[0; 64]; 6],
395 last_mbt: VPMBType::InterNoMV,
402 fstate: FrameState::new(),
403 dc_y: GenericCache::new(0, 0, 0),
404 dc_u: GenericCache::new(0, 0, 0),
405 dc_v: GenericCache::new(0, 0, 0),
406 dc_a: GenericCache::new(0, 0, 0),
407 last_dc: [[0; 4]; 3],
408 top_ctx: [Vec::new(), Vec::new(), Vec::new(), Vec::new()],
413 fn set_dimensions(&mut self, width: usize, height: usize) {
415 self.height = height;
416 self.mb_w = (self.width + 15) >> 4;
417 self.mb_h = (self.height + 15) >> 4;
418 self.mb_info.resize(self.mb_w * self.mb_h, MBInfo::default());
419 self.dc_y = GenericCache::new(2, 1 + self.mb_w * 2, 0);
420 self.dc_u = GenericCache::new(1, 1 + self.mb_w, 0);
421 self.dc_v = GenericCache::new(1, 1 + self.mb_w, 0);
422 self.dc_a = GenericCache::new(2, 1 + self.mb_w * 2, 0);
423 self.top_ctx = [vec![0; self.mb_w * 2], vec![0; self.mb_w], vec![0; self.mb_w], vec![0; self.mb_w * 2]];
425 pub fn init(&mut self, supp: &mut NADecoderSupport, vinfo: NAVideoInfo) -> DecoderResult<()> {
426 supp.pool_u8.set_dec_bufs(3);
427 supp.pool_u8.prealloc_video(NAVideoInfo::new(vinfo.get_width(), vinfo.get_height(), false, vinfo.get_format()), 4)?;
428 self.set_dimensions(vinfo.get_width(), vinfo.get_height());
431 pub fn flush(&mut self) {
434 pub fn decode_frame(&mut self, supp: &mut NADecoderSupport, src: &[u8], br: &mut dyn VP56Parser) -> DecoderResult<(NABufferType, FrameType)> {
438 validate!(src.len() >= 7);
439 aoffset = ((src[0] as usize) << 16) | ((src[1] as usize) << 8) | (src[2] as usize);
440 validate!((aoffset > 0) && (aoffset < src.len() - 3));
441 bc = BoolCoder::new(&src[3..])?;
443 validate!(src.len() >= 4);
445 bc = BoolCoder::new(src)?;
447 let hdr = br.parse_header(&mut bc)?;
448 validate!((hdr.offset as usize) < aoffset); //XXX: take alpha 3 byte offset into account?
451 self.set_dimensions((hdr.mb_w as usize) * 16, (hdr.mb_h as usize) * 16);
453 let vinfo = NAVideoInfo::new(self.width, self.height, self.flip, YUV420_FORMAT);
454 let ret = supp.pool_u8.get_free();
456 return Err(DecoderError::AllocError);
458 let mut buf = ret.unwrap();
459 if buf.get_info() != vinfo {
461 supp.pool_u8.reset();
462 supp.pool_u8.prealloc_video(vinfo, 4)?;
463 let ret = supp.pool_u8.get_free();
465 return Err(DecoderError::AllocError);
469 let mut dframe = NASimpleVideoFrame::from_video_buf(&mut buf).unwrap();
474 if !self.shuf.has_refs() {
475 return Err(DecoderError::MissingReference);
481 let off = (if self.has_alpha { 3 } else { 0 }) + (hdr.offset as usize);
482 if !hdr.use_huffman {
483 let bc2 = BoolCoder::new(&src[off..])?;
484 cr = CoeffReader::Bool(bc2);
486 let br = BitReader::new(&src[off..], aoffset - off, BitReaderMode::BE);
487 cr = CoeffReader::Huff(br);
490 cr = CoeffReader::None;
494 br.reset_models(&mut self.models);
495 self.reset_mbtype_models();
497 self.decode_mode_prob_models(&mut bc)?;
498 br.decode_mv_models(&mut bc, &mut self.models.mv_models)?;
500 br.decode_coeff_models(&mut bc, &mut self.models, hdr.is_intra)?;
503 self.models.vp6huff.dc_token_tree[i].build_codes(&self.models.coeff_models[i].dc_value_probs);
508 self.models.vp6huff.ac_token_tree[i][mode][band].build_codes(&self.models.coeff_models[i].ac_val_probs[mode][band]);
513 self.models.vp6huff.zero_run_tree[i].build_codes_zero_run(&self.models.vp6models.zero_run_probs[i]);
518 self.ilace_prob = bc.read_bits(8) as u8;
521 self.fstate = FrameState::new();
522 self.fstate.dc_quant = VP56_DC_QUANTS[hdr.quant as usize] * 4;
523 self.fstate.ac_quant = VP56_AC_QUANTS[hdr.quant as usize] * 4;
524 self.loop_thr = VP56_FILTER_LIMITS[hdr.quant as usize] as i16;
526 self.last_mbt = VPMBType::InterNoMV;
531 for vec in self.top_ctx.iter_mut() {
532 for el in vec.iter_mut() {
536 self.last_dc = [[0; 4]; 3];
537 self.last_dc[0][1] = 0x80;
538 self.last_dc[0][2] = 0x80;
540 self.ilace_mb = false;
541 for mb_y in 0..self.mb_h {
542 self.fstate.mb_y = mb_y;
543 self.fstate.coeff_cat = [[0; 64]; 4];
544 self.fstate.last_idx = [24; 4];
545 for mb_x in 0..self.mb_w {
546 self.fstate.mb_x = mb_x;
547 self.decode_mb(&mut dframe, &mut bc, &mut cr, br, &hdr, false)?;
549 self.dc_y.update_row();
550 self.dc_u.update_row();
551 self.dc_v.update_row();
552 self.dc_a.update_row();
556 let asrc = &src[aoffset + 3..];
557 let mut bc = BoolCoder::new(asrc)?;
558 let ahdr = br.parse_header(&mut bc)?;
559 validate!(ahdr.mb_w == hdr.mb_w && ahdr.mb_h == hdr.mb_h);
563 self.shuf.add_golden_frame(buf.clone());
565 self.shuf.add_frame(buf.clone());
567 Ok((NABufferType::Video(buf), if hdr.is_intra { FrameType::I } else { FrameType::P }))
569 fn reset_mbtype_models(&mut self) {
570 const DEFAULT_XMITTED_PROBS: [[u8; 20]; 3] = [
571 [ 42, 69, 2, 1, 7, 1, 42, 44, 22, 6, 3, 1, 2, 0, 5, 1, 1, 0, 0, 0 ],
572 [ 8, 229, 1, 1, 8, 0, 0, 0, 0, 0, 2, 1, 1, 0, 0, 0, 1, 1, 0, 0 ],
573 [ 35, 122, 1, 1, 6, 1, 34, 46, 0, 0, 2, 1, 1, 0, 1, 0, 1, 1, 0, 0 ]
575 self.models.prob_xmitted.copy_from_slice(&DEFAULT_XMITTED_PROBS);
577 fn decode_mode_prob_models(&mut self, bc: &mut BoolCoder) -> DecoderResult<()> {
579 if bc.read_prob(174) {
580 let idx = bc.read_bits(4) as usize;
582 self.models.prob_xmitted[ctx][i ^ 1] = VP56_MODE_VQ[ctx][idx][i];
585 if bc.read_prob(254) {
587 if bc.read_prob(205) {
588 let sign = bc.read_bool();
589 let diff = vp_tree!(bc, 171,
590 vp_tree!(bc, 83, 2, 1),
594 vp_tree!(bc, 104, 6, 5),
601 validate!(diff < 256);
602 let diff = diff as u8;
604 validate!(self.models.prob_xmitted[ctx][set ^ 1] <= 255 - diff);
605 self.models.prob_xmitted[ctx][set ^ 1] += diff;
607 validate!(self.models.prob_xmitted[ctx][set ^ 1] >= diff);
608 self.models.prob_xmitted[ctx][set ^ 1] -= diff;
615 let prob_xmitted = &self.models.prob_xmitted[ctx];
617 let mdl = &mut self.models.mbtype_models[ctx][mode];
618 let mut cnt = [0u32; 10];
621 if i == mode { continue; }
622 cnt[i] = 100 * (prob_xmitted[i * 2] as u32);
625 let sum = (prob_xmitted[mode * 2] as u32) + (prob_xmitted[mode * 2 + 1] as u32);
626 mdl.probs[9] = 255 - rescale_mb_mode_prob(prob_xmitted[mode * 2 + 1] as u32, sum);
628 let inter_mv0_weight = (cnt[0] as u32) + (cnt[2] as u32);
629 let inter_mv1_weight = (cnt[3] as u32) + (cnt[4] as u32);
630 let gold_mv0_weight = (cnt[5] as u32) + (cnt[6] as u32);
631 let gold_mv1_weight = (cnt[8] as u32) + (cnt[9] as u32);
632 let mix_weight = (cnt[1] as u32) + (cnt[7] as u32);
633 mdl.probs[0] = 1 + rescale_mb_mode_prob(inter_mv0_weight + inter_mv1_weight, total);
634 mdl.probs[1] = 1 + rescale_mb_mode_prob(inter_mv0_weight, inter_mv0_weight + inter_mv1_weight);
635 mdl.probs[2] = 1 + rescale_mb_mode_prob(mix_weight, mix_weight + gold_mv0_weight + gold_mv1_weight);
636 mdl.probs[3] = 1 + rescale_mb_mode_prob(cnt[0] as u32, inter_mv0_weight);
637 mdl.probs[4] = 1 + rescale_mb_mode_prob(cnt[3] as u32, inter_mv1_weight);
638 mdl.probs[5] = 1 + rescale_mb_mode_prob(cnt[1], mix_weight);
639 mdl.probs[6] = 1 + rescale_mb_mode_prob(gold_mv0_weight, gold_mv0_weight + gold_mv1_weight);
640 mdl.probs[7] = 1 + rescale_mb_mode_prob(cnt[5], gold_mv0_weight);
641 mdl.probs[8] = 1 + rescale_mb_mode_prob(cnt[8], gold_mv1_weight);
646 fn find_mv_pred(&self, ref_id: u8) -> (usize, MV, MV, MV) {
647 const CAND_POS: [(i8, i8); 12] = [
656 let mut nearest_mv = ZERO_MV;
657 let mut near_mv = ZERO_MV;
658 let mut pred_mv = ZERO_MV;
659 let mut num_mv: usize = 0;
661 for (i, (yoff, xoff)) in CAND_POS.iter().enumerate() {
662 let cx = (self.fstate.mb_x as isize) + (*xoff as isize);
663 let cy = (self.fstate.mb_y as isize) + (*yoff as isize);
664 if (cx < 0) || (cy < 0) {
667 let cx = cx as usize;
668 let cy = cy as usize;
669 if (cx >= self.mb_w) || (cy >= self.mb_h) {
672 let mb_pos = cx + cy * self.mb_w;
673 let mv = self.mb_info[mb_pos].mv;
674 if (self.mb_info[mb_pos].mb_type.get_ref_id() != ref_id) || (mv == ZERO_MV) {
680 if (self.version > 5) && (i < 2) {
683 } else if mv != nearest_mv {
690 (num_mv, nearest_mv, near_mv, pred_mv)
692 fn decode_mv(&self, bc: &mut BoolCoder, br: &mut dyn VP56Parser) -> MV {
693 let x = br.decode_mv(bc, &self.models.mv_models[0]);
694 let y = br.decode_mv(bc, &self.models.mv_models[1]);
697 fn decode_mb_type(&mut self, bc: &mut BoolCoder, ctx: usize) -> DecoderResult<VPMBType> {
698 let probs = &self.models.mbtype_models[ctx][map_mb_type(self.last_mbt)].probs;
699 if !bc.read_prob(probs[9]) {
700 self.last_mbt = vp_tree!(
702 vp_tree!(bc, probs[1],
703 vp_tree!(bc, probs[3], VPMBType::InterNoMV, VPMBType::InterMV),
704 vp_tree!(bc, probs[4], VPMBType::InterNearest, VPMBType::InterNear)
706 vp_tree!(bc, probs[2],
707 vp_tree!(bc, probs[5], VPMBType::Intra, VPMBType::InterFourMV),
708 vp_tree!(bc, probs[6],
709 vp_tree!(bc, probs[7], VPMBType::GoldenNoMV, VPMBType::GoldenMV),
710 vp_tree!(bc, probs[8], VPMBType::InterNearest, VPMBType::InterNear)
717 fn decode_mb(&mut self, frm: &mut NASimpleVideoFrame<u8>, bc: &mut BoolCoder, cr: &mut CoeffReader, br: &mut dyn VP56Parser, hdr: &VP56Header, alpha: bool) -> DecoderResult<()> {
718 const FOURMV_SUB_TYPE: [VPMBType; 4] = [ VPMBType::InterNoMV, VPMBType::InterMV, VPMBType::InterNearest, VPMBType::InterNear ];
720 let mb_x = self.fstate.mb_x;
721 let mb_y = self.fstate.mb_y;
722 self.coeffs = [[0; 64]; 6];
723 let mb_pos = mb_x + mb_y * self.mb_w;
724 let mut four_mv = [ZERO_MV; 4];
725 let mut four_mbt = [VPMBType::Intra; 4];
728 let iprob = self.ilace_prob;
729 let prob = if mb_x == 0 {
731 } else if !self.ilace_mb {
732 iprob + (((256 - (iprob as u16)) >> 1) as u8)
736 self.ilace_mb = bc.read_prob(prob);
739 let (num_mv, nearest_mv, near_mv, pred_mv) = if hdr.is_intra {
740 (0, ZERO_MV, ZERO_MV, ZERO_MV)
741 } else { self.find_mv_pred(VP_REF_INTER) };
742 let mb_type = if hdr.is_intra {
745 self.decode_mb_type(bc, (num_mv + 1) % 3)?
747 self.mb_info[mb_pos].mb_type = mb_type;
748 if mb_type.get_ref_id() != VP_REF_GOLDEN {
751 VPMBType::InterNoMV => {
752 self.mb_info[mb_pos].mv = ZERO_MV;
754 VPMBType::InterMV => {
755 let diff_mv = self.decode_mv(bc, br);
756 self.mb_info[mb_pos].mv = pred_mv + diff_mv;
758 VPMBType::InterNearest => {
759 self.mb_info[mb_pos].mv = nearest_mv;
761 VPMBType::InterNear => {
762 self.mb_info[mb_pos].mv = near_mv;
764 VPMBType::InterFourMV => {
766 four_mbt[i] = FOURMV_SUB_TYPE[bc.read_bits(2) as usize];
770 VPMBType::InterNoMV => {},
771 VPMBType::InterMV => {
772 let diff_mv = self.decode_mv(bc, br);
773 four_mv[i] = pred_mv + diff_mv;
775 VPMBType::InterNearest => {
776 four_mv[i] = nearest_mv;
778 VPMBType::InterNear => {
779 four_mv[i] = near_mv;
784 self.mb_info[mb_pos].mv = four_mv[3];
789 let (_num_mv, nearest_mv, near_mv, pred_mv) = self.find_mv_pred(VP_REF_GOLDEN);
791 VPMBType::GoldenNoMV => {
792 self.mb_info[mb_pos].mv = ZERO_MV;
794 VPMBType::GoldenMV => {
795 let diff_mv = self.decode_mv(bc, br);
796 self.mb_info[mb_pos].mv = pred_mv + diff_mv;
798 VPMBType::GoldenNearest => {
799 self.mb_info[mb_pos].mv = nearest_mv;
801 VPMBType::GoldenNear => {
802 self.mb_info[mb_pos].mv = near_mv;
807 if !mb_type.is_intra() && (mb_type != VPMBType::InterFourMV) {
808 self.do_mc(br, frm, mb_type, self.mb_info[mb_pos].mv, alpha);
809 } else if mb_type == VPMBType::InterFourMV {
810 self.do_fourmv(br, frm, &four_mv, alpha);
814 self.fstate.plane = if !alpha { 0 } else { 3 };
815 self.fstate.ctx_idx = blk_no >> 1;
816 self.fstate.top_ctx = self.top_ctx[self.fstate.plane][mb_x * 2 + (blk_no & 1)];
818 CoeffReader::None => {
819 br.decode_block(bc, &mut self.coeffs[blk_no], &self.models.coeff_models[0], &self.models.vp6models, &mut self.fstate)?;
821 CoeffReader::Bool(ref mut bcc) => {
822 br.decode_block(bcc, &mut self.coeffs[blk_no], &self.models.coeff_models[0], &self.models.vp6models, &mut self.fstate)?;
824 CoeffReader::Huff(ref mut brc) => {
825 br.decode_block_huff(brc, &mut self.coeffs[blk_no], &self.models.vp6models, &self.models.vp6huff, &mut self.fstate)?;
828 self.top_ctx[self.fstate.plane][mb_x * 2 + (blk_no & 1)] = self.fstate.top_ctx;
829 self.predict_dc(mb_type, mb_pos, blk_no, alpha);
831 let bx = mb_x * 2 + (blk_no & 1);
832 let by = mb_y * 2 + (blk_no >> 1);
833 let has_ac = self.fstate.last_idx[self.fstate.ctx_idx] > 0;
834 if mb_type.is_intra() {
837 vp_put_block(&mut self.coeffs[blk_no], bx, by, self.fstate.plane, frm);
839 vp_put_block_dc(&mut self.coeffs[blk_no], bx, by, self.fstate.plane, frm);
842 vp_put_block_ilace(&mut self.coeffs[blk_no], bx, by, self.fstate.plane, frm);
847 vp_add_block(&mut self.coeffs[blk_no], bx, by, self.fstate.plane, frm);
849 vp_add_block_dc(&mut self.coeffs[blk_no], bx, by, self.fstate.plane, frm);
852 vp_add_block_ilace(&mut self.coeffs[blk_no], bx, by, self.fstate.plane, frm);
858 self.fstate.plane = blk_no - 3;
859 self.fstate.ctx_idx = blk_no - 2;
860 self.fstate.top_ctx = self.top_ctx[self.fstate.plane][mb_x];
862 CoeffReader::None => {
863 br.decode_block(bc, &mut self.coeffs[blk_no], &self.models.coeff_models[1], &self.models.vp6models, &mut self.fstate)?;
865 CoeffReader::Bool(ref mut bcc) => {
866 br.decode_block(bcc, &mut self.coeffs[blk_no], &self.models.coeff_models[1], &self.models.vp6models, &mut self.fstate)?;
868 CoeffReader::Huff(ref mut brc) => {
869 br.decode_block_huff(brc, &mut self.coeffs[blk_no], &self.models.vp6models, &self.models.vp6huff, &mut self.fstate)?;
872 self.top_ctx[self.fstate.plane][mb_x] = self.fstate.top_ctx;
873 self.predict_dc(mb_type, mb_pos, blk_no, alpha);
875 let has_ac = self.fstate.last_idx[self.fstate.ctx_idx] > 0;
876 if mb_type.is_intra() {
878 vp_put_block(&mut self.coeffs[blk_no], mb_x, mb_y, self.fstate.plane, frm);
880 vp_put_block_dc(&mut self.coeffs[blk_no], mb_x, mb_y, self.fstate.plane, frm);
884 vp_add_block(&mut self.coeffs[blk_no], mb_x, mb_y, self.fstate.plane, frm);
886 vp_add_block_dc(&mut self.coeffs[blk_no], mb_x, mb_y, self.fstate.plane, frm);
893 fn do_mc(&mut self, br: &dyn VP56Parser, frm: &mut NASimpleVideoFrame<u8>, mb_type: VPMBType, mv: MV, alpha: bool) {
894 let x = self.fstate.mb_x * 16;
895 let y = self.fstate.mb_y * 16;
896 let plane = if !alpha { 0 } else { 3 };
897 let src = if mb_type.get_ref_id() == VP_REF_INTER {
898 self.shuf.get_last().unwrap()
900 self.shuf.get_golden().unwrap()
903 br.mc_block(frm, self.mc_buf.clone(), src.clone(), plane, x + 0, y + 0, mv, self.loop_thr);
904 br.mc_block(frm, self.mc_buf.clone(), src.clone(), plane, x + 8, y + 0, mv, self.loop_thr);
905 br.mc_block(frm, self.mc_buf.clone(), src.clone(), plane, x + 0, y + 8, mv, self.loop_thr);
906 br.mc_block(frm, self.mc_buf.clone(), src.clone(), plane, x + 8, y + 8, mv, self.loop_thr);
908 let x = self.fstate.mb_x * 8;
909 let y = self.fstate.mb_y * 8;
910 br.mc_block(frm, self.mc_buf.clone(), src.clone(), 1, x, y, mv, self.loop_thr);
911 br.mc_block(frm, self.mc_buf.clone(), src.clone(), 2, x, y, mv, self.loop_thr);
914 fn do_fourmv(&mut self, br: &dyn VP56Parser, frm: &mut NASimpleVideoFrame<u8>, mvs: &[MV; 4], alpha: bool) {
915 let x = self.fstate.mb_x * 16;
916 let y = self.fstate.mb_y * 16;
917 let plane = if !alpha { 0 } else { 3 };
918 let src = self.shuf.get_last().unwrap();
920 br.mc_block(frm, self.mc_buf.clone(), src.clone(),
921 plane, x + (blk_no & 1) * 8, y + (blk_no & 2) * 4,
922 mvs[blk_no], self.loop_thr);
925 let x = self.fstate.mb_x * 8;
926 let y = self.fstate.mb_y * 8;
927 let sum = mvs[0] + mvs[1] + mvs[2] + mvs[3];
928 let mv = MV { x: sum.x / 4, y: sum.y / 4 };
929 br.mc_block(frm, self.mc_buf.clone(), src.clone(), 1, x, y, mv, self.loop_thr);
930 br.mc_block(frm, self.mc_buf.clone(), src.clone(), 2, x, y, mv, self.loop_thr);
933 fn predict_dc(&mut self, mb_type: VPMBType, mb_pos: usize, blk_no: usize, alpha: bool) {
934 let mb_x = self.fstate.mb_x;
935 let is_luma = blk_no < 4;
936 let (plane, dcs) = if alpha { (0, &mut self.dc_a) } else {
938 4 => (1, &mut self.dc_u),
939 5 => (2, &mut self.dc_v),
940 _ => (0, &mut self.dc_y),
943 let dc_pos = if is_luma {
944 dcs.xpos + mb_x * 2 + (blk_no & 1) + (blk_no >> 1) * dcs.stride
948 let ref_id = mb_type.get_ref_id();
949 let has_left_blk = is_luma && ((blk_no & 1) != 0);
950 let has_top_blk = is_luma && ((blk_no & 2) != 0);
953 if has_left_blk || ((mb_x > 0) && (self.mb_info[mb_pos - 1].mb_type.get_ref_id() == ref_id)) {
954 dc_pred += dcs.data[dc_pos - 1];
957 if has_top_blk || ((mb_pos >= self.mb_w) && (self.mb_info[mb_pos - self.mb_w].mb_type.get_ref_id() == ref_id)) {
958 dc_pred += dcs.data[dc_pos - dcs.stride];
961 if self.version == 5 {
962 if (count < 2) && has_left_blk {
966 if (count < 2) && !has_left_blk && has_top_blk && (mb_x > 0) && (self.mb_info[mb_pos - 1].mb_type.get_ref_id() == ref_id) {
970 if (count < 2) && mb_pos == 0 && !is_luma {
973 if (count < 2) && !has_left_blk && !has_top_blk && is_luma && (mb_x > 0) && (self.mb_info[mb_pos - 1].mb_type.get_ref_id() == ref_id) {
974 dc_pred += dcs.data[dc_pos + dcs.stride - 1];
977 if (count < 2) && blk_no == 2 {
978 dc_pred += dcs.data[dc_pos - dcs.stride + 1];
981 if (count < 2) && !has_left_blk && (mb_pos >= self.mb_w) && (self.mb_info[mb_pos - self.mb_w].mb_type.get_ref_id() == ref_id) {
982 dc_pred += dcs.data[dc_pos - dcs.stride + 1];
985 if (count < 2) && has_left_blk && (mb_pos > self.mb_w) && (mb_x < self.mb_w - 1) && (self.mb_info[mb_pos - self.mb_w + 1].mb_type.get_ref_id() == ref_id) {
986 dc_pred += dcs.data[dc_pos - dcs.stride + 1];
991 dc_pred = self.last_dc[ref_id as usize][plane];
992 } else if count == 2 {
995 self.coeffs[blk_no][0] += dc_pred;
996 self.last_dc[ref_id as usize][plane] = self.coeffs[blk_no][0];
997 dcs.data[dc_pos] = self.coeffs[blk_no][0];
998 self.coeffs[blk_no][0] = self.coeffs[blk_no][0].wrapping_mul(self.fstate.dc_quant);
1002 const VP56_DC_QUANTS: [i16; 64] = [
1003 47, 47, 47, 47, 45, 43, 43, 43,
1004 43, 43, 42, 41, 41, 40, 40, 40,
1005 40, 35, 35, 35, 35, 33, 33, 33,
1006 33, 32, 32, 32, 27, 27, 26, 26,
1007 25, 25, 24, 24, 23, 23, 19, 19,
1008 19, 19, 18, 18, 17, 16, 16, 16,
1009 16, 16, 15, 11, 11, 11, 10, 10,
1010 9, 8, 7, 5, 3, 3, 2, 2
1012 const VP56_AC_QUANTS: [i16; 64] = [
1013 94, 92, 90, 88, 86, 82, 78, 74,
1014 70, 66, 62, 58, 54, 53, 52, 51,
1015 50, 49, 48, 47, 46, 45, 44, 43,
1016 42, 40, 39, 37, 36, 35, 34, 33,
1017 32, 31, 30, 29, 28, 27, 26, 25,
1018 24, 23, 22, 21, 20, 19, 18, 17,
1019 16, 15, 14, 13, 12, 11, 10, 9,
1020 8, 7, 6, 5, 4, 3, 2, 1
1023 const VP56_FILTER_LIMITS: [u8; 64] = [
1024 14, 14, 13, 13, 12, 12, 10, 10,
1025 10, 10, 8, 8, 8, 8, 8, 8,
1026 8, 8, 8, 8, 8, 8, 8, 8,
1027 8, 8, 8, 8, 8, 8, 8, 8,
1028 8, 8, 8, 8, 7, 7, 7, 7,
1029 7, 7, 6, 6, 6, 6, 6, 6,
1030 5, 5, 5, 5, 4, 4, 4, 4,
1031 4, 4, 4, 3, 3, 3, 3, 2
1034 const VP56_MODE_VQ: [[[u8; 20]; 16]; 3] = [
1036 [ 9, 15, 32, 25, 7, 19, 9, 21, 1, 12, 14, 12, 3, 18, 14, 23, 3, 10, 0, 4 ],
1037 [ 48, 39, 1, 2, 11, 27, 29, 44, 7, 27, 1, 4, 0, 3, 1, 6, 1, 2, 0, 0 ],
1038 [ 21, 32, 1, 2, 4, 10, 32, 43, 6, 23, 2, 3, 1, 19, 1, 6, 12, 21, 0, 7 ],
1039 [ 69, 83, 0, 0, 0, 2, 10, 29, 3, 12, 0, 1, 0, 3, 0, 3, 2, 2, 0, 0 ],
1040 [ 11, 20, 1, 4, 18, 36, 43, 48, 13, 35, 0, 2, 0, 5, 3, 12, 1, 2, 0, 0 ],
1041 [ 70, 44, 0, 1, 2, 10, 37, 46, 8, 26, 0, 2, 0, 2, 0, 2, 0, 1, 0, 0 ],
1042 [ 8, 15, 0, 1, 8, 21, 74, 53, 22, 42, 0, 1, 0, 2, 0, 3, 1, 2, 0, 0 ],
1043 [ 141, 42, 0, 0, 1, 4, 11, 24, 1, 11, 0, 1, 0, 1, 0, 2, 0, 0, 0, 0 ],
1044 [ 8, 19, 4, 10, 24, 45, 21, 37, 9, 29, 0, 3, 1, 7, 11, 25, 0, 2, 0, 1 ],
1045 [ 46, 42, 0, 1, 2, 10, 54, 51, 10, 30, 0, 2, 0, 2, 0, 1, 0, 1, 0, 0 ],
1046 [ 28, 32, 0, 0, 3, 10, 75, 51, 14, 33, 0, 1, 0, 2, 0, 1, 1, 2, 0, 0 ],
1047 [ 100, 46, 0, 1, 3, 9, 21, 37, 5, 20, 0, 1, 0, 2, 1, 2, 0, 1, 0, 0 ],
1048 [ 27, 29, 0, 1, 9, 25, 53, 51, 12, 34, 0, 1, 0, 3, 1, 5, 0, 2, 0, 0 ],
1049 [ 80, 38, 0, 0, 1, 4, 69, 33, 5, 16, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0 ],
1050 [ 16, 20, 0, 0, 2, 8, 104, 49, 15, 33, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0 ],
1051 [ 194, 16, 0, 0, 1, 1, 1, 9, 1, 3, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0 ],
1053 [ 41, 22, 1, 0, 1, 31, 0, 0, 0, 0, 0, 1, 1, 7, 0, 1, 98, 25, 4, 10 ],
1054 [ 123, 37, 6, 4, 1, 27, 0, 0, 0, 0, 5, 8, 1, 7, 0, 1, 12, 10, 0, 2 ],
1055 [ 26, 14, 14, 12, 0, 24, 0, 0, 0, 0, 55, 17, 1, 9, 0, 36, 5, 7, 1, 3 ],
1056 [ 209, 5, 0, 0, 0, 27, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0 ],
1057 [ 2, 5, 4, 5, 0, 121, 0, 0, 0, 0, 0, 3, 2, 4, 1, 4, 2, 2, 0, 1 ],
1058 [ 175, 5, 0, 1, 0, 48, 0, 0, 0, 0, 0, 2, 0, 1, 0, 2, 0, 1, 0, 0 ],
1059 [ 83, 5, 2, 3, 0, 102, 0, 0, 0, 0, 1, 3, 0, 2, 0, 1, 0, 0, 0, 0 ],
1060 [ 233, 6, 0, 0, 0, 8, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0 ],
1061 [ 34, 16, 112, 21, 1, 28, 0, 0, 0, 0, 6, 8, 1, 7, 0, 3, 2, 5, 0, 2 ],
1062 [ 159, 35, 2, 2, 0, 25, 0, 0, 0, 0, 3, 6, 0, 5, 0, 1, 4, 4, 0, 1 ],
1063 [ 75, 39, 5, 7, 2, 48, 0, 0, 0, 0, 3, 11, 2, 16, 1, 4, 7, 10, 0, 2 ],
1064 [ 212, 21, 0, 1, 0, 9, 0, 0, 0, 0, 1, 2, 0, 2, 0, 0, 2, 2, 0, 0 ],
1065 [ 4, 2, 0, 0, 0, 172, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 2, 0, 0, 0 ],
1066 [ 187, 22, 1, 1, 0, 17, 0, 0, 0, 0, 3, 6, 0, 4, 0, 1, 4, 4, 0, 1 ],
1067 [ 133, 6, 1, 2, 1, 70, 0, 0, 0, 0, 0, 2, 0, 4, 0, 3, 1, 1, 0, 0 ],
1068 [ 251, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
1070 [ 2, 3, 2, 3, 0, 2, 0, 2, 0, 0, 11, 4, 1, 4, 0, 2, 3, 2, 0, 4 ],
1071 [ 49, 46, 3, 4, 7, 31, 42, 41, 0, 0, 2, 6, 1, 7, 1, 4, 2, 4, 0, 1 ],
1072 [ 26, 25, 1, 1, 2, 10, 67, 39, 0, 0, 1, 1, 0, 14, 0, 2, 31, 26, 1, 6 ],
1073 [ 103, 46, 1, 2, 2, 10, 33, 42, 0, 0, 1, 4, 0, 3, 0, 1, 1, 3, 0, 0 ],
1074 [ 14, 31, 9, 13, 14, 54, 22, 29, 0, 0, 2, 6, 4, 18, 6, 13, 1, 5, 0, 1 ],
1075 [ 85, 39, 0, 0, 1, 9, 69, 40, 0, 0, 0, 1, 0, 3, 0, 1, 2, 3, 0, 0 ],
1076 [ 31, 28, 0, 0, 3, 14, 130, 34, 0, 0, 0, 1, 0, 3, 0, 1, 3, 3, 0, 1 ],
1077 [ 171, 25, 0, 0, 1, 5, 25, 21, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0 ],
1078 [ 17, 21, 68, 29, 6, 15, 13, 22, 0, 0, 6, 12, 3, 14, 4, 10, 1, 7, 0, 3 ],
1079 [ 51, 39, 0, 1, 2, 12, 91, 44, 0, 0, 0, 2, 0, 3, 0, 1, 2, 3, 0, 1 ],
1080 [ 81, 25, 0, 0, 2, 9, 106, 26, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0 ],
1081 [ 140, 37, 0, 1, 1, 8, 24, 33, 0, 0, 1, 2, 0, 2, 0, 1, 1, 2, 0, 0 ],
1082 [ 14, 23, 1, 3, 11, 53, 90, 31, 0, 0, 0, 3, 1, 5, 2, 6, 1, 2, 0, 0 ],
1083 [ 123, 29, 0, 0, 1, 7, 57, 30, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0 ],
1084 [ 13, 14, 0, 0, 4, 20, 175, 20, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0 ],
1085 [ 202, 23, 0, 0, 1, 3, 2, 9, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0 ],