use nihav_core::formats::YUV420_FORMAT;
use nihav_core::frame::{NABufferType, NAVideoInfo, NAVideoBuffer, NAVideoBufferRef, FrameType, alloc_video_buffer};
-use nihav_core::codecs::{NADecoderSupport, MV, ZERO_MV, DecoderError, DecoderResult, IPBShuffler};
+use nihav_core::codecs::{NADecoderSupport, DecoderError, DecoderResult};
+use nihav_codec_support::codecs::{MV, ZERO_MV, IPBShuffler};
use nihav_core::io::bitreader::{BitReader,BitReaderMode};
use nihav_core::io::intcode::*;
-use nihav_core::data::GenericCache;
+use nihav_codec_support::data::GenericCache;
use std::mem;
use super::rv34codes::*;
}
pub trait RV34DSP {
- fn loop_filter(&self, frame: &mut NAVideoBuffer<u8>, ftype: FrameType, mbinfo: &[RV34MBInfo], mb_w: usize, row: usize);
+ fn loop_filter(&self, frame: &mut NAVideoBuffer<u8>, ftype: FrameType, mbinfo: &[RV34MBInfo], mb_w: usize, mb_h: usize, row: usize);
fn do_luma_mc(&self, frame: &mut NAVideoBuffer<u8>, prev_frame: &NAVideoBuffer<u8>, x: usize, y: usize, mv: MV, use16: bool, avg: bool);
fn do_chroma_mc(&self, frame: &mut NAVideoBuffer<u8>, prev_frame: &NAVideoBuffer<u8>, x: usize, y: usize, comp: usize, mv: MV, use8: bool, avg: bool);
}
if ini_off >= src.len() { return Err(DecoderError::ShortData); }
- let mut br = BitReader::new(&src[1..], ini_off - 1, BitReaderMode::BE);
+ let mut br = BitReader::new(&src[1..ini_off], BitReaderMode::BE);
for i in 0..num_slices {
br.skip(32)?;
validate!(slice_no < slice_offs.len());
br.seek((slice_offs[slice_no] * 8) as u32)?;
let mut shdr = bd.decode_slice_header(br, old_width, old_height)?;
+ if ((shdr.width == 0) || (shdr.height == 0)) && (shdr.ftype != FrameType::I) {
+ return Err(DecoderError::MissingReference);
+ }
if slice_no < slice_offs.len() - 1 {
let cur_pos = br.tell() as u32;
br.seek((slice_offs[slice_no + 1] * 8) as u32)?;
- let nhdr = bd.decode_slice_header(br, shdr.width, shdr.height)?;
+ if let Ok(nhdr) = bd.decode_slice_header(br, shdr.width, shdr.height) {
+ validate!(nhdr.start > shdr.start);
+ shdr.end = nhdr.start;
+ } else {
+ if slice_no + 2 < slice_offs.len() {
+ br.seek((slice_offs[slice_no + 2] * 8) as u32)?;
+ if let Ok(nhdr) = bd.decode_slice_header(br, shdr.width, shdr.height) {
+ validate!(nhdr.start > shdr.start);
+ shdr.end = nhdr.start;
+ } else {
+ shdr.end = ((shdr.width + 15) >> 4) * ((shdr.height + 15) >> 4);
+ }
+ } else {
+ shdr.end = ((shdr.width + 15) >> 4) * ((shdr.height + 15) >> 4);
+ }
+ }
br.seek(cur_pos)?;
- validate!(nhdr.start > shdr.start);
- shdr.end = nhdr.start;
} else {
shdr.end = ((shdr.width + 15) >> 4) * ((shdr.height + 15) >> 4);
}
const RV34_SLICE_START_BITS: [u8; 6] = [ 6, 7, 9, 11, 13, 14 ];
pub fn get_slice_start_offset_bits(w: usize, h: usize) -> u8 {
+ if (w == 0) || (h == 0) {
+ return 0;
+ }
let mb_size = ((w + 15) >> 4) * ((h + 15) >> 4) - 1;
let mut idx: usize = 0;
while (idx < 5) && (RV34_MB_MAX_SIZES[idx] < mb_size) { idx += 1; }
Ok(MV{ x, y })
}
-fn do_mc_16x16(dsp: &Box<dyn RV34DSP>, buf: &mut NAVideoBuffer<u8>, prevbuf: &NAVideoBuffer<u8>, mb_x: usize, mb_y: usize, mv: MV, avg: bool) {
+fn do_mc_16x16(dsp: &Box<dyn RV34DSP + Send>, buf: &mut NAVideoBuffer<u8>, prevbuf: &NAVideoBuffer<u8>, mb_x: usize, mb_y: usize, mv: MV, avg: bool) {
dsp.do_luma_mc (buf, prevbuf, mb_x * 16, mb_y * 16, mv, true, avg);
dsp.do_chroma_mc(buf, prevbuf, mb_x * 8, mb_y * 8, 1, mv, true, avg);
dsp.do_chroma_mc(buf, prevbuf, mb_x * 8, mb_y * 8, 2, mv, true, avg);
}
-fn do_mc_8x8(dsp: &Box<dyn RV34DSP>, buf: &mut NAVideoBuffer<u8>, prevbuf: &NAVideoBuffer<u8>, mb_x: usize, xoff: usize, mb_y: usize, yoff: usize, mv: MV, avg: bool) {
+fn do_mc_8x8(dsp: &Box<dyn RV34DSP + Send>, buf: &mut NAVideoBuffer<u8>, prevbuf: &NAVideoBuffer<u8>, mb_x: usize, xoff: usize, mb_y: usize, yoff: usize, mv: MV, avg: bool) {
dsp.do_luma_mc (buf, prevbuf, mb_x * 16 + xoff * 8, mb_y * 16 + yoff * 8, mv, false, avg);
dsp.do_chroma_mc(buf, prevbuf, mb_x * 8 + xoff * 4, mb_y * 8 + yoff * 4, 1, mv, false, avg);
dsp.do_chroma_mc(buf, prevbuf, mb_x * 8 + xoff * 4, mb_y * 8 + yoff * 4, 2, mv, false, avg);
pub struct RV34Decoder {
is_rv30: bool,
coderead: RV34Codes,
- dsp: Box<dyn RV34DSP>,
+ dsp: Box<dyn RV34DSP + Send>,
cdsp: RV34CommonDSP,
width: usize,
height: usize,
}
impl RV34Decoder {
- pub fn new(is_rv30: bool, dsp: Box<dyn RV34DSP>) -> Self {
+ pub fn new(is_rv30: bool, dsp: Box<dyn RV34DSP + Send>) -> Self {
let tmp_vinfo = NAVideoInfo::new(16, 16, false, YUV420_FORMAT);
let vt = alloc_video_buffer(tmp_vinfo, 4).unwrap();
let vb = vt.get_vbuf();
parse_slice_offsets(src, &mut slice_offs)?;
let ini_off = slice_offs.len() * 8 + 1;
- let mut br = BitReader::new(&src[ini_off..], src.len() - ini_off, BitReaderMode::BE);
+ let mut br = BitReader::new(&src[ini_off..], BitReaderMode::BE);
let hdr0 = decode_slice_header(&mut br, bd, 0, slice_offs.as_slice(), self.width, self.height)?;
validate!((hdr0.width != 0) && (hdr0.height != 0));
self.width = hdr0.width;
sstate.q_dc = bd.quant_dc(true, q);
self.decode_mb_intra(&sstate, &imode, &mut buf, &mut br, is_16)?;
} else {
+ sstate.q_dc = bd.quant_dc(false, q);
imode.fill_block(0);
self.decode_mb_inter(&sstate, &mbh, &mut buf, &mut br, is_16)?;
}
mb_pos += 1;
}
if hdr0.deblock && (mb_y >= 1) {
- self.dsp.loop_filter(&mut buf, hdr0.ftype, &mbinfo, mb_w, mb_y - 1);
+ self.dsp.loop_filter(&mut buf, hdr0.ftype, &mbinfo, mb_w, mb_h, mb_y - 1);
}
imode.update();
}
if hdr0.deblock {
- self.dsp.loop_filter(&mut buf, hdr0.ftype, &mbinfo, mb_w, mb_h - 1);
+ self.dsp.loop_filter(&mut buf, hdr0.ftype, &mbinfo, mb_w, mb_h, mb_h - 1);
}
if !self.is_b {
self.ipbs.add_frame(buf.clone());