replace vec.truncate(0) with vec.clear()
[nihav.git] / nihav-realmedia / src / codecs / rv3040.rs
index adde67840a340a2d74f0c2f1fcea6b70631b85ee..762d05459b3b11172f9f89b3c2aa321d8ac1086a 100644 (file)
@@ -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::{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<T: Copy> {
-    pub height: usize,
-    pub stride: usize,
-    pub xpos:   usize,
-    pub data:   Vec<T>,
-    pub default: T,
-}
-
-impl<T:Copy> GenericCache<T> {
-    pub fn new(height: usize, stride: usize, default: T) -> Self {
-        let mut ret = Self {
-                stride: stride,
-                height: height,
-                xpos:   0,
-                data:   Vec::with_capacity((height + 1) * stride),
-                default: 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);
 }
@@ -106,17 +70,17 @@ pub enum MBType {
 }
 
 impl MBType {
-    pub fn is_intra(&self) -> bool {
-        (*self == MBType::MBIntra) || (*self == MBType::MBIntra16)
+    pub fn is_intra(self) -> bool {
+        (self == MBType::MBIntra) || (self == MBType::MBIntra16)
     }
-    pub fn is_16(&self) -> bool {
-        (*self == MBType::MBIntra16) || (*self == MBType::MBP16x16Mix)
+    pub fn is_16(self) -> bool {
+        (self == MBType::MBIntra16) || (self == MBType::MBP16x16Mix)
     }
-    pub fn is_intra_or_16(&self) -> bool {
+    pub fn is_intra_or_16(self) -> bool {
         self.is_intra() || self.is_16()
     }
-    pub fn get_num_mvs(&self) -> usize {
-        match *self {
+    pub fn get_num_mvs(self) -> usize {
+        match self {
             MBType::MBIntra | MBType::MBIntra16 |
             MBType::MBSkip | MBType::MBDirect                       => 0,
             MBType::MBP16x16 | MBType::MBP16x16Mix |
@@ -126,42 +90,42 @@ impl MBType {
             MBType::Invalid => unreachable!(),
         }
     }
-    pub fn is_fwd(&self) -> bool {
-        match *self {
+    pub fn is_fwd(self) -> bool {
+        match self {
             MBType::MBP16x16 | MBType::MBP16x16Mix |
             MBType::MBP16x8 | MBType::MBP8x16 | MBType::MBP8x8 |
             MBType::MBForward => true,
             _ => false,
         }
     }
-    pub fn is_bwd(&self) -> bool {
-        match *self {
+    pub fn is_bwd(self) -> bool {
+        match self {
             MBType::MBBidir | MBType::MBBackward => true,
             _                  => false,
         }
     }
-    pub fn has_mv_dir(&self, fwd: bool) -> bool {
-        match *self {
+    pub fn has_mv_dir(self, fwd: bool) -> bool {
+        match self {
             MBType::MBBidir             => true,
             MBType::MBForward  if  fwd  => true,
             MBType::MBBackward if !fwd  => true,
             _ => false,
         }
     }
-    pub fn is_nomv(&self) -> bool {
-        match *self {
+    pub fn is_nomv(self) -> bool {
+        match self {
             MBType::MBIntra | MBType::MBIntra16 | MBType::MBSkip | MBType::MBDirect => true,
             _                  => false,
         }
     }
-    /*pub fn is_16x16(&self) -> bool {
-        match *self {
+    /*pub fn is_16x16(self) -> bool {
+        match self {
             MBType::MBP16x8 | MBType::MBP8x16 | MBType::MBP8x8 => false,
             _ => true,
         }
     }*/
-    fn get_weight(&self) -> usize {
-        match *self {
+    fn get_weight(self) -> usize {
+        match self {
             MBType::MBIntra     => 0,
             MBType::MBIntra16   => 1,
             MBType::MBSkip      => unreachable!(),
@@ -362,13 +326,13 @@ impl MVInfo {
     }
     fn reset(&mut self) {
         let size = self.w * self.h;
-        self.mv_f.truncate(0);
+        self.mv_f.clear();
         self.mv_f.resize(size, ZERO_MV);
-        self.mv_b.truncate(0);
+        self.mv_b.clear();
         self.mv_b.resize(size, ZERO_MV);
-        self.has_f.truncate(0);
+        self.has_f.clear();
         self.has_f.resize(size >> 2, false);
-        self.has_b.truncate(0);
+        self.has_b.clear();
         self.has_b.resize(size >> 2, false);
     }
     fn fill(&mut self, mb_x: usize, mb_y: usize, fwd: bool, mv: MV) {
@@ -535,11 +499,11 @@ pub trait RV34BitstreamDecoder {
     fn decode_intra_pred(&mut self, br: &mut BitReader, types: &mut [i8], pos: usize, tstride: usize, has_top: bool) -> DecoderResult<()>;
     fn quant_dc(&self, is_intra: bool, q: u8) -> u8;
     fn decode_inter_mb_hdr(&mut self, br: &mut BitReader, ftype: FrameType, mbtype: MBType) -> DecoderResult<MBInfo>;
-    fn predict_b_mv(&self, sstate: &SState, mvi: &MVInfo, mbtype: MBType, mvs: &[MV], mbinfo: &Vec<RV34MBInfo>) -> (MV, MV);
+    fn predict_b_mv(&self, sstate: &SState, mvi: &MVInfo, mbtype: MBType, mvs: &[MV], mbinfo: &[RV34MBInfo]) -> (MV, MV);
 }
 
 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);
 }
@@ -547,11 +511,11 @@ pub trait RV34DSP {
 fn parse_slice_offsets(src: &[u8], offsets: &mut Vec<usize>) -> DecoderResult<()> {
     let num_slices = (src[0] as usize) + 1;
     let ini_off = num_slices * 8 + 1;
-    offsets.truncate(0);
+    offsets.clear();
 
     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)?;
@@ -568,17 +532,33 @@ fn parse_slice_offsets(src: &[u8], offsets: &mut Vec<usize>) -> DecoderResult<()
     Ok(())
 }
 
-fn decode_slice_header(br: &mut BitReader, bd: &mut RV34BitstreamDecoder, slice_no: usize, slice_offs: &Vec<usize>, old_width: usize, old_height: usize) -> DecoderResult<RV34SliceHeader> {
+fn decode_slice_header(br: &mut BitReader, bd: &mut dyn RV34BitstreamDecoder, slice_no: usize, slice_offs: &[usize], old_width: usize, old_height: usize) -> DecoderResult<RV34SliceHeader> {
     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);
     }
@@ -589,6 +569,9 @@ const RV34_MB_MAX_SIZES: [usize; 6] = [ 0x2F, 0x62, 0x18B, 0x62F, 0x18BF, 0x23FF
 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; }
@@ -713,16 +696,16 @@ impl MBHist {
 fn decode_mv(br: &mut BitReader) -> DecoderResult<MV> {
     let x = br.read_code_signed(IntCodeType::Gamma)? as i16;
     let y = br.read_code_signed(IntCodeType::Gamma)? as i16;
-    Ok(MV{ x: x, y: y })
+    Ok(MV{ x, y })
 }
 
-fn do_mc_16x16(dsp: &Box<RV34DSP>, buf: &mut NAVideoBuffer<u8>, prevbuf: &NAVideoBuffer<u8>, mb_x: usize, mb_y: usize, mv: MV, avg: bool) {
+fn do_mc_16x16(dsp: &mut dyn RV34DSP, 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<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: &mut dyn RV34DSP, 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);
@@ -754,7 +737,7 @@ fn do_avg(cdsp: &RV34CommonDSP, buf: &mut NAVideoBuffer<u8>, avg_buf: &NAVideoBu
 pub struct RV34Decoder {
     is_rv30:    bool,
     coderead:   RV34Codes,
-    dsp:        Box<RV34DSP>,
+    dsp:        Box<dyn RV34DSP + Send>,
     cdsp:       RV34CommonDSP,
     width:      usize,
     height:     usize,
@@ -772,15 +755,15 @@ pub struct RV34Decoder {
 }
 
 impl RV34Decoder {
-    pub fn new(is_rv30: bool, dsp: Box<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();
         let avg_buf = vb.unwrap();
         RV34Decoder {
-            is_rv30:    is_rv30,
+            is_rv30,
             coderead:   RV34Codes::new(),
-            dsp:        dsp,
+            dsp,
             cdsp:       RV34CommonDSP::new(),
             ipbs:       IPBShuffler::new(),
             mvi:        MVInfo::new(),
@@ -790,15 +773,15 @@ impl RV34Decoder {
             last_ts: 0, next_ts: 0,
             ratio1: 0, ratio2: 0,
             is_b:       false,
-            avg_buf:    avg_buf,
+            avg_buf,
             base_ts:    0,
         }
     }
-    fn decode_mb_header_intra(&mut self, bd: &mut RV34BitstreamDecoder, br: &mut BitReader, is_i16: bool, im: &mut IntraModeState, q: u8, has_top: bool, has_dq: bool) -> DecoderResult<MBInfo> {
+    fn decode_mb_header_intra(&mut self, bd: &mut dyn RV34BitstreamDecoder, br: &mut BitReader, is_i16: bool, im: &mut IntraModeState, q: u8, has_top: bool, has_dq: bool) -> DecoderResult<MBInfo> {
         if is_i16 {
             let imode = br.read(2)? as i8;
             im.fill_block(imode);
-            return Ok(MBInfo { mbtype: MBType::MBIntra16, skip_run: 0, dquant: false });
+            Ok(MBInfo { mbtype: MBType::MBIntra16, skip_run: 0, dquant: false })
         } else {
             let dq = if !has_dq {
                     if !self.is_rv30 { !br.read_bool()? } else { false }
@@ -807,10 +790,10 @@ impl RV34Decoder {
                 decode_dquant(br, q)?;
             }
             bd.decode_intra_pred(br, im.cache.data.as_mut_slice(), im.cache.xpos, im.cache.stride, has_top)?;
-            return Ok(MBInfo { mbtype: MBType::MBIntra, skip_run: 0, dquant: dq });
+            Ok(MBInfo { mbtype: MBType::MBIntra, skip_run: 0, dquant: dq })
         }
     }
-    fn decode_mb_header_inter(&mut self, bd: &mut RV34BitstreamDecoder, br: &mut BitReader, ftype: FrameType, mbtype: MBType, im: &mut IntraModeState, q: u8, has_top: bool) -> DecoderResult<MBInfo> {
+    fn decode_mb_header_inter(&mut self, bd: &mut dyn RV34BitstreamDecoder, br: &mut BitReader, ftype: FrameType, mbtype: MBType, im: &mut IntraModeState, q: u8, has_top: bool) -> DecoderResult<MBInfo> {
         let hdr = bd.decode_inter_mb_hdr(br, ftype, mbtype)?;
         validate!(hdr.mbtype != MBType::Invalid);
         if hdr.dquant {
@@ -819,7 +802,7 @@ impl RV34Decoder {
         if hdr.mbtype.is_intra() {
             return self.decode_mb_header_intra(bd, br, hdr.mbtype.is_16(), im, q, has_top, true);
         }
-        return Ok(hdr);
+        Ok(hdr)
     }
 
     fn decode_mb_intra(&mut self, sstate: &SState, imode: &IntraModeState, buf: &mut NAVideoBuffer<u8>, br: &mut BitReader, is_16: bool) -> DecoderResult<()> {
@@ -941,19 +924,19 @@ impl RV34Decoder {
             MBType::MBP16x16 | MBType::MBP16x16Mix => {
                     if let Some(ref prevbuf) = self.ipbs.get_lastref() {
                         let mv = self.mvi.get_mv(mb_x, mb_y, 0, 0, true);
-                        do_mc_16x16(&self.dsp, buf, prevbuf, mb_x, mb_y, mv, false);
+                        do_mc_16x16(self.dsp.as_mut(), buf, prevbuf, mb_x, mb_y, mv, false);
                     }
                 },
             MBType::MBForward => {
                     if let Some(ref fwdbuf) = self.ipbs.get_b_fwdref() {
                         let mv = self.mvi.get_mv(mb_x, mb_y, 0, 0, true);
-                        do_mc_16x16(&self.dsp, buf, fwdbuf, mb_x, mb_y, mv, false);
+                        do_mc_16x16(self.dsp.as_mut(), buf, fwdbuf, mb_x, mb_y, mv, false);
                     }
                 },
             MBType::MBBackward => {
                     if let Some(ref bwdbuf) = self.ipbs.get_b_bwdref() {
                         let mv = self.mvi.get_mv(mb_x, mb_y, 0, 0, false);
-                        do_mc_16x16(&self.dsp, buf, bwdbuf, mb_x, mb_y, mv, false);
+                        do_mc_16x16(self.dsp.as_mut(), buf, bwdbuf, mb_x, mb_y, mv, false);
                     }
                 },
             MBType::MBP8x8 | MBType::MBP8x16 | MBType::MBP16x8 => {
@@ -961,14 +944,14 @@ impl RV34Decoder {
                         for y in 0..2 {
                             for x in 0..2 {
                                 let mv = self.mvi.get_mv(mb_x, mb_y, x, y, true);
-                                do_mc_8x8(&self.dsp, buf, prevbuf, mb_x, x, mb_y, y, mv, false);
+                                do_mc_8x8(self.dsp.as_mut(), buf, prevbuf, mb_x, x, mb_y, y, mv, false);
                             }
                         }
                     }
                 },
             MBType::MBSkip if !self.is_b => {
                     if let Some(ref prevbuf) = self.ipbs.get_lastref() {
-                        do_mc_16x16(&self.dsp, buf, prevbuf, mb_x, mb_y, ZERO_MV, false);
+                        do_mc_16x16(self.dsp.as_mut(), buf, prevbuf, mb_x, mb_y, ZERO_MV, false);
                     }
                 },
             MBType::MBSkip | MBType::MBDirect => {
@@ -976,8 +959,8 @@ impl RV34Decoder {
                         for y in 0..2 {
                             for x in 0..2 {
                                 let (mv_f, mv_b) = self.ref_mvi.get_mv(mb_x, mb_y, x, y, true).scale(sstate.trd, sstate.trb);
-                                do_mc_8x8(&self.dsp, buf, fwdbuf, mb_x, x, mb_y, y, mv_f, false);
-                                do_mc_8x8(&self.dsp, &mut self.avg_buf, bwdbuf, mb_x, x, mb_y, y, mv_b, true);
+                                do_mc_8x8(self.dsp.as_mut(), buf, fwdbuf, mb_x, x, mb_y, y, mv_f, false);
+                                do_mc_8x8(self.dsp.as_mut(), &mut self.avg_buf, bwdbuf, mb_x, x, mb_y, y, mv_b, true);
                                 do_avg(&self.cdsp, buf, &self.avg_buf, mb_x, x, mb_y, y, 8, self.ratio1, self.ratio2);
                             }
                         }
@@ -987,8 +970,8 @@ impl RV34Decoder {
                     if let (Some(ref fwdbuf), Some(ref bwdbuf)) = (self.ipbs.get_b_fwdref(), self.ipbs.get_b_bwdref()) {
                         let mv_f = self.mvi.get_mv(mb_x, mb_y, 0, 0, true);
                         let mv_b = self.mvi.get_mv(mb_x, mb_y, 0, 0, false);
-                        do_mc_16x16(&self.dsp, buf, fwdbuf, mb_x, mb_y, mv_f, false);
-                        do_mc_16x16(&self.dsp, &mut self.avg_buf, bwdbuf, mb_x, mb_y, mv_b, true);
+                        do_mc_16x16(self.dsp.as_mut(), buf, fwdbuf, mb_x, mb_y, mv_f, false);
+                        do_mc_16x16(self.dsp.as_mut(), &mut self.avg_buf, bwdbuf, mb_x, mb_y, mv_b, true);
                         do_avg(&self.cdsp, buf, &self.avg_buf, mb_x, 0, mb_y, 0, 16, self.ratio1, self.ratio2);
                     }
                 },
@@ -1112,13 +1095,14 @@ impl RV34Decoder {
         }
     }
 
-    pub fn parse_frame(&mut self, src: &[u8], bd: &mut RV34BitstreamDecoder) -> DecoderResult<(NABufferType, FrameType, u64)> {
+    #[allow(clippy::cognitive_complexity)]
+    pub fn parse_frame(&mut self, supp: &mut NADecoderSupport, src: &[u8], bd: &mut dyn RV34BitstreamDecoder) -> DecoderResult<(NABufferType, FrameType, u64)> {
         let mut slice_offs: Vec<usize> = Vec::new();
         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 hdr0 = decode_slice_header(&mut br, bd, 0, &slice_offs, self.width, self.height)?;
+        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;
         self.height = hdr0.height;
@@ -1143,6 +1127,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;
@@ -1157,10 +1157,21 @@ impl RV34Decoder {
         //todo validate against ref frame
 
         let vinfo = NAVideoInfo::new(hdr0.width, hdr0.height, false, YUV420_FORMAT);
-        let bufret = alloc_video_buffer(vinfo, 4);
-        if let Err(_) = bufret { return Err(DecoderError::InvalidData); }
-        let bufinfo = bufret.unwrap();
-        let mut buf = bufinfo.get_vbuf().unwrap();
+        let ret = supp.pool_u8.get_free();
+        if ret.is_none() {
+            return Err(DecoderError::AllocError);
+        }
+        let mut buf = ret.unwrap();
+        if buf.get_info() != vinfo {
+            self.ipbs.clear();
+            supp.pool_u8.reset();
+            supp.pool_u8.prealloc_video(vinfo, 4)?;
+            let ret = supp.pool_u8.get_free();
+            if ret.is_none() {
+                return Err(DecoderError::AllocError);
+            }
+            buf = ret.unwrap();
+        }
 
         sstate.q = q;
         sstate.has_top = false;
@@ -1221,7 +1232,7 @@ impl RV34Decoder {
                     if !self.is_b {
                         self.mvi.set_mb(mb_x, mb_y, mbh.mbtype, &self.ref_mvi, &mvs, &sstate);
                     } else {
-                        let (mv_f, mv_b) = bd.predict_b_mv(&sstate, &self.mvi, mbh.mbtype, &mvs, &mbinfo);
+                        let (mv_f, mv_b) = bd.predict_b_mv(&sstate, &self.mvi, mbh.mbtype, &mvs, mbinfo.as_slice());
                         self.mvi.fill(mb_x, mb_y, true,  mv_f);
                         self.mvi.fill(mb_x, mb_y, false, mv_b);
                     }
@@ -1245,11 +1256,12 @@ impl RV34Decoder {
                     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)?;
                 }
 
-                let mi = RV34MBInfo { cbp: cbp, q: q, mbtype: mbh.mbtype, deblock: 0, cbp_c: 0 };
+                let mi = RV34MBInfo { cbp, q, mbtype: mbh.mbtype, deblock: 0, cbp_c: 0 };
                 mbinfo.push(mi);
                 if is_intra {
                     mbinfo[mb_pos].deblock = 0xFFFF;
@@ -1261,19 +1273,22 @@ impl RV34Decoder {
                 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);
+            self.ipbs.add_frame(buf.clone());
             mem::swap(&mut self.mvi, &mut self.ref_mvi);
             mem::swap(&mut self.mbinfo, &mut mbinfo);
         }
 
-        Ok((bufinfo, hdr0.ftype, ts))
+        Ok((NABufferType::Video(buf), hdr0.ftype, ts))
+    }
+    pub fn flush(&mut self) {
+        self.ipbs.clear();
     }
 }