]> git.nihav.org Git - nihav.git/commitdiff
QT SIVQ decoder master
authorKostya Shishkov <kostya.shishkov@gmail.com>
Wed, 6 May 2026 16:06:28 +0000 (18:06 +0200)
committerKostya Shishkov <kostya.shishkov@gmail.com>
Wed, 6 May 2026 16:06:28 +0000 (18:06 +0200)
nihav-qt/Cargo.toml
nihav-qt/src/codecs/mod.rs
nihav-qt/src/codecs/sivq.rs [new file with mode: 0644]
nihav-registry/src/register.rs

index af9a82bdd25ced38f47075a8e3f1623b4896bbed..8e8f20afd2bb32ac763ecbf26a521d608d9c50ff 100644 (file)
@@ -20,11 +20,12 @@ default = ["all_decoders", "all_demuxers", "all_encoders"]
 all_decoders = ["all_video_decoders", "all_audio_decoders"]
 decoders = []
 
-all_video_decoders = ["decoder_rle", "decoder_smc", "decoder_rpza", "decoder_qdraw", "decoder_svq1", "decoder_svq3", "decoder_rawvid", "decoder_cdvideo"]
+all_video_decoders = ["decoder_rle", "decoder_smc", "decoder_rpza", "decoder_qdraw", "decoder_sivq", "decoder_svq1", "decoder_svq3", "decoder_rawvid", "decoder_cdvideo"]
 decoder_rle = ["decoders"]
 decoder_smc = ["decoders"]
 decoder_rpza = ["decoders"]
 decoder_qdraw = ["decoders"]
+decoder_sivq = ["decoders"]
 decoder_svq1 = ["decoders"]
 decoder_svq3 = ["decoders"]
 decoder_rawvid = ["decoders"]
index 739ffe8ea452080bb128fa2208d933dc57d1286b..bf5e5abbabfd310980e1676886bf8483f8abfcb0 100644 (file)
@@ -24,6 +24,9 @@ mod smc;
 #[cfg(feature="decoder_cdvideo")]
 mod cdvideo;
 
+#[cfg(feature="decoder_sivq")]
+mod sivq;
+
 #[cfg(feature="decoder_svq1")]
 mod svq1;
 #[cfg(feature="decoder_svq1")]
