use crate::engine::decode::StreamDecoder;
use crate::engine::error::Error as EngineError;
use crate::engine::latm::MuxCfg;
use crate::error::{AacError, Result};
use crate::isomp4::sniff_is_isobmff;
use crate::options::{ChannelMode, DEFAULT_MAX_INPUT_BYTES, DecodeOptions};
mod frame;
mod m4a;
mod pump;
pub use frame::{Frame, StreamInfo};
enum Container {
Unknown,
Adts,
Latm,
}
pub struct Decoder {
opts: DecodeOptions,
buf: Vec<u8>,
pos: usize,
bytes_fed: u64,
container: Container,
dec: StreamDecoder,
mux: Option<MuxCfg>,
mono_scratch: Vec<f32>,
locked: Option<(u32, usize)>,
max_samples: usize,
aac_frames: u64,
samples_decoded: u64,
samples_out: u64,
emitted: u64,
}
impl Decoder {
pub fn new(opts: DecodeOptions) -> Self {
let mut dec = StreamDecoder::new();
dec.mix_down_mono = matches!(opts.channel_mode, ChannelMode::Mono);
Self {
opts,
buf: Vec::new(),
pos: 0,
bytes_fed: 0,
container: Container::Unknown,
dec,
mux: None,
mono_scratch: Vec::new(),
locked: None,
max_samples: 0,
aac_frames: 0,
samples_decoded: 0,
samples_out: 0,
emitted: 0,
}
}
pub fn feed<F>(&mut self, bytes: &[u8], on_frame: F) -> Result<usize>
where
F: FnMut(Frame<'_>) -> Result<()>,
{
self.bytes_fed = self.bytes_fed.saturating_add(bytes.len() as u64);
if self.bytes_fed > DEFAULT_MAX_INPUT_BYTES {
return Err(AacError::too_long(
self.bytes_fed as f64 / 40_000.0, self.opts.max_duration_secs,
));
}
let mut buf = std::mem::take(&mut self.buf);
buf.extend_from_slice(bytes);
let mut cb = on_frame;
let res = self.pump(&buf, None, None, &mut cb, false);
if res.is_ok() && self.pos >= 64 * 1024 && self.pos >= buf.len() / 2 {
buf.drain(..self.pos);
self.pos = 0;
}
self.buf = buf;
res?;
Ok(bytes.len())
}
pub fn finish<F>(mut self, on_frame: F) -> Result<StreamInfo>
where
F: FnMut(Frame<'_>) -> Result<()>,
{
let buf = std::mem::take(&mut self.buf);
let mut cb = on_frame;
self.pump(&buf, None, None, &mut cb, true)?;
self.tallies()
}
fn decode_slice<F>(mut self, data: &[u8], on_frame: F) -> Result<StreamInfo>
where
F: FnMut(Frame<'_>) -> Result<()>,
{
let mut cb = on_frame;
self.pump(data, None, None, &mut cb, true)?;
self.tallies()
}
fn decode_slice_mono(
mut self,
data: &[u8],
est_frames: Option<usize>,
dst: &mut Vec<f32>,
) -> Result<StreamInfo> {
fn ignore(_: Frame<'_>) -> Result<()> {
Ok(())
}
self.pump(data, Some(dst), est_frames, &mut ignore, true)?;
self.tallies()
}
fn tallies(&self) -> Result<StreamInfo> {
if self.emitted == 0 {
return Err(match self.container {
Container::Latm => AacError::from(EngineError::LoasSyncInvalid),
_ => AacError::NotAac,
});
}
let (sample_rate, channels) = self.locked.unwrap_or((0, 0));
Ok(StreamInfo {
sample_rate,
channels,
aac_frames: self.aac_frames,
samples: self.samples_out,
})
}
}
pub fn decode_streaming<F>(data: &[u8], opts: &DecodeOptions, on_frame: F) -> Result<StreamInfo>
where
F: FnMut(Frame<'_>) -> Result<()>,
{
if data.len() as u64 > DEFAULT_MAX_INPUT_BYTES {
return Err(AacError::too_long(
data.len() as f64 / 40_000.0, opts.max_duration_secs,
));
}
if sniff_is_isobmff(data) {
return m4a::stream_m4a(data, opts, on_frame);
}
Decoder::new(opts.clone()).decode_slice(data, on_frame)
}
pub(crate) fn decode_streaming_mono_into(
data: &[u8],
opts: &DecodeOptions,
est_frames: Option<usize>,
dst: &mut Vec<f32>,
) -> Result<StreamInfo> {
if data.len() as u64 > DEFAULT_MAX_INPUT_BYTES {
return Err(AacError::too_long(
data.len() as f64 / 40_000.0, opts.max_duration_secs,
));
}
Decoder::new(opts.clone()).decode_slice_mono(data, est_frames, dst)
}