]> git.sesse.net Git - vlc/commitdiff
aout: inline synchronization code into dec.c
authorRémi Denis-Courmont <remi@remlab.net>
Sun, 11 Nov 2012 14:54:51 +0000 (16:54 +0200)
committerRémi Denis-Courmont <remi@remlab.net>
Sun, 11 Nov 2012 14:55:24 +0000 (16:55 +0200)
po/POTFILES.in
src/Makefile.am
src/audio_output/aout_internal.h
src/audio_output/dec.c
src/audio_output/input.c [deleted file]
src/audio_output/output.c

index 1b4f28afb2d679698d8e62888bd5b5d359d81229..b026e2e1d2e94ed95d460cd9785bb8a4c69e6aa8 100644 (file)
@@ -66,7 +66,6 @@ src/audio_output/aout_internal.h
 src/audio_output/common.c
 src/audio_output/dec.c
 src/audio_output/filters.c
-src/audio_output/input.c
 src/audio_output/output.c
 src/config/chain.c
 src/config/cmdline.c
index d6fde32d8d2faad7988375e5fdf8bf517eddea47..f87581dbcd3244573cea9ef41bce8fa58e72e8af 100644 (file)
@@ -413,7 +413,6 @@ SOURCES_libvlc_common = \
        audio_output/common.c \
        audio_output/dec.c \
        audio_output/filters.c \
-       audio_output/input.c \
        audio_output/output.c \
        audio_output/volume.c \
        network/getaddrinfo.c \
index 96212975414965fe1a1c96a1a981d842696193c4..994ffacc974d92a0d1ef945cbc5b94938232f804 100644 (file)
@@ -46,26 +46,17 @@ typedef struct
 
 typedef struct aout_volume aout_volume_t;
 
-/** an input stream for the audio output */
-struct aout_input_t
-{
-    int                     i_resampling_type;
-    int                     i_resamp_start_drift;
-
-    /* */
-    int               i_buffer_lost;
-};
-
 typedef struct
 {
     vlc_mutex_t lock;
     module_t *module; /**< Output plugin (or NULL if inactive) */
-    aout_input_t *input;
     aout_volume_t *volume;
 
     struct
     {
         date_t date;
+        int resamp_type;
+        int resamp_start_drift;
     } sync;
 
     audio_sample_format_t input_format;
@@ -84,6 +75,8 @@ typedef struct
     aout_request_vout_t request_vout;
     bool recycle_vout;
 
+    unsigned buffers_lost;
+
     vlc_atomic_t restart;
 } aout_owner_t;
 
@@ -102,12 +95,6 @@ static inline aout_owner_t *aout_owner (audio_output_t *aout)
  * Prototypes
  *****************************************************************************/
 
-/* From input.c : */
-aout_input_t *aout_InputNew(void);
-void aout_InputDelete(aout_input_t *);
-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_FiltersPipelineCreate(vlc_object_t *, filter_t **, unsigned *,
     unsigned, const audio_sample_format_t *, const audio_sample_format_t *);
index 82dfa344505e5f0ebc4d169c64560b1a84813484..bbf48cc32abb06e012c43e0296d5cce3dd47339b 100644 (file)
@@ -95,9 +95,10 @@ error:
 
     date_Init (&owner->sync.date, owner->mixer_format.i_rate, 1);
     date_Set (&owner->sync.date, VLC_TS_INVALID);
+    owner->sync.resamp_type = AOUT_RESAMPLING_NONE;
+
+    owner->buffers_lost = 0;
 
-    assert (owner->input == NULL);
-    owner->input = aout_InputNew ();
     aout_unlock( p_aout );
     return ret;
 }
