]> git.nihav.org Git - nihav.git/commitdiff
truemotion1: add support for an old variant of the format
authorKostya Shishkov <kostya.shishkov@gmail.com>
Sat, 8 Mar 2025 15:30:42 +0000 (16:30 +0100)
committerKostya Shishkov <kostya.shishkov@gmail.com>
Sat, 8 Mar 2025 15:30:42 +0000 (16:30 +0100)
nihav-duck/src/codecs/truemotion1.rs
nihav-duck/src/codecs/truemotion1data.rs
nihav-duck/src/codecs/truemotion1enc.rs

index dbcbcfb45441bd807eef3beb8ada6a901d8ba08d..591a4bc7865e98915069c3f96a9a454430687d1d 100644 (file)
@@ -43,11 +43,12 @@ struct IndexState<'a> {
     pos:        usize,
     vec_idx:    usize,
     vec_subidx: usize,
+    tbl0:       bool,
 }
 
 impl<'a> IndexState<'a> {
     fn new(src: &'a [u8]) -> Self {
-        Self { src, pos: 0, vec_idx: 0, vec_subidx: 0 }
+        Self { src, pos: 0, vec_idx: 0, vec_subidx: 0, tbl0: false }
     }
     fn get_next(&mut self) -> DecoderResult<()> {
         validate!(self.pos < self.src.len());
@@ -58,6 +59,9 @@ impl<'a> IndexState<'a> {
     }
     fn get_pred(&self, dtab: &[[u32; 4]; 256]) -> u32 { dtab[self.vec_idx][self.vec_subidx] }
     fn get_diff16(&mut self, dtab: &[[u32; 4]; 256]) -> DecoderResult<u32> {
+        if self.tbl0 {
+            return self.get_diff16_noesc(dtab);
+        }
         let pred1 = self.get_pred(dtab);
         let mut pred = pred1 >> 1;
         if (pred1 & 1) != 0 {
@@ -176,14 +180,14 @@ struct TM1Decoder {
 
 #[allow(clippy::identity_op)]
 impl TM1Decoder {
-    fn new() -> Self { Self::default() }
+    fn new() -> Self { Self { last_table_idx: 42, ..Default::default() } }
     fn set_delta_tables(&mut self, delta_set: usize, table_idx: usize, is_24bit: bool) {
         if (self.last_delta_set == delta_set) && (self.last_table_idx == table_idx) { return; }
         let ydt  = &DUCK_Y_DELTAS[delta_set];
         let yfdt = DUCK_Y_FAT_DELTAS[delta_set];
         let cdt  = &DUCK_C_DELTAS[delta_set];
         let cfdt = DUCK_C_FAT_DELTAS[delta_set];
-        let vec  = DUCK_VECTABLES[table_idx - 1];
+        let vec  = DUCK_VECTABLES[table_idx];
 
         let mut vec_iter = vec.iter();
         for i in 0..256 {
@@ -566,7 +570,7 @@ impl NADecoder for TM1Decoder {
         let is_24bit = !is_sprite && compr_info.is_24bit;
 
         let vec_idx = if ((tm1type & 1) != 0) && (meta_type > 0) { 1 } else { table_idx };
-        validate!((delta_set < DUCK_Y_DELTAS.len()) && (vec_idx > 0) && (vec_idx <= DUCK_VECTABLES.len()));
+        validate!((delta_set < DUCK_Y_DELTAS.len()) && (vec_idx < DUCK_VECTABLES.len()));
         self.set_delta_tables(delta_set, vec_idx, is_24bit);
 
         let out_width = if is_24bit { width >> 1 } else { width };
@@ -600,6 +604,14 @@ impl NADecoder for TM1Decoder {
         self.blk_h = compr_info.block_h;
         let mut mask = MaskState::new(is_intra && !is_sprite, mask_bits, mask_row_size);
         let mut index = IndexState::new(index_bytes);
+        index.tbl0 = vec_idx == 0;
+        let mut padded_idx_bytes = Vec::new();
+        if index.tbl0 { // old format, use padded buffer as the source instead
+            padded_idx_bytes.extend_from_slice(index_bytes);
+            padded_idx_bytes.resize(index_bytes.len() + 4, 0);
+            index = IndexState::new(&padded_idx_bytes);
+            index.tbl0 = true;
+        }
         let bufinfo;
         if !is_24bit {
             if let Some(mut buf) = self.lastframe.get16() {
@@ -692,4 +704,21 @@ mod test {
         //let file = "assets/Duck/TRICORD.AVI";
         //test_file_decoding("avi", file, Some(42), true, false, None/*Some("tm1-")*/, &dmx_reg, &dec_reg);
     }
+    #[test]
+    fn test_old_tm1() {
+        let mut dmx_reg = RegisteredDemuxers::new();
+        generic_register_all_demuxers(&mut dmx_reg);
+        let mut dec_reg = RegisteredDecoders::new();
+        duck_register_all_decoders(&mut dec_reg);
+
+        // sample from The Horde demo
+        test_decoding("avi", "truemotion1", "assets/Duck/segue00.duk", Some(5), &dmx_reg, &dec_reg,
+                      ExpectedTestResult::MD5Frames(vec![
+                        [0xc9b65289, 0x7f64d11d, 0xbfb6cbc5, 0x25778bec],
+                        [0xc9b65289, 0x7f64d11d, 0xbfb6cbc5, 0x25778bec],
+                        [0x8f1b56dd, 0x19c042f3, 0xcb0a220f, 0xc5942c0e],
+                        [0xa0373260, 0xf6c86a10, 0xa4267f65, 0xa5f112d7],
+                        [0xb0c2e64c, 0xc11a3e5a, 0x6fad1e3d, 0x9aa3b54f],
+                        [0x2a25cd1b, 0x1012d3a6, 0x4258be61, 0x0e3b6df6]]));
+    }
 }
index 8b048df9ad8a4db758b809449cc6bffd585b6a92..8474588b539a5d37b11ff9c08e194e972cf3c0b2 100644 (file)
@@ -65,6 +65,265 @@ pub const DUCK_C_FAT_DELTAS: [&[i32; 8]; 4] = [
     &DUCK_C_FAT_DELTA3, &DUCK_C_FAT_DELTA3, &DUCK_C_FAT_DELTA3, &DUCK_Y_FAT_DELTA4
 ];
 
+const DUCK_VECTBL1: &[u8] = &[
+0x8,0x00,0x00,0x00,0x00,
+0x8,0x10,0x00,0x00,0x00,
+0x8,0x01,0x00,0x00,0x00,
+0x8,0x00,0x10,0x00,0x00,
+0x8,0x00,0x01,0x00,0x00,
+0x8,0x00,0x00,0x10,0x00,
+0x8,0x00,0x00,0x01,0x00,
+0x8,0x00,0x00,0x00,0x10,
+0x8,0x00,0x00,0x00,0x01,
+0x6,0x00,0x00,0x00,
+0x6,0x10,0x00,0x00,
+0x6,0x01,0x00,0x00,
+0x6,0x00,0x10,0x00,
+0x6,0x00,0x01,0x00,
+0x6,0x00,0x00,0x01,
+0x6,0x00,0x00,0x10,
+0x6,0x00,0x00,0x02,
+0x6,0x00,0x00,0x20,
+0x6,0x20,0x10,0x00,
+0x6,0x00,0x02,0x01,
+0x6,0x00,0x20,0x10,
+0x6,0x02,0x01,0x00,
+0x6,0x11,0x00,0x00,
+0x6,0x00,0x20,0x00,
+0x6,0x00,0x02,0x00,
+0x6,0x20,0x00,0x00,
+0x6,0x01,0x10,0x00,
+0x6,0x02,0x00,0x00,
+0x6,0x01,0x00,0x02,
+0x6,0x10,0x00,0x20,
+0x6,0x00,0x01,0x02,
+0x6,0x10,0x01,0x00,
+0x6,0x00,0x10,0x20,
+0x6,0x10,0x10,0x00,
+0x6,0x10,0x00,0x01,
+0x6,0x20,0x00,0x10,
+0x6,0x02,0x00,0x01,
+0x6,0x01,0x01,0x00,
+0x6,0x01,0x00,0x10,
+0x6,0x00,0x11,0x00,
+0x6,0x10,0x00,0x02,
+0x6,0x00,0x01,0x10,
+0x6,0x00,0x00,0x11,
+0x6,0x10,0x00,0x10,
+0x6,0x01,0x00,0x01,
+0x6,0x00,0x00,0x22,
+0x6,0x02,0x01,0x01,
+0x6,0x10,0x20,0x10,
+0x6,0x01,0x02,0x01,
+0x6,0x20,0x10,0x10,
+0x6,0x01,0x00,0x20,
+0x6,0x00,0x10,0x01,
+0x6,0x21,0x10,0x00,
+0x6,0x10,0x02,0x01,
+0x6,0x12,0x01,0x00,
+0x6,0x01,0x20,0x10,
+0x6,0x01,0x02,0x00,
+0x6,0x10,0x20,0x00,
+0x6,0x00,0x10,0x02,
+0x6,0x00,0x01,0x20,
+0x6,0x00,0x02,0x21,
+0x6,0x00,0x02,0x20,
+0x6,0x00,0x00,0x12,
+0x6,0x00,0x00,0x21,
+0x6,0x20,0x11,0x00,
+0x6,0x00,0x01,0x01,
+0x6,0x11,0x10,0x00,
+0x6,0x00,0x20,0x12,
+0x6,0x00,0x20,0x11,
+0x6,0x20,0x10,0x02,
+0x6,0x02,0x01,0x20,
+0x6,0x00,0x22,0x11,
+0x6,0x00,0x10,0x10,
+0x6,0x02,0x11,0x00,
+0x6,0x00,0x21,0x10,
+0x6,0x00,0x02,0x03,
+0x6,0x20,0x10,0x01,
+0x6,0x00,0x12,0x01,
+0x4,0x11,0x00,
+0x4,0x00,0x22,
+0x4,0x20,0x00,
+0x4,0x01,0x10,
+0x4,0x02,0x20,
+0x4,0x00,0x20,
+0x4,0x02,0x00,
+0x4,0x10,0x01,
+0x4,0x00,0x11,
+0x4,0x02,0x01,
+0x4,0x02,0x21,
+0x4,0x00,0x02,
+0x4,0x20,0x02,
+0x4,0x01,0x01,
+0x4,0x10,0x10,
+0x4,0x10,0x02,
+0x4,0x22,0x00,
+0x4,0x10,0x00,
+0x4,0x01,0x00,
+0x4,0x21,0x00,
+0x4,0x12,0x00,
+0x4,0x00,0x10,
+0x4,0x20,0x12,
+0x4,0x01,0x11,
+0x4,0x00,0x01,
+0x4,0x01,0x02,
+0x4,0x11,0x02,
+0x4,0x11,0x01,
+0x4,0x10,0x20,
+0x4,0x20,0x01,
+0x4,0x22,0x11,
+0x4,0x00,0x12,
+0x4,0x20,0x10,
+0x4,0x22,0x01,
+0x4,0x01,0x20,
+0x4,0x00,0x21,
+0x4,0x10,0x11,
+0x4,0x21,0x10,
+0x4,0x10,0x22,
+0x4,0x02,0x03,
+0x4,0x12,0x01,
+0x4,0x20,0x11,
+0x4,0x11,0x10,
+0x4,0x20,0x30,
+0x4,0x11,0x20,
+0x4,0x02,0x10,
+0x4,0x22,0x10,
+0x4,0x11,0x11,
+0x4,0x30,0x20,
+0x4,0x30,0x00,
+0x4,0x01,0x22,
+0x4,0x01,0x12,
+0x4,0x02,0x11,
+0x4,0x03,0x02,
+0x4,0x03,0x00,
+0x4,0x10,0x21,
+0x4,0x12,0x20,
+0x4,0x00,0x00,
+0x4,0x12,0x21,
+0x4,0x21,0x11,
+0x4,0x02,0x22,
+0x4,0x10,0x12,
+0x4,0x31,0x00,
+0x4,0x20,0x20,
+0x4,0x00,0x03,
+0x4,0x02,0x02,
+0x4,0x22,0x20,
+0x4,0x01,0x21,
+0x4,0x21,0x02,
+0x4,0x21,0x12,
+0x4,0x11,0x22,
+0x4,0x00,0x30,
+0x4,0x12,0x11,
+0x4,0x20,0x22,
+0x4,0x31,0x20,
+0x4,0x21,0x30,
+0x4,0x22,0x02,
+0x4,0x22,0x22,
+0x4,0x20,0x31,
+0x4,0x13,0x02,
+0x4,0x03,0x10,
+0x4,0x11,0x12,
+0x4,0x00,0x13,
+0x4,0x21,0x01,
+0x4,0x12,0x03,
+0x4,0x13,0x00,
+0x4,0x13,0x10,
+0x4,0x02,0x13,
+0x4,0x30,0x01,
+0x4,0x12,0x10,
+0x4,0x22,0x13,
+0x4,0x03,0x12,
+0x4,0x31,0x01,
+0x4,0x30,0x22,
+0x4,0x00,0x31,
+0x4,0x01,0x31,
+0x4,0x02,0x23,
+0x4,0x01,0x30,
+0x4,0x11,0x21,
+0x4,0x22,0x21,
+0x4,0x01,0x13,
+0x4,0x10,0x03,
+0x4,0x22,0x03,
+0x4,0x30,0x21,
+0x4,0x21,0x31,
+0x4,0x33,0x00,
+0x4,0x13,0x12,
+0x4,0x11,0x31,
+0x4,0x30,0x02,
+0x4,0x12,0x02,
+0x4,0x11,0x13,
+0x4,0x12,0x22,
+0x4,0x20,0x32,
+0x4,0x10,0x13,
+0x4,0x22,0x31,
+0x4,0x21,0x20,
+0x4,0x01,0x33,
+0x4,0x33,0x10,
+0x4,0x20,0x13,
+0x4,0x31,0x22,
+0x4,0x13,0x30,
+0x4,0x01,0x03,
+0x4,0x11,0x33,
+0x4,0x20,0x21,
+0x4,0x13,0x31,
+0x4,0x03,0x22,
+0x4,0x31,0x02,
+0x4,0x00,0x24,
+0x4,0x02,0x12,
+0x2,0x00,
+0x2,0x10,
+0x2,0x20,
+0x2,0x30,
+0x2,0x40,
+0x2,0x50,
+0x2,0x60,
+0x2,0x01,
+0x2,0x11,
+0x2,0x21,
+0x2,0x31,
+0x2,0x41,
+0x2,0x51,
+0x2,0x61,
+0x2,0x02,
+0x2,0x12,
+0x2,0x22,
+0x2,0x32,
+0x2,0x42,
+0x2,0x52,
+0x2,0x62,
+0x2,0x03,
+0x2,0x13,
+0x2,0x23,
+0x2,0x33,
+0x2,0x43,
+0x2,0x53,
+0x2,0x63,
+0x2,0x04,
+0x2,0x14,
+0x2,0x24,
+0x2,0x34,
+0x2,0x44,
+0x2,0x54,
+0x2,0x64,
+0x2,0x05,
+0x2,0x15,
+0x2,0x25,
+0x2,0x35,
+0x2,0x45,
+0x2,0x55,
+0x2,0x65,
+0x2,0x06,
+0x2,0x16,
+0x2,0x26,
+0x2,0x36,
+0x2,0x46,
+0x2,0x56,
+0x2,0x66
+];
+
 const DUCK_VECTBL2: &[u8] = &[
 0x8,0x00,0x00,0x00,0x00,
 0x8,0x00,0x00,0x00,0x00,
@@ -842,4 +1101,4 @@ const DUCK_VECTBL4: &[u8] = &[
 0x2,0x77
 ];
 
-pub const DUCK_VECTABLES: [&[u8]; 3] = [ DUCK_VECTBL2, DUCK_VECTBL3, DUCK_VECTBL4 ];
+pub const DUCK_VECTABLES: [&[u8]; 4] = [ DUCK_VECTBL1, DUCK_VECTBL2, DUCK_VECTBL3, DUCK_VECTBL4 ];
index 4adc3bf116efe27da48d6bd885c1324cc060f053..90aa32f4d361a4f347f3c58ae371f2302d709a0c 100644 (file)
@@ -305,13 +305,13 @@ impl IndexWriter {
             in_seq: [0; 4],
             in_len: 0,
             cand:   0,
-            table:  DUCK_VECTABLES[0],
+            table:  DUCK_VECTABLES[1],
         }
     }
     fn reset(&mut self, idx: usize) {
         self.dst.clear();
         self.in_len = 0;
-        self.table = DUCK_VECTABLES[idx];
+        self.table = DUCK_VECTABLES[idx + 1];
     }
     fn flush(&mut self) {
         if self.in_len > 0 {