--- /dev/null
+use nihav_core::codecs::{DecoderResult, DecoderError};
+use nihav_core::io::bitreader::*;
+use std::fmt;
+
+#[allow(non_camel_case_types)]
+#[derive(Clone,Copy,PartialEq)]
+pub enum M4AType {
+ None,
+ Main,
+ LC,
+ SSR,
+ LTP,
+ SBR,
+ Scalable,
+ TwinVQ,
+ CELP,
+ HVXC,
+ TTSI,
+ MainSynth,
+ WavetableSynth,
+ GeneralMIDI,
+ Algorithmic,
+ ER_AAC_LC,
+ ER_AAC_LTP,
+ ER_AAC_Scalable,
+ ER_TwinVQ,
+ ER_BSAC,
+ ER_AAC_LD,
+ ER_CELP,
+ ER_HVXC,
+ ER_HILN,
+ ER_Parametric,
+ SSC,
+ PS,
+ MPEGSurround,
+ Layer1,
+ Layer2,
+ Layer3,
+ DST,
+ ALS,
+ SLS,
+ SLSNonCore,
+ ER_AAC_ELD,
+ SMRSimple,
+ SMRMain,
+ Reserved,
+ Unknown,
+}
+
+const M4A_TYPES: &[M4AType] = &[
+ M4AType::None, M4AType::Main, M4AType::LC, M4AType::SSR,
+ M4AType::LTP, M4AType::SBR, M4AType::Scalable, M4AType::TwinVQ,
+ M4AType::CELP, M4AType::HVXC, M4AType::Reserved, M4AType::Reserved,
+ M4AType::TTSI, M4AType::MainSynth, M4AType::WavetableSynth, M4AType::GeneralMIDI,
+ M4AType::Algorithmic, M4AType::ER_AAC_LC, M4AType::Reserved, M4AType::ER_AAC_LTP,
+ M4AType::ER_AAC_Scalable, M4AType::ER_TwinVQ, M4AType::ER_BSAC, M4AType::ER_AAC_LD,
+ M4AType::ER_CELP, M4AType::ER_HVXC, M4AType::ER_HILN, M4AType::ER_Parametric,
+ M4AType::SSC, M4AType::PS, M4AType::MPEGSurround, M4AType::Reserved /*escape*/,
+ M4AType::Layer1, M4AType::Layer2, M4AType::Layer3, M4AType::DST,
+ M4AType::ALS, M4AType::SLS, M4AType::SLSNonCore, M4AType::ER_AAC_ELD,
+ M4AType::SMRSimple, M4AType::SMRMain,
+];
+const M4A_TYPE_NAMES: &[&str] = &[
+ "None", "AAC Main", "AAC LC", "AAC SSR", "AAC LTP", "SBR", "AAC Scalable", "TwinVQ", "CELP", "HVXC",
+ /*"(reserved10)", "(reserved11)", */ "TTSI",
+ "Main synthetic", "Wavetable synthesis", "General MIDI", "Algorithmic Synthesis and Audio FX",
+ "ER AAC LC", /*"(reserved18)",*/ "ER AAC LTP", "ER AAC Scalable", "ER TwinVQ", "ER BSAC", "ER AAC LD",
+ "ER CELP", "ER HVXC", "ER HILN", "ER Parametric", "SSC", "PS", "MPEG Surround", /*"(escape)",*/
+ "Layer-1", "Layer-2", "Layer-3", "DST", "ALS", "SLS", "SLS non-core", "ER AAC ELD", "SMR Simple", "SMR Main",
+ "(reserved)", "(unknown)",
+];
+
+impl fmt::Display for M4AType {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{}", M4A_TYPE_NAMES[*self as usize])
+ }
+}
+
+const AAC_SAMPLE_RATES: [u32; 16] = [
+ 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
+ 16000, 12000, 11025, 8000, 7350, 0, 0, 0
+];
+
+const AAC_CHANNELS: [usize; 8] = [ 0, 1, 2, 3, 4, 5, 6, 8 ];
+
+pub struct M4AInfo {
+ pub otype: M4AType,
+ pub srate: u32,
+ pub channels: usize,
+ pub samples: usize,
+ pub sbr_ps_info: Option<(u32, usize)>,
+ pub sbr_present: bool,
+ pub ps_present: bool,
+}
+
+impl M4AInfo {
+ pub fn new() -> Self {
+ Self {
+ otype: M4AType::None,
+ srate: 0,
+ channels: 0,
+ samples: 0,
+ sbr_ps_info: Option::None,
+ sbr_present: false,
+ ps_present: false,
+ }
+ }
+ fn read_object_type(br: &mut BitReader) -> DecoderResult<M4AType> {
+ let otypeidx;
+ if br.peek(5) == 31 {
+ br.skip(5)?;
+ otypeidx = (br.read(6)? as usize) + 32;
+ } else {
+ otypeidx = br.read(5)? as usize;
+ }
+ if otypeidx >= M4A_TYPES.len() {
+ Ok(M4AType::Unknown)
+ } else {
+ Ok(M4A_TYPES[otypeidx])
+ }
+ }
+ fn read_sampling_frequency(br: &mut BitReader) -> DecoderResult<u32> {
+ if br.peek(4) == 15 {
+ let srate = br.read(24)?;
+ Ok(srate)
+ } else {
+ let srate_idx = br.read(4)? as usize;
+ Ok(AAC_SAMPLE_RATES[srate_idx])
+ }
+ }
+ fn read_channel_config(br: &mut BitReader) -> DecoderResult<usize> {
+ let chidx = br.read(4)? as usize;
+ if chidx < AAC_CHANNELS.len() {
+ Ok(AAC_CHANNELS[chidx])
+ } else {
+ Ok(chidx)
+ }
+ }
+ pub fn read(&mut self, src: &[u8]) -> DecoderResult<()> {
+ 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);
+ self.channels = Self::read_channel_config(&mut br)?;
+
+ if (self.otype == M4AType::SBR) || (self.otype == M4AType::PS) {
+ let ext_srate = Self::read_sampling_frequency(&mut br)?;
+ self.otype = Self::read_object_type(&mut br)?;
+ let ext_chans;
+ if self.otype == M4AType::ER_BSAC {
+ ext_chans = Self::read_channel_config(&mut br)?;
+ } else {
+ ext_chans = 0;
+ }
+ self.sbr_ps_info = Some((ext_srate, ext_chans));
+ }
+
+ match self.otype {
+ M4AType::Main | M4AType::LC | M4AType::SSR | M4AType::Scalable | M4AType::TwinVQ |
+ M4AType::ER_AAC_LC | M4AType::ER_AAC_LTP | M4AType::ER_AAC_Scalable | M4AType::ER_TwinVQ |
+ M4AType::ER_BSAC | M4AType::ER_AAC_LD => {
+ // GASpecificConfig
+ let short_frame = br.read_bool()?;
+ self.samples = if short_frame { 960 } else { 1024 };
+ let depends_on_core = br.read_bool()?;
+ if depends_on_core {
+ let _delay = br.read(14)?;
+ }
+ let extension_flag = br.read_bool()?;
+ if self.channels == 0 {
+ unimplemented!("program config element");
+ }
+ if (self.otype == M4AType::Scalable) || (self.otype == M4AType::ER_AAC_Scalable) {
+ let _layer = br.read(3)?;
+ }
+ if extension_flag {
+ if self.otype == M4AType::ER_BSAC {
+ let _num_subframes = br.read(5)? as usize;
+ let _layer_length = br.read(11)?;
+ }
+ if (self.otype == M4AType::ER_AAC_LC) ||
+ (self.otype == M4AType::ER_AAC_LTP) ||
+ (self.otype == M4AType::ER_AAC_Scalable) ||
+ (self.otype == M4AType::ER_AAC_LD) {
+ let _section_data_resilience = br.read_bool()?;
+ let _scalefactors_resilience = br.read_bool()?;
+ let _spectral_data_resilience = br.read_bool()?;
+ }
+ let extension_flag3 = br.read_bool()?;
+ if extension_flag3 {
+ unimplemented!("version3 extensions");
+ }
+ }
+ },
+ M4AType::CELP => { unimplemented!("CELP config"); },
+ M4AType::HVXC => { unimplemented!("HVXC config"); },
+ M4AType::TTSI => { unimplemented!("TTS config"); },
+ M4AType::MainSynth | M4AType::WavetableSynth | M4AType::GeneralMIDI | M4AType::Algorithmic => { unimplemented!("structured audio config"); },
+ M4AType::ER_CELP => { unimplemented!("ER CELP config"); },
+ M4AType::ER_HVXC => { unimplemented!("ER HVXC config"); },
+ M4AType::ER_HILN | M4AType::ER_Parametric => { unimplemented!("parametric config"); },
+ M4AType::SSC => { unimplemented!("SSC config"); },
+ M4AType::MPEGSurround => {
+ br.skip(1)?; // sacPayloadEmbedding
+ unimplemented!("MPEG Surround config");
+ },
+ M4AType::Layer1 | M4AType::Layer2 | M4AType::Layer3 => { unimplemented!("MPEG Layer 1/2/3 config"); },
+ M4AType::DST => { unimplemented!("DST config"); },
+ M4AType::ALS => {
+ br.skip(5)?; // fillBits
+ unimplemented!("ALS config");
+ },
+ M4AType::SLS | M4AType::SLSNonCore => { unimplemented!("SLS config"); },
+ M4AType::ER_AAC_ELD => { unimplemented!("ELD config"); },
+ M4AType::SMRSimple | M4AType::SMRMain => { unimplemented!("symbolic music config"); },
+ _ => {},
+ };
+ match self.otype {
+ M4AType::ER_AAC_LC | M4AType::ER_AAC_LTP | M4AType::ER_AAC_Scalable | M4AType::ER_TwinVQ |
+ M4AType::ER_BSAC | M4AType::ER_AAC_LD | M4AType::ER_CELP | M4AType::ER_HVXC |
+ M4AType::ER_HILN | M4AType::ER_Parametric | M4AType::ER_AAC_ELD => {
+ let ep_config = br.read(2)?;
+ if (ep_config == 2) || (ep_config == 3) {
+ unimplemented!("error protection config");
+ }
+ if ep_config == 3 {
+ let direct_mapping = br.read_bool()?;
+ validate!(direct_mapping);
+ }
+ },
+ _ => {},
+ };
+ if self.sbr_ps_info.is_some() && (br.left() >= 16) {
+ let sync = br.read(11)?;
+ if sync == 0x2B7 {
+ let ext_otype = Self::read_object_type(&mut br)?;
+ if ext_otype == M4AType::SBR {
+ self.sbr_present = br.read_bool()?;
+ if self.sbr_present {
+ let _ext_srate = Self::read_sampling_frequency(&mut br)?;
+ if br.left() >= 12 {
+ let sync = br.read(11)?;
+ if sync == 0x548 {
+ self.ps_present = br.read_bool()?;
+ }
+ }
+ }
+ }
+ if ext_otype == M4AType::PS {
+ self.sbr_present = br.read_bool()?;
+ if self.sbr_present {
+ let _ext_srate = Self::read_sampling_frequency(&mut br)?;
+ }
+ let _ext_channels = br.read(4)?;
+ }
+ }
+ }
+
+ Ok(())
+ }
+}
+
+impl fmt::Display for M4AInfo {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "MPEG 4 Audio {}, {} Hz, {} channels, {} samples per frame",
+ self.otype, self.srate, self.channels, self.samples)
+ }
+}
+