X-Git-Url: https://git.nihav.org/?p=nihav.git;a=blobdiff_plain;f=nihav-commonfmt%2Fsrc%2Fcodecs%2Fclearvideo.rs;h=8b22dad4c194b33bfc8c72d572b622ab61178c1e;hp=4aee1fed704d0386ef505f26e3cd7c844e6ee2f1;hb=78fb6560c73965d834b215fb0b49505ae5443288;hpb=c2a4fa57b414ec496948a1812344a60bd72e1845 diff --git a/nihav-commonfmt/src/codecs/clearvideo.rs b/nihav-commonfmt/src/codecs/clearvideo.rs index 4aee1fe..8b22dad 100644 --- a/nihav-commonfmt/src/codecs/clearvideo.rs +++ b/nihav-commonfmt/src/codecs/clearvideo.rs @@ -3,8 +3,7 @@ use nihav_core::io::bitreader::*; use nihav_core::io::codebook::*; use nihav_core::formats; use nihav_core::codecs::*; -use std::fmt; -use std::ops::{Add, Sub}; +use nihav_codec_support::codecs::{HAMShuffler, MV, ZERO_MV, ZIGZAG}; struct CLVDCCodeReader { } struct CLVACCodeReader { } @@ -13,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() } } @@ -53,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 } } } @@ -208,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; @@ -224,6 +164,7 @@ 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; @@ -237,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; @@ -258,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]) { @@ -275,12 +216,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[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; @@ -288,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; @@ -302,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; @@ -356,7 +297,7 @@ fn copyadd_block(dst: &mut NAVideoBuffer, src: &NAVideoBuffer, 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; } @@ -432,7 +373,7 @@ struct ClearVideoDecoder { info: NACodecInfoRef, dc_cb: Codebook, ac_cb: Codebook, - frmmgr: HAMShuffler, + frmmgr: HAMShuffler, is_rm: bool, ylev: [LevelCodes; 4], ulev: [LevelCodes; 3], @@ -445,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(()); } @@ -454,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 { @@ -496,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; @@ -515,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 { @@ -537,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, @@ -594,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)?; @@ -682,8 +623,8 @@ impl ClearVideoDecoder { } impl NADecoder for ClearVideoDecoder { + #[allow(clippy::or_fun_call)] fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> { - if info.get_extradata().is_none() { return Err(DecoderError::InvalidData); } if let NACodecTypeInfo::Video(vinfo) = info.get_properties() { let w = vinfo.get_width(); let h = vinfo.get_height(); @@ -692,9 +633,11 @@ impl NADecoder for ClearVideoDecoder { let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(w, h, f, fmt)); 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(); @@ -731,12 +674,10 @@ impl NADecoder for ClearVideoDecoder { } 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 bufinfo = bufret.unwrap(); + let bufinfo = alloc_video_buffer(vinfo, self.tsize)?; let mut buf = bufinfo.get_vbuf().unwrap(); if is_intra { @@ -745,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,13 +703,22 @@ impl NADecoder for ClearVideoDecoder { } 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)) } @@ -774,18 +726,28 @@ pub fn get_decoder_rm() -> Box { mod test { use nihav_core::codecs::RegisteredDecoders; use nihav_core::demuxers::RegisteredDemuxers; - use nihav_core::test::dec_video::test_file_decoding; - use crate::codecs::generic_register_all_codecs; - use crate::demuxers::generic_register_all_demuxers; + use nihav_codec_support::test::dec_video::*; + use crate::generic_register_all_decoders; + use crate::generic_register_all_demuxers; #[test] fn test_clv() { let mut dmx_reg = RegisteredDemuxers::new(); generic_register_all_demuxers(&mut dmx_reg); let mut dec_reg = RegisteredDecoders::new(); - generic_register_all_codecs(&mut dec_reg); - test_file_decoding("avi", "assets/Misc/TalkingHead_352x288.avi", Some(10), true, false, None/*Some("clv")*/, &dmx_reg, &dec_reg); -// test_file_decoding("avi", "assets/Misc/basketball.avi", None/*Some(10)*/, true, false, Some("clv1")); -//panic!("debug"); + 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]])); } } @@ -877,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] = &[