]> git.nihav.org Git - nihav.git/blobdiff - nihav-duck/src/codecs/on2avc.rs
avimux: do not record palette change chunks in OpenDML index
[nihav.git] / nihav-duck / src / codecs / on2avc.rs
index 29ead41d3c1ec9ebf7dd3106fef30495d0e6bf23..4fabe2b458deb7da24a0f3110ed285155d44df21 100644 (file)
@@ -37,56 +37,39 @@ struct Codebooks {
     spec_cb:        [Codebook<u16>; 15],
 }
 
-fn scale_map(idx: usize) -> i8 { (idx as i8) - 60 }
-fn cb_map1(idx: usize)  -> u16 { AVC_SPEC_CB1_SYMS[idx] }
-fn cb_map2(idx: usize)  -> u16 { AVC_SPEC_CB2_SYMS[idx] }
-fn cb_map3(idx: usize)  -> u16 { AVC_SPEC_CB3_SYMS[idx] }
-fn cb_map4(idx: usize)  -> u16 { AVC_SPEC_CB4_SYMS[idx] }
-fn cb_map5(idx: usize)  -> u16 { AVC_SPEC_CB5_SYMS[idx] }
-fn cb_map6(idx: usize)  -> u16 { AVC_SPEC_CB6_SYMS[idx] }
-fn cb_map7(idx: usize)  -> u16 { AVC_SPEC_CB7_SYMS[idx] }
-fn cb_map8(idx: usize)  -> u16 { AVC_SPEC_CB8_SYMS[idx] }
-fn cb_map9(idx: usize)  -> u16 { AVC_SPEC_CB9_SYMS[idx] }
-fn cb_map10(idx: usize) -> u16 { AVC_SPEC_CB10_SYMS[idx] }
-fn cb_map11(idx: usize) -> u16 { AVC_SPEC_CB11_SYMS[idx] }
-fn cb_map12(idx: usize) -> u16 { AVC_SPEC_CB12_SYMS[idx] }
-fn cb_map13(idx: usize) -> u16 { AVC_SPEC_CB13_SYMS[idx] }
-fn cb_map14(idx: usize) -> u16 { AVC_SPEC_CB14_SYMS[idx] }
-fn cb_map15(idx: usize) -> u16 { AVC_SPEC_CB15_SYMS[idx] }
-
 impl Codebooks {
     fn new() -> Self {
-        let mut coderead = TableCodebookDescReader::new(AVC_SCF_CODEBOOK_CODES, AVC_SCF_CODEBOOK_BITS, scale_map);
+        let mut coderead = TableCodebookDescReader::new(AVC_SCF_CODEBOOK_CODES, AVC_SCF_CODEBOOK_BITS, |idx| (idx as i8) - 60);
         let scale_cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
-        let mut coderead = TableCodebookDescReader::new(AVC_SPEC_CB1_CODES, AVC_SPEC_CB1_BITS, cb_map1);
+        let mut coderead = TableCodebookDescReader::new(AVC_SPEC_CB1_CODES, AVC_SPEC_CB1_BITS, |idx| AVC_SPEC_CB1_SYMS[idx]);
         let cb1 = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
-        let mut coderead = TableCodebookDescReader::new(AVC_SPEC_CB2_CODES, AVC_SPEC_CB2_BITS, cb_map2);
+        let mut coderead = TableCodebookDescReader::new(AVC_SPEC_CB2_CODES, AVC_SPEC_CB2_BITS, |idx| AVC_SPEC_CB2_SYMS[idx]);
         let cb2 = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
-        let mut coderead = TableCodebookDescReader::new(AVC_SPEC_CB3_CODES, AVC_SPEC_CB3_BITS, cb_map3);
+        let mut coderead = TableCodebookDescReader::new(AVC_SPEC_CB3_CODES, AVC_SPEC_CB3_BITS, |idx| AVC_SPEC_CB3_SYMS[idx]);
         let cb3 = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
-        let mut coderead = TableCodebookDescReader::new(AVC_SPEC_CB4_CODES, AVC_SPEC_CB4_BITS, cb_map4);
+        let mut coderead = TableCodebookDescReader::new(AVC_SPEC_CB4_CODES, AVC_SPEC_CB4_BITS, |idx| AVC_SPEC_CB4_SYMS[idx]);
         let cb4 = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
-        let mut coderead = TableCodebookDescReader::new(AVC_SPEC_CB5_CODES, AVC_SPEC_CB5_BITS, cb_map5);
+        let mut coderead = TableCodebookDescReader::new(AVC_SPEC_CB5_CODES, AVC_SPEC_CB5_BITS, |idx| AVC_SPEC_CB5_SYMS[idx]);
         let cb5 = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
-        let mut coderead = TableCodebookDescReader::new(AVC_SPEC_CB6_CODES, AVC_SPEC_CB6_BITS, cb_map6);
+        let mut coderead = TableCodebookDescReader::new(AVC_SPEC_CB6_CODES, AVC_SPEC_CB6_BITS, |idx| AVC_SPEC_CB6_SYMS[idx]);
         let cb6 = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
-        let mut coderead = TableCodebookDescReader::new(AVC_SPEC_CB7_CODES, AVC_SPEC_CB7_BITS, cb_map7);
+        let mut coderead = TableCodebookDescReader::new(AVC_SPEC_CB7_CODES, AVC_SPEC_CB7_BITS, |idx| AVC_SPEC_CB7_SYMS[idx]);
         let cb7 = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
-        let mut coderead = TableCodebookDescReader::new(AVC_SPEC_CB8_CODES, AVC_SPEC_CB8_BITS, cb_map8);
+        let mut coderead = TableCodebookDescReader::new(AVC_SPEC_CB8_CODES, AVC_SPEC_CB8_BITS, |idx| AVC_SPEC_CB8_SYMS[idx]);
         let cb8 = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
-        let mut coderead = TableCodebookDescReader::new(AVC_SPEC_CB9_CODES, AVC_SPEC_CB9_BITS, cb_map9);
+        let mut coderead = TableCodebookDescReader::new(AVC_SPEC_CB9_CODES, AVC_SPEC_CB9_BITS, |idx| AVC_SPEC_CB9_SYMS[idx]);
         let cb9 = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
-        let mut coderead = TableCodebookDescReader::new(AVC_SPEC_CB10_CODES, AVC_SPEC_CB10_BITS, cb_map10);
+        let mut coderead = TableCodebookDescReader::new(AVC_SPEC_CB10_CODES, AVC_SPEC_CB10_BITS, |idx| AVC_SPEC_CB10_SYMS[idx]);
         let cb10 = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
-        let mut coderead = TableCodebookDescReader::new(AVC_SPEC_CB11_CODES, AVC_SPEC_CB11_BITS, cb_map11);
+        let mut coderead = TableCodebookDescReader::new(AVC_SPEC_CB11_CODES, AVC_SPEC_CB11_BITS, |idx| AVC_SPEC_CB11_SYMS[idx]);
         let cb11 = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
-        let mut coderead = TableCodebookDescReader::new(AVC_SPEC_CB12_CODES, AVC_SPEC_CB12_BITS, cb_map12);
+        let mut coderead = TableCodebookDescReader::new(AVC_SPEC_CB12_CODES, AVC_SPEC_CB12_BITS, |idx| AVC_SPEC_CB12_SYMS[idx]);
         let cb12 = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
-        let mut coderead = TableCodebookDescReader::new(AVC_SPEC_CB13_CODES, AVC_SPEC_CB13_BITS, cb_map13);
+        let mut coderead = TableCodebookDescReader::new(AVC_SPEC_CB13_CODES, AVC_SPEC_CB13_BITS, |idx| AVC_SPEC_CB13_SYMS[idx]);
         let cb13 = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
-        let mut coderead = TableCodebookDescReader::new(AVC_SPEC_CB14_CODES, AVC_SPEC_CB14_BITS, cb_map14);
+        let mut coderead = TableCodebookDescReader::new(AVC_SPEC_CB14_CODES, AVC_SPEC_CB14_BITS, |idx| AVC_SPEC_CB14_SYMS[idx]);
         let cb14 = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
-        let mut coderead = TableCodebookDescReader::new(AVC_SPEC_CB15_CODES, AVC_SPEC_CB15_BITS, cb_map15);
+        let mut coderead = TableCodebookDescReader::new(AVC_SPEC_CB15_CODES, AVC_SPEC_CB15_BITS, |idx| AVC_SPEC_CB15_SYMS[idx]);
         let cb15 = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
         let spec_cb = [cb1, cb2, cb3, cb4, cb5, cb6, cb7, cb8, cb9, cb10, cb11, cb12, cb13, cb14, cb15];
         Self { scale_cb, spec_cb }
@@ -210,21 +193,36 @@ impl AVCDecoder {
         let mut cur_band = 0;
         let mut scale = 0;
         let mut first = true;
-        for wg in self.win_grp.iter().take(self.windows) {
-            if *wg {
+        for wg in 0..self.windows {
+            if self.win_grp[wg] {
                 for _ in 0..bands {
                     if self.cbs[cur_band] == 0 {
-                        self.scales[cur_band] = 0;
-                    } else {
-                        if first {
-                            scale               = br.read(7)? as i16;
-                            first = false
-                        } else {
-                            scale               += i16::from(br.read_cb(&self.codebooks.scale_cb)?);
-                            validate!((scale >= 0) && (scale < 128));
+                        let mut all_zero = true;
+                        let mut band2 = cur_band;
+                        for wg2 in wg + 1..self.windows {
+                            if self.win_grp[wg2] {
+                                break;
+                            }
+                            band2 += bands;
+                            if self.cbs[band2] != 0 {
+                                all_zero = false;
+                                break;
+                            }
+                        }
+                        if all_zero {
+                            self.scales[cur_band] = 0;
+                            cur_band += 1;
+                            continue;
                         }
-                        self.scales[cur_band] = scale as u8;
                     }
+                    if first {
+                        scale                   = br.read(7)? as i16;
+                        first = false;
+                    } else {
+                        scale                   += i16::from(br.read_cb(&self.codebooks.scale_cb)?);
+                        validate!((0..128).contains(&scale));
+                    }
+                    self.scales[cur_band] = scale as u8;
                     cur_band += 1;
                 }
             } else {
@@ -331,7 +329,7 @@ impl AVCDecoder {
         }
         Ok(())
     }
-    #[allow(clippy::cyclomatic_complexity)]
+    #[allow(clippy::cognitive_complexity)]
     fn synth_channel(&mut self, chno: usize, dst: &mut [f32]) {
         let coeffs = &mut self.coeffs[chno];
         let delay  = &mut self.delay[chno];
@@ -340,123 +338,73 @@ impl AVCDecoder {
             0 | 1 => {
                 self.imdct_long.imdct_half(coeffs, &mut self.tmp);
                 overlap_half(dst, &self.tmp, delay, self.win_long);
-                (&mut delay[0..COEFFS/2]).copy_from_slice(&self.tmp[COEFFS/2..COEFFS]);
+                delay[0..COEFFS/2].copy_from_slice(&self.tmp[COEFFS/2..COEFFS]);
                 for i in COEFFS/2..COEFFS {
                     delay[i] = delay[COEFFS - 1 - i];
                 }
             },
             2 | 7 => {
-                self.imdct_long.imdct(coeffs, &mut self.tmp);
-                for i in 0..SHORT_WIN_POINT0 {
-                    dst[i] = delay[i];
-                }
-                overlap(&mut dst[SHORT_WIN_POINT0..SHORT_WIN_POINT1],
-                        &self.tmp[SHORT_WIN_POINT0..SHORT_WIN_POINT1],
-                        &delay[SHORT_WIN_POINT0..SHORT_WIN_POINT1], AVC_WIN_SHORT);
-                for i in SHORT_WIN_POINT1..COEFFS {
-                    dst[i] = self.tmp[i - SHORT_WIN_POINT1 + 128];
-                }
-                delay.copy_from_slice(&self.tmp[COEFFS..]);
+                self.imdct_long.imdct_half(coeffs, &mut self.ew_buf);
             },
             3 => {
                 for (ain, aout) in coeffs.chunks(128).zip(self.tmp.chunks_mut(256)) {
                     self.imdct_short.imdct(ain, aout);
                 }
                 self.ew_buf = [0.0; 1152];
-                for i in 0..128 {
-                    self.ew_buf[i] = self.tmp[i];
-                }
+                self.ew_buf[..128].copy_from_slice(&self.tmp[..128]);
                 for w in 0..7 {
                     overlap(&mut self.ew_buf[(w + 1) * 128..][..128],
                             &self.tmp[(w + 1) * 256..][..128],
                             &self.tmp[w * 256 + 128..][..128],
                             AVC_WIN_SHORT);
                 }
-                for i in 0..128 {
-                    self.ew_buf[1024 + i] = self.tmp[7 * 256 + 128 + i];
-                }
-                for i in 0..SHORT_WIN_POINT0 {
-                    dst[i] = delay[i];
-                }
+                self.ew_buf[1024..][..128].copy_from_slice(&self.tmp[7 * 256 + 128..][..128]);
+                dst[..SHORT_WIN_POINT0].copy_from_slice(&delay[..SHORT_WIN_POINT0]);
                 overlap(&mut dst[SHORT_WIN_POINT0..SHORT_WIN_POINT1],
                         &self.ew_buf[0..128],
                         &delay[SHORT_WIN_POINT0..SHORT_WIN_POINT1], AVC_WIN_SHORT);
-                for i in SHORT_WIN_POINT1..COEFFS {
-                    dst[i] = self.ew_buf[i - SHORT_WIN_POINT1 + 128];
-                }
-                for i in 0..SHORT_WIN_POINT1 {
-                    delay[i] = self.ew_buf[SHORT_WIN_POINT1 + i];
-                }
-                for i in SHORT_WIN_POINT1..COEFFS {
-                    delay[i] = 0.0;
+                dst[SHORT_WIN_POINT1..COEFFS].copy_from_slice(&self.ew_buf[128..][..COEFFS-SHORT_WIN_POINT1]);
+                delay[..SHORT_WIN_POINT1].copy_from_slice(&self.ew_buf[SHORT_WIN_POINT1..][..SHORT_WIN_POINT1]);
+                for i in COEFFS/2..COEFFS {
+                    delay[i] = delay[COEFFS - 1 - i];
                 }
             },
             4 => {
-                for i in 0..SHORT_WIN_POINT0 {
-                    dst[i] = delay[i];
-                }
                 if !self.use_generic {
                     synth1024(&mut self.dsp, coeffs, &mut self.ew_buf, &mut self.tmp, self.is_40khz);
                 } else {
                     synth_generic(coeffs, &mut self.ew_buf, &mut self.tmp, self.is_40khz, 1024);
                 }
-                overlap_half(&mut dst[SHORT_WIN_POINT0..SHORT_WIN_POINT1],
-                             &self.ew_buf[0..64],
-                             &delay[SHORT_WIN_POINT0..SHORT_WIN_POINT1], AVC_WIN_SHORT);
-                for i in SHORT_WIN_POINT1..COEFFS {
-                    dst[i] = self.ew_buf[i - SHORT_WIN_POINT1 + 64];
-                }
-                for i in 0..COEFFS/2 {
-                    delay[i] = self.ew_buf[COEFFS/2 + i];
-                }
-                for i in COEFFS/2..COEFFS {
-                    delay[i] = delay[COEFFS - 1 - i];
-                }
-            },
+             },
             5 => {
-                for i in 0..SHORT_WIN_POINT0 {
-                    dst[i] = delay[i];
-                }
                 if !self.use_generic {
                     synth512(&mut self.dsp, coeffs, &mut self.ew_buf, &mut self.tmp, self.is_40khz);
                 } else {
                     synth_generic(coeffs, &mut self.ew_buf, &mut self.tmp, self.is_40khz, 512);
                 }
-                self.imdct_mid.imdct(&coeffs[512..], &mut self.ew_buf[512..]);
-                overlap(&mut dst[SHORT_WIN_POINT0..SHORT_WIN_POINT1],
-                        &self.ew_buf[SHORT_WIN_POINT0..SHORT_WIN_POINT1],
-                        &delay[SHORT_WIN_POINT0..SHORT_WIN_POINT1], AVC_WIN_SHORT);
-                for i in SHORT_WIN_POINT1..COEFFS {
-                    dst[i] = self.ew_buf[i];
-                }
-                *delay = [0.0; COEFFS];
-                for i in 0..SHORT_WIN_POINT1 {
-                    delay[i] = self.ew_buf[i];
-                }
+                self.imdct_mid.imdct_half(&coeffs[512..], &mut self.ew_buf[512..]);
             },
             6 => {
-                for i in 0..SHORT_WIN_POINT0 {
-                    dst[i] = delay[i];
-                }
-                self.imdct_mid.imdct(coeffs, &mut self.ew_buf);
+                self.imdct_mid.imdct_half(coeffs, &mut self.ew_buf);
                 if !self.use_generic {
                     synth512(&mut self.dsp, &coeffs[512..], &mut self.ew_buf[512..], &mut self.tmp, self.is_40khz);
                 } else {
                     synth_generic(&coeffs[512..], &mut self.ew_buf[512..], &mut self.tmp, self.is_40khz, 512);
                 }
-                overlap(&mut dst[SHORT_WIN_POINT0..SHORT_WIN_POINT1],
-                        &self.ew_buf[SHORT_WIN_POINT0..SHORT_WIN_POINT1],
-                        &delay[SHORT_WIN_POINT0..SHORT_WIN_POINT1], AVC_WIN_SHORT);
-                for i in SHORT_WIN_POINT1..COEFFS {
-                    dst[i] = self.ew_buf[i];
-                }
-                *delay = [0.0; COEFFS];
-                for i in 0..SHORT_WIN_POINT1 {
-                    delay[i] = self.ew_buf[i];
-                }
             },
             _ => unreachable!(),
         };
+        if (self.cur_win == 2) || (self.cur_win >= 4) {
+            dst[..SHORT_WIN_POINT0].copy_from_slice(&delay[..SHORT_WIN_POINT0]);
+            overlap_half(&mut dst[SHORT_WIN_POINT0..SHORT_WIN_POINT1],
+                         &self.ew_buf[0..64],
+                         &delay[SHORT_WIN_POINT0..SHORT_WIN_POINT1], AVC_WIN_SHORT);
+            dst[SHORT_WIN_POINT1..COEFFS].copy_from_slice(&self.ew_buf[64..][..COEFFS-SHORT_WIN_POINT1]);
+            delay[..COEFFS/2].copy_from_slice(&self.ew_buf[COEFFS/2..COEFFS]);
+            for i in COEFFS/2..COEFFS {
+                delay[i] = delay[COEFFS - 1 - i];
+            }
+        }
     }
 }
 
@@ -540,6 +488,7 @@ fn zero_some(buf: &mut [FFTComplex], p0: usize, p1: usize)
     }
 }
 
+#[allow(clippy::identity_op)]
 fn merge_bands(src: &[FFTComplex], dst: &mut [FFTComplex], size: usize) {
     let step = if size == 512 { 2 } else { 4 };
     let (s01, s23) = src.split_at(size / 2);
@@ -676,12 +625,12 @@ fn synth_recursive(dst: &mut [f32], tmp: &mut [f32], size: usize, order: &[u8],
         let idx = if !dir { i } else { bands - 1 - i };
         synth_filter(src, tmp, size, step, bands, idx);
     }
-    (&mut dst[..size]).copy_from_slice(&tmp[..size]);
+    dst[..size].copy_from_slice(&tmp[..size]);
 }
 
 fn synth_generic(src: &[f32], dst: &mut [f32], tmpbuf: &mut [f32; COEFFS * 2], is_40khz: bool, size: usize) {
     let order = if is_40khz { MERGE_ORDER_40K } else { MERGE_ORDER_44K };
-    (&mut dst[..size]).copy_from_slice(&src[..size]);
+    dst[..size].copy_from_slice(&src[..size]);
     let mut order_idx = 0;
     synth_recursive(dst, tmpbuf, size, order, &mut order_idx, false);
     for el in dst.iter_mut().take(COEFFS) { *el *= 0.125; }
@@ -927,7 +876,7 @@ fn dequant(val: i16, qtab: &[f32; QTAB_SIZE], scale: f32) -> f32 {
     if val >= 0 {
         qtab[val as usize] * scale
     } else {
-        -qtab[val.abs() as usize] * scale
+        -qtab[val.unsigned_abs() as usize] * scale
     }
 }
 
@@ -1079,6 +1028,7 @@ mod test {
 
         //let file = "assets/Duck/Cell-140.vp5";
         //let file = "assets/Duck/Chocolat-500.vp5";
+        // sample: https://samples.mplayerhq.hu/V-codecs/VP7/potter-500.vp7
         let file = "assets/Duck/potter-500.vp7";
         test_decode_audio("avi", file, Some(1500), None/*Some("avc")*/, &dmx_reg, &dec_reg);
     }