aac: issue a warning instead of an error on window sequence mismatch
[nihav.git] / nihav-commonfmt / src / codecs / aac.rs
index f24ba20e39a7c328bb03b7c3c27c3fcb39ef5368..09a5b6b1dd582e90600e1b6ae16715ccfbf7f9f3 100644 (file)
@@ -1,9 +1,10 @@
 use nihav_core::formats::*;
 use nihav_core::frame::*;
 use nihav_core::codecs::*;
-use nihav_core::dsp::mdct::IMDCT;
-use nihav_core::dsp::window::*;
+use nihav_codec_support::dsp::mdct::IMDCT;
+use nihav_codec_support::dsp::window::*;
 use nihav_core::io::bitreader::*;
+use nihav_core::io::byteio::*;
 use nihav_core::io::codebook::*;
 use std::fmt;
 use nihav_core::io::intcode::*;
@@ -147,7 +148,7 @@ impl M4AInfo {
         }
     }
     fn read(&mut self, src: &[u8]) -> DecoderResult<()> {
-        let mut br = BitReader::new(src, src.len(), BitReaderMode::BE);
+        let mut br = BitReader::new(src, BitReaderMode::BE);
         self.otype = Self::read_object_type(&mut br)?;
         self.srate = Self::read_sampling_frequency(&mut br)?;
         validate!(self.srate > 0);
@@ -324,12 +325,16 @@ impl ICSInfo {
         self.window_sequence                            = br.read(2)? as u8;
         match self.prev_window_sequence {
             ONLY_LONG_SEQUENCE | LONG_STOP_SEQUENCE => {
-                    validate!((self.window_sequence == ONLY_LONG_SEQUENCE) ||
-                              (self.window_sequence == LONG_START_SEQUENCE));
+                    if (self.window_sequence != ONLY_LONG_SEQUENCE) &&
+                       (self.window_sequence != LONG_START_SEQUENCE) {
+                        println!("incorrect previous window");
+                    }
                 },
             LONG_START_SEQUENCE | EIGHT_SHORT_SEQUENCE => {
-                    validate!((self.window_sequence == EIGHT_SHORT_SEQUENCE) ||
-                              (self.window_sequence == LONG_STOP_SEQUENCE));
+                    if (self.window_sequence != EIGHT_SHORT_SEQUENCE) &&
+                       (self.window_sequence != LONG_STOP_SEQUENCE) {
+                        println!("incorrect previous window");
+                    }
                 },
             _ => {},
         };
@@ -782,17 +787,23 @@ impl ICS {
                     let start = w * 128 + self.get_band_start(tns_max_bands.min(bottom));
                     let end   = w * 128 + self.get_band_start(tns_max_bands.min(top));
                     let lpc = &tns_data.coeffs[w][f].coef;
+                    let mut state = [0.0f32; 64];
+                    let mut sidx = 32;
                     if !tns_data.coeffs[w][f].direction {
                         for m in start..end {
-                            for i in 0..order.min(m) {
-                                self.coeffs[m] -= self.coeffs[m - i - 1] * lpc[i];
+                            for i in 0..order {
+                                self.coeffs[m] -= state[(sidx + i) & 63] * lpc[i];
                             }
+                            sidx = (sidx + 63) & 63;
+                            state[sidx] = self.coeffs[m];
                         }
                     } else {
                         for m in (start..end).rev() {
-                            for i in 0..order.min(m) {
-                                self.coeffs[m] -= self.coeffs[m + i - 1] * lpc[i];
+                            for i in 0..order {
+                                self.coeffs[m] -= state[(sidx + i) & 63] * lpc[i];
                             }
+                            sidx = (sidx + 63) & 63;
+                            state[sidx] = self.coeffs[m];
                         }
                     }
                 }
@@ -876,6 +887,7 @@ fn read_escape(br: &mut BitReader, sign: bool) -> DecoderResult<i16> {
     let prefix                                          = br.read_code(UintCodeType::UnaryOnes)? as u8;
     validate!(prefix < 9);
     let bits                                            = br.read(prefix + 4)? as i16;
+    let bits = bits | (1 << (prefix + 4));
     if sign {
         Ok(bits)
     } else {
@@ -924,11 +936,11 @@ impl ChannelPair {
             self.ics[1].info = self.ics[0].info;
         }
         self.ics[0].decode_ics(br, codebooks, m4atype, common_window, true)?;
-        self.ics[1].decode_ics(br, codebooks, m4atype, common_window, false)?;
+        self.ics[1].decode_ics(br, codebooks, m4atype, common_window, true)?;
         if common_window && self.ms_mask_present != 0 {
             let mut g = 0;
             for w in 0..self.ics[0].info.num_windows {
-                if w > 0 && self.ics[0].info.scale_factor_grouping[w - 1] {
+                if w > 0 && !self.ics[0].info.scale_factor_grouping[w - 1] {
                     g += 1;
                 }
                 for sfb in 0..self.ics[0].info.max_sfb {
@@ -1003,6 +1015,7 @@ impl DSP {
             tmp: [0.0; 2048], ew_buf: [0.0; 1152],
         }
     }
+    #[allow(clippy::cyclomatic_complexity)]
     fn synth(&mut self, coeffs: &[f32; 1024], delay: &mut [f32; 1024], seq: u8, window_shape: bool, prev_window_shape: bool, dst: &mut [f32]) {
         let long_win  = if window_shape { &self.kbd_long_win  } else { &self.sine_long_win };
         let short_win = if window_shape { &self.kbd_short_win } else { &self.sine_short_win };
@@ -1206,7 +1219,60 @@ impl NADecoder for AACDecoder {
             validate!(edata.len() >= 2);
 
 //print!("edata:"); for s in edata.iter() { print!(" {:02X}", *s);}println!("");
-            self.m4ainfo.read(&edata)?;
+            if (edata.len() > 12) && (&edata[4..8] == b"esds") {
+                let mut mr = MemoryReader::new_read(edata.as_slice());
+                let mut br = ByteReader::new(&mut mr);
+                let esds_size           = br.read_u32be()? as usize;
+                validate!(esds_size <= edata.len());
+                                          br.read_skip(8)?;
+                let mut info_start = 0;
+                let mut info_size = 0;
+                while br.tell() < (esds_size as u64) {
+                    let tag             = br.read_byte()?;
+                    let mut size = 0;
+                    loop {
+                        let b           = br.read_byte()?;
+                        size = (size << 7) | u64::from(b & 0x7F);
+                        validate!(br.tell() + size <= (esds_size as u64));
+                        if (b & 0x80) == 0 {
+                            break;
+                        }
+                    }
+                    match tag {
+                        3 => {
+                                          br.read_u16be()?;
+                            let flags   = br.read_byte()?;
+                            if (flags & 0x80) != 0 {
+                                          br.read_u16be()?;
+                            }
+                            if (flags & 0x40) != 0 {
+                                let len = br.read_byte()?;
+                                          br.read_skip(len as usize)?;
+                            }
+                            if (flags & 0x20) != 0 {
+                                          br.read_u16be()?;
+                            }
+                        },
+                        4 => {
+                            let _otype  = br.read_byte()?;
+                            let _stype  = br.read_byte()?;
+                            let _flags  = br.read_u24be()?;
+                            let _max_br = br.read_u32be()?;
+                            let _min_br = br.read_u32be()?;
+                        },
+                        5 => {
+                            info_start = br.tell() as usize;
+                            info_size = size as usize;
+                            break;
+                        },
+                        _ => br.read_skip(size as usize)?,
+                    }
+                }
+                validate!(info_start > 0 && info_size > 0);
+                self.m4ainfo.read(&edata[info_start..][..info_size])?;
+            } else {
+                self.m4ainfo.read(&edata)?;
+            }
 
             //println!("{}", self.m4ainfo);
             if (self.m4ainfo.otype != M4AType::LC) || (self.m4ainfo.channels > 2) || (self.m4ainfo.samples != 1024) {
@@ -1238,7 +1304,7 @@ impl NADecoder for AACDecoder {
         let ainfo = self.info.get_properties().get_audio_info().unwrap();
         let mut abuf = alloc_audio_buffer(ainfo, self.m4ainfo.samples, self.chmap.clone())?;
 
-        let mut br = BitReader::new(&pktbuf, pktbuf.len(), BitReaderMode::BE);
+        let mut br = BitReader::new(&pktbuf, BitReaderMode::BE);
         match self.m4ainfo.otype {
             M4AType::LC => {
                     self.decode_ga(&mut br, &mut abuf)?;
@@ -1258,7 +1324,13 @@ impl NADecoder for AACDecoder {
     }
 }
 
-pub fn get_decoder() -> Box<dyn NADecoder> {
+impl NAOptionHandler for AACDecoder {
+    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() -> Box<dyn NADecoder + Send> {
     Box::new(AACDecoder::new())
 }
 
@@ -1266,15 +1338,15 @@ pub fn get_decoder() -> Box<dyn NADecoder> {
 mod test {
     use nihav_core::codecs::RegisteredDecoders;
     use nihav_core::demuxers::RegisteredDemuxers;
-    use nihav_core::test::dec_video::test_decode_audio;
-    use crate::codecs::generic_register_all_codecs;
-    use nihav_realmedia::demuxers::realmedia_register_all_demuxers;
+    use nihav_codec_support::test::dec_video::test_decode_audio;
+    use crate::generic_register_all_decoders;
+    use nihav_realmedia::realmedia_register_all_demuxers;
     #[test]
     fn test_aac() {
         let mut dmx_reg = RegisteredDemuxers::new();
         realmedia_register_all_demuxers(&mut dmx_reg);
         let mut dec_reg = RegisteredDecoders::new();
-        generic_register_all_codecs(&mut dec_reg);
+        generic_register_all_decoders(&mut dec_reg);
 
 //        let file = "assets/RV/rv40_weighted_mc.rmvb";
         let file = "assets/RV/rv40_weighted_mc_2.rmvb";