]> git.nihav.org Git - nihav.git/commitdiff
add wrapper codec for Escape formats in AVI and MOV
authorKostya Shishkov <kostya.shishkov@gmail.com>
Sat, 14 Jun 2025 14:08:07 +0000 (16:08 +0200)
committerKostya Shishkov <kostya.shishkov@gmail.com>
Sat, 14 Jun 2025 14:08:07 +0000 (16:08 +0200)
nihav-acorn/src/codecs/escape.rs
nihav-acorn/src/codecs/mod.rs
nihav-registry/src/register.rs

index dea9d5b958e82bff5132b6a14562fef9e533cb52..d2e0b4d72db6eb5315a78e0cc6817d02dcfbda33 100644 (file)
@@ -2,6 +2,7 @@ use nihav_core::codecs::*;
 use nihav_core::io::byteio::*;
 use nihav_core::io::bitreader::*;
 use nihav_codec_support::codecs::imaadpcm::*;
+use std::convert::TryFrom;
 use std::str::FromStr;
 use super::RGB555_FORMAT;
 use super::yuvtab::YUV2RGB;
@@ -699,6 +700,124 @@ pub fn get_decoder130() -> Box<dyn NADecoder + Send> {
     Box::new(Escape130Decoder::new())
 }
 
+#[derive(Debug,Copy,Clone,PartialEq)]
+enum EscapeCodec {
+    Escape102,
+    Escape122,
+    Escape124,
+    Escape130,
+}
+
+impl TryFrom<u16> for EscapeCodec {
+    type Error = ();
+    fn try_from(val: u16) -> Result<EscapeCodec, Self::Error> {
+        match val {
+            0x102 => Ok(EscapeCodec::Escape102),
+            0x116 => Ok(EscapeCodec::Escape122),
+            0x114 => Ok(EscapeCodec::Escape124),
+            0x130 => Ok(EscapeCodec::Escape130),
+            _ => Err(())
+        }
+    }
+}
+
+#[derive(Default)]
+#[allow(clippy::large_enum_variant)]
+enum EscapeDecoderVariant {
+    #[default]
+    None,
+    Escape102(Escape102Decoder),
+    Escape122(Escape122Decoder),
+    Escape124(Escape124Decoder),
+    Escape130(Escape130Decoder),
+}
+
+#[derive(Default)]
+struct EscapeAnyDecoder {
+    info:           NACodecInfoRef,
+    decoder:        EscapeDecoderVariant,
+}
+
+impl NADecoder for EscapeAnyDecoder {
+    fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
+        if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
+            let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(vinfo.get_width(), vinfo.get_height(), false, YUV420_FORMAT));
+            validate!((vinfo.get_width() | vinfo.get_height()) & 7 == 0);
+            self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
+            Ok(())
+        } else {
+            Err(DecoderError::InvalidData)
+        }
+    }
+    fn decode(&mut self, supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
+        let src = pkt.get_buffer();
+        validate!(src.len() > 16);
+
+        let id = read_u16le(&src).unwrap_or_default();
+        let etype = EscapeCodec::try_from(id).map_err(|_| DecoderError::InvalidData)?;
+
+        if matches!(self.decoder, EscapeDecoderVariant::None) {
+            match etype {
+                EscapeCodec::Escape102 => {
+                    let mut dec = Escape102Decoder::new();
+                    dec.init(supp, self.info.clone())?;
+                    self.decoder = EscapeDecoderVariant::Escape102(dec);
+                },
+                EscapeCodec::Escape122 => {
+                    let mut dec = Escape122Decoder::new();
+                    dec.init(supp, self.info.clone())?;
+                    self.decoder = EscapeDecoderVariant::Escape122(dec);
+                },
+                EscapeCodec::Escape124 => {
+                    let mut dec = Escape124Decoder::new();
+                    dec.init(supp, self.info.clone())?;
+                    self.decoder = EscapeDecoderVariant::Escape124(dec);
+                },
+                EscapeCodec::Escape130 => {
+                    let mut dec = Escape130Decoder::new();
+                    dec.init(supp, self.info.clone())?;
+                    self.decoder = EscapeDecoderVariant::Escape130(dec);
+                },
+            }
+        }
+
+        match (etype, &mut self.decoder) {
+            (EscapeCodec::Escape102, EscapeDecoderVariant::Escape102(ref mut dec)) => {
+                dec.decode(supp, pkt)
+            },
+            (EscapeCodec::Escape122, EscapeDecoderVariant::Escape122(ref mut dec)) => {
+                dec.decode(supp, pkt)
+            },
+            (EscapeCodec::Escape124, EscapeDecoderVariant::Escape124(ref mut dec)) => {
+                dec.decode(supp, pkt)
+            },
+            (EscapeCodec::Escape130, EscapeDecoderVariant::Escape130(ref mut dec)) => {
+                dec.decode(supp, pkt)
+            },
+            _ => Err(DecoderError::InvalidData),
+        }
+    }
+    fn flush(&mut self) {
+        match self.decoder {
+            EscapeDecoderVariant::None => {},
+            EscapeDecoderVariant::Escape102(ref mut dec) => { dec.flush(); },
+            EscapeDecoderVariant::Escape122(ref mut dec) => { dec.flush(); },
+            EscapeDecoderVariant::Escape124(ref mut dec) => { dec.flush(); },
+            EscapeDecoderVariant::Escape130(ref mut dec) => { dec.flush(); },
+        }
+    }
+}
+
+impl NAOptionHandler for EscapeAnyDecoder {
+    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_any() -> Box<dyn NADecoder + Send> {
+    Box::<EscapeAnyDecoder>::default()
+}
+
 pub struct EscapeIMAState {
     pub predictor:  i32,
     pub step:       usize,
index 3dcdd157bbfa6b1268a571e73a99614ba9f4973e..923052764fbc2acc550ec58ee717fecfe6c411ad 100644 (file)
@@ -61,6 +61,8 @@ const ACORN_CODECS: &[DecoderInfo] = &[
 #[cfg(feature="decoder_linepack")]
     DecoderInfo { name: "linepack", get_decoder: linepack::get_decoder },
 
+#[cfg(feature="decoder_escape")]
+    DecoderInfo { name: "escape-any", get_decoder: escape::get_decoder_any },
 #[cfg(feature="decoder_escape")]
     DecoderInfo { name: "escape102", get_decoder: escape::get_decoder102 },
 #[cfg(feature="decoder_escape")]
index 5d94ff924d136bfb1458701527f0c9eb449692a6..09f53a3f3777132a24127710f7fd69c695aaf6b4 100644 (file)
@@ -216,6 +216,7 @@ static CODEC_REGISTER: &[CodecDescription] = &[
     desc!(video;    "supermovingblocks",    "Acorn Super Moving Blocks"),
     desc!(video;    "linepack",             "Henrik Pedersen's LinePack"),
     desc!(video;    "movie16_3",            "Henrik Pedersen's Movie 16:3"),
+    desc!(video;    "escape-any",           "wrapper for Eidos Escape codecs"),
     desc!(video;    "escape100",            "Eidos Escape 100"),
     desc!(video;    "escape102",            "Eidos Escape 102"),
     desc!(video;    "escape122",            "Eidos Escape 122"),
@@ -380,6 +381,8 @@ static AVI_VIDEO_CODEC_REGISTER: &[(&[u8;4], &str)] = &[
     (b"azpr", "apple-video"),
     (b"PGVV", "pgvv"),
 
+    (b"ESCP", "escape-any"),
+
     (b"VXS1", "vxvideo"),
 
     (b"DX50", "mpeg4asp"),
@@ -427,6 +430,8 @@ static MOV_VIDEO_CODEC_REGISTER: &[(&[u8;4], &str)] = &[
     (b"VP30", "vp3"),
     (b"VP31", "vp3"),
 
+    (b"ESCP", "escape-any"),
+
     (b"mp4v", "mpeg4asp"),
     (b"avc1", "h264"),
 ];