X-Git-Url: https://git.nihav.org/?p=nihav.git;a=blobdiff_plain;f=nihav-mpeg%2Fsrc%2Fcodecs%2Faac%2Finfo.rs;fp=nihav-mpeg%2Fsrc%2Fcodecs%2Faac%2Finfo.rs;h=e6e021b3761c793253555ac5dc3da667eda20679;hp=0000000000000000000000000000000000000000;hb=999c25f70cce9929567ece9cb285a900f56727f7;hpb=2826a23f3a214e2f5d47d6dee6fb06754730dc0e diff --git a/nihav-mpeg/src/codecs/aac/info.rs b/nihav-mpeg/src/codecs/aac/info.rs new file mode 100644 index 0000000..e6e021b --- /dev/null +++ b/nihav-mpeg/src/codecs/aac/info.rs @@ -0,0 +1,269 @@ +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 { + 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 { + 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 { + 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) + } +} +