use std::error::Error;
use std::io::{Read, Seek, SeekFrom};
use crate::buffer::{AudioBuffer, ChannelData};
use symphonia::core::audio::AudioBufferRef;
use symphonia::core::audio::Signal;
use symphonia::core::codecs::{Decoder, DecoderOptions, FinalizeResult};
use symphonia::core::conv::FromSample;
use symphonia::core::errors::Error as SymphoniaError;
use symphonia::core::formats::{FormatOptions, FormatReader};
use symphonia::core::meta::MetadataOptions;
use symphonia::core::probe::Hint;
struct MediaInput<R> {
input: R,
}
impl<R: Read> MediaInput<R> {
pub fn new(input: R) -> Self {
Self { input }
}
}
impl<R: Read> Read for MediaInput<R> {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
self.input.read(buf)
}
}
impl<R> Seek for MediaInput<R> {
fn seek(&mut self, _pos: SeekFrom) -> std::io::Result<u64> {
panic!("NotSupportedError - MediaInput does not support seeking")
}
}
impl<R: Read + Send + Sync> symphonia::core::io::MediaSource for MediaInput<R> {
fn is_seekable(&self) -> bool {
false
}
fn byte_len(&self) -> Option<u64> {
None
}
}
pub(crate) struct MediaDecoder {
format: Box<dyn FormatReader>,
decoder: Box<dyn Decoder>,
track_index: usize,
packet_count: usize,
}
impl MediaDecoder {
pub fn try_new<R: std::io::Read + Send + Sync + 'static>(
input: R,
) -> Result<Self, Box<dyn std::error::Error + Send + Sync>> {
let input = Box::new(MediaInput::new(input));
let stream = symphonia::core::io::MediaSourceStream::new(input, Default::default());
let hint = Hint::new();
let format_opts: FormatOptions = Default::default();
let metadata_opts: MetadataOptions = Default::default();
let decoder_opts = DecoderOptions {
verify: true,
};
let probed =
symphonia::default::get_probe().format(&hint, stream, &format_opts, &metadata_opts)?;
let format = probed.format;
let track = format.default_track().ok_or(SymphoniaError::Unsupported(
"no default media track available",
))?;
let track_index = format
.tracks()
.iter()
.position(|t| t.id == track.id)
.unwrap();
let decoder = symphonia::default::get_codecs().make(&track.codec_params, &decoder_opts)?;
Ok(Self {
format,
decoder,
track_index,
packet_count: 0,
})
}
}
impl Iterator for MediaDecoder {
type Item = Result<AudioBuffer, Box<dyn Error + Send + Sync>>;
fn next(&mut self) -> Option<Self::Item> {
let Self {
format,
decoder,
track_index,
packet_count,
} = self;
let track = format.tracks().get(*track_index)?;
let track_id = track.id;
loop {
let packet = match format.next_packet() {
Err(err) => {
if let SymphoniaError::IoError(err) = &err {
if err.kind() == std::io::ErrorKind::UnexpectedEof {
log::debug!("Decoding finished after {packet_count} packet(s)");
let FinalizeResult { verify_ok } = decoder.finalize();
if verify_ok == Some(false) {
log::warn!("Verification of decoded data failed");
}
return None;
}
}
log::warn!(
"Failed to fetch next packet following packet #{packet_count}: {err}"
);
return Some(Err(Box::new(err)));
}
Ok(packet) => {
*packet_count += 1;
packet
}
};
let packet_track_id = packet.track_id();
if packet_track_id != track_id {
log::debug!(
"Skipping packet from other track {packet_track_id} while decoding track {track_id}"
);
continue;
}
match decoder.decode(&packet) {
Ok(input) => {
let output = convert_buf(input);
return Some(Ok(output));
}
Err(SymphoniaError::DecodeError(err)) => {
log::warn!("Failed to decode packet #{packet_count}: {err}");
}
Err(SymphoniaError::IoError(err)) => {
log::warn!("I/O error while decoding packet #{packet_count}: {err}");
}
Err(err) => {
return Some(Err(Box::new(err)));
}
};
}
}
}
fn convert_buf(input: AudioBufferRef<'_>) -> AudioBuffer {
let channels = 0..input.spec().channels.count();
let sample_rate = input.spec().rate as f32;
use symphonia::core::audio::AudioBufferRef::*;
let data: Vec<Vec<f32>> = match input {
U8(buf) => channels
.map(|i| buf.chan(i).iter().copied().map(f32::from_sample).collect())
.collect(),
U16(buf) => channels
.map(|i| buf.chan(i).iter().copied().map(f32::from_sample).collect())
.collect(),
U24(buf) => channels
.map(|i| buf.chan(i).iter().copied().map(f32::from_sample).collect())
.collect(),
U32(buf) => channels
.map(|i| buf.chan(i).iter().copied().map(f32::from_sample).collect())
.collect(),
S8(buf) => channels
.map(|i| buf.chan(i).iter().copied().map(f32::from_sample).collect())
.collect(),
S16(buf) => channels
.map(|i| buf.chan(i).iter().copied().map(f32::from_sample).collect())
.collect(),
S24(buf) => channels
.map(|i| buf.chan(i).iter().copied().map(f32::from_sample).collect())
.collect(),
S32(buf) => channels
.map(|i| buf.chan(i).iter().copied().map(f32::from_sample).collect())
.collect(),
F32(buf) => channels
.map(|i| buf.chan(i).iter().copied().map(f32::from_sample).collect())
.collect(),
F64(buf) => channels
.map(|i| buf.chan(i).iter().copied().map(f32::from_sample).collect())
.collect(),
};
let channels = data.into_iter().map(ChannelData::from).collect();
AudioBuffer::from_channels(channels, sample_rate)
}
#[cfg(test)]
mod tests {
use super::*;
use std::io::Cursor;
#[test]
fn test_media_decoder() {
let input = Cursor::new(vec![0; 32]);
let media = MediaDecoder::try_new(input);
assert!(media.is_err()); }
}