X-Git-Url: https://git.nihav.org/?a=blobdiff_plain;f=nihav-realmedia%2Fsrc%2Fcodecs%2Frv20.rs;h=7f24650298c68ad701393a3d5b352f47c8338f08;hb=7f73eeeeff30f6319d5ff3fe6b945d64ce2c8fef;hp=eeb56cfb9b2f59625e52968ddd6f86e2837e3070;hpb=3167c45c8087a692192021e08a8063dff680001c;p=nihav.git diff --git a/nihav-realmedia/src/codecs/rv20.rs b/nihav-realmedia/src/codecs/rv20.rs index eeb56cf..7f24650 100644 --- a/nihav-realmedia/src/codecs/rv20.rs +++ b/nihav-realmedia/src/codecs/rv20.rs @@ -1,14 +1,14 @@ -use std::rc::Rc; -use std::cell::RefCell; use nihav_core::io::bitreader::*; use nihav_core::io::codebook::*; use nihav_core::formats; use nihav_core::frame::*; use nihav_core::codecs::*; -use nihav_core::codecs::h263::*; -use nihav_core::codecs::h263::code::H263BlockDSP; -use nihav_core::codecs::h263::decoder::*; -use nihav_core::codecs::h263::data::*; +use nihav_codec_support::codecs::{MV, ZIGZAG}; +use nihav_codec_support::codecs::blockdsp; +use nihav_codec_support::codecs::h263::*; +use nihav_codec_support::codecs::h263::code::{H263_INTERP_FUNCS, H263_INTERP_AVG_FUNCS, h263_filter_row}; +use nihav_codec_support::codecs::h263::decoder::*; +use nihav_codec_support::codecs::h263::data::*; #[allow(dead_code)] @@ -32,14 +32,17 @@ struct RPRInfo { } struct RealVideo20Decoder { - info: Rc, + info: NACodecInfoRef, dec: H263BaseDecoder, tables: Tables, w: usize, h: usize, minor_ver: u8, rpr: RPRInfo, - bdsp: H263BlockDSP, + bdsp: Box, + base_ts: u64, + last_ts: u16, + next_ts: u16, } struct RealVideo20BR<'a> { @@ -55,6 +58,7 @@ struct RealVideo20BR<'a> { mb_pos_bits: u8, minor_ver: u8, rpr: RPRInfo, + pts: u16, } struct RV20SliceInfo { @@ -68,9 +72,81 @@ struct RV20SliceInfo { h: usize, } +#[derive(Default)] +struct RV20BlockDSP {} + impl RV20SliceInfo { fn new(ftype: Type, seq: u32, qscale: u8, mb_x: usize, mb_y: usize, mb_pos: usize, w: usize, h: usize) -> Self { - RV20SliceInfo { ftype: ftype, seq: seq, qscale: qscale, mb_x: mb_x, mb_y: mb_y, mb_pos: mb_pos, w: w, h: h } + RV20SliceInfo { ftype, seq, qscale, mb_x, mb_y, mb_pos, w, h } + } +} + +macro_rules! idct { + ($src: expr, $sstep: expr, $dst: expr, $dstep: expr, $bias: expr, $shift: expr, $dtype: tt) => { + let s0 = $src[0] as i32; + let s1 = $src[$sstep] as i32; + let s2 = $src[$sstep * 2] as i32; + let s3 = $src[$sstep * 3] as i32; + let s4 = $src[$sstep * 4] as i32; + let s5 = $src[$sstep * 5] as i32; + let s6 = $src[$sstep * 6] as i32; + let s7 = $src[$sstep * 7] as i32; + + let t0 = (s0 + s4).wrapping_mul(1448); + let t1 = (s0 - s4).wrapping_mul(1448); + let t2 = s2.wrapping_mul(1892) + s6.wrapping_mul(784); + let t3 = s2.wrapping_mul(784) - s6.wrapping_mul(1892); + let t4 = s1.wrapping_mul(2009) + s3.wrapping_mul(1703) + + s5.wrapping_mul(1138) + s7.wrapping_mul(400); + let t5 = s1.wrapping_mul(1703) - s3.wrapping_mul(400) + - s5.wrapping_mul(2009) - s7.wrapping_mul(1138); + let t6 = s1.wrapping_mul(1138) - s3.wrapping_mul(2009) + + s5.wrapping_mul(400) + s7.wrapping_mul(1703); + let t7 = s1.wrapping_mul(400) - s3.wrapping_mul(1138) + + s5.wrapping_mul(1703) - s7.wrapping_mul(2009); + + let t8 = t0 + t2; + let t9 = t0 - t2; + let ta = t1 + t3; + let tb = t1 - t3; + + $dst[0] = ((t8 + t4 + $bias) >> $shift) as $dtype; + $dst[$dstep] = ((ta + t5 + $bias) >> $shift) as $dtype; + $dst[$dstep * 2] = ((tb + t6 + $bias) >> $shift) as $dtype; + $dst[$dstep * 3] = ((t9 + t7 + $bias) >> $shift) as $dtype; + $dst[$dstep * 4] = ((t9 - t7 + $bias) >> $shift) as $dtype; + $dst[$dstep * 5] = ((tb - t6 + $bias) >> $shift) as $dtype; + $dst[$dstep * 6] = ((ta - t5 + $bias) >> $shift) as $dtype; + $dst[$dstep * 7] = ((t8 - t4 + $bias) >> $shift) as $dtype; + } +} + +impl BlockDSP for RV20BlockDSP { + fn idct(&self, blk: &mut [i16; 64]) { + let mut tmp = [0i32; 64]; + for (dst, src) in tmp.chunks_mut(8).zip(blk.chunks(8)) { + idct!(src, 1, dst, 1, 0, 4, i32); + } + for i in 0..8 { + idct!(&tmp[i..], 8, &mut blk[i..], 8, 1 << 19, 20, i16); + } + } + fn copy_blocks(&self, dst: &mut NAVideoBuffer, src: &NAVideoBuffer, xpos: usize, ypos: usize, w: usize, h: usize, mv: MV) { + let srcx = ((mv.x >> 1) as isize) + (xpos as isize); + let srcy = ((mv.y >> 1) as isize) + (ypos as isize); + let mode = ((mv.x & 1) + (mv.y & 1) * 2) as usize; + + blockdsp::copy_blocks(dst, src, xpos, ypos, srcx, srcy, w, h, 0, 1, mode, H263_INTERP_FUNCS); + } + fn avg_blocks(&self, dst: &mut NAVideoBuffer, src: &NAVideoBuffer, xpos: usize, ypos: usize, w: usize, h: usize, mv: MV) { + let srcx = ((mv.x >> 1) as isize) + (xpos as isize); + let srcy = ((mv.y >> 1) as isize) + (ypos as isize); + let mode = ((mv.x & 1) + (mv.y & 1) * 2) as usize; + + blockdsp::copy_blocks(dst, src, xpos, ypos, srcx, srcy, w, h, 0, 1, mode, H263_INTERP_AVG_FUNCS); + } + fn filter_row(&self, buf: &mut NAVideoBuffer, mb_y: usize, mb_w: usize, cbpi: &CBPInfo) { + h263_filter_row(buf, mb_y, mb_w, cbpi) } } @@ -80,7 +156,7 @@ impl<'a> RealVideo20BR<'a> { let mut slice_offs = Vec::with_capacity(nslices); { let offs = &src[1..][..nslices * 8]; - let mut br = BitReader::new(offs, offs.len(), BitReaderMode::BE); + let mut br = BitReader::new(offs, BitReaderMode::BE); for _ in 0..nslices { br.skip(32).unwrap(); let off = br.read(32).unwrap(); @@ -99,18 +175,19 @@ impl<'a> RealVideo20BR<'a> { } } RealVideo20BR { - br: BitReader::new(&src[soff..], src.len() - soff, BitReaderMode::BE), - tables: tables, + br: BitReader::new(&src[soff..], BitReaderMode::BE), + tables, num_slices: nslices, slice_no: 0, slice_off: slice_offs, w: width, h: height, - mb_w: mb_w, - mb_h: mb_h, + mb_w, + mb_h, mb_pos_bits: mbpb, - minor_ver: minor_ver, - rpr: rpr, + minor_ver, + rpr, + pts: 0, } } @@ -128,12 +205,12 @@ impl<'a> RealVideo20BR<'a> { let scan = match acpred { ACPredMode::Hor => H263_SCAN_V, ACPredMode::Ver => H263_SCAN_H, - _ => H263_ZIGZAG, + _ => &ZIGZAG, }; let rl_cb = if sstate.is_iframe { &self.tables.aic_rl_cb } else { &self.tables.rl_cb }; - let q_add = if quant == 0 || sstate.is_iframe { 0i16 } else { ((quant - 1) | 1) as i16 }; - let q = if plane_no == 0 { (quant * 2) as i16 } else { H263_CHROMA_QUANT[quant as usize] as i16 }; + let q = if plane_no == 0 { (quant * 2) as i16 } else { (H263_CHROMA_QUANT[quant as usize] * 2) as i16 }; + let q_add = if q == 0 || sstate.is_iframe { 0i16 } else { (((q >> 1) - 1) | 1) as i16 }; while idx < 64 { let code = br.read_cb(rl_cb)?; let run; @@ -144,7 +221,11 @@ impl<'a> RealVideo20BR<'a> { level = code.get_level(); last = code.is_last(); if br.read_bool()? { level = -level; } - level = (level * q) + q_add; + if level >= 0 { + level = (level * q) + q_add; + } else { + level = (level * q) - q_add; + } } else { last = br.read_bool()?; run = br.read(6)? as u8; @@ -154,7 +235,11 @@ impl<'a> RealVideo20BR<'a> { let top = br.read_s(6)? as i16; level = (top << 5) | low; } - level = (level * q) + q_add; + if level >= 0 { + level = (level * q) + q_add; + } else { + level = (level * q) - q_add; + } if level < -2048 { level = -2048; } if level > 2047 { level = 2047; } } @@ -383,6 +468,7 @@ impl<'a> RealVideo20BR<'a> { } else { br.read(13)? << 3 }; + self.pts = seq as u16; let w; let h; if self.rpr.present { @@ -434,38 +520,41 @@ impl RealVideo20Decoder { let mv_cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap(); let tables = Tables { - intra_mcbpc_cb: intra_mcbpc_cb, - inter_mcbpc_cb: inter_mcbpc_cb, - mbtype_b_cb: mbtype_b_cb, - cbpy_cb: cbpy_cb, - cbpc_b_cb: cbpc_b_cb, - rl_cb: rl_cb, - aic_rl_cb: aic_rl_cb, - mv_cb: mv_cb, + intra_mcbpc_cb, + inter_mcbpc_cb, + mbtype_b_cb, + cbpy_cb, + cbpc_b_cb, + rl_cb, + aic_rl_cb, + mv_cb, }; RealVideo20Decoder{ - info: Rc::new(DUMMY_CODEC_INFO), + info: NACodecInfoRef::default(), dec: H263BaseDecoder::new_b_frames(false), - tables: tables, + tables, w: 0, h: 0, minor_ver: 0, rpr: RPRInfo { present: false, bits: 0, widths: [0; 8], heights: [0; 8] }, - bdsp: H263BlockDSP::new(), + bdsp: Box::new(RV20BlockDSP::default()), + base_ts: 0, + last_ts: 0, + next_ts: 0, } } } impl NADecoder for RealVideo20Decoder { #[allow(unused_variables)] - fn init(&mut self, info: Rc) -> DecoderResult<()> { + fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> { if let NACodecTypeInfo::Video(vinfo) = info.get_properties() { let w = vinfo.get_width(); let h = vinfo.get_height(); let fmt = formats::YUV420_FORMAT; let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(w, h, false, fmt)); - self.info = Rc::new(NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata())); + self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref(); self.w = w; self.h = h; @@ -493,17 +582,32 @@ impl NADecoder for RealVideo20Decoder { Err(DecoderError::InvalidData) } } - fn decode(&mut self, pkt: &NAPacket) -> DecoderResult { + fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult { let src = pkt.get_buffer(); let mut ibr = RealVideo20BR::new(&src, &self.tables, self.w, self.h, self.minor_ver, self.rpr); - let bufinfo = self.dec.parse_frame(&mut ibr, &self.bdsp)?; + let bufinfo = self.dec.parse_frame(&mut ibr, self.bdsp.as_ref())?; let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo); + let ftype = self.dec.get_frame_type(); + let pts = ibr.pts; + if ftype != FrameType::B { + self.last_ts = self.next_ts; + self.next_ts = pts; + if self.last_ts > self.next_ts { + self.base_ts += 1 << 16; + } + } + let ts_diff = self.next_ts.wrapping_sub(pts); + let ts = self.base_ts + (self.next_ts as u64) - (ts_diff as u64); frm.set_keyframe(self.dec.is_intra()); - frm.set_frame_type(self.dec.get_frame_type()); - Ok(Rc::new(RefCell::new(frm))) + frm.set_frame_type(ftype); + frm.set_pts(Some(ts >> 3)); + Ok(frm.into_ref()) + } + fn flush(&mut self) { + self.dec.flush(); } } @@ -518,7 +622,7 @@ const H263_MBB: &[MBB; 7] = &[ MBB{ blocks: 65536, bits: 14 }, ]; -pub fn get_decoder() -> Box { +pub fn get_decoder() -> Box { Box::new(RealVideo20Decoder::new()) } @@ -526,9 +630,9 @@ pub fn get_decoder() -> Box { 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 nihav_codec_support::test::dec_video::*; + use crate::realmedia_register_all_codecs; + use crate::realmedia_register_all_demuxers; #[test] fn test_rv20() { let mut dmx_reg = RegisteredDemuxers::new();