rename register_all_codecs to register_all_decoders
[nihav.git] / nihav-duck / src / codecs / on2avc.rs
index 35b9c76ce8620323368246cb92ac29407bf73a23..29ead41d3c1ec9ebf7dd3106fef30495d0e6bf23 100644 (file)
@@ -4,8 +4,8 @@ use nihav_core::io::byteio::read_u16le;
 use nihav_core::io::bitreader::*;
 use nihav_core::io::codebook::*;
 use nihav_core::io::intcode::*;
-use nihav_core::dsp::fft::*;
-use nihav_core::dsp::mdct::IMDCT;
+use nihav_codec_support::dsp::fft::*;
+use nihav_codec_support::dsp::mdct::IMDCT;
 
 use std::str::FromStr;
 
@@ -144,6 +144,7 @@ struct AVCDecoder {
     delay:          [[f32; COEFFS]; 2],
     tmp:            [f32; COEFFS * 2],
     ew_buf:         [f32; 1152],
+    use_generic:    bool,
 
     qtab:           [f32; QTAB_SIZE],
     scale_tab:      [f32; 128],
@@ -194,6 +195,7 @@ impl AVCDecoder {
             delay:          [[0.0; COEFFS]; 2],
             tmp:            [0.0; COEFFS * 2],
             ew_buf:         [0.0; 1152],
+            use_generic:    true,
 
             qtab,
             scale_tab,
@@ -218,7 +220,7 @@ impl AVCDecoder {
                             scale               = br.read(7)? as i16;
                             first = false
                         } else {
-                            scale               += br.read_cb(&self.codebooks.scale_cb)? as i16;
+                            scale               += i16::from(br.read_cb(&self.codebooks.scale_cb)?);
                             validate!((scale >= 0) && (scale < 128));
                         }
                         self.scales[cur_band] = scale as u8;
@@ -329,17 +331,21 @@ impl AVCDecoder {
         }
         Ok(())
     }
+    #[allow(clippy::cyclomatic_complexity)]
     fn synth_channel(&mut self, chno: usize, dst: &mut [f32]) {
         let coeffs = &mut self.coeffs[chno];
         let delay  = &mut self.delay[chno];
 
         match self.cur_win {
             0 | 1 => {
-                self.imdct_long.imdct(coeffs, &mut self.tmp);
-                overlap(dst, &self.tmp, delay, self.win_long);
-                delay.copy_from_slice(&self.tmp[COEFFS..]);
+                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]);
+                for i in COEFFS/2..COEFFS {
+                    delay[i] = delay[COEFFS - 1 - i];
+                }
             },
-            2 => {
+            2 | 7 => {
                 self.imdct_long.imdct(coeffs, &mut self.tmp);
                 for i in 0..SHORT_WIN_POINT0 {
                     dst[i] = delay[i];
@@ -348,7 +354,7 @@ impl AVCDecoder {
                         &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];
+                    dst[i] = self.tmp[i - SHORT_WIN_POINT1 + 128];
                 }
                 delay.copy_from_slice(&self.tmp[COEFFS..]);
             },
@@ -389,30 +395,34 @@ impl AVCDecoder {
                 for i in 0..SHORT_WIN_POINT0 {
                     dst[i] = delay[i];
                 }
-                synth1024(&mut self.dsp, coeffs, &mut self.ew_buf, &mut self.tmp, self.is_40khz);
-                let tmp = &mut self.ew_buf[0..COEFFS];
-                tmp.reverse();
-                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);
+                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];
+                    dst[i] = self.ew_buf[i - SHORT_WIN_POINT1 + 64];
                 }
-                *delay = [0.0; COEFFS];
-                for i in 0..SHORT_WIN_POINT1 {
-                    delay[i] = self.ew_buf[i];
+                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];
                 }
-                synth512(&mut self.dsp, coeffs, &mut self.ew_buf, &mut self.tmp, self.is_40khz);
+                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..]);
-                let tmp = &mut self.ew_buf[512..1024];
-                tmp.reverse();
-                let tmp = &mut self.ew_buf[0..1024];
-                tmp.reverse();
                 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);
@@ -429,11 +439,11 @@ impl AVCDecoder {
                     dst[i] = delay[i];
                 }
                 self.imdct_mid.imdct(coeffs, &mut self.ew_buf);
-                let tmp = &mut self.ew_buf[0..512];
-                tmp.reverse();
-                synth512(&mut self.dsp, &coeffs[512..], &mut self.ew_buf[512..], &mut self.tmp, self.is_40khz);
-                let tmp = &mut self.ew_buf[0..1024];
-                tmp.reverse();
+                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);
@@ -445,22 +455,6 @@ impl AVCDecoder {
                     delay[i] = self.ew_buf[i];
                 }
             },
