feat: resample audio in transcoder
This commit is contained in:
parent
90b98598e1
commit
ad0919b2a4
@ -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)?;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user