use super::adts::ADTS_SAMPLE_RATES_HZ;
use super::bits::{BitReader, BitWriter};
use super::channel_map::{PceChannelMap, parse_pce_in_asc};
use super::error::{Error, Result};
pub(crate) const AOT_MAIN: u8 = 1;
pub(crate) const AOT_LC: u8 = 2;
pub(crate) const AOT_SSR: u8 = 3;
pub(crate) const AOT_LTP: u8 = 4;
const AOT_SBR: u8 = 5;
const AOT_PS: u8 = 29;
pub(crate) const AOT_LD: u8 = 23;
#[must_use]
pub fn write_lc(fs_index: u8, channel_configuration: u8) -> Vec<u8> {
let mut w = BitWriter::new();
push_lc(&mut w, fs_index, channel_configuration);
w.finish()
}
pub fn push_lc(w: &mut BitWriter, fs_index: u8, channel_configuration: u8) {
w.write(u32::from(AOT_LC), 5);
w.write(u32::from(fs_index), 4);
w.write(u32::from(channel_configuration), 4);
w.write(0, 3);
}
pub fn write_he(core_fs_index: u8, out_fs_index: u8, channel_configuration: u8) -> Vec<u8> {
let mut w = BitWriter::new();
push_he(&mut w, core_fs_index, out_fs_index, channel_configuration);
w.finish()
}
pub fn write_he_ps(core_fs_index: u8, out_fs_index: u8) -> Vec<u8> {
let mut w = BitWriter::new();
w.write(u32::from(AOT_PS), 5);
w.write(u32::from(core_fs_index), 4);
w.write(1, 4);
w.write(u32::from(out_fs_index), 4);
w.write(u32::from(AOT_LC), 5);
w.write(0, 3);
w.finish()
}
pub fn push_he(w: &mut BitWriter, core_fs_index: u8, out_fs_index: u8, channel_configuration: u8) {
w.write(5, 5);
w.write(u32::from(core_fs_index), 4);
w.write(u32::from(channel_configuration), 4);
w.write(u32::from(out_fs_index), 4);
w.write(u32::from(AOT_LC), 5);
w.write(0, 3);
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct AudioSpecificConfig {
pub aot: u8,
pub sampling_frequency_index: u8,
pub sample_rate: u32,
pub output_sample_rate: u32,
pub channel_configuration: u8,
pub sbr_present: bool,
pub ps_present: bool,
pub frame_samples: u16,
pub(crate) pce: Option<PceChannelMap>,
}
impl AudioSpecificConfig {
pub fn parse(data: &[u8]) -> Result<(Self, u64)> {
let mut reader = BitReader::new(data);
Self::parse_from_reader(&mut reader)
}
pub fn parse_from_reader(reader: &mut BitReader<'_>) -> Result<(Self, u64)> {
let start = reader.bit_position();
let asc = Self::parse_bits(reader)?;
Ok((asc, reader.bit_position().saturating_sub(start)))
}
fn parse_bits(reader: &mut BitReader<'_>) -> Result<Self> {
let outer_aot = read_aot(reader)?;
let sampling_frequency_index = reader.read(4)? as u8;
let sample_rate = resolve_rate(sampling_frequency_index, reader)?;
let channel_configuration = reader.read(4)? as u8;
let mut sbr_present = outer_aot == AOT_SBR || outer_aot == AOT_PS;
let mut ps_present = outer_aot == AOT_PS;
let mut output_sample_rate = sample_rate;
let (aot, pce, short_frame) = if sbr_present {
let ext_idx = reader.read(4)? as u8;
output_sample_rate = resolve_rate(ext_idx, reader)?;
let inner = read_aot(reader)?;
if inner != AOT_LC {
return Err(Error::UnsupportedAot(inner));
}
let (pce, flag) = parse_ga(
reader,
channel_configuration,
sampling_frequency_index,
inner,
)?;
(inner, pce, flag)
} else {
if !matches!(outer_aot, AOT_MAIN | AOT_LC | AOT_SSR | AOT_LTP | AOT_LD) {
return Err(Error::UnsupportedAot(outer_aot));
}
let (pce, flag) = parse_ga(
reader,
channel_configuration,
sampling_frequency_index,
outer_aot,
)?;
if outer_aot == AOT_LD {
if reader.read(2)? > 1 {
return Err(Error::Format("ASC epConfig error protection"));
}
} else {
parse_implicit_sbr(
reader,
&mut sbr_present,
&mut ps_present,
&mut output_sample_rate,
)?;
}
(outer_aot, pce, flag)
};
if sbr_present {
check_sbr_rates(sample_rate, output_sample_rate)?;
}
let frame_samples = if aot == AOT_LD {
if short_frame { 480 } else { 512 }
} else if short_frame {
960
} else {
1024
};
if short_frame && sbr_present {
return Err(Error::UnsupportedHeFrame960);
}
Ok(AudioSpecificConfig {
aot,
sampling_frequency_index,
sample_rate,
output_sample_rate,
channel_configuration,
sbr_present,
ps_present,
frame_samples,
pce,
})
}
}
fn parse_implicit_sbr(
reader: &mut BitReader<'_>,
sbr_present: &mut bool,
ps_present: &mut bool,
output_sample_rate: &mut u32,
) -> Result<()> {
if reader.bits_remaining() < 16 || reader.peek_u32(11).ok() != Some(0x2b7) {
return Ok(());
}
let _ = reader.read(11)?;
let ext = read_aot(reader)?;
if ext != AOT_SBR && ext != AOT_PS {
return Ok(());
}
if !reader.read_bit()? {
return Ok(());
}
*sbr_present = true;
*ps_present = *ps_present || ext == AOT_PS;
let ext_idx = reader.read(4)? as u8;
*output_sample_rate = resolve_rate(ext_idx, reader)?;
if reader.bits_remaining() >= 12 && reader.peek_u32(11).ok() == Some(0x548) {
let _ = reader.read(11)?;
*ps_present = reader.read_bit()?;
}
Ok(())
}
fn check_sbr_rates(core: u32, output: u32) -> Result<()> {
if output == core || output == core.saturating_mul(2) {
Ok(())
} else {
Err(Error::Format("SBR extension rate must be 1x or 2x core"))
}
}
fn read_aot(reader: &mut BitReader<'_>) -> Result<u8> {
let aot = reader.read(5)? as u8;
if aot == 31 {
Ok(32 + reader.read(6)? as u8)
} else {
Ok(aot)
}
}
fn resolve_rate(index: u8, reader: &mut BitReader<'_>) -> Result<u32> {
if index == 0x0f {
let rate = reader.read(24)?;
if rate == 0 {
return Err(Error::UnsupportedSampleRateIndex(index));
}
return Ok(rate);
}
ADTS_SAMPLE_RATES_HZ
.get(index as usize)
.copied()
.ok_or(Error::UnsupportedSampleRateIndex(index))
}
fn parse_ga(
reader: &mut BitReader<'_>,
channel_configuration: u8,
sf_index: u8,
aot: u8,
) -> Result<(Option<PceChannelMap>, bool)> {
let frame_length_flag = reader.read_bit()?;
let depends_on_core_coder = reader.read_bit()?;
if depends_on_core_coder {
let _core_coder_delay = reader.read(14)?;
}
let extension_flag = reader.read_bit()?;
let pce = if channel_configuration == 0 {
Some(parse_pce_in_asc(reader, sf_index)?)
} else {
None
};
if extension_flag {
if aot == AOT_LD {
let _ = reader.read(3)?;
}
let extension_flag3 = reader.read_bit()?;
if extension_flag3 {
return Err(Error::Format("ASC extensionFlag3 is Media"));
}
}
Ok((pce, frame_length_flag))
}
#[cfg(test)]
#[path = "asc_tests.rs"]
mod asc_tests;