|
|
|
@ -2,15 +2,26 @@ 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_get_delay, AVFrame, SwrContext,
|
|
|
|
|
swr_alloc, swr_alloc_set_opts, swr_convert_frame, swr_get_delay, AVFrame, AVSampleFormat,
|
|
|
|
|
SwrContext,
|
|
|
|
|
};
|
|
|
|
|
use std::ptr::{null, null_mut};
|
|
|
|
|
|
|
|
|
|
pub struct Resampler {
|
|
|
|
|
ptr: *mut SwrContext,
|
|
|
|
|
output_sample_rate: i64,
|
|
|
|
|
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 {
|
|
|
|
@ -31,30 +42,57 @@ impl Resampler {
|
|
|
|
|
|
|
|
|
|
Resampler {
|
|
|
|
|
ptr: swr,
|
|
|
|
|
output_sample_rate: encoder.sample_rate() as i64,
|
|
|
|
|
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) -> Frame {
|
|
|
|
|
pub fn convert(&self, input: &Frame) -> Result<Frame, String> {
|
|
|
|
|
let output = Frame::alloc();
|
|
|
|
|
unsafe {
|
|
|
|
|
swr_convert_frame(self.ptr, output.as_mut_ptr(), input.as_ptr());
|
|
|
|
|
}
|
|
|
|
|
output.allocate_audio(
|
|
|
|
|
self.output.sample_format,
|
|
|
|
|
self.output.channel_layout,
|
|
|
|
|
self.output.frame_size,
|
|
|
|
|
)?;
|
|
|
|
|
output.set_sample_rate(self.output.sample_rate);
|
|
|
|
|
|
|
|
|
|
output
|
|
|
|
|
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) -> Option<Frame> {
|
|
|
|
|
if 0 < unsafe { swr_get_delay(self.ptr, self.output_sample_rate) } {
|
|
|
|
|
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();
|
|
|
|
|
unsafe {
|
|
|
|
|
swr_convert_frame(self.ptr, output.as_mut_ptr(), null());
|
|
|
|
|
}
|
|
|
|
|
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())
|
|
|
|
|
})?;
|
|
|
|
|
|
|
|
|
|
Some(output)
|
|
|
|
|
Ok(Some(output))
|
|
|
|
|
} else {
|
|
|
|
|
None
|
|
|
|
|
Ok(None)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|