make decoders Send-able
[nihav.git] / nihav-realmedia / src / codecs / rv60.rs
index 1d13efdd9e073cce2976b335363da40b7bc87014..9fee64636d25a4b490807910dc101b892b171676 100644 (file)
@@ -257,58 +257,58 @@ const RV60_PU_TYPES: [PUType; 8] = [
 ];
 
 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,6 +673,12 @@ 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<()> {
@@ -1431,6 +1443,22 @@ println!("???");
         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())
 }