@@ -80,6 +83,8 @@ const QT_CODECS: &[DecoderInfo] = &[
     DecoderInfo { name: "qt-smc", get_decoder: smc::get_decoder },
 #[cfg(feature="decoder_cdvideo")]
     DecoderInfo { name: "qt-cdvideo", get_decoder: cdvideo::get_decoder },
+#[cfg(feature="decoder_sivq")]
+    DecoderInfo { name: "qt-sivq", get_decoder: sivq::get_decoder },
 #[cfg(feature="decoder_svq1")]
     DecoderInfo { name: "sorenson-video", get_decoder: svq1::get_decoder },
 #[cfg(feature="decoder_svq3")]
diff --git a/nihav-qt/src/codecs/sivq.rs b/nihav-qt/src/codecs/sivq.rs
new file mode 100644 (file)
index 0000000..224b90c
--- /dev/null
@@ -0,0 +1,94 @@
+use nihav_core::codecs::*;
+
+struct SIVQDecoder {
+    info:       NACodecInfoRef,
+    width:      usize,
+    height:     usize,
+}
+
+impl SIVQDecoder {
+    fn new() -> Self {
+        Self {
+            info:       NACodecInfoRef::default(),
+            width:      0,
+            height:     0,
+        }
+    }
+}
+
+impl NADecoder for SIVQDecoder {
+    fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
+        if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
+            self.width  = (vinfo.get_width()  + 1) & !1;
+            self.height = (vinfo.get_height() + 1) & !1;
+            let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(self.width, self.height, false, RGB24_FORMAT));
+            self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
+
+            Ok(())
+        } else {
+            Err(DecoderError::InvalidData)
+        }
+    }
+    #[allow(clippy::cognitive_complexity)]
+    fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
+        let src = pkt.get_buffer();
+        const CODEBOOK_SIZE: usize = 256 * 4 * 3;
+        validate!(src.len() >= CODEBOOK_SIZE + self.width * self.height / 4);
+
+        let (cb, indices) = src.split_at(CODEBOOK_SIZE);
+
+        let buftype = alloc_video_buffer(self.info.get_properties().get_video_info().unwrap(), 1)?;
+        let mut buf = buftype.get_vbuf().unwrap();
+        let stride = buf.get_stride(0);
+        let dst = buf.get_data_mut().unwrap();
+
+        for (strip, idx_row) in dst.chunks_exact_mut(stride * 2)
+                .zip(indices.chunks_exact(self.width / 2)) {
+            for (x, &idx) in idx_row.iter().enumerate() {
+                for (line, cb_row) in strip.chunks_exact_mut(stride)
+                        .zip(cb[usize::from(idx) * 4 * 3..].chunks_exact(2 * 3)) {
+                    line[x * 2 * 3..][..2 * 3].copy_from_slice(cb_row);
+                }
+            }
+        }
+
+        let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), buftype);
+        frm.set_keyframe(true);
+        frm.set_frame_type(FrameType::I);
+        Ok(frm.into_ref())
+    }
+    fn flush(&mut self) {}
+}
+
+impl NAOptionHandler for SIVQDecoder {
+    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(SIVQDecoder::new())
+}
+
+#[cfg(test)]
+mod test {
+    use nihav_core::codecs::RegisteredDecoders;
+    use nihav_core::demuxers::RegisteredDemuxers;
+    use nihav_codec_support::test::dec_video::*;
+    use crate::qt_register_all_decoders;
+    use nihav_commonfmt::generic_register_all_demuxers;
+    // sample from QuickTime beta disc
+    #[test]
+    fn test_sivq() {
+        let mut dmx_reg = RegisteredDemuxers::new();
+        generic_register_all_demuxers(&mut dmx_reg);
+        let mut dec_reg = RegisteredDecoders::new();
+        qt_register_all_decoders(&mut dec_reg);
+
+        test_decoding("mov-macbin", "qt-sivq", "assets/QT/Football", Some(2), &dmx_reg, &dec_reg,
+                      ExpectedTestResult::MD5Frames(vec![
+                            [0x92628d33, 0xe3513f25, 0x7f887907, 0xe94d0d45],
+                            [0x55758a95, 0x6e27c158, 0x718eae11, 0x100e76ee],
+                            [0x084c60f2, 0xfbf75d07, 0x7f9d9caf, 0x713ef103]]));
+    }
+}
index 2d0a1be4cde169693cfbcaf0c7c903effb755983..834645b72b36326966c762b0206fcf5e3286460e 100644 (file)
@@ -205,6 +205,7 @@ static CODEC_REGISTER: &[CodecDescription] = &[
     desc!(video;    "sorenson-video",       "Sorenson Video"),
     desc!(video;    "sorenson-video3",      "Sorenson Video 3", CODEC_CAP_REORDER),
     desc!(video;    "qt-cdvideo",           "CD Video Codec"),
+    desc!(video-im; "qt-sivq",              "SIVQ"),
     desc!(video-ll; "qt-yuv2",              "Raw YUV"),
     desc!(video-ll; "qt-yuv4",              "libquicktime YUV4"),
     desc!(audio-ll; "alac",                 "Apple Lossless Audio Codec"),
@@ -454,6 +455,7 @@ static MOV_VIDEO_CODEC_REGISTER: &[(&[u8;4], &str)] = &[
     (b"rpza", "apple-video"),
     (b"qdrw", "qdraw"),
     (b"cdvc", "qt-cdvideo"),
+    (b"SIVQ", "qt-sivq"),
     (b"kpcd", "kodak-photocd"),
     //(b"mpeg", "mpeg-video"),
     (b"mjpa", "mjpeg-a"),