From 2a24c87ba622d10017906d9f216f667011a18777 Mon Sep 17 00:00:00 2001 From: Gildas Bazin Date: Fri, 27 Aug 2004 13:31:23 +0000 Subject: [PATCH] * modules/stream_out/transcode.c: - Re-use our audio decoder modules instead of using libavcodec directly. - No more dependance on libavcodec. (downmixing is currently broken + you have to force the ffmpeg codec for a52) * modules/audio_filter/format.c: - PCM audio format conversion filter using the new common filter architecture. * modules/audio_filter/converter/mpgatofixed32.c: - implements both the old and new filter architecture (ie. useable in the transcoder). * modules/codec/ffmpeg/audio.c: - fixes and cleanup. --- configure.ac | 35 +- include/audio_output.h | 9 +- include/vlc_block.h | 1 + include/vlc_es.h | 14 +- include/vlc_filter.h | 6 +- modules/audio_filter/Modules.am | 1 + .../audio_filter/converter/mpgatofixed32.c | 128 ++++- modules/audio_filter/format.c | 176 ++++++ modules/codec/ffmpeg/audio.c | 33 +- modules/stream_out/Modules.am | 1 - modules/stream_out/transcode.c | 530 +++++++----------- 11 files changed, 540 insertions(+), 394 deletions(-) create mode 100644 modules/audio_filter/format.c diff --git a/configure.ac b/configure.ac index 7e7c49cc21..df3f789e8f 100644 --- a/configure.ac +++ b/configure.ac @@ -440,7 +440,7 @@ AC_CHECK_LIB(m,cos,[ VLC_ADD_LDFLAGS([adjust distort a52tofloat32 dtstofloat32 x264],[-lm]) ]) AC_CHECK_LIB(m,pow,[ - VLC_ADD_LDFLAGS([ffmpeg ffmpegaltivec stream_out_transcode stream_out_transcodealtivec stream_out_transrate i420_rgb faad toolame equalizer vlc],[-lm]) + VLC_ADD_LDFLAGS([ffmpeg ffmpegaltivec stream_out_transrate i420_rgb faad toolame equalizer vlc],[-lm]) ]) AC_CHECK_LIB(m,sqrt,[ VLC_ADD_LDFLAGS([headphone_channel_mixer normvol],[-lm]) @@ -1175,7 +1175,7 @@ then VLC_ADD_PLUGINS([packetizer_copy]) VLC_ADD_PLUGINS([stream_out_dummy stream_out_standard stream_out_es stream_out_rtp]) - VLC_ADD_PLUGINS([stream_out_duplicate stream_out_gather stream_out_display]) + VLC_ADD_PLUGINS([stream_out_duplicate stream_out_gather stream_out_display stream_out_transcode]) # VLC_ADD_PLUGINS([stream_out_transrate]) dnl Ogg and vorbis are handled in their respective section @@ -1818,25 +1818,18 @@ then then AC_CHECK_HEADERS(ffmpeg/avcodec.h) AC_CHECK_HEADERS(postproc/postprocess.h) - VLC_ADD_PLUGINS([ffmpeg stream_out_transcode]) - VLC_ADD_CFLAGS([ffmpeg stream_out_transcode],[`${FFMPEG_CONFIG} --cflags`]) + VLC_ADD_PLUGINS([ffmpeg]) + VLC_ADD_CFLAGS([ffmpeg],[`${FFMPEG_CONFIG} --cflags`]) VLC_ADD_LDFLAGS([ffmpeg],[`${FFMPEG_CONFIG} --plugin-libs avcodec avformat postproc`]) - VLC_ADD_LDFLAGS([stream_out_transcode],[`${FFMPEG_CONFIG} --libs avcodec`]) else AC_ARG_WITH(ffmpeg-mp3lame, [ --with-ffmpeg-mp3lame if ffmpeg has been compiled with mp3lame support], [ - dnl XXX: we don't link with -lavcodec a 2nd time because the OS X - dnl linker would miserably barf on multiple definitions. - VLC_ADD_LDFLAGS([stream_out_transcode],[]) VLC_ADD_LDFLAGS([ffmpeg],[-lmp3lame]) ]) AC_ARG_WITH(ffmpeg-faac, [ --with-ffmpeg-faac if ffmpeg has been compiled with faac support], [ - dnl XXX: we don't link with -lavcodec a 2nd time because the OS X - dnl linker would miserably barf on multiple definitions. - VLC_ADD_LDFLAGS([stream_out_transcode],[]) VLC_ADD_LDFLAGS([ffmpeg],[-lfaac]) ]) AC_ARG_WITH(ffmpeg-tree, @@ -1851,11 +1844,8 @@ then AC_CHECK_HEADERS(ffmpeg/avcodec.h, [], [AC_MSG_ERROR([Missing header file ffmpeg/avcodec.h.])] ) AC_CHECK_HEADERS(postproc/postprocess.h, [], [AC_MSG_ERROR([Missing header file postproc/postprocess.h.])] ) AC_CHECK_LIB(avcodec, avcodec_init, [ - VLC_ADD_BUILTINS([ffmpeg stream_out_transcode]) + VLC_ADD_BUILTINS([ffmpeg]) VLC_ADD_LDFLAGS([ffmpeg],[-lavcodec]) - dnl XXX: we don't link with -lavcodec a 2nd time because the OS X - dnl linker would miserably barf on multiple definitions. - VLC_ADD_LDFLAGS([stream_out_transcode],[]) ], [ AC_MSG_ERROR([Could not find ffmpeg on your system: you may get it from http://ffmpeg.sf.net/ (cvs version is recommended). Alternatively you can use --disable-ffmpeg to disable the ffmpeg plugins.]) ]) AC_CHECK_LIB(avformat, av_open_input_stream, [ AC_DEFINE(HAVE_LIBAVFORMAT, 1, @@ -1888,7 +1878,7 @@ then fi dnl Use a custom libffmpeg AC_MSG_RESULT(${real_ffmpeg_tree}/libavcodec/libavcodec.a) - VLC_ADD_BUILTINS([ffmpeg stream_out_transcode]) + VLC_ADD_BUILTINS([ffmpeg]) VLC_ADD_LDFLAGS([ffmpeg],[-L${real_ffmpeg_tree}/libavcodec -lavcodec]) VLC_ADD_CPPFLAGS([ffmpeg],[-I${real_ffmpeg_tree}/libavcodec -I${real_ffmpeg_tree}/libavformat]) @@ -1897,11 +1887,6 @@ then VLC_ADD_LDFLAGS([ffmpeg],[-L${real_ffmpeg_tree}/libavformat -lavformat -lz]) VLC_ADD_CPPFLAGS([ffmpeg],[-I${real_ffmpeg_tree}/libavformat]) fi - - dnl XXX: we don't link with -lavcodec a 2nd time because the OS X - dnl linker would miserably barf on multiple definitions. - VLC_ADD_LDFLAGS([stream_out_transcode],[-L${real_ffmpeg_tree}/libavcodec]) - VLC_ADD_CPPFLAGS([stream_out_transcode],[-I${real_ffmpeg_tree}/libavcodec -I${real_ffmpeg_tree}/libavformat]) fi fi fi @@ -1933,7 +1918,7 @@ then fi dnl Use a custom libffmpeg AC_MSG_RESULT(${real_ffmpeg_tree}/libavcodec/libavcodecaltivec.a) - VLC_ADD_BUILTINS([ffmpegaltivec stream_out_transcodealtivec]) + VLC_ADD_BUILTINS([ffmpegaltivec]) VLC_ADD_LDFLAGS([ffmpegaltivec],[-L${real_ffmpeg_tree}/libavcodec -lavcodecaltivec]) VLC_ADD_CPPFLAGS([ffmpeg],[-DNO_ALTIVEC_IN_FFMPEG]) VLC_ADD_CPPFLAGS([ffmpegaltivec],[-I${real_ffmpeg_tree}/libavcodec -I${real_ffmpeg_tree}/libavformat]) @@ -1943,12 +1928,6 @@ then VLC_ADD_LDFLAGS([ffmpegaltivec],[-L${real_ffmpeg_tree}/libavformat -lavformataltivec -lz]) VLC_ADD_CPPFLAGS([ffmpegaltivec],[-I${real_ffmpeg_tree}/libavformat]) fi - - dnl XXX: we don't link with -lavcodec a 2nd time because the OS X - dnl linker would miserably barf on multiple definitions. - VLC_ADD_LDFLAGS([stream_out_transcodealtivec],[-L${real_ffmpeg_tree}/libavcodec]) - VLC_ADD_CPPFLAGS([stream_out_transcode],[-DNO_ALTIVEC_IN_FFMPEG]) - VLC_ADD_CPPFLAGS([stream_out_transcodealtivec],[-I${real_ffmpeg_tree}/libavcodec -I${real_ffmpeg_tree}/libavformat]) fi fi diff --git a/include/audio_output.h b/include/audio_output.h index 8464511d64..af16452c53 100644 --- a/include/audio_output.h +++ b/include/audio_output.h @@ -2,7 +2,7 @@ * audio_output.h : audio output interface ***************************************************************************** * Copyright (C) 2002 VideoLAN - * $Id: audio_output.h,v 1.86 2003/11/20 22:10:55 fenrir Exp $ + * $Id$ * * Authors: Christophe Massiot * @@ -129,6 +129,13 @@ struct aout_buffer_t mtime_t start_date, end_date; struct aout_buffer_t * p_next; + + /** Private data (aout_buffer_t will disappear soon so no need for an + * aout_buffer_sys_t type) */ + void * p_sys; + + /** This way the release can be overloaded */ + void (*pf_release)( aout_buffer_t * ); }; /* Size of a frame for S/PDIF output. */ diff --git a/include/vlc_block.h b/include/vlc_block.h index e3e74c057f..ee22800f3b 100644 --- a/include/vlc_block.h +++ b/include/vlc_block.h @@ -74,6 +74,7 @@ struct block_t mtime_t i_dts; mtime_t i_length; + int i_samples; /* Used for audio */ int i_rate; int i_buffer; diff --git a/include/vlc_es.h b/include/vlc_es.h index a47c0f66b0..8a4f3f78f2 100644 --- a/include/vlc_es.h +++ b/include/vlc_es.h @@ -74,6 +74,14 @@ struct audio_format_t int i_bitspersample; }; +#ifdef WORDS_BIGENDIAN +# define AUDIO_FMT_S16_NE VLC_FOURCC('s','1','6','b') +# define AUDIO_FMT_U16_NE VLC_FOURCC('u','1','6','b') +#else +# define AUDIO_FMT_S16_NE VLC_FOURCC('s','1','6','l') +# define AUDIO_FMT_U16_NE VLC_FOURCC('u','1','6','l') +#endif + /** * video format description */ @@ -202,8 +210,10 @@ static inline void es_format_Copy( es_format_t *dst, es_format_t *src ) if( src->video.p_palette ) { - dst->video.p_palette = (video_palette_t*)malloc( sizeof( video_palette_t ) ); - memcpy( dst->video.p_palette, src->video.p_palette, sizeof( video_palette_t ) ); + dst->video.p_palette = + (video_palette_t*)malloc( sizeof( video_palette_t ) ); + memcpy( dst->video.p_palette, src->video.p_palette, + sizeof( video_palette_t ) ); } } diff --git a/include/vlc_filter.h b/include/vlc_filter.h index e10e14524b..9bb4db92a2 100644 --- a/include/vlc_filter.h +++ b/include/vlc_filter.h @@ -51,10 +51,11 @@ struct filter_t /* Output format of filter */ es_format_t fmt_out; + picture_t * ( * pf_video_filter ) ( filter_t *, picture_t * ); + block_t * ( * pf_audio_filter ) ( filter_t *, block_t * ); void ( * pf_video_blend ) ( filter_t *, picture_t *, picture_t *, picture_t *, int, int ); - picture_t * ( * pf_video_filter ) ( filter_t *, picture_t * ); subpicture_t * ( *pf_render_string ) ( filter_t *, block_t * ); @@ -63,8 +64,7 @@ struct filter_t */ /* Audio output callbacks */ - aout_buffer_t * ( * pf_aout_buffer_new) ( filter_t *, int ); - void ( * pf_aout_buffer_del) ( filter_t *, aout_buffer_t * ); + block_t * ( * pf_audio_buffer_new) ( filter_t *, int ); /* Video output callbacks */ picture_t * ( * pf_vout_buffer_new) ( filter_t * ); diff --git a/modules/audio_filter/Modules.am b/modules/audio_filter/Modules.am index e7002ff019..778434e43f 100644 --- a/modules/audio_filter/Modules.am +++ b/modules/audio_filter/Modules.am @@ -1,2 +1,3 @@ SOURCES_equalizer = equalizer.c equalizer_presets.h SOURCES_normvol = normvol.c +SOURCES_format = format.c diff --git a/modules/audio_filter/converter/mpgatofixed32.c b/modules/audio_filter/converter/mpgatofixed32.c index d516a3dff6..4d94e1d21a 100644 --- a/modules/audio_filter/converter/mpgatofixed32.c +++ b/modules/audio_filter/converter/mpgatofixed32.c @@ -32,8 +32,9 @@ #include #include -#include "audio_output.h" +#include #include "aout_internal.h" +#include "vlc_filter.h" /***************************************************************************** * Local prototypes @@ -43,10 +44,14 @@ static void Destroy ( vlc_object_t * ); static void DoWork ( aout_instance_t *, aout_filter_t *, aout_buffer_t *, aout_buffer_t * ); +static int OpenFilter ( vlc_object_t * ); +static void CloseFilter( vlc_object_t * ); +static block_t *Convert( filter_t *, block_t * ); + /***************************************************************************** * Local structures *****************************************************************************/ -struct aout_filter_sys_t +struct filter_sys_t { struct mad_stream mad_stream; struct mad_frame mad_frame; @@ -60,15 +65,20 @@ vlc_module_begin(); set_description( _("MPEG audio decoder") ); set_capability( "audio filter", 100 ); set_callbacks( Create, Destroy ); + + add_submodule(); + set_description( _("MPEG audio decoder") ); + set_capability( "audio filter2", 100 ); + set_callbacks( OpenFilter, CloseFilter ); vlc_module_end(); /***************************************************************************** * Create: *****************************************************************************/ -static int Create( vlc_object_t * _p_filter ) +static int Create( vlc_object_t *p_this ) { - aout_filter_t * p_filter = (aout_filter_t *)_p_filter; - struct aout_filter_sys_t * p_sys; + aout_filter_t *p_filter = (aout_filter_t *)p_this; + struct filter_sys_t *p_sys; if ( (p_filter->input.i_format != VLC_FOURCC('m','p','g','a') && p_filter->input.i_format != VLC_FOURCC('m','p','g','3')) @@ -84,7 +94,8 @@ static int Create( vlc_object_t * _p_filter ) } /* Allocate the memory needed to store the module's structure */ - p_sys = p_filter->p_sys = malloc( sizeof(struct aout_filter_sys_t) ); + p_sys = malloc( sizeof(filter_sys_t) ); + p_filter->p_sys = (struct aout_filter_sys_t *)p_sys; if( p_sys == NULL ) { msg_Err( p_filter, "out of memory" ); @@ -109,7 +120,7 @@ static int Create( vlc_object_t * _p_filter ) static void DoWork( aout_instance_t * p_aout, aout_filter_t * p_filter, aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf ) { - struct aout_filter_sys_t * p_sys = p_filter->p_sys; + filter_sys_t *p_sys = (filter_sys_t *)p_filter->p_sys; p_out_buf->i_nb_samples = p_in_buf->i_nb_samples; p_out_buf->i_nb_bytes = p_in_buf->i_nb_samples * sizeof(vlc_fixed_t) * @@ -179,7 +190,7 @@ static void DoWork( aout_instance_t * p_aout, aout_filter_t * p_filter, mad_fixed_t const * p_right = p_pcm->samples[1]; float f_temp = (float)FIXED32_ONE; - switch ( p_pcm->channels ) + switch ( p_pcm->channels ) { case 2: while ( i_samples-- ) @@ -206,10 +217,10 @@ static void DoWork( aout_instance_t * p_aout, aout_filter_t * p_filter, /***************************************************************************** * Destroy : deallocate data structures *****************************************************************************/ -static void Destroy( vlc_object_t * _p_filter ) +static void Destroy( vlc_object_t *p_this ) { - aout_filter_t * p_filter = (aout_filter_t *)_p_filter; - struct aout_filter_sys_t * p_sys = p_filter->p_sys; + aout_filter_t *p_filter = (aout_filter_t *)p_this; + filter_sys_t *p_sys = (filter_sys_t *)p_filter->p_sys; mad_synth_finish( &p_sys->mad_synth ); mad_frame_finish( &p_sys->mad_frame ); @@ -217,3 +228,98 @@ static void Destroy( vlc_object_t * _p_filter ) free( p_sys ); } +/***************************************************************************** + * OpenFilter: + *****************************************************************************/ +static int OpenFilter( vlc_object_t *p_this ) +{ + filter_t *p_filter = (filter_t *)p_this; + filter_sys_t *p_sys; + + if( p_filter->fmt_in.i_codec != VLC_FOURCC('m','p','g','a') && + p_filter->fmt_in.i_codec != VLC_FOURCC('m','p','g','3') ) + { + return VLC_EGENERIC; + } + + /* Allocate the memory needed to store the module's structure */ + p_sys = p_filter->p_sys = malloc( sizeof(filter_sys_t) ); + if( p_sys == NULL ) + { + msg_Err( p_filter, "out of memory" ); + return -1; + } + + p_filter->pf_audio_filter = Convert; + + /* Initialize libmad */ + mad_stream_init( &p_sys->mad_stream ); + mad_frame_init( &p_sys->mad_frame ); + mad_synth_init( &p_sys->mad_synth ); + mad_stream_options( &p_sys->mad_stream, MAD_OPTION_IGNORECRC ); + + msg_Err( p_this, "%4.4s->%4.4s, bits per sample: %i", + (char *)&p_filter->fmt_in.i_codec, + (char *)&p_filter->fmt_out.i_codec, + p_filter->fmt_out.audio.i_bitspersample ); + + p_filter->fmt_out.i_codec = + p_filter->fmt_out.audio.i_format = VLC_FOURCC('f','l','3','2'); + p_filter->fmt_out.audio.i_bitspersample = sizeof(float); + + return 0; +} + +/***************************************************************************** + * CloseFilter : deallocate data structures + *****************************************************************************/ +static void CloseFilter( vlc_object_t *p_this ) +{ + filter_t *p_filter = (filter_t *)p_this; + filter_sys_t *p_sys = p_filter->p_sys; + + mad_synth_finish( &p_sys->mad_synth ); + mad_frame_finish( &p_sys->mad_frame ); + mad_stream_finish( &p_sys->mad_stream ); + free( p_sys ); +} + +static block_t *Convert( filter_t *p_filter, block_t *p_block ) +{ + aout_filter_t aout_filter; + aout_buffer_t in_buf, out_buf; + block_t *p_out; + + int i_out_size = p_block->i_samples * + p_filter->fmt_out.audio.i_bitspersample * + p_filter->fmt_out.audio.i_channels; + + p_out = p_filter->pf_audio_buffer_new( p_filter, i_out_size ); + if( !p_out ) + { + msg_Warn( p_filter, "can't get output buffer" ); + return NULL; + } + + p_out->i_samples = p_block->i_samples; + p_out->i_dts = p_block->i_dts; + p_out->i_pts = p_block->i_pts; + p_out->i_length = p_block->i_length; + + aout_filter.p_sys = (struct aout_filter_sys_t *)p_filter->p_sys; + aout_filter.input = p_filter->fmt_in.audio; + aout_filter.input.i_format = p_filter->fmt_in.i_codec; + aout_filter.output = p_filter->fmt_out.audio; + aout_filter.output.i_format = p_filter->fmt_out.i_codec; + + in_buf.p_buffer = p_block->p_buffer; + in_buf.i_nb_bytes = p_block->i_buffer; + in_buf.i_nb_samples = p_block->i_samples; + out_buf.p_buffer = p_out->p_buffer; + out_buf.i_nb_bytes = p_out->i_buffer; + out_buf.i_nb_samples = p_out->i_samples; + + DoWork( (aout_instance_t *)p_filter, &aout_filter, &in_buf, &out_buf ); + + return p_out; +} diff --git a/modules/audio_filter/format.c b/modules/audio_filter/format.c new file mode 100644 index 0000000000..a35174e3d0 --- /dev/null +++ b/modules/audio_filter/format.c @@ -0,0 +1,176 @@ +/***************************************************************************** + * format.c : PCM format converter + ***************************************************************************** + * Copyright (C) 2002 VideoLAN + * $Id: float32tos16.c 8391 2004-08-06 17:28:36Z sam $ + * + * Authors: Christophe Massiot + * Gildas Bazin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. + *****************************************************************************/ + +/***************************************************************************** + * Preamble + *****************************************************************************/ +#include /* malloc(), free() */ +#include + +#include +#include +#include "vlc_filter.h" + +/***************************************************************************** + * Local prototypes + *****************************************************************************/ +static int Open ( vlc_object_t * ); + +static block_t *Float32toS16( filter_t *, block_t * ); +static block_t *Float32toU16( filter_t *, block_t * ); +static block_t *S16toFloat32( filter_t *, block_t * ); + +/***************************************************************************** + * Module descriptor + *****************************************************************************/ +vlc_module_begin(); + set_description( _("audio filter for PCM format conversion") ); + set_capability( "audio filter2", 1 ); + set_callbacks( Open, NULL ); +vlc_module_end(); + +/***************************************************************************** + * Open: + *****************************************************************************/ +static int Open( vlc_object_t *p_this ) +{ + filter_t *p_filter = (filter_t *)p_this; + + if( p_filter->fmt_in.i_codec == VLC_FOURCC('f','l','3','2') && + p_filter->fmt_out.i_codec == AUDIO_FMT_S16_NE ) + { + p_filter->pf_audio_filter = Float32toS16; + } + else if ( p_filter->fmt_in.i_codec == VLC_FOURCC('f','l','3','2') && + p_filter->fmt_out.i_codec == AUDIO_FMT_U16_NE ) + { + p_filter->pf_audio_filter = Float32toU16; + } + else if ( p_filter->fmt_in.i_codec == AUDIO_FMT_S16_NE && + p_filter->fmt_out.i_codec == VLC_FOURCC('f','l','3','2') ) + { + p_filter->pf_audio_filter = S16toFloat32; + } + else return VLC_EGENERIC; + + msg_Err( p_this, "%4.4s->%4.4s, bits per sample: %i", + (char *)&p_filter->fmt_in.i_codec, + (char *)&p_filter->fmt_out.i_codec, + p_filter->fmt_in.audio.i_bitspersample ); + + return VLC_SUCCESS; +} + +/***************************************************************************** + * Convert a buffer + *****************************************************************************/ +static block_t *Float32toS16( filter_t *p_filter, block_t *p_block ) +{ + int i; + float *p_in = (float *)p_block->p_buffer; + int16_t *p_out = (int16_t *)p_in; + + for( i = p_block->i_buffer/ p_filter->fmt_in.audio.i_bitspersample; i-- ; ) + { +#if 0 + /* Slow version. */ + if ( *p_in >= 1.0 ) *p_out = 32767; + else if ( *p_in < -1.0 ) *p_out = -32768; + else *p_out = *p_in * 32768.0; +#else + /* This is walken's trick based on IEEE float format. */ + union { float f; int32_t i; } u; + u.f = *p_in + 384.0; + if ( u.i > 0x43c07fff ) *p_out = 32767; + else if ( u.i < 0x43bf8000 ) *p_out = -32768; + else *p_out = u.i - 0x43c00000; +#endif + p_in++; p_out++; + } + + p_block->i_buffer /= 2; + return p_block; +} + +static block_t *Float32toU16( filter_t *p_filter, block_t *p_block ) +{ + int i; + float *p_in = (float *)p_block->p_buffer; + uint16_t *p_out = (uint16_t *)p_in; + + for( i = p_block->i_buffer/ p_filter->fmt_in.audio.i_bitspersample; i-- ; ) + { + if ( *p_in >= 1.0 ) *p_out = 65535; + else if ( *p_in < -1.0 ) *p_out = 0; + else *p_out = (uint16_t)(32768 + *p_in * 32768); + p_in++; p_out++; + } + + p_block->i_buffer /= 2; + return p_block; +} + +static block_t *S16toFloat32( filter_t *p_filter, block_t *p_block ) +{ + block_t *p_block_out; + int16_t *p_in; + float *p_out; + int i; + + p_block_out = + p_filter->pf_audio_buffer_new( p_filter, p_block->i_buffer*2 ); + if( !p_block_out ) + { + msg_Warn( p_filter, "can't get output buffer" ); + return NULL; + } + + p_in = (int16_t *)(p_block->p_buffer + p_block->i_buffer) - 1; + p_out = (float *)(p_block_out->p_buffer + p_block_out->i_buffer) - 1; + + for( i = p_block->i_buffer/ p_filter->fmt_in.audio.i_bitspersample; i-- ; ) + { +#if 0 + /* Slow version */ + *p_out = (float)*p_in / 32768.0; +#else + /* This is walken's trick based on IEEE float format. On my PIII + * this takes 16 seconds to perform one billion conversions, instead + * of 19 seconds for the above division. */ + union { float f; int32_t i; } u; + u.i = *p_in + 0x43c00000; + *p_out = u.f - 384.0; +#endif + + p_in--; p_out--; + } + + p_block_out->i_samples = p_block->i_samples; + p_block_out->i_dts = p_block->i_dts; + p_block_out->i_pts = p_block->i_pts; + p_block_out->i_length = p_block->i_length; + p_block_out->i_rate = p_block->i_rate; + + return p_block_out; +} diff --git a/modules/codec/ffmpeg/audio.c b/modules/codec/ffmpeg/audio.c index d575039e0d..3aed746180 100644 --- a/modules/codec/ffmpeg/audio.c +++ b/modules/codec/ffmpeg/audio.c @@ -5,7 +5,7 @@ * $Id$ * * Authors: Laurent Aimar - * Gildas Bazin + * Gildas Bazin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -134,26 +134,32 @@ int E_(InitAudioDec)( decoder_t *p_dec, AVCodecContext *p_context, p_sys->p_samples = NULL; p_sys->i_samples = 0; - aout_DateSet( &p_sys->end_date, 0 ); + if( p_dec->fmt_in.audio.i_rate ) + { + aout_DateInit( &p_sys->end_date, p_dec->fmt_in.audio.i_rate ); + aout_DateSet( &p_sys->end_date, 0 ); + } /* Set output properties */ p_dec->fmt_out.i_cat = AUDIO_ES; p_dec->fmt_out.i_codec = AOUT_FMT_S16_NE; + p_dec->fmt_out.audio.i_bitspersample = 2; return VLC_SUCCESS; } -/* XXX Needed as aout really doesn't like big audio chunk and wma produce easily > 30000 samples... */ +/***************************************************************************** + * SplitBuffer: Needed because aout really doesn't like big audio chunk and + * wma produces easily > 30000 samples... + *****************************************************************************/ aout_buffer_t *SplitBuffer( decoder_t *p_dec ) { decoder_sys_t *p_sys = p_dec->p_sys; int i_samples = __MIN( p_sys->i_samples, 4096 ); aout_buffer_t *p_buffer; - if( i_samples == 0 ) - { - return NULL; - } + if( i_samples == 0 ) return NULL; + if( ( p_buffer = p_dec->pf_aout_buffer_new( p_dec, i_samples ) ) == NULL ) { msg_Err( p_dec, "cannot get aout buffer" ); @@ -189,10 +195,7 @@ aout_buffer_t *E_( DecodeAudio )( decoder_t *p_dec, block_t **pp_block ) { /* More data */ p_buffer = SplitBuffer( p_dec ); - if( p_buffer == NULL ) - { - block_Release( p_block ); - } + if( !p_buffer ) block_Release( p_block ); return p_buffer; } @@ -203,8 +206,7 @@ aout_buffer_t *E_( DecodeAudio )( decoder_t *p_dec, block_t **pp_block ) return NULL; } - if( p_block->i_buffer <= 0 || - ( p_block->i_flags&BLOCK_FLAG_DISCONTINUITY ) ) + if( p_block->i_buffer <= 0 || p_block->i_flags & BLOCK_FLAG_DISCONTINUITY ) { block_Release( p_block ); return NULL; @@ -264,10 +266,7 @@ aout_buffer_t *E_( DecodeAudio )( decoder_t *p_dec, block_t **pp_block ) p_sys->p_samples = p_sys->p_output; p_buffer = SplitBuffer( p_dec ); - if( !p_buffer ) - { - block_Release( p_block ); - } + if( !p_buffer ) block_Release( p_block ); return p_buffer; } diff --git a/modules/stream_out/Modules.am b/modules/stream_out/Modules.am index 1e132b5b6f..82c5b12b72 100644 --- a/modules/stream_out/Modules.am +++ b/modules/stream_out/Modules.am @@ -3,7 +3,6 @@ SOURCES_stream_out_standard = standard.c \ announce.c \ announce.h SOURCES_stream_out_transcode = transcode.c -SOURCES_stream_out_transcodealtivec = transcode.c SOURCES_stream_out_duplicate = duplicate.c SOURCES_stream_out_es = es.c SOURCES_stream_out_display = display.c diff --git a/modules/stream_out/transcode.c b/modules/stream_out/transcode.c index 12d0f96be9..0cd9510b9b 100644 --- a/modules/stream_out/transcode.c +++ b/modules/stream_out/transcode.c @@ -36,17 +36,6 @@ #include "vlc_filter.h" #include "osd.h" -/* ffmpeg header */ -#ifdef HAVE_FFMPEG_AVCODEC_H -# include -#else -# include -#endif - -#if LIBAVCODEC_BUILD < 4704 -# define AV_NOPTS_VALUE 0 -#endif - /***************************************************************************** * Module descriptor *****************************************************************************/ @@ -136,15 +125,8 @@ static void Close( vlc_object_t * ); #define SOUT_CFG_PREFIX "sout-transcode-" vlc_module_begin(); -#if defined(MODULE_NAME_is_stream_out_transcodealtivec) \ - || (defined(CAN_COMPILE_ALTIVEC) && !defined(NO_ALTIVEC_IN_FFMPEG)) - set_description( _("AltiVec transcode stream output") ); - add_requirement( ALTIVEC ); - set_capability( "sout stream", 51 ); -#else set_description( _("Transcode stream output") ); set_capability( "sout stream", 50 ); -#endif add_shortcut( "transcode" ); set_callbacks( Open, Close ); @@ -219,6 +201,9 @@ static void transcode_audio_close ( sout_stream_t *, sout_stream_id_t * ); static int transcode_audio_process( sout_stream_t *, sout_stream_id_t *, block_t *, block_t ** ); +static aout_buffer_t *audio_new_buffer( decoder_t *, int ); +static void audio_del_buffer( decoder_t *, aout_buffer_t * ); + static int transcode_video_new ( sout_stream_t *, sout_stream_id_t * ); static void transcode_video_close ( sout_stream_t *, sout_stream_id_t * ); static int transcode_video_encoder_open( sout_stream_t *, sout_stream_id_t *); @@ -477,9 +462,6 @@ static int Open( vlc_object_t *p_this ) p_stream->pf_send = Send; p_stream->p_sys = p_sys; - avcodec_init(); - avcodec_register_all(); - return VLC_SUCCESS; } @@ -552,8 +534,6 @@ struct sout_stream_id_t { vlc_fourcc_t b_transcode; - unsigned int i_inter_pixfmt; /* intermediary format when transcoding */ - /* id of the out stream */ void *id; @@ -567,25 +547,6 @@ struct sout_stream_id_t /* Encoder */ encoder_t *p_encoder; - /* ffmpeg part */ - AVCodec *ff_dec; - AVCodecContext *ff_dec_c; - - mtime_t i_dts; - mtime_t i_length; - - int i_buffer; - int i_buffer_pos; - uint8_t *p_buffer; - - AVFrame *p_ff_pic; - AVFrame *p_ff_pic_tmp0; /* to do deinterlace */ - AVFrame *p_ff_pic_tmp1; /* to do pix conversion */ - AVFrame *p_ff_pic_tmp2; /* to do resample */ - AVFrame *p_ff_pic_tmp3; /* to do subpicture overlay */ - - ImgReSampleContext *p_vresample; - /* Sync */ date_t interpolated_pts; mtime_t i_initial_pts; @@ -821,7 +782,6 @@ static int Send( sout_stream_t *p_stream, sout_stream_id_t *id, { case AUDIO_ES: transcode_audio_process( p_stream, id, p_buffer, &p_out ); - block_Release( p_buffer ); break; case VIDEO_ES: @@ -850,39 +810,25 @@ static int Send( sout_stream_t *p_stream, sout_stream_id_t *id, } /**************************************************************************** - * ffmpeg decoder reencoder part + * decoder reencoder part ****************************************************************************/ -static struct +int audio_BitsPerSample( vlc_fourcc_t i_format ) { - vlc_fourcc_t i_fcc; - int i_ff_codec; - -} fourcc_to_ff_code[] = -{ - /* audio */ - { VLC_FOURCC( 'm', 'p', 'g', 'a' ), CODEC_ID_MP2 }, - { VLC_FOURCC( 'm', 'p', '3', ' ' ), CODEC_ID_MP3LAME }, - { VLC_FOURCC( 'm', 'p', '4', 'a' ), CODEC_ID_AAC }, - { VLC_FOURCC( 'a', '5', '2', ' ' ), CODEC_ID_AC3 }, - { VLC_FOURCC( 'a', 'c', '3', ' ' ), CODEC_ID_AC3 }, - { VLC_FOURCC( 'w', 'm', 'a', '1' ), CODEC_ID_WMAV1 }, - { VLC_FOURCC( 'w', 'm', 'a', '2' ), CODEC_ID_WMAV2 }, - { VLC_FOURCC( 'v', 'o', 'r', 'b' ), CODEC_ID_VORBIS }, - { VLC_FOURCC( 'a', 'l', 'a', 'w' ), CODEC_ID_PCM_ALAW }, - - { VLC_FOURCC( 0, 0, 0, 0 ), 0 } -}; - -static inline int get_ff_codec( vlc_fourcc_t i_fcc ) -{ - int i; - - for( i = 0; fourcc_to_ff_code[i].i_fcc != 0; i++ ) + switch( i_format ) { - if( fourcc_to_ff_code[i].i_fcc == i_fcc ) - { - return fourcc_to_ff_code[i].i_ff_codec; - } + case VLC_FOURCC('u','8',' ',' '): + case VLC_FOURCC('s','8',' ',' '): + return 1; + + case VLC_FOURCC('u','1','6','l'): + case VLC_FOURCC('s','1','6','l'): + case VLC_FOURCC('u','1','6','b'): + case VLC_FOURCC('s','1','6','b'): + return 2; + + case VLC_FOURCC('f','l','3','2'): + case VLC_FOURCC('f','i','3','2'): + return 4; } return 0; @@ -891,57 +837,37 @@ static inline int get_ff_codec( vlc_fourcc_t i_fcc ) static int transcode_audio_new( sout_stream_t *p_stream, sout_stream_id_t *id ) { - int i_ff_codec; - - if( id->p_decoder->fmt_in.i_codec == VLC_FOURCC('s','1','6','l') || - id->p_decoder->fmt_in.i_codec == VLC_FOURCC('s','1','6','b') || - id->p_decoder->fmt_in.i_codec == VLC_FOURCC('s','8',' ',' ') || - id->p_decoder->fmt_in.i_codec == VLC_FOURCC('u','8',' ',' ') ) - { - id->ff_dec = NULL; + sout_stream_sys_t *p_sys = p_stream->p_sys; - id->ff_dec_c = avcodec_alloc_context(); - id->ff_dec_c->sample_rate = id->p_decoder->fmt_in.audio.i_rate; - id->ff_dec_c->channels = id->p_decoder->fmt_in.audio.i_channels; - id->ff_dec_c->block_align = id->p_decoder->fmt_in.audio.i_blockalign; - id->ff_dec_c->bit_rate = id->p_decoder->fmt_in.i_bitrate; - } - else - { - /* find decoder */ - i_ff_codec = get_ff_codec( id->p_decoder->fmt_in.i_codec ); - if( i_ff_codec == 0 ) - { - msg_Err( p_stream, "cannot find decoder id" ); - return VLC_EGENERIC; - } + /* + * Open decoder + */ - id->ff_dec = avcodec_find_decoder( i_ff_codec ); - if( !id->ff_dec ) - { - msg_Err( p_stream, "cannot find decoder (avcodec)" ); - return VLC_EGENERIC; - } + /* Initialization of decoder structures */ + id->p_decoder->pf_decode_audio = 0; + id->p_decoder->pf_aout_buffer_new = audio_new_buffer; + id->p_decoder->pf_aout_buffer_del = audio_del_buffer; + //id->p_decoder->p_cfg = p_sys->p_video_cfg; - id->ff_dec_c = avcodec_alloc_context(); - id->ff_dec_c->sample_rate = id->p_decoder->fmt_in.audio.i_rate; - id->ff_dec_c->channels = id->p_decoder->fmt_in.audio.i_channels; - id->ff_dec_c->block_align = id->p_decoder->fmt_in.audio.i_blockalign; - id->ff_dec_c->bit_rate = id->p_decoder->fmt_in.i_bitrate; + id->p_decoder->p_module = + module_Need( id->p_decoder, "decoder", "$codec", 0 ); - id->ff_dec_c->extradata_size = id->p_decoder->fmt_in.i_extra; - id->ff_dec_c->extradata = id->p_decoder->fmt_in.p_extra; - if( avcodec_open( id->ff_dec_c, id->ff_dec ) ) - { - msg_Err( p_stream, "cannot open decoder" ); - av_free( id->ff_dec_c ); - return VLC_EGENERIC; - } + if( !id->p_decoder->p_module ) + { + msg_Err( p_stream, "cannot find decoder" ); + return VLC_EGENERIC; } + id->p_decoder->fmt_out.audio.i_bitspersample = + audio_BitsPerSample( id->p_decoder->fmt_out.i_codec ); - id->i_buffer = 2 * AVCODEC_MAX_AUDIO_FRAME_SIZE; - id->i_buffer_pos = 0; - id->p_buffer = malloc( id->i_buffer ); + /* + * Open encoder + */ + + /* Initialization of encoder format structures */ + es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat, + id->p_decoder->fmt_out.i_codec ); + id->p_encoder->fmt_in.audio.i_format = id->p_decoder->fmt_out.i_codec; /* Sanity check for audio channels */ id->p_encoder->fmt_out.audio.i_channels = @@ -962,17 +888,78 @@ static int transcode_audio_new( sout_stream_t *p_stream, id->p_encoder->p_cfg = p_stream->p_sys->p_audio_cfg; id->p_encoder->p_module = - module_Need( id->p_encoder, "encoder", - p_stream->p_sys->psz_aenc, VLC_TRUE ); + module_Need( id->p_encoder, "encoder", p_sys->psz_aenc, VLC_TRUE ); if( !id->p_encoder->p_module ) { - vlc_object_detach( id->p_encoder ); - vlc_object_destroy( id->p_encoder ); - msg_Err( p_stream, "cannot open encoder" ); - av_free( id->ff_dec_c ); + msg_Err( p_stream, "cannot find encoder" ); + module_Unneed( id->p_decoder, id->p_decoder->p_module ); + id->p_decoder->p_module = 0; return VLC_EGENERIC; } + /* Check if we need a filter for chroma conversion or resizing */ + if( id->p_decoder->fmt_out.i_codec != + id->p_encoder->fmt_in.i_codec ) + { + id->pp_filter[0] = + vlc_object_create( p_stream, VLC_OBJECT_FILTER ); + vlc_object_attach( id->pp_filter[0], p_stream ); + + id->pp_filter[0]->pf_audio_buffer_new = __block_New; + + id->pp_filter[0]->fmt_in = id->p_decoder->fmt_out; + id->pp_filter[0]->fmt_out = id->p_encoder->fmt_in; + id->pp_filter[0]->p_module = + module_Need( id->pp_filter[0], "audio filter2", 0, 0 ); + if( id->pp_filter[0]->p_module ) id->i_filter++; + else + { + msg_Dbg( p_stream, "no audio filter found" ); + vlc_object_detach( id->pp_filter[0] ); + vlc_object_destroy( id->pp_filter[0] ); + module_Unneed( id->p_decoder, id->p_decoder->p_module ); + id->p_decoder->p_module = 0; + module_Unneed( id->p_encoder, id->p_encoder->p_module ); + id->p_encoder->p_module = 0; + return VLC_EGENERIC; + } + + /* Try a 2 stage conversion */ + if( id->pp_filter[0]->fmt_out.i_codec != + id->p_encoder->fmt_in.i_codec ) + { + id->pp_filter[1] = + vlc_object_create( p_stream, VLC_OBJECT_FILTER ); + vlc_object_attach( id->pp_filter[1], p_stream ); + + id->pp_filter[1]->pf_audio_buffer_new = __block_New; + + id->pp_filter[1]->fmt_in = id->pp_filter[0]->fmt_out; + id->pp_filter[1]->fmt_out = id->p_encoder->fmt_in; + id->pp_filter[1]->p_module = + module_Need( id->pp_filter[1], "audio filter2", 0, 0 ); + if( !id->pp_filter[1]->p_module || + id->pp_filter[1]->fmt_out.i_codec != + id->p_encoder->fmt_in.i_codec ) + { + msg_Dbg( p_stream, "no audio filter found" ); + module_Unneed( id->pp_filter[0], id->pp_filter[0]->p_module ); + vlc_object_detach( id->pp_filter[0] ); + vlc_object_destroy( id->pp_filter[0] ); + if( id->pp_filter[1]->p_module ) + module_Unneed( id->pp_filter[0], id->pp_filter[0]->p_module ); + vlc_object_detach( id->pp_filter[1] ); + vlc_object_destroy( id->pp_filter[1] ); + module_Unneed( id->p_decoder, id->p_decoder->p_module ); + id->p_decoder->p_module = 0; + module_Unneed( id->p_encoder, id->p_encoder->p_module ); + id->p_encoder->p_module = 0; + return VLC_EGENERIC; + } + else id->i_filter++; + } + } + /* FIXME: Hack for mp3 transcoding support */ if( id->p_encoder->fmt_out.i_codec == VLC_FOURCC( 'm','p','3',' ' ) ) id->p_encoder->fmt_out.i_codec = VLC_FOURCC( 'm','p','g','a' ); @@ -983,15 +970,24 @@ static int transcode_audio_new( sout_stream_t *p_stream, static void transcode_audio_close( sout_stream_t *p_stream, sout_stream_id_t *id ) { - if( id->ff_dec ) avcodec_close( id->ff_dec_c ); - av_free( id->ff_dec_c ); + int i; - module_Unneed( id->p_encoder, id->p_encoder->p_module ); + /* Close decoder */ + if( id->p_decoder->p_module ) + module_Unneed( id->p_decoder, id->p_decoder->p_module ); - vlc_object_detach( id->p_encoder ); - vlc_object_destroy( id->p_encoder ); + /* Close encoder */ + if( id->p_encoder->p_module ) + module_Unneed( id->p_encoder, id->p_encoder->p_module ); - free( id->p_buffer ); + /* Close filters */ + for( i = 0; i < id->i_filter; i++ ) + { + vlc_object_detach( id->pp_filter[i] ); + if( id->pp_filter[i]->p_module ) + module_Unneed( id->pp_filter[i], id->pp_filter[i]->p_module ); + vlc_object_destroy( id->pp_filter[i] ); + } } static int transcode_audio_process( sout_stream_t *p_stream, @@ -999,227 +995,99 @@ static int transcode_audio_process( sout_stream_t *p_stream, block_t *in, block_t **out ) { sout_stream_sys_t *p_sys = p_stream->p_sys; - aout_buffer_t aout_buf; - block_t *p_block; - int i_buffer = in->i_buffer; - char *p_buffer = in->p_buffer; - id->i_dts = in->i_dts; + aout_buffer_t *p_audio_buf; + block_t *p_block, *p_audio_block; + int i; *out = NULL; - while( i_buffer ) + while( (p_audio_buf = id->p_decoder->pf_decode_audio( id->p_decoder, + &in )) ) { - id->i_buffer_pos = 0; - - /* decode as much data as possible */ - if( id->ff_dec ) - { - int i_used; - - i_used = avcodec_decode_audio( id->ff_dec_c, - (int16_t*)id->p_buffer, &id->i_buffer_pos, - p_buffer, i_buffer ); - -#if 0 - msg_Warn( p_stream, "avcodec_decode_audio: %d used on %d", - i_used, i_buffer ); -#endif - if( i_used < 0 ) - { - msg_Warn( p_stream, "error audio decoding"); - break; - } - - i_buffer -= i_used; - p_buffer += i_used; - - if ( id->i_buffer_pos < 0 ) - { - msg_Warn( p_stream, "weird error audio decoding"); - break; - } - } - else - { - int16_t *sout = (int16_t*)id->p_buffer; - vlc_fourcc_t i_codec = id->p_decoder->fmt_in.i_codec; - - if( i_codec == VLC_FOURCC('s','8',' ',' ') || - i_codec == VLC_FOURCC('u','8',' ',' ') ) - { - int8_t *sin = (int8_t*)p_buffer; - int i_used = __MIN( id->i_buffer/2, i_buffer ); - int i_samples = i_used; - - if( i_codec == VLC_FOURCC('s','8',' ',' ') ) - while( i_samples > 0 ) - { - *sout++ = ( *sin++ ) << 8; - i_samples--; - } - else - while( i_samples > 0 ) - { - *sout++ = ( *sin++ - 128 ) << 8; - i_samples--; - } - - i_buffer -= i_used; - p_buffer += i_used; - id->i_buffer_pos = i_used * 2; - } - else if( i_codec == VLC_FOURCC('s','1','6','l') || - i_codec == VLC_FOURCC('s','1','6','b') ) - { - int16_t *sin = (int16_t*)p_buffer; - int i_used = __MIN( id->i_buffer, i_buffer ); - int i_samples = i_used / 2; - - /* first copy */ - memcpy( sout, sin, i_used ); - -#ifdef WORDS_BIGENDIAN - if( i_codec == VLC_FOURCC('s','1','6','l') ) -#else - if( i_codec == VLC_FOURCC('s','1','6','b') ) -#endif - { - uint8_t *dat = (uint8_t*)sout; - - while( i_samples > 0 ) - { - uint8_t tmp; - tmp = dat[0]; - dat[0] = dat[1]; - dat[1] = tmp; - - dat += 2; - - i_samples--; - } - } - - i_buffer -= i_used; - p_buffer += i_used; - id->i_buffer_pos = i_used; - } - } - - if( id->i_buffer_pos == 0 ) continue; - - aout_buf.p_buffer = id->p_buffer; - aout_buf.i_nb_bytes = id->i_buffer_pos; - aout_buf.i_nb_samples = id->i_buffer_pos / 2 / - id->p_decoder->fmt_in.audio.i_channels; - aout_buf.start_date = id->i_dts; - aout_buf.end_date = id->i_dts; - if( p_sys->b_audio_sync ) { - aout_buf.start_date = date_Get( &id->interpolated_pts ) + 1; - p_sys->i_master_drift = id->i_dts - aout_buf.start_date; - date_Increment( &id->interpolated_pts, aout_buf.i_nb_samples ); + mtime_t i_dts = date_Get( &id->interpolated_pts ) + 1; + p_sys->i_master_drift = p_audio_buf->start_date - i_dts; + date_Increment( &id->interpolated_pts, p_audio_buf->i_nb_samples ); + p_audio_buf->start_date -= p_sys->i_master_drift; + p_audio_buf->end_date -= p_sys->i_master_drift; } - id->i_dts += ( I64C(1000000) * id->i_buffer_pos / 2 / - id->p_decoder->fmt_in.audio.i_channels / - id->p_decoder->fmt_in.audio.i_rate ); + p_audio_block = p_audio_buf->p_sys; + p_audio_block->i_buffer = p_audio_buf->i_nb_bytes; + p_audio_block->i_dts = p_audio_block->i_pts = + p_audio_buf->start_date; + p_audio_block->i_length = p_audio_buf->end_date - + p_audio_buf->start_date; + p_audio_block->i_samples = p_audio_buf->i_nb_samples; - if( id->p_encoder->fmt_in.audio.i_channels == 1 && - id->p_decoder->fmt_in.audio.i_channels > 1 ) + /* Run filter chain */ + for( i = 0; i < id->i_filter; i++ ) { - int16_t *p_sample = (int16_t *)aout_buf.p_buffer; - int i_src_c = id->p_decoder->fmt_in.audio.i_channels; - unsigned int i; - - for( i = 0; i < aout_buf.i_nb_samples; i++ ) - { - int j, c = 0; - - for( j = 1; j < i_src_c; j++ ) - { - c += p_sample[i_src_c * i + j]; - } - p_sample[i] = c / (i_src_c-1); - } - aout_buf.i_nb_bytes = i * 2; + p_audio_block = + id->pp_filter[i]->pf_audio_filter( id->pp_filter[i], + p_audio_block ); } - else if( id->p_encoder->fmt_in.audio.i_channels == 2 && - id->p_decoder->fmt_in.audio.i_channels > 2 ) - { - int i_src_c = id->p_decoder->fmt_in.audio.i_channels; - unsigned int i; - static const float mixf_l[4][6] =/* [i_src_c - 3][channel index] */ - { - { 0.00, 1.00, 0.00, 0.00, 0.00, 0.00 }, /* 3 channels */ - { 0.00, 0.50, 0.50, 0.00, 0.00, 0.00 }, /* 4 channels */ - { 0.00, 0.50, 0.00, 0.50, 0.00, 0.00 }, /* 5 channels */ - { 0.00, 0.34, 0.33, 0.00, 0.33, 0.00 }, /* 6 channels */ - }; - static const float mixf_r[4][6] =/* [i_src_c - 3][channel index] */ - { - { 0.00, 1.00, 0.00, 0.00, 0.00, 0.00 }, /* 3 channels */ - { 0.00, 0.00, 0.50, 0.50, 0.00, 0.00 }, /* 4 channels */ - { 0.00, 0.00, 0.50, 0.00, 0.50, 0.00 }, /* 5 channels */ - { 0.00, 0.00, 0.33, 0.34, 0.00, 0.33 }, /* 6 channels */ - }; + p_audio_buf->p_buffer = p_audio_block->p_buffer; + p_audio_buf->i_nb_bytes = p_audio_block->i_buffer; + p_audio_buf->i_nb_samples = p_audio_block->i_samples; + p_audio_buf->start_date = p_audio_block->i_dts; + p_audio_buf->end_date = p_audio_block->i_dts + p_audio_block->i_length; + p_block = id->p_encoder->pf_encode_audio( id->p_encoder, p_audio_buf ); + block_ChainAppend( out, p_block ); + block_Release( p_audio_block ); + free( p_audio_buf ); + } - for( i = 0; i < aout_buf.i_nb_samples; i++ ) - { - int16_t *p_src = (int16_t *)aout_buf.p_buffer + i_src_c * i; - int16_t *p_dst = (int16_t *)aout_buf.p_buffer + 2 * i; + return VLC_SUCCESS; +} - int j; - float l = 0.0, r = 0.0; - for( j = 0; j < i_src_c; j++ ) - { - l += mixf_l[i_src_c-3][j] * p_src[j]; - r += mixf_r[i_src_c-3][j] * p_src[j]; - } +static void audio_release_buffer( aout_buffer_t *p_buffer ) +{ + if( p_buffer && p_buffer->p_sys ) block_Release( p_buffer->p_sys ); + if( p_buffer ) free( p_buffer ); +} - p_dst[0] = (int)( l + 0.5 ); - p_dst[1] = (int)( r + 0.5 ); - } - aout_buf.i_nb_bytes = i * 2 * 2; - } - else if( id->p_decoder->fmt_in.audio.i_channels != - id->p_encoder->fmt_in.audio.i_channels ) - { - unsigned int i; - int j; - - /* This is for liba52 which is what ffmpeg uses to decode ac3 */ - static const int translation[7][6] = - {{ 0, 0, 0, 0, 0, 0 }, /* 0 channels (rarely used) */ - { 0, 0, 0, 0, 0, 0 }, /* 1 ch */ - { 0, 1, 0, 0, 0, 0 }, /* 2 */ - { 1, 2, 0, 0, 0, 0 }, /* 3 */ - { 1, 3, 2, 0, 0, 0 }, /* 4 */ - { 1, 3, 4, 2, 0, 0 }, /* 5 */ - { 1, 3, 4, 5, 2, 0 }}; /* 6 */ - - /* dumb downmixing */ - for( i = 0; i < aout_buf.i_nb_samples; i++ ) - { - uint16_t *p_buffer = (uint16_t *)aout_buf.p_buffer; - for( j = 0 ; j < id->p_encoder->fmt_in.audio.i_channels; j++ ) - { - p_buffer[i*id->p_encoder->fmt_in.audio.i_channels+j] = - p_buffer[i*id->p_decoder->fmt_in.audio.i_channels + - translation[id->p_decoder->fmt_in.audio.i_channels][j]]; - } - } - aout_buf.i_nb_bytes = i*id->p_encoder->fmt_in.audio.i_channels * 2; - } +static aout_buffer_t *audio_new_buffer( decoder_t *p_dec, int i_samples ) +{ + aout_buffer_t *p_buffer; + block_t *p_block; + int i_size; - p_block = id->p_encoder->pf_encode_audio( id->p_encoder, &aout_buf ); - block_ChainAppend( out, p_block ); + if( p_dec->fmt_out.audio.i_bitspersample ) + { + i_size = i_samples * p_dec->fmt_out.audio.i_bitspersample * + p_dec->fmt_out.audio.i_channels; + } + else if( p_dec->fmt_out.audio.i_bytes_per_frame && + p_dec->fmt_out.audio.i_frame_length ) + { + i_size = i_samples * p_dec->fmt_out.audio.i_bytes_per_frame / + p_dec->fmt_out.audio.i_frame_length; + } + else + { + i_size = i_samples * 4 * p_dec->fmt_out.audio.i_channels; } - return VLC_SUCCESS; + p_buffer = malloc( sizeof(aout_buffer_t) ); + p_buffer->pf_release = audio_release_buffer; + p_buffer->p_sys = p_block = block_New( p_dec, i_size ); + + p_buffer->p_buffer = p_block->p_buffer; + p_buffer->i_size = p_buffer->i_nb_bytes = p_block->i_buffer; + p_buffer->i_nb_samples = i_samples; + p_block->i_samples = i_samples; + + return p_buffer; } +static void audio_del_buffer( decoder_t *p_dec, aout_buffer_t *p_buffer ) +{ + if( p_buffer && p_buffer->p_sys ) block_Release( p_buffer->p_sys ); + if( p_buffer ) free( p_buffer ); +} /* * video -- 2.39.5