X-Git-Url: https://git.nihav.org/?p=nihav.git;a=blobdiff_plain;f=nihav-duck%2Fsrc%2Fcodecs%2Fon2avc.rs;h=29ead41d3c1ec9ebf7dd3106fef30495d0e6bf23;hp=35b9c76ce8620323368246cb92ac29407bf73a23;hb=78fb6560c73965d834b215fb0b49505ae5443288;hpb=1333465786c9d2746030a1024e5ceb2ea1a77be5 diff --git a/nihav-duck/src/codecs/on2avc.rs b/nihav-duck/src/codecs/on2avc.rs index 35b9c76..29ead41 100644 --- a/nihav-duck/src/codecs/on2avc.rs +++ b/nihav-duck/src/codecs/on2avc.rs @@ -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 = 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 { None } } -pub fn get_decoder_500() -> Box { +pub fn get_decoder_500() -> Box { Box::new(AVCDecoder::new(500)) } -pub fn get_decoder_501() -> Box { +pub fn get_decoder_501() -> Box { Box::new(AVCDecoder::new(501)) } @@ -972,20 +1067,20 @@ pub fn get_decoder_501() -> Box { 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); } }