Commit 2a24c87b authored by Gildas Bazin's avatar Gildas Bazin

* 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.
parent 95977003
...@@ -440,7 +440,7 @@ AC_CHECK_LIB(m,cos,[ ...@@ -440,7 +440,7 @@ AC_CHECK_LIB(m,cos,[
VLC_ADD_LDFLAGS([adjust distort a52tofloat32 dtstofloat32 x264],[-lm]) VLC_ADD_LDFLAGS([adjust distort a52tofloat32 dtstofloat32 x264],[-lm])
]) ])
AC_CHECK_LIB(m,pow,[ 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,[ AC_CHECK_LIB(m,sqrt,[
VLC_ADD_LDFLAGS([headphone_channel_mixer normvol],[-lm]) VLC_ADD_LDFLAGS([headphone_channel_mixer normvol],[-lm])
...@@ -1175,7 +1175,7 @@ then ...@@ -1175,7 +1175,7 @@ then
VLC_ADD_PLUGINS([packetizer_copy]) 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_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]) # VLC_ADD_PLUGINS([stream_out_transrate])
dnl Ogg and vorbis are handled in their respective section dnl Ogg and vorbis are handled in their respective section
...@@ -1818,25 +1818,18 @@ then ...@@ -1818,25 +1818,18 @@ then
then then
AC_CHECK_HEADERS(ffmpeg/avcodec.h) AC_CHECK_HEADERS(ffmpeg/avcodec.h)
AC_CHECK_HEADERS(postproc/postprocess.h) AC_CHECK_HEADERS(postproc/postprocess.h)
VLC_ADD_PLUGINS([ffmpeg stream_out_transcode]) VLC_ADD_PLUGINS([ffmpeg])
VLC_ADD_CFLAGS([ffmpeg stream_out_transcode],[`${FFMPEG_CONFIG} --cflags`]) VLC_ADD_CFLAGS([ffmpeg],[`${FFMPEG_CONFIG} --cflags`])
VLC_ADD_LDFLAGS([ffmpeg],[`${FFMPEG_CONFIG} --plugin-libs avcodec avformat postproc`]) VLC_ADD_LDFLAGS([ffmpeg],[`${FFMPEG_CONFIG} --plugin-libs avcodec avformat postproc`])
VLC_ADD_LDFLAGS([stream_out_transcode],[`${FFMPEG_CONFIG} --libs avcodec`])
else else
AC_ARG_WITH(ffmpeg-mp3lame, AC_ARG_WITH(ffmpeg-mp3lame,
[ --with-ffmpeg-mp3lame if ffmpeg has been compiled with mp3lame support], [ --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]) ]) VLC_ADD_LDFLAGS([ffmpeg],[-lmp3lame]) ])
AC_ARG_WITH(ffmpeg-faac, AC_ARG_WITH(ffmpeg-faac,
[ --with-ffmpeg-faac if ffmpeg has been compiled with faac support], [ --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]) ]) VLC_ADD_LDFLAGS([ffmpeg],[-lfaac]) ])
AC_ARG_WITH(ffmpeg-tree, AC_ARG_WITH(ffmpeg-tree,
...@@ -1851,11 +1844,8 @@ then ...@@ -1851,11 +1844,8 @@ then
AC_CHECK_HEADERS(ffmpeg/avcodec.h, [], [AC_MSG_ERROR([Missing header file ffmpeg/avcodec.h.])] ) 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_HEADERS(postproc/postprocess.h, [], [AC_MSG_ERROR([Missing header file postproc/postprocess.h.])] )
AC_CHECK_LIB(avcodec, avcodec_init, [ AC_CHECK_LIB(avcodec, avcodec_init, [
VLC_ADD_BUILTINS([ffmpeg stream_out_transcode]) VLC_ADD_BUILTINS([ffmpeg])
VLC_ADD_LDFLAGS([ffmpeg],[-lavcodec]) 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_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_CHECK_LIB(avformat, av_open_input_stream, [
AC_DEFINE(HAVE_LIBAVFORMAT, 1, AC_DEFINE(HAVE_LIBAVFORMAT, 1,
...@@ -1888,7 +1878,7 @@ then ...@@ -1888,7 +1878,7 @@ then
fi fi
dnl Use a custom libffmpeg dnl Use a custom libffmpeg
AC_MSG_RESULT(${real_ffmpeg_tree}/libavcodec/libavcodec.a) 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_LDFLAGS([ffmpeg],[-L${real_ffmpeg_tree}/libavcodec -lavcodec])
VLC_ADD_CPPFLAGS([ffmpeg],[-I${real_ffmpeg_tree}/libavcodec -I${real_ffmpeg_tree}/libavformat]) VLC_ADD_CPPFLAGS([ffmpeg],[-I${real_ffmpeg_tree}/libavcodec -I${real_ffmpeg_tree}/libavformat])
...@@ -1897,11 +1887,6 @@ then ...@@ -1897,11 +1887,6 @@ then
VLC_ADD_LDFLAGS([ffmpeg],[-L${real_ffmpeg_tree}/libavformat -lavformat -lz]) VLC_ADD_LDFLAGS([ffmpeg],[-L${real_ffmpeg_tree}/libavformat -lavformat -lz])
VLC_ADD_CPPFLAGS([ffmpeg],[-I${real_ffmpeg_tree}/libavformat]) VLC_ADD_CPPFLAGS([ffmpeg],[-I${real_ffmpeg_tree}/libavformat])
fi 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
fi fi
...@@ -1933,7 +1918,7 @@ then ...@@ -1933,7 +1918,7 @@ then
fi fi
dnl Use a custom libffmpeg dnl Use a custom libffmpeg
AC_MSG_RESULT(${real_ffmpeg_tree}/libavcodec/libavcodecaltivec.a) 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_LDFLAGS([ffmpegaltivec],[-L${real_ffmpeg_tree}/libavcodec -lavcodecaltivec])
VLC_ADD_CPPFLAGS([ffmpeg],[-DNO_ALTIVEC_IN_FFMPEG]) VLC_ADD_CPPFLAGS([ffmpeg],[-DNO_ALTIVEC_IN_FFMPEG])
VLC_ADD_CPPFLAGS([ffmpegaltivec],[-I${real_ffmpeg_tree}/libavcodec -I${real_ffmpeg_tree}/libavformat]) VLC_ADD_CPPFLAGS([ffmpegaltivec],[-I${real_ffmpeg_tree}/libavcodec -I${real_ffmpeg_tree}/libavformat])
...@@ -1943,12 +1928,6 @@ then ...@@ -1943,12 +1928,6 @@ then
VLC_ADD_LDFLAGS([ffmpegaltivec],[-L${real_ffmpeg_tree}/libavformat -lavformataltivec -lz]) VLC_ADD_LDFLAGS([ffmpegaltivec],[-L${real_ffmpeg_tree}/libavformat -lavformataltivec -lz])
VLC_ADD_CPPFLAGS([ffmpegaltivec],[-I${real_ffmpeg_tree}/libavformat]) VLC_ADD_CPPFLAGS([ffmpegaltivec],[-I${real_ffmpeg_tree}/libavformat])
fi 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
fi fi
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* audio_output.h : audio output interface * audio_output.h : audio output interface
***************************************************************************** *****************************************************************************
* Copyright (C) 2002 VideoLAN * Copyright (C) 2002 VideoLAN
* $Id: audio_output.h,v 1.86 2003/11/20 22:10:55 fenrir Exp $ * $Id$
* *
* Authors: Christophe Massiot <massiot@via.ecp.fr> * Authors: Christophe Massiot <massiot@via.ecp.fr>
* *
...@@ -129,6 +129,13 @@ struct aout_buffer_t ...@@ -129,6 +129,13 @@ struct aout_buffer_t
mtime_t start_date, end_date; mtime_t start_date, end_date;
struct aout_buffer_t * p_next; 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. */ /* Size of a frame for S/PDIF output. */
......
...@@ -74,6 +74,7 @@ struct block_t ...@@ -74,6 +74,7 @@ struct block_t
mtime_t i_dts; mtime_t i_dts;
mtime_t i_length; mtime_t i_length;
int i_samples; /* Used for audio */
int i_rate; int i_rate;
int i_buffer; int i_buffer;
......
...@@ -74,6 +74,14 @@ struct audio_format_t ...@@ -74,6 +74,14 @@ struct audio_format_t
int i_bitspersample; 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 * video format description
*/ */
...@@ -202,8 +210,10 @@ static inline void es_format_Copy( es_format_t *dst, es_format_t *src ) ...@@ -202,8 +210,10 @@ static inline void es_format_Copy( es_format_t *dst, es_format_t *src )
if( src->video.p_palette ) if( src->video.p_palette )
{ {
dst->video.p_palette = (video_palette_t*)malloc( sizeof( video_palette_t ) ); dst->video.p_palette =
memcpy( dst->video.p_palette, src->video.p_palette, sizeof( video_palette_t ) ); (video_palette_t*)malloc( sizeof( video_palette_t ) );
memcpy( dst->video.p_palette, src->video.p_palette,
sizeof( video_palette_t ) );
} }
} }
......
...@@ -51,10 +51,11 @@ struct filter_t ...@@ -51,10 +51,11 @@ struct filter_t
/* Output format of filter */ /* Output format of filter */
es_format_t fmt_out; 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 *, void ( * pf_video_blend ) ( filter_t *, picture_t *,
picture_t *, picture_t *, picture_t *, picture_t *,
int, int ); int, int );
picture_t * ( * pf_video_filter ) ( filter_t *, picture_t * );
subpicture_t * ( *pf_render_string ) ( filter_t *, block_t * ); subpicture_t * ( *pf_render_string ) ( filter_t *, block_t * );
...@@ -63,8 +64,7 @@ struct filter_t ...@@ -63,8 +64,7 @@ struct filter_t
*/ */
/* Audio output callbacks */ /* Audio output callbacks */
aout_buffer_t * ( * pf_aout_buffer_new) ( filter_t *, int ); block_t * ( * pf_audio_buffer_new) ( filter_t *, int );
void ( * pf_aout_buffer_del) ( filter_t *, aout_buffer_t * );
/* Video output callbacks */ /* Video output callbacks */
picture_t * ( * pf_vout_buffer_new) ( filter_t * ); picture_t * ( * pf_vout_buffer_new) ( filter_t * );
......
SOURCES_equalizer = equalizer.c equalizer_presets.h SOURCES_equalizer = equalizer.c equalizer_presets.h
SOURCES_normvol = normvol.c SOURCES_normvol = normvol.c
SOURCES_format = format.c
...@@ -32,8 +32,9 @@ ...@@ -32,8 +32,9 @@
#include <mad.h> #include <mad.h>
#include <vlc/vlc.h> #include <vlc/vlc.h>
#include "audio_output.h" #include <vlc/decoder.h>
#include "aout_internal.h" #include "aout_internal.h"
#include "vlc_filter.h"
/***************************************************************************** /*****************************************************************************
* Local prototypes * Local prototypes
...@@ -43,10 +44,14 @@ static void Destroy ( vlc_object_t * ); ...@@ -43,10 +44,14 @@ static void Destroy ( vlc_object_t * );
static void DoWork ( aout_instance_t *, aout_filter_t *, aout_buffer_t *, static void DoWork ( aout_instance_t *, aout_filter_t *, aout_buffer_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 * Local structures
*****************************************************************************/ *****************************************************************************/
struct aout_filter_sys_t struct filter_sys_t
{ {
struct mad_stream mad_stream; struct mad_stream mad_stream;
struct mad_frame mad_frame; struct mad_frame mad_frame;
...@@ -60,15 +65,20 @@ vlc_module_begin(); ...@@ -60,15 +65,20 @@ vlc_module_begin();
set_description( _("MPEG audio decoder") ); set_description( _("MPEG audio decoder") );
set_capability( "audio filter", 100 ); set_capability( "audio filter", 100 );
set_callbacks( Create, Destroy ); set_callbacks( Create, Destroy );
add_submodule();
set_description( _("MPEG audio decoder") );
set_capability( "audio filter2", 100 );
set_callbacks( OpenFilter, CloseFilter );
vlc_module_end(); vlc_module_end();
/***************************************************************************** /*****************************************************************************
* Create: * 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; aout_filter_t *p_filter = (aout_filter_t *)p_this;
struct aout_filter_sys_t * p_sys; struct filter_sys_t *p_sys;
if ( (p_filter->input.i_format != VLC_FOURCC('m','p','g','a') if ( (p_filter->input.i_format != VLC_FOURCC('m','p','g','a')
&& p_filter->input.i_format != VLC_FOURCC('m','p','g','3')) && p_filter->input.i_format != VLC_FOURCC('m','p','g','3'))
...@@ -84,7 +94,8 @@ static int Create( vlc_object_t * _p_filter ) ...@@ -84,7 +94,8 @@ static int Create( vlc_object_t * _p_filter )
} }
/* Allocate the memory needed to store the module's structure */ /* 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 ) if( p_sys == NULL )
{ {
msg_Err( p_filter, "out of memory" ); msg_Err( p_filter, "out of memory" );
...@@ -109,7 +120,7 @@ static int Create( vlc_object_t * _p_filter ) ...@@ -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, 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 ) 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_samples = p_in_buf->i_nb_samples;
p_out_buf->i_nb_bytes = p_in_buf->i_nb_samples * sizeof(vlc_fixed_t) * p_out_buf->i_nb_bytes = p_in_buf->i_nb_samples * sizeof(vlc_fixed_t) *
...@@ -206,10 +217,66 @@ static void DoWork( aout_instance_t * p_aout, aout_filter_t * p_filter, ...@@ -206,10 +217,66 @@ static void DoWork( aout_instance_t * p_aout, aout_filter_t * p_filter,
/***************************************************************************** /*****************************************************************************
* Destroy : deallocate data structures * 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_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 );
mad_stream_finish( &p_sys->mad_stream );
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 )
{ {
aout_filter_t * p_filter = (aout_filter_t *)_p_filter; filter_t *p_filter = (filter_t *)p_this;
struct aout_filter_sys_t * p_sys = p_filter->p_sys; filter_sys_t *p_sys = p_filter->p_sys;
mad_synth_finish( &p_sys->mad_synth ); mad_synth_finish( &p_sys->mad_synth );
mad_frame_finish( &p_sys->mad_frame ); mad_frame_finish( &p_sys->mad_frame );
...@@ -217,3 +284,42 @@ static void Destroy( vlc_object_t * _p_filter ) ...@@ -217,3 +284,42 @@ static void Destroy( vlc_object_t * _p_filter )
free( p_sys ); 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;
}
/*****************************************************************************
* 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;
}
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* $Id$ * $Id$
* *
* Authors: Laurent Aimar <fenrir@via.ecp.fr> * Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Gildas Bazin <gbazin@netcourrier.com> * Gildas Bazin <gbazin@videolan.org>
* *
* This program is free software; you can redistribute it and/or modify * 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 * 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, ...@@ -134,26 +134,32 @@ int E_(InitAudioDec)( decoder_t *p_dec, AVCodecContext *p_context,
p_sys->p_samples = NULL; p_sys->p_samples = NULL;
p_sys->i_samples = 0; p_sys->i_samples = 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 ); aout_DateSet( &p_sys->end_date, 0 );
}
/* Set output properties */ /* Set output properties */
p_dec->fmt_out.i_cat = AUDIO_ES; p_dec->fmt_out.i_cat = AUDIO_ES;
p_dec->fmt_out.i_codec = AOUT_FMT_S16_NE; p_dec->fmt_out.i_codec = AOUT_FMT_S16_NE;
p_dec->fmt_out.audio.i_bitspersample = 2;
return VLC_SUCCESS; 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 ) aout_buffer_t *SplitBuffer( decoder_t *p_dec )
{ {
decoder_sys_t *p_sys = p_dec->p_sys; decoder_sys_t *p_sys = p_dec->p_sys;
int i_samples = __MIN( p_sys->i_samples, 4096 ); int i_samples = __MIN( p_sys->i_samples, 4096 );
aout_buffer_t *p_buffer; aout_buffer_t *p_buffer;
if( i_samples == 0 ) if( i_samples == 0 ) return NULL;
{
return NULL;
}
if( ( p_buffer = p_dec->pf_aout_buffer_new( p_dec, i_samples ) ) == NULL ) if( ( p_buffer = p_dec->pf_aout_buffer_new( p_dec, i_samples ) ) == NULL )
{ {
msg_Err( p_dec, "cannot get aout buffer" ); 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 ) ...@@ -189,10 +195,7 @@ aout_buffer_t *E_( DecodeAudio )( decoder_t *p_dec, block_t **pp_block )
{ {
/* More data */ /* More data */
p_buffer = SplitBuffer( p_dec ); p_buffer = SplitBuffer( p_dec );
if( p_buffer == NULL ) if( !p_buffer ) block_Release( p_block );
{
block_Release( p_block );
}
return p_buffer; return p_buffer;
} }
...@@ -203,8 +206,7 @@ aout_buffer_t *E_( DecodeAudio )( decoder_t *p_dec, block_t **pp_block ) ...@@ -203,8 +206,7 @@ aout_buffer_t *E_( DecodeAudio )( decoder_t *p_dec, block_t **pp_block )
return NULL; return NULL;
} }
if( p_block->i_buffer <= 0 || if( p_block->i_buffer <= 0 || p_block->i_flags & BLOCK_FLAG_DISCONTINUITY )
( p_block->i_flags&BLOCK_FLAG_DISCONTINUITY ) )
{ {
block_Release( p_block ); block_Release( p_block );
return NULL; return NULL;
...@@ -264,10 +266,7 @@ aout_buffer_t *E_( DecodeAudio )( decoder_t *p_dec, block_t **pp_block ) ...@@ -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_sys->p_samples = p_sys->p_output;
p_buffer = SplitBuffer( p_dec ); p_buffer = SplitBuffer( p_dec );
if( !p_buffer ) if( !p_buffer ) block_Release( p_block );
{
block_Release( p_block );
}
return p_buffer; return p_buffer;
} }
......
...@@ -3,7 +3,6 @@ SOURCES_stream_out_standard = standard.c \ ...@@ -3,7 +3,6 @@ SOURCES_stream_out_standard = standard.c \
announce.c \ announce.c \
announce.h announce.h
SOURCES_stream_out_transcode = transcode.c SOURCES_stream_out_transcode = transcode.c
SOURCES_stream_out_transcodealtivec = transcode.c
SOURCES_stream_out_duplicate = duplicate.c SOURCES_stream_out_duplicate = duplicate.c
SOURCES_stream_out_es = es.c SOURCES_stream_out_es = es.c
SOURCES_stream_out_display = display.c SOURCES_stream_out_display = display.c
......
...@@ -36,17 +36,6 @@ ...@@ -36,17 +36,6 @@
#include "vlc_filter.h" #include "vlc_filter.h"
#include "osd.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 * Module descriptor
*****************************************************************************/ *****************************************************************************/
...@@ -136,15 +125,8 @@ static void Close( vlc_object_t * ); ...@@ -136,15 +125,8 @@ static void Close( vlc_object_t * );
#define SOUT_CFG_PREFIX "sout-transcode-" #define SOUT_CFG_PREFIX "sout-transcode-"
vlc_module_begin(); 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_description( _("Transcode stream output") );
set_capability( "sout stream", 50 ); set_capability( "sout stream", 50 );
#endif
add_shortcut( "transcode" ); add_shortcut( "transcode" );
set_callbacks( Open, Close ); set_callbacks( Open, Close );
...@@ -219,6 +201,9 @@ static void transcode_audio_close ( sout_stream_t *, sout_stream_id_t * ); ...@@ -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 *, static int transcode_audio_process( sout_stream_t *, sout_stream_id_t *,
block_t *, block_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 int transcode_video_new ( sout_stream_t *, sout_stream_id_t * );
static void transcode_video_close ( 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 *); 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 ) ...@@ -477,9 +462,6 @@ static int Open( vlc_object_t *p_this )
p_stream->pf_send = Send; p_stream->pf_send = Send;
p_stream->p_sys = p_sys; p_stream->p_sys = p_sys;
avcodec_init();
avcodec_register_all();
return VLC_SUCCESS; return VLC_SUCCESS;
} }
...@@ -552,8 +534,6 @@ struct sout_stream_id_t ...@@ -552,8 +534,6 @@ struct sout_stream_id_t
{ {
vlc_fourcc_t b_transcode; vlc_fourcc_t b_transcode;
unsigned int i_inter_pixfmt; /* intermediary format when transcoding */
/* id of the out stream */ /* id of the out stream */
void *id; void *id;
...@@ -567,25 +547,6 @@ struct sout_stream_id_t ...@@ -567,25 +547,6 @@ struct sout_stream_id_t
/* Encoder */ /* Encoder */
encoder_t *p_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 */ /* Sync */
date_t interpolated_pts; date_t interpolated_pts;
mtime_t i_initial_pts; mtime_t i_initial_pts;
...@@ -821,7 +782,6 @@ static int Send( sout_stream_t *p_stream, sout_stream_id_t *id, ...@@ -821,7 +782,6 @@ static int Send( sout_stream_t *p_stream, sout_stream_id_t *id,
{ {
case AUDIO_ES: case AUDIO_ES:
transcode_audio_process( p_stream, id, p_buffer, &p_out ); transcode_audio_process( p_stream, id, p_buffer, &p_out );
block_Release( p_buffer );
break; break;
case VIDEO_ES: case VIDEO_ES:
...@@ -850,39 +810,25 @@ static int Send( sout_stream_t *p_stream, sout_stream_id_t *id, ...@@ -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; switch( i_format )
int i_ff_codec; {
case VLC_FOURCC('u','8',' ',' '):
} fourcc_to_ff_code[] = case VLC_FOURCC('s','8',' ',' '):
{ return 1;
/* 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 ) case VLC_FOURCC('u','1','6','l'):
{ case VLC_FOURCC('s','1','6','l'):
int i; case VLC_FOURCC('u','1','6','b'):
case VLC_FOURCC('s','1','6','b'):
return 2;
for( i = 0; fourcc_to_ff_code[i].i_fcc != 0; i++ ) case VLC_FOURCC('f','l','3','2'):
{ case VLC_FOURCC('f','i','3','2'):
if( fourcc_to_ff_code[i].i_fcc == i_fcc ) return 4;
{
return fourcc_to_ff_code[i].i_ff_codec;
}
} }
return 0; return 0;
...@@ -891,57 +837,37 @@ static inline int get_ff_codec( vlc_fourcc_t i_fcc ) ...@@ -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, static int transcode_audio_new( sout_stream_t *p_stream,
sout_stream_id_t *id ) sout_stream_id_t *id )
{ {
int i_ff_codec; sout_stream_sys_t *p_sys = p_stream->p_sys;
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;
id->ff_dec_c = avcodec_alloc_context(); /*
id->ff_dec_c->sample_rate = id->p_decoder->fmt_in.audio.i_rate; * Open decoder
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;
}
id->ff_dec = avcodec_find_decoder( i_ff_codec ); /* Initialization of decoder structures */
if( !id->ff_dec ) id->p_decoder->pf_decode_audio = 0;
{ id->p_decoder->pf_aout_buffer_new = audio_new_buffer;
msg_Err( p_stream, "cannot find decoder (avcodec)" ); id->p_decoder->pf_aout_buffer_del = audio_del_buffer;
return VLC_EGENERIC; //id->p_decoder->p_cfg = p_sys->p_video_cfg;
}
id->ff_dec_c = avcodec_alloc_context(); id->p_decoder->p_module =
id->ff_dec_c->sample_rate = id->p_decoder->fmt_in.audio.i_rate; module_Need( id->p_decoder, "decoder", "$codec", 0 );
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->ff_dec_c->extradata_size = id->p_decoder->fmt_in.i_extra; if( !id->p_decoder->p_module )
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" ); msg_Err( p_stream, "cannot find decoder" );
av_free( id->ff_dec_c );
return VLC_EGENERIC; 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; * Open encoder
id->p_buffer = malloc( id->i_buffer ); */
/* 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 */ /* Sanity check for audio channels */
id->p_encoder->fmt_out.audio.i_channels = id->p_encoder->fmt_out.audio.i_channels =
...@@ -962,17 +888,78 @@ static int transcode_audio_new( sout_stream_t *p_stream, ...@@ -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_cfg = p_stream->p_sys->p_audio_cfg;
id->p_encoder->p_module = id->p_encoder->p_module =
module_Need( id->p_encoder, "encoder", module_Need( id->p_encoder, "encoder", p_sys->psz_aenc, VLC_TRUE );
p_stream->p_sys->psz_aenc, VLC_TRUE );
if( !id->p_encoder->p_module ) if( !id->p_encoder->p_module )
{ {
vlc_object_detach( id->p_encoder ); msg_Err( p_stream, "cannot find encoder" );
vlc_object_destroy( id->p_encoder ); module_Unneed( id->p_decoder, id->p_decoder->p_module );
msg_Err( p_stream, "cannot open encoder" ); id->p_decoder->p_module = 0;
av_free( id->ff_dec_c );
return VLC_EGENERIC; 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 */ /* FIXME: Hack for mp3 transcoding support */
if( id->p_encoder->fmt_out.i_codec == VLC_FOURCC( 'm','p','3',' ' ) ) 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' ); 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, ...@@ -983,15 +970,24 @@ static int transcode_audio_new( sout_stream_t *p_stream,
static void transcode_audio_close( sout_stream_t *p_stream, static void transcode_audio_close( sout_stream_t *p_stream,
sout_stream_id_t *id ) sout_stream_id_t *id )
{ {
if( id->ff_dec ) avcodec_close( id->ff_dec_c ); int i;
av_free( id->ff_dec_c );
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 ); /* Close encoder */
vlc_object_destroy( id->p_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, static int transcode_audio_process( sout_stream_t *p_stream,
...@@ -999,227 +995,99 @@ 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 ) block_t *in, block_t **out )
{ {
sout_stream_sys_t *p_sys = p_stream->p_sys; sout_stream_sys_t *p_sys = p_stream->p_sys;
aout_buffer_t aout_buf; aout_buffer_t *p_audio_buf;
block_t *p_block; block_t *p_block, *p_audio_block;
int i_buffer = in->i_buffer; int i;
char *p_buffer = in->p_buffer;
id->i_dts = in->i_dts;
*out = NULL; *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; if( p_sys->b_audio_sync )
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"); mtime_t i_dts = date_Get( &id->interpolated_pts ) + 1;
break; 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;
} }
i_buffer -= i_used; p_audio_block = p_audio_buf->p_sys;
p_buffer += i_used; p_audio_block->i_buffer = p_audio_buf->i_nb_bytes;
p_audio_block->i_dts = p_audio_block->i_pts =
if ( id->i_buffer_pos < 0 ) p_audio_buf->start_date;
{ p_audio_block->i_length = p_audio_buf->end_date -
msg_Warn( p_stream, "weird error audio decoding"); p_audio_buf->start_date;
break; p_audio_block->i_samples = p_audio_buf->i_nb_samples;
}
}
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',' ',' ') ) /* Run filter chain */
while( i_samples > 0 ) for( i = 0; i < id->i_filter; i++ )
{
*sout++ = ( *sin++ ) << 8;
i_samples--;
}
else
while( i_samples > 0 )
{ {
*sout++ = ( *sin++ - 128 ) << 8; p_audio_block =
i_samples--; id->pp_filter[i]->pf_audio_filter( id->pp_filter[i],
p_audio_block );
} }
i_buffer -= i_used; p_audio_buf->p_buffer = p_audio_block->p_buffer;
p_buffer += i_used; p_audio_buf->i_nb_bytes = p_audio_block->i_buffer;
id->i_buffer_pos = i_used * 2; p_audio_buf->i_nb_samples = p_audio_block->i_samples;
} p_audio_buf->start_date = p_audio_block->i_dts;
else if( i_codec == VLC_FOURCC('s','1','6','l') || p_audio_buf->end_date = p_audio_block->i_dts + p_audio_block->i_length;
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--; 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 );
} }
i_buffer -= i_used; return VLC_SUCCESS;
p_buffer += i_used; }
id->i_buffer_pos = i_used;
}
}
if( id->i_buffer_pos == 0 ) continue; 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 );
}
aout_buf.p_buffer = id->p_buffer; static aout_buffer_t *audio_new_buffer( decoder_t *p_dec, int i_samples )
aout_buf.i_nb_bytes = id->i_buffer_pos; {
aout_buf.i_nb_samples = id->i_buffer_pos / 2 / aout_buffer_t *p_buffer;
id->p_decoder->fmt_in.audio.i_channels; block_t *p_block;
aout_buf.start_date = id->i_dts; int i_size;
aout_buf.end_date = id->i_dts;
if( p_sys->b_audio_sync ) if( p_dec->fmt_out.audio.i_bitspersample )
{ {
aout_buf.start_date = date_Get( &id->interpolated_pts ) + 1; i_size = i_samples * p_dec->fmt_out.audio.i_bitspersample *
p_sys->i_master_drift = id->i_dts - aout_buf.start_date; p_dec->fmt_out.audio.i_channels;
date_Increment( &id->interpolated_pts, aout_buf.i_nb_samples );
} }
else if( p_dec->fmt_out.audio.i_bytes_per_frame &&
id->i_dts += ( I64C(1000000) * id->i_buffer_pos / 2 / p_dec->fmt_out.audio.i_frame_length )
id->p_decoder->fmt_in.audio.i_channels /
id->p_decoder->fmt_in.audio.i_rate );
if( id->p_encoder->fmt_in.audio.i_channels == 1 &&
id->p_decoder->fmt_in.audio.i_channels > 1 )
{ {
int16_t *p_sample = (int16_t *)aout_buf.p_buffer; i_size = i_samples * p_dec->fmt_out.audio.i_bytes_per_frame /
int i_src_c = id->p_decoder->fmt_in.audio.i_channels; p_dec->fmt_out.audio.i_frame_length;
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;
} }
else if( id->p_encoder->fmt_in.audio.i_channels == 2 && else
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 */
};
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;
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]; i_size = i_samples * 4 * p_dec->fmt_out.audio.i_channels;
r += mixf_r[i_src_c-3][j] * p_src[j];
}
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 */ p_buffer = malloc( sizeof(aout_buffer_t) );
static const int translation[7][6] = p_buffer->pf_release = audio_release_buffer;
{{ 0, 0, 0, 0, 0, 0 }, /* 0 channels (rarely used) */ p_buffer->p_sys = p_block = block_New( p_dec, i_size );
{ 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 */ p_buffer->p_buffer = p_block->p_buffer;
for( i = 0; i < aout_buf.i_nb_samples; i++ ) p_buffer->i_size = p_buffer->i_nb_bytes = p_block->i_buffer;
{ p_buffer->i_nb_samples = i_samples;
uint16_t *p_buffer = (uint16_t *)aout_buf.p_buffer; p_block->i_samples = i_samples;
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;
}
p_block = id->p_encoder->pf_encode_audio( id->p_encoder, &aout_buf ); return p_buffer;
block_ChainAppend( out, p_block );
}
return VLC_SUCCESS;
} }
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 * video
......
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