From a715e99fd5a8b724cf31877c74bbd8191d7fd256 Mon Sep 17 00:00:00 2001 From: Kostya Shishkov Date: Sun, 19 Sep 2021 13:50:54 +0200 Subject: [PATCH 1/1] introduce raw video "codec" --- nihav-commonfmt/Cargo.toml | 3 +- nihav-commonfmt/src/codecs/mod.rs | 4 + nihav-commonfmt/src/codecs/rawvideo.rs | 107 +++++++++++++++++++++++++ nihav-registry/src/register.rs | 3 + 4 files changed, 116 insertions(+), 1 deletion(-) create mode 100644 nihav-commonfmt/src/codecs/rawvideo.rs diff --git a/nihav-commonfmt/Cargo.toml b/nihav-commonfmt/Cargo.toml index 1ac7261..7f4cc4f 100644 --- a/nihav-commonfmt/Cargo.toml +++ b/nihav-commonfmt/Cargo.toml @@ -34,9 +34,10 @@ muxer_wav = ["muxers"] all_decoders = ["all_video_decoders", "all_audio_decoders"] -all_video_decoders = ["decoder_cinepak", "decoder_clearvideo", "decoder_zmbv"] +all_video_decoders = ["decoder_cinepak", "decoder_clearvideo", "decoder_rawvideo", "decoder_zmbv"] decoder_cinepak = ["decoders"] decoder_clearvideo = ["decoders"] +decoder_rawvideo = ["decoders"] decoder_zmbv = ["decoders"] all_audio_decoders = ["decoder_pcm", "decoder_ts102366", "decoder_sipro", "decoder_atrac3", "decoder_aac"] diff --git a/nihav-commonfmt/src/codecs/mod.rs b/nihav-commonfmt/src/codecs/mod.rs index 7fef1cb..2c9eef7 100644 --- a/nihav-commonfmt/src/codecs/mod.rs +++ b/nihav-commonfmt/src/codecs/mod.rs @@ -8,6 +8,8 @@ macro_rules! validate { mod cinepak; #[cfg(feature="decoder_clearvideo")] mod clearvideo; +#[cfg(feature="decoder_rawvideo")] +mod rawvideo; #[cfg(feature="decoder_zmbv")] mod zmbv; @@ -36,6 +38,8 @@ const DECODERS: &[DecoderInfo] = &[ DecoderInfo { name: "clearvideo", get_decoder: clearvideo::get_decoder }, #[cfg(feature="decoder_clearvideo")] DecoderInfo { name: "clearvideo_rm", get_decoder: clearvideo::get_decoder_rm }, +#[cfg(feature="decoder_rawvideo")] + DecoderInfo { name: "rawvideo", get_decoder: rawvideo::get_decoder }, #[cfg(feature="decoder_zmbv")] DecoderInfo { name: "zmbv", get_decoder: zmbv::get_decoder }, diff --git a/nihav-commonfmt/src/codecs/rawvideo.rs b/nihav-commonfmt/src/codecs/rawvideo.rs new file mode 100644 index 0000000..fd1c0c3 --- /dev/null +++ b/nihav-commonfmt/src/codecs/rawvideo.rs @@ -0,0 +1,107 @@ +use nihav_core::codecs::*; + +struct RawDecoder { + info: NACodecInfoRef, +} + +impl RawDecoder { + fn new() -> Self { + Self { + info: NACodecInfo::new_dummy(), + } + } +} + +impl NADecoder for RawDecoder { + fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> { + if let NACodecTypeInfo::Video(_vinfo) = info.get_properties() { + self.info = info.clone(); + Ok(()) + } else { + Err(DecoderError::InvalidData) + } + } + fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult { + if let NACodecTypeInfo::Video(ref vinfo) = self.info.get_properties() { + let src = pkt.get_buffer(); + let width = vinfo.width; + let height = vinfo.height; + let ncomp = vinfo.format.components as usize; + let buf = if vinfo.format.is_unpacked() && vinfo.format.get_max_depth() == 8 { + let mut offs = vec![0; ncomp]; + let mut strides = Vec::with_capacity(ncomp); + let mut sizes = Vec::with_capacity(ncomp); + for chr in vinfo.format.comp_info[..ncomp].iter() { + if let Some(chromaton) = chr { + let stride = chromaton.get_linesize(width); + let size = stride * chromaton.get_height(height); + sizes.push(size); + strides.push(stride); + } else { + return Err(DecoderError::InvalidData); + } + } + let mut off = 0; + for i in 0..ncomp { + for (cno, chr) in vinfo.format.comp_info[..ncomp].iter().enumerate() { + if let Some(chromaton) = chr { + let comp_off = chromaton.comp_offs as usize; + validate!(comp_off < ncomp); + if comp_off != i { + continue; + } + offs[cno] = off; + off += sizes[i]; + } + } + } + validate!(off == src.len()); + + NABufferType::Video(NAVideoBuffer::from_raw_parts(vinfo.clone(), src.clone(), offs, strides).into_ref()) + } else { + let offs = vec![0; ncomp]; + let strides = vec![0; ncomp]; + NABufferType::VideoPacked(NAVideoBuffer::from_raw_parts(vinfo.clone(), src.clone(), offs, strides).into_ref()) + }; + + let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), buf); + frm.set_keyframe(true); + frm.set_frame_type(FrameType::I); + Ok(frm.into_ref()) + } else { + Err(DecoderError::Bug) + } + } + fn flush(&mut self) {} +} + + +impl NAOptionHandler for RawDecoder { + 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(RawDecoder::new()) +} + +#[cfg(test)] +mod test { + 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_rawvideo() { + 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("yuv4mpeg", "rawvideo", "assets/Misc/test.y4m", None, &dmx_reg, + &dec_reg, ExpectedTestResult::MD5Frames(vec![ + [0xd58326b0, 0xdbfc1dcc, 0x6d66a04c, 0x08a21bbb], + [0x9b2cb5c5, 0x69b5f261, 0xcaccaaaf, 0xff2a807d]])); + } +} diff --git a/nihav-registry/src/register.rs b/nihav-registry/src/register.rs index 48d4541..d929e28 100644 --- a/nihav-registry/src/register.rs +++ b/nihav-registry/src/register.rs @@ -185,6 +185,9 @@ static CODEC_REGISTER: &[CodecDescription] = &[ desc!(audio; "atrac3", "Sony Atrac3"), desc!(audio; "sipro", "Sipro Labs ADPCM"), + + desc!(video-ll; "rawvideo", "Raw video data"), + desc!(video; "cinepak", "Cinepak"), desc!(video-llp; "zmbv", "Zip Motion Blocks Video"), -- 2.30.2