X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;ds=sidebyside;f=src%2Faudio_output%2Faout_internal.h;h=f8ebd79ae2a767c2be53909466ec39e96773f0b7;hb=c48875b31615603d9d2daaa1a1daf161a83e1f2a;hp=9ca72b3a02c17c124a4448ebd3cfdb6c09467911;hpb=d5b5b74679e4a5ae7353dacc87d6991f9325156e;p=vlc diff --git a/src/audio_output/aout_internal.h b/src/audio_output/aout_internal.h index 9ca72b3a02..f8ebd79ae2 100644 --- a/src/audio_output/aout_internal.h +++ b/src/audio_output/aout_internal.h @@ -21,121 +21,238 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ -#if defined(__PLUGIN__) || defined(__BUILTIN__) || !defined(__LIBVLC__) -# error This header file can only be included from LibVLC. -#endif +#ifndef LIBVLC_AOUT_INTERNAL_H +# define LIBVLC_AOUT_INTERNAL_H 1 -#ifndef __LIBVLC_AOUT_INTERNAL_H -# define __LIBVLC_AOUT_INTERNAL_H 1 +/* Max input rate factor (1/4 -> 4) */ +# define AOUT_MAX_INPUT_RATE (4) -#if defined( __APPLE__ ) || defined( SYS_BSD ) -#undef HAVE_ALLOCA -#endif +enum { + AOUT_RESAMPLING_NONE=0, + AOUT_RESAMPLING_UP, + AOUT_RESAMPLING_DOWN +}; -#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 +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 +{ + audio_output_t *p_aout; + aout_input_t *p_input; +}; + +/** an input stream for the audio output */ +struct aout_input_t +{ + unsigned samplerate; /**< Input sample rate */ + + /* 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; + + /* last rate from input */ + int i_last_input_rate; + + /* */ + int i_buffer_lost; + + /* */ + bool b_recycle_vout; + aout_request_vout_t request_vout; +}; + +typedef struct +{ + vlc_mutex_t lock; + module_t *module; /**< Output plugin (or NULL if inactive) */ + aout_input_t *input; + + struct + { + date_t date; + } sync; + + struct + { + vlc_mutex_t lock; + float multiplier; /**< Software volume amplification multiplier */ + struct audio_mixer *mixer; /**< Software volume plugin */ + } volume; + + struct + { + vlc_atomic_t multiplier; + audio_replay_gain_t data; + } gain; + + audio_sample_format_t mixer_format; + audio_sample_format_t input_format; + + /* Filters between mixer and output */ + filter_t *filters[AOUT_MAX_FILTERS]; + int nb_filters; + + vlc_atomic_t restart; +} aout_owner_t; + +typedef struct +{ + audio_output_t output; + aout_owner_t owner; +} aout_instance_t; -#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__); */ \ - } +static inline aout_owner_t *aout_owner (audio_output_t *aout) +{ + return &((aout_instance_t *)aout)->owner; +} /**************************************************************************** * 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, int i_input_rate ); +aout_input_t *aout_InputNew(audio_output_t *, const audio_sample_format_t *, + const audio_sample_format_t *, + const aout_request_vout_t *); +int aout_InputDelete( audio_output_t * p_aout, aout_input_t * p_input ); +block_t *aout_InputPlay( audio_output_t *p_aout, aout_input_t *p_input, + block_t *p_buffer, int i_input_rate, date_t * ); /* 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( vlc_object_t *, filter_t **, int *, + const audio_sample_format_t *, const audio_sample_format_t * ); +#define aout_FiltersCreatePipeline(o, pv, pc, inf, outf) \ + aout_FiltersCreatePipeline(VLC_OBJECT(o), pv, pc, inf, outf) +void aout_FiltersDestroyPipeline( filter_t *const *, unsigned ); +void aout_FiltersPlay( filter_t *const *, unsigned, aout_buffer_t ** ); /* From mixer.c : */ -int aout_MixerNew( aout_instance_t * p_aout ); -void 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 ); +struct audio_mixer *aout_MixerNew(vlc_object_t *, vlc_fourcc_t); +#define aout_MixerNew(o, f) aout_MixerNew(VLC_OBJECT(o), f) +void aout_MixerDelete(struct audio_mixer *); +void aout_MixerRun(struct audio_mixer *, block_t *, float); +float aout_ReplayGainSelect(vlc_object_t *, const char *, + const audio_replay_gain_t *); +#define aout_ReplayGainSelect(o, s, g) \ + aout_ReplayGainSelect(VLC_OBJECT(o), s, g) + +static inline void aout_ReplayGainInit(audio_replay_gain_t *restrict d, + const audio_replay_gain_t *restrict s) +{ + if (s != NULL) + *d = *s; + else + memset (d, 0, sizeof (*d)); +} + /* From output.c : */ -int aout_OutputNew( aout_instance_t * p_aout, - audio_sample_format_t * p_format ); -void aout_OutputPlay( aout_instance_t * p_aout, aout_buffer_t * p_buffer ); -void aout_OutputDelete( aout_instance_t * p_aout ); +int aout_OutputNew( audio_output_t * p_aout, + const audio_sample_format_t * p_format ); +void aout_OutputPlay( audio_output_t * p_aout, aout_buffer_t * p_buffer ); +void aout_OutputPause( audio_output_t * p_aout, bool, mtime_t ); +void aout_OutputFlush( audio_output_t * p_aout, bool ); +void aout_OutputDelete( audio_output_t * p_aout ); /* From common.c : */ -#define aout_New(a) __aout_New(VLC_OBJECT(a)) -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 * ); -void aout_FifoPush( aout_instance_t *, aout_fifo_t *, aout_buffer_t * ); -void aout_FifoSet( aout_instance_t *, aout_fifo_t *, mtime_t ); -void aout_FifoMoveDates( aout_instance_t *, aout_fifo_t *, mtime_t ); -void aout_FifoDestroy( aout_instance_t * p_aout, aout_fifo_t * p_fifo ); -void aout_FormatsPrint( aout_instance_t * p_aout, const char * psz_text, const audio_sample_format_t * p_format1, const audio_sample_format_t * p_format2 ); - - -/* From intf.c :*/ -int aout_VolumeSoftGet( aout_instance_t *, audio_volume_t * ); -int aout_VolumeSoftSet( aout_instance_t *, audio_volume_t ); -int aout_VolumeSoftInfos( aout_instance_t *, audio_volume_t * ); -int aout_VolumeNoneGet( aout_instance_t *, audio_volume_t * ); -int aout_VolumeNoneSet( aout_instance_t *, audio_volume_t ); -int aout_VolumeNoneInfos( aout_instance_t *, audio_volume_t * ); +audio_output_t *aout_New (vlc_object_t *); +#define aout_New(a) aout_New(VLC_OBJECT(a)) +void aout_Destroy (audio_output_t *); + +void aout_FifoInit( vlc_object_t *, aout_fifo_t *, uint32_t ); +mtime_t aout_FifoFirstDate( const aout_fifo_t * ) VLC_USED; +#define aout_FifoInit(o, f, r) aout_FifoInit(VLC_OBJECT(o), f, r) +void aout_FifoPush( aout_fifo_t *, aout_buffer_t * ); +aout_buffer_t *aout_FifoPop( aout_fifo_t * p_fifo ) VLC_USED; +void aout_FifoReset( aout_fifo_t * ); +void aout_FifoMoveDates( aout_fifo_t *, mtime_t ); +void aout_FifoDestroy( aout_fifo_t * p_fifo ); +void aout_FormatsPrint(vlc_object_t *, const char *, + const audio_sample_format_t *, + const audio_sample_format_t *); +#define aout_FormatsPrint(o, t, a, b) \ + aout_FormatsPrint(VLC_OBJECT(o), t, a, b) +bool aout_ChangeFilterString( vlc_object_t *manager, vlc_object_t *aout, + const char *var, const char *name, bool b_add ); /* From dec.c */ -#define aout_DecNew(a, b, c, d) __aout_DecNew(VLC_OBJECT(a), b, c, d) -aout_input_t * __aout_DecNew( vlc_object_t *, aout_instance_t **, audio_sample_format_t *, audio_replay_gain_t * ); -int aout_DecDelete ( aout_instance_t *, aout_input_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 i_input_rate ); - -#endif /* !__LIBVLC_AOUT_INTERNAL_H */ +int aout_DecNew(audio_output_t *, const audio_sample_format_t *, + const audio_replay_gain_t *, const aout_request_vout_t *); +void aout_DecDelete(audio_output_t *); +block_t *aout_DecNewBuffer(audio_output_t *, size_t); +void aout_DecDeleteBuffer(audio_output_t *, block_t *); +int aout_DecPlay(audio_output_t *, block_t *, int i_input_rate); +int aout_DecGetResetLost(audio_output_t *); +void aout_DecChangePause(audio_output_t *, bool b_paused, mtime_t i_date); +void aout_DecFlush(audio_output_t *); +bool aout_DecIsEmpty(audio_output_t *); + +void aout_InputRequestRestart(audio_output_t *); +void aout_RequestRestart(audio_output_t *); +void aout_Shutdown (audio_output_t *); + +/* Audio output locking */ + +#if !defined (NDEBUG) \ + && defined __linux__ && (defined (__i386__) || defined (__x86_64__)) +# define AOUT_DEBUG 1 +#endif + +#ifdef AOUT_DEBUG +enum +{ + OUTPUT_LOCK=1, + VOLUME_LOCK=2, +}; + +void aout_lock_check (unsigned); +void aout_unlock_check (unsigned); + +#else +# define aout_lock_check( i ) (void)0 +# define aout_unlock_check( i ) (void)0 +#endif + +static inline void aout_lock( audio_output_t *p_aout ) +{ + aout_lock_check( OUTPUT_LOCK ); + vlc_mutex_lock( &aout_owner(p_aout)->lock ); +} + +static inline void aout_unlock( audio_output_t *p_aout ) +{ + aout_unlock_check( OUTPUT_LOCK ); + vlc_mutex_unlock( &aout_owner(p_aout)->lock ); +} + +static inline void aout_lock_volume( audio_output_t *p_aout ) +{ + aout_lock_check( VOLUME_LOCK ); + vlc_mutex_lock( &aout_owner(p_aout)->volume.lock ); +} + +static inline void aout_unlock_volume( audio_output_t *p_aout ) +{ + aout_unlock_check( VOLUME_LOCK ); + vlc_mutex_unlock( &aout_owner(p_aout)->volume.lock ); +} + +#define aout_assert_locked( aout ) \ + vlc_assert_locked( &aout_owner(aout)->lock ) + +#endif /* !LIBVLC_AOUT_INTERNAL_H */