* Fixed a compile issue in s16tofloat32swab.
* Fixed a typo in demux/mpeg/ts.c.
PLAYLIST := playlist
INPUT := input input_ext-plugins input_ext-dec input_ext-intf input_dec input_programs input_clock input_info
VIDEO_OUTPUT := video_output video_text vout_pictures vout_subpictures
-AUDIO_OUTPUT := audio_output filters input mixer output intf
+AUDIO_OUTPUT := common filters input mixer output intf dec
STREAM_OUTPUT := stream_output
MISC := mtime modules threads cpu configuration netutils iso_lang messages objects extras
* aout_internal.h : internal defines for audio output
*****************************************************************************
* Copyright (C) 2002 VideoLAN
- * $Id: aout_internal.h,v 1.20 2002/09/20 23:27:03 massiot Exp $
+ * $Id: aout_internal.h,v 1.21 2002/09/26 22:40:18 massiot Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
void (* pf_do_work)( struct aout_instance_t *,
struct aout_buffer_t * );
+ /* If b_error == 1, there is no mixer nor audio output pipeline. */
+ vlc_bool_t b_error;
/* Multiplier used to raise or lower the volume of the sound in
* software. Beware, this creates sound distortion and should be avoided
* as much as possible. This isn't available for non-float32 mixer. */
/* Mixer information */
byte_t * p_first_byte_to_mix;
- /* Is the input dead ? */
+ /* If b_error == 1, there is no input pipeline. */
vlc_bool_t b_error;
+ /* Did we just change the output format ? (expect buffer inconsistencies) */
+ vlc_bool_t b_changed;
};
/*****************************************************************************
/* Locks : please note that if you need several of these locks, it is
* mandatory (to avoid deadlocks) to take them in the following order :
- * p_input->lock, mixer_lock, output_fifo_lock, input_fifos_lock.
+ * mixer_lock, p_input->lock, output_fifo_lock, input_fifos_lock.
* --Meuuh */
/* When input_fifos_lock is taken, none of the p_input->fifo structures
* can be read or modified by a third-party thread. */
* Prototypes
*****************************************************************************/
/* From input.c : */
+int aout_InputNew( aout_instance_t * p_aout, aout_input_t * p_input );
+int aout_InputDelete( aout_instance_t * p_aout, aout_input_t * p_input );
int aout_InputPlay( aout_instance_t * p_aout, aout_input_t * p_input,
aout_buffer_t * p_buffer );
/* From mixer.c : */
int aout_MixerNew( aout_instance_t * p_aout );
-void aout_MixerDelete( aout_instance_t * p_aout );
+int aout_MixerDelete( aout_instance_t * p_aout );
void aout_MixerRun( aout_instance_t * p_aout );
int aout_MixerMultiplierSet( aout_instance_t * p_aout, float f_multiplier );
int aout_MixerMultiplierGet( aout_instance_t * p_aout, float * pf_multiplier );
void aout_OutputDelete( aout_instance_t * p_aout );
VLC_EXPORT( aout_buffer_t *, aout_OutputNextBuffer, ( aout_instance_t *, mtime_t, vlc_bool_t ) );
-/* From audio_output.c : */
+/* From common.c : */
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 );
* audio_output.h : audio output interface
*****************************************************************************
* Copyright (C) 2002 VideoLAN
- * $Id: audio_output.h,v 1.66 2002/09/20 23:27:03 massiot Exp $
+ * $Id: audio_output.h,v 1.67 2002/09/26 22:40:18 massiot Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
/*****************************************************************************
* Prototypes
*****************************************************************************/
-/* From audio_output.c : */
-#define aout_NewInstance(a) __aout_NewInstance(VLC_OBJECT(a))
-VLC_EXPORT( aout_instance_t *, __aout_NewInstance, ( vlc_object_t * ) );
-VLC_EXPORT( void, aout_DeleteInstance, ( aout_instance_t * ) );
-VLC_EXPORT( aout_buffer_t *, aout_BufferNew, ( aout_instance_t *, aout_input_t *, size_t ) );
-VLC_EXPORT( void, aout_BufferDelete, ( aout_instance_t *, aout_input_t *, aout_buffer_t * ) );
-VLC_EXPORT( int, aout_BufferPlay, ( aout_instance_t *, aout_input_t *, aout_buffer_t * ) );
+/* From common.c : */
+#define aout_New(a) __aout_New(VLC_OBJECT(a))
+VLC_EXPORT( aout_instance_t *, __aout_New, ( vlc_object_t * ) );
+VLC_EXPORT( void, aout_Delete, ( aout_instance_t * ) );
VLC_EXPORT( void, aout_DateInit, ( audio_date_t *, u32 ) );
VLC_EXPORT( void, aout_DateSet, ( audio_date_t *, mtime_t ) );
VLC_EXPORT( void, aout_DateMove, ( audio_date_t *, mtime_t ) );
VLC_EXPORT( mtime_t, aout_DateGet, ( const audio_date_t * ) );
VLC_EXPORT( mtime_t, aout_DateIncrement, ( audio_date_t *, u32 ) );
-/* From input.c : */
-#define aout_InputNew(a,b,c) __aout_InputNew(VLC_OBJECT(a),b,c)
-VLC_EXPORT( aout_input_t *, __aout_InputNew, ( vlc_object_t *, aout_instance_t **, audio_sample_format_t * ) );
-VLC_EXPORT( void, aout_InputDelete, ( aout_instance_t *, aout_input_t * ) );
+/* From dec.c : */
+#define aout_DecNew(a, b, c) __aout_DecNew(VLC_OBJECT(a), b, c)
+VLC_EXPORT( aout_input_t *, __aout_DecNew, ( vlc_object_t *, aout_instance_t **, audio_sample_format_t * ) );
+VLC_EXPORT( int, aout_DecDelete, ( aout_instance_t *, aout_input_t * ) );
+VLC_EXPORT( aout_buffer_t *, aout_DecNewBuffer, ( aout_instance_t *, aout_input_t *, size_t ) );
+VLC_EXPORT( void, aout_DecDeleteBuffer, ( aout_instance_t *, aout_input_t *, aout_buffer_t * ) );
+VLC_EXPORT( int, aout_DecPlay, ( aout_instance_t *, aout_input_t *, aout_buffer_t * ) );
/* From intf.c : */
VLC_EXPORT( int, aout_VolumeGet, ( aout_instance_t *, audio_volume_t * ) );
VLC_EXPORT( int, aout_VolumeInfos, ( aout_instance_t *, audio_volume_t * ) );
VLC_EXPORT( int, aout_VolumeUp, ( aout_instance_t *, int, audio_volume_t * ) );
VLC_EXPORT( int, aout_VolumeDown, ( aout_instance_t *, int, audio_volume_t * ) );
+VLC_EXPORT( int, aout_Restart, ( aout_instance_t * p_aout ) );
struct module_symbols_t
{
- aout_buffer_t * (* aout_BufferNew_inner) ( aout_instance_t *, aout_input_t *, size_t ) ;
+ aout_buffer_t * (* aout_DecNewBuffer_inner) ( aout_instance_t *, aout_input_t *, size_t ) ;
aout_buffer_t * (* aout_FifoPop_inner) ( aout_instance_t * p_aout, aout_fifo_t * p_fifo ) ;
aout_buffer_t * (* aout_OutputNextBuffer_inner) ( aout_instance_t *, mtime_t, vlc_bool_t ) ;
- aout_input_t * (* __aout_InputNew_inner) ( vlc_object_t *, aout_instance_t **, audio_sample_format_t * ) ;
- aout_instance_t * (* __aout_NewInstance_inner) ( vlc_object_t * ) ;
+ aout_input_t * (* __aout_DecNew_inner) ( vlc_object_t *, aout_instance_t **, audio_sample_format_t * ) ;
+ aout_instance_t * (* __aout_New_inner) ( vlc_object_t * ) ;
char * (* __config_GetPsz_inner) (vlc_object_t *, const char *) ;
char * (* config_GetHomeDir_inner) ( void ) ;
char * (* input_OffsetToTime_inner) ( input_thread_t *, char *, off_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_BufferPlay_inner) ( aout_instance_t *, aout_input_t *, aout_buffer_t * ) ;
+ int (* aout_DecDelete_inner) ( aout_instance_t *, aout_input_t * ) ;
+ int (* aout_DecPlay_inner) ( aout_instance_t *, aout_input_t *, aout_buffer_t * ) ;
int (* aout_FormatNbChannels_inner) ( audio_sample_format_t * p_format ) ;
+ int (* aout_Restart_inner) ( aout_instance_t * p_aout ) ;
int (* aout_VolumeDown_inner) ( aout_instance_t *, int, audio_volume_t * ) ;
int (* aout_VolumeGet_inner) ( aout_instance_t *, audio_volume_t * ) ;
int (* aout_VolumeInfos_inner) ( aout_instance_t *, audio_volume_t * ) ;
void (* __vlc_object_yield_inner) ( vlc_object_t * ) ;
void (* __vlc_thread_join_inner) ( vlc_object_t *, char *, int ) ;
void (* __vlc_thread_ready_inner) ( vlc_object_t * ) ;
- void (* aout_BufferDelete_inner) ( aout_instance_t *, aout_input_t *, aout_buffer_t * ) ;
void (* aout_DateInit_inner) ( audio_date_t *, u32 ) ;
void (* aout_DateMove_inner) ( audio_date_t *, mtime_t ) ;
void (* aout_DateSet_inner) ( audio_date_t *, mtime_t ) ;
- void (* aout_DeleteInstance_inner) ( aout_instance_t * ) ;
- void (* aout_InputDelete_inner) ( aout_instance_t *, aout_input_t * ) ;
+ void (* aout_DecDeleteBuffer_inner) ( aout_instance_t *, aout_input_t *, aout_buffer_t * ) ;
+ void (* aout_Delete_inner) ( aout_instance_t * ) ;
void (* aout_VolumeNoneInit_inner) ( aout_instance_t * ) ;
void (* aout_VolumeSoftInit_inner) ( aout_instance_t * ) ;
void (* config_Duplicate_inner) ( module_t *, module_config_t * ) ;
# define UnalignedGetBits p_symbols->UnalignedGetBits_inner
# define UnalignedRemoveBits p_symbols->UnalignedRemoveBits_inner
# define UnalignedShowBits p_symbols->UnalignedShowBits_inner
-# define __aout_InputNew p_symbols->__aout_InputNew_inner
-# define __aout_NewInstance p_symbols->__aout_NewInstance_inner
+# define __aout_DecNew p_symbols->__aout_DecNew_inner
+# define __aout_New p_symbols->__aout_New_inner
# define __config_GetFloat p_symbols->__config_GetFloat_inner
# define __config_GetInt p_symbols->__config_GetInt_inner
# define __config_GetPsz p_symbols->__config_GetPsz_inner
# define __vlc_threads_end p_symbols->__vlc_threads_end_inner
# define __vlc_threads_init p_symbols->__vlc_threads_init_inner
# define __vout_CreateThread p_symbols->__vout_CreateThread_inner
-# define aout_BufferDelete p_symbols->aout_BufferDelete_inner
-# define aout_BufferNew p_symbols->aout_BufferNew_inner
-# define aout_BufferPlay p_symbols->aout_BufferPlay_inner
# define aout_DateGet p_symbols->aout_DateGet_inner
# define aout_DateIncrement p_symbols->aout_DateIncrement_inner
# define aout_DateInit p_symbols->aout_DateInit_inner
# define aout_DateMove p_symbols->aout_DateMove_inner
# define aout_DateSet p_symbols->aout_DateSet_inner
-# define aout_DeleteInstance p_symbols->aout_DeleteInstance_inner
+# define aout_DecDelete p_symbols->aout_DecDelete_inner
+# define aout_DecDeleteBuffer p_symbols->aout_DecDeleteBuffer_inner
+# define aout_DecNewBuffer p_symbols->aout_DecNewBuffer_inner
+# define aout_DecPlay p_symbols->aout_DecPlay_inner
+# define aout_Delete p_symbols->aout_Delete_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 aout_Restart p_symbols->aout_Restart_inner
# define aout_VolumeDown p_symbols->aout_VolumeDown_inner
# define aout_VolumeGet p_symbols->aout_VolumeGet_inner
# define aout_VolumeInfos p_symbols->aout_VolumeInfos_inner
* with endianness change
*****************************************************************************
* Copyright (C) 2002 VideoLAN
- * $Id: s16tofloat32swab.c,v 1.3 2002/09/20 23:27:03 massiot Exp $
+ * $Id: s16tofloat32swab.c,v 1.4 2002/09/26 22:40:19 massiot Exp $
*
* Authors: Samuel Hocevar <sam@zoy.org>
* Henri Fallon <henri@videolan.org>
#ifndef HAVE_SWAB
p_tmp[0] = ((byte_t *)p_in)[1];
p_tmp[1] = ((byte_t *)p_in)[0];
- *p_out = (float)*( *(s16 *)p_tmp ) / 32768.0;
+ *p_out = (float)( *(s16 *)p_tmp ) / 32768.0;
#else
*p_out = (float)*p_in / 32768.0;
#endif
* a52.c: A/52 basic parser
*****************************************************************************
* Copyright (C) 2001-2002 VideoLAN
- * $Id: a52.c,v 1.12 2002/09/20 23:27:03 massiot Exp $
+ * $Id: a52.c,v 1.13 2002/09/26 22:40:20 massiot Exp $
*
* Authors: Stéphane Borel <stef@via.ecp.fr>
* Christophe Massiot <massiot@via.ecp.fr>
|| (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 );
+ aout_DecDelete( p_dec->p_aout, p_dec->p_aout_input );
p_dec->p_aout_input = NULL;
}
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 );
+ p_dec->p_aout_input = aout_DecNew( p_dec->p_fifo,
+ &p_dec->p_aout,
+ &p_dec->output_format );
if ( p_dec->p_aout_input == NULL )
{
continue;
}
- p_buffer = aout_BufferNew( p_dec->p_aout, p_dec->p_aout_input,
- A52_FRAME_NB );
+ p_buffer = aout_DecNewBuffer( 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,
i_frame_size - 7 );
if( p_dec->p_fifo->b_die )
{
- aout_BufferDelete( p_dec->p_aout, p_dec->p_aout_input,
- p_buffer );
+ aout_DecDeleteBuffer( p_dec->p_aout, p_dec->p_aout_input,
+ p_buffer );
break;
}
/* Send the buffer to the mixer. */
- aout_BufferPlay( p_dec->p_aout, p_dec->p_aout_input, p_buffer );
+ aout_DecPlay( 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_aout_input != NULL )
{
- aout_InputDelete( p_dec->p_aout, p_dec->p_aout_input );
+ aout_DecDelete( p_dec->p_aout, p_dec->p_aout_input );
}
free( p_dec );
* a52old.c: A52 decoder module main file
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
- * $Id: a52old.c,v 1.6 2002/08/30 22:22:24 massiot Exp $
+ * $Id: a52old.c,v 1.7 2002/09/26 22:40:20 massiot Exp $
*
* Authors: Michel Lespinasse <walken@zoy.org>
*
{
/* Delete old output */
msg_Warn( p_a52dec->p_fifo, "opening a new aout" );
- aout_InputDelete( p_a52dec->p_aout, p_a52dec->p_aout_input );
+ aout_DecDelete( p_a52dec->p_aout, p_a52dec->p_aout_input );
}
/* Set output configuration */
output_format.i_channels = 2; /* FIXME ! */
output_format.i_rate = sync_info.sample_rate;
aout_DateInit( &end_date, output_format.i_rate );
- p_a52dec->p_aout_input = aout_InputNew( p_a52dec->p_fifo,
- &p_a52dec->p_aout,
- &output_format );
+ p_a52dec->p_aout_input = aout_DecNew( p_a52dec->p_fifo,
+ &p_a52dec->p_aout,
+ &output_format );
}
if( p_a52dec->p_aout_input == NULL )
continue;
}
- p_aout_buffer = aout_BufferNew( p_a52dec->p_aout,
- p_a52dec->p_aout_input,
- A52DEC_FRAME_SIZE );
+ p_aout_buffer = aout_DecNewBuffer( p_a52dec->p_aout,
+ p_a52dec->p_aout_input,
+ A52DEC_FRAME_SIZE );
if( !p_aout_buffer )
{
msg_Err( p_a52dec->p_fifo, "cannot get aout buffer" );
if (decode_frame (p_a52dec, (s16*)p_aout_buffer->p_buffer))
{
b_sync = 0;
- aout_BufferDelete( p_a52dec->p_aout, p_a52dec->p_aout_input,
- p_aout_buffer );
+ aout_DecDeleteBuffer( p_a52dec->p_aout, p_a52dec->p_aout_input,
+ p_aout_buffer );
continue;
}
else
{
- aout_BufferPlay( p_a52dec->p_aout, p_a52dec->p_aout_input,
- p_aout_buffer );
+ aout_DecPlay( p_a52dec->p_aout, p_a52dec->p_aout_input,
+ p_aout_buffer );
}
RealignBits(&p_a52dec->bit_stream);
/* If the audio output fifo was created, we destroy it */
if( p_a52dec->p_aout_input )
{
- aout_InputDelete( p_a52dec->p_aout, p_a52dec->p_aout_input );
+ aout_DecDelete( p_a52dec->p_aout, p_a52dec->p_aout_input );
}
/* Free allocated structures */
* decoder.c: AAC decoder using libfaad2
*****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN
- * $Id: decoder.c,v 1.2 2002/08/23 14:05:22 sam Exp $
+ * $Id: decoder.c,v 1.3 2002/09/26 22:40:21 massiot Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
*
if( p_adec->p_aout_input )
{
/* **** Delete the old **** */
- aout_InputDelete( p_adec->p_aout, p_adec->p_aout_input );
+ aout_DecDelete( p_adec->p_aout, p_adec->p_aout_input );
}
/* **** Create a new audio output **** */
p_adec->output_format.i_channels = faad_frame.channels;
aout_DateInit( &p_adec->date, p_adec->output_format.i_rate );
- p_adec->p_aout_input = aout_InputNew( p_adec->p_fifo,
- &p_adec->p_aout,
- &p_adec->output_format );
+ p_adec->p_aout_input = aout_DecNew( p_adec->p_fifo,
+ &p_adec->p_aout,
+ &p_adec->output_format );
}
if( !p_adec->p_aout_input )
return;
}
- p_aout_buffer = aout_BufferNew( p_adec->p_aout,
- p_adec->p_aout_input,
- faad_frame.samples / faad_frame.channels );
+ p_aout_buffer = aout_DecNewBuffer( p_adec->p_aout,
+ p_adec->p_aout_input,
+ faad_frame.samples / faad_frame.channels );
if( !p_aout_buffer )
{
msg_Err( p_adec->p_fifo, "cannot get aout buffer" );
p_faad_buffer,
p_aout_buffer->i_nb_bytes );
- aout_BufferPlay( p_adec->p_aout, p_adec->p_aout_input, p_aout_buffer );
+ aout_DecPlay( p_adec->p_aout, p_adec->p_aout_input, p_aout_buffer );
}
{
if( p_adec->p_aout_input )
{
- aout_InputDelete( p_adec->p_aout, p_adec->p_aout_input );
+ aout_DecDelete( p_adec->p_aout, p_adec->p_aout_input );
}
if( p_adec->p_handle )
* lpcm.c: lpcm decoder module
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
- * $Id: lpcm.c,v 1.1 2002/09/20 23:27:03 massiot Exp $
+ * $Id: lpcm.c,v 1.2 2002/09/26 22:40:20 massiot Exp $
*
* Authors: Samuel Hocevar <sam@zoy.org>
* Henri Fallon <henri@videolan.org>
p_dec->output_format.i_rate = 48000;
aout_DateInit( &p_dec->end_date, 48000 );
- p_dec->p_aout_input = aout_InputNew( p_dec->p_fifo,
- &p_dec->p_aout,
- &p_dec->output_format );
+ p_dec->p_aout_input = aout_DecNew( p_dec->p_fifo,
+ &p_dec->p_aout,
+ &p_dec->output_format );
if ( p_dec->p_aout_input == NULL )
{
aout_DateSet( &p_dec->end_date, i_pts );
}
- p_aout_buffer = aout_BufferNew( p_dec->p_aout,
- p_dec->p_aout_input,
- LPCM_FRAME_NB );
+ p_aout_buffer = aout_DecNewBuffer( p_dec->p_aout,
+ p_dec->p_aout_input,
+ LPCM_FRAME_NB );
if( !p_aout_buffer )
{
if( p_dec->p_fifo->b_die )
{
- aout_BufferDelete( p_dec->p_aout, p_dec->p_aout_input,
- p_aout_buffer );
+ aout_DecDeleteBuffer( p_dec->p_aout, p_dec->p_aout_input,
+ p_aout_buffer );
return;
}
- aout_BufferPlay( p_dec->p_aout, p_dec->p_aout_input,
- p_aout_buffer );
+ aout_DecPlay( p_dec->p_aout, p_dec->p_aout_input,
+ p_aout_buffer );
}
/*****************************************************************************
{
if( p_dec->p_aout_input != NULL )
{
- aout_InputDelete( p_dec->p_aout, p_dec->p_aout_input );
+ aout_DecDelete( p_dec->p_aout, p_dec->p_aout_input );
}
free( p_dec );
|| p_dec->output_format.i_channels != p_pcm->channels) )
{
/* Parameters changed - this should not happen. */
- aout_InputDelete( p_dec->p_aout, p_dec->p_aout_input );
+ aout_DecDelete( p_dec->p_aout, p_dec->p_aout_input );
p_dec->p_aout_input = NULL;
}
p_dec->output_format.i_rate = p_pcm->samplerate;
p_dec->output_format.i_channels = p_pcm->channels;
aout_DateInit( &p_dec->end_date, p_pcm->samplerate );
- p_dec->p_aout_input = aout_InputNew( p_dec->p_fifo,
- &p_dec->p_aout,
- &p_dec->output_format );
+ p_dec->p_aout_input = aout_DecNew( p_dec->p_fifo,
+ &p_dec->p_aout,
+ &p_dec->output_format );
if ( p_dec->p_aout_input == NULL )
{
return MAD_FLOW_CONTINUE;
}
- p_buffer = aout_BufferNew( p_dec->p_aout, p_dec->p_aout_input, i_samples );
+ p_buffer = aout_DecNewBuffer( p_dec->p_aout, p_dec->p_aout_input, i_samples );
if ( p_buffer == NULL )
{
p_pcm->channels );
}
- aout_BufferPlay( p_dec->p_aout, p_dec->p_aout_input, p_buffer );
+ aout_DecPlay( p_dec->p_aout, p_dec->p_aout_input, p_buffer );
return MAD_FLOW_CONTINUE;
}
* decoder.c: MPEG audio decoder thread
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
- * $Id: decoder.c,v 1.3 2002/08/26 23:00:22 massiot Exp $
+ * $Id: decoder.c,v 1.4 2002/09/26 22:40:23 massiot Exp $
*
* Authors: Michel Kaempf <maxx@via.ecp.fr>
* Michel Lespinasse <walken@via.ecp.fr>
{
/* Delete old output */
msg_Warn( p_dec->p_fifo, "opening a new aout" );
- aout_InputDelete( p_dec->p_aout, p_dec->p_aout_input );
+ aout_DecDelete( p_dec->p_aout, p_dec->p_aout_input );
}
/* Set output configuration */
p_dec->output_format.i_channels = ( sync_info.b_stereo ? 2 : 1 );
p_dec->output_format.i_rate = sync_info.sample_rate;
aout_DateInit( &p_dec->end_date, sync_info.sample_rate );
- p_dec->p_aout_input = aout_InputNew( p_dec->p_fifo,
- &p_dec->p_aout,
- &p_dec->output_format );
+ p_dec->p_aout_input = aout_DecNew( p_dec->p_fifo,
+ &p_dec->p_aout,
+ &p_dec->output_format );
}
if( p_dec->p_aout_input == NULL )
return;
}
- p_aout_buffer = aout_BufferNew( p_dec->p_aout,
- p_dec->p_aout_input,
- ADEC_FRAME_NB );
+ p_aout_buffer = aout_DecNewBuffer( p_dec->p_aout,
+ p_dec->p_aout_input,
+ ADEC_FRAME_NB );
if( !p_aout_buffer )
{
msg_Err( p_dec->p_fifo, "cannot get aout buffer" );
if( adec_DecodeFrame (p_dec, (float*)p_aout_buffer->p_buffer ) )
{
/* Ouch, failed decoding... We'll have to resync */
- aout_BufferDelete( p_dec->p_aout, p_dec->p_aout_input, p_aout_buffer );
+ aout_DecDeleteBuffer( p_dec->p_aout, p_dec->p_aout_input, p_aout_buffer );
}
else
{
- aout_BufferPlay( p_dec->p_aout, p_dec->p_aout_input, p_aout_buffer );
+ aout_DecPlay( p_dec->p_aout, p_dec->p_aout_input, p_aout_buffer );
}
}
}
/* If the audio output fifo was created, we destroy it */
if( p_dec->p_aout_input )
{
- aout_InputDelete( p_dec->p_aout, p_dec->p_aout_input );
+ aout_DecDelete( p_dec->p_aout, p_dec->p_aout_input );
}
* mpeg_ts.c : Transport Stream input module for vlc
*****************************************************************************
* Copyright (C) 2000-2001 VideoLAN
- * $Id: ts.c,v 1.5 2002/09/23 23:05:58 massiot Exp $
+ * $Id: ts.c,v 1.6 2002/09/26 22:40:24 massiot Exp $
*
* Authors: Henri Fallon <henri@via.ecp.fr>
* Johan Bilien <jobi@via.ecp.fr>
p_new_es->i_stream_id = 0xBD;
break;
case DVD_SPU_ES:
- case A52_AUDIO_ES:
if ( !b_vls_compat )
p_new_es->i_fourcc = VLC_FOURCC('s','p','u',' ');
else
/*****************************************************************************
- * audio_output.c : audio output instance miscellaneous functions
+ * common.c : audio output management of common data structures
*****************************************************************************
* Copyright (C) 2002 VideoLAN
- * $Id: audio_output.c,v 1.103 2002/09/20 23:27:04 massiot Exp $
+ * $Id: common.c,v 1.1 2002/09/26 22:40:25 massiot Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
#include <vlc/vlc.h>
-#ifdef HAVE_ALLOCA_H
-# include <alloca.h>
-#endif
-
#include "audio_output.h"
#include "aout_internal.h"
+
/*
- * Instances management (see also input.c:aout_InputNew())
+ * Instances management (internal and external)
*/
/*****************************************************************************
- * aout_NewInstance: initialize aout structure
+ * aout_New: initialize aout structure
*****************************************************************************/
-aout_instance_t * __aout_NewInstance( vlc_object_t * p_parent )
+aout_instance_t * __aout_New( vlc_object_t * p_parent )
{
aout_instance_t * p_aout;
vlc_mutex_init( p_parent, &p_aout->output_fifo_lock );
p_aout->i_nb_inputs = 0;
p_aout->mixer.f_multiplier = 1.0;
+ p_aout->mixer.b_error = 1;
vlc_object_attach( p_aout, p_parent->p_vlc );
}
/*****************************************************************************
- * aout_DeleteInstance: destroy aout structure
+ * aout_Delete: destroy aout structure
*****************************************************************************/
-void aout_DeleteInstance( aout_instance_t * p_aout )
+void aout_Delete( aout_instance_t * p_aout )
{
vlc_mutex_destroy( &p_aout->input_fifos_lock );
vlc_mutex_destroy( &p_aout->mixer_lock );
/*
- * Buffer management (interface to the decoders)
- */
-
-/*****************************************************************************
- * aout_BufferNew : ask for a new empty buffer
- *****************************************************************************/
-aout_buffer_t * aout_BufferNew( aout_instance_t * p_aout,
- aout_input_t * p_input,
- size_t i_nb_samples )
-{
- aout_buffer_t * p_buffer;
- mtime_t duration = (1000000 * (mtime_t)i_nb_samples)
- / p_input->input.i_rate;
-
- /* This necessarily allocates in the heap. */
- aout_BufferAlloc( &p_input->input_alloc, duration, NULL, p_buffer );
- p_buffer->i_nb_samples = i_nb_samples;
- p_buffer->i_nb_bytes = i_nb_samples * p_input->input.i_bytes_per_frame
- / p_input->input.i_frame_length;
-
- if ( p_buffer == NULL )
- {
- msg_Err( p_aout, "NULL buffer !" );
- }
- else
- {
- p_buffer->start_date = p_buffer->end_date = 0;
- }
-
- return p_buffer;
-}
-
-/*****************************************************************************
- * aout_BufferDelete : destroy an undecoded buffer
- *****************************************************************************/
-void aout_BufferDelete( aout_instance_t * p_aout, aout_input_t * p_input,
- aout_buffer_t * p_buffer )
-{
- aout_BufferFree( p_buffer );
-}
-
-/*****************************************************************************
- * aout_BufferPlay : filter & mix the decoded buffer
- *****************************************************************************/
-int aout_BufferPlay( aout_instance_t * p_aout, aout_input_t * p_input,
- aout_buffer_t * p_buffer )
-{
- if ( p_buffer->start_date == 0 )
- {
- msg_Warn( p_aout, "non-dated buffer received" );
- aout_BufferFree( p_buffer );
- }
- else
- {
- p_buffer->end_date = p_buffer->start_date
- + (mtime_t)(p_buffer->i_nb_samples * 1000000)
- / p_input->input.i_rate;
- }
-
- /* If the buffer is too early, wait a while. */
- mwait( p_buffer->start_date - AOUT_MAX_PREPARE_TIME );
-
- if ( aout_InputPlay( p_aout, p_input, p_buffer ) == -1 ) return -1;
-
- /* Run the mixer if it is able to run. */
- aout_MixerRun( p_aout );
-}
-
-
-/*
- * Formats management
+ * Formats management (internal and external)
*/
/*****************************************************************************
--- /dev/null
+/*****************************************************************************
+ * dec.c : audio output API towards decoders
+ *****************************************************************************
+ * Copyright (C) 2002 VideoLAN
+ * $Id: dec.c,v 1.1 2002/09/26 22:40:25 massiot Exp $
+ *
+ * Authors: Christophe Massiot <massiot@via.ecp.fr>
+ *
+ * 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> /* calloc(), malloc(), free() */
+#include <string.h>
+
+#include <vlc/vlc.h>
+
+#ifdef HAVE_ALLOCA_H
+# include <alloca.h>
+#endif
+
+#include "audio_output.h"
+#include "aout_internal.h"
+
+/*
+ * Creation/Deletion
+ */
+
+/*****************************************************************************
+ * aout_DecNew : create a decoder
+ *****************************************************************************/
+static aout_input_t * DecNew( aout_instance_t * p_aout,
+ audio_sample_format_t * p_format )
+{
+ aout_input_t * p_input;
+
+ /* We can only be called by the decoder, so no need to lock
+ * p_input->lock. */
+ vlc_mutex_lock( &p_aout->mixer_lock );
+
+ if ( p_aout->i_nb_inputs >= AOUT_MAX_INPUTS )
+ {
+ msg_Err( p_aout, "too many inputs already (%d)", p_aout->i_nb_inputs );
+ return NULL;
+ }
+
+ p_input = malloc(sizeof(aout_input_t));
+ if ( p_input == NULL )
+ {
+ msg_Err( p_aout, "out of memory" );
+ return NULL;
+ }
+
+ vlc_mutex_init( p_aout, &p_input->lock );
+
+ p_input->b_changed = 0;
+ p_input->b_error = 1;
+ memcpy( &p_input->input, p_format,
+ sizeof(audio_sample_format_t) );
+ aout_FormatPrepare( &p_input->input );
+
+ p_aout->pp_inputs[p_aout->i_nb_inputs] = p_input;
+ p_aout->i_nb_inputs++;
+
+ if ( p_aout->mixer.b_error )
+ {
+ int i;
+
+ /* Recreate the output using the new format. */
+ if ( aout_OutputNew( p_aout, p_format ) < 0 )
+ {
+ for ( i = 0; i < p_aout->i_nb_inputs - 1; i++ )
+ {
+ vlc_mutex_lock( &p_aout->pp_inputs[i]->lock );
+ aout_InputDelete( p_aout, p_aout->pp_inputs[i] );
+ vlc_mutex_unlock( &p_aout->pp_inputs[i]->lock );
+ }
+ vlc_mutex_unlock( &p_aout->mixer_lock );
+ return p_input;
+ }
+
+ /* Create other input streams. */
+ for ( i = 0; i < p_aout->i_nb_inputs - 1; i++ )
+ {
+ vlc_mutex_lock( &p_aout->pp_inputs[i]->lock );
+ aout_InputDelete( p_aout, p_aout->pp_inputs[i] );
+ aout_InputNew( p_aout, p_aout->pp_inputs[i] );
+ vlc_mutex_unlock( &p_aout->pp_inputs[i]->lock );
+ }
+ }
+ else
+ {
+ aout_MixerDelete( p_aout );
+ }
+
+ if ( aout_MixerNew( p_aout ) == -1 )
+ {
+ aout_OutputDelete( p_aout );
+ vlc_mutex_unlock( &p_aout->mixer_lock );
+ return NULL;
+ }
+
+ aout_MixerNew( p_aout );
+
+ aout_InputNew( p_aout, p_input );
+
+ vlc_mutex_unlock( &p_aout->mixer_lock );
+
+ return p_input;
+}
+
+aout_input_t * __aout_DecNew( vlc_object_t * p_this,
+ aout_instance_t ** pp_aout,
+ audio_sample_format_t * p_format )
+{
+ if ( *pp_aout == NULL )
+ {
+ /* Create an audio output if there is none. */
+ *pp_aout = vlc_object_find( p_this, VLC_OBJECT_AOUT, FIND_ANYWHERE );
+
+ if( *pp_aout == NULL )
+ {
+ msg_Dbg( p_this, "no aout present, spawning one" );
+
+ *pp_aout = aout_New( p_this );
+ /* Everything failed, I'm a loser, I just wanna die */
+ if( *pp_aout == NULL )
+ {
+ return NULL;
+ }
+ }
+ else
+ {
+ vlc_object_release( *pp_aout );
+ }
+ }
+
+ return DecNew( *pp_aout, p_format );
+}
+
+/*****************************************************************************
+ * aout_DecDelete : delete a decoder
+ *****************************************************************************/
+int aout_DecDelete( aout_instance_t * p_aout, aout_input_t * p_input )
+{
+ int i_input;
+
+ /* This function can only be called by the decoder itself, so no need
+ * to lock p_input->lock. */
+ vlc_mutex_lock( &p_aout->mixer_lock );
+
+ for ( i_input = 0; i_input < p_aout->i_nb_inputs; i_input++ )
+ {
+ if ( p_aout->pp_inputs[i_input] == p_input )
+ {
+ break;
+ }
+ }
+
+ if ( i_input == p_aout->i_nb_inputs )
+ {
+ msg_Err( p_aout, "cannot find an input to delete" );
+ return -1;
+ }
+
+ /* Remove the input from the list. */
+ memmove( &p_aout->pp_inputs[i_input], &p_aout->pp_inputs[i_input + 1],
+ (AOUT_MAX_INPUTS - i_input - 1) * sizeof(aout_input_t *) );
+ p_aout->i_nb_inputs--;
+
+ aout_InputDelete( p_aout, p_input );
+
+ vlc_mutex_destroy( &p_input->lock );
+ free( p_input );
+
+ if ( !p_aout->i_nb_inputs )
+ {
+ aout_OutputDelete( p_aout );
+ aout_MixerDelete( p_aout );
+ }
+
+ vlc_mutex_unlock( &p_aout->mixer_lock );
+
+ return 0;
+}
+
+
+/*
+ * Buffer management
+ */
+
+/*****************************************************************************
+ * aout_DecNewBuffer : ask for a new empty buffer
+ *****************************************************************************/
+aout_buffer_t * aout_DecNewBuffer( aout_instance_t * p_aout,
+ aout_input_t * p_input,
+ size_t i_nb_samples )
+{
+ aout_buffer_t * p_buffer;
+ mtime_t duration;
+
+ vlc_mutex_lock( &p_input->lock );
+
+ if ( p_input->b_error )
+ {
+ vlc_mutex_unlock( &p_input->lock );
+ return NULL;
+ }
+
+ duration = (1000000 * (mtime_t)i_nb_samples) / p_input->input.i_rate;
+
+ /* This necessarily allocates in the heap. */
+ aout_BufferAlloc( &p_input->input_alloc, duration, NULL, p_buffer );
+ p_buffer->i_nb_samples = i_nb_samples;
+ p_buffer->i_nb_bytes = i_nb_samples * p_input->input.i_bytes_per_frame
+ / p_input->input.i_frame_length;
+
+ /* Suppose the decoder doesn't have more than one buffered buffer */
+ p_input->b_changed = 0;
+
+ vlc_mutex_unlock( &p_input->lock );
+
+ if ( p_buffer == NULL )
+ {
+ msg_Err( p_aout, "NULL buffer !" );
+ }
+ else
+ {
+ p_buffer->start_date = p_buffer->end_date = 0;
+ }
+
+ return p_buffer;
+}
+
+/*****************************************************************************
+ * aout_DecDeleteBuffer : destroy an undecoded buffer
+ *****************************************************************************/
+void aout_DecDeleteBuffer( aout_instance_t * p_aout, aout_input_t * p_input,
+ aout_buffer_t * p_buffer )
+{
+ aout_BufferFree( p_buffer );
+}
+
+/*****************************************************************************
+ * aout_DecPlay : filter & mix the decoded buffer
+ *****************************************************************************/
+int aout_DecPlay( aout_instance_t * p_aout, aout_input_t * p_input,
+ aout_buffer_t * p_buffer )
+{
+ if ( p_buffer->start_date == 0 )
+ {
+ msg_Warn( p_aout, "non-dated buffer received" );
+ aout_BufferFree( p_buffer );
+ return -1;
+ }
+
+ p_buffer->end_date = p_buffer->start_date
+ + (mtime_t)(p_buffer->i_nb_samples * 1000000)
+ / p_input->input.i_rate;
+
+ vlc_mutex_lock( &p_input->lock );
+
+ if ( p_input->b_error )
+ {
+ vlc_mutex_unlock( &p_input->lock );
+ aout_BufferFree( p_buffer );
+ return -1;
+ }
+
+ if ( p_input->b_changed )
+ {
+ /* Maybe the allocation size has changed. Re-allocate a buffer. */
+ aout_buffer_t * p_new_buffer;
+ mtime_t duration = (1000000 * (mtime_t)p_buffer->i_nb_samples)
+ / p_input->input.i_rate;
+
+ aout_BufferAlloc( &p_input->input_alloc, duration, NULL, p_new_buffer );
+ p_aout->p_vlc->pf_memcpy( p_new_buffer->p_buffer, p_buffer->p_buffer,
+ p_buffer->i_nb_bytes );
+ p_new_buffer->i_nb_samples = p_buffer->i_nb_samples;
+ p_new_buffer->i_nb_bytes = p_buffer->i_nb_bytes;
+ p_new_buffer->start_date = p_buffer->start_date;
+ p_new_buffer->end_date = p_buffer->end_date;
+ aout_BufferFree( p_buffer );
+ p_buffer = p_new_buffer;
+ p_input->b_changed = 0;
+ }
+
+ /* If the buffer is too early, wait a while. */
+ mwait( p_buffer->start_date - AOUT_MAX_PREPARE_TIME );
+
+ if ( aout_InputPlay( p_aout, p_input, p_buffer ) == -1 )
+ {
+ vlc_mutex_unlock( &p_input->lock );
+ return -1;
+ }
+
+ vlc_mutex_unlock( &p_input->lock );
+
+ /* Run the mixer if it is able to run. */
+ vlc_mutex_lock( &p_aout->mixer_lock );
+ aout_MixerRun( p_aout );
+ vlc_mutex_unlock( &p_aout->mixer_lock );
+
+ return 0;
+}
+
* input.c : internal management of input streams for the audio output
*****************************************************************************
* Copyright (C) 2002 VideoLAN
- * $Id: input.c,v 1.12 2002/09/20 23:27:04 massiot Exp $
+ * $Id: input.c,v 1.13 2002/09/26 22:40:25 massiot Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
/*****************************************************************************
* aout_InputNew : allocate a new input and rework the filter pipeline
*****************************************************************************/
-static aout_input_t * InputNew( aout_instance_t * p_aout,
- audio_sample_format_t * p_format )
+int aout_InputNew( aout_instance_t * p_aout, aout_input_t * p_input )
{
- aout_input_t * p_input;
-
- vlc_mutex_lock( &p_aout->mixer_lock );
-
- if ( p_aout->i_nb_inputs >= AOUT_MAX_INPUTS )
- {
- msg_Err( p_aout, "too many inputs already (%d)", p_aout->i_nb_inputs );
- vlc_mutex_unlock( &p_aout->mixer_lock );
- return NULL;
- }
-
- p_input = malloc(sizeof(aout_input_t));
- if ( p_input == NULL )
- {
- msg_Err( p_aout, "out of memory" );
- vlc_mutex_unlock( &p_aout->mixer_lock );
- return NULL;
- }
-
- vlc_mutex_init( p_aout, &p_input->lock );
- vlc_mutex_lock( &p_input->lock );
-
- if ( p_aout->i_nb_inputs == 0 )
- {
- /* Recreate the output using the new format. */
- if ( aout_OutputNew( p_aout, p_format ) < 0 )
- {
- vlc_mutex_unlock( &p_input->lock );
- vlc_mutex_destroy( &p_input->lock );
- free( p_input );
- vlc_mutex_unlock( &p_aout->mixer_lock );
- return NULL;
- }
- }
- else
- {
- aout_MixerDelete( p_aout );
- }
-
- p_input->b_error = 0;
- memcpy( &p_input->input, p_format,
- sizeof(audio_sample_format_t) );
- aout_FormatPrepare( &p_input->input );
-
/* Prepare FIFO. */
aout_FifoInit( p_aout, &p_input->fifo, p_aout->mixer.mixer.i_rate );
p_input->p_first_byte_to_mix = NULL;
- p_aout->pp_inputs[p_aout->i_nb_inputs] = p_input;
- p_aout->i_nb_inputs++;
-
- if ( aout_MixerNew( p_aout ) < 0 )
- {
- p_aout->i_nb_inputs--;
-
- if ( !p_aout->i_nb_inputs )
- {
- aout_OutputDelete( p_aout );
- }
- else
- {
- aout_MixerNew( p_aout );
- }
-
- aout_FifoDestroy( p_aout, &p_input->fifo );
- vlc_mutex_unlock( &p_input->lock );
- vlc_mutex_destroy( &p_input->lock );
- free( p_input );
- vlc_mutex_unlock( &p_aout->mixer_lock );
-
- return NULL;
- }
-
- vlc_mutex_unlock( &p_aout->mixer_lock );
-
/* Create filters. */
if ( aout_FiltersCreatePipeline( p_aout, p_input->pp_filters,
&p_input->i_nb_filters, &p_input->input,
{
msg_Err( p_aout, "couldn't set an input pipeline" );
- p_aout->i_nb_inputs--;
-
- aout_MixerDelete( p_aout );
- if ( !p_aout->i_nb_inputs )
- {
- aout_OutputDelete( p_aout );
- }
- else
- {
- aout_MixerNew( p_aout );
- }
-
aout_FifoDestroy( p_aout, &p_input->fifo );
- vlc_mutex_unlock( &p_input->lock );
- vlc_mutex_destroy( &p_input->lock );
- free( p_input );
- vlc_mutex_unlock( &p_aout->mixer_lock );
+ p_input->b_error = 1;
- return NULL;
+ return -1;
}
/* Prepare hints for the buffer allocator. */
/* Allocate in the heap, it is more convenient for the decoder. */
p_input->input_alloc.i_alloc_type = AOUT_ALLOC_HEAP;
- vlc_mutex_unlock( &p_input->lock );
-
- msg_Dbg( p_aout, "input 0x%x created", p_input );
- return p_input;
-}
-
-aout_input_t * __aout_InputNew( vlc_object_t * p_this,
- aout_instance_t ** pp_aout,
- audio_sample_format_t * p_format )
-{
- /* Create an audio output if there is none. */
- *pp_aout = vlc_object_find( p_this, VLC_OBJECT_AOUT, FIND_ANYWHERE );
-
- if( *pp_aout == NULL )
- {
- msg_Dbg( p_this, "no aout present, spawning one" );
-
- *pp_aout = aout_NewInstance( p_this );
- /* Everything failed, I'm a loser, I just wanna die */
- if( *pp_aout == NULL )
- {
- return NULL;
- }
- }
- else
- {
- vlc_object_release( *pp_aout );
- }
+ p_input->b_error = 0;
- return InputNew( *pp_aout, p_format );
+ return 0;
}
/*****************************************************************************
* aout_InputDelete : delete an input
- *****************************************************************************/
-void aout_InputDelete( aout_instance_t * p_aout, aout_input_t * p_input )
-{
- int i_input;
-
- vlc_mutex_lock( &p_aout->mixer_lock );
- vlc_mutex_lock( &p_input->lock );
-
- for ( i_input = 0; i_input < p_aout->i_nb_inputs; i_input++ )
- {
- if ( p_aout->pp_inputs[i_input] == p_input )
- {
- break;
- }
- }
-
- if ( i_input == p_aout->i_nb_inputs )
- {
- msg_Err( p_aout, "cannot find an input to delete" );
- return;
- }
-
- /* Remove the input from the list. */
- memmove( &p_aout->pp_inputs[i_input], &p_aout->pp_inputs[i_input + 1],
- (AOUT_MAX_INPUTS - i_input - 1) * sizeof(aout_input_t *) );
- p_aout->i_nb_inputs--;
-
- if ( !p_aout->i_nb_inputs )
- {
- aout_OutputDelete( p_aout );
- aout_MixerDelete( p_aout );
- }
-
- vlc_mutex_unlock( &p_aout->mixer_lock );
-
- aout_FiltersDestroyPipeline( p_aout, p_input->pp_filters,
- p_input->i_nb_filters );
- aout_FifoDestroy( p_aout, &p_input->fifo );
-
- vlc_mutex_unlock( &p_input->lock );
- vlc_mutex_destroy( &p_input->lock );
- free( p_input );
-
- msg_Dbg( p_aout, "input 0x%x destroyed", p_input );
-}
-
-/*****************************************************************************
- * aout_InputChange : recreate the pipeline framework, in case the output
- * device has changed
*****************************************************************************
- * You must own p_input->lock and the mixer lock before entering this function.
- * It returns -1 if the input pipeline couldn't be created. Please remember
- * to call aout_MixerNew() afterwards.
+ * This function must be entered with the mixer lock.
*****************************************************************************/
-int aout_InputChange( aout_instance_t * p_aout, aout_input_t * p_input )
+int aout_InputDelete( aout_instance_t * p_aout, aout_input_t * p_input )
{
+ if ( p_input->b_error ) return 0;
+
aout_FiltersDestroyPipeline( p_aout, p_input->pp_filters,
p_input->i_nb_filters );
aout_FifoDestroy( p_aout, &p_input->fifo );
- aout_FifoInit( p_aout, &p_input->fifo, p_aout->mixer.mixer.i_rate );
- p_input->p_first_byte_to_mix = NULL;
-
- /* Create filters. */
- if ( aout_FiltersCreatePipeline( p_aout, p_input->pp_filters,
- &p_input->i_nb_filters, &p_input->input,
- &p_aout->mixer.mixer ) < 0 )
- {
- p_input->b_error = 1;
-
- return -1;
- }
-
- /* Prepare hints for the buffer allocator. */
- p_input->input_alloc.i_alloc_type = AOUT_ALLOC_HEAP;
- p_input->input_alloc.i_bytes_per_sec = -1;
-
- aout_FiltersHintBuffers( p_aout, p_input->pp_filters,
- p_input->i_nb_filters,
- &p_input->input_alloc );
-
- /* i_bytes_per_sec is still == -1 if no filters */
- p_input->input_alloc.i_bytes_per_sec = __MAX(
- p_input->input_alloc.i_bytes_per_sec,
- p_input->input.i_bytes_per_frame
- * p_input->input.i_rate
- / p_input->input.i_frame_length );
- /* Allocate in the heap, it is more convenient for the decoder. */
- p_input->input_alloc.i_alloc_type = AOUT_ALLOC_HEAP;
-
return 0;
}
/*****************************************************************************
* aout_InputPlay : play a buffer
+ *****************************************************************************
+ * This function must be entered with the input lock.
*****************************************************************************/
int aout_InputPlay( aout_instance_t * p_aout, aout_input_t * p_input,
aout_buffer_t * p_buffer )
{
mtime_t start_date, duration;
- vlc_mutex_lock( &p_input->lock );
-
- if ( p_input->b_error ) return -1;
-
/* We don't care if someone changes the start date behind our back after
* this. We'll deal with that when pushing the buffer, and compensate
* with the next incoming buffer. */
+ vlc_mutex_lock( &p_aout->input_fifos_lock );
start_date = aout_FifoNextStart( p_aout, &p_input->fifo );
+ vlc_mutex_unlock( &p_aout->input_fifos_lock );
if ( start_date != 0 && start_date < mdate() )
{
&p_buffer );
}
- vlc_mutex_unlock( &p_input->lock );
-
- vlc_mutex_lock( &p_aout->input_fifos_lock );
/* Adding the start date will be managed by aout_FifoPush(). */
p_buffer->start_date = start_date;
p_buffer->end_date = start_date + duration;
+
+ vlc_mutex_lock( &p_aout->input_fifos_lock );
aout_FifoPush( p_aout, &p_input->fifo, p_buffer );
vlc_mutex_unlock( &p_aout->input_fifos_lock );
* intf.c : audio output API towards the interface modules
*****************************************************************************
* Copyright (C) 2002 VideoLAN
- * $Id: intf.c,v 1.3 2002/09/19 21:56:40 massiot Exp $
+ * $Id: intf.c,v 1.4 2002/09/26 22:40:25 massiot Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
#include "audio_output.h"
#include "aout_internal.h"
+
/*
* Volume management
*
vlc_mutex_lock( &p_aout->mixer_lock );
- if ( p_aout->i_nb_inputs == 0 )
+ if ( p_aout->mixer.b_error )
{
/* The output module is destroyed. */
vlc_mutex_unlock( &p_aout->mixer_lock );
vlc_mutex_lock( &p_aout->mixer_lock );
- if ( p_aout->i_nb_inputs == 0 )
+ if ( p_aout->mixer.b_error )
{
/* The output module is destroyed. */
vlc_mutex_unlock( &p_aout->mixer_lock );
vlc_mutex_lock( &p_aout->mixer_lock );
- if ( p_aout->i_nb_inputs == 0 )
+ if ( p_aout->mixer.b_error )
{
/* The output module is destroyed. */
vlc_mutex_unlock( &p_aout->mixer_lock );
vlc_mutex_lock( &p_aout->mixer_lock );
- if ( p_aout->i_nb_inputs == 0 )
+ if ( p_aout->mixer.b_error )
{
/* The output module is destroyed. */
vlc_mutex_unlock( &p_aout->mixer_lock );
vlc_mutex_lock( &p_aout->mixer_lock );
- if ( p_aout->i_nb_inputs == 0 )
+ if ( p_aout->mixer.b_error )
{
/* The output module is destroyed. */
vlc_mutex_unlock( &p_aout->mixer_lock );
return -1;
}
-
/* Placeholder for pf_volume_set(). */
int aout_VolumeNoneSet( aout_instance_t * p_aout, audio_volume_t i_volume )
{
return -1;
}
+
+/*
+ * Pipelines management
+ */
+
+/*****************************************************************************
+ * aout_Restart : re-open the output device and rebuild the input and output
+ * pipelines
+ *****************************************************************************
+ * This function is used whenever the parameters of the output plug-in are
+ * changed (eg. selecting S/PDIF or PCM).
+ *****************************************************************************/
+int aout_Restart( aout_instance_t * p_aout )
+{
+ int i;
+ vlc_bool_t b_error = 0;
+
+ vlc_mutex_lock( &p_aout->mixer_lock );
+
+ if ( p_aout->i_nb_inputs == 0 )
+ {
+ vlc_mutex_unlock( &p_aout->mixer_lock );
+ msg_Err( p_aout, "no decoder thread" );
+ return -1;
+ }
+
+ /* Lock all inputs. */
+ for ( i = 0; i < p_aout->i_nb_inputs; i++ )
+ {
+ vlc_mutex_lock( &p_aout->pp_inputs[i]->lock );
+ aout_InputDelete( p_aout, p_aout->pp_inputs[i] );
+ }
+
+ aout_MixerDelete( p_aout );
+
+ /* Re-open the output plug-in. */
+ aout_OutputDelete( p_aout );
+ if ( aout_OutputNew( p_aout, &p_aout->pp_inputs[0]->input ) == -1 )
+ {
+ /* Release all locks and report the error. */
+ for ( i = 0; i < p_aout->i_nb_inputs; i++ )
+ {
+ vlc_mutex_unlock( &p_aout->pp_inputs[i]->lock );
+ }
+ vlc_mutex_unlock( &p_aout->mixer_lock );
+ return -1;
+ }
+
+ if ( aout_MixerNew( p_aout ) == -1 )
+ {
+ aout_OutputDelete( p_aout );
+ for ( i = 0; i < p_aout->i_nb_inputs; i++ )
+ {
+ vlc_mutex_unlock( &p_aout->pp_inputs[i]->lock );
+ }
+ vlc_mutex_unlock( &p_aout->mixer_lock );
+ return -1;
+ }
+
+ /* Re-open all inputs. */
+ for ( i = 0; i < p_aout->i_nb_inputs; i++ )
+ {
+ aout_input_t * p_input = p_aout->pp_inputs[i];
+
+ b_error |= aout_InputNew( p_aout, p_input );
+ vlc_mutex_unlock( &p_input->lock );
+ }
+
+ vlc_mutex_unlock( &p_aout->mixer_lock );
+
+ return b_error;
+}
+
* mixer.c : audio output mixing operations
*****************************************************************************
* Copyright (C) 2002 VideoLAN
- * $Id: mixer.c,v 1.15 2002/09/23 23:05:58 massiot Exp $
+ * $Id: mixer.c,v 1.16 2002/09/26 22:40:25 massiot Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
msg_Err( p_aout, "no suitable aout mixer" );
return -1;
}
+ p_aout->mixer.b_error = 0;
return 0;
}
*****************************************************************************
* Please note that you must hold the mixer lock.
*****************************************************************************/
-void aout_MixerDelete( aout_instance_t * p_aout )
+int aout_MixerDelete( aout_instance_t * p_aout )
{
+ if ( p_aout->mixer.b_error ) return 0;
module_Unneed( p_aout, p_aout->mixer.p_module );
+ p_aout->mixer.b_error = 1;
+
+ return 0;
}
/*****************************************************************************
* MixBuffer: try to prepare one output buffer
+ *****************************************************************************
+ * Please note that you must hold the mixer lock.
*****************************************************************************/
static int MixBuffer( aout_instance_t * p_aout )
{
- int i;
+ int i, i_nb_real_inputs = 0;
aout_buffer_t * p_output_buffer;
mtime_t start_date, end_date;
audio_date_t exact_start_date;
- vlc_mutex_lock( &p_aout->mixer_lock );
+ if ( p_aout->mixer.b_error )
+ {
+ /* Free all incoming buffers. */
+ vlc_mutex_lock( &p_aout->input_fifos_lock );
+ for ( i = 0; i < p_aout->i_nb_inputs; i++ )
+ {
+ aout_input_t * p_input = p_aout->pp_inputs[i];
+ aout_buffer_t * p_buffer = p_input->fifo.p_first;
+ if ( p_input->b_error ) continue;
+ while ( p_buffer != NULL )
+ {
+ aout_buffer_t * p_next = p_buffer->p_next;
+ aout_BufferFree( p_buffer );
+ p_buffer = p_next;
+ }
+ }
+ vlc_mutex_unlock( &p_aout->input_fifos_lock );
+ return -1;
+ }
+
+
vlc_mutex_lock( &p_aout->output_fifo_lock );
vlc_mutex_lock( &p_aout->input_fifos_lock );
{
/* Interrupted before the end... We can't run. */
vlc_mutex_unlock( &p_aout->input_fifos_lock );
- vlc_mutex_unlock( &p_aout->mixer_lock );
return -1;
}
}
vlc_bool_t b_drop_buffers;
if ( p_input->b_error ) continue;
+ i_nb_real_inputs++;
p_buffer = p_fifo->p_first;
if ( p_buffer == NULL )
if ( p_buffer == NULL ) break;
}
- if ( i < p_aout->i_nb_inputs )
+ if ( i < p_aout->i_nb_inputs || !i_nb_real_inputs )
{
/* Interrupted before the end... We can't run. */
vlc_mutex_unlock( &p_aout->input_fifos_lock );
- vlc_mutex_unlock( &p_aout->mixer_lock );
return -1;
}
{
msg_Err( p_aout, "out of memory" );
vlc_mutex_unlock( &p_aout->input_fifos_lock );
- vlc_mutex_unlock( &p_aout->mixer_lock );
return -1;
}
/* This is again a bit kludgy - for the S/PDIF mixer. */
aout_OutputPlay( p_aout, p_output_buffer );
- vlc_mutex_unlock( &p_aout->mixer_lock );
-
return 0;
}
/*****************************************************************************
* aout_MixerRun: entry point for the mixer & post-filters processing
+ *****************************************************************************
+ * Please note that you must hold the mixer lock.
*****************************************************************************/
void aout_MixerRun( aout_instance_t * p_aout )
{
int aout_MixerMultiplierSet( aout_instance_t * p_aout, float f_multiplier )
{
float f_old = p_aout->mixer.f_multiplier;
+ vlc_bool_t b_new_mixer = 0;
- aout_MixerDelete( p_aout );
+ if ( !p_aout->mixer.b_error )
+ {
+ aout_MixerDelete( p_aout );
+ b_new_mixer = 1;
+ }
p_aout->mixer.f_multiplier = f_multiplier;
- if ( aout_MixerNew( p_aout ) )
+ if ( b_new_mixer && aout_MixerNew( p_aout ) )
{
p_aout->mixer.f_multiplier = f_old;
aout_MixerNew( p_aout );
* output.c : internal management of output streams for the audio output
*****************************************************************************
* Copyright (C) 2002 VideoLAN
- * $Id: output.c,v 1.14 2002/08/30 23:27:06 massiot Exp $
+ * $Id: output.c,v 1.15 2002/09/26 22:40:25 massiot Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
/*****************************************************************************
* aout_OutputNew : allocate a new output and rework the filter pipeline
*****************************************************************************
- * This function is entered with the mixer_lock.
+ * This function is entered with the mixer lock.
*****************************************************************************/
int aout_OutputNew( aout_instance_t * p_aout,
audio_sample_format_t * p_format )
/*****************************************************************************
* aout_OutputDelete : delete the output
*****************************************************************************
- * This function is entered with the mixer_lock.
+ * This function is entered with the mixer lock.
*****************************************************************************/
void aout_OutputDelete( aout_instance_t * p_aout )
{
/*****************************************************************************
* aout_OutputPlay : play a buffer
*****************************************************************************
- * This function is entered with the mixer_lock.
+ * This function is entered with the mixer lock.
*****************************************************************************/
void aout_OutputPlay( aout_instance_t * p_aout, aout_buffer_t * p_buffer )
{
* If b_can_sleek is 1, the aout core functions won't try to resample
* new buffers to catch up - that is we suppose that the output plug-in can
* compensate it by itself. S/PDIF outputs should always set b_can_sleek = 1.
+ * This function is entered with no lock at all :-).
*****************************************************************************/
aout_buffer_t * aout_OutputNextBuffer( aout_instance_t * p_aout,
mtime_t start_date,
* libvlc.c: main libvlc source
*****************************************************************************
* Copyright (C) 1998-2002 VideoLAN
- * $Id: libvlc.c,v 1.31 2002/09/17 14:56:13 sam Exp $
+ * $Id: libvlc.c,v 1.32 2002/09/26 22:40:24 massiot Exp $
*
* Authors: Vincent Seguin <seguin@via.ecp.fr>
* Samuel Hocevar <sam@zoy.org>
{
vlc_object_detach( (vlc_object_t *)p_aout );
vlc_object_release( (vlc_object_t *)p_aout );
- aout_DeleteInstance( p_aout );
+ aout_Delete( p_aout );
}
/* Update the handle status */
(p_symbols)->aout_FifoPop_inner = aout_FifoPop; \
(p_symbols)->aout_VolumeSoftInit_inner = aout_VolumeSoftInit; \
(p_symbols)->aout_VolumeNoneInit_inner = aout_VolumeNoneInit; \
- (p_symbols)->__aout_NewInstance_inner = __aout_NewInstance; \
- (p_symbols)->aout_DeleteInstance_inner = aout_DeleteInstance; \
- (p_symbols)->aout_BufferNew_inner = aout_BufferNew; \
- (p_symbols)->aout_BufferDelete_inner = aout_BufferDelete; \
- (p_symbols)->aout_BufferPlay_inner = aout_BufferPlay; \
+ (p_symbols)->__aout_New_inner = __aout_New; \
+ (p_symbols)->aout_Delete_inner = aout_Delete; \
(p_symbols)->aout_DateInit_inner = aout_DateInit; \
(p_symbols)->aout_DateSet_inner = aout_DateSet; \
(p_symbols)->aout_DateMove_inner = aout_DateMove; \
(p_symbols)->aout_DateGet_inner = aout_DateGet; \
(p_symbols)->aout_DateIncrement_inner = aout_DateIncrement; \
- (p_symbols)->__aout_InputNew_inner = __aout_InputNew; \
- (p_symbols)->aout_InputDelete_inner = aout_InputDelete; \
+ (p_symbols)->__aout_DecNew_inner = __aout_DecNew; \
+ (p_symbols)->aout_DecDelete_inner = aout_DecDelete; \
+ (p_symbols)->aout_DecNewBuffer_inner = aout_DecNewBuffer; \
+ (p_symbols)->aout_DecDeleteBuffer_inner = aout_DecDeleteBuffer; \
+ (p_symbols)->aout_DecPlay_inner = aout_DecPlay; \
(p_symbols)->aout_VolumeGet_inner = aout_VolumeGet; \
(p_symbols)->aout_VolumeSet_inner = aout_VolumeSet; \
(p_symbols)->aout_VolumeInfos_inner = aout_VolumeInfos; \
(p_symbols)->aout_VolumeUp_inner = aout_VolumeUp; \
(p_symbols)->aout_VolumeDown_inner = aout_VolumeDown; \
+ (p_symbols)->aout_Restart_inner = aout_Restart; \
(p_symbols)->__config_GetInt_inner = __config_GetInt; \
(p_symbols)->__config_PutInt_inner = __config_PutInt; \
(p_symbols)->__config_GetFloat_inner = __config_GetFloat; \