@@ -108,14 +109,8 @@ error:
 void aout_DecDelete (audio_output_t *p_aout)
 {
     aout_owner_t *owner = aout_owner (p_aout);
-    aout_input_t *input;
 
     aout_lock( p_aout );
-    /* Remove the input. */
-    input = owner->input;
-    aout_InputDelete (input);
-    owner->input = NULL;
-
     aout_FiltersDelete (p_aout);
     aout_OutputDelete( p_aout );
     aout_volume_Delete (owner->volume);
@@ -127,7 +122,7 @@ void aout_DecDelete (audio_output_t *p_aout)
 
 #define AOUT_RESTART_OUTPUT 1
 #define AOUT_RESTART_INPUT  2
-static void aout_CheckRestart (audio_output_t *aout)
+static int aout_CheckRestart (audio_output_t *aout)
 {
     aout_owner_t *owner = aout_owner (aout);
 
@@ -135,15 +130,12 @@ static void aout_CheckRestart (audio_output_t *aout)
 
     int restart = vlc_atomic_swap (&owner->restart, 0);
     if (likely(restart == 0))
-        return;
+        return 0;
 
     assert (restart & AOUT_RESTART_INPUT);
 
     const aout_request_vout_t request_vout = owner->request_vout;
 
-    aout_InputDelete (owner->input);
-    owner->input = NULL;
-
     aout_FiltersDelete (aout);
 
     /* Reinitializes the output */
@@ -151,16 +143,18 @@ static void aout_CheckRestart (audio_output_t *aout)
     {
         aout_OutputDelete (aout);
         if (aout_OutputNew (aout, &owner->input_format))
-        {
-            aout_volume_Delete (owner->volume);
-            return; /* we are officially screwed */
-        }
+            abort (); /* FIXME we are officially screwed */
         aout_volume_SetFormat (owner->volume, owner->mixer_format.i_format);
     }
 
+    owner->sync.resamp_type = AOUT_RESAMPLING_NONE;
+
     if (aout_FiltersNew (aout, &owner->input_format, &owner->mixer_format,
-                         &request_vout) == 0)
-        owner->input = aout_InputNew ();
+                         &request_vout))
+    {
+        abort (); /* FIXME */
+    }
+    return 0;
 }
 
 /**
@@ -235,64 +229,175 @@ void aout_DecDeleteBuffer (audio_output_t *aout, block_t *block)
     block_Release (block);
 }
 
+static void aout_StopResampling (audio_output_t *aout)
+{
+    aout_owner_t *owner = aout_owner (aout);
+
+    owner->sync.resamp_type = AOUT_RESAMPLING_NONE;
+    aout_FiltersAdjustResampling (aout, 0);
+}
+
 /*****************************************************************************
  * aout_DecPlay : filter & mix the decoded buffer
  *****************************************************************************/
-int aout_DecPlay (audio_output_t *p_aout, block_t *p_buffer, int i_input_rate)
+int aout_DecPlay (audio_output_t *aout, block_t *block, int input_rate)
 {
-    aout_owner_t *owner = aout_owner (p_aout);
-    aout_input_t *input;
+    aout_owner_t *owner = aout_owner (aout);
 
-    assert( i_input_rate >= INPUT_RATE_DEFAULT / AOUT_MAX_INPUT_RATE &&
-            i_input_rate <= INPUT_RATE_DEFAULT * AOUT_MAX_INPUT_RATE );
-    assert( p_buffer->i_pts > 0 );
+    assert (input_rate >= INPUT_RATE_DEFAULT / AOUT_MAX_INPUT_RATE);
+    assert (input_rate <= INPUT_RATE_DEFAULT * AOUT_MAX_INPUT_RATE);
+    assert (block->i_pts >= VLC_TS_0);
 
-    p_buffer->i_length = (mtime_t)p_buffer->i_nb_samples * 1000000
-                                / owner->input_format.i_rate;
+    block->i_length = CLOCK_FREQ * block->i_nb_samples
+                                 / owner->input_format.i_rate;
 
-    aout_lock( p_aout );
-    aout_CheckRestart( p_aout );
+    aout_lock (aout);
+    if (unlikely(aout_CheckRestart (aout)))
+        goto drop; /* Pipeline is unrecoverably broken :-( */
+
+    /* 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. */
+    mtime_t start_date = date_Get (&owner->sync.date);
+    const mtime_t now = mdate ();
+
+    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 (aout, "computed PTS is out of range (%"PRId64"), "
+                  "clearing out", now - start_date);
+        aout_OutputFlush (aout, false);
+        if (owner->sync.resamp_type != AOUT_RESAMPLING_NONE)
+            msg_Warn (aout, "timing screwed, stopping resampling");
+        aout_StopResampling (aout);
+        block->i_flags |= BLOCK_FLAG_DISCONTINUITY;
+        start_date = VLC_TS_INVALID;
+    }
+
+    if (block->i_pts < now + AOUT_MIN_PREPARE_TIME)
+    {   /* The decoder gives us f*cked up PTS. It's its business, but we
+         * can't present it anyway, so drop the buffer. */
+        msg_Warn (aout, "PTS is out of range (%"PRId64"), dropping buffer",
+                  now - block->i_pts);
+        aout_StopResampling (aout);
+        goto drop;
+    }
 
