mb_w: usize,
mb_h: usize,
models: VP56Models,
+ amodels: VP56Models,
coeffs: [[i16; 64]; 6],
last_mbt: VPMBType,
mb_w: 0,
mb_h: 0,
models: VP56Models::new(),
+ amodels: VP56Models::new(),
coeffs: [[0; 64]; 6],
last_mbt: VPMBType::InterNoMV,
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]];
}
pub fn init(&mut self, supp: &mut NADecoderSupport, vinfo: NAVideoInfo) -> DecoderResult<()> {
- supp.pool_u8.set_dec_bufs(3);
+ supp.pool_u8.set_dec_bufs(3 + if vinfo.get_format().has_alpha() { 1 } else { 0 });
supp.pool_u8.prealloc_video(NAVideoInfo::new(vinfo.get_width(), vinfo.get_height(), false, vinfo.get_format()), 4)?;
self.set_dimensions(vinfo.get_width(), vinfo.get_height());
self.dc_pred.resize(self.mb_w);
let hdr = br.parse_header(&mut bc)?;
validate!((hdr.offset as usize) < aoffset); //XXX: take alpha 3 byte offset into account?
- if hdr.mb_w != 0 {
+ if hdr.mb_w != 0 && (usize::from(hdr.mb_w) != self.mb_w || usize::from(hdr.mb_h) != self.mb_h) {
self.set_dimensions((hdr.mb_w as usize) * 16, (hdr.mb_h as usize) * 16);
}
let fmt = if !self.has_alpha {
}
}
+ let psrc = &src[if self.has_alpha { 3 } else { 0 }..aoffset];
+ self.decode_planes(br, &mut dframe, &mut bc, &hdr, psrc, false)?;
+
+ if self.has_alpha {
+ let asrc = &src[aoffset + 3..];
+ let mut bc = BoolCoder::new(asrc)?;
+ let ahdr = br.parse_header(&mut bc)?;
+ validate!(ahdr.mb_w == hdr.mb_w && ahdr.mb_h == hdr.mb_h);
+ std::mem::swap(&mut self.models, &mut self.amodels);
+ let ret = self.decode_planes(br, &mut dframe, &mut bc, &ahdr, asrc, true);
+ std::mem::swap(&mut self.models, &mut self.amodels);
+ if let Err(err) = ret {
+ return Err(err);
+ }
+ match (hdr.is_golden, ahdr.is_golden) {
+ (true, true) => { self.shuf.add_golden_frame(buf.clone()); },
+ (true, false) => {
+ let cur_golden = self.shuf.get_golden().unwrap();
+ let off = cur_golden.get_offset(3);
+ let stride = cur_golden.get_stride(3);
+ let mut new_golden = supp.pool_u8.get_copy(&buf).unwrap();
+ let dst = new_golden.get_data_mut().unwrap();
+ let src = cur_golden.get_data();
+ dst[off..][..stride * self.mb_h * 16].copy_from_slice(&src[off..][..stride * self.mb_h * 16]);
+ self.shuf.add_golden_frame(new_golden);
+ },
+ (false, true) => {
+ let cur_golden = self.shuf.get_golden().unwrap();
+ let off = cur_golden.get_offset(3);
+ let stride = cur_golden.get_stride(3);
+ let mut new_golden = supp.pool_u8.get_copy(&cur_golden).unwrap();
+ let dst = new_golden.get_data_mut().unwrap();
+ let src = buf.get_data();
+ dst[off..][..stride * self.mb_h * 16].copy_from_slice(&src[off..][..stride * self.mb_h * 16]);
+ self.shuf.add_golden_frame(new_golden);
+ },
+ _ => {},
+ };
+ }
+
+ if hdr.is_golden && !self.has_alpha {
+ self.shuf.add_golden_frame(buf.clone());
+ }
+ self.shuf.add_frame(buf.clone());
+
+ Ok((NABufferType::Video(buf), if hdr.is_intra { FrameType::I } else { FrameType::P }))
+ }
+ fn decode_planes(&mut self, br: &mut dyn VP56Parser, dframe: &mut NASimpleVideoFrame<u8>, bc: &mut BoolCoder, hdr: &VP56Header, src: &[u8], alpha: bool) -> DecoderResult<()> {
let mut cr;
if hdr.multistream {
- let off = (if self.has_alpha { 3 } else { 0 }) + (hdr.offset as usize);
+ let off = hdr.offset as usize;
if !hdr.use_huffman {
let bc2 = BoolCoder::new(&src[off..])?;
cr = CoeffReader::Bool(bc2);
} else {
- let br = BitReader::new(&src[off..aoffset], BitReaderMode::BE);
+ let br = BitReader::new(&src[off..], BitReaderMode::BE);
cr = CoeffReader::Huff(br);
}
} else {
br.reset_models(&mut self.models);
self.reset_mbtype_models();
} else {
- self.decode_mode_prob_models(&mut bc)?;
- br.decode_mv_models(&mut bc, &mut self.models.mv_models)?;
+ self.decode_mode_prob_models(bc)?;
+ br.decode_mv_models(bc, &mut self.models.mv_models)?;
}
- br.decode_coeff_models(&mut bc, &mut self.models, hdr.is_intra)?;
+ br.decode_coeff_models(bc, &mut self.models, hdr.is_intra)?;
if hdr.use_huffman {
for i in 0..2 {
self.models.vp6huff.dc_token_tree[i].build_codes(&self.models.coeff_models[i].dc_value_probs);
self.fstate.last_idx = [24; 4];
for mb_x in 0..self.mb_w {
self.fstate.mb_x = mb_x;
- self.decode_mb(&mut dframe, &mut bc, &mut cr, br, &hdr, false)?;
+ self.decode_mb(dframe, bc, &mut cr, br, &hdr, alpha)?;
self.dc_pred.next_mb();
}
self.dc_pred.update_row();
}
-
- if self.has_alpha {
- let asrc = &src[aoffset + 3..];
- let mut bc = BoolCoder::new(asrc)?;
- let ahdr = br.parse_header(&mut bc)?;
- validate!(ahdr.mb_w == hdr.mb_w && ahdr.mb_h == hdr.mb_h);
- }
-
- if hdr.is_golden {
- self.shuf.add_golden_frame(buf.clone());
- }
- self.shuf.add_frame(buf.clone());
-
- Ok((NABufferType::Video(buf), if hdr.is_intra { FrameType::I } else { FrameType::P }))
+ Ok(())
}
fn reset_mbtype_models(&mut self) {
const DEFAULT_XMITTED_PROBS: [[u8; 20]; 3] = [
}
}
}
- if !alpha {
- for blk_no in 4..6 {
- self.fstate.plane = blk_no - 3;
- self.fstate.ctx_idx = blk_no - 2;
- self.fstate.top_ctx = self.top_ctx[self.fstate.plane][mb_x];
- match cr {
- CoeffReader::None => {
- br.decode_block(bc, &mut self.coeffs[blk_no], &self.models.coeff_models[1], &self.models.vp6models, &mut self.fstate)?;
- },
- CoeffReader::Bool(ref mut bcc) => {
- br.decode_block(bcc, &mut self.coeffs[blk_no], &self.models.coeff_models[1], &self.models.vp6models, &mut self.fstate)?;
- },
- CoeffReader::Huff(ref mut brc) => {
- br.decode_block_huff(brc, &mut self.coeffs[blk_no], &self.models.vp6models, &self.models.vp6huff, &mut self.fstate)?;
- },
- };
- self.top_ctx[self.fstate.plane][mb_x] = self.fstate.top_ctx;
- self.predict_dc(mb_type, mb_pos, blk_no, alpha);
-
+ for blk_no in 4..6 {
+ self.fstate.plane = blk_no - 3;
+ self.fstate.ctx_idx = blk_no - 2;
+ self.fstate.top_ctx = self.top_ctx[self.fstate.plane][mb_x];
+ match cr {
+ CoeffReader::None => {
+ br.decode_block(bc, &mut self.coeffs[blk_no], &self.models.coeff_models[1], &self.models.vp6models, &mut self.fstate)?;
+ },
+ CoeffReader::Bool(ref mut bcc) => {
+ br.decode_block(bcc, &mut self.coeffs[blk_no], &self.models.coeff_models[1], &self.models.vp6models, &mut self.fstate)?;
+ },
+ CoeffReader::Huff(ref mut brc) => {
+ br.decode_block_huff(brc, &mut self.coeffs[blk_no], &self.models.vp6models, &self.models.vp6huff, &mut self.fstate)?;
+ },
+ };
+ self.top_ctx[self.fstate.plane][mb_x] = self.fstate.top_ctx;
+ self.predict_dc(mb_type, mb_pos, blk_no, alpha);
+ if !alpha {
let has_ac = self.fstate.last_idx[self.fstate.ctx_idx] > 0;
if mb_type.is_intra() {
if has_ac {