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])
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
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,
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,
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])
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
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])
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
#include <mad.h>
#include <vlc/vlc.h>
-#include "audio_output.h"
+#include <vlc/decoder.h>
#include "aout_internal.h"
+#include "vlc_filter.h"
/*****************************************************************************
* Local prototypes
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;
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'))
}
/* 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" );
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) *
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-- )
/*****************************************************************************
* 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 );
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;
+}
--- /dev/null
+/*****************************************************************************
+ * format.c : PCM format converter
+ *****************************************************************************
+ * Copyright (C) 2002 VideoLAN
+ * $Id: float32tos16.c 8391 2004-08-06 17:28:36Z sam $
+ *
+ * Authors: Christophe Massiot <massiot@via.ecp.fr>
+ * Gildas Bazin <gbazin@videolan.org>
+ *
+ * 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 <stdlib.h> /* malloc(), free() */
+#include <string.h>
+
+#include <vlc/vlc.h>
+#include <vlc/decoder.h>
+#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;
+}
#include "vlc_filter.h"
#include "osd.h"
-/* ffmpeg header */
-#ifdef HAVE_FFMPEG_AVCODEC_H
-# include <ffmpeg/avcodec.h>
-#else
-# include <avcodec.h>
-#endif
-
-#if LIBAVCODEC_BUILD < 4704
-# define AV_NOPTS_VALUE 0
-#endif
-
/*****************************************************************************
* Module descriptor
*****************************************************************************/
#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 );
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 *);
p_stream->pf_send = Send;
p_stream->p_sys = p_sys;
- avcodec_init();
- avcodec_register_all();
-
return VLC_SUCCESS;
}
{
vlc_fourcc_t b_transcode;
- unsigned int i_inter_pixfmt; /* intermediary format when transcoding */
-
/* id of the out stream */
void *id;
/* 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;
{
case AUDIO_ES:
transcode_audio_process( p_stream, id, p_buffer, &p_out );
- block_Release( p_buffer );
break;
case VIDEO_ES:
}
/****************************************************************************
- * 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;
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 =
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' );
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,
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