-    input = owner->input;
-    if (unlikely(input == NULL)) /* can happen due to restart */
+    /* If the audio drift is too big then it's not worth trying to resample
+     * the audio. */
+    if (start_date == VLC_TS_INVALID)
     {
-        aout_unlock( p_aout );
-        block_Release( p_buffer );
-        return -1;
+        start_date = block->i_pts;
+        date_Set (&owner->sync.date, start_date);
     }
 
-    /* Input */
-    p_buffer = aout_InputPlay (p_aout, input, p_buffer, i_input_rate,
-                               &owner->sync.date);
-    if( p_buffer != NULL )
+    mtime_t drift = start_date - block->i_pts;
+    if (drift < -input_rate * 3 * AOUT_MAX_PTS_ADVANCE / INPUT_RATE_DEFAULT)
     {
-        date_Increment (&owner->sync.date, p_buffer->i_nb_samples);
+        msg_Warn (aout, "buffer way too early (%"PRId64"), clearing queue",
+                  drift);
+        aout_OutputFlush (aout, false);
+        if (owner->sync.resamp_type != AOUT_RESAMPLING_NONE)
+            msg_Warn (aout, "timing screwed, stopping resampling");
+        aout_StopResampling (aout);
+        block->i_flags |= BLOCK_FLAG_DISCONTINUITY;
+        start_date = block->i_pts;
+        date_Set (&owner->sync.date, start_date);
+        drift = 0;
+    }
+    else
+    if (drift > +input_rate * 3 * AOUT_MAX_PTS_DELAY / INPUT_RATE_DEFAULT)
+    {
+        msg_Warn (aout, "buffer way too late (%"PRId64"), dropping buffer",
+                  drift);
+        goto drop;
+    }
 
-        /* Mixer */
-        aout_volume_Amplify (owner->volume, p_buffer);
+    block = aout_FiltersPlay (aout, block, input_rate);
+    if (block == NULL)
+    {
+        owner->buffers_lost++;
+        goto out;
+    }
 
-        /* Output */
-        aout_OutputPlay( p_aout, p_buffer );
+    /* Adjust the resampler if needed.
+     * We first need to calculate the output rate of this resampler. */
+    if ((owner->sync.resamp_type == AOUT_RESAMPLING_NONE)
+     && (drift < -AOUT_MAX_PTS_ADVANCE || drift > +AOUT_MAX_PTS_DELAY))
+    {   /* Can happen in several circumstances :
+         * 1. A problem at the input (clock drift)
+         * 2. A small pause triggered by the user
+         * 3. Some delay in the output stage, causing a loss of lip
+         *    synchronization
+         * Solution : resample the buffer to avoid a scratch.
+         */
+        owner->sync.resamp_start_drift = (int)-drift;
+        owner->sync.resamp_type = (drift < 0) ? AOUT_RESAMPLING_DOWN
+                                             : AOUT_RESAMPLING_UP;
+        msg_Warn (aout, (drift < 0)
+                  ? "buffer too early (%"PRId64"), down-sampling"
+                  : "buffer too late  (%"PRId64"), up-sampling", drift);
+    }
+    if (owner->sync.resamp_type != AOUT_RESAMPLING_NONE)
+    {   /* Resampling has been triggered previously (because of dates
+         * mismatch). We want the resampling to happen progressively so
+         * it isn't too audible to the listener. */
+        const int adjust = (owner->sync.resamp_type == AOUT_RESAMPLING_UP)
+            ? +2 : -2;
+        /* Check if everything is back to normal, then stop resampling. */
+        if (!aout_FiltersAdjustResampling (aout, adjust))
+        {
+            owner->sync.resamp_type = AOUT_RESAMPLING_NONE;
+            msg_Warn (aout, "resampling stopped (drift: %"PRIi64")",
+                      block->i_pts - start_date);
+        }
+        else if (abs ((int)(block->i_pts - start_date))
+                                    < abs (owner->sync.resamp_start_drift) / 2)
+        {   /* If we reduced the drift from half, then it is time to switch
+             * back the resampling direction. */
+            if (owner->sync.resamp_type == AOUT_RESAMPLING_UP)
+                owner->sync.resamp_type = AOUT_RESAMPLING_DOWN;
+            else
+                owner->sync.resamp_type = AOUT_RESAMPLING_UP;
+            owner->sync.resamp_start_drift = 0;
+        }
+        else if (owner->sync.resamp_start_drift
+              && (abs ((int)(block->i_pts - start_date))
+                               > abs (owner->sync.resamp_start_drift) * 3 / 2))
+        {   /* If the drift is increasing and not decreasing, than something
+             * is bad. We'd better stop the resampling right now. */
+            msg_Warn (aout, "timing screwed, stopping resampling");
+            aout_StopResampling (aout);
+            block->i_flags |= BLOCK_FLAG_DISCONTINUITY;
+        }
     }
 
