[vlc-devel] [PATCH] Backport fixes for audio resampling or downmixing from master.
Jean-Baptiste Kempf
jb at videolan.org
Sat Feb 28 13:53:58 CET 2009
This solves the segfault when transcoding from a DVD on 0.9.9?
On Sat, Feb 28, 2009 at 01:51:32PM +0100, Alexis Ballier wrote :
> Fixed audio transcoding when channel mixing or resampling is needed.
>
> Signed-off-by: Alexis Ballier <aballier at gentoo.org>
> ---
> modules/stream_out/transcode.c | 238 +++++++++++++++++++++-------------------
> 1 files changed, 123 insertions(+), 115 deletions(-)
>
> diff --git a/modules/stream_out/transcode.c b/modules/stream_out/transcode.c
> index 7290b60..da60d1c 100644
> --- a/modules/stream_out/transcode.c
> +++ b/modules/stream_out/transcode.c
> @@ -1101,12 +1101,107 @@ static int transcode_audio_filter_allocation_init( filter_t *p_filter,
> 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_FOURCC('f','l','3','2') )
> + {
> + /* First step, convert to fl32 */
> + current.i_codec =
> + current.audio.i_format = VLC_FOURCC('f','l','3','2');
> +
> + if( !filter_chain_AppendFilter( p_chain, NULL, NULL, NULL, ¤t ) )
> + {
> + msg_Err( p_stream, "Failed to find conversion filter to fl32" );
> + 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;
> + if( !filter_chain_AppendFilter( p_chain, NULL, NULL, NULL, ¤t ) )
> + {
> + 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];
> +
> + if( !filter_chain_AppendFilter( p_chain, NULL, NULL, NULL, ¤t ) )
> + {
> + 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;
> + if( !filter_chain_AppendFilter( p_chain, NULL, NULL, NULL, ¤t ) )
> + {
> + 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, ¤t ) )
> + {
> + /* 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;
> +}
> +
> static 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;
> - int i;
>
> /*
> * Open decoder
> @@ -1172,130 +1267,39 @@ static int transcode_audio_new( sout_stream_t *p_stream,
> id->p_encoder->fmt_in.audio.i_bitspersample =
> aout_BitsPerSample( id->p_encoder->fmt_in.i_codec );
>
> - /* Init filter chain */
> - id->p_f_chain = filter_chain_New( p_stream, "audio filter2", true,
> - transcode_audio_filter_allocation_init, NULL, NULL );
> - filter_chain_Reset( id->p_f_chain, &fmt_last, &id->p_encoder->fmt_in );
> -
> - /* Load conversion filters */
> - if( fmt_last.audio.i_channels != id->p_encoder->fmt_in.audio.i_channels ||
> - fmt_last.audio.i_rate != id->p_encoder->fmt_in.audio.i_rate )
> - {
> - /* We'll have to go through fl32 first */
> - fmt_last.i_codec = fmt_last.audio.i_format = VLC_FOURCC('f','l','3','2');
> - fmt_last.audio.i_bitspersample = aout_BitsPerSample( fmt_last.i_codec );
> - filter_chain_AppendFilter( id->p_f_chain, NULL, NULL, NULL, &fmt_last );
> - fmt_last = *filter_chain_GetFmtOut( id->p_f_chain );
> - }
> -
> - for( i = 0; i < 4; i++ )
> - {
> - if( (fmt_last.audio.i_channels !=
> - id->p_encoder->fmt_in.audio.i_channels) ||
> - (fmt_last.audio.i_rate != id->p_encoder->fmt_in.audio.i_rate) ||
> - (fmt_last.i_codec != id->p_encoder->fmt_in.i_codec) )
> - {
> - msg_Dbg( p_stream, "Looking for filter "
> - "(%4.4s->%4.4s, channels %d->%d, rate %d->%d)",
> - (char *)&fmt_last.i_codec,
> - (char *)&id->p_encoder->fmt_in.i_codec,
> - fmt_last.audio.i_channels,
> - id->p_encoder->fmt_in.audio.i_channels,
> - fmt_last.audio.i_rate,
> - id->p_encoder->fmt_in.audio.i_rate );
> - filter_chain_AppendFilter( id->p_f_chain, NULL, NULL,
> - &fmt_last, &id->p_encoder->fmt_in );
> - fmt_last = *filter_chain_GetFmtOut( id->p_f_chain );
> - }
> - else break;
> - }
> -
> - /* Final checks to see if conversions were successful */
> - if( fmt_last.i_codec != id->p_encoder->fmt_in.i_codec )
> - {
> - msg_Err( p_stream, "no audio filter found "
> - "(%4.4s->%4.4s, channels %d->%d, rate %d->%d)",
> - (char *)&fmt_last.i_codec,
> - (char *)&id->p_encoder->fmt_in.i_codec,
> - fmt_last.audio.i_channels,
> - id->p_encoder->fmt_in.audio.i_channels,
> - fmt_last.audio.i_rate,
> - id->p_encoder->fmt_in.audio.i_rate );
> - transcode_audio_close( id );
> - return VLC_EGENERIC;
> - }
> -
> - /* Load user specified audio filters now */
> + /* Load user specified audio filters */
> if( p_sys->psz_af2 )
> {
> - id->p_uf_chain = filter_chain_New( p_stream, "audio filter2", false,
> - transcode_audio_filter_allocation_init, NULL, NULL );
> - filter_chain_Reset( id->p_uf_chain, &fmt_last, &id->p_encoder->fmt_in );
> - filter_chain_AppendFromString( id->p_uf_chain, p_sys->psz_af2 );
> - fmt_last = *filter_chain_GetFmtOut( id->p_uf_chain );
> - }
> -
> - if( fmt_last.audio.i_channels != id->p_encoder->fmt_in.audio.i_channels )
> - {
> -#if 1
> - module_Unneed( id->p_encoder, id->p_encoder->p_module );
> - id->p_encoder->p_module = NULL;
> -
> - /* This might work, but only if the encoder is restarted */
> - id->p_encoder->fmt_in.audio.i_channels = fmt_last.audio.i_channels;
> - id->p_encoder->fmt_out.audio.i_channels = fmt_last.audio.i_channels;
> -
> - id->p_encoder->fmt_in.audio.i_physical_channels =
> - id->p_encoder->fmt_in.audio.i_original_channels =
> - fmt_last.audio.i_physical_channels;
> - id->p_encoder->fmt_out.audio.i_physical_channels =
> - id->p_encoder->fmt_out.audio.i_original_channels =
> - fmt_last.audio.i_physical_channels;
> -
> - msg_Dbg( p_stream, "number of audio channels for mixing changed, "
> - "trying to reopen the encoder for mixing %i to %i channels",
> - fmt_last.audio.i_channels,
> - id->p_encoder->fmt_in.audio.i_channels );
> -
> - /* reload encoder */
> - id->p_encoder->p_cfg = p_stream->p_sys->p_audio_cfg;
> - id->p_encoder->p_module =
> - module_Need( id->p_encoder, "encoder", p_sys->psz_aenc, true );
> - if( !id->p_encoder->p_module )
> + es_format_t fmt_fl32 = fmt_last;
> + fmt_fl32.i_codec =
> + fmt_fl32.audio.i_format = VLC_FOURCC('f','l','3','2');
> + if( transcode_audio_filter_chain_build( p_stream, id->p_uf_chain,
> + &fmt_fl32, &fmt_last ) )
> {
> - msg_Err( p_stream, "cannot find audio encoder (module:%s fourcc:%4.4s)",
> - p_sys->psz_aenc ? p_sys->psz_aenc : "any",
> - (char *)&p_sys->i_acodec );
> transcode_audio_close( id );
> return VLC_EGENERIC;
> }
> - id->p_encoder->fmt_in.audio.i_format = id->p_encoder->fmt_in.i_codec;
> - id->p_encoder->fmt_in.audio.i_bitspersample =
> - aout_BitsPerSample( id->p_encoder->fmt_in.i_codec );
> -#else
> - msg_Err( p_stream, "no audio filter found for mixing from"
> - " %i to %i channels", fmt_last.audio.i_channels,
> - id->p_encoder->fmt_in.audio.i_channels );
> + fmt_last = fmt_fl32;
>
> - transcode_audio_close( id );
> - return VLC_EGENERIC;
> -#endif
> + id->p_uf_chain = filter_chain_New( p_stream, "audio filter2", false,
> + transcode_audio_filter_allocation_init, NULL, NULL );
> + filter_chain_Reset( id->p_uf_chain, &fmt_last, &fmt_fl32 );
> + if( filter_chain_AppendFromString( id->p_uf_chain, p_sys->psz_af2 ) > 0 )
> + fmt_last = *filter_chain_GetFmtOut( id->p_uf_chain );
> }
>
> - if( fmt_last.audio.i_rate != id->p_encoder->fmt_in.audio.i_rate )
> + /* Load conversion filters */
> + id->p_f_chain = filter_chain_New( p_stream, "audio filter2", 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 ) )
> {
> - msg_Err( p_stream, "no audio filter found for resampling from"
> - " %iHz to %iHz", fmt_last.audio.i_rate,
> - id->p_encoder->fmt_in.audio.i_rate );
> -#if 0
> - /* FIXME : this might work, but only if the encoder is restarted */
> - id->p_encoder->fmt_in.audio.i_rate = fmt_last.audio.i_rate;
> - id->p_encoder->fmt_out.audio.i_rate = fmt_last.audio.i_rate;
> -#else
> transcode_audio_close( id );
> return VLC_EGENERIC;
> -#endif
> }
> + fmt_last = id->p_encoder->fmt_in;
>
> /* FIXME: Hack for mp3 transcoding support */
> if( id->p_encoder->fmt_out.i_codec == VLC_FOURCC( 'm','p','3',' ' ) )
> @@ -1319,10 +1323,10 @@ static void transcode_audio_close( sout_stream_id_t *id )
> id->p_encoder->p_module = NULL;
>
> /* Close filters */
> - if( id->p_f_chain )
> - filter_chain_Delete( id->p_f_chain );
> if( id->p_uf_chain )
> filter_chain_Delete( id->p_uf_chain );
> + if( id->p_f_chain )
> + filter_chain_Delete( id->p_f_chain );
> }
>
> static int transcode_audio_process( sout_stream_t *p_stream,
> @@ -1363,9 +1367,13 @@ static int transcode_audio_process( sout_stream_t *p_stream,
> p_audio_block->i_samples = p_audio_buf->i_nb_samples;
>
> /* Run filter chain */
> - p_audio_block = filter_chain_AudioFilter( id->p_f_chain, p_audio_block );
> if( id->p_uf_chain )
> + {
> p_audio_block = filter_chain_AudioFilter( id->p_uf_chain, p_audio_block );
> + assert( p_audio_block );
> + }
> +
> + p_audio_block = filter_chain_AudioFilter( id->p_f_chain, p_audio_block );
> assert( p_audio_block );
>
> p_audio_buf->p_buffer = p_audio_block->p_buffer;
> --
> 1.6.1.3
>
> _______________________________________________
> vlc-devel mailing list
> To unsubscribe or modify your subscription options:
> http://mailman.videolan.org/listinfo/vlc-devel
--
Best Regards,
--
Jean-Baptiste Kempf
http://www.jbkempf.com/
More information about the vlc-devel
mailing list