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
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)
|
|
}
|
|
}
|
|
}
|