use oxideav_core::bits::BitReader;
use oxideav_core::{Error, Result};
#[inline]
pub fn base_sample_rate(fs_index: u32) -> u32 {
if fs_index == 0 {
44_100
} else {
48_000
}
}
pub fn frame_rate_entry(frame_rate_index: u32, fs_index: u32) -> (u32, u32) {
if fs_index == 0 {
if frame_rate_index == 13 {
(21_533, 2_048)
} else {
(0, 0)
}
} else {
match frame_rate_index {
0 => (23_976, 1_920),
1 => (24_000, 1_920),
2 => (25_000, 2_048),
3 => (29_970, 1_536),
4 => (30_000, 1_536),
5 => (47_950, 960),
6 => (48_000, 960),
7 => (50_000, 1_024),
8 => (59_940, 768),
9 => (60_000, 768),
10 => (100_000, 512),
11 => (119_880, 384),
12 => (120_000, 384),
13 => (23_440, 2_048),
_ => (0, 0),
}
}
}
pub fn variable_bits(br: &mut BitReader<'_>, n_bits: u32) -> Result<u32> {
let mut value: u32 = 0;
loop {
let chunk = br.read_u32(n_bits)?;
value = value
.checked_add(chunk)
.ok_or_else(|| Error::invalid("ac4: variable_bits overflow"))?;
let more = br.read_bit()?;
if !more {
return Ok(value);
}
value = value
.checked_shl(n_bits)
.ok_or_else(|| Error::invalid("ac4: variable_bits shift overflow"))?;
value = value
.checked_add(1u32 << n_bits)
.ok_or_else(|| Error::invalid("ac4: variable_bits bias overflow"))?;
}
}
pub fn decode_channel_mode(br: &mut BitReader<'_>) -> Result<(u32, u32)> {
let b0 = br.read_u32(1)?;
if b0 == 0 {
return Ok((1, 1));
}
let b1 = br.read_u32(1)?;
if b1 == 0 {
return Ok((2, 2));
}
let nx = br.read_u32(2)?;
if nx != 0b11 {
return Ok((
match nx {
0b00 => 3,
0b01 => 5,
0b10 => 6,
_ => 0,
},
4,
));
}
let tail = br.read_u32(3)?;
let channels = match tail {
0b000 => 7, 0b001 => 8, 0b010 => 7, 0b011 => 8, 0b100 => 7, 0b101 => 8, 0b110 => 7, 0b111 => {
let _ext = variable_bits(br, 2)?;
return Ok((0, 7 + 3));
}
_ => unreachable!("3-bit tail is 0..=7"),
};
Ok((channels, 7))
}
#[derive(Debug, Clone)]
pub struct Ac4FrameInfo {
pub bitstream_version: u32,
pub sequence_counter: u32,
pub fs_index: u32,
pub base_sample_rate: u32,
pub sample_rate: u32,
pub frame_rate_index: u32,
pub frame_rate_milli: u32,
pub frame_length: u32,
pub b_iframe_global: bool,
pub channels: u16,
pub n_presentations: u32,
pub n_substreams: u32,
pub substream_sizes: Vec<u32>,
pub payload_base: u32,
pub presentations: Vec<PresentationInfo>,
}
#[derive(Debug, Clone, Default)]
pub struct PresentationInfo {
pub version: u32,
pub b_single_substream: bool,
pub presentation_config: u32,
pub channels: u16,
pub n_substream_info: u32,
pub n_hsf_ext: u32,
pub n_add_emdf_substreams: u32,
pub b_iframe: bool,
pub sf_multiplier: u32,
}
pub fn parse_ac4_toc(bytes: &[u8]) -> Result<Ac4FrameInfo> {
let mut br = BitReader::new(bytes);
let mut bitstream_version = br.read_u32(2)?;
if bitstream_version == 3 {
bitstream_version += variable_bits(&mut br, 2)?;
}
let sequence_counter = br.read_u32(10)?;
let b_wait_frames = br.read_bit()?;
if b_wait_frames {
let wait_frames = br.read_u32(3)?;
if wait_frames > 0 {
let _reserved = br.read_u32(2)?;
}
}
let fs_index = br.read_u32(1)?;
let frame_rate_index = br.read_u32(4)?;
let b_iframe_global = br.read_bit()?;
let b_single_presentation = br.read_bit()?;
let n_presentations = if b_single_presentation {
1
} else {
let b_more = br.read_bit()?;
if b_more {
variable_bits(&mut br, 2)? + 2
} else {
0
}
};
let b_payload_base = br.read_bit()?;
let payload_base = if b_payload_base {
let base = br.read_u32(5)? + 1;
if base == 0x20 {
base + variable_bits(&mut br, 3)?
} else {
base
}
} else {
0
};
let mut presentations = Vec::with_capacity(n_presentations as usize);
for _ in 0..n_presentations {
let pi = parse_presentation_info(&mut br, fs_index, frame_rate_index)?;
presentations.push(pi);
}
let (n_substreams, substream_sizes) = parse_substream_index_table(&mut br)?;
br.align_to_byte();
let base_sr = base_sample_rate(fs_index);
let sf_mul = presentations
.first()
.map(|p| p.sf_multiplier)
.unwrap_or(0);
let sample_rate = match (fs_index, sf_mul) {
(1, 1) => 96_000,
(1, 2) => 192_000,
_ => base_sr,
};
let channels = presentations.first().map(|p| p.channels).unwrap_or(0);
let (fps_milli, frame_length) = frame_rate_entry(frame_rate_index, fs_index);
Ok(Ac4FrameInfo {
bitstream_version,
sequence_counter,
fs_index,
base_sample_rate: base_sr,
sample_rate,
frame_rate_index,
frame_rate_milli: fps_milli,
frame_length,
b_iframe_global,
channels,
n_presentations,
n_substreams,
substream_sizes,
payload_base,
presentations,
})
}
fn frame_rate_factor(frame_rate_index: u32, b_multiplier: bool, multiplier_bit: u32) -> u32 {
match frame_rate_index {
2 | 3 | 4 => {
if b_multiplier {
if multiplier_bit == 0 {
2
} else {
4
}
} else {
1
}
}
0 | 1 | 7 | 8 | 9 => {
if b_multiplier {
2
} else {
1
}
}
_ => 1,
}
}
fn parse_frame_rate_multiply_info(
br: &mut BitReader<'_>,
frame_rate_index: u32,
) -> Result<(bool, u32)> {
let mut b_multiplier = false;
let mut multiplier_bit = 0u32;
match frame_rate_index {
2 | 3 | 4 => {
b_multiplier = br.read_bit()?;
if b_multiplier {
multiplier_bit = br.read_u32(1)?;
}
}
0 | 1 | 7 | 8 | 9 => {
b_multiplier = br.read_bit()?;
}
_ => {}
}
Ok((b_multiplier, multiplier_bit))
}
fn parse_emdf_info(br: &mut BitReader<'_>) -> Result<()> {
let emdf_version = br.read_u32(2)?;
if emdf_version == 3 {
let _ = variable_bits(br, 2)?;
}
let key_id = br.read_u32(3)?;
if key_id == 7 {
let _ = variable_bits(br, 3)?;
}
let b_emdf_payloads_substream_info = br.read_bit()?;
if b_emdf_payloads_substream_info {
parse_emdf_payloads_substream_info(br)?;
}
parse_emdf_reserved(br)?;
Ok(())
}
fn parse_emdf_payloads_substream_info(br: &mut BitReader<'_>) -> Result<()> {
let substream_index = br.read_u32(2)?;
if substream_index == 3 {
let _ = variable_bits(br, 2)?;
}
Ok(())
}
fn parse_emdf_reserved(br: &mut BitReader<'_>) -> Result<()> {
let b_more_bits = br.read_bit()?;
if b_more_bits {
let n_bits = variable_bits(br, 5)?;
if n_bits > 1 << 20 {
return Err(Error::invalid("ac4: emdf_reserved claims too many bits"));
}
br.skip(n_bits)?;
}
Ok(())
}
fn parse_substream_info(
br: &mut BitReader<'_>,
fs_index: u32,
frame_rate_index: u32,
) -> Result<SubstreamInfo> {
let (channels, _mode_bits) = decode_channel_mode(br)?;
let mut sf_multiplier = 0;
if fs_index == 1 {
let b_sf_multiplier = br.read_bit()?;
if b_sf_multiplier {
sf_multiplier = br.read_u32(1)? + 1;
}
}
let b_bitrate_info = br.read_bit()?;
if b_bitrate_info {
let short = br.read_u32(3)?;
if short == 0b111 {
let _ = br.read_u32(2)?;
}
}
if channels == 7 || channels == 8 {
}
let b_content_type = br.read_bit()?;
if b_content_type {
parse_content_type(br)?;
}
let factor = frame_rate_factor(frame_rate_index, false, 0);
let mut b_iframe = false;
for _ in 0..factor.max(1) {
let f = br.read_bit()?;
if !b_iframe {
b_iframe = f;
}
}
let si = br.read_u32(2)?;
if si == 3 {
let _ = variable_bits(br, 2)?;
}
Ok(SubstreamInfo {
channels: channels as u16,
sf_multiplier,
b_iframe,
})
}
struct SubstreamInfo {
channels: u16,
sf_multiplier: u32,
b_iframe: bool,
}
fn parse_content_type(br: &mut BitReader<'_>) -> Result<()> {
let _content_classifier = br.read_u32(3)?;
let b_language_indicator = br.read_bit()?;
if b_language_indicator {
let b_serialized = br.read_bit()?;
if b_serialized {
let _b_start_tag = br.read_bit()?;
let _language_tag_chunk = br.read_u32(16)?;
} else {
let n = br.read_u32(6)?;
br.skip(8 * n)?;
}
}
Ok(())
}
fn parse_hsf_ext_substream_info(br: &mut BitReader<'_>) -> Result<()> {
let si = br.read_u32(2)?;
if si == 3 {
let _ = variable_bits(br, 2)?;
}
Ok(())
}
fn parse_presentation_config_ext_info(br: &mut BitReader<'_>) -> Result<()> {
let mut n_skip_bytes = br.read_u32(5)?;
let b_more = br.read_bit()?;
if b_more {
n_skip_bytes += variable_bits(br, 2)? << 5;
}
if n_skip_bytes > 1 << 20 {
return Err(Error::invalid("ac4: presentation_config_ext_info too big"));
}
br.skip(n_skip_bytes * 8)?;
Ok(())
}
fn parse_presentation_info(
br: &mut BitReader<'_>,
fs_index: u32,
frame_rate_index: u32,
) -> Result<PresentationInfo> {
let mut info = PresentationInfo::default();
let b_single_substream = br.read_bit()?;
info.b_single_substream = b_single_substream;
let mut presentation_config: u32 = 0;
if !b_single_substream {
presentation_config = br.read_u32(3)?;
if presentation_config == 7 {
presentation_config += variable_bits(br, 2)?;
}
}
info.presentation_config = presentation_config;
let mut ver = 0u32;
while br.read_bit()? {
ver += 1;
if ver > 32 {
return Err(Error::invalid("ac4: runaway presentation_version"));
}
}
info.version = ver;
let b_add_emdf_substreams;
if !b_single_substream && presentation_config == 6 {
b_add_emdf_substreams = true;
} else {
let _md_compat = br.read_u32(3)?;
let b_belongs_to_presentation_id = br.read_bit()?;
if b_belongs_to_presentation_id {
let _presentation_id = variable_bits(br, 2)?;
}
let (_b_mult, _mult_bit) = parse_frame_rate_multiply_info(br, frame_rate_index)?;
parse_emdf_info(br)?;
if b_single_substream {
let si = parse_substream_info(br, fs_index, frame_rate_index)?;
info.channels = si.channels;
info.sf_multiplier = si.sf_multiplier;
info.b_iframe = si.b_iframe;
info.n_substream_info = 1;
} else {
let _b_hsf_ext = br.read_bit()?;
let b_hsf_ext = _b_hsf_ext;
match presentation_config {
0 | 1 | 2 => {
let first = parse_substream_info(br, fs_index, frame_rate_index)?;
info.channels = first.channels;
info.sf_multiplier = first.sf_multiplier;
info.b_iframe = first.b_iframe;
info.n_substream_info = 1;
if b_hsf_ext {
parse_hsf_ext_substream_info(br)?;
info.n_hsf_ext += 1;
}
let _second = parse_substream_info(br, fs_index, frame_rate_index)?;
info.n_substream_info += 1;
}
3 | 4 => {
let first = parse_substream_info(br, fs_index, frame_rate_index)?;
info.channels = first.channels;
info.sf_multiplier = first.sf_multiplier;
info.b_iframe = first.b_iframe;
info.n_substream_info = 1;
if b_hsf_ext {
parse_hsf_ext_substream_info(br)?;
info.n_hsf_ext += 1;
}
let _second = parse_substream_info(br, fs_index, frame_rate_index)?;
let _third = parse_substream_info(br, fs_index, frame_rate_index)?;
info.n_substream_info += 2;
}
5 => {
let first = parse_substream_info(br, fs_index, frame_rate_index)?;
info.channels = first.channels;
info.sf_multiplier = first.sf_multiplier;
info.b_iframe = first.b_iframe;
info.n_substream_info = 1;
if b_hsf_ext {
parse_hsf_ext_substream_info(br)?;
info.n_hsf_ext += 1;
}
}
_ => {
parse_presentation_config_ext_info(br)?;
}
}
}
let _b_pre_virtualized = br.read_bit()?;
b_add_emdf_substreams = br.read_bit()?;
}
if b_add_emdf_substreams {
let mut n = br.read_u32(2)?;
if n == 0 {
n = variable_bits(br, 2)? + 4;
}
for _ in 0..n {
parse_emdf_info(br)?;
}
info.n_add_emdf_substreams = n;
}
Ok(info)
}
fn parse_substream_index_table(br: &mut BitReader<'_>) -> Result<(u32, Vec<u32>)> {
let mut n_substreams = br.read_u32(2)?;
if n_substreams == 0 {
n_substreams = variable_bits(br, 2)? + 4;
}
let b_size_present = if n_substreams == 1 {
br.read_bit()?
} else {
true
};
let mut sizes = Vec::new();
if b_size_present {
for _ in 0..n_substreams {
let b_more_bits = br.read_bit()?;
let mut size = br.read_u32(10)?;
if b_more_bits {
size += variable_bits(br, 2)? << 10;
}
sizes.push(size);
}
}
Ok((n_substreams, sizes))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn variable_bits_single_chunk() {
let bytes = [0b10_0_00000];
let mut br = BitReader::new(&bytes);
let v = variable_bits(&mut br, 2).unwrap();
assert_eq!(v, 0b10);
}
#[test]
fn variable_bits_multi_chunk() {
let bytes = [0b1110_1000];
let mut br = BitReader::new(&bytes);
let v = variable_bits(&mut br, 2).unwrap();
assert_eq!(v, 17);
}
#[test]
fn frame_rate_entry_table() {
assert_eq!(frame_rate_entry(1, 1), (24_000, 1_920));
assert_eq!(frame_rate_entry(6, 1), (48_000, 960));
assert_eq!(frame_rate_entry(13, 0), (21_533, 2_048));
assert_eq!(frame_rate_entry(14, 1), (0, 0));
}
#[test]
fn channel_mode_mono_stereo_51() {
let bytes = [0b0_0000000];
let mut br = BitReader::new(&bytes);
assert_eq!(decode_channel_mode(&mut br).unwrap(), (1, 1));
let bytes = [0b10_000000];
let mut br = BitReader::new(&bytes);
assert_eq!(decode_channel_mode(&mut br).unwrap(), (2, 2));
let bytes = [0b1110_0000];
let mut br = BitReader::new(&bytes);
assert_eq!(decode_channel_mode(&mut br).unwrap(), (6, 4));
}
}