-    aout_unlock( p_aout );
+    block->i_pts = start_date;
+    date_Increment (&owner->sync.date, block->i_nb_samples);
+
+    /* Software volume */
+    aout_volume_Amplify (owner->volume, block);
+
+    /* Output */
+    aout_OutputPlay (aout, block);
+out:
+    aout_unlock (aout);
     return 0;
+drop:
+    block_Release (block);
+    owner->buffers_lost++;
+    goto out;
 }
 
 int aout_DecGetResetLost (audio_output_t *aout)
 {
     aout_owner_t *owner = aout_owner (aout);
-    aout_input_t *input = owner->input;
-    int val;
+    unsigned val;
 
     aout_lock (aout);
-    if (likely(input != NULL))
-    {
-        val = input->i_buffer_lost;
-        input->i_buffer_lost = 0;
-    }
-    else
-        val = 0; /* if aout_CheckRestart() failed */
+    val = owner->buffers_lost;
+    owner->buffers_lost = 0;
     aout_unlock (aout);
 
     return val;
diff --git a/src/audio_output/input.c b/src/audio_output/input.c
deleted file mode 100644 (file)
index 1a9ea83..0000000
+++ /dev/null
@@ -1,223 +0,0 @@
-/*****************************************************************************
- * input.c : internal management of input streams for the audio output
- *****************************************************************************
- * Copyright (C) 2002-2007 VLC authors and VideoLAN
- * $Id$
- *
- * Authors: Christophe Massiot <massiot@via.ecp.fr>
- *
- * 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 Lesser General Public License for more details.
- *
- * 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.
- *****************************************************************************/
-
-/*****************************************************************************
- * Preamble
- *****************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include <vlc_common.h>
-#include <vlc_input.h>
-#include <vlc_aout.h>
-
-#include <libvlc.h>
-#include "aout_internal.h"
-
-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
- *****************************************************************************/
-aout_input_t *aout_InputNew (void)
-{
-    aout_input_t *p_input = xmalloc (sizeof (*p_input));
-
-    p_input->i_resampling_type = AOUT_RESAMPLING_NONE;
-    p_input->i_buffer_lost = 0;
-    return p_input;
-}
-
-/*****************************************************************************
- * aout_InputDelete : delete an input
- *****************************************************************************
- * This function must be entered with the mixer lock.
- *****************************************************************************/
-void aout_InputDelete (aout_input_t * p_input )
-{
-    free (p_input);
-}
-
-/*****************************************************************************
- * aout_InputPlay : play a buffer
- *****************************************************************************
- * This function must be entered with the input lock.
- *****************************************************************************/
-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_locked( p_aout );
-
-    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. */
-    start_date = date_Get (date);
-
-    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_OutputFlush( p_aout, false );
-        if ( p_input->i_resampling_type != AOUT_RESAMPLING_NONE )
-            msg_Warn( p_aout, "timing screwed, stopping resampling" );
-        inputResamplingStop( p_aout, p_input );
-        p_buffer->i_flags |= BLOCK_FLAG_DISCONTINUITY;
-        start_date = VLC_TS_INVALID;
-    }
-
-    if ( p_buffer->i_pts < now + AOUT_MIN_PREPARE_TIME )
-    {
-        /* The decoder gives us f*cked up PTS. It's its business, but we
-         * 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_aout, p_input );
-        return NULL;
-    }
-
-    /* If the audio drift is too big then it's not worth trying to resample
-     * the audio. */
-    if( start_date == VLC_TS_INVALID )
-    {
-        start_date = p_buffer->i_pts;
-        date_Set (date, start_date);
-    }
-
-    mtime_t drift = start_date - p_buffer->i_pts;
-
-    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_OutputFlush( p_aout, false );
-        if ( p_input->i_resampling_type != AOUT_RESAMPLING_NONE )
-            msg_Warn( p_aout, "timing screwed, stopping resampling" );
-        inputResamplingStop( p_aout, 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 > +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 NULL;
-    }
-
-    p_buffer = aout_FiltersPlay( p_aout, p_buffer, i_input_rate );
-    if( !p_buffer )
-        return NULL;
-
-    /* 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 ) )
-    {
-        /* Can happen in several circumstances :
-         * 1. A problem at the input (clock drift)
-         * 2. A small pause triggered by the user
-         * 3. Some delay in the output stage, causing a loss of lip
-         *    synchronization
-         * Solution : resample the buffer to avoid a scratch.
-         */
-        p_input->i_resamp_start_drift = (int)-drift;
-        p_input->i_resampling_type = (drift < 0) ? AOUT_RESAMPLING_DOWN
-                                                 : AOUT_RESAMPLING_UP;
-        msg_Warn( p_aout, (drift < 0)
-                  ? "buffer too early (%"PRId64"), down-sampling"
-                  : "buffer too late  (%"PRId64"), up-sampling", drift );
-    }
-
-    if ( p_input->i_resampling_type != AOUT_RESAMPLING_NONE )
-    {
-        /* Resampling has been triggered previously (because of dates
-         * mismatch). We want the resampling to happen progressively so
-         * it isn't too audible to the listener. */
-        const int adjust = ( p_input->i_resampling_type == AOUT_RESAMPLING_UP )
-            ? +2 : -2;
-
-        /* Check if everything is back to normal, in which case we can stop the
-         * resampling */
-        if( !aout_FiltersAdjustResampling( p_aout, adjust ) )
-        {
-            p_input->i_resampling_type = AOUT_RESAMPLING_NONE;
-            msg_Warn( p_aout, "resampling stopped (drift: %"PRIi64")",
-                      p_buffer->i_pts - start_date);
-        }
-        else if( abs( (int)(p_buffer->i_pts - start_date) ) <
-                 abs( p_input->i_resamp_start_drift ) / 2 )
-        {
-            /* if we reduced the drift from half, then it is time to switch
-             * back the resampling direction. */
-            if( p_input->i_resampling_type == AOUT_RESAMPLING_UP )
-                p_input->i_resampling_type = AOUT_RESAMPLING_DOWN;
-            else
-                p_input->i_resampling_type = AOUT_RESAMPLING_UP;
-            p_input->i_resamp_start_drift = 0;
-        }
-        else if( p_input->i_resamp_start_drift &&
-                 ( abs( (int)(p_buffer->i_pts - start_date) ) >
-                   abs( p_input->i_resamp_start_drift ) * 3 / 2 ) )
-        {
-            /* 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_aout, p_input );
-            p_buffer->i_flags |= BLOCK_FLAG_DISCONTINUITY;
-        }
-    }
-
-    p_buffer->i_pts = start_date;
-    return p_buffer;
-}
-
-/*****************************************************************************
- * static functions
- *****************************************************************************/
-
-static void inputDrop( aout_input_t *p_input, block_t *p_buffer )
-{
-    block_Release( p_buffer );
-
-    p_input->i_buffer_lost++;
-}
-
-static void inputResamplingStop( audio_output_t *p_aout, aout_input_t *p_input )
-{
-    p_input->i_resampling_type = AOUT_RESAMPLING_NONE;
-    aout_FiltersAdjustResampling( p_aout, 0 );
-}
index 99bd37a0b9f438d1c022b0fab445a61ef38dd036..098bc9fda6ed934fd425cf216ff03db79744cedc 100644 (file)
@@ -96,8 +96,6 @@ audio_output_t *aout_New (vlc_object_t *parent)
     vlc_mutex_init (&owner->lock);
     vlc_object_set_destructor (aout, aout_Destructor);
 
-    owner->input = NULL;
-
     /* Audio output module callbacks */
     var_Create (aout, "volume", VLC_VAR_FLOAT);
     var_AddCallback (aout, "volume", var_Copy, parent);