X-Git-Url: https://git.nihav.org/?p=nihav.git;a=blobdiff_plain;f=nihav-realmedia%2Fsrc%2Fcodecs%2Frv3040.rs;h=e45b62b0682204306551761a04f147b1a3871264;hp=f7f5334aa2dfe48c99e00ba08c2fe30a26e7c783;hb=404d527a49c44e461ab887280b576969a80d87c0;hpb=e07387c7f125550a41faf36a509b252cf71d7f9a diff --git a/nihav-realmedia/src/codecs/rv3040.rs b/nihav-realmedia/src/codecs/rv3040.rs index f7f5334..e45b62b 100644 --- a/nihav-realmedia/src/codecs/rv3040.rs +++ b/nihav-realmedia/src/codecs/rv3040.rs @@ -1,51 +1,15 @@ 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_codec_support::data::GenericCache; use std::mem; use super::rv34codes::*; use super::rv34dsp::*; -pub struct GenericCache { - pub height: usize, - pub stride: usize, - pub xpos: usize, - pub data: Vec, - pub default: T, -} - -impl GenericCache { - pub fn new(height: usize, stride: usize, default: T) -> Self { - let mut ret = Self { - stride, - height, - xpos: 0, - data: Vec::with_capacity((height + 1) * stride), - default, - }; - ret.reset(); - ret - } - fn full_size(&self) -> usize { self.stride * (self.height + 1) } - pub fn reset(&mut self) { - self.data.truncate(0); - let size = self.full_size(); - self.data.resize(size, self.default); - self.xpos = self.stride + 1; - } - pub fn update_row(&mut self) { - for i in 0..self.stride { - self.data[i] = self.data[self.height * self.stride + i]; - } - self.data.truncate(self.stride); - let size = self.full_size(); - self.data.resize(size, self.default); - self.xpos = self.stride + 1; - } -} - trait RV34MVScale { fn scale(&self, trd: u16, trb: u16) -> (MV, MV); } @@ -551,7 +515,7 @@ fn parse_slice_offsets(src: &[u8], offsets: &mut Vec) -> DecoderResult<() 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)?; @@ -575,10 +539,23 @@ fn decode_slice_header(br: &mut BitReader, bd: &mut RV34BitstreamDecoder, slice_ 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); } @@ -716,13 +693,13 @@ fn decode_mv(br: &mut BitReader) -> DecoderResult { Ok(MV{ x, y }) } -fn do_mc_16x16(dsp: &Box, buf: &mut NAVideoBuffer, prevbuf: &NAVideoBuffer, mb_x: usize, mb_y: usize, mv: MV, avg: bool) { +fn do_mc_16x16(dsp: &Box, buf: &mut NAVideoBuffer, prevbuf: &NAVideoBuffer, 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, buf: &mut NAVideoBuffer, prevbuf: &NAVideoBuffer, mb_x: usize, xoff: usize, mb_y: usize, yoff: usize, mv: MV, avg: bool) { +fn do_mc_8x8(dsp: &Box, buf: &mut NAVideoBuffer, prevbuf: &NAVideoBuffer, 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); @@ -754,7 +731,7 @@ fn do_avg(cdsp: &RV34CommonDSP, buf: &mut NAVideoBuffer, avg_buf: &NAVideoBu pub struct RV34Decoder { is_rv30: bool, coderead: RV34Codes, - dsp: Box, + dsp: Box, cdsp: RV34CommonDSP, width: usize, height: usize, @@ -772,7 +749,7 @@ pub struct RV34Decoder { } impl RV34Decoder { - pub fn new(is_rv30: bool, dsp: Box) -> Self { + pub fn new(is_rv30: bool, dsp: Box) -> 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(); @@ -1117,7 +1094,7 @@ impl RV34Decoder { 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; @@ -1143,6 +1120,22 @@ impl RV34Decoder { self.base_ts += 1 << 13; } } + match hdr0.ftype { + FrameType::P => { + if self.ipbs.get_lastref().is_none() { + return Err(DecoderError::MissingReference); + } + }, + FrameType::B => { + if self.ipbs.get_lastref().is_none() { + return Err(DecoderError::MissingReference); + } + if self.ipbs.get_nextref().is_none() { + return Err(DecoderError::MissingReference); + } + }, + _ => {}, + }; let ts_diff = (self.next_ts << 3).wrapping_sub(hdr0.pts << 3) >> 3; let ts = self.base_ts + (self.next_ts as u64) - (ts_diff as u64); sstate.trd = (self.next_ts << 3).wrapping_sub(self.last_ts << 3) >> 3; @@ -1287,4 +1280,7 @@ impl RV34Decoder { Ok((NABufferType::Video(buf), hdr0.ftype, ts)) } + pub fn flush(&mut self) { + self.ipbs.clear(); + } }