+use nihav_core::frame::*;
+use nihav_core::codecs::*;
+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 std::str::FromStr;
+
+use super::on2avcdata::*;
+
+const COEFFS: usize = 1024;
+const MAX_BANDS: usize = 14 * 8;
+const QTAB_SIZE: usize = 10000;
+const SHORT_WIN_POINT0: usize = 512 - 64;
+const SHORT_WIN_POINT1: usize = 512 + 64;
+
+struct WinInfo {
+ is_long: bool,
+ bands: &'static [usize],
+}
+
+impl WinInfo {
+ fn get_tot_bands(&self) -> usize {
+ if self.is_long {
+ self.bands.len()
+ } else {
+ self.bands.len() * 8
+ }
+ }
+}
+
+struct Codebooks {
+ scale_cb: Codebook<i8>,
+ 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 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 cb1 = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
+ let mut coderead = TableCodebookDescReader::new(AVC_SPEC_CB2_CODES, AVC_SPEC_CB2_BITS, cb_map2);
+ 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 cb3 = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
+ let mut coderead = TableCodebookDescReader::new(AVC_SPEC_CB4_CODES, AVC_SPEC_CB4_BITS, cb_map4);
+ 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 cb5 = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
+ let mut coderead = TableCodebookDescReader::new(AVC_SPEC_CB6_CODES, AVC_SPEC_CB6_BITS, cb_map6);
+ 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 cb7 = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
+ let mut coderead = TableCodebookDescReader::new(AVC_SPEC_CB8_CODES, AVC_SPEC_CB8_BITS, cb_map8);
+ 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 cb9 = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
+ let mut coderead = TableCodebookDescReader::new(AVC_SPEC_CB10_CODES, AVC_SPEC_CB10_BITS, cb_map10);
+ 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 cb11 = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
+ let mut coderead = TableCodebookDescReader::new(AVC_SPEC_CB12_CODES, AVC_SPEC_CB12_BITS, cb_map12);
+ 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 cb13 = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
+ let mut coderead = TableCodebookDescReader::new(AVC_SPEC_CB14_CODES, AVC_SPEC_CB14_BITS, cb_map14);
+ 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 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 }
+ }
+}
+
+struct SynthDSP {
+ rdft512: RDFT,
+ rdft256: RDFT,
+ irdft128: RDFT,
+ irdft64: RDFT,
+ synth_tmp: [FFTComplex; 512],
+ synth_out: [FFTComplex; 512],
+}
+
+impl SynthDSP {
+ fn new() -> Self {
+ let rdft512 = RDFTBuilder::new_rdft(512, true, true);
+ let rdft256 = RDFTBuilder::new_rdft(256, true, true);
+ let irdft128 = RDFTBuilder::new_rdft(128, false, false);
+ let irdft64 = RDFTBuilder::new_rdft(64, false, false);
+ Self {
+ rdft512, rdft256, irdft128, irdft64,
+ synth_tmp: [FFTC_ZERO; 512],
+ synth_out: [FFTC_ZERO; 512],
+ }
+ }
+}
+
+struct AVCDecoder {
+ chmap: NAChannelMap,
+ ainfo: NAAudioInfo,
+ info: NACodecInfoRef,
+ dsp: SynthDSP,
+ version: i32,
+ codebooks: Codebooks,
+ channels: usize,
+ is_40khz: bool,
+ win_long: &'static [f32; 1024],
+
+ prev_win: u8,
+ cur_win: u8,
+ winfo: &'static WinInfo,
+ windows: usize,
+ win_grp: [bool; 8],
+ ms_present: bool,
+ ms_info: [bool; MAX_BANDS],
+ cbs: [u8; MAX_BANDS],
+ scales: [u8; MAX_BANDS],
+
+ imdct_long: IMDCT,
+ imdct_mid: IMDCT,
+ imdct_short: IMDCT,
+ coeffs: [[f32; COEFFS]; 2],
+ delay: [[f32; COEFFS]; 2],
+ tmp: [f32; COEFFS * 2],
+ ew_buf: [f32; 1152],
+
+ qtab: [f32; QTAB_SIZE],
+ scale_tab: [f32; 128],
+}
+
+impl AVCDecoder {
+ fn new(version: i32) -> Self {
+ let mut qtab = [0.0f32; QTAB_SIZE];
+ for (i, el) in qtab.iter_mut().enumerate() {
+ *el = (i as f32) * (i as f32).sqrt();
+ }
+ let mut scale_tab = [0.0f32; 128];
+ for (i, el) in scale_tab.iter_mut().enumerate() {
+ let pow = 10.0f32.powf((i as f32) * 0.1);
+ if i < 20 {
+ *el = (pow * 16.0).ceil() / 32.0;
+ } else {
+ *el = (pow * 0.5).ceil();
+ }
+ *el /= 32768.0;
+ }
+
+ AVCDecoder {
+ chmap: NAChannelMap::new(),
+ ainfo: NAAudioInfo::new(0, 0, SND_F32P_FORMAT, 0),
+ info: NACodecInfo::new_dummy(),
+ dsp: SynthDSP::new(),
+ version,
+ codebooks: Codebooks::new(),
+ channels: 0,
+ is_40khz: false,
+ win_long: AVC_WIN_LONG_32K,
+
+ prev_win: 0,
+ cur_win: 0,
+ winfo: &AVC_WINFO_LONG,
+ windows: 0,
+ win_grp: [false; 8],
+ ms_present: false,
+ ms_info: [false; MAX_BANDS],
+ cbs: [0; MAX_BANDS],
+ scales: [0; MAX_BANDS],
+
+ imdct_long: IMDCT::new(1024 * 2, true),
+ imdct_mid: IMDCT::new(512 * 2, true),
+ imdct_short: IMDCT::new(128 * 2, true),
+ coeffs: [[0.0; COEFFS]; 2],
+ delay: [[0.0; COEFFS]; 2],
+ tmp: [0.0; COEFFS * 2],
+ ew_buf: [0.0; 1152],
+
+ qtab,
+ scale_tab,
+ }
+ }
+ fn decode_channel(&mut self, br: &mut BitReader, chno: usize) -> DecoderResult<()> {
+ let coeffs = &mut self.coeffs[chno];
+
+ decode_band_types(br, &mut self.cbs, self.winfo)?;
+ // band scales
+ let bands = self.winfo.bands.len();
+ 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 _ 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 += br.read_cb(&self.codebooks.scale_cb)? as i16;
+ validate!((scale >= 0) && (scale < 128));
+ }
+ self.scales[cur_band] = scale as u8;
+ }
+ cur_band += 1;
+ }
+ } else {
+ for _ in 0..bands {
+ self.scales[cur_band] = self.scales[cur_band - bands];
+ cur_band += 1;
+ }
+ }
+ }
+ // coefficients
+ let mut cur_band = 0;
+ let mut idx = 0;
+ *coeffs = [0.0; COEFFS];
+ for _ in 0..self.windows {
+ let mut band_start = 0;
+ for band_end in self.winfo.bands.iter() {
+ let band_size = *band_end - band_start;
+ let cb_idx = self.cbs[cur_band];
+ if cb_idx > 0 {
+ let cb = &self.codebooks.spec_cb[(cb_idx - 1) as usize];
+ let scale = self.scale_tab[self.scales[cur_band] as usize];
+ let dst = &mut coeffs[idx..][..band_size];
+ if cb_idx < 9 {
+ decode_quads(br, cb, &self.qtab, scale, dst)?;
+ } else {
+ decode_pairs(br, cb, &self.qtab, scale, dst, cb_idx == 15)?;
+ }
+ }
+
+ band_start = *band_end;
+ idx += band_size;
+ cur_band += 1;
+ }
+ }
+ Ok(())
+ }
+ fn decode_frame(&mut self, br: &mut BitReader, adata: &mut NAAudioBuffer<f32>, offset: usize) -> DecoderResult<()> {
+ let enh_flag = br.read_bool()?;
+ validate!(!enh_flag);
+ self.prev_win = self.cur_win;
+ self.cur_win = br.read(3)? as u8;
+ self.winfo = match self.cur_win {
+ 3 => &AVC_WINFO_SHORT,
+ 4 => if self.is_40khz { &AVC_WINFO_40K_MODE4 } else { &AVC_WINFO_44K_MODE4 },
+ 5 => if self.is_40khz { &AVC_WINFO_40K_MODE5 } else { &AVC_WINFO_44K_MODE5 },
+ 6 => if self.is_40khz { &AVC_WINFO_40K_MODE6 } else { &AVC_WINFO_44K_MODE6 },
+ _ => &AVC_WINFO_LONG,
+ };
+ self.windows = if self.winfo.is_long { 1 } else { 8 };
+ let bands = self.winfo.bands.len();
+ self.win_grp[0] = true;
+ for el in self.win_grp.iter_mut().skip(1).take(self.windows - 1) {
+ *el = !br.read_bool()?;
+ }
+
+ self.ms_present = br.read_bool()?;
+ if self.ms_present {
+ validate!(self.channels == 2);
+ let mut cur_band = 0;
+ for wg in self.win_grp.iter().take(self.windows) {
+ if *wg {
+ for _ in 0..bands {
+ self.ms_info[cur_band] = br.read_bool()?;
+ cur_band += 1;
+ }
+ } else {
+ for _ in 0..bands {
+ self.ms_info[cur_band] = self.ms_info[cur_band - bands];
+ cur_band += 1;
+ }
+ }
+ }
+ }
+ for ch in 0..self.channels {
+ self.decode_channel(br, ch)?;
+ }
+
+ if (self.channels == 2) && self.ms_present {
+ let mut idx = 0;
+ let mut cur_band = 0;
+ for _ in 0..self.windows {
+ let mut band_start = 0;
+ for band_end in self.winfo.bands.iter() {
+ let band_size = *band_end - band_start;
+ if self.ms_info[cur_band] {
+ for i in 0..band_size {
+ let l = self.coeffs[0][idx + i];
+ let r = self.coeffs[1][idx + i];
+ self.coeffs[0][idx + i] = l + r;
+ self.coeffs[1][idx + i] = l - r;
+ }
+ }
+ cur_band += 1;
+ idx += band_size;
+ band_start = *band_end;
+ }
+ }
+ }
+
+ for ch in 0..self.channels {
+ let off = adata.get_offset(ch) + offset;
+ let output = adata.get_data_mut().unwrap();
+ self.synth_channel(ch, &mut output[off..][..COEFFS]);
+ }
+ Ok(())
+ }
+ 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..]);
+ },
+ 2 => {
+ 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];
+ }
+ delay.copy_from_slice(&self.tmp[COEFFS..]);
+ },
+ 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];
+ }
+ 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];
+ }
+ 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;
+ }
+ },
+ 4 => {
+ 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);
+ 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];
+ }
+ },
+ 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);
+ 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);
+ 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];
+ }
+ },
+ 6 => {
+ for i in 0..SHORT_WIN_POINT0 {
+ 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();
+ 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];
+ }
+ },
+ 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!(),
+ };
+ }
+}
+
+fn overlap(dst: &mut [f32], src: &[f32], delay: &[f32], win: &[f32]) {
+ for (i, ((out, s), d)) in dst.iter_mut().zip(src.iter()).zip(delay.iter()).enumerate() {
+ *out = *s * win[i] + *d * win[win.len() - 1 - i];
+ }
+}
+
+#[derive(Clone,Copy)]
+struct SynthParams {
+ p0: usize,
+ p1: usize,
+ idx: usize
+}
+
+macro_rules! synth_step0_template {
+ ($name:ident, $tab: ident, $size: expr) => {
+ 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;
+ }
+ }
+ 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;
+ }
+ }
+ }
+ }
+}
+
+synth_step0_template!(synth_step0_10, AVC_SYNTH_TABS10, 10);
+synth_step0_template!(synth_step0_20, AVC_SYNTH_TABS20, 20);
+synth_step0_template!(synth_step0_40, AVC_SYNTH_TABS40, 40);
+synth_step0_template!(synth_step0_84, AVC_SYNTH_TABS84, 84);
+
+fn synth_step1(src: &[f32], dst: &mut [f32], size: usize, stride: usize, step: usize, off: usize, mut p0: usize, win: &[f64])
+{
+ let mut pos = step - 1;
+ for _ in 0..off {
+ let scale = src[p0] as f64;
+ p0 += 1;
+ pos &= size - 1;
+ for i in 0..pos.min(step) {
+ dst[pos - i] += (scale * win[i]) as f32;
+ }
+ pos += stride;
+ }
+}
+
+fn zero_some(buf: &mut [FFTComplex], p0: usize, p1: usize)
+{
+ for el in buf.iter_mut().take(p0/2) {
+ *el = FFTC_ZERO;
+ }
+ if (p0 & 1) != 0 {
+ buf[p0 / 2].re = 0.0;
+ }
+ let len = buf.len();
+ let dst = &mut buf[len - p1/2..];
+ for el in dst.iter_mut() {
+ *el = FFTC_ZERO;
+ }
+ if (p1 & 1) != 0 {
+ buf[len - p1/2 - 1].im = 0.0;
+ }
+}
+
+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);
+ let (src0, src1) = s01.split_at(size / 4);
+ let (src2, src3) = s23.split_at(size / 4);
+ let (t00, t01) = AVC_SYNTH_TAB0.split_at(512);
+ let (t10, t11) = AVC_SYNTH_TAB1.split_at(512);
+ let (t20, t21) = AVC_SYNTH_TAB2.split_at(512);
+ let (t30, t31) = AVC_SYNTH_TAB3.split_at(512);
+ let hsize = size / 2;
+ let qsize = size / 4;
+ let osize = size / 8;
+ dst[0].re = src0[0].re * t00[0] + src1[0].re * t10[0] + src2[0].re * t20[0] + src3[0].re * t30[0];
+ dst[0].im = src0[0].re * t00[1] + src1[0].re * t10[1] + src2[0].re * t20[1] + src3[0].re * t30[1];
+ dst[qsize].re = src0[0].im * t00[256] + src1[0].im * t10[256] +
+ src2[0].im * t20[256] + src3[0].im * t30[256];
+ dst[qsize].im = src0[0].im * t00[257] + src1[0].im * t10[257] +
+ src2[0].im * t20[257] + src3[0].im * t30[257];
+ for i in 1..qsize {
+ let s0 = src0[i];
+ let s1 = src1[i];
+ let s2 = src2[i];
+ let s3 = src3[i];
+ let t0 = s0 * FFTComplex { re: t00[i * step + 0], im: t00[i * step + 1] } +
+ s1 * FFTComplex { re: t10[i * step + 0], im: t10[i * step + 1] } +
+ s2 * FFTComplex { re: t20[i * step + 0], im: t20[i * step + 1] } +
+ s3 * FFTComplex { re: t30[i * step + 0], im: t30[i * step + 1] };
+ let t1 = s0 * FFTComplex { re: t01[i * step + 0], im: t01[i * step + 1] } +
+ s1 * FFTComplex { re: t11[i * step + 0], im: t11[i * step + 1] } +
+ s2 * FFTComplex { re: t21[i * step + 0], im: t21[i * step + 1] } +
+ s3 * FFTComplex { re: t31[i * step + 0], im: t31[i * step + 1] };
+ dst[i] = t0;
+ dst[qsize + i] = t1;
+ }
+
+ dst[hsize].re = src0[0].im * t01[256] + src1[0].im * t11[256] +
+ src2[0].im * t21[256] + src3[0].im * t31[256];
+ dst[hsize].im = src0[0].im * t01[257] + src1[0].im * t11[257] +
+ src2[0].im * t21[257] + src3[0].im * t31[257];
+ dst[hsize + qsize].re = src0[0].re * t01[256] + src1[0].re * t11[256] +
+ src2[0].re * t21[256] + src3[0].re * t31[256];
+ dst[hsize + qsize].im = src0[0].re * t01[257] + src1[0].re * t11[257] +
+ src2[0].re * t21[257] + src3[0].re * t31[257];
+ for i in 1..osize {
+ let s0 = !src0[qsize - i];
+ let s1 = !src1[qsize - i];
+ let s2 = !src2[qsize - i];
+ let s3 = !src3[qsize - i];
+ let t0 = s0 * FFTComplex { re: t00[256 + i * step + 0], im: t00[256 + i * step + 1] } +
+ s1 * FFTComplex { re: t10[256 + i * step + 0], im: t10[256 + i * step + 1] } +
+ s2 * FFTComplex { re: t20[256 + i * step + 0], im: t20[256 + i * step + 1] } +
+ s3 * FFTComplex { re: t30[256 + i * step + 0], im: t30[256 + i * step + 1] };
+ let t1 = s0 * FFTComplex { re: t01[256 + i * step + 0], im: t01[256 + i * step + 1] } +
+ s1 * FFTComplex { re: t11[256 + i * step + 0], im: t11[256 + i * step + 1] } +
+ s2 * FFTComplex { re: t21[256 + i * step + 0], im: t21[256 + i * step + 1] } +
+ s3 * FFTComplex { re: t31[256 + i * step + 0], im: t31[256 + i * step + 1] };
+ dst[hsize + i] = !t0;
+ dst[hsize + qsize + i] = !t1;
+ }
+}
+
+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 } ];
+
+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;
+ }
+ let (tmp, tmp2) = tmpbuf.split_at_mut(COEFFS);
+ for el in dsp.synth_tmp.iter_mut() { *el = FFTC_ZERO; }
+ for el in dsp.synth_out.iter_mut() { *el = FFTC_ZERO; }
+
+ let (size, step, stride) = (32, 20, 2);
+ let off = (size - step) / stride + 1;
+ let mut sparam0 = SynthParams { p0: 5, p1: 4, idx: 0 };
+ let mut sparam1 = SynthParams { p0: 4, p1: 5, idx: 1 };
+ for (i, dst) in tmp.chunks_mut(size).take(8).enumerate() {
+ let coeffs = &src[i * 32..];
+ synth_step0_20(coeffs, dst, step, off, &sparam0);
+ synth_step1(coeffs, dst, size, stride, step, off, sparam0.p0, &AVC_TAB20[sparam0.idx]);
+ let coeffs = &src[i * 32 + 16..];
+ synth_step0_20(coeffs, dst, step, off, &sparam1);
+ synth_step1(coeffs, dst, size, stride, step, off, sparam0.p0, &AVC_TAB20[sparam1.idx]);
+ std::mem::swap(&mut sparam0, &mut sparam1);
+ }
+
+ let (size, step, stride) = (64, 40, 2);
+ let off = (size - step) / stride + 1;
+ let mut sparam0 = SynthParams { p0: 11, p1: 8, idx: 0 };
+ let mut sparam1 = SynthParams { p0: 8, p1: 11, idx: 1 };
+ let nchunks = if !is_40khz { 8 } else { 12 };
+ for (i, dst) in tmp2.chunks_mut(size).take(nchunks).enumerate() {
+ let coeffs = if i < 4 { &tmp[i * 64..] } else { &src[i * 64 + 32..] };
+ synth_step0_40(coeffs, dst, step, off, &sparam0);
+ synth_step1(coeffs, dst, size, stride, step, off, sparam0.p0, &AVC_TAB40[sparam0.idx]);
+ let coeffs = if i < 4 { &tmp[i * 64 + 32..] } else { &src[i * 64 + 32..] };
+ synth_step0_40(coeffs, dst, step, off, &sparam1);
+ synth_step1(coeffs, dst, size, stride, step, off, sparam0.p0, &AVC_TAB40[sparam1.idx]);
+ std::mem::swap(&mut sparam0, &mut sparam1);
+ }
+
+ for el in tmp.iter_mut().take(128) {
+ *el = 0.0;
+ }
+ let (size, step, stride) = (256, 84, 4);
+ let off = (size - step) / stride + 1;
+ for i in 0..4 {
+ let coeffs = &tmp2[i * 64..];
+ synth_step0_84(coeffs, tmp, step, off, &SPARAMS84[i]);
+ synth_step1(coeffs, tmp, size, stride, step, off, SPARAMS84[i].p0, &AVC_TAB84[i]);
+ }
+ for i in 0..4 {
+ let coeffs = if i < 2 && is_40khz { &tmp2[256 + i * 64..] } else { &src[256 + i * 64..] };
+ let dst = &mut tmp[256..];
+ synth_step0_84(coeffs, dst, step, off, &SPARAMS84[3 - i]);
+ synth_step1(coeffs, dst, size, stride, step, off, SPARAMS84[3 - i].p0, &AVC_TAB84[3 - i]);
+ }
+
+ if !is_40khz {
+ let (size, step, stride) = (256, 40, 2);
+ let off = (size - step) / stride + 1;
+ let sparams = [ SynthParams { p0: 11, p1: 8, idx: 0 },
+ SynthParams { p0: 8, p1: 11, idx: 1 } ];
+ for i in 0..2 {
+ let coeffs = &src[512 + i * 128..];
+ let dst = &mut tmp[512..];
+ synth_step0_40(coeffs, dst, step, off, &sparams[i]);
+ synth_step1(coeffs, dst, size, stride, step, off, sparams[i].p0, &AVC_TAB40[i]);
+ }
+ } else {
+ let (size, step, stride) = (256, 84, 4);
+ let off = (size - step) / stride + 1;
+ for i in 0..4 {
+ let coeffs = &src[512 + i * 64..];
+ let dst = &mut tmp[512..];
+ synth_step0_84(coeffs, dst, step, off, &SPARAMS84[i]);
+ synth_step1(coeffs, dst, size, stride, step, off, SPARAMS84[i].p0, &AVC_TAB84[i]);
+ }
+ }
+
+ for (i, s) in tmp.chunks(2).take(768/2).enumerate() {
+ dsp.synth_tmp[i] = FFTComplex { re: s[0], im: s[1] };
+ }
+ for i in (768..1024).step_by(2) {
+ dsp.synth_tmp[i >> 1] = FFTComplex { re: src[i], im: src[i + 1] };
+ }
+ {
+ let dst = &mut tmp[768..1024];
+ dst.copy_from_slice(&src[768..1024]);
+ }
+ for (i, chunk) in dsp.synth_tmp.chunks_exact_mut(128).enumerate() {
+ zero_some(chunk, SPARAMS84[i].p0, SPARAMS84[i].p1);
+ }
+ for chunk in dsp.synth_tmp.chunks_exact_mut(128) {
+ dsp.irdft128.do_rdft_inplace(chunk);
+ for el in chunk.iter_mut() { *el = el.scale(1.0/128.0f32); }
+ }
+ merge_bands(&dsp.synth_tmp, &mut dsp.synth_out, 512);
+ dsp.rdft512.do_rdft_inplace(&mut dsp.synth_out);
+ for (out, src) in dst.chunks_exact_mut(2).zip(dsp.synth_out.iter()) {
+ out[0] = src.re * (1.0 / 1024.0f32.sqrt());
+ out[1] = src.im * (1.0 / 1024.0f32.sqrt());
+ }
+ let (size, step, stride) = (1024, 84, 4);
+ let off = (size - step) / stride + 1;
+ for i in 0..4 {
+ let src = &tmp[256 * i..];
+ synth_step0_84(src, dst, step, off, &SPARAMS84[i]);
+ }
+}
+fn synth512(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;
+ }
+ let (tmp, tmp2) = tmpbuf.split_at_mut(COEFFS);
+
+ let (size, step, stride) = (16, 10, 2);
+ let off = (size - step) / stride + 1;
+ let mut sparam0 = SynthParams { p0: 1, p1: 3, idx: 0 };
+ let mut sparam1 = SynthParams { p0: 3, p1: 1, idx: 1 };
+ let mut tab_ptr0: &[f64] = AVC_TAB10_0;
+ let mut tab_ptr1: &[f64] = AVC_TAB10_1;
+ for (i, dst) in tmp.chunks_mut(size).take(8).enumerate() {
+ let coeffs = &src[i * 16..];
+ synth_step0_10(coeffs, dst, step, off, &sparam0);
+ synth_step1(coeffs, dst, size, stride, step, off, sparam0.p0, tab_ptr0);
+ let coeffs = &src[i * 16 + 8..];
+ synth_step0_10(coeffs, dst, step, off, &sparam1);
+ synth_step1(coeffs, dst, size, stride, step, off, sparam0.p0, tab_ptr1);
+ std::mem::swap(&mut sparam0, &mut sparam1);
+ std::mem::swap(&mut tab_ptr0, &mut tab_ptr1);
+ }
+
+ let (size, step, stride) = (32, 20, 2);
+ let off = (size - step) / stride + 1;
+ let mut sparam0 = SynthParams { p0: 5, p1: 4, idx: 0 };
+ let mut sparam1 = SynthParams { p0: 4, p1: 5, idx: 1 };
+ let nchunks = if !is_40khz { 8 } else { 12 };
+ for (i, dst) in tmp2.chunks_mut(size).take(nchunks).enumerate() {
+ let coeffs = if i < 4 { &tmp[i * 32..] } else { &src[i * 32..] };
+ synth_step0_20(coeffs, dst, step, off, &sparam0);
+ synth_step1(coeffs, dst, size, stride, step, off, sparam0.p0, &AVC_TAB20[sparam0.idx]);
+ let coeffs = if i < 4 { &tmp[i * 32 + 16..] } else { &src[i * 32 + 16..] };
+ synth_step0_20(coeffs, dst, step, off, &sparam1);
+ synth_step1(coeffs, dst, size, stride, step, off, sparam0.p0, &AVC_TAB20[sparam1.idx]);
+ std::mem::swap(&mut sparam0, &mut sparam1);
+ }
+
+ for el in tmp.iter_mut().take(64) {
+ *el = 0.0;
+ }
+ let (size, step, stride) = (128, 84, 4);
+ let off = (size - step) / stride + 1;
+ for i in 0..4 {
+ let coeffs = &tmp2[i * 32..];
+ synth_step0_84(coeffs, tmp, step, off, &SPARAMS84[i]);
+ synth_step1(coeffs, tmp, size, stride, step, off, SPARAMS84[i].p0, &AVC_TAB84[i]);
+ }
+ for i in 0..4 {
+ let coeffs = if i < 2 && is_40khz { &tmp2[128 + i * 32..] } else { &src[128 + i * 32..] };
+ let dst = &mut tmp[128..];
+ synth_step0_84(coeffs, dst, step, off, &SPARAMS84[3 - i]);
+ synth_step1(coeffs, dst, size, stride, step, off, SPARAMS84[3 - i].p0, &AVC_TAB84[3 - i]);
+ }
+
+ if !is_40khz {
+ let (size, step, stride) = (128, 40, 2);
+ let off = (size - step) / stride + 1;
+ let sparams = [ SynthParams { p0: 11, p1: 8, idx: 0 },
+ SynthParams { p0: 8, p1: 11, idx: 1 } ];
+ for i in 0..2 {
+ let coeffs = &src[256 + i * 64..];
+ let dst = &mut tmp[256..];
+ synth_step0_40(coeffs, dst, step, off, &sparams[i]);
+ synth_step1(coeffs, dst, size, stride, step, off, sparams[i].p0, &AVC_TAB40[i]);
+ }
+ } else {
+ let (size, step, stride) = (128, 84, 4);
+ let off = (size - step) / stride + 1;
+ for i in 0..4 {
+ let coeffs = &src[256 + i * 32..];
+ let dst = &mut tmp[256..];
+ synth_step0_84(coeffs, dst, step, off, &SPARAMS84[i]);
+ synth_step1(coeffs, dst, size, stride, step, off, SPARAMS84[i].p0, &AVC_TAB84[i]);
+ }
+ }
+
+ for (i, s) in tmp.chunks(2).take(384/2).enumerate() {
+ dsp.synth_tmp[i] = FFTComplex { re: s[0], im: s[1] };
+ }
+ for i in (384..512).step_by(2) {
+ dsp.synth_tmp[i >> 1] = FFTComplex { re: src[i], im: src[i + 1] };
+ }
+ {
+ let dst = &mut tmp[384..512];
+ dst.copy_from_slice(&src[384..512]);
+ }
+ for (i, chunk) in dsp.synth_tmp.chunks_exact_mut(128).enumerate() {
+ zero_some(chunk, SPARAMS84[i].p0, SPARAMS84[i].p1);
+ }
+ for chunk in dsp.synth_tmp.chunks_exact_mut(64) {
+ dsp.irdft64.do_rdft_inplace(chunk);
+ }
+ merge_bands(&dsp.synth_tmp, &mut dsp.synth_out, 256);
+ dsp.rdft256.do_rdft_inplace(&mut dsp.synth_out);
+ for (out, src) in dst.chunks_exact_mut(2).zip(dsp.synth_out.iter()).take(256) {
+ out[0] = src.re * (1.0 / 512.0f32 / 1024.0f32);
+ out[1] = src.im * (1.0 / 512.0f32 / 1024.0f32);
+ }
+ let (size, step, stride) = (512, 84, 4);
+ let off = (size - step) / stride + 1;
+ for i in 0..4 {
+ let src = &tmp[128 * i..];
+ synth_step0_84(src, dst, step, off, &SPARAMS84[i]);
+ }
+}
+
+fn decode_band_types(br: &mut BitReader, cbs: &mut [u8; MAX_BANDS], winfo: &WinInfo) -> DecoderResult<()> {
+ let bits_per_sect = if winfo.is_long { 5 } else { 3 };
+ let esc_val = (1 << bits_per_sect) - 1;
+ let tot_bands = winfo.get_tot_bands();
+
+ let mut cur_band = 0;
+ while cur_band < tot_bands {
+ let codebook = br.read(4)? as u8;
+ let mut run = 1;
+ loop {
+ let run_add = br.read(bits_per_sect)? as usize;
+ run += run_add;
+ if run_add != esc_val { break; }
+ }
+ validate!(cur_band + run <= tot_bands);
+ for _ in 0..run {
+ cbs[cur_band] = codebook;
+ cur_band += 1;
+ }
+ }
+ Ok(())
+}
+
+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
+ }
+}
+
+fn decode_quads(br: &mut BitReader, cb: &Codebook<u16>, qtab: &[f32; QTAB_SIZE], scale: f32, dst: &mut [f32]) -> DecoderResult<()> {
+ for quad in dst.chunks_exact_mut(4) {
+ let mut idx = br.read_cb(cb)? as i16;
+ for el in quad.iter_mut() {
+ *el = dequant(idx >> 12, qtab, scale);
+ idx <<= 4;
+ }
+ }
+ Ok(())
+}
+
+fn decode_esc_val(br: &mut BitReader, qtab: &[f32; QTAB_SIZE], scale: f32, sign: bool) -> DecoderResult<f32> {
+ let pfx = br.read_code(UintCodeType::LimitedOnes(24))? + 4;
+ let add = br.read(pfx as u8)? as usize;
+ let val = (1 << pfx) + add;
+ let fval = scale * if val < qtab.len() {
+ qtab[val]
+ } else {
+ (val as f32) * (val as f32).sqrt()
+ };
+ if !sign {
+ Ok(fval)
+ } else {
+ Ok(-fval)
+ }
+}
+
+fn decode_pairs(br: &mut BitReader, cb: &Codebook<u16>, qtab: &[f32; QTAB_SIZE], scale: f32, dst: &mut [f32], is_esc: bool) -> DecoderResult<()> {
+ for pair in dst.chunks_exact_mut(2) {
+ let idx = br.read_cb(cb)? as i16;
+ let idx0 = idx >> 8;
+ let idx1 = (idx << 8) >> 8;
+ if !is_esc || (idx0.abs() < 16) {
+ pair[0] = dequant(idx0, qtab, scale);
+ } else {
+ pair[0] = decode_esc_val(br, qtab, scale, idx0 < 0)?;
+ }
+ if !is_esc || (idx1.abs() < 16) {
+ pair[1] = dequant(idx1, qtab, scale);
+ } else {
+ pair[1] = decode_esc_val(br, qtab, scale, idx1 < 0)?;
+ }
+ }
+ Ok(())
+}
+
+impl NADecoder for AVCDecoder {
+ fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
+ if let NACodecTypeInfo::Audio(ainfo) = info.get_properties() {
+ self.chmap = match ainfo.get_channels() {
+ 1 => { NAChannelMap::from_str("C").unwrap() },
+ 2 => { NAChannelMap::from_str("L,R").unwrap() },
+ _ => { return Err(DecoderError::InvalidData); },
+ };
+ let srate = ainfo.get_sample_rate();
+ self.ainfo = NAAudioInfo::new(srate, ainfo.get_channels(),
+ SND_F32P_FORMAT, COEFFS);
+ self.info = info.replace_info(NACodecTypeInfo::Audio(self.ainfo));
+ self.channels = ainfo.get_channels() as usize;
+ self.is_40khz = srate <= 40000;
+
+ self.win_long = if (srate > 24000) && ((srate > 32000) || (self.channels == 2)) {
+ AVC_WIN_LONG_32K
+ } else {
+ AVC_WIN_LONG_24K
+ };
+
+ Ok(())
+ } else {
+ Err(DecoderError::InvalidData)
+ }
+ }
+ fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
+ let info = pkt.get_stream().get_info();
+ validate!(info.get_properties().is_audio());
+ let src = pkt.get_buffer();
+
+ let abuf;
+
+ 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);
+ self.decode_frame(&mut br, &mut adata, 0)?;
+ } else {
+ let mut offsets: Vec<usize> = Vec::new();
+ let mut sizes: Vec<usize> = Vec::new();
+
+ let mut cur_off = 0;
+ while cur_off + 2 < src.len() {
+ let sz = read_u16le(&src[cur_off..])? as usize;
+ validate!(sz > 0);
+ validate!(cur_off + sz + 2 <= src.len());
+ offsets.push(cur_off + 2);
+ sizes.push(sz);
+ cur_off += sz + 2;
+ }
+
+ validate!(!sizes.is_empty());
+
+ abuf = alloc_audio_buffer(self.ainfo, COEFFS * sizes.len(), self.chmap.clone())?;
+ 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);
+ self.decode_frame(&mut br, &mut adata, aoffset)?;
+ aoffset += COEFFS;
+ }
+ }
+
+ let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), abuf);
+ frm.set_keyframe(true);
+ Ok(frm.into_ref())
+ }
+}
+
+pub fn get_decoder_500() -> Box<dyn NADecoder> {
+ Box::new(AVCDecoder::new(500))
+}
+
+pub fn get_decoder_501() -> Box<dyn NADecoder> {
+ Box::new(AVCDecoder::new(501))
+}
+
+#[cfg(test)]
+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;
+ #[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);
+
+ //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);
+panic!("end");
+ }
+}
+
+const AVC_WINFO_LONG: WinInfo = WinInfo {
+ is_long: true,
+ bands: &[
+ 4, 8, 12, 16, 20, 24, 28, 32,
+ 36, 40, 48, 56, 64, 72, 80, 88,
+ 96, 108, 120, 132, 144, 156, 172, 188,
+ 204, 224, 244, 264, 288, 312, 340, 368,
+ 400, 432, 464, 496, 528, 560, 592, 624,
+ 656, 688, 720, 752, 784, 816, 848, 880, 1024
+ ],
+};
+
+const AVC_WINFO_SHORT: WinInfo = WinInfo {
+ is_long: false,
+ bands: &[ 4, 8, 12, 16, 20, 24, 32, 40, 48, 56, 68, 80, 108, 128 ],
+};
+
+const AVC_WINFO_40K_MODE4: WinInfo = WinInfo {
+ is_long: true,
+ bands: &[
+ 8, 16, 24, 32, 40, 48, 56, 64,
+ 72, 80, 88, 96, 104, 112, 120, 128,
+ 144, 160, 176, 192, 208, 224, 240, 256,
+ 264, 272, 280, 288, 296, 304, 312, 320,
+ 328, 336, 344, 352, 360, 368, 376, 384,
+ 400, 416, 432, 448, 464, 480, 496, 512,
+ 520, 528, 536, 544, 552, 560, 568, 576,
+ 584, 592, 600, 608, 616, 624, 632, 640,
+ 648, 656, 664, 672, 680, 688, 696, 704,
+ 712, 720, 728, 736, 744, 752, 760, 768,
+ 800, 832, 864, 896, 928, 960, 992, 1024
+ ],
+};
+const AVC_WINFO_40K_MODE5: WinInfo = WinInfo {
+ is_long: true,
+ bands: &[
+ 8, 16, 24, 32, 40, 48, 56, 64,
+ 80, 96, 112, 128, 136, 144, 152, 160,
+ 168, 176, 184, 192, 208, 224, 240, 256,
+ 264, 272, 280, 288, 296, 304, 312, 320,
+ 328, 336, 344, 352, 360, 368, 376, 384,
+ 416, 448, 480, 512, 516, 520, 524, 528,
+ 532, 536, 540, 548, 556, 568, 580, 592,
+ 608, 624, 640, 656, 672, 688, 704, 720,
+ 736, 752, 768, 784, 800, 816, 832, 848,
+ 864, 880, 896, 912, 928, 944, 1024
+ ],
+};
+const AVC_WINFO_40K_MODE6: WinInfo = WinInfo {
+ is_long: true,
+ bands: &[
+ 4, 8, 12, 16, 20, 24, 28, 36,
+ 44, 56, 68, 80, 96, 112, 128, 144,
+ 160, 176, 192, 208, 224, 240, 256, 272,
+ 288, 304, 320, 336, 352, 368, 384, 400,
+ 416, 432, 512, 520, 528, 536, 544, 552,
+ 560, 568, 576, 592, 608, 624, 640, 648,
+ 656, 664, 672, 680, 688, 696, 704, 720,
+ 736, 752, 768, 776, 784, 792, 800, 808,
+ 816, 824, 832, 840, 848, 856, 864, 872,
+ 880, 888, 896, 928, 960, 992, 1024
+ ],
+};
+
+const AVC_WINFO_44K_MODE4: WinInfo = WinInfo {
+ is_long: true,
+ bands: &[
+ 8, 16, 24, 32, 40, 48, 56, 64,
+ 72, 80, 88, 96, 104, 112, 120, 128,
+ 136, 144, 152, 160, 168, 176, 184, 192,
+ 200, 208, 216, 224, 232, 240, 248, 256,
+ 264, 272, 280, 288, 296, 304, 312, 320,
+ 328, 336, 344, 352, 360, 368, 376, 384,
+ 392, 400, 408, 416, 424, 432, 440, 448,
+ 456, 464, 472, 480, 488, 496, 504, 512,
+ 528, 544, 560, 576, 592, 608, 624, 640,
+ 672, 704, 736, 768, 832, 896, 960, 1024
+ ],
+};
+const AVC_WINFO_44K_MODE5: WinInfo = WinInfo {
+ is_long: true,
+ bands: &[
+ 8, 16, 24, 32, 40, 48, 56, 64,
+ 72, 80, 88, 96, 104, 112, 120, 128,
+ 136, 144, 152, 160, 168, 176, 184, 192,
+ 200, 208, 216, 224, 232, 240, 248, 256,
+ 272, 288, 304, 320, 352, 384, 448, 512,
+ 516, 520, 524, 528, 532, 536, 540, 548,
+ 556, 568, 580, 592, 608, 624, 640, 656,
+ 672, 688, 704, 720, 736, 752, 768, 784,
+ 800, 816, 832, 848, 864, 880, 896, 912,
+ 928, 944, 1024
+ ],
+};
+const AVC_WINFO_44K_MODE6: WinInfo = WinInfo {
+ is_long: true,
+ bands: &[
+ 4, 8, 12, 16, 20, 24, 28, 36,
+ 44, 56, 68, 80, 96, 112, 128, 144,
+ 160, 176, 192, 208, 224, 240, 256, 272,
+ 288, 304, 320, 336, 352, 368, 384, 400,
+ 416, 432, 512, 520, 528, 536, 544, 552,
+ 560, 568, 576, 584, 592, 600, 608, 616,
+ 624, 632, 640, 648, 656, 664, 672, 680,
+ 688, 696, 704, 712, 720, 728, 736, 744,
+ 752, 760, 768, 784, 800, 816, 832, 864,
+ 896, 960, 1024
+ ],
+};