make all codec crates export just register_all functions and document them
[nihav.git] / nihav-realmedia / src / codecs / rv60.rs
index a4cf919cb8337841acb5f58ace5a06ccb131e060..801f8c212706df7733f8039686251412851afb36 100644 (file)
@@ -253,7 +253,7 @@ 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 {
@@ -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 {
@@ -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;
@@ -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) {
@@ -1427,10 +1439,26 @@ println!("???");
 
         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 ret = supp.pool_u8.get_free();
@@ -1469,15 +1497,30 @@ println!("???");
             self.ipbs.add_frame(buf.clone());
         }
 
+        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<dyn NADecoder> {
+pub fn get_decoder() -> Box<dyn NADecoder + Send> {
     Box::new(RealVideo60Decoder::new())
 }
 
@@ -1486,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();