use oxideav_core::bits::BitReader;
use crate::adts::ADTS_SAMPLE_RATES_HZ;
use crate::pce::Pce;
use crate::{Error, Result};
const GA_AOTS: &[u8] = &[1, 2, 3, 4, 6, 7, 17, 19, 20, 21, 22, 23];
const SBR_AOT: u8 = 5;
const PS_AOT: u8 = 29;
const GA_EXTENSION_NUM_OF_SUBFRAME_AOTS: &[u8] = &[22];
const GA_EXTENSION_RESILIENCE_AOTS: &[u8] = &[17, 19, 20, 23];
const EP_CONFIG_AOTS: &[u8] = &[17, 19, 20, 21, 22, 23, 24, 25, 26, 27, 39];
pub const SYNC_EXTENSION_TYPE_SBR: u16 = 0x2b7;
pub const SYNC_EXTENSION_TYPE_PS: u16 = 0x548;
pub const SYNC_EXTENSION_TYPE_BITS: u32 = 11;
pub const TRAILING_EXTENSION_AOT_SBR: u8 = 5;
pub const TRAILING_EXTENSION_AOT_BSAC: u8 = 22;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum FrameLength {
Long1024,
Long960,
}
impl FrameLength {
pub fn samples(self) -> u32 {
match self {
FrameLength::Long1024 => 1024,
FrameLength::Long960 => 960,
}
}
pub fn family(self, aot: u8) -> crate::swb_offset::FrameFamily {
crate::swb_offset::FrameFamily::from_aot_and_flag(aot, self == FrameLength::Long960)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct GaSpecificConfig {
pub frame_length: FrameLength,
pub depends_on_core_coder: bool,
pub core_coder_delay: Option<u16>,
pub extension_flag: bool,
pub pce: Option<Pce>,
pub layer_nr: Option<u8>,
pub extension_body: Option<GaExtensionBody>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct GaExtensionBody {
pub bsac_layer: Option<BsacLayerSpec>,
pub resilience: Option<AacResilienceFlags>,
pub extension_flag3: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct BsacLayerSpec {
pub num_of_sub_frame: u8,
pub layer_length: u16,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub struct AacResilienceFlags {
pub section_data: bool,
pub scalefactor_data: bool,
pub spectral_data: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct SbrExtensionProbe {
pub extension_audio_object_type: u8,
pub sbr_present_flag: bool,
pub extension_sampling_frequency_index: Option<u8>,
pub extension_sample_rate: Option<u32>,
pub ps_present_flag: Option<bool>,
pub extension_channel_configuration: Option<u8>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct AudioSpecificConfig {
pub outer_aot: u8,
pub aot: u8,
pub sampling_frequency_index: u8,
pub sample_rate: u32,
pub channel_configuration: u8,
pub sbr_present: bool,
pub ps_present: bool,
pub extension_sampling_frequency_index: Option<u8>,
pub extension_sample_rate: Option<u32>,
pub extension_channel_configuration: Option<u8>,
pub ga_body: GaSpecificConfig,
pub ep_config: Option<u8>,
pub error_protection: Option<crate::ep_config::ErrorProtectionSpecificConfig>,
pub direct_mapping: Option<bool>,
pub trailing_sbr_probe: Option<SbrExtensionProbe>,
}
impl AudioSpecificConfig {
pub fn parse(data: &[u8]) -> Result<(Self, u64)> {
let mut reader = BitReader::new(data);
let asc_bit_length = (data.len() as u64).saturating_mul(8);
let asc = Self::parse_bits_bounded(&mut reader, 0, asc_bit_length)?;
Ok((asc, reader.bit_position()))
}
pub fn parse_bits_bounded(
reader: &mut BitReader<'_>,
origin_bit_offset: u64,
asc_bit_length: u64,
) -> Result<Self> {
let start_bit = reader.bit_position();
let mut asc = Self::parse_bits_core(reader, origin_bit_offset)?;
let consumed = reader.bit_position().saturating_sub(start_bit);
let already_hierarchical_sbr = asc.outer_aot == SBR_AOT || asc.outer_aot == PS_AOT;
if !already_hierarchical_sbr && consumed < asc_bit_length {
let remaining = asc_bit_length - consumed;
if let Some(probe) = parse_trailing_sbr_probe(reader, remaining)? {
if probe.extension_audio_object_type == TRAILING_EXTENSION_AOT_SBR {
if probe.sbr_present_flag {
asc.sbr_present = true;
asc.extension_sampling_frequency_index =
probe.extension_sampling_frequency_index;
asc.extension_sample_rate = probe.extension_sample_rate;
}
if probe.ps_present_flag == Some(true) {
asc.ps_present = true;
}
} else if probe.extension_audio_object_type == TRAILING_EXTENSION_AOT_BSAC {
if probe.sbr_present_flag {
asc.sbr_present = true;
asc.extension_sampling_frequency_index =
probe.extension_sampling_frequency_index;
asc.extension_sample_rate = probe.extension_sample_rate;
}
asc.extension_channel_configuration = probe.extension_channel_configuration;
}
asc.trailing_sbr_probe = Some(probe);
}
}
Ok(asc)
}
pub fn parse_bits(reader: &mut BitReader<'_>, origin_bit_offset: u64) -> Result<Self> {
Self::parse_bits_core(reader, origin_bit_offset)
}
fn parse_bits_core(reader: &mut BitReader<'_>, origin_bit_offset: u64) -> Result<Self> {
let outer_aot = read_aot(reader)?;
let sampling_frequency_index = read_u8(reader, 4)?;
let core_sample_rate = if sampling_frequency_index == 0xf {
read_u32(reader, 24)?
} else {
resolve_sample_rate_index(sampling_frequency_index)?
};
let channel_configuration = read_u8(reader, 4)?;
let mut sbr_present = false;
let mut ps_present = false;
let mut ext_sfi = None;
let mut ext_rate = None;
let mut ext_chan_cfg = None;
let mut effective_aot = outer_aot;
if outer_aot == SBR_AOT || outer_aot == PS_AOT {
sbr_present = true;
if outer_aot == PS_AOT {
ps_present = true;
}
let sfi = read_u8(reader, 4)?;
let rate = if sfi == 0xf {
read_u32(reader, 24)?
} else {
resolve_sample_rate_index(sfi)?
};
ext_sfi = Some(sfi);
ext_rate = Some(rate);
effective_aot = read_aot(reader)?;
if effective_aot == 22 {
ext_chan_cfg = Some(read_u8(reader, 4)?);
}
}
if !GA_AOTS.contains(&effective_aot) {
return Err(Error::UnsupportedAot(effective_aot));
}
let ga_body = parse_ga_specific_config(
reader,
channel_configuration,
effective_aot,
origin_bit_offset,
)?;
let mut error_protection = None;
let mut direct_mapping = None;
let ep_config = if EP_CONFIG_AOTS.contains(&effective_aot) {
let v = read_u8(reader, 2)?;
if v == 2 || v == 3 {
error_protection = Some(crate::ep_config::ErrorProtectionSpecificConfig::parse(
reader,
)?);
}
if v == 3 {
direct_mapping = Some(read_bit(reader)?);
}
Some(v)
} else {
None
};
Ok(AudioSpecificConfig {
outer_aot,
aot: effective_aot,
sampling_frequency_index,
sample_rate: core_sample_rate,
channel_configuration,
sbr_present,
ps_present,
extension_sampling_frequency_index: ext_sfi,
extension_sample_rate: ext_rate,
extension_channel_configuration: ext_chan_cfg,
ga_body,
ep_config,
error_protection,
direct_mapping,
trailing_sbr_probe: None,
})
}
pub fn channel_count(&self) -> usize {
match self.channel_configuration {
0 => self
.ga_body
.pce
.as_ref()
.map(Pce::channel_count)
.unwrap_or(0),
1 => 1,
2 => 2,
3 => 3,
4 => 4,
5 => 5,
6 => 6, 7 => 8, _ => 0,
}
}
}
fn parse_ga_specific_config(
reader: &mut BitReader<'_>,
channel_configuration: u8,
aot: u8,
origin_bit_offset: u64,
) -> Result<GaSpecificConfig> {
let frame_length_flag = read_bit(reader)?;
let frame_length = if frame_length_flag {
FrameLength::Long960
} else {
FrameLength::Long1024
};
let depends_on_core_coder = read_bit(reader)?;
let core_coder_delay = if depends_on_core_coder {
Some(read_u32(reader, 14)? as u16)
} else {
None
};
let extension_flag = read_bit(reader)?;
let pce = if channel_configuration == 0 {
Some(Pce::parse(reader, origin_bit_offset)?)
} else {
None
};
let layer_nr = if aot == 6 || aot == 20 {
Some(read_u8(reader, 3)?)
} else {
None
};
let extension_body = if extension_flag {
Some(parse_ga_extension_body(reader, aot)?)
} else {
None
};
Ok(GaSpecificConfig {
frame_length,
depends_on_core_coder,
core_coder_delay,
extension_flag,
pce,
layer_nr,
extension_body,
})
}
fn parse_ga_extension_body(reader: &mut BitReader<'_>, aot: u8) -> Result<GaExtensionBody> {
let bsac_layer = if GA_EXTENSION_NUM_OF_SUBFRAME_AOTS.contains(&aot) {
let num_of_sub_frame = read_u8(reader, 5)?;
let layer_length = read_u32(reader, 11)? as u16;
Some(BsacLayerSpec {
num_of_sub_frame,
layer_length,
})
} else {
None
};
let resilience = if GA_EXTENSION_RESILIENCE_AOTS.contains(&aot) {
let section_data = read_bit(reader)?;
let scalefactor_data = read_bit(reader)?;
let spectral_data = read_bit(reader)?;
Some(AacResilienceFlags {
section_data,
scalefactor_data,
spectral_data,
})
} else {
None
};
let extension_flag3 = read_bit(reader)?;
if extension_flag3 {
return Err(Error::UnsupportedAscExtensionFlag3);
}
Ok(GaExtensionBody {
bsac_layer,
resilience,
extension_flag3,
})
}
fn parse_trailing_sbr_probe(
reader: &mut BitReader<'_>,
remaining_bits: u64,
) -> Result<Option<SbrExtensionProbe>> {
if remaining_bits < (SYNC_EXTENSION_TYPE_BITS as u64 + 5) {
return Ok(None);
}
let sync = read_u32(reader, SYNC_EXTENSION_TYPE_BITS)? as u16;
if sync != SYNC_EXTENSION_TYPE_SBR {
return Ok(None);
}
let extension_audio_object_type = read_aot(reader)?;
match extension_audio_object_type {
TRAILING_EXTENSION_AOT_SBR => parse_trailing_sbr_branch(reader, remaining_bits),
TRAILING_EXTENSION_AOT_BSAC => parse_trailing_bsac_branch(reader),
other => Err(Error::UnsupportedTrailingExtensionAot(other)),
}
}
fn parse_trailing_sbr_branch(
reader: &mut BitReader<'_>,
initial_remaining_bits: u64,
) -> Result<Option<SbrExtensionProbe>> {
let sbr_present_flag = read_bit(reader)?;
let mut extension_sampling_frequency_index = None;
let mut extension_sample_rate = None;
let mut ps_present_flag = None;
if sbr_present_flag {
let sfi = read_u8(reader, 4)?;
let rate = if sfi == 0xf {
read_u32(reader, 24)?
} else {
resolve_sample_rate_index(sfi)?
};
extension_sampling_frequency_index = Some(sfi);
extension_sample_rate = Some(rate);
let consumed_so_far = SYNC_EXTENSION_TYPE_BITS as u64
+ 5 + 1 + 4 + if sfi == 0xf { 24 } else { 0 };
let still_available = initial_remaining_bits.saturating_sub(consumed_so_far);
if still_available >= 12 {
let inner_sync = read_u32(reader, SYNC_EXTENSION_TYPE_BITS)? as u16;
if inner_sync == SYNC_EXTENSION_TYPE_PS {
ps_present_flag = Some(read_bit(reader)?);
}
}
}
Ok(Some(SbrExtensionProbe {
extension_audio_object_type: TRAILING_EXTENSION_AOT_SBR,
sbr_present_flag,
extension_sampling_frequency_index,
extension_sample_rate,
ps_present_flag,
extension_channel_configuration: None,
}))
}
fn parse_trailing_bsac_branch(reader: &mut BitReader<'_>) -> Result<Option<SbrExtensionProbe>> {
let sbr_present_flag = read_bit(reader)?;
let mut extension_sampling_frequency_index = None;
let mut extension_sample_rate = None;
if sbr_present_flag {
let sfi = read_u8(reader, 4)?;
let rate = if sfi == 0xf {
read_u32(reader, 24)?
} else {
resolve_sample_rate_index(sfi)?
};
extension_sampling_frequency_index = Some(sfi);
extension_sample_rate = Some(rate);
}
let extension_channel_configuration = Some(read_u8(reader, 4)?);
Ok(Some(SbrExtensionProbe {
extension_audio_object_type: TRAILING_EXTENSION_AOT_BSAC,
sbr_present_flag,
extension_sampling_frequency_index,
extension_sample_rate,
ps_present_flag: None,
extension_channel_configuration,
}))
}
fn read_aot(reader: &mut BitReader<'_>) -> Result<u8> {
let base = read_u8(reader, 5)?;
if base == 31 {
let ext = read_u8(reader, 6)?;
let aot = 32u16 + ext as u16;
if aot > u8::MAX as u16 {
return Err(Error::UnsupportedAot(0));
}
Ok(aot as u8)
} else {
Ok(base)
}
}
fn resolve_sample_rate_index(idx: u8) -> Result<u32> {
if (idx as usize) >= ADTS_SAMPLE_RATES_HZ.len() {
return Err(Error::AdtsReservedSampleRateIndex);
}
Ok(ADTS_SAMPLE_RATES_HZ[idx as usize])
}
fn read_u8(reader: &mut BitReader<'_>, n: u32) -> Result<u8> {
debug_assert!(n <= 8);
Ok(reader.read_u32(n).map_err(|_| Error::UnexpectedEnd)? as u8)
}
fn read_u32(reader: &mut BitReader<'_>, n: u32) -> Result<u32> {
reader.read_u32(n).map_err(|_| Error::UnexpectedEnd)
}
fn read_bit(reader: &mut BitReader<'_>) -> Result<bool> {
reader.read_bit().map_err(|_| Error::UnexpectedEnd)
}