introduce raw video "codec"
authorKostya Shishkov <kostya.shishkov@gmail.com>
Sun, 19 Sep 2021 11:50:54 +0000 (13:50 +0200)
committerKostya Shishkov <kostya.shishkov@gmail.com>
Thu, 30 Sep 2021 16:13:21 +0000 (18:13 +0200)
nihav-commonfmt/Cargo.toml
nihav-commonfmt/src/codecs/mod.rs
nihav-commonfmt/src/codecs/rawvideo.rs [new file with mode: 0644]
nihav-registry/src/register.rs

index 1ac726122854aa6171ab40468ec2ddeed3190882..7f4cc4f13c66fad11311e4eeebc13d125a507de9 100644 (file)
@@ -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"]
index 7fef1cb109deeb652cbe8e3b10841895f2deb3d4..2c9eef764eef7d194b95e7ec144fc5fc55bc167c 100644 (file)
@@ -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 (file)
index 0000000..fd1c0c3
--- /dev/null
@@ -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<NAFrameRef> {
+        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<NAValue> { None }
+}
+
+pub fn get_decoder() -> Box<dyn NADecoder + Send> {
+    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]]));
+    }
+}
index 48d4541715995917f6a4331a2da149a14cdfebef..d929e28b9a7ae3a736565f93d1a18b935602aea3 100644 (file)
@@ -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"),