X-Git-Url: https://git.nihav.org/?a=blobdiff_plain;f=nihav-realmedia%2Fsrc%2Fcodecs%2Frv60.rs;h=9fee64636d25a4b490807910dc101b892b171676;hb=08a1fab72215ea7716f51adf7008f85372e80c71;hp=4b7a2f2178f0dbaa62d6af63026fbfec6d510c39;hpb=6011e20199143f519881660144a4ca95ba77fd2d;p=nihav.git diff --git a/nihav-realmedia/src/codecs/rv60.rs b/nihav-realmedia/src/codecs/rv60.rs index 4b7a2f2..9fee646 100644 --- a/nihav-realmedia/src/codecs/rv60.rs +++ b/nihav-realmedia/src/codecs/rv60.rs @@ -21,7 +21,7 @@ impl UniqueList { 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; @@ -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, hdr: &FrameHeader, src: &[u8], cu_y: usize) -> DecoderResult<()> { @@ -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; } @@ -1431,6 +1443,22 @@ println!("???"); let hdr = FrameHeader::read(&mut br)?; let mut slices: Vec = 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 { +pub fn get_decoder() -> Box { Box::new(RealVideo60Decoder::new()) }