]> git.sesse.net Git - vlc/blobdiff - src/audio_output/input.c
aout_PacketPlay: use aout_TimeReport(), restore resampling
[vlc] / src / audio_output / input.c
index 28620d7ae5c2424336c12fdae17438eb9fd97b41..a6c6f952ca2231e0b9c2c17a58ade096da93c2f2 100644 (file)
 
 #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 );