make all codec crates export just register_all functions and document them
[nihav.git] / nihav-realmedia / src / codecs / rv60.rs
index 2ec99ede09c9e4450c8598c86e84b6e5ee116a0c..801f8c212706df7733f8039686251412851afb36 100644 (file)
@@ -21,7 +21,7 @@ impl<A:Copy+Default+PartialEq> UniqueList<A> {
     fn add(&mut self, cand: A) {
         if self.fill == self.max_size { return; }
         let mut unique = true;
-        for el in self.list.into_iter().take(self.fill) {
+        for el in self.list.iter().take(self.fill) {
             if *el == cand {
                 unique = false;
                 break;
@@ -253,62 +253,62 @@ enum PUType {
 
 const RV60_PU_TYPES: [PUType; 8] = [
     PUType::Full,   PUType::N2Hor,  PUType::N2Ver,  PUType::Quarters,
-    PUType::N4Hor,  PUType::N34Hor, PUType::N4Ver,  PUType::N34Ver, 
+    PUType::N4Hor,  PUType::N34Hor, PUType::N4Ver,  PUType::N34Ver,
 ];
 
 impl PUType {
-    fn get_num_mvs(&self) -> usize {
-        match *self {
+    fn get_num_mvs(self) -> usize {
+        match self {
             PUType::Full        => 1,
             PUType::Quarters    => 4,
             _                   => 2,
         }
     }
-    fn get_mv_size(&self, part_no: usize, size: usize) -> (usize, usize) {
+    fn get_mv_size(self, part_no: usize, size: usize) -> (usize, usize) {
         let mv_size = size >> 2;
-        match *self {
+        match self {
             PUType::Full        => (mv_size, mv_size),
             PUType::N2Hor       => (mv_size, mv_size >> 1),
             PUType::N2Ver       => (mv_size >> 1, mv_size),
             PUType::Quarters    => (mv_size >> 1, mv_size >> 1),
             PUType::N4Hor       => {
                     if part_no == 0 {
-                        (mv_size,     mv_size >> 2)
+                        (mv_size,      mv_size  >> 2)
                     } else {
-                        (mv_size, 3 * mv_size >> 2)
+                        (mv_size, (3 * mv_size) >> 2)
                     }
                 },
             PUType::N34Hor      => {
                     if part_no == 0 {
-                        (mv_size, 3 * mv_size >> 2)
+                        (mv_size, (3 * mv_size) >> 2)
                     } else {
-                        (mv_size,     mv_size >> 2)
+                        (mv_size,      mv_size  >> 2)
                     }
                 },
             PUType::N4Ver       => {
                     if part_no == 0 {
-                        (    mv_size >> 2, mv_size)
+                        (     mv_size  >> 2, mv_size)
                     } else {
-                        (3 * mv_size >> 2, mv_size)
+                        ((3 * mv_size) >> 2, mv_size)
                     }
                 },
             PUType::N34Ver      => {
                     if part_no == 0 {
-                        (3 * mv_size >> 2, mv_size)
+                        ((3 * mv_size) >> 2, mv_size)
                     } else {
-                        (    mv_size >> 2, mv_size)
+                        (     mv_size  >> 2, mv_size)
                     }
                 },
         }
     }
-    fn has_hor_split(&self) -> bool {
-        match *self {
+    fn has_hor_split(self) -> bool {
+        match self {
             PUType::N2Hor | PUType::N4Hor | PUType::N34Hor | PUType::Quarters => true,
             _ => false,
         }
     }
-    fn has_ver_split(&self) -> bool {
-        match *self {
+    fn has_ver_split(self) -> bool {
+        match self {
             PUType::N2Ver | PUType::N4Ver | PUType::N34Ver | PUType::Quarters => true,
             _ => false,
         }
@@ -355,28 +355,28 @@ enum MVRef {
 const SKIP_MV_REF: [MVRef; 4] = [ MVRef::Skip0,  MVRef::Skip1, MVRef::Skip2,  MVRef::Skip3 ];
 
 impl MVRef {
-    fn get_skip_mv_num(&self) -> usize {
-        match *self {
+    fn get_skip_mv_num(self) -> usize {
+        match self {
             MVRef::Skip1    => 1,
             MVRef::Skip2    => 2,
             MVRef::Skip3    => 3,
             _               => 0,
         }
     }
-    fn is_ref0(&self) -> bool {
-        match *self {
+    fn is_ref0(self) -> bool {
+        match self {
             MVRef::Ref0 | MVRef::Ref0AndBRef => true,
             _ => false,
         }
     }
-    fn is_fwd(&self) -> bool {
-        match *self {
+    fn is_fwd(self) -> bool {
+        match self {
             MVRef::Ref0 | MVRef::Ref1 | MVRef::Ref0AndBRef => true,
             _ => false,
         }
     }
-    fn is_bwd(&self) -> bool {
-        match *self {
+    fn is_bwd(self) -> bool {
+        match self {
             MVRef::BRef | MVRef::Ref0AndBRef => true,
             _ => false,
         }
@@ -550,7 +550,7 @@ struct PUInfo {
 }
 
 impl PUInfo {
-    fn is_intra(&self) -> bool { self.cu_type == CUType::Intra }
+    fn is_intra(self) -> bool { self.cu_type == CUType::Intra }
 }
 
 const RV60_CANDIDATE_INTRA_ANGLES: [u8; 6] = [ 0, 1, 10, 26, 18, 2 ];
@@ -636,6 +636,12 @@ struct RealVideo60Decoder {
 
     xpos:       usize,
     ypos:       usize,
+
+    ts_scale:   u64,
+    ref0_pts:   u64,
+    ref1_pts:   u64,
+    ref0_ts:    u64,
+    ref1_ts:    u64,
 }
 
 impl RealVideo60Decoder {
@@ -650,7 +656,7 @@ impl RealVideo60Decoder {
             ipbs:       IPBShuffler::new(),
             ipred:      IntraPredContext::new(),
             dsp:        RV60DSP::new(),
-            avg_buf:    avg_buf,
+            avg_buf,
             y_coeffs:   [0; 16 * 16],
             u_coeffs:   [0; 8 * 8],
             v_coeffs:   [0; 8 * 8],
@@ -667,10 +673,16 @@ impl RealVideo60Decoder {
             blk_pos:    0,
             xpos:       0,
             ypos:       0,
+
+            ts_scale:   1,
+            ref0_pts:   0,
+            ref1_pts:   0,
+            ref0_ts:    0,
+            ref1_ts:    0,
         }
     }
     fn decode_cu_line(&mut self, buf: &mut NASimpleVideoFrame<u8>, hdr: &FrameHeader, src: &[u8], cu_y: usize) -> DecoderResult<()> {
-        let mut br = BitReader::new(src, src.len(), BitReaderMode::BE);
+        let mut br = BitReader::new(src, BitReaderMode::BE);
         let cu_w = hdr.get_width_cu();
         let dqp = hdr.read_line_qp_offset(&mut br)?;
         let qps = (hdr.qp as i8) + dqp;
@@ -1117,7 +1129,7 @@ println!(" left {} bits", br.left());
                 }
             }
         }
-        for el in RV60_CANDIDATE_INTRA_ANGLES.into_iter() {
+        for el in RV60_CANDIDATE_INTRA_ANGLES.iter() {
             ipm_cand.add(*el);
         }
         // actually decode prediction mode
@@ -1129,7 +1141,7 @@ println!(" left {} bits", br.left());
                     let mut imode = mode;
                     let mut ipm_cs: [u8; 3] = [ipm_cand.list[0], ipm_cand.list[1], ipm_cand.list[2]];
                     ipm_cs.sort();
-                    for ic in ipm_cs.into_iter() {
+                    for ic in ipm_cs.iter() {
                         if imode >= *ic {
                             imode += 1;
                         }
@@ -1271,7 +1283,7 @@ println!(" left {} bits", br.left());
         } else {
             b_mv = ZERO_MV;
         }
-        
+
         MVInfo { f_mv: mvi.f_mv + f_mv, b_mv: mvi.b_mv + b_mv, mvref: mvi.mvref }
     }
     fn fill_skip_cand(&mut self, hdr: &FrameHeader, skip_cand: &mut UniqueList<MVInfo>, size: usize) {
@@ -1391,8 +1403,8 @@ println!(" left {} bits", br.left());
 }
 
 impl NADecoder for RealVideo60Decoder {
-    fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
-        if let NACodecTypeInfo::Video(_vinfo) = info.get_properties() {
+    fn init(&mut self, supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
+        if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
             let fmt = YUV420_FORMAT;
             let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(0, 0, false, fmt));
             self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
@@ -1412,27 +1424,58 @@ impl NADecoder for RealVideo60Decoder {
             //self.bd.width  = vinfo.get_width();
             //self.bd.height = vinfo.get_height();
             //self.frmmgr.clear();
+
+            supp.pool_u8.set_dec_bufs(3);
+            supp.pool_u8.prealloc_video(NAVideoInfo::new(vinfo.get_width(), vinfo.get_height(), false, fmt), 6)?;
+
             Ok(())
         } else {
 println!("???");
             Err(DecoderError::InvalidData)
         }
     }
-    fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
+    fn decode(&mut self, supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
         let src = pkt.get_buffer();
 
         validate!(src.len() > 9);
         let hsize = (src[0] as usize) * 8 + 9;
-        let mut br = BitReader::new(&src[hsize..], src.len() - hsize, BitReaderMode::BE);
+        let mut br = BitReader::new(&src[hsize..], BitReaderMode::BE);
         let hdr = FrameHeader::read(&mut br)?;
         let mut slices: Vec<usize> = Vec::new();
         hdr.parse_slice_sizes(&mut br, &mut slices)?;
+        match hdr.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 tmp_vinfo = NAVideoInfo::new(hdr.width, hdr.height, false, YUV420_FORMAT);
-        let res = alloc_video_buffer(tmp_vinfo, 6);
-        if !res.is_ok() { return Err(DecoderError::InvalidData); }
-        let bufinfo = res.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() != tmp_vinfo {
+            self.ipbs.clear();
+            supp.pool_u8.reset();
+            supp.pool_u8.prealloc_video(tmp_vinfo, 6)?;
+            let ret = supp.pool_u8.get_free();
+            if ret.is_none() {
+                return Err(DecoderError::AllocError);
+            }
+            buf = ret.unwrap();
+        }
 
         let cu_w = hdr.get_width_cu();
         let cu_h = hdr.get_height_cu();
@@ -1451,18 +1494,33 @@ println!("???");
             off += size;
         }
         if (hdr.ftype == FrameType::I) || (hdr.ftype == FrameType::P) {
-            self.ipbs.add_frame(buf);
+            self.ipbs.add_frame(buf.clone());
         }
 
-        let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo);
+        if hdr.ftype != FrameType::B {
+            self.ref0_pts = self.ref1_pts;
+            self.ref1_pts = pkt.get_pts().unwrap_or(0);
+            self.ref0_ts = self.ref1_ts;
+            self.ref1_ts = hdr.ts as u64;
+            if (self.ref1_pts > self.ref0_pts) && (self.ref1_ts > self.ref0_ts) {
+                self.ts_scale = (self.ref1_pts - self.ref0_pts) / (self.ref1_ts - self.ref0_ts);
+            }
+        }
+        let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), NABufferType::Video(buf));
         frm.set_keyframe(hdr.ftype == FrameType::I);
-        frm.set_pts(Some(hdr.ts as u64));
+        if hdr.ftype == FrameType::B {
+            let pts = self.ref0_pts + ((hdr.ts as u64) - self.ref0_ts) * self.ts_scale;
+            frm.set_pts(Some(pts));
+        }
         frm.set_frame_type(hdr.ftype);
         Ok(frm.into_ref())
     }
+    fn flush(&mut self) {
+        self.ipbs.clear();
+    }
 }
 
-pub fn get_decoder() -> Box<NADecoder> {
+pub fn get_decoder() -> Box<dyn NADecoder + Send> {
     Box::new(RealVideo60Decoder::new())
 }
 
@@ -1471,8 +1529,8 @@ mod test {
     use nihav_core::codecs::RegisteredDecoders;
     use nihav_core::demuxers::RegisteredDemuxers;
     use nihav_core::test::dec_video::*;
-    use crate::codecs::realmedia_register_all_codecs;
-    use crate::demuxers::realmedia_register_all_demuxers;
+    use crate::realmedia_register_all_codecs;
+    use crate::realmedia_register_all_demuxers;
     #[test]
     fn test_rv60() {
         let mut dmx_reg = RegisteredDemuxers::new();