X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Faudio_output%2Faout_internal.h;h=6ef8da46cd339d4ee01e0469165abbd0bdaacca1;hb=7a87d5768beaecfc8132a875d08b53ec5b780bee;hp=7b8011b4699e052ab32bdbddb46eaebf2a1d4421;hpb=bf48c33dbb564a5ede1581ab9bcb2db9213fba2f;p=vlc diff --git a/src/audio_output/aout_internal.h b/src/audio_output/aout_internal.h index 7b8011b469..6ef8da46cd 100644 --- a/src/audio_output/aout_internal.h +++ b/src/audio_output/aout_internal.h @@ -21,71 +21,99 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ -#if defined( __APPLE__ ) || defined( SYS_BSD ) -#undef HAVE_ALLOCA +#if defined(__PLUGIN__) || defined(__BUILTIN__) || !defined(__LIBVLC__) +# error This header file can only be included from LibVLC. #endif -#ifdef HAVE_ALLOCA -# define ALLOCA_TEST( p_alloc, p_new_buffer ) \ - if ( (p_alloc)->i_alloc_type == AOUT_ALLOC_STACK ) \ - { \ - (p_new_buffer) = alloca( i_alloc_size + sizeof(aout_buffer_t) );\ - i_alloc_type = AOUT_ALLOC_STACK; \ - } \ - else -#else -# define ALLOCA_TEST( p_alloc, p_new_buffer ) -#endif +#ifndef __LIBVLC_AOUT_INTERNAL_H +# define __LIBVLC_AOUT_INTERNAL_H 1 -#define aout_BufferAlloc( p_alloc, i_nb_usec, p_previous_buffer, \ - p_new_buffer ) \ - if ( (p_alloc)->i_alloc_type == AOUT_ALLOC_NONE ) \ - { \ - (p_new_buffer) = p_previous_buffer; \ - } \ - else \ - { \ - int i_alloc_size, i_alloc_type; \ - i_alloc_size = (int)( (uint64_t)(p_alloc)->i_bytes_per_sec \ - * (i_nb_usec) / 1000000 + 1 ); \ - ALLOCA_TEST( p_alloc, p_new_buffer ) \ - { \ - (p_new_buffer) = malloc( i_alloc_size + sizeof(aout_buffer_t) );\ - i_alloc_type = AOUT_ALLOC_HEAP; \ - } \ - if ( p_new_buffer != NULL ) \ - { \ - (p_new_buffer)->i_alloc_type = i_alloc_type; \ - (p_new_buffer)->i_size = i_alloc_size; \ - (p_new_buffer)->p_buffer = (byte_t *)(p_new_buffer) \ - + sizeof(aout_buffer_t); \ - (p_new_buffer)->b_discontinuity = VLC_FALSE; \ - if ( (p_previous_buffer) != NULL ) \ - { \ - (p_new_buffer)->start_date = \ - ((aout_buffer_t *)p_previous_buffer)->start_date;\ - (p_new_buffer)->end_date = \ - ((aout_buffer_t *)p_previous_buffer)->end_date; \ - } \ - } \ - /* we'll keep that for a while --Meuuh */ \ - /* else printf("%s:%d\n", __FILE__, __LINE__); */ \ - } +aout_buffer_t *aout_BufferAlloc(aout_alloc_t *allocation, mtime_t microseconds, + aout_buffer_t *old_buffer); + +typedef struct +{ + struct vout_thread_t *(*pf_request_vout)( void *, struct vout_thread_t *, + video_format_t *, bool ); + void *p_private; +} aout_request_vout_t; + +struct filter_owner_sys_t +{ + aout_instance_t *p_aout; + aout_input_t *p_input; +}; + +block_t *aout_FilterBufferNew( filter_t *, int ); + +/** an input stream for the audio output */ +struct aout_input_t +{ + /* When this lock is taken, the pipeline cannot be changed by a + * third-party. */ + vlc_mutex_t lock; + + audio_sample_format_t input; + aout_alloc_t input_alloc; + + /* pre-filters */ + filter_t * pp_filters[AOUT_MAX_FILTERS]; + int i_nb_filters; + + filter_t * p_playback_rate_filter; + + /* resamplers */ + filter_t * pp_resamplers[AOUT_MAX_FILTERS]; + int i_nb_resamplers; + int i_resampling_type; + mtime_t i_resamp_start_date; + int i_resamp_start_drift; + + /* Mixer information */ + audio_replay_gain_t replay_gain; + + /* If b_restart == 1, the input pipeline will be re-created. */ + bool b_restart; + + /* If b_error == 1, there is no input pipeline. */ + bool b_error; + + /* Did we just change the output format? (expect buffer inconsistencies) */ + bool b_changed; + + /* last rate from input */ + int i_last_input_rate; + + /* */ + int i_buffer_lost; + + /* */ + bool b_paused; + mtime_t i_pause_date; + + /* */ + bool b_recycle_vout; + aout_request_vout_t request_vout; + + /* */ + aout_mixer_input_t mixer; + }; /**************************************************************************** * Prototypes *****************************************************************************/ + /* From input.c : */ -int aout_InputNew( aout_instance_t * p_aout, aout_input_t * p_input ); +int aout_InputNew( aout_instance_t * p_aout, aout_input_t * p_input, const aout_request_vout_t * ); 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 ); + aout_buffer_t * p_buffer, int i_input_rate ); /* From filters.c : */ -int aout_FiltersCreatePipeline ( aout_instance_t * p_aout, aout_filter_t ** pp_filters, int * pi_nb_filters, const audio_sample_format_t * p_input_format, const audio_sample_format_t * p_output_format ); -void aout_FiltersDestroyPipeline ( aout_instance_t * p_aout, aout_filter_t ** pp_filters, int i_nb_filters ); -void aout_FiltersPlay ( aout_instance_t * p_aout, aout_filter_t ** pp_filters, int i_nb_filters, aout_buffer_t ** pp_input_buffer ); -void aout_FiltersHintBuffers( aout_instance_t * p_aout, aout_filter_t ** pp_filters, int i_nb_filters, aout_alloc_t * p_first_alloc ); +int aout_FiltersCreatePipeline ( aout_instance_t * p_aout, filter_t ** pp_filters, int * pi_nb_filters, const audio_sample_format_t * p_input_format, const audio_sample_format_t * p_output_format ); +void aout_FiltersDestroyPipeline ( aout_instance_t * p_aout, filter_t ** pp_filters, int i_nb_filters ); +void aout_FiltersPlay ( filter_t ** pp_filters, unsigned i_nb_filters, aout_buffer_t ** pp_input_buffer ); +void aout_FiltersHintBuffers( aout_instance_t * p_aout, filter_t ** pp_filters, int i_nb_filters, aout_alloc_t * p_first_alloc ); /* From mixer.c : */ int aout_MixerNew( aout_instance_t * p_aout ); @@ -103,8 +131,8 @@ void aout_OutputDelete( aout_instance_t * p_aout ); /* From common.c : */ #define aout_New(a) __aout_New(VLC_OBJECT(a)) +/* Release with vlc_object_release() */ aout_instance_t * __aout_New ( vlc_object_t * ); -void aout_Delete ( aout_instance_t * ); void aout_FifoInit( aout_instance_t *, aout_fifo_t *, uint32_t ); mtime_t aout_FifoNextStart( aout_instance_t *, aout_fifo_t * ); @@ -124,10 +152,167 @@ int aout_VolumeNoneSet( aout_instance_t *, audio_volume_t ); int aout_VolumeNoneInfos( aout_instance_t *, audio_volume_t * ); /* From dec.c */ -#define aout_DecNew(a, b, c) __aout_DecNew(VLC_OBJECT(a), b, c) -aout_input_t * __aout_DecNew( vlc_object_t *, aout_instance_t **, audio_sample_format_t * ); +#define aout_DecNew(a, b, c, d, e) __aout_DecNew(VLC_OBJECT(a), b, c, d, e) +aout_input_t * __aout_DecNew( vlc_object_t *, aout_instance_t **, + audio_sample_format_t *, const audio_replay_gain_t *, + const aout_request_vout_t * ); int aout_DecDelete ( aout_instance_t *, aout_input_t * ); -aout_buffer_t * aout_DecNewBuffer( aout_instance_t *, aout_input_t *, size_t ); +aout_buffer_t * aout_DecNewBuffer( aout_input_t *, size_t ); void aout_DecDeleteBuffer( aout_instance_t *, aout_input_t *, aout_buffer_t * ); -int aout_DecPlay( aout_instance_t *, aout_input_t *, aout_buffer_t * ); +int aout_DecPlay( aout_instance_t *, aout_input_t *, aout_buffer_t *, int i_input_rate ); +int aout_DecGetResetLost( aout_instance_t *, aout_input_t * ); +void aout_DecChangePause( aout_instance_t *, aout_input_t *, bool b_paused, mtime_t i_date ); +void aout_DecFlush( aout_instance_t *, aout_input_t * ); + +/* Audio output locking */ + +#if !defined (NDEBUG) \ + && defined __linux__ && (defined (__i386__) || defined (__x86_64__)) +# define AOUT_DEBUG 1 +#endif + +#ifdef AOUT_DEBUG +enum +{ + MIXER_LOCK=1, + INPUT_LOCK=2, + INPUT_FIFO_LOCK=4, + OUTPUT_FIFO_LOCK=8, +}; + +void aout_lock (unsigned); +void aout_unlock (unsigned); + +#else +# define aout_lock( i ) (void)0 +# define aout_unlock( i ) (void)0 +#endif + +static inline void aout_lock_mixer( aout_instance_t *p_aout ) +{ + aout_lock( MIXER_LOCK ); + vlc_mutex_lock( &p_aout->mixer_lock ); +} + +static inline void aout_unlock_mixer( aout_instance_t *p_aout ) +{ + aout_unlock( MIXER_LOCK ); + vlc_mutex_unlock( &p_aout->mixer_lock ); +} + +static inline void aout_lock_input_fifos( aout_instance_t *p_aout ) +{ + aout_lock( INPUT_FIFO_LOCK ); + vlc_mutex_lock( &p_aout->input_fifos_lock ); +} + +static inline void aout_unlock_input_fifos( aout_instance_t *p_aout ) +{ + aout_unlock( INPUT_FIFO_LOCK ); + vlc_mutex_unlock( &p_aout->input_fifos_lock ); +} + +static inline void aout_lock_output_fifo( aout_instance_t *p_aout ) +{ + aout_lock( OUTPUT_FIFO_LOCK ); + vlc_mutex_lock( &p_aout->output_fifo_lock ); +} + +static inline void aout_unlock_output_fifo( aout_instance_t *p_aout ) +{ + aout_unlock( OUTPUT_FIFO_LOCK ); + vlc_mutex_unlock( &p_aout->output_fifo_lock ); +} + +static inline void aout_lock_input( aout_instance_t *p_aout, aout_input_t * p_input ) +{ + (void)p_aout; + aout_lock( INPUT_LOCK ); + vlc_mutex_lock( &p_input->lock ); +} + +static inline void aout_unlock_input( aout_instance_t *p_aout, aout_input_t * p_input ) +{ + (void)p_aout; + aout_unlock( INPUT_LOCK ); + vlc_mutex_unlock( &p_input->lock ); +} + + +/* Helpers */ + +/** + * This function will safely mark aout input to be restarted as soon as + * possible to take configuration changes into account */ +static inline void AoutInputsMarkToRestart( aout_instance_t *p_aout ) +{ + int i; + aout_lock_mixer( p_aout ); + for( i = 0; i < p_aout->i_nb_inputs; i++ ) + p_aout->pp_inputs[i]->b_restart = true; + aout_unlock_mixer( p_aout ); +} + +/* This function will add or remove a a module from a string list (comma + * separated). It will return true if there is a modification + * In case p_aout is NULL, we will use configuration instead of variable */ +static inline bool AoutChangeFilterString( vlc_object_t *p_obj, aout_instance_t * p_aout, + const char* psz_variable, + const char *psz_name, bool b_add ) +{ + char *psz_val; + char *psz_parser; + + if( *psz_name == '\0' ) + return false; + + if( p_aout ) + psz_val = var_GetString( p_aout, psz_variable ); + else + psz_val = config_GetPsz( p_obj, "audio-filter" ); + + if( !psz_val ) + psz_val = strdup( "" ); + + psz_parser = strstr( psz_val, psz_name ); + + if( ( b_add && psz_parser ) || ( !b_add && !psz_parser ) ) + { + /* Nothing to do */ + free( psz_val ); + return false; + } + + if( b_add ) + { + char *psz_old = psz_val; + if( *psz_old ) + { + if( asprintf( &psz_val, "%s:%s", psz_old, psz_name ) == -1 ) + psz_val = NULL; + } + else + psz_val = strdup( psz_name ); + free( psz_old ); + } + else + { + const int i_name = strlen( psz_name ); + const char *psz_next; + + psz_next = &psz_parser[i_name]; + if( *psz_next == ':' ) + psz_next++; + + memmove( psz_parser, psz_next, strlen(psz_next)+1 ); + } + + if( p_aout ) + var_SetString( p_aout, psz_variable, psz_val ); + else + config_PutPsz( p_obj, psz_variable, psz_val ); + free( psz_val ); + return true; +} +#endif /* !__LIBVLC_AOUT_INTERNAL_H */