X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Faudio_output%2Finput.c;h=9820854bbcd79487503cb08c420dea45e44fedc3;hb=d96db36fd8a8df02339cb6bf26d796d24b332e02;hp=4cc4b55f1ff9ac10a708d8b5f2591f6fa7551349;hpb=aa7fcdb139b2b733af6e7c3cd8e1ab6b75d4e963;p=vlc diff --git a/src/audio_output/input.c b/src/audio_output/input.c index 4cc4b55f1f..9820854bbc 100644 --- a/src/audio_output/input.c +++ b/src/audio_output/input.c @@ -1,24 +1,24 @@ /***************************************************************************** * input.c : internal management of input streams for the audio output ***************************************************************************** - * Copyright (C) 2002-2007 the VideoLAN team + * Copyright (C) 2002-2007 VLC authors and VideoLAN * $Id$ * * Authors: Christophe Massiot * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 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. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ /***************************************************************************** @@ -29,401 +29,30 @@ # include "config.h" #endif -#include - #include - -#include -#include -#include -#include - #include -#include /* for vout_Request */ -#include - #include #include -#include +#include #include "aout_internal.h" -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 ); - -static int VisualizationCallback( vlc_object_t *, char const *, - vlc_value_t, vlc_value_t, void * ); -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 float ReplayGainSelect(vlc_object_t *, const char *, - const audio_replay_gain_t *); - -static vout_thread_t *RequestVout( void *, - vout_thread_t *, video_format_t *, bool ); +static void inputDrop( aout_input_t *, block_t * ); +static void inputResamplingStop( audio_output_t *, aout_input_t * ); /***************************************************************************** * aout_InputNew : allocate a new input and rework the filter pipeline *****************************************************************************/ -int aout_InputNew( audio_output_t * p_aout, - const audio_sample_format_t *restrict infmt, - const audio_sample_format_t *restrict outfmt, - aout_input_t * p_input, - const aout_request_vout_t *p_request_vout ) +aout_input_t *aout_InputNew (const audio_sample_format_t *restrict infmt) { - audio_sample_format_t chain_input_format; - audio_sample_format_t chain_output_format; - vlc_value_t val, text; - char *psz_filters, *psz_visual, *psz_scaletempo; - int i_visual; + aout_input_t *p_input = xmalloc (sizeof (*p_input)); - aout_FormatPrint( p_aout, "input", infmt ); p_input->samplerate = infmt->i_rate; - p_input->i_nb_resamplers = p_input->i_nb_filters = 0; - - /* */ - if( p_request_vout ) - { - p_input->request_vout = *p_request_vout; - } - else - { - p_input->request_vout.pf_request_vout = RequestVout; - p_input->request_vout.p_private = p_aout; - } - - /* Prepare format structure */ - chain_input_format = *infmt; - chain_output_format = *outfmt; - chain_output_format.i_rate = infmt->i_rate; - aout_FormatPrepare( &chain_output_format ); - - /* Now add user filters */ - if( var_Type( p_aout, "visual" ) == 0 ) - { - var_Create( p_aout, "visual", VLC_VAR_STRING | VLC_VAR_HASCHOICE ); - text.psz_string = _("Visualizations"); - var_Change( p_aout, "visual", VLC_VAR_SETTEXT, &text, NULL ); - val.psz_string = (char*)""; text.psz_string = _("Disable"); - var_Change( p_aout, "visual", VLC_VAR_ADDCHOICE, &val, &text ); - val.psz_string = (char*)"spectrometer"; text.psz_string = _("Spectrometer"); - var_Change( p_aout, "visual", VLC_VAR_ADDCHOICE, &val, &text ); - val.psz_string = (char*)"scope"; text.psz_string = _("Scope"); - var_Change( p_aout, "visual", VLC_VAR_ADDCHOICE, &val, &text ); - val.psz_string = (char*)"spectrum"; text.psz_string = _("Spectrum"); - var_Change( p_aout, "visual", VLC_VAR_ADDCHOICE, &val, &text ); - val.psz_string = (char*)"vuMeter"; text.psz_string = _("Vu meter"); - var_Change( p_aout, "visual", VLC_VAR_ADDCHOICE, &val, &text ); - - /* Look for goom plugin */ - if( module_exists( "goom" ) ) - { - val.psz_string = (char*)"goom"; text.psz_string = (char*)"Goom"; - var_Change( p_aout, "visual", VLC_VAR_ADDCHOICE, &val, &text ); - } - - /* Look for libprojectM plugin */ - if( module_exists( "projectm" ) ) - { - val.psz_string = (char*)"projectm"; text.psz_string = (char*)"projectM"; - var_Change( p_aout, "visual", VLC_VAR_ADDCHOICE, &val, &text ); - } - - if( var_Get( p_aout, "effect-list", &val ) == VLC_SUCCESS ) - { - var_SetString( p_aout, "visual", val.psz_string ); - free( val.psz_string ); - } - var_AddCallback( p_aout, "visual", VisualizationCallback, p_input ); - } - - if( var_Type( p_aout, "equalizer" ) == 0 ) - { - module_config_t *p_config; - int i; - - p_config = config_FindConfig( VLC_OBJECT(p_aout), "equalizer-preset" ); - if( p_config && p_config->i_list ) - { - var_Create( p_aout, "equalizer", - VLC_VAR_STRING | VLC_VAR_HASCHOICE ); - text.psz_string = _("Equalizer"); - var_Change( p_aout, "equalizer", VLC_VAR_SETTEXT, &text, NULL ); - - val.psz_string = (char*)""; text.psz_string = _("Disable"); - var_Change( p_aout, "equalizer", VLC_VAR_ADDCHOICE, &val, &text ); - - for( i = 0; i < p_config->i_list; i++ ) - { - val.psz_string = (char *)p_config->ppsz_list[i]; - text.psz_string = (char *)p_config->ppsz_list_text[i]; - var_Change( p_aout, "equalizer", VLC_VAR_ADDCHOICE, - &val, &text ); - } - - var_AddCallback( p_aout, "equalizer", EqualizerCallback, p_input ); - } - } - - if( var_Type( p_aout, "audio-filter" ) == 0 ) - { - var_Create( p_aout, "audio-filter", - VLC_VAR_STRING | VLC_VAR_DOINHERIT ); - text.psz_string = _("Audio filters"); - var_Change( p_aout, "audio-filter", VLC_VAR_SETTEXT, &text, NULL ); - } - if( var_Type( p_aout, "audio-visual" ) == 0 ) - { - var_Create( p_aout, "audio-visual", - VLC_VAR_STRING | VLC_VAR_DOINHERIT ); - text.psz_string = _("Audio visualizations"); - var_Change( p_aout, "audio-visual", VLC_VAR_SETTEXT, &text, NULL ); - } - - if( var_Type( p_aout, "audio-replay-gain-mode" ) == 0 ) - { - module_config_t *p_config; - int i; - - p_config = config_FindConfig( VLC_OBJECT(p_aout), "audio-replay-gain-mode" ); - if( p_config && p_config->i_list ) - { - var_Create( p_aout, "audio-replay-gain-mode", - VLC_VAR_STRING | VLC_VAR_DOINHERIT ); - - text.psz_string = _("Replay gain"); - var_Change( p_aout, "audio-replay-gain-mode", VLC_VAR_SETTEXT, &text, NULL ); - - for( i = 0; i < p_config->i_list; i++ ) - { - val.psz_string = (char *)p_config->ppsz_list[i]; - text.psz_string = (char *)p_config->ppsz_list_text[i]; - var_Change( p_aout, "audio-replay-gain-mode", VLC_VAR_ADDCHOICE, - &val, &text ); - } - - var_AddCallback( p_aout, "audio-replay-gain-mode", ReplayGainCallback, p_input ); - } - } - - char *gain = var_InheritString (p_aout, "audio-replay-gain-mode"); - p_input->multiplier = ReplayGainSelect (VLC_OBJECT(p_aout), gain, - &p_input->replay_gain); - free (gain); - - if( var_Type( p_aout, "audio-replay-gain-preamp" ) == 0 ) - { - var_Create( p_aout, "audio-replay-gain-preamp", - VLC_VAR_FLOAT | VLC_VAR_DOINHERIT ); - } - if( var_Type( p_aout, "audio-replay-gain-default" ) == 0 ) - { - var_Create( p_aout, "audio-replay-gain-default", - VLC_VAR_FLOAT | VLC_VAR_DOINHERIT ); - } - if( var_Type( p_aout, "audio-replay-gain-peak-protection" ) == 0 ) - { - var_Create( p_aout, "audio-replay-gain-peak-protection", - VLC_VAR_BOOL | VLC_VAR_DOINHERIT ); - } - - psz_filters = var_GetString( p_aout, "audio-filter" ); - psz_visual = var_GetString( p_aout, "audio-visual"); - psz_scaletempo = var_InheritBool( p_aout, "audio-time-stretch" ) ? strdup( "scaletempo" ) : NULL; - - p_input->b_recycle_vout = psz_visual && *psz_visual; - - /* parse user filter lists */ - char *const ppsz_array[] = { psz_scaletempo, psz_filters, psz_visual }; - p_input->p_playback_rate_filter = NULL; - - for( i_visual = 0; i_visual < 3 && AOUT_FMT_LINEAR(&chain_output_format); i_visual++ ) - { - char *psz_next = NULL; - char *psz_parser = ppsz_array[i_visual]; - - if( psz_parser == NULL || !*psz_parser ) - continue; - - while( psz_parser && *psz_parser ) - { - filter_t * p_filter = NULL; - - if( p_input->i_nb_filters >= AOUT_MAX_FILTERS ) - { - msg_Dbg( p_aout, "max filters reached (%d)", AOUT_MAX_FILTERS ); - break; - } - - while( *psz_parser == ' ' && *psz_parser == ':' ) - { - psz_parser++; - } - if( ( psz_next = strchr( psz_parser , ':' ) ) ) - { - *psz_next++ = '\0'; - } - if( *psz_parser =='\0' ) - { - break; - } - - /* Create a VLC object */ - p_filter = vlc_custom_create( p_aout, sizeof(*p_filter), - "audio filter" ); - if( p_filter == NULL ) - { - msg_Err( p_aout, "cannot add user filter %s (skipped)", - psz_parser ); - psz_parser = psz_next; - continue; - } - - p_filter->p_owner = malloc( sizeof(*p_filter->p_owner) ); - p_filter->p_owner->p_aout = p_aout; - p_filter->p_owner->p_input = p_input; - - /* request format */ - memcpy( &p_filter->fmt_in.audio, &chain_output_format, - sizeof(audio_sample_format_t) ); - p_filter->fmt_in.i_codec = chain_output_format.i_format; - memcpy( &p_filter->fmt_out.audio, &chain_output_format, - sizeof(audio_sample_format_t) ); - p_filter->fmt_out.i_codec = chain_output_format.i_format; - p_filter->pf_audio_buffer_new = aout_FilterBufferNew; - - /* try to find the requested filter */ - if( i_visual == 2 ) /* this can only be a visualization module */ - { - p_filter->p_module = module_need( p_filter, "visualization2", - psz_parser, true ); - } - else /* this can be a audio filter module as well as a visualization module */ - { - p_filter->p_module = module_need( p_filter, "audio filter", - psz_parser, true ); - - if ( p_filter->p_module == NULL ) - { - /* if the filter requested a special format, retry */ - if ( !( AOUT_FMTS_IDENTICAL( &p_filter->fmt_in.audio, - &chain_input_format ) - && AOUT_FMTS_IDENTICAL( &p_filter->fmt_out.audio, - &chain_output_format ) ) ) - { - aout_FormatPrepare( &p_filter->fmt_in.audio ); - aout_FormatPrepare( &p_filter->fmt_out.audio ); - p_filter->p_module = module_need( p_filter, - "audio filter", - psz_parser, true ); - } - /* try visual filters */ - else - { - memcpy( &p_filter->fmt_in.audio, &chain_output_format, - sizeof(audio_sample_format_t) ); - memcpy( &p_filter->fmt_out.audio, &chain_output_format, - sizeof(audio_sample_format_t) ); - p_filter->p_module = module_need( p_filter, - "visualization2", - psz_parser, true ); - } - } - } - - /* failure */ - if ( p_filter->p_module == NULL ) - { - msg_Err( p_aout, "cannot add user filter %s (skipped)", - psz_parser ); - - free( p_filter->p_owner ); - vlc_object_release( p_filter ); - - psz_parser = psz_next; - continue; - } - - /* complete the filter chain if necessary */ - if ( aout_FiltersCreatePipeline( p_aout, p_input->pp_filters, - &p_input->i_nb_filters, - &chain_input_format, - &p_filter->fmt_in.audio ) < 0 ) - { - msg_Err( p_aout, "cannot add user filter %s (skipped)", - psz_parser ); - - module_unneed( p_filter, p_filter->p_module ); - free( p_filter->p_owner ); - vlc_object_release( p_filter ); - - psz_parser = psz_next; - continue; - } - - /* success */ - p_input->pp_filters[p_input->i_nb_filters++] = p_filter; - memcpy( &chain_input_format, &p_filter->fmt_out.audio, - sizeof( audio_sample_format_t ) ); - - if( i_visual == 0 ) /* scaletempo */ - p_input->p_playback_rate_filter = p_filter; - - /* next filter if any */ - psz_parser = psz_next; - } - } - free( psz_visual ); - free( psz_filters ); - free( psz_scaletempo ); - - /* complete the filter chain if necessary */ - if ( aout_FiltersCreatePipeline( p_aout, p_input->pp_filters, - &p_input->i_nb_filters, - &chain_input_format, - &chain_output_format ) < 0 ) - { - inputFailure( p_aout, p_input, "couldn't set an input pipeline" ); - return -1; - } - - /* Create resamplers. */ - if (AOUT_FMT_LINEAR(outfmt)) - { - chain_output_format.i_rate = (__MAX(p_input->samplerate, - outfmt->i_rate) - * (100 + AOUT_MAX_RESAMPLING)) / 100; - if ( chain_output_format.i_rate == outfmt->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, outfmt) < 0) - { - inputFailure( p_aout, p_input, "couldn't set a resampler pipeline"); - return -1; - } - - /* Setup the initial rate of the resampler */ - p_input->pp_resamplers[0]->fmt_in.audio.i_rate = p_input->samplerate; - } p_input->i_resampling_type = AOUT_RESAMPLING_NONE; - - if( ! p_input->p_playback_rate_filter && p_input->i_nb_resamplers > 0 ) - { - p_input->p_playback_rate_filter = p_input->pp_resamplers[0]; - } - - /* Success */ - p_input->b_error = false; p_input->i_last_input_rate = INPUT_RATE_DEFAULT; - - return 0; + p_input->i_buffer_lost = 0; + return p_input; } /***************************************************************************** @@ -431,27 +60,9 @@ int aout_InputNew( audio_output_t * p_aout, ***************************************************************************** * This function must be entered with the mixer lock. *****************************************************************************/ -int aout_InputDelete( audio_output_t * p_aout, aout_input_t * p_input ) +void aout_InputDelete (aout_input_t * p_input ) { - aout_assert_locked( p_aout ); - if ( p_input->b_error ) - return 0; - - /* XXX We need to update b_recycle_vout before calling aout_FiltersDestroyPipeline. - * FIXME They can be a race condition if audio-visual is updated between - * aout_InputDelete and aout_InputNew. - */ - char *psz_visual = var_GetString( p_aout, "audio-visual"); - p_input->b_recycle_vout = psz_visual && *psz_visual; - free( psz_visual ); - - aout_FiltersDestroyPipeline( p_input->pp_filters, p_input->i_nb_filters ); - p_input->i_nb_filters = 0; - aout_FiltersDestroyPipeline( p_input->pp_resamplers, - p_input->i_nb_resamplers ); - p_input->i_nb_resamplers = 0; - - return 0; + free (p_input); } /***************************************************************************** @@ -459,50 +70,24 @@ int aout_InputDelete( audio_output_t * p_aout, aout_input_t * p_input ) ***************************************************************************** * This function must be entered with the input lock. *****************************************************************************/ -/* XXX Do not activate it !! */ -//#define AOUT_PROCESS_BEFORE_CHEKS 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_owner_t *owner = aout_owner(p_aout); aout_assert_locked( p_aout ); - if( i_input_rate != INPUT_RATE_DEFAULT && p_input->p_playback_rate_filter == NULL ) + if( i_input_rate != INPUT_RATE_DEFAULT && owner->rate_filter == NULL ) { inputDrop( p_input, p_buffer ); return NULL; } -#ifdef AOUT_PROCESS_BEFORE_CHEKS - /* Run pre-filters. */ - aout_FiltersPlay( p_aout, p_input->pp_filters, p_input->i_nb_filters, - &p_buffer ); - if( !p_buffer ) - return NULL; - - /* Actually run the resampler now. */ - if ( p_input->i_nb_resamplers > 0 ) - { - const mtime_t i_date = p_buffer->i_pts; - aout_FiltersPlay( p_aout, p_input->pp_resamplers, - p_input->i_nb_resamplers, - &p_buffer ); - } - - if( !p_buffer ) - return NULL; - if( p_buffer->i_nb_samples <= 0 ) - { - block_Release( p_buffer ); - return NULL; - } -#endif - /* Handle input rate change, but keep drift correction */ if( i_input_rate != p_input->i_last_input_rate ) { - unsigned int * const pi_rate = &p_input->p_playback_rate_filter->fmt_in.audio.i_rate; + unsigned int * const pi_rate = &owner->rate_filter->fmt_in.audio.i_rate; #define F(r,ir) ( INPUT_RATE_DEFAULT * (r) / (ir) ) const int i_delta = *pi_rate - F(p_input->samplerate,p_input->i_last_input_rate); *pi_rate = F(p_input->samplerate + i_delta, i_input_rate); @@ -527,7 +112,7 @@ block_t *aout_InputPlay(audio_output_t *p_aout, aout_input_t *p_input, 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 ); + inputResamplingStop( p_aout, p_input ); p_buffer->i_flags |= BLOCK_FLAG_DISCONTINUITY; start_date = VLC_TS_INVALID; } @@ -539,7 +124,7 @@ block_t *aout_InputPlay(audio_output_t *p_aout, aout_input_t *p_input, 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 ); + inputResamplingStop( p_aout, p_input ); return NULL; } @@ -560,7 +145,7 @@ block_t *aout_InputPlay(audio_output_t *p_aout, aout_input_t *p_input, 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 ); + inputResamplingStop( p_aout, p_input ); p_buffer->i_flags |= BLOCK_FLAG_DISCONTINUITY; start_date = p_buffer->i_pts; date_Set (date, start_date); @@ -575,18 +160,16 @@ block_t *aout_InputPlay(audio_output_t *p_aout, aout_input_t *p_input, return NULL; } -#ifndef AOUT_PROCESS_BEFORE_CHEKS /* Run pre-filters. */ - aout_FiltersPlay( p_input->pp_filters, p_input->i_nb_filters, &p_buffer ); + aout_FiltersPlay( owner->filters, owner->nb_filters, &p_buffer ); if( !p_buffer ) 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_MAX_PTS_ADVANCE || drift > +AOUT_MAX_PTS_DELAY ) && - p_input->i_nb_resamplers > 0 ) + owner->resampler != NULL ) { /* Can happen in several circumstances : * 1. A problem at the input (clock drift) @@ -595,7 +178,6 @@ block_t *aout_InputPlay(audio_output_t *p_aout, aout_input_t *p_input, * synchronization * Solution : resample the buffer to avoid a scratch. */ - p_input->i_resamp_start_date = now; p_input->i_resamp_start_drift = (int)-drift; p_input->i_resampling_type = (drift < 0) ? AOUT_RESAMPLING_DOWN : AOUT_RESAMPLING_UP; @@ -611,22 +193,20 @@ block_t *aout_InputPlay(audio_output_t *p_aout, aout_input_t *p_input, * it isn't too audible to the listener. */ if( p_input->i_resampling_type == AOUT_RESAMPLING_UP ) - p_input->pp_resamplers[0]->fmt_in.audio.i_rate += 2; /* Hz */ + owner->resampler->fmt_in.audio.i_rate += 2; /* Hz */ else - p_input->pp_resamplers[0]->fmt_in.audio.i_rate -= 2; /* Hz */ + owner->resampler->fmt_in.audio.i_rate -= 2; /* Hz */ /* Check if everything is back to normal, in which case we can stop the * resampling */ unsigned int i_nominal_rate = - (p_input->pp_resamplers[0] == p_input->p_playback_rate_filter) + (owner->resampler == owner->rate_filter) ? INPUT_RATE_DEFAULT * p_input->samplerate / i_input_rate : p_input->samplerate; - if( p_input->pp_resamplers[0]->fmt_in.audio.i_rate == i_nominal_rate ) + if( owner->resampler->fmt_in.audio.i_rate == i_nominal_rate ) { p_input->i_resampling_type = AOUT_RESAMPLING_NONE; - msg_Warn( p_aout, "resampling stopped after %"PRIi64" usec " - "(drift: %"PRIi64")", - now - p_input->i_resamp_start_date, + msg_Warn( p_aout, "resampling stopped (drift: %"PRIi64")", p_buffer->i_pts - start_date); } else if( abs( (int)(p_buffer->i_pts - start_date) ) < @@ -647,18 +227,14 @@ block_t *aout_InputPlay(audio_output_t *p_aout, aout_input_t *p_input, /* If the drift is increasing and not decreasing, than something * is bad. We'd better stop the resampling right now. */ msg_Warn( p_aout, "timing screwed, stopping resampling" ); - inputResamplingStop( p_input ); + inputResamplingStop( p_aout, p_input ); p_buffer->i_flags |= BLOCK_FLAG_DISCONTINUITY; } } -#ifndef AOUT_PROCESS_BEFORE_CHEKS /* Actually run the resampler now. */ - if ( p_input->i_nb_resamplers > 0 ) - { - aout_FiltersPlay( p_input->pp_resamplers, p_input->i_nb_resamplers, - &p_buffer ); - } + if ( owner->resampler != NULL ) + aout_FiltersPlay( &owner->resampler, 1, &p_buffer ); if( !p_buffer ) return NULL; @@ -667,7 +243,6 @@ block_t *aout_InputPlay(audio_output_t *p_aout, aout_input_t *p_input, block_Release( p_buffer ); return NULL; } -#endif p_buffer->i_pts = start_date; return p_buffer; @@ -677,207 +252,23 @@ block_t *aout_InputPlay(audio_output_t *p_aout, aout_input_t *p_input, * static functions *****************************************************************************/ -static void inputFailure( audio_output_t * p_aout, aout_input_t * p_input, - const char * psz_error_message ) +static void inputDrop( aout_input_t *p_input, block_t *p_buffer ) { - /* error message */ - msg_Err( p_aout, "%s", psz_error_message ); - - /* clean up */ - aout_FiltersDestroyPipeline( p_input->pp_filters, p_input->i_nb_filters ); - aout_FiltersDestroyPipeline( p_input->pp_resamplers, - p_input->i_nb_resamplers ); - var_Destroy( p_aout, "visual" ); - var_Destroy( p_aout, "equalizer" ); - var_Destroy( p_aout, "audio-filter" ); - var_Destroy( p_aout, "audio-visual" ); - - var_Destroy( p_aout, "audio-replay-gain-mode" ); - var_Destroy( p_aout, "audio-replay-gain-default" ); - var_Destroy( p_aout, "audio-replay-gain-preamp" ); - var_Destroy( p_aout, "audio-replay-gain-peak-protection" ); - - /* error flag */ - p_input->b_error = 1; -} - -static void inputDrop( aout_input_t *p_input, aout_buffer_t *p_buffer ) -{ - aout_BufferFree( p_buffer ); + block_Release( p_buffer ); p_input->i_buffer_lost++; } -static void inputResamplingStop( aout_input_t *p_input ) +static void inputResamplingStop( audio_output_t *p_aout, aout_input_t *p_input ) { + aout_owner_t *owner = aout_owner(p_aout); + p_input->i_resampling_type = AOUT_RESAMPLING_NONE; - if( p_input->i_nb_resamplers != 0 ) + if( owner->resampler != NULL ) { - p_input->pp_resamplers[0]->fmt_in.audio.i_rate = - ( p_input->pp_resamplers[0] == p_input->p_playback_rate_filter ) + owner->resampler->fmt_in.audio.i_rate = + ( owner->resampler == owner->rate_filter ) ? INPUT_RATE_DEFAULT * p_input->samplerate / p_input->i_last_input_rate : p_input->samplerate; } } - -static vout_thread_t *RequestVout( void *p_private, - vout_thread_t *p_vout, video_format_t *p_fmt, bool b_recycle ) -{ - audio_output_t *p_aout = p_private; - VLC_UNUSED(b_recycle); - vout_configuration_t cfg = { - .vout = p_vout, - .input = NULL, - .change_fmt = true, - .fmt = p_fmt, - .dpb_size = 1, - }; - return vout_Request( p_aout, &cfg ); -} - -vout_thread_t *aout_filter_RequestVout( filter_t *p_filter, - vout_thread_t *p_vout, video_format_t *p_fmt ) -{ - aout_input_t *p_input = p_filter->p_owner->p_input; - aout_request_vout_t *p_request = &p_input->request_vout; - - /* XXX: this only works from audio input */ - /* If you want to use visualization filters from another place, you will - * need to add a new pf_aout_request_vout callback or store a pointer - * to aout_request_vout_t inside filter_t (i.e. a level of indirection). */ - - return p_request->pf_request_vout( p_request->p_private, - p_vout, p_fmt, p_input->b_recycle_vout ); -} - -static inline bool ChangeFiltersString (vlc_object_t *aout, const char *var, - const char *filter, bool add) -{ - return aout_ChangeFilterString (aout, aout, var, filter, add); -} - -static int VisualizationCallback (vlc_object_t *obj, char const *var, - vlc_value_t oldval, vlc_value_t newval, - void *data) -{ - const char *mode = newval.psz_string; - //aout_input_t *input = data; - (void) data; - - 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 (obj, "audio-visual", "visual", false); - ChangeFiltersString (obj, "audio-visual", "goom", false); - ChangeFiltersString (obj, "audio-visual", "projectm", true); - } - else - { - var_Create (obj, "effect-list", VLC_VAR_STRING); - var_SetString (obj, "effect-list", mode); - - ChangeFiltersString (obj, "audio-visual", "goom", false); - ChangeFiltersString (obj, "audio-visual", "visual", true); - ChangeFiltersString (obj, "audio-visual", "projectm", false); - } - - /* That sucks FIXME: use "input" instead of cast */ - aout_InputRequestRestart ((audio_output_t *)obj); - - (void) var; (void) oldval; - return VLC_SUCCESS; -} - -static int EqualizerCallback (vlc_object_t *obj, char const *cmd, - vlc_value_t oldval, vlc_value_t newval, - void *data) -{ - char *mode = newval.psz_string; - //aout_input_t *input = data; - bool ret; - - (void) data; - (void) cmd; (void) oldval; - if (!*mode) - ret = ChangeFiltersString (obj, "audio-filter", "equalizer", false); - else - { - var_Create (obj, "equalizer-preset", VLC_VAR_STRING); - var_SetString (obj, "equalizer-preset", mode); - ret = ChangeFiltersString (obj, "audio-filter", "equalizer", true); - } - - /* That sucks */ - if (ret) - aout_InputRequestRestart ((audio_output_t *)obj); - return VLC_SUCCESS; -} - -static int ReplayGainCallback (vlc_object_t *obj, char const *var, - vlc_value_t oldval, vlc_value_t val, void *data) -{ - audio_output_t *aout = (audio_output_t *)obj; - aout_input_t *input = data; - float multiplier = ReplayGainSelect (obj, val.psz_string, - &input->replay_gain); - - aout_lock (aout); - input->multiplier = multiplier; - aout_unlock (aout); - - VLC_UNUSED(var); VLC_UNUSED(oldval); - return VLC_SUCCESS; -} - -static float ReplayGainSelect (vlc_object_t *obj, const char *str, - const audio_replay_gain_t *replay_gain) -{ - float gain = 0.; - unsigned mode = AUDIO_REPLAY_GAIN_MAX; - - if (likely(str != NULL)) - { /* Find selectrf mode */ - if (!strcmp (str, "track")) - mode = AUDIO_REPLAY_GAIN_TRACK; - else - if (!strcmp (str, "album")) - mode = AUDIO_REPLAY_GAIN_ALBUM; - - /* If the selectrf mode is not available, prefer the other one */ - if (mode != AUDIO_REPLAY_GAIN_MAX && !replay_gain->pb_gain[mode]) - { - if (replay_gain->pb_gain[!mode]) - mode = !mode; - } - } - - /* */ - if (mode == AUDIO_REPLAY_GAIN_MAX) - return 1.; - - if (replay_gain->pb_gain[mode]) - gain = replay_gain->pf_gain[mode] - + var_InheritFloat (obj, "audio-replay-gain-preamp"); - else - gain = var_InheritFloat (obj, "audio-replay-gain-default"); - - float multiplier = pow (10., gain / 20.); - - if (replay_gain->pb_peak[mode] - && var_InheritBool (obj, "audio-replay-gain-peak-protection") - && replay_gain->pf_peak[mode] * multiplier > 1.0) - multiplier = 1.0f / replay_gain->pf_peak[mode]; - - return multiplier; -}