X-Git-Url: https://git.nihav.org/?p=nihav.git;a=blobdiff_plain;f=nihav-commonfmt%2Fsrc%2Fcodecs%2Fclearvideo.rs;h=8b22dad4c194b33bfc8c72d572b622ab61178c1e;hp=85431784dee3ef3ad039c7541346538497367e36;hb=78fb6560c73965d834b215fb0b49505ae5443288;hpb=38953fb529efad1b0b609eec77f7839e62ad2719 diff --git a/nihav-commonfmt/src/codecs/clearvideo.rs b/nihav-commonfmt/src/codecs/clearvideo.rs index 8543178..8b22dad 100644 --- a/nihav-commonfmt/src/codecs/clearvideo.rs +++ b/nihav-commonfmt/src/codecs/clearvideo.rs @@ -1,13 +1,9 @@ -use std::rc::Rc; -use std::cell::RefCell; use nihav_core::io::byteio::{ByteReader,MemoryReader}; use nihav_core::io::bitreader::*; use nihav_core::io::codebook::*; use nihav_core::formats; use nihav_core::codecs::*; -use nihav_core::frame::*; -use std::fmt; -use std::ops::{Add, Sub}; +use nihav_codec_support::codecs::{HAMShuffler, MV, ZERO_MV, ZIGZAG}; struct CLVDCCodeReader { } struct CLVACCodeReader { } @@ -16,28 +12,28 @@ struct CLVSym16CodeReader { codes: &'static [u16], bits: &'static [u8], syms: &' impl CodebookDescReader for CLVDCCodeReader { fn bits(&mut self, idx: usize) -> u8 { CLV_DC_BITS[idx] } - fn code(&mut self, idx: usize) -> u32 { CLV_DC_CODES[idx] as u32 } + fn code(&mut self, idx: usize) -> u32 { u32::from(CLV_DC_CODES[idx]) } fn sym (&mut self, idx: usize) -> i8 { (idx as i8) - 63 } fn len(&mut self) -> usize { CLV_DC_BITS.len() } } impl CodebookDescReader for CLVACCodeReader { fn bits(&mut self, idx: usize) -> u8 { CLV_AC_BITS[idx] } - fn code(&mut self, idx: usize) -> u32 { CLV_AC_CODES[idx] as u32 } + fn code(&mut self, idx: usize) -> u32 { u32::from(CLV_AC_CODES[idx]) } fn sym (&mut self, idx: usize) -> u16 { CLV_AC_SYMS[idx] } fn len(&mut self) -> usize { CLV_AC_BITS.len() } } impl CodebookDescReader for CLVFlagsCodeReader { fn bits(&mut self, idx: usize) -> u8 { self.bits[idx] } - fn code(&mut self, idx: usize) -> u32 { self.codes[idx] as u32 } + fn code(&mut self, idx: usize) -> u32 { u32::from(self.codes[idx]) } fn sym (&mut self, idx: usize) -> u8 { idx as u8 } fn len(&mut self) -> usize { self.bits.len() } } impl CodebookDescReader for CLVSym16CodeReader { fn bits(&mut self, idx: usize) -> u8 { self.bits[idx] } - fn code(&mut self, idx: usize) -> u32 { self.codes[idx] as u32 } + fn code(&mut self, idx: usize) -> u32 { u32::from(self.codes[idx]) } fn sym (&mut self, idx: usize) -> u16 { self.syms[idx] } fn len(&mut self) -> usize { self.bits.len() } } @@ -56,83 +52,24 @@ impl LevelCodes { mvd: Option<(&'static [u8], &'static [u16], &'static [u16])>, mv_esc: u16, bias: Option<(&'static [u8], &'static [u16], &'static [u16])>, bias_esc: u16) -> Self { let flags_cb = if let Some((bits, codes)) = flgd { - let mut coderead = CLVFlagsCodeReader { bits: bits, codes: codes }; + let mut coderead = CLVFlagsCodeReader { bits, codes }; Some(Codebook::new(&mut coderead, CodebookMode::MSB).unwrap()) } else { None }; let mv_cb = if let Some((bits, codes, syms)) = mvd { - let mut coderead = CLVSym16CodeReader { bits: bits, codes: codes, syms: syms }; + let mut coderead = CLVSym16CodeReader { bits, codes, syms }; Some(Codebook::new(&mut coderead, CodebookMode::MSB).unwrap()) } else { None }; let bias_cb = if let Some((bits, codes, syms)) = bias { - let mut coderead = CLVSym16CodeReader { bits: bits, codes: codes, syms: syms }; + let mut coderead = CLVSym16CodeReader { bits, codes, syms }; Some(Codebook::new(&mut coderead, CodebookMode::MSB).unwrap()) } else { None }; - LevelCodes { flags_cb: flags_cb, mv_cb: mv_cb, mv_esc: mv_esc, bias_cb: bias_cb, bias_esc: bias_esc } - } -} - -#[derive(Debug,Clone,Copy)] -pub struct MV { - x: i16, - y: i16, -} - -impl MV { - pub fn new(x: i16, y: i16) -> Self { MV{ x: x, y: y } } - pub fn pred(a: MV, b: MV, c: MV) -> Self { - let x; - if a.x < b.x { - if b.x < c.x { - x = b.x; - } else { - if a.x < c.x { x = c.x; } else { x = a.x; } - } - } else { - if b.x < c.x { - if a.x < c.x { x = a.x; } else { x = c.x; } - } else { - x = b.x; - } - } - let y; - if a.y < b.y { - if b.y < c.y { - y = b.y; - } else { - if a.y < c.y { y = c.y; } else { y = a.y; } - } - } else { - if b.y < c.y { - if a.y < c.y { y = a.y; } else { y = c.y; } - } else { - y = b.y; - } - } - MV { x: x, y: y } - } -} - -pub const ZERO_MV: MV = MV { x: 0, y: 0 }; - -impl Add for MV { - type Output = MV; - fn add(self, other: MV) -> MV { MV { x: self.x + other.x, y: self.y + other.y } } -} - -impl Sub for MV { - type Output = MV; - fn sub(self, other: MV) -> MV { MV { x: self.x - other.x, y: self.y - other.y } } -} - -impl fmt::Display for MV { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{},{}", self.x, self.y) + LevelCodes { flags_cb, mv_cb, mv_esc, bias_cb, bias_esc } } } @@ -211,8 +148,8 @@ fn dct_row(blk: &mut [i32]) { let t7 = ((blk[0] - blk[4]) << dshift) + (1 << (shift - 1)); let t8 = t0 + t2; let t9 = t0 - t2; - let tA = 181 * (t9 + (t1 - t3)) + 0x80 >> 8; - let tB = 181 * (t9 - (t1 - t3)) + 0x80 >> 8; + let tA = (181 * (t9 + (t1 - t3)) + 0x80) >> 8; + let tB = (181 * (t9 - (t1 - t3)) + 0x80) >> 8; let tC = t1 + t3; blk[0] = (t6 + t5 + t8) >> shift; @@ -226,6 +163,8 @@ fn dct_row(blk: &mut [i32]) { } #[allow(non_snake_case)] +#[allow(clippy::erasing_op)] +#[allow(clippy::identity_op)] fn dct_col(blk: &mut [i32; 64], col: usize) { let dshift = 8; let shift = 14; @@ -239,8 +178,8 @@ fn dct_col(blk: &mut [i32; 64], col: usize) { let t7 = ((blk[0*8 + col] - blk[4*8 + col]) << dshift) + (1 << (shift - 1)); let t8 = t0 + t2; let t9 = t0 - t2; - let tA = 181 * (t9 + (t1 - t3)) + 0x80 >> 8; - let tB = 181 * (t9 - (t1 - t3)) + 0x80 >> 8; + let tA = (181 * (t9 + (t1 - t3)) + 0x80) >> 8; + let tB = (181 * (t9 - (t1 - t3)) + 0x80) >> 8; let tC = t1 + t3; blk[0*8 + col] = (t6 + t5 + t8) >> shift; @@ -260,7 +199,7 @@ fn clv_dct(blk: &mut [i32; 64]) { fn clv_dct_dc(blk: &mut [i32; 64]) { let dval = blk[0] >> 3; - for i in 0..64 { blk[i] = dval; } + for el in blk.iter_mut() { *el = dval; } } fn put_blocks(buf: &mut NAVideoBuffer, xpos: usize, ypos: usize, blk: &[[i32;64]; 6]) { @@ -271,18 +210,18 @@ fn put_blocks(buf: &mut NAVideoBuffer, xpos: usize, ypos: usize, blk: &[[i32 let mut idxu = buf.get_offset(1) + xpos * 8 + ypos * 8 * strideu; let mut idxv = buf.get_offset(2) + xpos * 8 + ypos * 8 * stridev; - let mut data = buf.get_data_mut(); + let data = buf.get_data_mut().unwrap(); let framebuf: &mut [u8] = data.as_mut_slice(); for j in 0..8 { for k in 0..8 { let mut v = blk[0][k + j * 8] + 128; - if v < 0 { v = 0; } if v > 255 { v = 255; } + if v < 0 { v = 0; } else if v > 255 { v = 255; } framebuf[idxy + k] = v as u8; } for k in 0..8 { let mut v = blk[1][k + j * 8] + 128; - if v < 0 { v = 0; } if v > 255 { v = 255; } + if v < 0 { v = 0; } else if v > 255 { v = 255; } framebuf[idxy + k + 8] = v as u8; } idxy += stridey; @@ -290,12 +229,12 @@ fn put_blocks(buf: &mut NAVideoBuffer, xpos: usize, ypos: usize, blk: &[[i32 for j in 0..8 { for k in 0..8 { let mut v = blk[2][k + j * 8] + 128; - if v < 0 { v = 0; } if v > 255 { v = 255; } + if v < 0 { v = 0; } else if v > 255 { v = 255; } framebuf[idxy + k] = v as u8; } for k in 0..8 { let mut v = blk[3][k + j * 8] + 128; - if v < 0 { v = 0; } if v > 255 { v = 255; } + if v < 0 { v = 0; } else if v > 255 { v = 255; } framebuf[idxy + k + 8] = v as u8; } idxy += stridey; @@ -304,12 +243,12 @@ fn put_blocks(buf: &mut NAVideoBuffer, xpos: usize, ypos: usize, blk: &[[i32 for j in 0..8 { for k in 0..8 { let mut v = blk[4][k + j * 8] + 128; - if v < 0 { v = 0; } if v > 255 { v = 255; } + if v < 0 { v = 0; } else if v > 255 { v = 255; } framebuf[idxu + k] = v as u8; } for k in 0..8 { let mut v = blk[5][k + j * 8] + 128; - if v < 0 { v = 0; } if v > 255 { v = 255; } + if v < 0 { v = 0; } else if v > 255 { v = 255; } framebuf[idxv + k] = v as u8; } idxu += strideu; @@ -329,7 +268,7 @@ fn copy_block(dst: &mut NAVideoBuffer, src: &NAVideoBuffer, let sbuf: &[u8] = sdta.as_slice(); let dstride = dst.get_stride(plane); let mut doff = dst.get_offset(plane) + x + y * dstride; - let mut ddta = dst.get_data_mut(); + let ddta = dst.get_data_mut().unwrap(); let dbuf: &mut [u8] = ddta.as_mut_slice(); for _ in 0..size { let dst = &mut dbuf[doff..][..size]; @@ -352,13 +291,13 @@ fn copyadd_block(dst: &mut NAVideoBuffer, src: &NAVideoBuffer, let sbuf: &[u8] = sdta.as_slice(); let dstride = dst.get_stride(plane); let mut doff = dst.get_offset(plane) + x + y * dstride; - let mut ddta = dst.get_data_mut(); + let ddta = dst.get_data_mut().unwrap(); let dbuf: &mut [u8] = ddta.as_mut_slice(); for _ in 0..size { let dst = &mut dbuf[doff..][..size]; let src = &sbuf[soff..][..size]; for i in 0..size { - let val = (src[i] as i16) + bias; + let val = i16::from(src[i]) + bias; if val < 0x00 { dst[i] = 0x00; } else if val > 0xFF { dst[i] = 0xFF; } else { dst[i] = val as u8; } @@ -405,7 +344,7 @@ fn extend_edges(buf: &mut NAVideoBuffer, tile_size: usize) { let size = if comp == 0 { tile_size } else { tile_size >> 1 }; let stride = buf.get_stride(comp); let planeoff = buf.get_offset(comp); - let mut data = buf.get_data_mut(); + let data = buf.get_data_mut().unwrap(); let framebuf: &mut [u8] = data.as_mut_slice(); let right = size - (w & (size - 1)); @@ -431,10 +370,10 @@ fn extend_edges(buf: &mut NAVideoBuffer, tile_size: usize) { #[allow(dead_code)] struct ClearVideoDecoder { - info: Rc, + info: NACodecInfoRef, dc_cb: Codebook, ac_cb: Codebook, - frmmgr: HAMShuffler, + frmmgr: HAMShuffler, is_rm: bool, ylev: [LevelCodes; 4], ulev: [LevelCodes; 3], @@ -447,7 +386,7 @@ fn decode_dct_block(br: &mut BitReader, blk: &mut [i32; 64], ac_quant: i32, has_ let mut idx = 1; let mut eob = false; - blk[0] = br.read_cb(dc_cb)? as i32; + blk[0] = i32::from(br.read_cb(dc_cb)?); if !has_ac { return Ok(()); } @@ -456,7 +395,7 @@ fn decode_dct_block(br: &mut BitReader, blk: &mut [i32; 64], ac_quant: i32, has_ let (level, skip) = if val != CLV_AC_ESCAPE { eob = ((val >> 12) & 1) != 0; let run = ((val >> 4) & 0xFF) as usize; - let lev = (val & 0xF) as i32; + let lev = i32::from(val & 0xF); if br.read_bool()? { (-lev, run) } else { @@ -498,7 +437,7 @@ fn decode_tile_info(br: &mut BitReader, lc: &[LevelCodes], level: usize) -> Deco let mv = if let Some(ref cb) = lc[level].mv_cb { let mv_code = br.read_cb(cb)?; if mv_code != lc[level].mv_esc { - MV::new(((mv_code & 0xFF) as i8) as i16, (mv_code as i16) >> 8) + MV::new(i16::from((mv_code & 0xFF) as i8), (mv_code as i16) >> 8) } else { let x = br.read_s(8)? as i16; let y = br.read_s(8)? as i16; @@ -517,7 +456,7 @@ fn decode_tile_info(br: &mut BitReader, lc: &[LevelCodes], level: usize) -> Deco } else { 0 }; - let mut ti = TileInfo { flags: flags, mv: mv, bias: bias, child: [None, None, None, None] }; + let mut ti = TileInfo { flags, mv, bias, child: [None, None, None, None] }; if ti.flags != 0 { for i in 0..4 { if (ti.flags & (1 << i)) != 0 { @@ -531,7 +470,7 @@ fn decode_tile_info(br: &mut BitReader, lc: &[LevelCodes], level: usize) -> Deco impl ClearVideoDecoder { fn new(is_rm: bool) -> Self { - let dummy_info = Rc::new(DUMMY_CODEC_INFO); + let dummy_info = NACodecInfo::new_dummy(); let mut coderead = CLVDCCodeReader{}; let dc_cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap(); let mut coderead = CLVACCodeReader{}; @@ -539,9 +478,9 @@ impl ClearVideoDecoder { ClearVideoDecoder { info: dummy_info, - dc_cb: dc_cb, ac_cb: ac_cb, + dc_cb, ac_cb, frmmgr: HAMShuffler::new(), - is_rm: is_rm, + is_rm, ylev: [ LevelCodes::new(Some((CLV_FLAGSY_0_BITS, CLV_FLAGSY_0_CODES)), Some((CLV_MVY_0_BITS, CLV_MVY_0_CODES, CLV_MVY_0_SYMS)), CLV_MVY_0_ESCAPE, @@ -596,7 +535,7 @@ impl ClearVideoDecoder { let mut blks: [[i32; 64]; 6] = [[0; 64]; 6]; let mut has_ac: [bool; 6] = [false; 6]; - for i in 0..6 { has_ac[i] = br.read_bool()? } + for flag in has_ac.iter_mut() { *flag = br.read_bool()?; } for i in 0..4 { decode_dct_block(br, &mut blks[i], ac_quant, has_ac[i], &self.dc_cb, &self.ac_cb)?; @@ -684,19 +623,21 @@ impl ClearVideoDecoder { } impl NADecoder for ClearVideoDecoder { - fn init(&mut self, info: Rc) -> DecoderResult<()> { - if info.get_extradata().is_none() { return Err(DecoderError::InvalidData); } + #[allow(clippy::or_fun_call)] + 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 f = vinfo.is_flipped(); let fmt = formats::YUV420_FORMAT; let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(w, h, f, 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.frmmgr.clear(); - let edata = info.get_extradata().unwrap(); + let edata = info.get_extradata().unwrap_or(std::sync::Arc::new(vec![])); //todo detect simply by extradata contents? - if !self.is_rm { + if edata.len() == 0 || edata.len() < 0x60 { // no or short extradata probably comes from MOV + self.tsize = 4; + } else if !self.is_rm { let mut mr = MemoryReader::new_read(edata.as_slice()); let mut br = ByteReader::new(&mut mr); br.read_skip(0x5E).unwrap(); @@ -714,7 +655,7 @@ impl NADecoder for ClearVideoDecoder { 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(); if src.len() <= 1 { return Err(DecoderError::ShortData); } let off = if self.is_rm { @@ -729,16 +670,14 @@ impl NADecoder for ClearVideoDecoder { let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), NABufferType::None); frm.set_keyframe(false); frm.set_frame_type(FrameType::Skip); - return Ok(Rc::new(RefCell::new(frm))); + return Ok(frm.into_ref()); } let is_intra = (src[off] & 2) == 2; - let mut br = BitReader::new(&src[(off + 1)..], src.len() - (off + 1), BitReaderMode::BE); + let mut br = BitReader::new(&src[(off + 1)..], BitReaderMode::BE); let vinfo = self.info.get_properties().get_video_info().unwrap(); - let bufret = alloc_video_buffer(vinfo, self.tsize); - if let Err(_) = bufret { return Err(DecoderError::InvalidData); } - let mut bufinfo = bufret.unwrap(); + let bufinfo = alloc_video_buffer(vinfo, self.tsize)?; let mut buf = bufinfo.get_vbuf().unwrap(); if is_intra { @@ -747,7 +686,9 @@ impl NADecoder for ClearVideoDecoder { self.decode_frame_intra(&mut br, &mut buf, vinfo.get_width(), vinfo.get_height())?; extend_edges(&mut buf, 1 << self.tsize); } else { - let mut prev = self.frmmgr.clone_ref().unwrap(); + let pref = self.frmmgr.clone_ref(); + if pref.is_none() { return Err(DecoderError::MissingReference); } + let mut prev = pref.unwrap(); extend_edges(&mut prev, 1 << self.tsize); self.decode_frame_inter(&mut br, &mut buf, &mut prev, vinfo.get_width(), vinfo.get_height())?; extend_edges(&mut buf, 1 << self.tsize); @@ -760,26 +701,53 @@ impl NADecoder for ClearVideoDecoder { } else { frm.set_frame_type(FrameType::P); } - Ok(Rc::new(RefCell::new(frm))) + Ok(frm.into_ref()) + } + fn flush(&mut self) { + self.frmmgr.clear(); } } -pub fn get_decoder() -> Box { +impl NAOptionHandler for ClearVideoDecoder { + fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] } + fn set_options(&mut self, _options: &[NAOption]) { } + fn query_option_value(&self, _name: &str) -> Option { None } +} + +pub fn get_decoder() -> Box { Box::new(ClearVideoDecoder::new(false)) } -pub fn get_decoder_rm() -> Box { +pub fn get_decoder_rm() -> Box { Box::new(ClearVideoDecoder::new(true)) } #[cfg(test)] mod test { - use crate::test::dec_video::test_file_decoding; + use nihav_core::codecs::RegisteredDecoders; + use nihav_core::demuxers::RegisteredDemuxers; + use nihav_codec_support::test::dec_video::*; + use crate::generic_register_all_decoders; + use crate::generic_register_all_demuxers; #[test] fn test_clv() { - test_file_decoding("avi", "assets/TalkingHead_352x288.avi", Some(10), true, false, None/*Some("clv")*/); -// test_file_decoding("avi", "assets/basketball.avi", None/*Some(10)*/, true, false, Some("clv1")); -//panic!("debug"); + let mut dmx_reg = RegisteredDemuxers::new(); + generic_register_all_demuxers(&mut dmx_reg); + let mut dec_reg = RegisteredDecoders::new(); + generic_register_all_decoders(&mut dec_reg); + test_decoding("avi", "clearvideo", "assets/Misc/TalkingHead_352x288.avi", Some(10), &dmx_reg, + &dec_reg, ExpectedTestResult::MD5Frames(vec![ + [0xb432376c, 0xf1dce57b, 0x8e79c7ee, 0xdd51850d], + [0x76eb9726, 0x7ca1aabd, 0xf3f0740c, 0xf804dd0e], + [0xc639b32c, 0x1f53f1f4, 0x50c34651, 0xc49cd2ac], + [0x55408f2a, 0x37b01de0, 0xcc6aeadd, 0x09768735], + [0xea219c51, 0xed72710c, 0x6c4b2bb0, 0xbfab0cb7], + [0xfbf56708, 0x7f6597c7, 0x08ce894d, 0x9c4c7f60], + [0x3dbf8b57, 0x9e1513ef, 0x209309a6, 0x56f0aca7], + [0xc5fb6cb7, 0x1b9b092f, 0xe11127be, 0xe4fe8f45], + [0x81a4a122, 0xb2b84bcf, 0xa478bd80, 0x12c78fb6], + [0xb5b43c22, 0xd9c457fa, 0xcc5390d8, 0x1201ef22], + [0x27a206e9, 0x88085556, 0x1114fb62, 0x77f1ebed]])); } } @@ -871,17 +839,6 @@ const CLV_AC_BITS: &[u8] = &[ const CLV_AC_ESCAPE: u16 = 0x1BFF; -const ZIGZAG: &[usize] = &[ - 0, 1, 8, 16, 9, 2, 3, 10, - 17, 24, 32, 25, 18, 11, 4, 5, - 12, 19, 26, 33, 40, 48, 41, 34, - 27, 20, 13, 6, 7, 14, 21, 28, - 35, 42, 49, 56, 57, 50, 43, 36, - 29, 22, 15, 23, 30, 37, 44, 51, - 58, 59, 52, 45, 38, 31, 39, 46, - 53, 60, 61, 54, 47, 55, 62, 63 -]; - const CLV_BIAS_ESCAPE: u16 = 0x100; const CLV_MVY_0_BITS: &[u8] = &[