X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Faudio_output%2Finput.c;h=a6c6f952ca2231e0b9c2c17a58ade096da93c2f2;hb=887b13d2cee8f5f255602752dd81e7c81864fb76;hp=28620d7ae5c2424336c12fdae17438eb9fd97b41;hpb=fa5084f6804886c9e0a329b247834c23c344312d;p=vlc diff --git a/src/audio_output/input.c b/src/audio_output/input.c index 28620d7ae5..a6c6f952ca 100644 --- a/src/audio_output/input.c +++ b/src/audio_output/input.c @@ -48,10 +48,7 @@ #include "aout_internal.h" -#define AOUT_ASSERT_MIXER_LOCKED vlc_assert_locked( &p_aout->mixer_lock ) -#define AOUT_ASSERT_INPUT_LOCKED vlc_assert_locked( &p_input->lock ) - -static void inputFailure( aout_instance_t *, aout_input_t *, const char * ); +static void inputFailure( audio_output_t *, aout_input_t *, const char * ); static void inputDrop( aout_input_t *, aout_buffer_t * ); static void inputResamplingStop( aout_input_t *p_input ); @@ -61,7 +58,7 @@ static int EqualizerCallback( vlc_object_t *, char const *, vlc_value_t, vlc_value_t, void * ); static int ReplayGainCallback( vlc_object_t *, char const *, vlc_value_t, vlc_value_t, void * ); -static void ReplayGainSelect( aout_instance_t *, aout_input_t * ); +static void ReplayGainSelect( audio_output_t *, aout_input_t * ); static vout_thread_t *RequestVout( void *, vout_thread_t *, video_format_t *, bool ); @@ -69,8 +66,9 @@ static vout_thread_t *RequestVout( void *, /***************************************************************************** * aout_InputNew : allocate a new input and rework the filter pipeline *****************************************************************************/ -int aout_InputNew( aout_instance_t * p_aout, aout_input_t * p_input, const aout_request_vout_t *p_request_vout ) +int aout_InputNew( audio_output_t * p_aout, aout_input_t * p_input, const aout_request_vout_t *p_request_vout ) { + aout_owner_t *owner = aout_owner (p_aout); audio_sample_format_t chain_input_format; audio_sample_format_t chain_output_format; vlc_value_t val, text; @@ -81,9 +79,6 @@ int aout_InputNew( aout_instance_t * p_aout, aout_input_t * p_input, const aout_ p_input->i_nb_resamplers = p_input->i_nb_filters = 0; - /* Prepare FIFO. */ - aout_FifoInit( p_aout, &p_input->mixer.fifo, p_aout->mixer_format.i_rate ); - /* */ if( p_request_vout ) { @@ -97,7 +92,7 @@ int aout_InputNew( aout_instance_t * p_aout, aout_input_t * p_input, const aout_ /* Prepare format structure */ chain_input_format = p_input->input; - chain_output_format = p_aout->mixer_format; + chain_output_format = owner->mixer_format; chain_output_format.i_rate = p_input->input.i_rate; aout_FormatPrepare( &chain_output_format ); @@ -137,7 +132,7 @@ int aout_InputNew( aout_instance_t * p_aout, aout_input_t * p_input, const aout_ var_SetString( p_aout, "visual", val.psz_string ); free( val.psz_string ); } - var_AddCallback( p_aout, "visual", VisualizationCallback, NULL ); + var_AddCallback( p_aout, "visual", VisualizationCallback, p_input ); } if( var_Type( p_aout, "equalizer" ) == 0 ) @@ -266,9 +261,8 @@ int aout_InputNew( aout_instance_t * p_aout, aout_input_t * p_input, const aout_ } /* Create a VLC object */ - static const char typename[] = "audio filter"; p_filter = vlc_custom_create( p_aout, sizeof(*p_filter), - VLC_OBJECT_GENERIC, typename ); + "audio filter" ); if( p_filter == NULL ) { msg_Err( p_aout, "cannot add user filter %s (skipped)", @@ -386,20 +380,20 @@ int aout_InputNew( aout_instance_t * p_aout, aout_input_t * p_input, const aout_ } /* Create resamplers. */ - if ( !AOUT_FMT_NON_LINEAR( &p_aout->mixer_format ) ) + if (!AOUT_FMT_NON_LINEAR(&owner->mixer_format)) { chain_output_format.i_rate = (__MAX(p_input->input.i_rate, - p_aout->mixer_format.i_rate) + owner->mixer_format.i_rate) * (100 + AOUT_MAX_RESAMPLING)) / 100; - if ( chain_output_format.i_rate == p_aout->mixer_format.i_rate ) + if ( chain_output_format.i_rate == owner->mixer_format.i_rate ) { /* Just in case... */ chain_output_format.i_rate++; } - if ( aout_FiltersCreatePipeline( p_aout, p_input->pp_resamplers, - &p_input->i_nb_resamplers, - &chain_output_format, - &p_aout->mixer_format ) < 0 ) + if (aout_FiltersCreatePipeline (p_aout, p_input->pp_resamplers, + &p_input->i_nb_resamplers, + &chain_output_format, + &owner->mixer_format) < 0) { inputFailure( p_aout, p_input, "couldn't set a resampler pipeline"); return -1; @@ -429,9 +423,9 @@ int aout_InputNew( aout_instance_t * p_aout, aout_input_t * p_input, const aout_ ***************************************************************************** * This function must be entered with the mixer lock. *****************************************************************************/ -int aout_InputDelete( aout_instance_t * p_aout, aout_input_t * p_input ) +int aout_InputDelete( audio_output_t * p_aout, aout_input_t * p_input ) { - AOUT_ASSERT_MIXER_LOCKED; + aout_assert_locked( p_aout ); if ( p_input->b_error ) return 0; @@ -448,7 +442,6 @@ int aout_InputDelete( aout_instance_t * p_aout, aout_input_t * p_input ) aout_FiltersDestroyPipeline( p_input->pp_resamplers, p_input->i_nb_resamplers ); p_input->i_nb_resamplers = 0; - aout_FifoDestroy( &p_input->mixer.fifo ); return 0; } @@ -458,34 +451,17 @@ int aout_InputDelete( aout_instance_t * p_aout, aout_input_t * p_input ) ***************************************************************************** * This function must be entered with the input and mixer lock. *****************************************************************************/ -void aout_InputCheckAndRestart( aout_instance_t * p_aout, aout_input_t * p_input ) +void aout_InputCheckAndRestart( audio_output_t * p_aout, aout_input_t * p_input ) { - AOUT_ASSERT_MIXER_LOCKED; - AOUT_ASSERT_INPUT_LOCKED; + aout_assert_locked( p_aout ); if( !p_input->b_restart ) return; - aout_lock_input_fifos( p_aout ); - - /* A little trick to avoid loosing our input fifo and properties */ - - aout_fifo_t fifo = p_input->mixer.fifo; - bool b_paused = p_input->b_paused; - mtime_t i_pause_date = p_input->i_pause_date; - - aout_FifoInit( p_aout, &p_input->mixer.fifo, p_aout->mixer_format.i_rate ); - aout_InputDelete( p_aout, p_input ); - aout_InputNew( p_aout, p_input, &p_input->request_vout ); - p_input->mixer.fifo = fifo; - p_input->b_paused = b_paused; - p_input->i_pause_date = i_pause_date; p_input->b_restart = false; - - aout_unlock_input_fifos( p_aout ); } /***************************************************************************** * aout_InputPlay : play a buffer @@ -494,16 +470,17 @@ void aout_InputCheckAndRestart( aout_instance_t * p_aout, aout_input_t * p_input *****************************************************************************/ /* XXX Do not activate it !! */ //#define AOUT_PROCESS_BEFORE_CHEKS -int aout_InputPlay( aout_instance_t * p_aout, aout_input_t * p_input, - aout_buffer_t * p_buffer, int i_input_rate ) +block_t *aout_InputPlay(audio_output_t *p_aout, aout_input_t *p_input, + block_t *p_buffer, int i_input_rate, date_t *date ) { mtime_t start_date; - AOUT_ASSERT_INPUT_LOCKED; + + aout_assert_locked( p_aout ); if( i_input_rate != INPUT_RATE_DEFAULT && p_input->p_playback_rate_filter == NULL ) { inputDrop( p_input, p_buffer ); - return 0; + return NULL; } #ifdef AOUT_PROCESS_BEFORE_CHEKS @@ -511,7 +488,7 @@ int aout_InputPlay( aout_instance_t * p_aout, aout_input_t * p_input, aout_FiltersPlay( p_aout, p_input->pp_filters, p_input->i_nb_filters, &p_buffer ); if( !p_buffer ) - return 0; + return NULL; /* Actually run the resampler now. */ if ( p_input->i_nb_resamplers > 0 ) @@ -523,11 +500,11 @@ int aout_InputPlay( aout_instance_t * p_aout, aout_input_t * p_input, } if( !p_buffer ) - return 0; + return NULL; if( p_buffer->i_nb_samples <= 0 ) { block_Release( p_buffer ); - return 0; + return NULL; } #endif @@ -542,29 +519,26 @@ int aout_InputPlay( aout_instance_t * p_aout, aout_input_t * p_input, p_input->i_last_input_rate = i_input_rate; } + mtime_t now = mdate(); + /* 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. */ - aout_lock_input_fifos( p_aout ); - start_date = aout_FifoNextStart( &p_input->mixer.fifo ); - aout_unlock_input_fifos( p_aout ); + start_date = date_Get (date); - mtime_t now = mdate(); - if ( start_date != 0 && start_date < now ) + if ( start_date != VLC_TS_INVALID && start_date < now ) { /* The decoder is _very_ late. This can only happen if the user * pauses the stream (or if the decoder is buggy, which cannot * happen :). */ msg_Warn( p_aout, "computed PTS is out of range (%"PRId64"), " "clearing out", now - start_date ); - aout_lock_input_fifos( p_aout ); - aout_FifoSet( &p_input->mixer.fifo, 0 ); - aout_unlock_input_fifos( p_aout ); + aout_OutputFlush( p_aout, false ); if ( p_input->i_resampling_type != AOUT_RESAMPLING_NONE ) msg_Warn( p_aout, "timing screwed, stopping resampling" ); inputResamplingStop( p_input ); p_buffer->i_flags |= BLOCK_FLAG_DISCONTINUITY; - start_date = 0; + start_date = VLC_TS_INVALID; } if ( p_buffer->i_pts < now + AOUT_MIN_PREPARE_TIME ) @@ -573,53 +547,54 @@ int aout_InputPlay( aout_instance_t * p_aout, aout_input_t * p_input, * can't present it anyway, so drop the buffer. */ msg_Warn( p_aout, "PTS is out of range (%"PRId64"), dropping buffer", now - p_buffer->i_pts ); - inputDrop( p_input, p_buffer ); inputResamplingStop( p_input ); - return 0; + return NULL; } /* If the audio drift is too big then it's not worth trying to resample * the audio. */ - if( !start_date ) + if( start_date == VLC_TS_INVALID ) + { start_date = p_buffer->i_pts; + date_Set (date, start_date); + } - mtime_t tolerance = 3 * AOUT_PTS_TOLERANCE - * i_input_rate / INPUT_RATE_DEFAULT; mtime_t drift = start_date - p_buffer->i_pts; - if( drift < -tolerance ) + if( drift < -i_input_rate * 3 * AOUT_MAX_PTS_ADVANCE / INPUT_RATE_DEFAULT ) { msg_Warn( p_aout, "buffer way too early (%"PRId64"), clearing queue", drift ); - aout_lock_input_fifos( p_aout ); - aout_FifoSet( &p_input->mixer.fifo, 0 ); - aout_unlock_input_fifos( p_aout ); + aout_OutputFlush( p_aout, false ); if ( p_input->i_resampling_type != AOUT_RESAMPLING_NONE ) msg_Warn( p_aout, "timing screwed, stopping resampling" ); inputResamplingStop( p_input ); p_buffer->i_flags |= BLOCK_FLAG_DISCONTINUITY; start_date = p_buffer->i_pts; + date_Set (date, start_date); + drift = 0; } - else if( drift > +tolerance ) + else + if( drift > +i_input_rate * 3 * AOUT_MAX_PTS_DELAY / INPUT_RATE_DEFAULT ) { msg_Warn( p_aout, "buffer way too late (%"PRId64"), dropping buffer", drift ); inputDrop( p_input, p_buffer ); - return 0; + return NULL; } #ifndef AOUT_PROCESS_BEFORE_CHEKS /* Run pre-filters. */ aout_FiltersPlay( p_input->pp_filters, p_input->i_nb_filters, &p_buffer ); if( !p_buffer ) - return 0; + return NULL; #endif /* Run the resampler if needed. * We first need to calculate the output rate of this resampler. */ if ( ( p_input->i_resampling_type == AOUT_RESAMPLING_NONE ) && - ( drift < -AOUT_PTS_TOLERANCE || drift > +AOUT_PTS_TOLERANCE ) && + ( drift < -AOUT_MAX_PTS_ADVANCE || drift > +AOUT_MAX_PTS_DELAY ) && p_input->i_nb_resamplers > 0 ) { /* Can happen in several circumstances : @@ -695,28 +670,23 @@ int aout_InputPlay( aout_instance_t * p_aout, aout_input_t * p_input, } if( !p_buffer ) - return 0; + return NULL; if( p_buffer->i_nb_samples <= 0 ) { block_Release( p_buffer ); - return 0; + return NULL; } #endif - /* Adding the start date will be managed by aout_FifoPush(). */ p_buffer->i_pts = start_date; - - aout_lock_input_fifos( p_aout ); - aout_FifoPush( &p_input->mixer.fifo, p_buffer ); - aout_unlock_input_fifos( p_aout ); - return 0; + return p_buffer; } /***************************************************************************** * static functions *****************************************************************************/ -static void inputFailure( aout_instance_t * p_aout, aout_input_t * p_input, +static void inputFailure( audio_output_t * p_aout, aout_input_t * p_input, const char * psz_error_message ) { /* error message */ @@ -726,7 +696,6 @@ static void inputFailure( aout_instance_t * p_aout, aout_input_t * p_input, aout_FiltersDestroyPipeline( p_input->pp_filters, p_input->i_nb_filters ); aout_FiltersDestroyPipeline( p_input->pp_resamplers, p_input->i_nb_resamplers ); - aout_FifoDestroy( &p_input->mixer.fifo ); var_Destroy( p_aout, "visual" ); var_Destroy( p_aout, "equalizer" ); var_Destroy( p_aout, "audio-filter" ); @@ -763,7 +732,7 @@ static void inputResamplingStop( aout_input_t *p_input ) static vout_thread_t *RequestVout( void *p_private, vout_thread_t *p_vout, video_format_t *p_fmt, bool b_recycle ) { - aout_instance_t *p_aout = p_private; + audio_output_t *p_aout = p_private; VLC_UNUSED(b_recycle); vout_configuration_t cfg = { .vout = p_vout, @@ -790,81 +759,75 @@ vout_thread_t *aout_filter_RequestVout( filter_t *p_filter, p_vout, p_fmt, p_input->b_recycle_vout ); } -static int ChangeFiltersString( aout_instance_t * p_aout, const char* psz_variable, - const char *psz_name, bool b_add ) +static inline bool ChangeFiltersString (vlc_object_t *aout, const char *var, + const char *filter, bool add) { - return aout_ChangeFilterString( VLC_OBJECT(p_aout), p_aout, - psz_variable, psz_name, b_add ) ? 1 : 0; + return aout_ChangeFilterString (aout, aout, var, filter, add); } -static int VisualizationCallback( vlc_object_t *p_this, char const *psz_cmd, - vlc_value_t oldval, vlc_value_t newval, void *p_data ) +static int VisualizationCallback (vlc_object_t *obj, char const *var, + vlc_value_t oldval, vlc_value_t newval, + void *data) { - aout_instance_t *p_aout = (aout_instance_t *)p_this; - char *psz_mode = newval.psz_string; - (void)psz_cmd; (void)oldval; (void)p_data; + const char *mode = newval.psz_string; + aout_input_t *input = data; - if( !psz_mode || !*psz_mode ) + if (!*mode) + { + ChangeFiltersString (obj, "audio-visual", "goom", false); + ChangeFiltersString (obj, "audio-visual", "visual", false); + ChangeFiltersString (obj, "audio-visual", "projectm", false); + } + else if (!strcmp ("goom", mode)) + { + ChangeFiltersString (obj, "audio-visual", "visual", false ); + ChangeFiltersString (obj, "audio-visual", "goom", true ); + ChangeFiltersString (obj, "audio-visual", "projectm", false ); + } + else if (!strcmp ("projectm", mode)) { - ChangeFiltersString( p_aout, "audio-visual", "goom", false ); - ChangeFiltersString( p_aout, "audio-visual", "visual", false ); - ChangeFiltersString( p_aout, "audio-visual", "projectm", false ); + ChangeFiltersString (obj, "audio-visual", "visual", false); + ChangeFiltersString (obj, "audio-visual", "goom", false); + ChangeFiltersString (obj, "audio-visual", "projectm", true); } else { - if( !strcmp( "goom", psz_mode ) ) - { - ChangeFiltersString( p_aout, "audio-visual", "visual", false ); - ChangeFiltersString( p_aout, "audio-visual", "goom", true ); - ChangeFiltersString( p_aout, "audio-visual", "projectm", false ); - } - else if( !strcmp( "projectm", psz_mode ) ) - { - ChangeFiltersString( p_aout, "audio-visual", "visual", false ); - ChangeFiltersString( p_aout, "audio-visual", "goom", false ); - ChangeFiltersString( p_aout, "audio-visual", "projectm", true ); - } - else - { - var_Create( p_aout, "effect-list", VLC_VAR_STRING ); - var_SetString( p_aout, "effect-list", psz_mode ); + var_Create (obj, "effect-list", VLC_VAR_STRING); + var_SetString (obj, "effect-list", mode); - ChangeFiltersString( p_aout, "audio-visual", "goom", false ); - ChangeFiltersString( p_aout, "audio-visual", "visual", true ); - ChangeFiltersString( p_aout, "audio-visual", "projectm", false ); - } + ChangeFiltersString (obj, "audio-visual", "goom", false); + ChangeFiltersString (obj, "audio-visual", "visual", true); + ChangeFiltersString (obj, "audio-visual", "projectm", false); } - /* That sucks */ - AoutInputsMarkToRestart( p_aout ); + /* That sucks FIXME: use "input" instead of cast */ + AoutInputsMarkToRestart ((audio_output_t *)obj); + (void) var; (void) oldval; return VLC_SUCCESS; } -static int EqualizerCallback( vlc_object_t *p_this, char const *psz_cmd, - vlc_value_t oldval, vlc_value_t newval, void *p_data ) +static int EqualizerCallback (vlc_object_t *obj, char const *cmd, + vlc_value_t oldval, vlc_value_t newval, + void *data) { - aout_instance_t *p_aout = (aout_instance_t *)p_this; - char *psz_mode = newval.psz_string; - int i_ret; - (void)psz_cmd; (void)oldval; (void)p_data; + char *mode = newval.psz_string; + aout_input_t *input = data; + bool ret; - if( !psz_mode || !*psz_mode ) - { - i_ret = ChangeFiltersString( p_aout, "audio-filter", "equalizer", - false ); - } + (void) cmd; (void) oldval; + if (!*mode) + ret = ChangeFiltersString (obj, "audio-filter", "equalizer", false); else { - var_Create( p_aout, "equalizer-preset", VLC_VAR_STRING ); - var_SetString( p_aout, "equalizer-preset", psz_mode ); - i_ret = ChangeFiltersString( p_aout, "audio-filter", "equalizer", - true ); + var_Create (obj, "equalizer-preset", VLC_VAR_STRING); + var_SetString (obj, "equalizer-preset", mode); + ret = ChangeFiltersString (obj, "audio-filter", "equalizer", true); } /* That sucks */ - if( i_ret == 1 ) - AoutInputsMarkToRestart( p_aout ); + if (ret) + AoutInputsMarkToRestart ((audio_output_t *)obj); return VLC_SUCCESS; } @@ -873,17 +836,18 @@ static int ReplayGainCallback( vlc_object_t *p_this, char const *psz_cmd, { VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval); VLC_UNUSED(newval); VLC_UNUSED(p_data); - aout_instance_t *p_aout = (aout_instance_t *)p_this; + audio_output_t *aout = (audio_output_t *)p_this; + aout_owner_t *owner = aout_owner (aout); - aout_lock_mixer( p_aout ); - if( p_aout->p_input != NULL ) - ReplayGainSelect( p_aout, p_aout->p_input ); - aout_unlock_mixer( p_aout ); + aout_lock (aout); + if (owner->input != NULL) + ReplayGainSelect (aout, owner->input); + aout_unlock (aout); return VLC_SUCCESS; } -static void ReplayGainSelect( aout_instance_t *p_aout, aout_input_t *p_input ) +static void ReplayGainSelect( audio_output_t *p_aout, aout_input_t *p_input ) { char *psz_replay_gain = var_GetNonEmptyString( p_aout, "audio-replay-gain-mode" ); @@ -891,7 +855,7 @@ static void ReplayGainSelect( aout_instance_t *p_aout, aout_input_t *p_input ) int i_use; float f_gain; - p_input->mixer.multiplier = 1.0; + p_input->multiplier = 1.0; if( !psz_replay_gain ) return; @@ -922,14 +886,14 @@ static void ReplayGainSelect( aout_instance_t *p_aout, aout_input_t *p_input ) f_gain = var_GetFloat( p_aout, "audio-replay-gain-default" ); else f_gain = 0.0; - p_input->mixer.multiplier = pow( 10.0, f_gain / 20.0 ); + p_input->multiplier = pow( 10.0, f_gain / 20.0 ); /* */ if( p_input->replay_gain.pb_peak[i_use] && var_GetBool( p_aout, "audio-replay-gain-peak-protection" ) && - p_input->replay_gain.pf_peak[i_use] * p_input->mixer.multiplier > 1.0 ) + p_input->replay_gain.pf_peak[i_use] * p_input->multiplier > 1.0 ) { - p_input->mixer.multiplier = 1.0f / p_input->replay_gain.pf_peak[i_use]; + p_input->multiplier = 1.0f / p_input->replay_gain.pf_peak[i_use]; } free( psz_replay_gain );