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 decode_frame(&mut self, supp: &mut NADecoderSupport, src: &[u8], br: &mut dyn VP56Parser) -> DecoderResult<(NABufferType, FrameType)> {
435 validate!(src.len() >= 7);
436 aoffset = ((src[0] as usize) << 16) | ((src[1] as usize) << 8) | (src[2] as usize);
437 validate!((aoffset > 0) && (aoffset < src.len() - 3));
438 bc = BoolCoder::new(&src[3..])?;
440 validate!(src.len() >= 4);
442 bc = BoolCoder::new(src)?;
444 let hdr = br.parse_header(&mut bc)?;
445 validate!((hdr.offset as usize) < aoffset); //XXX: take alpha 3 byte offset into account?
448 self.set_dimensions((hdr.mb_w as usize) * 16, (hdr.mb_h as usize) * 16);
450 let vinfo = NAVideoInfo::new(self.width, self.height, self.flip, YUV420_FORMAT);
451 let ret = supp.pool_u8.get_free();
453 return Err(DecoderError::AllocError);
455 let mut buf = ret.unwrap();
456 if buf.get_info() != vinfo {
458 supp.pool_u8.reset();
459 supp.pool_u8.prealloc_video(vinfo, 4)?;
460 let ret = supp.pool_u8.get_free();
462 return Err(DecoderError::AllocError);
466 let mut dframe = NASimpleVideoFrame::from_video_buf(&mut buf).unwrap();
474 let off = (if self.has_alpha { 3 } else { 0 }) + (hdr.offset as usize);
475 if !hdr.use_huffman {
476 let bc2 = BoolCoder::new(&src[off..])?;
477 cr = CoeffReader::Bool(bc2);
479 let br = BitReader::new(&src[off..], aoffset - off, BitReaderMode::BE);
480 cr = CoeffReader::Huff(br);
483 cr = CoeffReader::None;
487 br.reset_models(&mut self.models);
488 self.reset_mbtype_models();
490 self.decode_mode_prob_models(&mut bc)?;
491 br.decode_mv_models(&mut bc, &mut self.models.mv_models)?;
493 br.decode_coeff_models(&mut bc, &mut self.models, hdr.is_intra)?;
496 self.models.vp6huff.dc_token_tree[i].build_codes(&self.models.coeff_models[i].dc_value_probs);
501 self.models.vp6huff.ac_token_tree[i][mode][band].build_codes(&self.models.coeff_models[i].ac_val_probs[mode][band]);
506 self.models.vp6huff.zero_run_tree[i].build_codes_zero_run(&self.models.vp6models.zero_run_probs[i]);
511 self.ilace_prob = bc.read_bits(8) as u8;
514 self.fstate = FrameState::new();
515 self.fstate.dc_quant = VP56_DC_QUANTS[hdr.quant as usize] * 4;
516 self.fstate.ac_quant = VP56_AC_QUANTS[hdr.quant as usize] * 4;
517 self.loop_thr = VP56_FILTER_LIMITS[hdr.quant as usize] as i16;
519 self.last_mbt = VPMBType::InterNoMV;
524 for vec in self.top_ctx.iter_mut() {
525 for el in vec.iter_mut() {
529 self.last_dc = [[0; 4]; 3];
530 self.last_dc[0][1] = 0x80;
531 self.last_dc[0][2] = 0x80;
533 self.ilace_mb = false;
534 for mb_y in 0..self.mb_h {
535 self.fstate.mb_y = mb_y;
536 self.fstate.coeff_cat = [[0; 64]; 4];
537 self.fstate.last_idx = [24; 4];
538 for mb_x in 0..self.mb_w {
539 self.fstate.mb_x = mb_x;
540 self.decode_mb(&mut dframe, &mut bc, &mut cr, br, &hdr, false)?;
542 self.dc_y.update_row();
543 self.dc_u.update_row();
544 self.dc_v.update_row();
545 self.dc_a.update_row();
549 let asrc = &src[aoffset + 3..];
550 let mut bc = BoolCoder::new(asrc)?;
551 let ahdr = br.parse_header(&mut bc)?;
552 validate!(ahdr.mb_w == hdr.mb_w && ahdr.mb_h == hdr.mb_h);
556 self.shuf.add_golden_frame(buf.clone());
558 self.shuf.add_frame(buf.clone());
560 Ok((NABufferType::Video(buf), if hdr.is_intra { FrameType::I } else { FrameType::P }))
562 fn reset_mbtype_models(&mut self) {
563 const DEFAULT_XMITTED_PROBS: [[u8; 20]; 3] = [
564 [ 42, 69, 2, 1, 7, 1, 42, 44, 22, 6, 3, 1, 2, 0, 5, 1, 1, 0, 0, 0 ],
565 [ 8, 229, 1, 1, 8, 0, 0, 0, 0, 0, 2, 1, 1, 0, 0, 0, 1, 1, 0, 0 ],
566 [ 35, 122, 1, 1, 6, 1, 34, 46, 0, 0, 2, 1, 1, 0, 1, 0, 1, 1, 0, 0 ]
568 self.models.prob_xmitted.copy_from_slice(&DEFAULT_XMITTED_PROBS);
570 fn decode_mode_prob_models(&mut self, bc: &mut BoolCoder) -> DecoderResult<()> {
572 if bc.read_prob(174) {
573 let idx = bc.read_bits(4) as usize;
575 self.models.prob_xmitted[ctx][i ^ 1] = VP56_MODE_VQ[ctx][idx][i];
578 if bc.read_prob(254) {
580 if bc.read_prob(205) {
581 let sign = bc.read_bool();
582 let diff = vp_tree!(bc, 171,
583 vp_tree!(bc, 83, 2, 1),
587 vp_tree!(bc, 104, 6, 5),
594 validate!(diff < 256);
595 let diff = diff as u8;
597 validate!(self.models.prob_xmitted[ctx][set ^ 1] <= 255 - diff);
598 self.models.prob_xmitted[ctx][set ^ 1] += diff;
600 validate!(self.models.prob_xmitted[ctx][set ^ 1] >= diff);
601 self.models.prob_xmitted[ctx][set ^ 1] -= diff;
608 let prob_xmitted = &self.models.prob_xmitted[ctx];
610 let mdl = &mut self.models.mbtype_models[ctx][mode];
611 let mut cnt = [0u32; 10];
614 if i == mode { continue; }
615 cnt[i] = 100 * (prob_xmitted[i * 2] as u32);
618 let sum = (prob_xmitted[mode * 2] as u32) + (prob_xmitted[mode * 2 + 1] as u32);
619 mdl.probs[9] = 255 - rescale_mb_mode_prob(prob_xmitted[mode * 2 + 1] as u32, sum);
621 let inter_mv0_weight = (cnt[0] as u32) + (cnt[2] as u32);
622 let inter_mv1_weight = (cnt[3] as u32) + (cnt[4] as u32);
623 let gold_mv0_weight = (cnt[5] as u32) + (cnt[6] as u32);
624 let gold_mv1_weight = (cnt[8] as u32) + (cnt[9] as u32);
625 let mix_weight = (cnt[1] as u32) + (cnt[7] as u32);
626 mdl.probs[0] = 1 + rescale_mb_mode_prob(inter_mv0_weight + inter_mv1_weight, total);
627 mdl.probs[1] = 1 + rescale_mb_mode_prob(inter_mv0_weight, inter_mv0_weight + inter_mv1_weight);
628 mdl.probs[2] = 1 + rescale_mb_mode_prob(mix_weight, mix_weight + gold_mv0_weight + gold_mv1_weight);
629 mdl.probs[3] = 1 + rescale_mb_mode_prob(cnt[0] as u32, inter_mv0_weight);
630 mdl.probs[4] = 1 + rescale_mb_mode_prob(cnt[3] as u32, inter_mv1_weight);
631 mdl.probs[5] = 1 + rescale_mb_mode_prob(cnt[1], mix_weight);
632 mdl.probs[6] = 1 + rescale_mb_mode_prob(gold_mv0_weight, gold_mv0_weight + gold_mv1_weight);
633 mdl.probs[7] = 1 + rescale_mb_mode_prob(cnt[5], gold_mv0_weight);
634 mdl.probs[8] = 1 + rescale_mb_mode_prob(cnt[8], gold_mv1_weight);
639 fn find_mv_pred(&self, ref_id: u8) -> (usize, MV, MV, MV) {
640 const CAND_POS: [(i8, i8); 12] = [
649 let mut nearest_mv = ZERO_MV;
650 let mut near_mv = ZERO_MV;
651 let mut pred_mv = ZERO_MV;
652 let mut num_mv: usize = 0;
654 for (i, (yoff, xoff)) in CAND_POS.iter().enumerate() {
655 let cx = (self.fstate.mb_x as isize) + (*xoff as isize);
656 let cy = (self.fstate.mb_y as isize) + (*yoff as isize);
657 if (cx < 0) || (cy < 0) {
660 let cx = cx as usize;
661 let cy = cy as usize;
662 if (cx >= self.mb_w) || (cy >= self.mb_h) {
665 let mb_pos = cx + cy * self.mb_w;
666 let mv = self.mb_info[mb_pos].mv;
667 if (self.mb_info[mb_pos].mb_type.get_ref_id() != ref_id) || (mv == ZERO_MV) {
673 if (self.version > 5) && (i < 2) {
676 } else if mv != nearest_mv {
683 (num_mv, nearest_mv, near_mv, pred_mv)
685 fn decode_mv(&self, bc: &mut BoolCoder, br: &mut dyn VP56Parser) -> MV {
686 let x = br.decode_mv(bc, &self.models.mv_models[0]);
687 let y = br.decode_mv(bc, &self.models.mv_models[1]);
690 fn decode_mb_type(&mut self, bc: &mut BoolCoder, ctx: usize) -> DecoderResult<VPMBType> {
691 let probs = &self.models.mbtype_models[ctx][map_mb_type(self.last_mbt)].probs;
692 if !bc.read_prob(probs[9]) {
693 self.last_mbt = vp_tree!(
695 vp_tree!(bc, probs[1],
696 vp_tree!(bc, probs[3], VPMBType::InterNoMV, VPMBType::InterMV),
697 vp_tree!(bc, probs[4], VPMBType::InterNearest, VPMBType::InterNear)
699 vp_tree!(bc, probs[2],
700 vp_tree!(bc, probs[5], VPMBType::Intra, VPMBType::InterFourMV),
701 vp_tree!(bc, probs[6],
702 vp_tree!(bc, probs[7], VPMBType::GoldenNoMV, VPMBType::GoldenMV),
703 vp_tree!(bc, probs[8], VPMBType::InterNearest, VPMBType::InterNear)
710 fn decode_mb(&mut self, frm: &mut NASimpleVideoFrame<u8>, bc: &mut BoolCoder, cr: &mut CoeffReader, br: &mut dyn VP56Parser, hdr: &VP56Header, alpha: bool) -> DecoderResult<()> {
711 const FOURMV_SUB_TYPE: [VPMBType; 4] = [ VPMBType::InterNoMV, VPMBType::InterMV, VPMBType::InterNearest, VPMBType::InterNear ];
713 let mb_x = self.fstate.mb_x;
714 let mb_y = self.fstate.mb_y;
715 self.coeffs = [[0; 64]; 6];
716 let mb_pos = mb_x + mb_y * self.mb_w;
717 let mut four_mv = [ZERO_MV; 4];
718 let mut four_mbt = [VPMBType::Intra; 4];
721 let iprob = self.ilace_prob;
722 let prob = if mb_x == 0 {
724 } else if !self.ilace_mb {
725 iprob + (((256 - (iprob as u16)) >> 1) as u8)
729 self.ilace_mb = bc.read_prob(prob);
732 let (num_mv, nearest_mv, near_mv, pred_mv) = if hdr.is_intra {
733 (0, ZERO_MV, ZERO_MV, ZERO_MV)
734 } else { self.find_mv_pred(VP_REF_INTER) };
735 let mb_type = if hdr.is_intra {
738 self.decode_mb_type(bc, (num_mv + 1) % 3)?
740 self.mb_info[mb_pos].mb_type = mb_type;
741 if mb_type.get_ref_id() != VP_REF_GOLDEN {
744 VPMBType::InterNoMV => {
745 self.mb_info[mb_pos].mv = ZERO_MV;
747 VPMBType::InterMV => {
748 let diff_mv = self.decode_mv(bc, br);
749 self.mb_info[mb_pos].mv = pred_mv + diff_mv;
751 VPMBType::InterNearest => {
752 self.mb_info[mb_pos].mv = nearest_mv;
754 VPMBType::InterNear => {
755 self.mb_info[mb_pos].mv = near_mv;
757 VPMBType::InterFourMV => {
759 four_mbt[i] = FOURMV_SUB_TYPE[bc.read_bits(2) as usize];
763 VPMBType::InterNoMV => {},
764 VPMBType::InterMV => {
765 let diff_mv = self.decode_mv(bc, br);
766 four_mv[i] = pred_mv + diff_mv;
768 VPMBType::InterNearest => {
769 four_mv[i] = nearest_mv;
771 VPMBType::InterNear => {
772 four_mv[i] = near_mv;
777 self.mb_info[mb_pos].mv = four_mv[3];
782 let (_num_mv, nearest_mv, near_mv, pred_mv) = self.find_mv_pred(VP_REF_GOLDEN);
784 VPMBType::GoldenNoMV => {
785 self.mb_info[mb_pos].mv = ZERO_MV;
787 VPMBType::GoldenMV => {
788 let diff_mv = self.decode_mv(bc, br);
789 self.mb_info[mb_pos].mv = pred_mv + diff_mv;
791 VPMBType::GoldenNearest => {
792 self.mb_info[mb_pos].mv = nearest_mv;
794 VPMBType::GoldenNear => {
795 self.mb_info[mb_pos].mv = near_mv;
800 if !mb_type.is_intra() && (mb_type != VPMBType::InterFourMV) {
801 self.do_mc(br, frm, mb_type, self.mb_info[mb_pos].mv, alpha);
802 } else if mb_type == VPMBType::InterFourMV {
803 self.do_fourmv(br, frm, &four_mv, alpha);
807 self.fstate.plane = if !alpha { 0 } else { 3 };
808 self.fstate.ctx_idx = blk_no >> 1;
809 self.fstate.top_ctx = self.top_ctx[self.fstate.plane][mb_x * 2 + (blk_no & 1)];
811 CoeffReader::None => {
812 br.decode_block(bc, &mut self.coeffs[blk_no], &self.models.coeff_models[0], &self.models.vp6models, &mut self.fstate)?;
814 CoeffReader::Bool(ref mut bcc) => {
815 br.decode_block(bcc, &mut self.coeffs[blk_no], &self.models.coeff_models[0], &self.models.vp6models, &mut self.fstate)?;
817 CoeffReader::Huff(ref mut brc) => {
818 br.decode_block_huff(brc, &mut self.coeffs[blk_no], &self.models.vp6models, &self.models.vp6huff, &mut self.fstate)?;
821 self.top_ctx[self.fstate.plane][mb_x * 2 + (blk_no & 1)] = self.fstate.top_ctx;
822 self.predict_dc(mb_type, mb_pos, blk_no, alpha);
824 let bx = mb_x * 2 + (blk_no & 1);
825 let by = mb_y * 2 + (blk_no >> 1);
826 let has_ac = self.fstate.last_idx[self.fstate.ctx_idx] > 0;
827 if mb_type.is_intra() {
830 vp_put_block(&mut self.coeffs[blk_no], bx, by, self.fstate.plane, frm);
832 vp_put_block_dc(&mut self.coeffs[blk_no], bx, by, self.fstate.plane, frm);
835 vp_put_block_ilace(&mut self.coeffs[blk_no], bx, by, self.fstate.plane, frm);
840 vp_add_block(&mut self.coeffs[blk_no], bx, by, self.fstate.plane, frm);
842 vp_add_block_dc(&mut self.coeffs[blk_no], bx, by, self.fstate.plane, frm);
845 vp_add_block_ilace(&mut self.coeffs[blk_no], bx, by, self.fstate.plane, frm);
851 self.fstate.plane = blk_no - 3;
852 self.fstate.ctx_idx = blk_no - 2;
853 self.fstate.top_ctx = self.top_ctx[self.fstate.plane][mb_x];
855 CoeffReader::None => {
856 br.decode_block(bc, &mut self.coeffs[blk_no], &self.models.coeff_models[1], &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[1], &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] = self.fstate.top_ctx;
866 self.predict_dc(mb_type, mb_pos, blk_no, alpha);
868 let has_ac = self.fstate.last_idx[self.fstate.ctx_idx] > 0;
869 if mb_type.is_intra() {
871 vp_put_block(&mut self.coeffs[blk_no], mb_x, mb_y, self.fstate.plane, frm);
873 vp_put_block_dc(&mut self.coeffs[blk_no], mb_x, mb_y, self.fstate.plane, frm);
877 vp_add_block(&mut self.coeffs[blk_no], mb_x, mb_y, self.fstate.plane, frm);
879 vp_add_block_dc(&mut self.coeffs[blk_no], mb_x, mb_y, self.fstate.plane, frm);
886 fn do_mc(&mut self, br: &dyn VP56Parser, frm: &mut NASimpleVideoFrame<u8>, mb_type: VPMBType, mv: MV, alpha: bool) {
887 let x = self.fstate.mb_x * 16;
888 let y = self.fstate.mb_y * 16;
889 let plane = if !alpha { 0 } else { 3 };
890 let src = if mb_type.get_ref_id() == VP_REF_INTER {
891 self.shuf.get_last().unwrap()
893 self.shuf.get_golden().unwrap()
896 br.mc_block(frm, self.mc_buf.clone(), src.clone(), plane, x + 0, y + 0, mv, self.loop_thr);
897 br.mc_block(frm, self.mc_buf.clone(), src.clone(), plane, x + 8, y + 0, mv, self.loop_thr);
898 br.mc_block(frm, self.mc_buf.clone(), src.clone(), plane, x + 0, y + 8, mv, self.loop_thr);
899 br.mc_block(frm, self.mc_buf.clone(), src.clone(), plane, x + 8, y + 8, mv, self.loop_thr);
901 let x = self.fstate.mb_x * 8;
902 let y = self.fstate.mb_y * 8;
903 br.mc_block(frm, self.mc_buf.clone(), src.clone(), 1, x, y, mv, self.loop_thr);
904 br.mc_block(frm, self.mc_buf.clone(), src.clone(), 2, x, y, mv, self.loop_thr);
907 fn do_fourmv(&mut self, br: &dyn VP56Parser, frm: &mut NASimpleVideoFrame<u8>, mvs: &[MV; 4], alpha: bool) {
908 let x = self.fstate.mb_x * 16;
909 let y = self.fstate.mb_y * 16;
910 let plane = if !alpha { 0 } else { 3 };
911 let src = self.shuf.get_last().unwrap();
913 br.mc_block(frm, self.mc_buf.clone(), src.clone(),
914 plane, x + (blk_no & 1) * 8, y + (blk_no & 2) * 4,
915 mvs[blk_no], self.loop_thr);
918 let x = self.fstate.mb_x * 8;
919 let y = self.fstate.mb_y * 8;
920 let sum = mvs[0] + mvs[1] + mvs[2] + mvs[3];
921 let mv = MV { x: sum.x / 4, y: sum.y / 4 };
922 br.mc_block(frm, self.mc_buf.clone(), src.clone(), 1, x, y, mv, self.loop_thr);
923 br.mc_block(frm, self.mc_buf.clone(), src.clone(), 2, x, y, mv, self.loop_thr);
926 fn predict_dc(&mut self, mb_type: VPMBType, mb_pos: usize, blk_no: usize, alpha: bool) {
927 let mb_x = self.fstate.mb_x;
928 let is_luma = blk_no < 4;
929 let (plane, dcs) = if alpha { (0, &mut self.dc_a) } else {
931 4 => (1, &mut self.dc_u),
932 5 => (2, &mut self.dc_v),
933 _ => (0, &mut self.dc_y),
936 let dc_pos = if is_luma {
937 dcs.xpos + mb_x * 2 + (blk_no & 1) + (blk_no >> 1) * dcs.stride
941 let ref_id = mb_type.get_ref_id();
942 let has_left_blk = is_luma && ((blk_no & 1) != 0);
943 let has_top_blk = is_luma && ((blk_no & 2) != 0);
946 if has_left_blk || ((mb_x > 0) && (self.mb_info[mb_pos - 1].mb_type.get_ref_id() == ref_id)) {
947 dc_pred += dcs.data[dc_pos - 1];
950 if has_top_blk || ((mb_pos >= self.mb_w) && (self.mb_info[mb_pos - self.mb_w].mb_type.get_ref_id() == ref_id)) {
951 dc_pred += dcs.data[dc_pos - dcs.stride];
954 if self.version == 5 {
955 if (count < 2) && has_left_blk {
959 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) {
963 if (count < 2) && mb_pos == 0 && !is_luma {
966 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) {
967 dc_pred += dcs.data[dc_pos + dcs.stride - 1];
970 if (count < 2) && blk_no == 2 {
971 dc_pred += dcs.data[dc_pos - dcs.stride + 1];
974 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) {
975 dc_pred += dcs.data[dc_pos - dcs.stride + 1];
978 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) {
979 dc_pred += dcs.data[dc_pos - dcs.stride + 1];
984 dc_pred = self.last_dc[ref_id as usize][plane];
985 } else if count == 2 {
988 self.coeffs[blk_no][0] += dc_pred;
989 self.last_dc[ref_id as usize][plane] = self.coeffs[blk_no][0];
990 dcs.data[dc_pos] = self.coeffs[blk_no][0];
991 self.coeffs[blk_no][0] = self.coeffs[blk_no][0].wrapping_mul(self.fstate.dc_quant);
995 const VP56_DC_QUANTS: [i16; 64] = [
996 47, 47, 47, 47, 45, 43, 43, 43,
997 43, 43, 42, 41, 41, 40, 40, 40,
998 40, 35, 35, 35, 35, 33, 33, 33,
999 33, 32, 32, 32, 27, 27, 26, 26,
1000 25, 25, 24, 24, 23, 23, 19, 19,
1001 19, 19, 18, 18, 17, 16, 16, 16,
1002 16, 16, 15, 11, 11, 11, 10, 10,
1003 9, 8, 7, 5, 3, 3, 2, 2
1005 const VP56_AC_QUANTS: [i16; 64] = [
1006 94, 92, 90, 88, 86, 82, 78, 74,
1007 70, 66, 62, 58, 54, 53, 52, 51,
1008 50, 49, 48, 47, 46, 45, 44, 43,
1009 42, 40, 39, 37, 36, 35, 34, 33,
1010 32, 31, 30, 29, 28, 27, 26, 25,
1011 24, 23, 22, 21, 20, 19, 18, 17,
1012 16, 15, 14, 13, 12, 11, 10, 9,
1013 8, 7, 6, 5, 4, 3, 2, 1
1016 const VP56_FILTER_LIMITS: [u8; 64] = [
1017 14, 14, 13, 13, 12, 12, 10, 10,
1018 10, 10, 8, 8, 8, 8, 8, 8,
1019 8, 8, 8, 8, 8, 8, 8, 8,
1020 8, 8, 8, 8, 8, 8, 8, 8,
1021 8, 8, 8, 8, 7, 7, 7, 7,
1022 7, 7, 6, 6, 6, 6, 6, 6,
1023 5, 5, 5, 5, 4, 4, 4, 4,
1024 4, 4, 4, 3, 3, 3, 3, 2
1027 const VP56_MODE_VQ: [[[u8; 20]; 16]; 3] = [
1029 [ 9, 15, 32, 25, 7, 19, 9, 21, 1, 12, 14, 12, 3, 18, 14, 23, 3, 10, 0, 4 ],
1030 [ 48, 39, 1, 2, 11, 27, 29, 44, 7, 27, 1, 4, 0, 3, 1, 6, 1, 2, 0, 0 ],
1031 [ 21, 32, 1, 2, 4, 10, 32, 43, 6, 23, 2, 3, 1, 19, 1, 6, 12, 21, 0, 7 ],
1032 [ 69, 83, 0, 0, 0, 2, 10, 29, 3, 12, 0, 1, 0, 3, 0, 3, 2, 2, 0, 0 ],
1033 [ 11, 20, 1, 4, 18, 36, 43, 48, 13, 35, 0, 2, 0, 5, 3, 12, 1, 2, 0, 0 ],
1034 [ 70, 44, 0, 1, 2, 10, 37, 46, 8, 26, 0, 2, 0, 2, 0, 2, 0, 1, 0, 0 ],
1035 [ 8, 15, 0, 1, 8, 21, 74, 53, 22, 42, 0, 1, 0, 2, 0, 3, 1, 2, 0, 0 ],
1036 [ 141, 42, 0, 0, 1, 4, 11, 24, 1, 11, 0, 1, 0, 1, 0, 2, 0, 0, 0, 0 ],
1037 [ 8, 19, 4, 10, 24, 45, 21, 37, 9, 29, 0, 3, 1, 7, 11, 25, 0, 2, 0, 1 ],
1038 [ 46, 42, 0, 1, 2, 10, 54, 51, 10, 30, 0, 2, 0, 2, 0, 1, 0, 1, 0, 0 ],
1039 [ 28, 32, 0, 0, 3, 10, 75, 51, 14, 33, 0, 1, 0, 2, 0, 1, 1, 2, 0, 0 ],
1040 [ 100, 46, 0, 1, 3, 9, 21, 37, 5, 20, 0, 1, 0, 2, 1, 2, 0, 1, 0, 0 ],
1041 [ 27, 29, 0, 1, 9, 25, 53, 51, 12, 34, 0, 1, 0, 3, 1, 5, 0, 2, 0, 0 ],
1042 [ 80, 38, 0, 0, 1, 4, 69, 33, 5, 16, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0 ],
1043 [ 16, 20, 0, 0, 2, 8, 104, 49, 15, 33, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0 ],
1044 [ 194, 16, 0, 0, 1, 1, 1, 9, 1, 3, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0 ],
1046 [ 41, 22, 1, 0, 1, 31, 0, 0, 0, 0, 0, 1, 1, 7, 0, 1, 98, 25, 4, 10 ],
1047 [ 123, 37, 6, 4, 1, 27, 0, 0, 0, 0, 5, 8, 1, 7, 0, 1, 12, 10, 0, 2 ],
1048 [ 26, 14, 14, 12, 0, 24, 0, 0, 0, 0, 55, 17, 1, 9, 0, 36, 5, 7, 1, 3 ],
1049 [ 209, 5, 0, 0, 0, 27, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0 ],
1050 [ 2, 5, 4, 5, 0, 121, 0, 0, 0, 0, 0, 3, 2, 4, 1, 4, 2, 2, 0, 1 ],
1051 [ 175, 5, 0, 1, 0, 48, 0, 0, 0, 0, 0, 2, 0, 1, 0, 2, 0, 1, 0, 0 ],
1052 [ 83, 5, 2, 3, 0, 102, 0, 0, 0, 0, 1, 3, 0, 2, 0, 1, 0, 0, 0, 0 ],
1053 [ 233, 6, 0, 0, 0, 8, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0 ],
1054 [ 34, 16, 112, 21, 1, 28, 0, 0, 0, 0, 6, 8, 1, 7, 0, 3, 2, 5, 0, 2 ],
1055 [ 159, 35, 2, 2, 0, 25, 0, 0, 0, 0, 3, 6, 0, 5, 0, 1, 4, 4, 0, 1 ],
1056 [ 75, 39, 5, 7, 2, 48, 0, 0, 0, 0, 3, 11, 2, 16, 1, 4, 7, 10, 0, 2 ],
1057 [ 212, 21, 0, 1, 0, 9, 0, 0, 0, 0, 1, 2, 0, 2, 0, 0, 2, 2, 0, 0 ],
1058 [ 4, 2, 0, 0, 0, 172, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 2, 0, 0, 0 ],
1059 [ 187, 22, 1, 1, 0, 17, 0, 0, 0, 0, 3, 6, 0, 4, 0, 1, 4, 4, 0, 1 ],
1060 [ 133, 6, 1, 2, 1, 70, 0, 0, 0, 0, 0, 2, 0, 4, 0, 3, 1, 1, 0, 0 ],
1061 [ 251, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
1063 [ 2, 3, 2, 3, 0, 2, 0, 2, 0, 0, 11, 4, 1, 4, 0, 2, 3, 2, 0, 4 ],
1064 [ 49, 46, 3, 4, 7, 31, 42, 41, 0, 0, 2, 6, 1, 7, 1, 4, 2, 4, 0, 1 ],
1065 [ 26, 25, 1, 1, 2, 10, 67, 39, 0, 0, 1, 1, 0, 14, 0, 2, 31, 26, 1, 6 ],
1066 [ 103, 46, 1, 2, 2, 10, 33, 42, 0, 0, 1, 4, 0, 3, 0, 1, 1, 3, 0, 0 ],
1067 [ 14, 31, 9, 13, 14, 54, 22, 29, 0, 0, 2, 6, 4, 18, 6, 13, 1, 5, 0, 1 ],
1068 [ 85, 39, 0, 0, 1, 9, 69, 40, 0, 0, 0, 1, 0, 3, 0, 1, 2, 3, 0, 0 ],
1069 [ 31, 28, 0, 0, 3, 14, 130, 34, 0, 0, 0, 1, 0, 3, 0, 1, 3, 3, 0, 1 ],
1070 [ 171, 25, 0, 0, 1, 5, 25, 21, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0 ],
1071 [ 17, 21, 68, 29, 6, 15, 13, 22, 0, 0, 6, 12, 3, 14, 4, 10, 1, 7, 0, 3 ],
1072 [ 51, 39, 0, 1, 2, 12, 91, 44, 0, 0, 0, 2, 0, 3, 0, 1, 2, 3, 0, 1 ],
1073 [ 81, 25, 0, 0, 2, 9, 106, 26, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0 ],
1074 [ 140, 37, 0, 1, 1, 8, 24, 33, 0, 0, 1, 2, 0, 2, 0, 1, 1, 2, 0, 0 ],
1075 [ 14, 23, 1, 3, 11, 53, 90, 31, 0, 0, 0, 3, 1, 5, 2, 6, 1, 2, 0, 0 ],
1076 [ 123, 29, 0, 0, 1, 7, 57, 30, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0 ],
1077 [ 13, 14, 0, 0, 4, 20, 175, 20, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0 ],
1078 [ 202, 23, 0, 0, 1, 3, 2, 9, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0 ],