use ffmpeg_next::{
ffi::{
AVAudioFifo, av_audio_fifo_alloc, av_audio_fifo_free, av_audio_fifo_read,
av_audio_fifo_size, av_audio_fifo_write,
},
format::Sample,
frame,
};
use crate::{Result, error::AVMuxError};
pub(crate) struct AudioFifo {
ptr: *mut AVAudioFifo,
}
unsafe impl Send for AudioFifo {}
impl AudioFifo {
pub(crate) fn new(format: Sample, nb_channels: i32) -> Result<Self> {
let ptr = unsafe { av_audio_fifo_alloc(format.into(), nb_channels, 1) };
if ptr.is_null() {
return Err(AVMuxError::Invalid);
}
Ok(Self { ptr })
}
pub(crate) fn size(&self) -> i32 {
unsafe { av_audio_fifo_size(self.ptr) }
}
pub(crate) fn write(&mut self, frame: &mut frame::Audio) -> Result<()> {
let nb_samples = frame.samples() as i32;
let written = unsafe {
av_audio_fifo_write(
self.ptr,
(*frame.as_mut_ptr()).data.as_mut_ptr().cast(),
nb_samples,
)
};
match written {
e if e < 0 => Err(ffmpeg_next::Error::from(e).into()),
n if n < nb_samples => Err(AVMuxError::Invalid),
_ => Ok(()),
}
}
pub(crate) fn read(&mut self, frame: &mut frame::Audio) -> Result<()> {
let nb_samples = frame.samples() as i32;
let read = unsafe {
av_audio_fifo_read(
self.ptr,
(*frame.as_mut_ptr()).data.as_mut_ptr().cast(),
nb_samples,
)
};
match read {
e if e < 0 => Err(ffmpeg_next::Error::from(e).into()),
n if n < nb_samples => Err(AVMuxError::Invalid),
_ => Ok(()),
}
}
}
impl Drop for AudioFifo {
fn drop(&mut self) {
unsafe { av_audio_fifo_free(self.ptr) }
}
}