From: Kostya Shishkov Date: Wed, 6 May 2026 16:06:28 +0000 (+0200) Subject: QT SIVQ decoder X-Git-Url: https://git.nihav.org/?a=commitdiff_plain;h=cf767ae52f96f8ed81c79e2098fa42381dc8002d;p=nihav.git QT SIVQ decoder --- diff --git a/nihav-qt/Cargo.toml b/nihav-qt/Cargo.toml index af9a82b..8e8f20a 100644 --- a/nihav-qt/Cargo.toml +++ b/nihav-qt/Cargo.toml @@ -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"] diff --git a/nihav-qt/src/codecs/mod.rs b/nihav-qt/src/codecs/mod.rs index 739ffe8..bf5e5ab 100644 --- a/nihav-qt/src/codecs/mod.rs +++ b/nihav-qt/src/codecs/mod.rs @@ -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 index 0000000..224b90c --- /dev/null +++ b/nihav-qt/src/codecs/sivq.rs @@ -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 { + 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 { None } +} + +pub fn get_decoder() -> Box { + 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]])); + } +} diff --git a/nihav-registry/src/register.rs b/nihav-registry/src/register.rs index 2d0a1be..834645b 100644 --- a/nihav-registry/src/register.rs +++ b/nihav-registry/src/register.rs @@ -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"),