feat: resample audio in transcoder

This commit is contained in:
kieran 2024-11-12 10:48:30 +00:00
parent 90b98598e1
commit ad0919b2a4
No known key found for this signature in database
GPG Key ID: DE71CEB3925BE941
2 changed files with 38 additions and 7 deletions

View File

@ -187,4 +187,4 @@ pub struct StreamGroupInfo {
pub(crate) group: *mut AVStreamGroup, pub(crate) group: *mut AVStreamGroup,
} }
unsafe impl Send for StreamGroupInfo {} unsafe impl Send for StreamGroupInfo {}

View File

@ -1,4 +1,6 @@
use crate::{Decoder, Demuxer, DemuxerInfo, Encoder, Muxer, Scaler, StreamInfo}; use crate::{
Decoder, Demuxer, DemuxerInfo, Encoder, Muxer, Resample, Scaler, StreamInfo, StreamType,
};
use anyhow::Result; use anyhow::Result;
use ffmpeg_sys_the_third::{av_frame_free, av_packet_free}; use ffmpeg_sys_the_third::{av_frame_free, av_packet_free};
use std::collections::HashMap; use std::collections::HashMap;
@ -11,6 +13,7 @@ pub struct Transcoder {
demuxer: Demuxer, demuxer: Demuxer,
decoder: Decoder, decoder: Decoder,
scalers: HashMap<i32, Scaler>, scalers: HashMap<i32, Scaler>,
resampler: HashMap<i32, Resample>,
encoders: HashMap<i32, Encoder>, encoders: HashMap<i32, Encoder>,
copy_stream: HashMap<i32, i32>, copy_stream: HashMap<i32, i32>,
muxer: Muxer, muxer: Muxer,
@ -24,6 +27,7 @@ impl Transcoder {
demuxer: Demuxer::new(input)?, demuxer: Demuxer::new(input)?,
decoder: Decoder::new(), decoder: Decoder::new(),
scalers: HashMap::new(), scalers: HashMap::new(),
resampler: HashMap::new(),
encoders: HashMap::new(), encoders: HashMap::new(),
copy_stream: HashMap::new(), copy_stream: HashMap::new(),
muxer, muxer,
@ -45,18 +49,38 @@ impl Transcoder {
let src_index = in_stream.index as i32; let src_index = in_stream.index as i32;
let dst_stream = self.muxer.add_stream_encoder(&encoder_out)?; let dst_stream = self.muxer.add_stream_encoder(&encoder_out)?;
let out_ctx = encoder_out.codec_context(); let out_ctx = encoder_out.codec_context();
if in_stream.width != (*out_ctx).width as usize
|| in_stream.height != (*out_ctx).height as usize // Setup scaler if the size/format is different from what the codec expects
|| in_stream.format != (*out_ctx).pix_fmt as isize if in_stream.stream_type == StreamType::Video
&& (in_stream.width != (*out_ctx).width as usize
|| in_stream.height != (*out_ctx).height as usize
|| in_stream.format != (*out_ctx).pix_fmt as isize)
{ {
// Setup scaler if the size/format is different from what the codec expects
self.scalers.insert(src_index, Scaler::new()); self.scalers.insert(src_index, Scaler::new());
} }
// Setup resampler for audio
if in_stream.stream_type == StreamType::Audio
&& (in_stream.format != (*out_ctx).sample_fmt as isize
|| in_stream.sample_rate != (*out_ctx).sample_rate as usize)
{
let r = Resample::new(
(*out_ctx).sample_fmt,
(*out_ctx).sample_rate as u32,
(*out_ctx).ch_layout.nb_channels as usize,
);
self.resampler.insert(src_index, r);
}
// insert encoder for this stream
self.encoders.insert( self.encoders.insert(
src_index, src_index,
encoder_out.with_stream_index((*dst_stream).index), encoder_out.with_stream_index((*dst_stream).index),
); );
// setup decoder for this input
self.decoder.setup_decoder(in_stream, None)?; self.decoder.setup_decoder(in_stream, None)?;
Ok(()) Ok(())
} }
@ -86,7 +110,7 @@ impl Transcoder {
// check if encoded stream // check if encoded stream
if let Some(enc) = self.encoders.get_mut(&src_index) { if let Some(enc) = self.encoders.get_mut(&src_index) {
for mut frame in self.decoder.decode_pkt(pkt)? { for mut frame in self.decoder.decode_pkt(pkt)? {
// scale frame before sending to encoder // scale video frame before sending to encoder
let mut frame = if let Some(sws) = self.scalers.get_mut(&src_index) { let mut frame = if let Some(sws) = self.scalers.get_mut(&src_index) {
let enc_ctx = enc.codec_context(); let enc_ctx = enc.codec_context();
let new_frame = sws.process_frame( let new_frame = sws.process_frame(
@ -101,6 +125,13 @@ impl Transcoder {
frame frame
}; };
// resample audio frame before encoding
let mut frame = if let Some(swr) = self.resampler.get_mut(&src_index) {
swr.process_frame(frame)?
} else {
frame
};
// encode frame and send packets to muxer // encode frame and send packets to muxer
for mut new_pkt in enc.encode_frame(frame)? { for mut new_pkt in enc.encode_frame(frame)? {
self.muxer.write_packet(new_pkt)?; self.muxer.write_packet(new_pkt)?;