You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

108 lines
3.2 KiB
Rust

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<Frame, String> {
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<Option<Frame>, 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)
}
}
}