Commit 53ac08c9 authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

transcode: use aout filters instead of filter chain (fixes #8447)

parent 83660dd1
......@@ -31,6 +31,7 @@
#include "transcode.h"
#include <vlc_aout.h>
#include <vlc_input.h>
#include <vlc_meta.h>
#include <vlc_modules.h>
......@@ -71,119 +72,11 @@ static block_t *audio_new_buffer( decoder_t *p_dec, int i_samples )
return p_block;
}
static int transcode_audio_filter_allocation_init( filter_t *p_filter,
void *data )
{
VLC_UNUSED(p_filter);
VLC_UNUSED(data);
return VLC_SUCCESS;
}
static bool transcode_audio_filter_needed( const es_format_t *p_fmt1, const es_format_t *p_fmt2 )
{
if( p_fmt1->i_codec != p_fmt2->i_codec ||
p_fmt1->audio.i_channels != p_fmt2->audio.i_channels ||
p_fmt1->audio.i_rate != p_fmt2->audio.i_rate )
return true;
return false;
}
static int transcode_audio_filter_chain_build( sout_stream_t *p_stream, filter_chain_t *p_chain,
const es_format_t *p_dst, const es_format_t *p_src )
{
if( !transcode_audio_filter_needed( p_dst, p_src ) )
return VLC_SUCCESS;
es_format_t current = *p_src;
msg_Dbg( p_stream, "Looking for filter "
"(%4.4s->%4.4s, channels %d->%d, rate %d->%d)",
(const char *)&p_src->i_codec,
(const char *)&p_dst->i_codec,
p_src->audio.i_channels,
p_dst->audio.i_channels,
p_src->audio.i_rate,
p_dst->audio.i_rate );
/* If any filter is needed, convert to fl32 */
if( current.i_codec != VLC_CODEC_FL32 )
{
/* First step, convert to fl32 */
current.i_codec =
current.audio.i_format = VLC_CODEC_FL32;
aout_FormatPrepare( &current.audio );
if( !filter_chain_AppendFilter( p_chain, NULL, NULL, NULL, &current ) )
{
msg_Err( p_stream, "Failed to find conversion filter to floating point" );
return VLC_EGENERIC;
}
current = *filter_chain_GetFmtOut( p_chain );
}
/* Fix sample rate */
if( current.audio.i_rate != p_dst->audio.i_rate )
{
current.audio.i_rate = p_dst->audio.i_rate;
aout_FormatPrepare( &current.audio );
if( !filter_chain_AppendFilter( p_chain, NULL, NULL, NULL, &current ) )
{
msg_Err( p_stream, "Failed to find conversion filter for resampling" );
return VLC_EGENERIC;
}
current = *filter_chain_GetFmtOut( p_chain );
}
/* Fix channels */
if( current.audio.i_channels != p_dst->audio.i_channels )
{
current.audio.i_channels = p_dst->audio.i_channels;
current.audio.i_physical_channels = p_dst->audio.i_physical_channels;
current.audio.i_original_channels = p_dst->audio.i_original_channels;
if( ( !current.audio.i_physical_channels || !current.audio.i_original_channels ) &&
current.audio.i_channels < 6 )
current.audio.i_physical_channels =
current.audio.i_original_channels = pi_channels_maps[current.audio.i_channels];
aout_FormatPrepare( &current.audio );
if( !filter_chain_AppendFilter( p_chain, NULL, NULL, NULL, &current ) )
{
msg_Err( p_stream, "Failed to find conversion filter for channel mixing" );
return VLC_EGENERIC;
}
current = *filter_chain_GetFmtOut( p_chain );
}
/* And last step, convert to the requested codec */
if( current.i_codec != p_dst->i_codec )
{
current.i_codec = p_dst->i_codec;
aout_FormatPrepare( &current.audio );
if( !filter_chain_AppendFilter( p_chain, NULL, NULL, NULL, &current ) )
{
msg_Err( p_stream, "Failed to find conversion filter to %4.4s",
(const char*)&p_dst->i_codec);
return VLC_EGENERIC;
}
current = *filter_chain_GetFmtOut( p_chain );
}
if( transcode_audio_filter_needed( p_dst, &current ) )
{
/* Weird case, a filter has side effects, doomed */
msg_Err( p_stream, "Failed to create a valid audio filter chain" );
return VLC_EGENERIC;
}
msg_Dbg( p_stream, "Got complete audio filter chain" );
return VLC_SUCCESS;
}
int transcode_audio_new( sout_stream_t *p_stream,
sout_stream_id_t *id )
{
sout_stream_sys_t *p_sys = p_stream->p_sys;
es_format_t fmt_last;
audio_sample_format_t fmt_last;
/*
* Open decoder
......@@ -208,12 +101,12 @@ int transcode_audio_new( sout_stream_t *p_stream,
id->p_decoder->fmt_out.audio.i_format = id->p_decoder->fmt_out.i_codec;
id->p_decoder->fmt_out.audio.i_bitspersample =
aout_BitsPerSample( id->p_decoder->fmt_out.i_codec );
fmt_last = id->p_decoder->fmt_out;
fmt_last = id->p_decoder->fmt_out.audio;
/* Fix AAC SBR changing number of channels and sampling rate */
if( !(id->p_decoder->fmt_in.i_codec == VLC_CODEC_MP4A &&
fmt_last.audio.i_rate != id->p_encoder->fmt_in.audio.i_rate &&
fmt_last.audio.i_channels != id->p_encoder->fmt_in.audio.i_channels) )
fmt_last.audio.i_rate = id->p_decoder->fmt_in.audio.i_rate;
fmt_last.i_rate != id->p_encoder->fmt_in.audio.i_rate &&
fmt_last.i_channels != id->p_encoder->fmt_in.audio.i_channels) )
fmt_last.i_rate = id->p_decoder->fmt_in.audio.i_rate;
/*
* Open encoder
......@@ -253,41 +146,35 @@ int transcode_audio_new( sout_stream_t *p_stream,
id->p_encoder->fmt_out.i_codec =
vlc_fourcc_GetCodec( AUDIO_ES, id->p_encoder->fmt_out.i_codec );
/* Load user specified audio filters */
if( p_sys->psz_af )
/* Fix channels */
if( !id->p_encoder->fmt_in.audio.i_physical_channels
|| !id->p_encoder->fmt_in.audio.i_original_channels )
{
es_format_t fmt_fl32 = fmt_last;
fmt_fl32.i_codec =
fmt_fl32.audio.i_format = VLC_CODEC_FL32;
id->p_uf_chain = filter_chain_New( p_stream, "audio filter", false,
transcode_audio_filter_allocation_init, NULL, NULL );
filter_chain_Reset( id->p_uf_chain, &fmt_last, &fmt_fl32 );
if( transcode_audio_filter_chain_build( p_stream, id->p_uf_chain,
&fmt_fl32, &fmt_last ) )
{
transcode_audio_close( id );
return VLC_EGENERIC;
}
fmt_last = fmt_fl32;
if( filter_chain_AppendFromString( id->p_uf_chain, p_sys->psz_af ) > 0 )
fmt_last = *filter_chain_GetFmtOut( id->p_uf_chain );
if( id->p_encoder->fmt_in.audio.i_channels < 6 )
id->p_encoder->fmt_in.audio.i_physical_channels =
id->p_encoder->fmt_in.audio.i_original_channels =
pi_channels_maps[id->p_encoder->fmt_in.audio.i_channels];
}
/* Load conversion filters */
id->p_f_chain = filter_chain_New( p_stream, "audio converter", true,
transcode_audio_filter_allocation_init, NULL, NULL );
filter_chain_Reset( id->p_f_chain, &fmt_last, &id->p_encoder->fmt_in );
if( transcode_audio_filter_chain_build( p_stream, id->p_f_chain,
&id->p_encoder->fmt_in, &fmt_last ) )
/* Load user specified audio filters */
/* XXX: These variable names come kinda out of nowhere... */
var_Create( p_stream, "audio-time-stretch", VLC_VAR_BOOL );
var_Create( p_stream, "audio-filter", VLC_VAR_STRING );
if( p_sys->psz_af )
var_SetString( p_stream, "audio-filter", p_sys->psz_af );
id->p_af_chain = aout_FiltersNew( p_stream, &fmt_last,
&id->p_encoder->fmt_in.audio, NULL );
var_Destroy( p_stream, "audio-filter" );
var_Destroy( p_stream, "audio-time-stretch" );
if( id->p_af_chain == NULL )
{
transcode_audio_close( id );
msg_Err( p_stream, "cannot connect audio filters chain" );
module_unneed( id->p_encoder, id->p_encoder->p_module );
id->p_encoder->p_module = NULL;
module_unneed( id->p_decoder, id->p_decoder->p_module );
id->p_decoder->p_module = NULL;
return VLC_EGENERIC;
}
fmt_last = id->p_encoder->fmt_in;
return VLC_SUCCESS;
}
......@@ -309,10 +196,8 @@ void transcode_audio_close( sout_stream_id_t *id )
id->p_encoder->p_module = NULL;
/* Close filters */
if( id->p_uf_chain )
filter_chain_Delete( id->p_uf_chain );
if( id->p_f_chain )
filter_chain_Delete( id->p_f_chain );
if( id->p_af_chain != NULL )
aout_FiltersDelete( (vlc_object_t *)NULL, id->p_af_chain );
}
int transcode_audio_process( sout_stream_t *p_stream,
......@@ -356,15 +241,8 @@ int transcode_audio_process( sout_stream_t *p_stream,
p_audio_buf->i_dts = p_audio_buf->i_pts;
/* Run filter chain */
if( id->p_uf_chain )
{
p_audio_buf = filter_chain_AudioFilter( id->p_uf_chain,
p_audio_buf );
if( !p_audio_buf )
abort();
}
p_audio_buf = filter_chain_AudioFilter( id->p_f_chain, p_audio_buf );
p_audio_buf = aout_FiltersPlay( id->p_af_chain, p_audio_buf,
INPUT_RATE_DEFAULT );
if( !p_audio_buf )
abort();
......
......@@ -72,6 +72,8 @@ struct sout_stream_sys_t
mtime_t i_master_drift;
};
struct aout_filters;
struct sout_stream_id_t
{
bool b_transcode;
......@@ -82,10 +84,15 @@ struct sout_stream_id_t
/* Decoder */
decoder_t *p_decoder;
/* Filters */
filter_chain_t *p_f_chain;
/* User specified filters */
filter_chain_t *p_uf_chain;
union
{
struct
{
filter_chain_t *p_f_chain; /**< Video filters */
filter_chain_t *p_uf_chain; /**< User-specified video filters */
};
struct aout_filters *p_af_chain; /**< Audio filters */
};
/* Encoder */
encoder_t *p_encoder;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment