From: Christophe Massiot Date: Mon, 2 Sep 2002 23:17:06 +0000 (+0000) Subject: The liba52 "codec" is now an audio filter. It means we are now able to X-Git-Tag: 0.5.0~976 X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=34c71967f9b0e4533ba8343062282029f39e7089;p=vlc The liba52 "codec" is now an audio filter. It means we are now able to autodetect S/PDIF hardware support and the audio output plug-in chooses the best one. Of course it probably breaks existing output modules, see oss.c for hints :). Also include minor tweaks which will entitle us to decode and output 5.1 audio. It may break existing plug-ins, too. See audio_output.c:aout_FormatNbChannels for hints. --- diff --git a/Makefile.opts.in b/Makefile.opts.in index 2b8552e729..c96d7c11b9 100644 --- a/Makefile.opts.in +++ b/Makefile.opts.in @@ -58,7 +58,7 @@ plugins_CFLAGS = @plugins_CFLAGS@ builtins_CFLAGS = @builtins_CFLAGS@ mozilla_CFLAGS = @mozilla_CFLAGS@ -a52_CFLAGS = @a52_CFLAGS@ +a52tofloat32_CFLAGS = @a52tofloat32_CFLAGS@ arts_CFLAGS = @arts_CFLAGS@ i420_yuy2_mmx_CFLAGS = @i420_yuy2_mmx_CFLAGS@ directx_CFLAGS = @directx_CFLAGS@ @@ -94,7 +94,7 @@ plugins_LDFLAGS = @plugins_LDFLAGS@ builtins_LDFLAGS = @builtins_LDFLAGS@ mozilla_LDFLAGS = @mozilla_LDFLAGS@ -a52_LDFLAGS = @a52_LDFLAGS@ +a52tofloat32_LDFLAGS = @a52tofloat32_LDFLAGS@ aa_LDFLAGS = @aa_LDFLAGS@ alsa_LDFLAGS = @alsa_LDFLAGS@ arts_LDFLAGS = @arts_LDFLAGS@ diff --git a/configure.in b/configure.in index b046ee69a8..fa40343e49 100644 --- a/configure.in +++ b/configure.in @@ -446,8 +446,8 @@ BUILTINS="${BUILTINS}" PLUGINS="${PLUGINS} misc/dummy/dummy misc/null" PLUGINS="${PLUGINS} control/rc/rc misc/logger/logger access/file misc/memcpy/memcpy" PLUGINS="${PLUGINS} demux/mpeg/es demux/mpeg/audio demux/mpeg/mpeg_system demux/mpeg/ps demux/mpeg/ts demux/a52sys" -PLUGINS="${PLUGINS} codec/mpeg_video/idct/idct codec/mpeg_video/idct/idctclassic codec/mpeg_video/motion/motion codec/mpeg_video/mpeg_video codec/spudec/spudec codec/spdif codec/mpeg_audio/mpeg_audio" -PLUGINS="${PLUGINS} codec/a52old/imdct/imdct codec/a52old/downmix/downmix codec/a52old/a52old" +PLUGINS="${PLUGINS} codec/mpeg_video/idct/idct codec/mpeg_video/idct/idctclassic codec/mpeg_video/motion/motion codec/mpeg_video/mpeg_video codec/spudec/spudec codec/mpeg_audio/mpeg_audio" +PLUGINS="${PLUGINS} codec/a52old/imdct/imdct codec/a52old/downmix/downmix codec/a52old/a52old codec/a52" #PLUGINS="${PLUGINS} codec/lpcm/lpcm" PLUGINS="${PLUGINS} video_filter/deinterlace/deinterlace video_filter/invert video_filter/wall video_filter/transform video_filter/distort video_filter/clone video_filter/crop video_filter/motionblur" PLUGINS="${PLUGINS} audio_filter/converter/float32tos16 audio_filter/converter/float32tos8 audio_filter/converter/float32tou16 audio_filter/converter/float32tou8 audio_filter/converter/a52tospdif audio_filter/converter/fixed32tofloat32 audio_filter/converter/fixed32tos16 audio_filter/converter/s16tofloat32" @@ -1185,17 +1185,17 @@ then if test -f ${real_a52_tree}/include/a52.h then AC_MSG_RESULT(yes) - a52_CFLAGS="${a52_CFLAGS} -I${real_a52_tree}" - a52_LDFLAGS="${a52_LDFLAGS} -L${real_a52_tree}/liba52/.libs" - LDFLAGS="${save_LDFLAGS} ${a52_LDFLAGS}" + a52tofloat32_CFLAGS="${a52tofloat32_CFLAGS} -I${real_a52_tree}" + a52tofloat32_LDFLAGS="${a52tofloat32_LDFLAGS} -L${real_a52_tree}/liba52/.libs" + LDFLAGS="${save_LDFLAGS} ${a52tofloat32_LDFLAGS}" AC_CHECK_LIB(a52, a52_free, [ - BUILTINS="${BUILTINS} codec/a52" - a52_LDFLAGS="${a52_LDFLAGS} -la52 -lm" - a52_CFLAGS="${a52_CFLAGS} -DUSE_A52DEC_TREE" + BUILTINS="${BUILTINS} audio_filter/converter/a52tofloat32" + a52tofloat32_LDFLAGS="${a52tofloat32_LDFLAGS} -la52 -lm" + a52tofloat32_CFLAGS="${a52tofloat32_CFLAGS} -DUSE_A52DEC_TREE" ],[ if test -f ${real_a52_tree}/liba52/.libs/liba52.a then - AC_MSG_ERROR([make sure you have at least a52dec-0.7.3]) + AC_MSG_ERROR([make sure you have at least a52dec-0.7.4]) else AC_MSG_ERROR([the specified tree hasn't been compiled]) fi @@ -1220,9 +1220,9 @@ then LDFLAGS="${save_LDFLAGS} ${test_LDFLAGS}" AC_CHECK_HEADERS(a52dec/a52.h, [ AC_CHECK_LIB(a52, a52_free, [ - BUILTINS="${BUILTINS} codec/a52" - a52_LDFLAGS="${a52_LDFLAGS} ${test_LDFLAGS} -la52 -lm" - a52_CFLAGS="${a52_CFLAGS} ${test_CFLAGS}" + BUILTINS="${BUILTINS} audio_filter/converter/a52tofloat32" + a52tofloat32_LDFLAGS="${a52tofloat32_LDFLAGS} ${test_LDFLAGS} -la52 -lm" + a52tofloat32_CFLAGS="${a52tofloat32_CFLAGS} ${test_CFLAGS}" ],[ if test "x${enable_dvbpsi}" != "x" then @@ -2081,7 +2081,7 @@ AC_SUBST(plugins_CFLAGS) AC_SUBST(builtins_CFLAGS) AC_SUBST(mozilla_CFLAGS) -AC_SUBST(a52_CFLAGS) +AC_SUBST(a52tofloat32_CFLAGS) AC_SUBST(arts_CFLAGS) AC_SUBST(i420_yuy2_mmx_CFLAGS) AC_SUBST(dvd_CFLAGS) @@ -2115,7 +2115,7 @@ AC_SUBST(plugins_LDFLAGS) AC_SUBST(builtins_LDFLAGS) AC_SUBST(mozilla_LDFLAGS) -AC_SUBST(a52_LDFLAGS) +AC_SUBST(a52tofloat32_LDFLAGS) AC_SUBST(aa_LDFLAGS) AC_SUBST(alsa_LDFLAGS) AC_SUBST(arts_LDFLAGS) diff --git a/include/aout_internal.h b/include/aout_internal.h index ae78699d1f..d09ee2ccff 100644 --- a/include/aout_internal.h +++ b/include/aout_internal.h @@ -2,7 +2,7 @@ * aout_internal.h : internal defines for audio output ***************************************************************************** * Copyright (C) 2002 VideoLAN - * $Id: aout_internal.h,v 1.14 2002/08/30 23:27:05 massiot Exp $ + * $Id: aout_internal.h,v 1.15 2002/09/02 23:17:05 massiot Exp $ * * Authors: Christophe Massiot * @@ -226,6 +226,7 @@ void aout_OutputPlay( aout_instance_t * p_aout, aout_buffer_t * p_buffer ); void aout_OutputDelete( aout_instance_t * p_aout ); VLC_EXPORT( aout_buffer_t *, aout_OutputNextBuffer, ( aout_instance_t *, mtime_t, vlc_bool_t ) ); +VLC_EXPORT( int, aout_FormatNbChannels, ( audio_sample_format_t * p_format ) ); void aout_FormatPrepare( audio_sample_format_t * p_format ); void aout_FifoInit( aout_instance_t *, aout_fifo_t *, u32 ); mtime_t aout_FifoNextStart( aout_instance_t *, aout_fifo_t * ); diff --git a/include/audio_output.h b/include/audio_output.h index c31f73c681..e22bfd324d 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.61 2002/08/21 22:41:59 massiot Exp $ + * $Id: audio_output.h,v 1.62 2002/09/02 23:17:05 massiot Exp $ * * Authors: Christophe Massiot * @@ -107,6 +107,35 @@ typedef s32 vlc_fixed_t; #define FIXED32_ONE ((vlc_fixed_t) 0x10000000) +/* Dual mono. Two independant mono channels */ +#define AOUT_CHAN_CHANNEL 0x0000000B +#define AOUT_CHAN_MONO 0x00000001 +#define AOUT_CHAN_STEREO 0x00000002 +/* 3 front channels (left, center, right) */ +#define AOUT_CHAN_3F 0x00000003 +/* 2 front, 1 rear surround channels (L, R, S) */ +#define AOUT_CHAN_2F1R 0x00000004 +/* 3 front, 1 rear surround channels (L, C, R, S) */ +#define AOUT_CHAN_3F1R 0x00000005 +/* 2 front, 2 rear surround channels (L, R, LS, RS) */ +#define AOUT_CHAN_2F2R 0x00000006 +/* 3 front, 2 rear surround channels (L, C, R, LS, RS) */ +#define AOUT_CHAN_3F2R 0x00000007 +/* First of two mono channels */ +#define AOUT_CHAN_CHANNEL1 0x00000008 +/* Second of two mono channels */ +#define AOUT_CHAN_CHANNEL2 0x00000009 +/* Dolby surround compatible stereo */ +#define AOUT_CHAN_DOLBY 0x0000000A + +#define AOUT_CHAN_MASK 0x0000000F + +/* Low frequency effects channel. Normally used to connect a subwoofer. + * Can be combined with any of the above channels. For example : + * AOUT_CHAN_3F2R | AOUT_CHAN_LFE -> 3 front, 2 rear, 1 LFE (5.1) */ +#define AOUT_CHAN_LFE 0x00000010 + + /***************************************************************************** * aout_buffer_t : audio output buffer *****************************************************************************/ diff --git a/include/vlc_symbols.h b/include/vlc_symbols.h index 05639dd3a0..3ca6016252 100644 --- a/include/vlc_symbols.h +++ b/include/vlc_symbols.h @@ -37,6 +37,7 @@ struct module_symbols_t int (* __vlc_thread_create_inner) ( vlc_object_t *, char *, int, char *, void * ( * ) ( void * ), int, vlc_bool_t ) ; int (* __vlc_threads_end_inner) ( vlc_object_t * ) ; int (* __vlc_threads_init_inner) ( vlc_object_t * ) ; + int (* aout_FormatNbChannels_inner) ( audio_sample_format_t * p_format ) ; int (* input_AccessInit_inner) ( input_thread_t * ) ; int (* input_AddInfo_inner) ( input_info_category_t *, char *, char *, ... ) ; int (* input_ChangeArea_inner) ( input_thread_t *, input_area_t * ) ; @@ -224,6 +225,7 @@ struct module_symbols_t # define aout_DateSet p_symbols->aout_DateSet_inner # define aout_DeleteInstance p_symbols->aout_DeleteInstance_inner # define aout_FifoPop p_symbols->aout_FifoPop_inner +# define aout_FormatNbChannels p_symbols->aout_FormatNbChannels_inner # define aout_InputDelete p_symbols->aout_InputDelete_inner # define aout_OutputNextBuffer p_symbols->aout_OutputNextBuffer_inner # define config_Duplicate p_symbols->config_Duplicate_inner diff --git a/include/vlc_threads.h b/include/vlc_threads.h index c0de539dbb..f62e330c3a 100644 --- a/include/vlc_threads.h +++ b/include/vlc_threads.h @@ -3,7 +3,7 @@ * This header provides portable declarations for mutexes & conditions ***************************************************************************** * Copyright (C) 1999, 2002 VideoLAN - * $Id: vlc_threads.h,v 1.12 2002/09/01 21:20:29 massiot Exp $ + * $Id: vlc_threads.h,v 1.13 2002/09/02 23:17:05 massiot Exp $ * * Authors: Jean-Marc Dressler * Samuel Hocevar @@ -71,7 +71,7 @@ # define VLC_THREAD_PRIORITY_LOW 0 # define VLC_THREAD_PRIORITY_INPUT 37 # define VLC_THREAD_PRIORITY_AUDIO 38 -# define VLC_THREAD_PRIORITY_VIDEO 36 +# define VLC_THREAD_PRIORITY_VIDEO 31 # define VLC_THREAD_PRIORITY_OUTPUT 38 #elif defined(WIN32) diff --git a/modules/audio_filter/converter/Makefile b/modules/audio_filter/converter/Makefile index 4e9abde65e..213a68f87e 100644 --- a/modules/audio_filter/converter/Makefile +++ b/modules/audio_filter/converter/Makefile @@ -3,6 +3,7 @@ float32tos8_SOURCES = float32tos8.c float32tou16_SOURCES = float32tou16.c float32tou8_SOURCES = float32tou8.c a52tospdif_SOURCES = a52tospdif.c +a52tofloat32_SOURCES = a52tofloat32.c fixed32tos16_SOURCES = fixed32tos16.c fixed32tofloat32_SOURCES = fixed32tofloat32.c s16tofloat32_SOURCES = s16tofloat32.c diff --git a/modules/audio_filter/converter/a52tofloat32.c b/modules/audio_filter/converter/a52tofloat32.c new file mode 100644 index 0000000000..d36f3cf77c --- /dev/null +++ b/modules/audio_filter/converter/a52tofloat32.c @@ -0,0 +1,238 @@ +/***************************************************************************** + * a52tofloat32.c: ATSC A/52 aka AC-3 decoder plugin for VLC. + * This plugin makes use of liba52 to decode A/52 audio + * (http://liba52.sf.net/). + ***************************************************************************** + * Copyright (C) 2001, 2002 VideoLAN + * $Id: a52tofloat32.c,v 1.1 2002/09/02 23:17:05 massiot Exp $ + * + * Authors: Gildas Bazin + * Christophe Massiot + * + * 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 + +#include /* malloc(), free() */ +#include /* strdup() */ +#ifdef HAVE_STDINT_H +# include /* int16_t .. */ +#elif HAVE_INTTYPES_H +# include /* int16_t .. */ +#endif + +#ifdef HAVE_UNISTD_H +# include +#endif + +#ifdef USE_A52DEC_TREE /* liba52 header file */ +# include "include/a52.h" +#else +# include "a52dec/a52.h" +#endif + +#include "audio_output.h" +#include "aout_internal.h" + +/***************************************************************************** + * Local prototypes + *****************************************************************************/ +static int Create ( vlc_object_t * ); +static void Destroy ( vlc_object_t * ); +static void DoWork ( aout_instance_t *, aout_filter_t *, aout_buffer_t *, + aout_buffer_t * ); + +/***************************************************************************** + * Local structures + *****************************************************************************/ +struct aout_filter_sys_t +{ + a52_state_t * p_liba52; /* liba52 internal structure */ + vlc_bool_t b_dynrng; /* see below */ + int i_flags; /* liba52 flags, see a52dec/doc/liba52.txt */ + int i_nb_channels; /* number of float32 per sample */ +}; + +/***************************************************************************** + * Module descriptor + *****************************************************************************/ +#define DYNRNG_TEXT N_("A/52 dynamic range compression") +#define DYNRNG_LONGTEXT N_( \ + "Dynamic range compression makes the loud sounds softer, and the soft " \ + "sounds louder, so you can more easily listen to the stream in a noisy " \ + "environment without disturbing anyone. If you disable the dynamic range "\ + "compression the playback will be more adapted to a movie theater or a " \ + "listening room.") + +vlc_module_begin(); + add_category_hint( N_("Miscellaneous"), NULL ); + add_bool( "a52-dynrng", 1, NULL, DYNRNG_TEXT, DYNRNG_LONGTEXT ); + set_description( _("ATSC A/52 aka AC-3 audio decoder module") ); + set_capability( "audio filter", 100 ); + set_callbacks( Create, Destroy ); +vlc_module_end(); + +/***************************************************************************** + * Create: + *****************************************************************************/ +static int Create( vlc_object_t * _p_filter ) +{ + aout_filter_t * p_filter = (aout_filter_t *)_p_filter; + struct aout_filter_sys_t * p_sys; + + if ( p_filter->input.i_format != AOUT_FMT_A52 + || p_filter->output.i_format != AOUT_FMT_FLOAT32 ) + { + return -1; + } + + if ( p_filter->input.i_rate != p_filter->output.i_rate ) + { + return -1; + } + + /* Allocate the memory needed to store the module's structure */ + p_sys = p_filter->p_sys = malloc( sizeof(struct aout_filter_sys_t) ); + if( p_sys == NULL ) + { + msg_Err( p_filter, "out of memory" ); + return -1; + } + + p_sys->b_dynrng = config_GetInt( p_filter, "a52-dynrng" ); + + /* We'll do our own downmixing, thanks. */ + p_sys->i_nb_channels = aout_FormatNbChannels( &p_filter->output ); + switch ( p_filter->output.i_channels & AOUT_CHAN_MASK ) + { + case AOUT_CHAN_CHANNEL: p_sys->i_flags = A52_CHANNEL; break; + case AOUT_CHAN_CHANNEL1: p_sys->i_flags = A52_CHANNEL1; break; + case AOUT_CHAN_CHANNEL2: p_sys->i_flags = A52_CHANNEL2; break; + case AOUT_CHAN_MONO: p_sys->i_flags = A52_MONO; break; + case AOUT_CHAN_STEREO: p_sys->i_flags = A52_STEREO; break; + case AOUT_CHAN_DOLBY: p_sys->i_flags = A52_DOLBY; break; + case AOUT_CHAN_3F: p_sys->i_flags = A52_3F; break; + case AOUT_CHAN_2F1R: p_sys->i_flags = A52_2F1R; break; + case AOUT_CHAN_3F1R: p_sys->i_flags = A52_3F1R; break; + case AOUT_CHAN_2F2R: p_sys->i_flags = A52_2F2R; break; + case AOUT_CHAN_3F2R: p_sys->i_flags = A52_3F2R; break; + default: + msg_Err( p_filter, "unknow sample format !" ); + free( p_sys ); + return -1; + } + if ( p_filter->output.i_channels & AOUT_CHAN_LFE ) + { + p_sys->i_flags |= A52_LFE; + } + p_sys->i_flags |= A52_ADJUST_LEVEL; + + /* Initialize liba52 */ + p_sys->p_liba52 = a52_init( 0 ); + if( p_sys->p_liba52 == NULL ) + { + msg_Err( p_filter, "unable to initialize liba52" ); + return -1; + } + + p_filter->pf_do_work = DoWork; + p_filter->b_in_place = 0; + + return 0; +} + +/***************************************************************************** + * Interleave: helper function to interleave channels + *****************************************************************************/ +static void Interleave( float * p_out, const float * p_in, int i_channels ) +{ + int i, j; + + for ( j = 0; j < i_channels; j++ ) + { + for ( i = 0; i < 256; i++ ) + { + p_out[i * i_channels + j] = p_in[j * 256 + i]; + } + } +} + +/***************************************************************************** + * DoWork: decode an ATSC A/52 frame. + *****************************************************************************/ +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; + sample_t i_sample_level = 1; + int i_flags = p_sys->i_flags; + int i_bytes_per_block = 256 * p_sys->i_nb_channels + * sizeof(float); + int i; + + /* Do the actual decoding now. */ + a52_frame( p_sys->p_liba52, p_in_buf->p_buffer, + &i_flags, &i_sample_level, 0 ); + + if ( i_flags != p_sys->i_flags ) + { + msg_Err( p_filter, + "liba52 couldn't do the requested downmix 0x%x->0x%x", + p_sys->i_flags, i_flags ); + memset( p_out_buf->p_buffer, 0, i_bytes_per_block * 6 ); + return; + } + + if( !p_sys->b_dynrng ) + { + a52_dynrng( p_filter->p_sys->p_liba52, NULL, NULL ); + } + + for ( i = 0; i < 6; i++ ) + { + sample_t * p_samples; + + if( a52_block( p_sys->p_liba52 ) ) + { + msg_Warn( p_filter, "a52_block failed for block %d", i ); + } + + p_samples = a52_samples( p_sys->p_liba52 ); + + /* Interleave the *$£%ù samples. */ + Interleave( (float *)(p_out_buf->p_buffer + i * i_bytes_per_block), + p_samples, p_sys->i_nb_channels ); + } + + p_out_buf->i_nb_samples = p_in_buf->i_nb_samples; + p_out_buf->i_nb_bytes = i_bytes_per_block * 6; +} + +/***************************************************************************** + * Destroy : deallocate data structures + *****************************************************************************/ +static void Destroy( vlc_object_t * _p_filter ) +{ + aout_filter_t * p_filter = (aout_filter_t *)_p_filter; + struct aout_filter_sys_t * p_sys = p_filter->p_sys; + + a52_free( p_sys->p_liba52 ); + free( p_sys ); +} + diff --git a/modules/audio_filter/converter/a52tospdif.c b/modules/audio_filter/converter/a52tospdif.c index 81114b6629..dcb7efe6bd 100644 --- a/modules/audio_filter/converter/a52tospdif.c +++ b/modules/audio_filter/converter/a52tospdif.c @@ -2,7 +2,7 @@ * a52tospdif.c : encapsulates A/52 frames into S/PDIF packets ***************************************************************************** * Copyright (C) 2002 VideoLAN - * $Id: a52tospdif.c,v 1.10 2002/08/26 23:00:22 massiot Exp $ + * $Id: a52tospdif.c,v 1.11 2002/09/02 23:17:05 massiot Exp $ * * Authors: Christophe Massiot * Stéphane Borel @@ -42,7 +42,6 @@ * Local prototypes *****************************************************************************/ static int Create ( vlc_object_t * ); - static void DoWork ( aout_instance_t *, aout_filter_t *, aout_buffer_t *, aout_buffer_t * ); @@ -56,9 +55,7 @@ vlc_module_begin(); vlc_module_end(); /***************************************************************************** - * Create: allocate trivial mixer - ***************************************************************************** - * This function allocates and initializes a Crop vout method. + * Create: *****************************************************************************/ static int Create( vlc_object_t *p_this ) { diff --git a/modules/audio_output/oss.c b/modules/audio_output/oss.c index 9633e24af1..61acf8a1d1 100644 --- a/modules/audio_output/oss.c +++ b/modules/audio_output/oss.c @@ -2,7 +2,7 @@ * oss.c : OSS /dev/dsp module for vlc ***************************************************************************** * Copyright (C) 2000-2002 VideoLAN - * $Id: oss.c,v 1.22 2002/08/31 22:10:25 stef Exp $ + * $Id: oss.c,v 1.23 2002/09/02 23:17:05 massiot Exp $ * * Authors: Michel Kaempf * Samuel Hocevar @@ -174,8 +174,25 @@ static int Open( vlc_object_t *p_this ) if( ioctl( p_sys->i_fd, SNDCTL_DSP_SETFMT, &i_format ) < 0 || i_format != p_aout->output.output.i_format ) { - msg_Err( p_aout, "cannot set audio output format (%i)", i_format ); - return VLC_EGENERIC; + if ( i_format == AOUT_FMT_SPDIF ) + { + /* Retry with S16 */ + msg_Warn( p_aout, "cannot set audio output format (%i)", i_format ); + p_aout->output.output.i_format = i_format = AOUT_FMT_S16_NE; + p_aout->output.i_nb_samples = FRAME_SIZE; + if( ioctl( p_sys->i_fd, SNDCTL_DSP_SETFMT, &i_format ) < 0 + || i_format != p_aout->output.output.i_format ) + { + msg_Err( p_aout, "cannot set audio output format (%i)", + i_format ); + return VLC_EGENERIC; + } + } + else + { + msg_Err( p_aout, "cannot set audio output format (%i)", i_format ); + return VLC_EGENERIC; + } } if ( p_aout->output.output.i_format != AOUT_FMT_SPDIF ) diff --git a/modules/audio_output/sdl.c b/modules/audio_output/sdl.c index b18e464e71..ef671a5c0b 100644 --- a/modules/audio_output/sdl.c +++ b/modules/audio_output/sdl.c @@ -2,7 +2,7 @@ * sdl.c : SDL audio output plugin for vlc ***************************************************************************** * Copyright (C) 2000-2002 VideoLAN - * $Id: sdl.c,v 1.10 2002/08/31 19:58:04 stef Exp $ + * $Id: sdl.c,v 1.11 2002/09/02 23:17:05 massiot Exp $ * * Authors: Michel Kaempf * Samuel Hocevar @@ -103,6 +103,11 @@ static int Open ( vlc_object_t *p_this ) return VLC_EGENERIC; } + if ( p_aout->output.output.i_channels > 2 ) + p_aout->output.output.i_channels = 2; + p_aout->output.output.i_format = AOUT_FMT_S16_NE; + p_aout->output.i_nb_samples = FRAME_SIZE; + /* TODO: finish and clean this */ desired.freq = p_aout->output.output.i_rate; @@ -118,9 +123,6 @@ static int Open ( vlc_object_t *p_this ) return VLC_EGENERIC; } - p_aout->output.output.i_format = AOUT_FMT_S16_NE; - p_aout->output.i_nb_samples = FRAME_SIZE; - SDL_PauseAudio( 0 ); return VLC_SUCCESS; diff --git a/modules/codec/Makefile b/modules/codec/Makefile index 3215fb5278..ba23988e50 100644 --- a/modules/codec/Makefile +++ b/modules/codec/Makefile @@ -1,2 +1 @@ a52_SOURCES = a52.c -spdif_SOURCES = spdif.c diff --git a/modules/codec/a52.c b/modules/codec/a52.c index 2d16dbcdf5..c9be20ea1c 100644 --- a/modules/codec/a52.c +++ b/modules/codec/a52.c @@ -1,14 +1,14 @@ /***************************************************************************** - * a52.c: ATSC A/52 aka AC-3 decoder plugin for vlc. - * This plugin makes use of liba52 to decode A/52 audio - * (http://liba52.sf.net/). + * a52.c: A/52 basic parser ***************************************************************************** - * Copyright (C) 2001, 2002 VideoLAN - * $Id: a52.c,v 1.8 2002/08/30 22:22:24 massiot Exp $ + * Copyright (C) 2001-2002 VideoLAN + * $Id: a52.c,v 1.9 2002/09/02 23:17:05 massiot Exp $ * - * Authors: Gildas Bazin + * Authors: Stéphane Borel * Christophe Massiot - * + * Michel Lespinasse + * Aaron Holtzman + * * 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 @@ -27,49 +27,38 @@ /***************************************************************************** * Preamble *****************************************************************************/ +#include +#include +#include /* memcpy() */ +#include + #include -#include #include - -#include /* malloc(), free() */ -#include /* strdup() */ -#ifdef HAVE_STDINT_H -# include /* int16_t .. */ -#elif HAVE_INTTYPES_H -# include /* int16_t .. */ -#endif +#include #ifdef HAVE_UNISTD_H # include #endif -#ifdef USE_A52DEC_TREE /* liba52 header file */ -# include "include/a52.h" -#else -# include "a52dec/a52.h" -#endif - #define A52_FRAME_NB 1536 /***************************************************************************** - * a52_thread_t : a52 decoder thread descriptor + * spdif_thread_t : A52 pass-through thread descriptor *****************************************************************************/ -typedef struct a52_thread_s +typedef struct spdif_thread_s { /* - * liba52 properties + * Thread properties */ - a52_state_t * p_a52_state; - vlc_bool_t b_dynrng; - - /* The bit stream structure handles the PES stream at the bit level */ - bit_stream_t bit_stream; + vlc_thread_t thread_id; /* id for thread functions */ /* * Input properties */ decoder_fifo_t * p_fifo; /* stores the PES stream data */ - data_packet_t * p_data; + + /* The bit stream structure handles the PES stream at the bit level */ + bit_stream_t bit_stream; /* * Output properties @@ -77,111 +66,109 @@ typedef struct a52_thread_s aout_instance_t * p_aout; /* opaque */ aout_input_t * p_aout_input; /* opaque */ audio_sample_format_t output_format; - audio_date_t end_date; -} a52_thread_t; +} spdif_thread_t; -/***************************************************************************** +/**************************************************************************** * Local prototypes - *****************************************************************************/ + ****************************************************************************/ static int OpenDecoder ( vlc_object_t * ); static int RunDecoder ( decoder_fifo_t * ); -static int DecodeFrame ( a52_thread_t *, byte_t * ); -static int InitThread ( a52_thread_t *, decoder_fifo_t * ); -static void EndThread ( a52_thread_t * ); + +static int InitThread ( spdif_thread_t *, decoder_fifo_t * ); +static void EndThread ( spdif_thread_t * ); + +static int SyncInfo ( const byte_t *, int *, int *, int * ); /***************************************************************************** * Module descriptor *****************************************************************************/ -#define DYNRNG_TEXT N_("A/52 dynamic range compression") -#define DYNRNG_LONGTEXT N_( \ - "Dynamic range compression makes the loud sounds softer, and the soft " \ - "sounds louder, so you can more easily listen to the stream in a noisy " \ - "environment without disturbing anyone. If you disable the dynamic range "\ - "compression the playback will be more adapted to a movie theater or a " \ - "listening room.") - vlc_module_begin(); - add_category_hint( N_("Miscellaneous"), NULL ); - add_bool( "a52-dynrng", 1, NULL, DYNRNG_TEXT, DYNRNG_LONGTEXT ); - set_description( _("a52 ATSC A/52 aka AC-3 audio decoder module") ); - set_capability( "decoder", 60 ); + set_description( _("A/52 parser") ); + set_capability( "decoder", 0 ); set_callbacks( OpenDecoder, NULL ); + add_shortcut( "pass_through" ); + add_shortcut( "pass" ); vlc_module_end(); /***************************************************************************** * OpenDecoder: probe the decoder and return score ***************************************************************************** - * Tries to launch a decoder and return score so that the interface is able - * to choose. + * Tries to launch a decoder and return score so that the interface is able + * to chose. *****************************************************************************/ -static int OpenDecoder( vlc_object_t *p_this ) -{ +static int OpenDecoder( vlc_object_t *p_this ) +{ decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this; - + if( p_fifo->i_fourcc != VLC_FOURCC('a','5','2',' ') && p_fifo->i_fourcc != VLC_FOURCC('a','5','2','b') ) { - return VLC_EGENERIC; + return VLC_EGENERIC; } p_fifo->pf_run = RunDecoder; return VLC_SUCCESS; } -/***************************************************************************** - * RunDecoder: this function is called just after the thread is created - *****************************************************************************/ +/**************************************************************************** + * RunDecoder: the whole thing + **************************************************************************** + * This function is called just after the thread is launched. + ****************************************************************************/ static int RunDecoder( decoder_fifo_t *p_fifo ) { - a52_thread_t *p_dec; - + spdif_thread_t * p_dec; + audio_date_t end_date; + /* Allocate the memory needed to store the thread's structure */ - p_dec = (a52_thread_t *)malloc( sizeof(a52_thread_t) ); + p_dec = malloc( sizeof(spdif_thread_t) ); if( p_dec == NULL ) { msg_Err( p_fifo, "out of memory" ); DecoderError( p_fifo ); return -1; } - - if( InitThread( p_dec, p_fifo ) ) + + if ( InitThread( p_dec, p_fifo ) ) { - msg_Err( p_dec->p_fifo, "could not initialize thread" ); + + msg_Err( p_fifo, "could not initialize thread" ); DecoderError( p_fifo ); free( p_dec ); return -1; } - /* liba52 decoder thread's main loop */ - while( !p_dec->p_fifo->b_die && !p_dec->p_fifo->b_error ) + /* decoder thread's main loop */ + while ( !p_dec->p_fifo->b_die && !p_dec->p_fifo->b_error ) { - int i_frame_size, i_flags, i_rate, i_bit_rate; + int i_frame_size, i_channels, i_rate, i_bit_rate; mtime_t pts; /* Temporary buffer to store the raw frame to be decoded */ - byte_t p_frame_buffer[3840]; + byte_t p_header[7]; + aout_buffer_t * p_buffer; /* Look for sync word - should be 0x0b77 */ RealignBits( &p_dec->bit_stream ); - while( (ShowBits( &p_dec->bit_stream, 16 ) ) != 0x0b77 && - (!p_dec->p_fifo->b_die) && (!p_dec->p_fifo->b_error)) + while ( (ShowBits( &p_dec->bit_stream, 16 ) ) != 0x0b77 && + (!p_dec->p_fifo->b_die) && (!p_dec->p_fifo->b_error)) { RemoveBits( &p_dec->bit_stream, 8 ); } /* Set the Presentation Time Stamp */ NextPTS( &p_dec->bit_stream, &pts, NULL ); - if ( pts != 0 && pts != aout_DateGet( &p_dec->end_date ) ) + if ( pts != 0 && pts != aout_DateGet( &end_date ) ) { - aout_DateSet( &p_dec->end_date, pts ); + aout_DateSet( &end_date, pts ); } /* Get A/52 frame header */ - GetChunk( &p_dec->bit_stream, p_frame_buffer, 7 ); + GetChunk( &p_dec->bit_stream, p_header, 7 ); if( p_dec->p_fifo->b_die ) break; /* Check if frame is valid and get frame info */ - i_frame_size = a52_syncinfo( p_frame_buffer, &i_flags, &i_rate, - &i_bit_rate ); + i_frame_size = SyncInfo( p_header, &i_channels, &i_rate, + &i_bit_rate ); if( !i_frame_size ) { @@ -191,7 +178,8 @@ static int RunDecoder( decoder_fifo_t *p_fifo ) if( (p_dec->p_aout_input != NULL) && ( (p_dec->output_format.i_rate != i_rate) - /* || (p_dec->output_format.i_channels != i_channels) */ ) ) + || (p_dec->output_format.i_channels != i_channels) + || (p_dec->output_format.i_bytes_per_frame != i_frame_size) ) ) { /* Parameters changed - this should not happen. */ aout_InputDelete( p_dec->p_aout, p_dec->p_aout_input ); @@ -202,8 +190,10 @@ static int RunDecoder( decoder_fifo_t *p_fifo ) if( p_dec->p_aout_input == NULL ) { p_dec->output_format.i_rate = i_rate; - /* p_dec->output_format.i_channels = i_channels; */ - aout_DateInit( &p_dec->end_date, i_rate ); + p_dec->output_format.i_channels = i_channels; + p_dec->output_format.i_bytes_per_frame = i_frame_size; + p_dec->output_format.i_frame_length = A52_FRAME_NB; + aout_DateInit( &end_date, i_rate ); p_dec->p_aout_input = aout_InputNew( p_dec->p_fifo, &p_dec->p_aout, &p_dec->output_format ); @@ -215,51 +205,54 @@ static int RunDecoder( decoder_fifo_t *p_fifo ) } } - /* Get the complete frame */ - GetChunk( &p_dec->bit_stream, p_frame_buffer + 7, + if ( !aout_DateGet( &end_date ) ) + { + byte_t p_junk[3840]; + + /* We've just started the stream, wait for the first PTS. */ + GetChunk( &p_dec->bit_stream, p_junk, i_frame_size - 7 ); + continue; + } + + p_buffer = aout_BufferNew( p_dec->p_aout, p_dec->p_aout_input, + A52_FRAME_NB ); + if ( p_buffer == NULL ) return -1; + p_buffer->start_date = aout_DateGet( &end_date ); + p_buffer->end_date = aout_DateIncrement( &end_date, + A52_FRAME_NB ); + + /* Get the whole frame. */ + memcpy( p_buffer->p_buffer, p_header, 7 ); + GetChunk( &p_dec->bit_stream, p_buffer->p_buffer + 7, i_frame_size - 7 ); if( p_dec->p_fifo->b_die ) break; - if( DecodeFrame( p_dec, p_frame_buffer ) ) - { - p_dec->p_fifo->b_error = 1; - break; - } + /* Send the buffer to the mixer. */ + aout_BufferPlay( p_dec->p_aout, p_dec->p_aout_input, p_buffer ); } - /* If b_error is set, the decoder thread enters the error loop */ + /* If b_error is set, the spdif thread enters the error loop */ if( p_dec->p_fifo->b_error ) { DecoderError( p_dec->p_fifo ); } - /* End of the a52 decoder thread */ + /* End of the spdif decoder thread */ EndThread( p_dec ); - + return 0; } -/***************************************************************************** - * InitThread: initialize data before entering main loop - *****************************************************************************/ -static int InitThread( a52_thread_t * p_dec, decoder_fifo_t * p_fifo ) +/**************************************************************************** + * InitThread: initialize thread data and create output fifo + ****************************************************************************/ +static int InitThread( spdif_thread_t * p_dec, decoder_fifo_t * p_fifo ) { /* Initialize the thread properties */ p_dec->p_aout = NULL; p_dec->p_aout_input = NULL; p_dec->p_fifo = p_fifo; - p_dec->output_format.i_format = AOUT_FMT_FLOAT32; - p_dec->output_format.i_channels = 2; /* FIXME ! */ - - /* Initialize liba52 */ - p_dec->p_a52_state = a52_init( 0 ); - if( p_dec->p_a52_state == NULL ) - { - msg_Err( p_dec->p_fifo, "unable to initialize liba52" ); - return -1; - } - - p_dec->b_dynrng = config_GetInt( p_dec->p_fifo, "a52-dynrng" ); + p_dec->output_format.i_format = AOUT_FMT_A52; /* Init the Bitstream */ InitBitstream( &p_dec->bit_stream, p_dec->p_fifo, @@ -269,89 +262,85 @@ static int InitThread( a52_thread_t * p_dec, decoder_fifo_t * p_fifo ) } /***************************************************************************** - * Interleave: helper function to interleave channels + * EndThread : spdif thread destruction *****************************************************************************/ -static void Interleave( float * p_out, const float * p_in, int i_channels ) +static void EndThread( spdif_thread_t * p_dec ) { - int i, j; - - for ( j = 0; j < i_channels; j++ ) + if ( p_dec->p_aout_input != NULL ) { - for ( i = 0; i < 256; i++ ) - { - p_out[i * i_channels + j] = p_in[j * 256 + i]; - } + aout_InputDelete( p_dec->p_aout, p_dec->p_aout_input ); } + + free( p_dec ); } -/***************************************************************************** - * DecodeFrame: decode an ATSC A/52 frame. - *****************************************************************************/ -static int DecodeFrame( a52_thread_t * p_dec, byte_t * p_frame_buffer ) +/**************************************************************************** + * SyncInfo: parse A52 sync info + **************************************************************************** + * This code is borrowed from liba52 by Aaron Holtzman & Michel Lespinasse, + * since we don't want to oblige S/PDIF people to use liba52 just to get + * their SyncInfo... + ****************************************************************************/ +int SyncInfo( const byte_t * p_buf, int * pi_channels, int * pi_sample_rate, + int * pi_bit_rate) { - sample_t i_sample_level = 1; - aout_buffer_t * p_buffer; - int i, i_flags; - int i_bytes_per_block = 256 * p_dec->output_format.i_channels - * sizeof(float); - - if( !aout_DateGet( &p_dec->end_date ) ) - { - /* We've just started the stream, wait for the first PTS. */ + static const u8 halfrate[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3}; + static const int rate[] = { 32, 40, 48, 56, 64, 80, 96, 112, + 128, 160, 192, 224, 256, 320, 384, 448, + 512, 576, 640}; + static const u8 lfeon[8] = {0x10, 0x10, 0x04, 0x04, 0x04, 0x01, 0x04, 0x01}; + int frmsizecod; + int bitrate; + int half; + int acmod; + + if ((p_buf[0] != 0x0b) || (p_buf[1] != 0x77)) /* syncword */ return 0; - } - - p_buffer = aout_BufferNew( p_dec->p_aout, p_dec->p_aout_input, - A52_FRAME_NB ); - if ( p_buffer == NULL ) return -1; - p_buffer->start_date = aout_DateGet( &p_dec->end_date ); - p_buffer->end_date = aout_DateIncrement( &p_dec->end_date, - A52_FRAME_NB ); - - /* FIXME */ - i_flags = A52_STEREO | A52_ADJUST_LEVEL; - /* Do the actual decoding now */ - a52_frame( p_dec->p_a52_state, p_frame_buffer, - &i_flags, &i_sample_level, 0 ); + if (p_buf[5] >= 0x60) /* bsid >= 12 */ + return 0; + half = halfrate[p_buf[5] >> 3]; - if( !p_dec->b_dynrng ) + /* acmod, dsurmod and lfeon */ + acmod = p_buf[6] >> 5; + if ( p_buf[6] & 0xf8 ) { - a52_dynrng( p_dec->p_a52_state, NULL, NULL ); + *pi_channels = AOUT_CHAN_DOLBY; } - - for ( i = 0; i < 6; i++ ) + else switch ( acmod ) { - sample_t * p_samples; - - if( a52_block( p_dec->p_a52_state ) ) - { - msg_Warn( p_dec->p_fifo, "a52_block failed for block %i", i ); - } - - p_samples = a52_samples( p_dec->p_a52_state ); - - /* Interleave the *$£%ù samples */ - Interleave( (float *)(p_buffer->p_buffer + i * i_bytes_per_block), - p_samples, p_dec->output_format.i_channels ); + case 0x0: *pi_channels = AOUT_CHAN_CHANNEL; break; + case 0x1: *pi_channels = AOUT_CHAN_MONO; break; + case 0x2: *pi_channels = AOUT_CHAN_STEREO; break; + case 0x3: *pi_channels = AOUT_CHAN_3F; break; + case 0x4: *pi_channels = AOUT_CHAN_2F1R; break; + case 0x5: *pi_channels = AOUT_CHAN_3F1R; break; + case 0x6: *pi_channels = AOUT_CHAN_2F2R; break; + case 0x7: *pi_channels = AOUT_CHAN_3F2R; break; + case 0x8: *pi_channels = AOUT_CHAN_CHANNEL1; break; + case 0x9: *pi_channels = AOUT_CHAN_CHANNEL2; break; } + + if ( p_buf[6] & lfeon[acmod] ) *pi_channels |= AOUT_CHAN_LFE; - aout_BufferPlay( p_dec->p_aout, p_dec->p_aout_input, p_buffer ); - - return 0; -} - -/***************************************************************************** - * EndThread : liba52 decoder thread destruction - *****************************************************************************/ -static void EndThread( a52_thread_t * p_dec ) -{ - if ( p_dec->p_aout_input != NULL ) - { - aout_InputDelete( p_dec->p_aout, p_dec->p_aout_input ); + frmsizecod = p_buf[4] & 63; + if (frmsizecod >= 38) + return 0; + bitrate = rate [frmsizecod >> 1]; + *pi_bit_rate = (bitrate * 1000) >> half; + + switch (p_buf[4] & 0xc0) { + case 0: + *pi_sample_rate = 48000 >> half; + return 4 * bitrate; + case 0x40: + *pi_sample_rate = 44100 >> half; + return 2 * (320 * bitrate / 147 + (frmsizecod & 1)); + case 0x80: + *pi_sample_rate = 32000 >> half; + return 6 * bitrate; + default: + return 0; } - - a52_free( p_dec->p_a52_state ); - free( p_dec ); } diff --git a/modules/codec/spdif.c b/modules/codec/spdif.c deleted file mode 100644 index f9f58f8a4c..0000000000 --- a/modules/codec/spdif.c +++ /dev/null @@ -1,386 +0,0 @@ -/***************************************************************************** - * spdif.c: A/52 pass-through to external decoder with enabled soundcard - ***************************************************************************** - * Copyright (C) 2001-2002 VideoLAN - * $Id: spdif.c,v 1.8 2002/08/30 22:22:24 massiot Exp $ - * - * Authors: Stéphane Borel - * Juha Yrjola - * German Gomez Garcia - * Christophe Massiot - * - * 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 -#include -#include /* memcpy() */ -#include - -#include -#include -#include - -#ifdef HAVE_UNISTD_H -# include -#endif - -#define A52_FRAME_NB 1536 - -/***************************************************************************** - * spdif_thread_t : A52 pass-through thread descriptor - *****************************************************************************/ -typedef struct spdif_thread_s -{ - /* - * Thread properties - */ - vlc_thread_t thread_id; /* id for thread functions */ - - /* - * Input properties - */ - decoder_fifo_t * p_fifo; /* stores the PES stream data */ - - /* The bit stream structure handles the PES stream at the bit level */ - bit_stream_t bit_stream; - - /* - * Output properties - */ - aout_instance_t * p_aout; /* opaque */ - aout_input_t * p_aout_input; /* opaque */ - audio_sample_format_t output_format; -} spdif_thread_t; - -/**************************************************************************** - * Local prototypes - ****************************************************************************/ -static int OpenDecoder ( vlc_object_t * ); -static int RunDecoder ( decoder_fifo_t * ); - -static int InitThread ( spdif_thread_t *, decoder_fifo_t * ); -static void EndThread ( spdif_thread_t * ); - -static int SyncInfo ( const byte_t *, int *, int *, int * ); - -/***************************************************************************** - * Module descriptor - *****************************************************************************/ -vlc_module_begin(); - set_description( _("SPDIF pass-through A52 decoder") ); - set_capability( "decoder", 0 ); - set_callbacks( OpenDecoder, NULL ); - add_shortcut( "pass_through" ); - add_shortcut( "pass" ); -vlc_module_end(); - -/***************************************************************************** - * OpenDecoder: probe the decoder and return score - ***************************************************************************** - * Tries to launch a decoder and return score so that the interface is able - * to chose. - *****************************************************************************/ -static int OpenDecoder( vlc_object_t *p_this ) -{ - decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this; - - if( p_fifo->i_fourcc != VLC_FOURCC('a','5','2',' ') - && p_fifo->i_fourcc != VLC_FOURCC('a','5','2','b') ) - { - return VLC_EGENERIC; - } - - p_fifo->pf_run = RunDecoder; - return VLC_SUCCESS; -} - -/**************************************************************************** - * RunDecoder: the whole thing - **************************************************************************** - * This function is called just after the thread is launched. - ****************************************************************************/ -static int RunDecoder( decoder_fifo_t *p_fifo ) -{ - spdif_thread_t * p_dec; - audio_date_t end_date; - - /* Allocate the memory needed to store the thread's structure */ - p_dec = malloc( sizeof(spdif_thread_t) ); - if( p_dec == NULL ) - { - msg_Err( p_fifo, "out of memory" ); - DecoderError( p_fifo ); - return -1; - } - - if ( InitThread( p_dec, p_fifo ) ) - { - - msg_Err( p_fifo, "could not initialize thread" ); - DecoderError( p_fifo ); - free( p_dec ); - return -1; - } - - /* decoder thread's main loop */ - while ( !p_dec->p_fifo->b_die && !p_dec->p_fifo->b_error ) - { - int i_frame_size, i_flags, i_rate, i_bit_rate; - mtime_t pts; - /* Temporary buffer to store the raw frame to be decoded */ - byte_t p_header[7]; - aout_buffer_t * p_buffer; - - /* Look for sync word - should be 0x0b77 */ - RealignBits( &p_dec->bit_stream ); - while ( (ShowBits( &p_dec->bit_stream, 16 ) ) != 0x0b77 && - (!p_dec->p_fifo->b_die) && (!p_dec->p_fifo->b_error)) - { - RemoveBits( &p_dec->bit_stream, 8 ); - } - - /* Set the Presentation Time Stamp */ - NextPTS( &p_dec->bit_stream, &pts, NULL ); - if ( pts != 0 && pts != aout_DateGet( &end_date ) ) - { - aout_DateSet( &end_date, pts ); - } - - /* Get A/52 frame header */ - GetChunk( &p_dec->bit_stream, p_header, 7 ); - if( p_dec->p_fifo->b_die ) break; - - /* Check if frame is valid and get frame info */ - i_frame_size = SyncInfo( p_header, &i_flags, &i_rate, - &i_bit_rate ); - - if( !i_frame_size ) - { - msg_Warn( p_dec->p_fifo, "a52_syncinfo failed" ); - continue; - } - - if( (p_dec->p_aout_input != NULL) && - ( (p_dec->output_format.i_rate != i_rate) - || (p_dec->output_format.i_bytes_per_frame != i_frame_size) ) ) - { - /* Parameters changed - this should not happen. */ - aout_InputDelete( p_dec->p_aout, p_dec->p_aout_input ); - p_dec->p_aout_input = NULL; - } - - /* Creating the audio input if not created yet. */ - if( p_dec->p_aout_input == NULL ) - { - p_dec->output_format.i_rate = i_rate; - p_dec->output_format.i_bytes_per_frame = i_frame_size; - p_dec->output_format.i_frame_length = A52_FRAME_NB; - aout_DateInit( &end_date, i_rate ); - p_dec->p_aout_input = aout_InputNew( p_dec->p_fifo, - &p_dec->p_aout, - &p_dec->output_format ); - - if ( p_dec->p_aout_input == NULL ) - { - p_dec->p_fifo->b_error = 1; - break; - } - } - - if ( !aout_DateGet( &end_date ) ) - { - byte_t p_junk[3840]; - - /* We've just started the stream, wait for the first PTS. */ - GetChunk( &p_dec->bit_stream, p_junk, i_frame_size - 7 ); - continue; - } - - p_buffer = aout_BufferNew( p_dec->p_aout, p_dec->p_aout_input, - A52_FRAME_NB ); - if ( p_buffer == NULL ) return -1; - p_buffer->start_date = aout_DateGet( &end_date ); - p_buffer->end_date = aout_DateIncrement( &end_date, - A52_FRAME_NB ); - - /* Get the whole frame. */ - memcpy( p_buffer->p_buffer, p_header, 7 ); - GetChunk( &p_dec->bit_stream, p_buffer->p_buffer + 7, - i_frame_size - 7 ); - if( p_dec->p_fifo->b_die ) break; - - /* Send the buffer to the mixer. */ - aout_BufferPlay( p_dec->p_aout, p_dec->p_aout_input, p_buffer ); - } - - /* If b_error is set, the spdif thread enters the error loop */ - if( p_dec->p_fifo->b_error ) - { - DecoderError( p_dec->p_fifo ); - } - - /* End of the spdif decoder thread */ - EndThread( p_dec ); - - return 0; -} - -/**************************************************************************** - * InitThread: initialize thread data and create output fifo - ****************************************************************************/ -static int InitThread( spdif_thread_t * p_dec, decoder_fifo_t * p_fifo ) -{ - /* Initialize the thread properties */ - p_dec->p_aout = NULL; - p_dec->p_aout_input = NULL; - p_dec->p_fifo = p_fifo; - p_dec->output_format.i_format = AOUT_FMT_A52; - p_dec->output_format.i_channels = -1; - - /* Init the Bitstream */ - InitBitstream( &p_dec->bit_stream, p_dec->p_fifo, - NULL, NULL ); - - return 0; -} - -/***************************************************************************** - * EndThread : spdif thread destruction - *****************************************************************************/ -static void EndThread( spdif_thread_t * p_dec ) -{ - if ( p_dec->p_aout_input != NULL ) - { - aout_InputDelete( p_dec->p_aout, p_dec->p_aout_input ); - } - - free( p_dec ); -} - -/**************************************************************************** - * Local structures and tables - ****************************************************************************/ -typedef struct sync_frame_s -{ - struct syncinfo - { - u8 syncword[2]; - u8 crc1[2]; - u8 code; - } syncinfo; - - struct bsi - { - u8 bsidmod; - u8 acmod; - } bsi; -} sync_frame_t; - -typedef struct frame_size_s -{ - u16 i_bit_rate; - u16 i_frame_size[3]; -} frame_size_t; - -typedef struct info_s -{ - int i_bit_rate; - int i_frame_size; - int i_sample_rate; - int i_bs_mod; -} info_t; - -static const frame_size_t p_frame_size_code[64] = -{ - { 32 ,{64 ,69 ,96 } }, - { 32 ,{64 ,70 ,96 } }, - { 40 ,{80 ,87 ,120 } }, - { 40 ,{80 ,88 ,120 } }, - { 48 ,{96 ,104 ,144 } }, - { 48 ,{96 ,105 ,144 } }, - { 56 ,{112 ,121 ,168 } }, - { 56 ,{112 ,122 ,168 } }, - { 64 ,{128 ,139 ,192 } }, - { 64 ,{128 ,140 ,192 } }, - { 80 ,{160 ,174 ,240 } }, - { 80 ,{160 ,175 ,240 } }, - { 96 ,{192 ,208 ,288 } }, - { 96 ,{192 ,209 ,288 } }, - { 112 ,{224 ,243 ,336 } }, - { 112 ,{224 ,244 ,336 } }, - { 128 ,{256 ,278 ,384 } }, - { 128 ,{256 ,279 ,384 } }, - { 160 ,{320 ,348 ,480 } }, - { 160 ,{320 ,349 ,480 } }, - { 192 ,{384 ,417 ,576 } }, - { 192 ,{384 ,418 ,576 } }, - { 224 ,{448 ,487 ,672 } }, - { 224 ,{448 ,488 ,672 } }, - { 256 ,{512 ,557 ,768 } }, - { 256 ,{512 ,558 ,768 } }, - { 320 ,{640 ,696 ,960 } }, - { 320 ,{640 ,697 ,960 } }, - { 384 ,{768 ,835 ,1152 } }, - { 384 ,{768 ,836 ,1152 } }, - { 448 ,{896 ,975 ,1344 } }, - { 448 ,{896 ,976 ,1344 } }, - { 512 ,{1024 ,1114 ,1536 } }, - { 512 ,{1024 ,1115 ,1536 } }, - { 576 ,{1152 ,1253 ,1728 } }, - { 576 ,{1152 ,1254 ,1728 } }, - { 640 ,{1280 ,1393 ,1920 } }, - { 640 ,{1280 ,1394 ,1920 } } -}; - -/**************************************************************************** - * SyncInfo: parse A52 sync info - **************************************************************************** - * NB : i_flags is unused, this is just to mimick liba52's a52_syncinfo - * Returns the frame size - ****************************************************************************/ -static int SyncInfo( const byte_t * p_buffer, int * pi_flags, int * pi_rate, - int * pi_bitrate ) -{ - static const int p_sample_rates[4] = { 48000, 44100, 32000, -1 }; - int i_frame_rate_code; - int i_frame_size_code; - const sync_frame_t * p_sync_frame; - - p_sync_frame = (const sync_frame_t *)p_buffer; - - /* Compute frame rate */ - i_frame_rate_code = (p_sync_frame->syncinfo.code >> 6) & 0x03; - *pi_rate = p_sample_rates[i_frame_rate_code]; - if ( *pi_rate == -1 ) - { - return 0; - } - - if ( ( ( p_sync_frame->bsi.bsidmod >> 3 ) & 0x1f ) != 0x08 ) - { - return 0; - } - - /* Compute frame size */ - i_frame_size_code = p_sync_frame->syncinfo.code & 0x3f; - *pi_bitrate = p_frame_size_code[i_frame_size_code].i_bit_rate; - - return ( 2 * p_frame_size_code[i_frame_size_code] - .i_frame_size[i_frame_rate_code] ); -} diff --git a/modules/gui/macosx/aout.m b/modules/gui/macosx/aout.m index 84316e5044..6436ed5eb2 100644 --- a/modules/gui/macosx/aout.m +++ b/modules/gui/macosx/aout.m @@ -2,7 +2,7 @@ * aout.m: CoreAudio output plugin ***************************************************************************** * Copyright (C) 2002 VideoLAN - * $Id: aout.m,v 1.8 2002/08/30 23:27:06 massiot Exp $ + * $Id: aout.m,v 1.9 2002/09/02 23:17:05 massiot Exp $ * * Authors: Colin Delacroix * Jon Lech Johansen @@ -118,17 +118,13 @@ int E_(OpenAudio)( vlc_object_t * p_this ) return -1 ; } - /* We only deal with floats */ - if ( p_aout->output.output.i_format != AOUT_FMT_FLOAT32 ) - { - msg_Err( p_aout, "cannot set format 0x%x", - p_aout->output.output.i_format ); - return -1; - } + /* We only deal with floats. FIXME : this is where we should do S/PDIF. */ + p_aout->output.output.i_format = AOUT_FMT_FLOAT32; /* Set sample rate and channels per frame */ p_aout->output.output.i_rate = p_sys->stream_format.mSampleRate; - p_aout->output.output.i_channels = p_sys->stream_format.mChannelsPerFrame; + /* FIXME : this is where we should ask for downmixing. */ + p_aout->output.output.i_channels = 2; //p_sys->stream_format.mChannelsPerFrame; /* Get the buffer size that the device uses for IO */ i_param_size = sizeof( p_sys->i_buffer_size ); diff --git a/po/Makefile.in.in b/po/Makefile.in.in index 28726a21f2..32b7376550 100644 --- a/po/Makefile.in.in +++ b/po/Makefile.in.in @@ -2,7 +2,7 @@ # Copyright (C) 1995-1997, 2000, 2001 by Ulrich Drepper # # This file file be copied and used freely without restrictions. It can -# be used in projects which are not available under the GNU General Public License +# be used in projects which are not available under the GNU Public License # but which still want to provide support for the GNU gettext functionality. # Please note that the actual code is *not* freely available. diff --git a/src/audio_output/audio_output.c b/src/audio_output/audio_output.c index 63db8e9756..3fc2fcbfee 100644 --- a/src/audio_output/audio_output.c +++ b/src/audio_output/audio_output.c @@ -2,7 +2,7 @@ * audio_output.c : audio output instance miscellaneous functions ***************************************************************************** * Copyright (C) 2002 VideoLAN - * $Id: audio_output.c,v 1.100 2002/08/30 22:22:24 massiot Exp $ + * $Id: audio_output.c,v 1.101 2002/09/02 23:17:06 massiot Exp $ * * Authors: Christophe Massiot * @@ -150,9 +150,54 @@ void aout_BufferPlay( aout_instance_t * p_aout, aout_input_t * p_input, /* - * Formats management (internal) + * Formats management */ +/***************************************************************************** + * aout_FormatNbChannels : return the number of channels + *****************************************************************************/ +int aout_FormatNbChannels( audio_sample_format_t * p_format ) +{ + int i_nb; + + switch ( p_format->i_channels & AOUT_CHAN_MASK ) + { + case AOUT_CHAN_CHANNEL1: + case AOUT_CHAN_CHANNEL2: + case AOUT_CHAN_MONO: + i_nb = 1; + break; + + case AOUT_CHAN_CHANNEL: + case AOUT_CHAN_STEREO: + case AOUT_CHAN_DOLBY: + i_nb = 2; + break; + + case AOUT_CHAN_3F: + case AOUT_CHAN_2F1R: + i_nb = 3; + break; + + case AOUT_CHAN_3F1R: + case AOUT_CHAN_2F2R: + i_nb = 4; + break; + + case AOUT_CHAN_3F2R: + i_nb = 5; + break; + + default: + i_nb = 0; + } + + if ( p_format->i_channels & AOUT_CHAN_LFE ) + return i_nb + 1; + else + return i_nb; +} + /***************************************************************************** * aout_FormatPrepare : compute the number of bytes per frame & frame length *****************************************************************************/ @@ -190,7 +235,7 @@ void aout_FormatPrepare( audio_sample_format_t * p_format ) i_result = 0; /* will segfault much sooner... */ } - p_format->i_bytes_per_frame = i_result * p_format->i_channels; + p_format->i_bytes_per_frame = i_result * aout_FormatNbChannels( p_format ); p_format->i_frame_length = 1; } diff --git a/src/audio_output/filters.c b/src/audio_output/filters.c index adaa2eefb1..644870d904 100644 --- a/src/audio_output/filters.c +++ b/src/audio_output/filters.c @@ -2,7 +2,7 @@ * filters.c : audio output filters management ***************************************************************************** * Copyright (C) 2002 VideoLAN - * $Id: filters.c,v 1.8 2002/08/30 22:22:24 massiot Exp $ + * $Id: filters.c,v 1.9 2002/09/02 23:17:06 massiot Exp $ * * Authors: Christophe Massiot * @@ -75,9 +75,7 @@ static aout_filter_t * FindFilter( aout_instance_t * p_aout, static int SplitConversion( aout_instance_t * p_aout, const audio_sample_format_t * p_input_format, const audio_sample_format_t * p_output_format, - audio_sample_format_t * p_middle_format, - vlc_bool_t b_format_first, - vlc_bool_t b_rate_first ) + audio_sample_format_t * p_middle_format ) { vlc_bool_t b_format = (p_input_format->i_format != p_output_format->i_format); @@ -94,56 +92,23 @@ static int SplitConversion( aout_instance_t * p_aout, { if ( !b_format ) { - if ( b_rate_first ) - { - p_middle_format->i_channels = p_input_format->i_channels; - } - else - { - p_middle_format->i_rate = p_input_format->i_rate; - } + p_middle_format->i_rate = p_input_format->i_rate; return 1; } if ( !b_rate ) { - if ( b_format_first ) - { - p_middle_format->i_channels = p_input_format->i_channels; - } - else - { - p_middle_format->i_format = p_input_format->i_format; - } + p_middle_format->i_channels = p_input_format->i_channels; return 1; } /* !b_channels */ - if ( b_format_first ) - { - p_middle_format->i_rate = p_input_format->i_rate; - } - else - { - p_middle_format->i_format = p_input_format->i_format; - } + p_middle_format->i_rate = p_input_format->i_rate; return 1; } /* i_nb_conversion == 3 */ - if ( !b_format_first ) - { - p_middle_format->i_format = p_input_format->i_format; - } - else if ( !b_rate_first ) - { - p_middle_format->i_channels = p_input_format->i_channels; - } - else - { - p_middle_format->i_rate = p_input_format->i_rate; - } - + p_middle_format->i_channels = p_input_format->i_channels; return 2; } @@ -160,7 +125,7 @@ int aout_FiltersCreatePipeline( aout_instance_t * p_aout, const audio_sample_format_t * p_output_format ) { audio_sample_format_t temp_format; - vlc_bool_t b_format_first, b_rate_first; + int i_nb_conversions; if ( AOUT_FMTS_IDENTICAL( p_input_format, p_output_format ) ) { @@ -184,90 +149,83 @@ int aout_FiltersCreatePipeline( aout_instance_t * p_aout, } /* We'll have to split the conversion. We always do the downmixing - * before the resampling, and the upmixing after the resampling (to - * maximize the resampling efficiency). */ - b_rate_first = (p_input_format->i_channels < p_output_format->i_channels); + * before the resampling, because the audio decoder can probably do it + * for us. */ + i_nb_conversions = SplitConversion( p_aout, p_input_format, + p_output_format, &temp_format ); + if ( !i_nb_conversions ) + { + /* There was only one conversion to do, and we already failed. */ + msg_Err( p_aout, "couldn't find a filter for the conversion" ); + return -1; + } - for ( b_format_first = 1; b_format_first >= 0; b_format_first-- ) + pp_filters[0] = FindFilter( p_aout, p_input_format, &temp_format ); + if ( pp_filters[0] == NULL && i_nb_conversions == 2 ) { - int i_nb_conversions = SplitConversion( p_aout, p_input_format, - p_output_format, &temp_format, - b_format_first, b_rate_first ); - if ( !i_nb_conversions ) - { - /* There was only one conversion to do, and we already failed. */ - msg_Err( p_aout, "couldn't find a filter for the conversion" ); - return -1; - } + /* Try with only one conversion. */ + SplitConversion( p_aout, p_input_format, &temp_format, + &temp_format ); + pp_filters[0] = FindFilter( p_aout, p_input_format, + &temp_format ); + } + if ( pp_filters[0] == NULL ) + { + msg_Err( p_aout, + "couldn't find a filter for the first part of the conversion" ); + return -1; + } - pp_filters[0] = FindFilter( p_aout, p_input_format, &temp_format ); - if ( pp_filters[0] == NULL && i_nb_conversions == 2 ) - { - /* Try with only one conversion. */ - SplitConversion( p_aout, p_input_format, &temp_format, - &temp_format, b_format_first, b_rate_first ); - pp_filters[0] = FindFilter( p_aout, p_input_format, - &temp_format ); - } - if ( pp_filters[0] == NULL ) + /* We have the first stage of the conversion. Find a filter for + * the rest. */ + pp_filters[1] = FindFilter( p_aout, &pp_filters[0]->output, + p_output_format ); + if ( pp_filters[1] == NULL ) + { + /* Try to split the conversion. */ + i_nb_conversions = SplitConversion( p_aout, + &pp_filters[0]->output, + p_output_format, &temp_format ); + if ( !i_nb_conversions ) { - /* Retry with b_format_first = 0. */ - continue; + vlc_object_detach( pp_filters[0] ); + vlc_object_destroy( pp_filters[0] ); + msg_Err( p_aout, + "couldn't find a filter for the second part of the conversion" ); } - - /* We have the first stage of the conversion. Find a filter for - * the rest. */ pp_filters[1] = FindFilter( p_aout, &pp_filters[0]->output, + &temp_format ); + pp_filters[2] = FindFilter( p_aout, &temp_format, p_output_format ); - if ( pp_filters[1] == NULL ) + + if ( pp_filters[1] == NULL || pp_filters[2] == NULL ) { - /* Try to split the conversion. */ - i_nb_conversions = SplitConversion( p_aout, - &pp_filters[0]->output, - p_output_format, &temp_format, - b_format_first, b_rate_first ); - if ( !i_nb_conversions ) + vlc_object_detach( pp_filters[0] ); + vlc_object_destroy( pp_filters[0] ); + if ( pp_filters[1] != NULL ) { - vlc_object_detach( pp_filters[0] ); - vlc_object_destroy( pp_filters[0] ); - continue; + vlc_object_detach( pp_filters[1] ); + vlc_object_destroy( pp_filters[1] ); } - pp_filters[1] = FindFilter( p_aout, &pp_filters[0]->output, - &temp_format ); - pp_filters[2] = FindFilter( p_aout, &temp_format, - p_output_format ); - - if ( pp_filters[1] == NULL || pp_filters[2] == NULL ) + if ( pp_filters[2] != NULL ) { - vlc_object_detach( pp_filters[0] ); - vlc_object_destroy( pp_filters[0] ); - if ( pp_filters[1] != NULL ) - { - vlc_object_detach( pp_filters[1] ); - vlc_object_destroy( pp_filters[1] ); - } - if ( pp_filters[2] != NULL ) - { - vlc_object_detach( pp_filters[2] ); - vlc_object_destroy( pp_filters[2] ); - } - continue; + vlc_object_detach( pp_filters[2] ); + vlc_object_destroy( pp_filters[2] ); } - *pi_nb_filters = 3; - } - else - { - *pi_nb_filters = 2; + msg_Err( p_aout, + "couldn't find filters for the second part of the conversion" ); } - - /* We have enough filters. */ - msg_Dbg( p_aout, "found %d filters for the whole conversion", - *pi_nb_filters ); - return 0; + *pi_nb_filters = 3; + } + else + { + *pi_nb_filters = 2; } - msg_Err( p_aout, "couldn't find filters for the conversion" ); - return -1; + /* We have enough filters. */ + msg_Dbg( p_aout, "found %d filters for the whole conversion", + *pi_nb_filters ); + return 0; } /***************************************************************************** diff --git a/src/misc/modules_plugin.h b/src/misc/modules_plugin.h index c33914908a..fb346e824f 100644 --- a/src/misc/modules_plugin.h +++ b/src/misc/modules_plugin.h @@ -180,6 +180,7 @@ static const char * module_error( char *psz_buffer ) *****************************************************************************/ #define STORE_SYMBOLS( p_symbols ) \ (p_symbols)->aout_OutputNextBuffer_inner = aout_OutputNextBuffer; \ + (p_symbols)->aout_FormatNbChannels_inner = aout_FormatNbChannels; \ (p_symbols)->aout_FifoPop_inner = aout_FifoPop; \ (p_symbols)->__aout_NewInstance_inner = __aout_NewInstance; \ (p_symbols)->aout_DeleteInstance_inner = aout_DeleteInstance; \