use crate::av::as_ptr::{AsMutPtr, AsPtr}; use crate::av::decoder::Decoder; use crate::av::encoder::Encoder; use crate::av::frame::Frame; use crate::av::verify_response; use crate::av::xcoder::XCoder; use ffmpeg_sys_next::{ swr_alloc, swr_alloc_set_opts, swr_convert_frame, swr_drop_output, swr_free, swr_get_delay, AVSampleFormat, SwrContext, }; use std::ptr::{null, null_mut}; pub struct Resampler { ptr: *mut SwrContext, input: StreamConfig, output: StreamConfig, } #[derive(Copy, Clone, Debug)] pub struct StreamConfig { sample_rate: i32, sample_format: AVSampleFormat, channel_layout: u64, frame_size: i32, } impl Resampler { pub fn from_coder(decoder: &Decoder, encoder: &Encoder) -> Resampler { unsafe { let swr = swr_alloc(); swr_alloc_set_opts( swr, encoder.channel_layout() as i64, encoder.sample_format(), encoder.sample_rate(), decoder.channel_layout() as i64, decoder.sample_format(), decoder.sample_rate(), 0, null_mut(), ); Resampler { ptr: swr, input: StreamConfig { sample_rate: decoder.sample_rate(), sample_format: decoder.sample_format(), channel_layout: decoder.channel_layout(), frame_size: decoder.frame_size(), }, output: StreamConfig { sample_rate: encoder.sample_rate(), sample_format: encoder.sample_format(), channel_layout: encoder.channel_layout(), frame_size: encoder.frame_size(), }, } } } pub fn convert(&self, input: &Frame) -> Result { let output = Frame::alloc(); output.allocate_audio( self.output.sample_format, self.output.channel_layout, self.output.frame_size, )?; output.set_sample_rate(self.output.sample_rate); verify_response("Failed to resample frame", unsafe { swr_convert_frame(self.ptr, output.as_mut_ptr(), input.as_ptr()) })?; output.set_pts((input.pts() * input.sample_rate() as i64) / output.sample_rate() as i64); Ok(output) } pub fn drain(&self) -> Result, String> { if 0 < unsafe { swr_get_delay(self.ptr, self.output.sample_rate as i64) } { let output = Frame::alloc(); output.allocate_audio( self.output.sample_format, self.output.channel_layout, self.output.frame_size, )?; output.set_sample_rate(self.output.sample_rate); verify_response("Failed to resample remaining frame", unsafe { swr_convert_frame(self.ptr, output.as_mut_ptr(), null()) })?; Ok(Some(output)) } else { Ok(None) } } } impl Drop for Resampler { fn drop(&mut self) { unsafe { swr_drop_output(self.ptr, i32::MAX); swr_free(&mut self.ptr) } } }