1 use nihav_core::codecs::*;
2 use nihav_core::io::bitreader::*;
3 use super::vpcommon::*;
5 pub const TOKEN_LARGE: u8 = 5;
6 pub const TOKEN_EOB: u8 = 42;
8 #[derive(Clone,Copy,Debug,Default)]
10 pub struct VP56Header {
14 pub multistream: bool,
15 pub use_huffman: bool,
27 #[derive(Clone,Copy,Default)]
28 pub struct VP56MVModel {
31 pub raw_probs: [u8; 8],
32 pub tree_probs: [u8; 7],
35 #[derive(Clone,Copy,Default)]
36 pub struct VP56MBTypeModel {
40 #[derive(Clone,Copy,Default)]
41 pub struct VP56CoeffModel {
42 pub dc_token_probs: [[[u8; 5]; 6]; 6],
43 pub dc_value_probs: [u8; 11],
44 pub ac_ctype_probs: [[[[u8; 5]; 5]; 6]; 3],
45 pub ac_type_probs: [[[[u8; 5]; 6]; 3]; 3],
46 pub ac_val_probs: [[[u8; 11]; 6]; 3],
49 pub struct VP6Models {
50 pub scan_order: [usize; 64],
51 pub scan: [usize; 64],
52 pub zigzag: [usize; 64],
53 pub zero_run_probs: [[u8; 14]; 2],
56 const MAX_HUFF_ELEMS: usize = 12;
57 #[derive(Clone,Copy,Default)]
59 pub codes: [u16; MAX_HUFF_ELEMS],
60 pub bits: [u8; MAX_HUFF_ELEMS],
63 #[derive(Clone,Copy,Default)]
71 fn prob2weight(a: u8, b: u8) -> u8 {
72 let w = (((a as u16) * (b as u16)) >> 8) as u8;
81 fn build_codes(&mut self, probs: &[u8; 11]) {
82 let mut weights = [0u8; 12];
84 weights[11] = prob2weight( probs[0], probs[ 1]);
85 weights[ 0] = prob2weight( probs[0], !probs[ 1]);
86 weights[ 1] = prob2weight(!probs[0], probs[ 2]);
87 let lvroot = prob2weight(!probs[0], !probs[ 2]);
88 let tworoot = prob2weight( lvroot, probs[ 3]);
89 let hlroot = prob2weight( lvroot, !probs[ 3]);
90 weights[ 2] = prob2weight( tworoot, probs[ 4]);
91 let root34 = prob2weight( tworoot, !probs[ 4]);
92 weights[ 3] = prob2weight( root34, probs[ 5]);
93 weights[ 4] = prob2weight( root34, !probs[ 5]);
94 let c1root = prob2weight( hlroot, probs[ 6]);
95 let c34root = prob2weight( hlroot, !probs[ 6]);
96 weights[ 5] = prob2weight( c1root, probs[ 7]);
97 weights[ 6] = prob2weight( c1root, !probs[ 7]);
98 let c3root = prob2weight( c34root, probs[ 8]);
99 let c4root = prob2weight( c34root, !probs[ 8]);
100 weights[ 7] = prob2weight( c3root, probs[ 9]);
101 weights[ 8] = prob2weight( c3root, !probs[ 9]);
102 weights[ 9] = prob2weight( c4root, probs[10]);
103 weights[10] = prob2weight( c4root, !probs[10]);
105 self.build(&weights);
107 fn build_codes_zero_run(&mut self, probs: &[u8; 14]) {
108 let mut weights = [0u8; 9];
110 let root = prob2weight( probs[0], probs[1]);
111 weights[0] = prob2weight( root, probs[2]);
112 weights[1] = prob2weight( root, !probs[2]);
114 let root = prob2weight( probs[0], !probs[1]);
115 weights[2] = prob2weight( root, probs[3]);
116 weights[3] = prob2weight( root, !probs[3]);
118 let root = prob2weight(!probs[0], probs[4]);
119 weights[8] = prob2weight(!probs[0], !probs[4]);
120 let root1 = prob2weight( root, probs[5]);
121 let root2 = prob2weight( root, !probs[5]);
122 weights[4] = prob2weight( root1, probs[6]);
123 weights[5] = prob2weight( root1, !probs[6]);
124 weights[6] = prob2weight( root2, probs[7]);
125 weights[7] = prob2weight( root2, !probs[7]);
127 self.build(&weights);
129 fn build(&mut self, weights: &[u8]) {
130 let mut nodes = [Node::default(); MAX_HUFF_ELEMS * 2];
133 for w in weights.iter().rev() {
134 let weight = *w as u16;
137 if nodes[i].weight > weight {
142 for j in (pos..nlen).rev() {
143 nodes[j + 1] = nodes[j];
145 nodes[pos].weight = weight;
146 nodes[pos].sym = (weights.len() - nlen - 1) as i8;
153 weight: nodes[low + 0].weight + nodes[low + 1].weight,
160 while (pos < nlen) && (nodes[pos].weight < nnode.weight) {
163 for j in (pos..nlen).rev() {
164 nodes[j + 1] = nodes[j];
169 self.get_codes(&nodes, nlen - 1, 0, 0);
170 for i in nlen..self.codes.len() {
171 self.codes[i] = self.codes[0];
172 self.bits[i] = self.bits[0];
175 fn get_codes(&mut self, nodes: &[Node], pos: usize, code: u16, len: u8) {
176 if nodes[pos].sym >= 0 {
177 self.codes[nodes[pos].sym as usize] = code;
178 self.bits [nodes[pos].sym as usize] = len;
180 self.get_codes(nodes, nodes[pos].ch0, (code << 1) | 0, len + 1);
181 self.get_codes(nodes, nodes[pos].ch1, (code << 1) | 1, len + 1);
187 fn read_huff(&mut self, huff: &VP6Huff) -> DecoderResult<u8>;
190 impl<'a> ReadHuff for BitReader<'a> {
191 fn read_huff(&mut self, huff: &VP6Huff) -> DecoderResult<u8> {
192 let peekval = self.peek(16);
193 for (i, (code, bit)) in huff.codes.iter().zip(huff.bits.iter()).enumerate() {
194 if (peekval >> (16 - *bit)) == (*code as u32) {
195 self.skip(*bit as u32)?;
199 Err(DecoderError::InvalidData)
203 #[derive(Clone,Copy,Default)]
204 pub struct VP6HuffModels {
205 pub dc_token_tree: [VP6Huff; 2],
206 pub ac_token_tree: [[[VP6Huff; 6]; 3]; 2],
207 pub zero_run_tree: [VP6Huff; 2],
216 zero_run_probs: [[0; 14]; 2],
221 pub struct VP56Models {
222 pub mv_models: [VP56MVModel; 2],
223 pub mbtype_models: [[VP56MBTypeModel; 10]; 3],
224 pub coeff_models: [VP56CoeffModel; 2],
225 pub prob_xmitted: [[u8; 20]; 3],
226 pub vp6models: VP6Models,
227 pub vp6huff: VP6HuffModels,
233 mv_models: [VP56MVModel::default(); 2],
234 mbtype_models: [[VP56MBTypeModel::default(); 10]; 3],
235 coeff_models: [VP56CoeffModel::default(); 2],
236 prob_xmitted: [[0; 20]; 3],
237 vp6models: VP6Models::new(),
238 vp6huff: VP6HuffModels::default(),
243 pub trait VP56Parser {
244 fn parse_header(&mut self, bc: &mut BoolCoder) -> DecoderResult<VP56Header>;
245 fn reset_models(&self, models: &mut VP56Models);
246 fn decode_mv(&self, bc: &mut BoolCoder, model: &VP56MVModel) -> i16;
247 fn decode_mv_models(&self, bc: &mut BoolCoder, models: &mut [VP56MVModel; 2]) -> DecoderResult<()>;
248 fn decode_coeff_models(&self, bc: &mut BoolCoder, models: &mut VP56Models, is_intra: bool) -> DecoderResult<()>;
249 fn decode_block(&self, bc: &mut BoolCoder, coeffs: &mut [i16; 64], model: &VP56CoeffModel, vp6model: &VP6Models, fstate: &mut FrameState) -> DecoderResult<()>;
250 fn decode_block_huff(&self, br: &mut BitReader, coeffs: &mut [i16; 64], vp6model: &VP6Models, model: &VP6HuffModels, fstate: &mut FrameState) -> DecoderResult<()>;
251 fn mc_block(&self, dst: &mut NASimpleVideoFrame<u8>, mc_buf: NAVideoBufferRef<u8>, src: NAVideoBufferRef<u8>, plane: usize, x: usize, y: usize, mv: MV, loop_thr: i16);
254 enum CoeffReader<'a> {
260 #[derive(Clone,Copy,Default)]
266 pub struct FrameState {
270 pub coeff_cat: [[u8; 64]; 4],
271 pub last_idx: [usize; 4],
276 pub dc_zero_run: [usize; 2],
277 pub ac_zero_run: [usize; 2],
286 coeff_cat: [[0; 64]; 4],
298 pub struct GenericCache<T: Copy> {
306 impl<T:Copy> GenericCache<T> {
307 fn new(height: usize, stride: usize, default: T) -> Self {
312 data: Vec::with_capacity((height + 1) * stride),
318 fn full_size(&self) -> usize { self.stride * (self.height + 1) }
319 fn reset(&mut self) {
320 self.data.truncate(0);
321 let size = self.full_size();
322 self.data.resize(size, self.default);
323 self.xpos = self.stride + 1;
325 fn update_row(&mut self) {
326 for i in 0..self.stride {
327 self.data[i] = self.data[self.height * self.stride + i];
329 self.data.truncate(self.stride);
330 let size = self.full_size();
331 self.data.resize(size, self.default);
332 self.xpos = self.stride + 1;
336 pub struct VP56Decoder {
346 coeffs: [[i16; 64]; 6],
353 mb_info: Vec<MBInfo>,
355 dc_y: GenericCache<i16>,
356 dc_u: GenericCache<i16>,
357 dc_v: GenericCache<i16>,
358 dc_a: GenericCache<i16>,
359 last_dc: [[i16; 4]; 3],
360 top_ctx: [Vec<u8>; 4],
362 mc_buf: NAVideoBufferRef<u8>,
365 fn rescale_mb_mode_prob(prob: u32, total: u32) -> u8 {
366 (255 * prob / (1 + total)) as u8
369 fn map_mb_type(mbtype: VPMBType) -> usize {
371 VPMBType::InterNoMV => 0,
372 VPMBType::Intra => 1,
373 VPMBType::InterMV => 2,
374 VPMBType::InterNearest => 3,
375 VPMBType::InterNear => 4,
376 VPMBType::GoldenNoMV => 5,
377 VPMBType::GoldenMV => 6,
378 VPMBType::InterFourMV => 7,
379 VPMBType::GoldenNearest => 8,
380 VPMBType::GoldenNear => 9,
384 pub fn expand_token_bc(bc: &mut BoolCoder, val_probs: &[u8; 11], token: u8, version: u8) -> i16 {
385 let mut sign = false;
387 if token < TOKEN_LARGE {
389 sign = bc.read_bool();
391 level = token as i16;
393 let cat: usize = vp_tree!(bc, val_probs[6],
394 vp_tree!(bc, val_probs[7], 0, 1),
395 vp_tree!(bc, val_probs[8],
396 vp_tree!(bc, val_probs[9], 2, 3),
397 vp_tree!(bc, val_probs[10], 4, 5)));
399 sign = bc.read_bool();
402 let add_probs = &VP56_COEF_ADD_PROBS[cat];
403 for prob in add_probs.iter() {
404 if *prob == 128 { break; }
405 add = (add << 1) | (bc.read_prob(*prob) as i16);
408 sign = bc.read_bool();
410 level = VP56_COEF_BASE[cat] + add;
420 pub fn new(version: u8, has_alpha: bool, flip: bool) -> Self {
421 let vt = alloc_video_buffer(NAVideoInfo::new(24, 24, false, YUV420_FORMAT), 4).unwrap();
422 let mc_buf = vt.get_vbuf().unwrap();
424 version, has_alpha, flip,
425 shuf: VPShuffler::new(),
430 models: VP56Models::new(),
431 coeffs: [[0; 64]; 6],
432 last_mbt: VPMBType::InterNoMV,
439 fstate: FrameState::new(),
440 dc_y: GenericCache::new(0, 0, 0),
441 dc_u: GenericCache::new(0, 0, 0),
442 dc_v: GenericCache::new(0, 0, 0),
443 dc_a: GenericCache::new(0, 0, 0),
444 last_dc: [[0; 4]; 3],
445 top_ctx: [Vec::new(), Vec::new(), Vec::new(), Vec::new()],
450 fn set_dimensions(&mut self, width: usize, height: usize) {
452 self.height = height;
453 self.mb_w = (self.width + 15) >> 4;
454 self.mb_h = (self.height + 15) >> 4;
455 self.mb_info.resize(self.mb_w * self.mb_h, MBInfo::default());
456 self.dc_y = GenericCache::new(2, 1 + self.mb_w * 2, 0);
457 self.dc_u = GenericCache::new(1, 1 + self.mb_w, 0);
458 self.dc_v = GenericCache::new(1, 1 + self.mb_w, 0);
459 self.dc_a = GenericCache::new(2, 1 + self.mb_w * 2, 0);
460 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]];
462 pub fn init(&mut self, supp: &mut NADecoderSupport, vinfo: NAVideoInfo) -> DecoderResult<()> {
463 supp.pool_u8.set_dec_bufs(3);
464 supp.pool_u8.prealloc_video(NAVideoInfo::new(vinfo.get_width(), vinfo.get_height(), false, vinfo.get_format()), 4)?;
465 self.set_dimensions(vinfo.get_width(), vinfo.get_height());
468 pub fn decode_frame(&mut self, supp: &mut NADecoderSupport, src: &[u8], br: &mut dyn VP56Parser) -> DecoderResult<(NABufferType, FrameType)> {
472 validate!(src.len() >= 7);
473 aoffset = ((src[0] as usize) << 16) | ((src[1] as usize) << 8) | (src[2] as usize);
474 validate!((aoffset > 0) && (aoffset < src.len() - 3));
475 bc = BoolCoder::new(&src[3..])?;
477 validate!(src.len() >= 4);
479 bc = BoolCoder::new(src)?;
481 let hdr = br.parse_header(&mut bc)?;
482 validate!((hdr.offset as usize) < aoffset); //XXX: take alpha 3 byte offset into account?
485 self.set_dimensions((hdr.mb_w as usize) * 16, (hdr.mb_h as usize) * 16);
487 let vinfo = NAVideoInfo::new(self.width, self.height, self.flip, YUV420_FORMAT);
488 let ret = supp.pool_u8.get_free();
490 return Err(DecoderError::AllocError);
492 let mut buf = ret.unwrap();
493 if buf.get_info() != vinfo {
495 supp.pool_u8.reset();
496 supp.pool_u8.prealloc_video(vinfo, 4)?;
497 let ret = supp.pool_u8.get_free();
499 return Err(DecoderError::AllocError);
503 let mut dframe = NASimpleVideoFrame::from_video_buf(&mut buf).unwrap();
511 let off = (if self.has_alpha { 3 } else { 0 }) + (hdr.offset as usize);
512 if !hdr.use_huffman {
513 let bc2 = BoolCoder::new(&src[off..])?;
514 cr = CoeffReader::Bool(bc2);
516 let br = BitReader::new(&src[off..], aoffset - off, BitReaderMode::BE);
517 cr = CoeffReader::Huff(br);
520 cr = CoeffReader::None;
524 br.reset_models(&mut self.models);
525 self.reset_mbtype_models();
527 self.decode_mode_prob_models(&mut bc)?;
528 br.decode_mv_models(&mut bc, &mut self.models.mv_models)?;
530 br.decode_coeff_models(&mut bc, &mut self.models, hdr.is_intra)?;
533 self.models.vp6huff.dc_token_tree[i].build_codes(&self.models.coeff_models[i].dc_value_probs);
538 self.models.vp6huff.ac_token_tree[i][mode][band].build_codes(&self.models.coeff_models[i].ac_val_probs[mode][band]);
543 self.models.vp6huff.zero_run_tree[i].build_codes_zero_run(&self.models.vp6models.zero_run_probs[i]);
548 self.ilace_prob = bc.read_bits(8) as u8;
551 self.fstate = FrameState::new();
552 self.fstate.dc_quant = VP56_DC_QUANTS[hdr.quant as usize] * 4;
553 self.fstate.ac_quant = VP56_AC_QUANTS[hdr.quant as usize] * 4;
554 self.loop_thr = VP56_FILTER_LIMITS[hdr.quant as usize] as i16;
556 self.last_mbt = VPMBType::InterNoMV;
561 for vec in self.top_ctx.iter_mut() {
562 for el in vec.iter_mut() {
566 self.last_dc = [[0; 4]; 3];
567 self.last_dc[0][1] = 0x80;
568 self.last_dc[0][2] = 0x80;
570 self.ilace_mb = false;
571 for mb_y in 0..self.mb_h {
572 self.fstate.mb_y = mb_y;
573 self.fstate.coeff_cat = [[0; 64]; 4];
574 self.fstate.last_idx = [24; 4];
575 for mb_x in 0..self.mb_w {
576 self.fstate.mb_x = mb_x;
577 self.decode_mb(&mut dframe, &mut bc, &mut cr, br, &hdr, false)?;
579 self.dc_y.update_row();
580 self.dc_u.update_row();
581 self.dc_v.update_row();
582 self.dc_a.update_row();
586 let asrc = &src[aoffset + 3..];
587 let mut bc = BoolCoder::new(asrc)?;
588 let ahdr = br.parse_header(&mut bc)?;
589 validate!(ahdr.mb_w == hdr.mb_w && ahdr.mb_h == hdr.mb_h);
593 self.shuf.add_golden_frame(buf.clone());
595 self.shuf.add_frame(buf.clone());
597 Ok((NABufferType::Video(buf), if hdr.is_intra { FrameType::I } else { FrameType::P }))
599 fn reset_mbtype_models(&mut self) {
600 const DEFAULT_XMITTED_PROBS: [[u8; 20]; 3] = [
601 [ 42, 69, 2, 1, 7, 1, 42, 44, 22, 6, 3, 1, 2, 0, 5, 1, 1, 0, 0, 0 ],
602 [ 8, 229, 1, 1, 8, 0, 0, 0, 0, 0, 2, 1, 1, 0, 0, 0, 1, 1, 0, 0 ],
603 [ 35, 122, 1, 1, 6, 1, 34, 46, 0, 0, 2, 1, 1, 0, 1, 0, 1, 1, 0, 0 ]
605 self.models.prob_xmitted.copy_from_slice(&DEFAULT_XMITTED_PROBS);
607 fn decode_mode_prob_models(&mut self, bc: &mut BoolCoder) -> DecoderResult<()> {
609 if bc.read_prob(174) {
610 let idx = bc.read_bits(4) as usize;
612 self.models.prob_xmitted[ctx][i ^ 1] = VP56_MODE_VQ[ctx][idx][i];
615 if bc.read_prob(254) {
617 if bc.read_prob(205) {
618 let sign = bc.read_bool();
619 let diff = vp_tree!(bc, 171,
620 vp_tree!(bc, 83, 2, 1),
624 vp_tree!(bc, 104, 6, 5),
631 validate!(diff < 256);
632 let diff = diff as u8;
634 validate!(self.models.prob_xmitted[ctx][set ^ 1] <= 255 - diff);
635 self.models.prob_xmitted[ctx][set ^ 1] += diff;
637 validate!(self.models.prob_xmitted[ctx][set ^ 1] >= diff);
638 self.models.prob_xmitted[ctx][set ^ 1] -= diff;
645 let prob_xmitted = &self.models.prob_xmitted[ctx];
647 let mdl = &mut self.models.mbtype_models[ctx][mode];
648 let mut cnt = [0u32; 10];
651 if i == mode { continue; }
652 cnt[i] = 100 * (prob_xmitted[i * 2] as u32);
655 let sum = (prob_xmitted[mode * 2] as u32) + (prob_xmitted[mode * 2 + 1] as u32);
656 mdl.probs[9] = 255 - rescale_mb_mode_prob(prob_xmitted[mode * 2 + 1] as u32, sum);
658 let inter_mv0_weight = (cnt[0] as u32) + (cnt[2] as u32);
659 let inter_mv1_weight = (cnt[3] as u32) + (cnt[4] as u32);
660 let gold_mv0_weight = (cnt[5] as u32) + (cnt[6] as u32);
661 let gold_mv1_weight = (cnt[8] as u32) + (cnt[9] as u32);
662 let mix_weight = (cnt[1] as u32) + (cnt[7] as u32);
663 mdl.probs[0] = 1 + rescale_mb_mode_prob(inter_mv0_weight + inter_mv1_weight, total);
664 mdl.probs[1] = 1 + rescale_mb_mode_prob(inter_mv0_weight, inter_mv0_weight + inter_mv1_weight);
665 mdl.probs[2] = 1 + rescale_mb_mode_prob(mix_weight, mix_weight + gold_mv0_weight + gold_mv1_weight);
666 mdl.probs[3] = 1 + rescale_mb_mode_prob(cnt[0] as u32, inter_mv0_weight);
667 mdl.probs[4] = 1 + rescale_mb_mode_prob(cnt[3] as u32, inter_mv1_weight);
668 mdl.probs[5] = 1 + rescale_mb_mode_prob(cnt[1], mix_weight);
669 mdl.probs[6] = 1 + rescale_mb_mode_prob(gold_mv0_weight, gold_mv0_weight + gold_mv1_weight);
670 mdl.probs[7] = 1 + rescale_mb_mode_prob(cnt[5], gold_mv0_weight);
671 mdl.probs[8] = 1 + rescale_mb_mode_prob(cnt[8], gold_mv1_weight);
676 fn find_mv_pred(&self, ref_id: u8) -> (usize, MV, MV, MV) {
677 const CAND_POS: [(i8, i8); 12] = [
686 let mut nearest_mv = ZERO_MV;
687 let mut near_mv = ZERO_MV;
688 let mut pred_mv = ZERO_MV;
689 let mut num_mv: usize = 0;
691 for (i, (yoff, xoff)) in CAND_POS.iter().enumerate() {
692 let cx = (self.fstate.mb_x as isize) + (*xoff as isize);
693 let cy = (self.fstate.mb_y as isize) + (*yoff as isize);
694 if (cx < 0) || (cy < 0) {
697 let cx = cx as usize;
698 let cy = cy as usize;
699 if (cx >= self.mb_w) || (cy >= self.mb_h) {
702 let mb_pos = cx + cy * self.mb_w;
703 let mv = self.mb_info[mb_pos].mv;
704 if (self.mb_info[mb_pos].mb_type.get_ref_id() != ref_id) || (mv == ZERO_MV) {
710 if (self.version > 5) && (i < 2) {
713 } else if mv != nearest_mv {
720 (num_mv, nearest_mv, near_mv, pred_mv)
722 fn decode_mv(&self, bc: &mut BoolCoder, br: &mut dyn VP56Parser) -> MV {
723 let x = br.decode_mv(bc, &self.models.mv_models[0]);
724 let y = br.decode_mv(bc, &self.models.mv_models[1]);
727 fn decode_mb_type(&mut self, bc: &mut BoolCoder, ctx: usize) -> DecoderResult<VPMBType> {
728 let probs = &self.models.mbtype_models[ctx][map_mb_type(self.last_mbt)].probs;
729 if !bc.read_prob(probs[9]) {
730 self.last_mbt = vp_tree!(
732 vp_tree!(bc, probs[1],
733 vp_tree!(bc, probs[3], VPMBType::InterNoMV, VPMBType::InterMV),
734 vp_tree!(bc, probs[4], VPMBType::InterNearest, VPMBType::InterNear)
736 vp_tree!(bc, probs[2],
737 vp_tree!(bc, probs[5], VPMBType::Intra, VPMBType::InterFourMV),
738 vp_tree!(bc, probs[6],
739 vp_tree!(bc, probs[7], VPMBType::GoldenNoMV, VPMBType::GoldenMV),
740 vp_tree!(bc, probs[8], VPMBType::InterNearest, VPMBType::InterNear)
747 fn decode_mb(&mut self, frm: &mut NASimpleVideoFrame<u8>, bc: &mut BoolCoder, cr: &mut CoeffReader, br: &mut dyn VP56Parser, hdr: &VP56Header, alpha: bool) -> DecoderResult<()> {
748 const FOURMV_SUB_TYPE: [VPMBType; 4] = [ VPMBType::InterNoMV, VPMBType::InterMV, VPMBType::InterNearest, VPMBType::InterNear ];
750 let mb_x = self.fstate.mb_x;
751 let mb_y = self.fstate.mb_y;
752 self.coeffs = [[0; 64]; 6];
753 let mb_pos = mb_x + mb_y * self.mb_w;
754 let mut four_mv = [ZERO_MV; 4];
755 let mut four_mbt = [VPMBType::Intra; 4];
758 let iprob = self.ilace_prob;
759 let prob = if mb_x == 0 {
761 } else if !self.ilace_mb {
762 iprob + (((256 - (iprob as u16)) >> 1) as u8)
766 self.ilace_mb = bc.read_prob(prob);
769 let (num_mv, nearest_mv, near_mv, pred_mv) = if hdr.is_intra {
770 (0, ZERO_MV, ZERO_MV, ZERO_MV)
771 } else { self.find_mv_pred(VP_REF_INTER) };
772 let mb_type = if hdr.is_intra {
775 self.decode_mb_type(bc, (num_mv + 1) % 3)?
777 self.mb_info[mb_pos].mb_type = mb_type;
778 if mb_type.get_ref_id() != VP_REF_GOLDEN {
781 VPMBType::InterNoMV => {
782 self.mb_info[mb_pos].mv = ZERO_MV;
784 VPMBType::InterMV => {
785 let diff_mv = self.decode_mv(bc, br);
786 self.mb_info[mb_pos].mv = pred_mv + diff_mv;
788 VPMBType::InterNearest => {
789 self.mb_info[mb_pos].mv = nearest_mv;
791 VPMBType::InterNear => {
792 self.mb_info[mb_pos].mv = near_mv;
794 VPMBType::InterFourMV => {
796 four_mbt[i] = FOURMV_SUB_TYPE[bc.read_bits(2) as usize];
800 VPMBType::InterNoMV => {},
801 VPMBType::InterMV => {
802 let diff_mv = self.decode_mv(bc, br);
803 four_mv[i] = pred_mv + diff_mv;
805 VPMBType::InterNearest => {
806 four_mv[i] = nearest_mv;
808 VPMBType::InterNear => {
809 four_mv[i] = near_mv;
814 self.mb_info[mb_pos].mv = four_mv[3];
819 let (_num_mv, nearest_mv, near_mv, pred_mv) = self.find_mv_pred(VP_REF_GOLDEN);
821 VPMBType::GoldenNoMV => {
822 self.mb_info[mb_pos].mv = ZERO_MV;
824 VPMBType::GoldenMV => {
825 let diff_mv = self.decode_mv(bc, br);
826 self.mb_info[mb_pos].mv = pred_mv + diff_mv;
828 VPMBType::GoldenNearest => {
829 self.mb_info[mb_pos].mv = nearest_mv;
831 VPMBType::GoldenNear => {
832 self.mb_info[mb_pos].mv = near_mv;
837 if !mb_type.is_intra() && (mb_type != VPMBType::InterFourMV) {
838 self.do_mc(br, frm, mb_type, self.mb_info[mb_pos].mv, alpha);
839 } else if mb_type == VPMBType::InterFourMV {
840 self.do_fourmv(br, frm, &four_mv, alpha);
844 self.fstate.plane = if !alpha { 0 } else { 3 };
845 self.fstate.ctx_idx = blk_no >> 1;
846 self.fstate.top_ctx = self.top_ctx[self.fstate.plane][mb_x * 2 + (blk_no & 1)];
848 CoeffReader::None => {
849 br.decode_block(bc, &mut self.coeffs[blk_no], &self.models.coeff_models[0], &self.models.vp6models, &mut self.fstate)?;
851 CoeffReader::Bool(ref mut bcc) => {
852 br.decode_block(bcc, &mut self.coeffs[blk_no], &self.models.coeff_models[0], &self.models.vp6models, &mut self.fstate)?;
854 CoeffReader::Huff(ref mut brc) => {
855 br.decode_block_huff(brc, &mut self.coeffs[blk_no], &self.models.vp6models, &self.models.vp6huff, &mut self.fstate)?;
858 self.top_ctx[self.fstate.plane][mb_x * 2 + (blk_no & 1)] = self.fstate.top_ctx;
859 self.predict_dc(mb_type, mb_pos, blk_no, alpha);
861 let bx = mb_x * 2 + (blk_no & 1);
862 let by = mb_y * 2 + (blk_no >> 1);
863 let has_ac = self.fstate.last_idx[self.fstate.ctx_idx] > 0;
864 if mb_type.is_intra() {
867 vp_put_block(&mut self.coeffs[blk_no], bx, by, self.fstate.plane, frm);
869 vp_put_block_dc(&mut self.coeffs[blk_no], bx, by, self.fstate.plane, frm);
872 vp_put_block_ilace(&mut self.coeffs[blk_no], bx, by, self.fstate.plane, frm);
877 vp_add_block(&mut self.coeffs[blk_no], bx, by, self.fstate.plane, frm);
879 vp_add_block_dc(&mut self.coeffs[blk_no], bx, by, self.fstate.plane, frm);
882 vp_add_block_ilace(&mut self.coeffs[blk_no], bx, by, self.fstate.plane, frm);
888 self.fstate.plane = blk_no - 3;
889 self.fstate.ctx_idx = blk_no - 2;
890 self.fstate.top_ctx = self.top_ctx[self.fstate.plane][mb_x];
892 CoeffReader::None => {
893 br.decode_block(bc, &mut self.coeffs[blk_no], &self.models.coeff_models[1], &self.models.vp6models, &mut self.fstate)?;
895 CoeffReader::Bool(ref mut bcc) => {
896 br.decode_block(bcc, &mut self.coeffs[blk_no], &self.models.coeff_models[1], &self.models.vp6models, &mut self.fstate)?;
898 CoeffReader::Huff(ref mut brc) => {
899 br.decode_block_huff(brc, &mut self.coeffs[blk_no], &self.models.vp6models, &self.models.vp6huff, &mut self.fstate)?;
902 self.top_ctx[self.fstate.plane][mb_x] = self.fstate.top_ctx;
903 self.predict_dc(mb_type, mb_pos, blk_no, alpha);
905 let has_ac = self.fstate.last_idx[self.fstate.ctx_idx] > 0;
906 if mb_type.is_intra() {
908 vp_put_block(&mut self.coeffs[blk_no], mb_x, mb_y, self.fstate.plane, frm);
910 vp_put_block_dc(&mut self.coeffs[blk_no], mb_x, mb_y, self.fstate.plane, frm);
914 vp_add_block(&mut self.coeffs[blk_no], mb_x, mb_y, self.fstate.plane, frm);
916 vp_add_block_dc(&mut self.coeffs[blk_no], mb_x, mb_y, self.fstate.plane, frm);
923 fn do_mc(&mut self, br: &dyn VP56Parser, frm: &mut NASimpleVideoFrame<u8>, mb_type: VPMBType, mv: MV, alpha: bool) {
924 let x = self.fstate.mb_x * 16;
925 let y = self.fstate.mb_y * 16;
926 let plane = if !alpha { 0 } else { 3 };
927 let src = if mb_type.get_ref_id() == VP_REF_INTER {
928 self.shuf.get_last().unwrap()
930 self.shuf.get_golden().unwrap()
933 br.mc_block(frm, self.mc_buf.clone(), src.clone(), plane, x + 0, y + 0, mv, self.loop_thr);
934 br.mc_block(frm, self.mc_buf.clone(), src.clone(), plane, x + 8, y + 0, mv, self.loop_thr);
935 br.mc_block(frm, self.mc_buf.clone(), src.clone(), plane, x + 0, y + 8, mv, self.loop_thr);
936 br.mc_block(frm, self.mc_buf.clone(), src.clone(), plane, x + 8, y + 8, mv, self.loop_thr);
938 let x = self.fstate.mb_x * 8;
939 let y = self.fstate.mb_y * 8;
940 br.mc_block(frm, self.mc_buf.clone(), src.clone(), 1, x, y, mv, self.loop_thr);
941 br.mc_block(frm, self.mc_buf.clone(), src.clone(), 2, x, y, mv, self.loop_thr);
944 fn do_fourmv(&mut self, br: &dyn VP56Parser, frm: &mut NASimpleVideoFrame<u8>, mvs: &[MV; 4], alpha: bool) {
945 let x = self.fstate.mb_x * 16;
946 let y = self.fstate.mb_y * 16;
947 let plane = if !alpha { 0 } else { 3 };
948 let src = self.shuf.get_last().unwrap();
950 br.mc_block(frm, self.mc_buf.clone(), src.clone(),
951 plane, x + (blk_no & 1) * 8, y + (blk_no & 2) * 4,
952 mvs[blk_no], self.loop_thr);
955 let x = self.fstate.mb_x * 8;
956 let y = self.fstate.mb_y * 8;
957 let sum = mvs[0] + mvs[1] + mvs[2] + mvs[3];
958 let mv = MV { x: sum.x / 4, y: sum.y / 4 };
959 br.mc_block(frm, self.mc_buf.clone(), src.clone(), 1, x, y, mv, self.loop_thr);
960 br.mc_block(frm, self.mc_buf.clone(), src.clone(), 2, x, y, mv, self.loop_thr);
963 fn predict_dc(&mut self, mb_type: VPMBType, mb_pos: usize, blk_no: usize, alpha: bool) {
964 let mb_x = self.fstate.mb_x;
965 let is_luma = blk_no < 4;
966 let (plane, dcs) = if alpha { (0, &mut self.dc_a) } else {
968 4 => (1, &mut self.dc_u),
969 5 => (2, &mut self.dc_v),
970 _ => (0, &mut self.dc_y),
973 let dc_pos = if is_luma {
974 dcs.xpos + mb_x * 2 + (blk_no & 1) + (blk_no >> 1) * dcs.stride
978 let ref_id = mb_type.get_ref_id();
979 let has_left_blk = is_luma && ((blk_no & 1) != 0);
980 let has_top_blk = is_luma && ((blk_no & 2) != 0);
983 if has_left_blk || ((mb_x > 0) && (self.mb_info[mb_pos - 1].mb_type.get_ref_id() == ref_id)) {
984 dc_pred += dcs.data[dc_pos - 1];
987 if has_top_blk || ((mb_pos >= self.mb_w) && (self.mb_info[mb_pos - self.mb_w].mb_type.get_ref_id() == ref_id)) {
988 dc_pred += dcs.data[dc_pos - dcs.stride];
991 if self.version == 5 {
992 if (count < 2) && has_left_blk {
996 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) {
1000 if (count < 2) && mb_pos == 0 && !is_luma {
1003 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) {
1004 dc_pred += dcs.data[dc_pos + dcs.stride - 1];
1007 if (count < 2) && blk_no == 2 {
1008 dc_pred += dcs.data[dc_pos - dcs.stride + 1];
1011 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) {
1012 dc_pred += dcs.data[dc_pos - dcs.stride + 1];
1015 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) {
1016 dc_pred += dcs.data[dc_pos - dcs.stride + 1];
1021 dc_pred = self.last_dc[ref_id as usize][plane];
1022 } else if count == 2 {
1025 self.coeffs[blk_no][0] += dc_pred;
1026 self.last_dc[ref_id as usize][plane] = self.coeffs[blk_no][0];
1027 dcs.data[dc_pos] = self.coeffs[blk_no][0];
1028 self.coeffs[blk_no][0] = self.coeffs[blk_no][0].wrapping_mul(self.fstate.dc_quant);
1032 const VP56_DC_QUANTS: [i16; 64] = [
1033 47, 47, 47, 47, 45, 43, 43, 43,
1034 43, 43, 42, 41, 41, 40, 40, 40,
1035 40, 35, 35, 35, 35, 33, 33, 33,
1036 33, 32, 32, 32, 27, 27, 26, 26,
1037 25, 25, 24, 24, 23, 23, 19, 19,
1038 19, 19, 18, 18, 17, 16, 16, 16,
1039 16, 16, 15, 11, 11, 11, 10, 10,
1040 9, 8, 7, 5, 3, 3, 2, 2
1042 const VP56_AC_QUANTS: [i16; 64] = [
1043 94, 92, 90, 88, 86, 82, 78, 74,
1044 70, 66, 62, 58, 54, 53, 52, 51,
1045 50, 49, 48, 47, 46, 45, 44, 43,
1046 42, 40, 39, 37, 36, 35, 34, 33,
1047 32, 31, 30, 29, 28, 27, 26, 25,
1048 24, 23, 22, 21, 20, 19, 18, 17,
1049 16, 15, 14, 13, 12, 11, 10, 9,
1050 8, 7, 6, 5, 4, 3, 2, 1
1053 const VP56_FILTER_LIMITS: [u8; 64] = [
1054 14, 14, 13, 13, 12, 12, 10, 10,
1055 10, 10, 8, 8, 8, 8, 8, 8,
1056 8, 8, 8, 8, 8, 8, 8, 8,
1057 8, 8, 8, 8, 8, 8, 8, 8,
1058 8, 8, 8, 8, 7, 7, 7, 7,
1059 7, 7, 6, 6, 6, 6, 6, 6,
1060 5, 5, 5, 5, 4, 4, 4, 4,
1061 4, 4, 4, 3, 3, 3, 3, 2
1064 const VP56_MODE_VQ: [[[u8; 20]; 16]; 3] = [
1066 [ 9, 15, 32, 25, 7, 19, 9, 21, 1, 12, 14, 12, 3, 18, 14, 23, 3, 10, 0, 4 ],
1067 [ 48, 39, 1, 2, 11, 27, 29, 44, 7, 27, 1, 4, 0, 3, 1, 6, 1, 2, 0, 0 ],
1068 [ 21, 32, 1, 2, 4, 10, 32, 43, 6, 23, 2, 3, 1, 19, 1, 6, 12, 21, 0, 7 ],
1069 [ 69, 83, 0, 0, 0, 2, 10, 29, 3, 12, 0, 1, 0, 3, 0, 3, 2, 2, 0, 0 ],
1070 [ 11, 20, 1, 4, 18, 36, 43, 48, 13, 35, 0, 2, 0, 5, 3, 12, 1, 2, 0, 0 ],
1071 [ 70, 44, 0, 1, 2, 10, 37, 46, 8, 26, 0, 2, 0, 2, 0, 2, 0, 1, 0, 0 ],
1072 [ 8, 15, 0, 1, 8, 21, 74, 53, 22, 42, 0, 1, 0, 2, 0, 3, 1, 2, 0, 0 ],
1073 [ 141, 42, 0, 0, 1, 4, 11, 24, 1, 11, 0, 1, 0, 1, 0, 2, 0, 0, 0, 0 ],
1074 [ 8, 19, 4, 10, 24, 45, 21, 37, 9, 29, 0, 3, 1, 7, 11, 25, 0, 2, 0, 1 ],
1075 [ 46, 42, 0, 1, 2, 10, 54, 51, 10, 30, 0, 2, 0, 2, 0, 1, 0, 1, 0, 0 ],
1076 [ 28, 32, 0, 0, 3, 10, 75, 51, 14, 33, 0, 1, 0, 2, 0, 1, 1, 2, 0, 0 ],
1077 [ 100, 46, 0, 1, 3, 9, 21, 37, 5, 20, 0, 1, 0, 2, 1, 2, 0, 1, 0, 0 ],
1078 [ 27, 29, 0, 1, 9, 25, 53, 51, 12, 34, 0, 1, 0, 3, 1, 5, 0, 2, 0, 0 ],
1079 [ 80, 38, 0, 0, 1, 4, 69, 33, 5, 16, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0 ],
1080 [ 16, 20, 0, 0, 2, 8, 104, 49, 15, 33, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0 ],
1081 [ 194, 16, 0, 0, 1, 1, 1, 9, 1, 3, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0 ],
1083 [ 41, 22, 1, 0, 1, 31, 0, 0, 0, 0, 0, 1, 1, 7, 0, 1, 98, 25, 4, 10 ],
1084 [ 123, 37, 6, 4, 1, 27, 0, 0, 0, 0, 5, 8, 1, 7, 0, 1, 12, 10, 0, 2 ],
1085 [ 26, 14, 14, 12, 0, 24, 0, 0, 0, 0, 55, 17, 1, 9, 0, 36, 5, 7, 1, 3 ],
1086 [ 209, 5, 0, 0, 0, 27, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0 ],
1087 [ 2, 5, 4, 5, 0, 121, 0, 0, 0, 0, 0, 3, 2, 4, 1, 4, 2, 2, 0, 1 ],
1088 [ 175, 5, 0, 1, 0, 48, 0, 0, 0, 0, 0, 2, 0, 1, 0, 2, 0, 1, 0, 0 ],
1089 [ 83, 5, 2, 3, 0, 102, 0, 0, 0, 0, 1, 3, 0, 2, 0, 1, 0, 0, 0, 0 ],
1090 [ 233, 6, 0, 0, 0, 8, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0 ],
1091 [ 34, 16, 112, 21, 1, 28, 0, 0, 0, 0, 6, 8, 1, 7, 0, 3, 2, 5, 0, 2 ],
1092 [ 159, 35, 2, 2, 0, 25, 0, 0, 0, 0, 3, 6, 0, 5, 0, 1, 4, 4, 0, 1 ],
1093 [ 75, 39, 5, 7, 2, 48, 0, 0, 0, 0, 3, 11, 2, 16, 1, 4, 7, 10, 0, 2 ],
1094 [ 212, 21, 0, 1, 0, 9, 0, 0, 0, 0, 1, 2, 0, 2, 0, 0, 2, 2, 0, 0 ],
1095 [ 4, 2, 0, 0, 0, 172, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 2, 0, 0, 0 ],
1096 [ 187, 22, 1, 1, 0, 17, 0, 0, 0, 0, 3, 6, 0, 4, 0, 1, 4, 4, 0, 1 ],
1097 [ 133, 6, 1, 2, 1, 70, 0, 0, 0, 0, 0, 2, 0, 4, 0, 3, 1, 1, 0, 0 ],
1098 [ 251, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
1100 [ 2, 3, 2, 3, 0, 2, 0, 2, 0, 0, 11, 4, 1, 4, 0, 2, 3, 2, 0, 4 ],
1101 [ 49, 46, 3, 4, 7, 31, 42, 41, 0, 0, 2, 6, 1, 7, 1, 4, 2, 4, 0, 1 ],
1102 [ 26, 25, 1, 1, 2, 10, 67, 39, 0, 0, 1, 1, 0, 14, 0, 2, 31, 26, 1, 6 ],
1103 [ 103, 46, 1, 2, 2, 10, 33, 42, 0, 0, 1, 4, 0, 3, 0, 1, 1, 3, 0, 0 ],
1104 [ 14, 31, 9, 13, 14, 54, 22, 29, 0, 0, 2, 6, 4, 18, 6, 13, 1, 5, 0, 1 ],
1105 [ 85, 39, 0, 0, 1, 9, 69, 40, 0, 0, 0, 1, 0, 3, 0, 1, 2, 3, 0, 0 ],
1106 [ 31, 28, 0, 0, 3, 14, 130, 34, 0, 0, 0, 1, 0, 3, 0, 1, 3, 3, 0, 1 ],
1107 [ 171, 25, 0, 0, 1, 5, 25, 21, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0 ],
1108 [ 17, 21, 68, 29, 6, 15, 13, 22, 0, 0, 6, 12, 3, 14, 4, 10, 1, 7, 0, 3 ],
1109 [ 51, 39, 0, 1, 2, 12, 91, 44, 0, 0, 0, 2, 0, 3, 0, 1, 2, 3, 0, 1 ],
1110 [ 81, 25, 0, 0, 2, 9, 106, 26, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0 ],
1111 [ 140, 37, 0, 1, 1, 8, 24, 33, 0, 0, 1, 2, 0, 2, 0, 1, 1, 2, 0, 0 ],
1112 [ 14, 23, 1, 3, 11, 53, 90, 31, 0, 0, 0, 3, 1, 5, 2, 6, 1, 2, 0, 0 ],
1113 [ 123, 29, 0, 0, 1, 7, 57, 30, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0 ],
1114 [ 13, 14, 0, 0, 4, 20, 175, 20, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0 ],
1115 [ 202, 23, 0, 0, 1, 3, 2, 9, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0 ],