-            7 => {
-                for i in 0..SHORT_WIN_POINT0 {
-                    dst[i] = delay[i];
-                }
-                self.imdct_long.imdct(coeffs, &mut self.tmp);
-                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];
-                }
-                *delay = [0.0; COEFFS];
-                for i in 0..SHORT_WIN_POINT1 {
-                    delay[i] = self.ew_buf[i];
-                }
-            },
             _ => unreachable!(),
         };
     }
@@ -472,6 +466,19 @@ fn overlap(dst: &mut [f32], src: &[f32], delay: &[f32], win: &[f32]) {
     }
 }
 
+fn overlap_half(dst: &mut [f32], src: &[f32], delay: &[f32], win: &[f32]) {
+    let n = win.len();
+    for i in 0..n/2 {
+        let ii = n - 1 - i;
+        let c = src  [n/2 - 1 - i];
+        let d = delay[i];
+        let w0 = win[i];
+        let w1 = win[ii];
+        dst[i]      = d * w1 - c * w0;
+        dst[ii]     = d * w0 + c * w1;
+    }
+}
+
 #[derive(Clone,Copy)]
 struct SynthParams {
     p0:     usize,
@@ -484,12 +491,12 @@ macro_rules! synth_step0_template {
         fn $name(src: &[f32], dst: &mut [f32], step: usize, off: usize, sp: &SynthParams) {
             for i in 0..step {
                 for j in 0..sp.p0 {
-                    dst[i] += ((src[j] as f64) * $tab[sp.idx][j][i]) as f32;
+                    dst[i] += (f64::from(src[j]) * $tab[sp.idx][j][i]) as f32;
                 }
             }
             for i in 0..step {
                 for j in 0..sp.p1 {
-                    dst[$size - step + i] += ((src[sp.p0 + off + j] as f64) * $tab[sp.idx][sp.p0 + j][i]) as f32;
+                    dst[$size - step + i] += (f64::from(src[sp.p0 + off + j]) * $tab[sp.idx][sp.p0 + j][i]) as f32;
                 }
             }
         }
@@ -505,7 +512,7 @@ fn synth_step1(src: &[f32], dst: &mut [f32], size: usize, stride: usize, step: u
 {
     let mut pos = step - 1;
     for _ in 0..off {
-        let scale = src[p0] as f64;
+        let scale = f64::from(src[p0]);
         p0 += 1;
         pos &= size - 1;
         for i in 0..pos.min(step) {
@@ -594,12 +601,92 @@ fn merge_bands(src: &[FFTComplex], dst: &mut [FFTComplex], size: usize) {
     }
 }
 
+const SPARAMS10: [SynthParams; 2] = [
+    SynthParams { p0: 1, p1: 3, idx: 0 },
+    SynthParams { p0: 3, p1: 1, idx: 1 } ];
+const SPARAMS20: [SynthParams; 2] = [
+    SynthParams { p0: 5, p1: 4, idx: 0 },
+    SynthParams { p0: 4, p1: 5, idx: 1 } ];
+const SPARAMS40: [SynthParams; 2] = [
+    SynthParams { p0: 11, p1:  8, idx: 0 },
+    SynthParams { p0:  8, p1: 11, idx: 1 } ];
 const SPARAMS84: [SynthParams; 4] = [
     SynthParams { p0: 16, p1: 4, idx: 0 },
     SynthParams { p0: 16, p1: 4, idx: 1 },
     SynthParams { p0: 13, p1: 7, idx: 2 },
     SynthParams { p0: 15, p1: 5, idx: 3 } ];
 
+const MERGE_ORDER_44K: &[u8] = &[
+    4, 4, 2, 2, 0, 0, 2, 0, 0, 2, 2, 0, 0, 2, 0, 0, 2, 0, 0,
+    2, 0, 0, 4, 0, 0, 0, 0, 2, 0, 0, 0
+];
+const MERGE_ORDER_40K: &[u8] = &[
+    4, 4, 2, 2, 0, 0, 2, 0, 0, 2, 2, 0, 0, 2, 0, 0, 2, 0, 0,
+    2, 0, 0, 4, 2, 0, 0, 2, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0
+];
+
+fn synth_filter(src: &[f32], dst: &mut [f32], len: usize, step: usize, bands: usize, idx: usize)
+{
+    let off = (len - step) / bands + 1;
+    let params = match step {
+            10 => &SPARAMS10[idx],
+            20 => &SPARAMS20[idx],
+            40 => &SPARAMS40[idx],
+            _  => &SPARAMS84[idx],
+        };
+
+    if step == 10 {
+        synth_step0_10(src, dst, step, off, params);
+        synth_step1(src, dst, len, bands, step, off, params.p0, &AVC_TAB10[idx]);
+    } else if step == 20 {
+        synth_step0_20(src, dst, step, off, params);
+        synth_step1(src, dst, len, bands, step, off, params.p0, &AVC_TAB20[idx]);
+    } else if step == 40 {
+        synth_step0_40(src, dst, step, off, params);
+        synth_step1(src, dst, len, bands, step, off, params.p0, &AVC_TAB40[idx]);
+    } else {
+        synth_step0_84(src, dst, step, off, params);
+        synth_step1(src, dst, len, bands, step, off, params.p0, &AVC_TAB84[idx]);
+    }
+}
+
+fn synth_recursive(dst: &mut [f32], tmp: &mut [f32], size: usize, order: &[u8], order_idx: &mut usize, dir: bool) {
+    let bands = order[*order_idx] as usize;
+    *order_idx += 1;
+    if bands == 0 { return; }
+    let sub_size = size / bands;
+    let mut sub_dir = false;
+    for (dst, tmp) in dst.chunks_mut(sub_size).take(bands).zip(tmp.chunks_mut(sub_size)) {
+        synth_recursive(dst, tmp, sub_size, order, order_idx, sub_dir);
+        sub_dir = !sub_dir;
+    }
+    for el in tmp.iter_mut().take(size) { *el = 0.0; }
+    let step = if bands == 2 {
+            if sub_size <= 20 {
+                10
+            } else if sub_size <= 40 {
+                20
+            } else {
+                40
+            }
+        } else {
+            84
+        };
+    for (i, src) in dst.chunks_mut(sub_size).take(bands).enumerate() {
+        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]);
+}
+
+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]);
+    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; }
+}
+
 fn synth1024(dsp: &mut SynthDSP, src: &[f32], dst: &mut [f32], tmpbuf: &mut [f32; COEFFS * 2], is_40khz: bool) {
     for el in tmpbuf.iter_mut() {
         *el = 0.0;
@@ -926,7 +1013,7 @@ impl NADecoder for AVCDecoder {
         if self.version == 500 {
             abuf = alloc_audio_buffer(self.ainfo, COEFFS, self.chmap.clone())?;
             let mut adata = abuf.get_abuf_f32().unwrap();
-            let mut br = BitReader::new(src.as_slice(), src.len(), BitReaderMode::BE);
+            let mut br = BitReader::new(src.as_slice(), BitReaderMode::BE);
             self.decode_frame(&mut br, &mut adata, 0)?;
         } else {
             let mut offsets: Vec<usize> = Vec::new();
@@ -948,7 +1035,7 @@ impl NADecoder for AVCDecoder {
             let mut adata = abuf.get_abuf_f32().unwrap();
             let mut aoffset = 0;
             for (o, s) in offsets.iter().zip(sizes.iter()) {
-                let mut br = BitReader::new(&src[*o..], *s, BitReaderMode::BE);
+                let mut br = BitReader::new(&src[*o..][..*s], BitReaderMode::BE);
                 self.decode_frame(&mut br, &mut adata, aoffset)?;
                 aoffset += COEFFS;
             }
@@ -958,13 +1045,21 @@ impl NADecoder for AVCDecoder {
         frm.set_keyframe(true);
         Ok(frm.into_ref())
     }
+    fn flush(&mut self) {
+    }
+}
+
+impl NAOptionHandler for AVCDecoder {
+    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_500() -> Box<dyn NADecoder> {
+pub fn get_decoder_500() -> Box<dyn NADecoder + Send> {
     Box::new(AVCDecoder::new(500))
 }
 
-pub fn get_decoder_501() -> Box<dyn NADecoder> {
+pub fn get_decoder_501() -> Box<dyn NADecoder + Send> {
     Box::new(AVCDecoder::new(501))
 }
 
@@ -972,20 +1067,20 @@ pub fn get_decoder_501() -> Box<dyn NADecoder> {
 mod test {
     use nihav_core::codecs::RegisteredDecoders;
     use nihav_core::demuxers::RegisteredDemuxers;
-    use nihav_core::test::dec_video::*;
-    use crate::codecs::duck_register_all_codecs;
-    use nihav_commonfmt::demuxers::generic_register_all_demuxers;
+    use nihav_codec_support::test::dec_video::*;
+    use crate::duck_register_all_decoders;
+    use nihav_commonfmt::generic_register_all_demuxers;
     #[test]
     fn test_avc() {
         let mut dmx_reg = RegisteredDemuxers::new();
         generic_register_all_demuxers(&mut dmx_reg);
         let mut dec_reg = RegisteredDecoders::new();
-        duck_register_all_codecs(&mut dec_reg);
+        duck_register_all_decoders(&mut dec_reg);
 
         //let file = "assets/Duck/Cell-140.vp5";
         //let file = "assets/Duck/Chocolat-500.vp5";
         let file = "assets/Duck/potter-500.vp7";
-        test_decode_audio("avi", file, Some(1500), "avc", &dmx_reg, &dec_reg);
+        test_decode_audio("avi", file, Some(1500), None/*Some("avc")*/, &dmx_reg, &dec_reg);
     }
 }