]> git.sesse.net Git - vlc/blobdiff - src/audio_output/dec.c
aout: add wait parameter to aout_DecFlush()
[vlc] / src / audio_output / dec.c
index ad31ae476d1279d4744c0d6ff17ff4a96cfe132e..74440728958b99b98bfa0e09b5e0cd51c1455be4 100644 (file)
@@ -52,7 +52,7 @@ int aout_DecNew( audio_output_t *p_aout,
         return -1;
     }
 
-    if( p_format->i_rate > 192000 )
+    if( p_format->i_rate > 352800 )
     {
         msg_Err( p_aout, "excessive audio sample frequency (%u)",
                  p_format->i_rate );
@@ -68,7 +68,7 @@ int aout_DecNew( audio_output_t *p_aout,
     aout_owner_t *owner = aout_owner(p_aout);
 
     /* TODO: reduce lock scope depending on decoder's real need */
-    aout_lock( p_aout );
+    aout_OutputLock (p_aout);
 
     var_Destroy( p_aout, "stereo-mode" );
 
@@ -78,26 +78,28 @@ int aout_DecNew( audio_output_t *p_aout,
     atomic_store (&owner->restart, 0);
     owner->input_format = *p_format;
     owner->mixer_format = owner->input_format;
+    owner->request_vout = *p_request_vout;
 
     if (aout_OutputNew (p_aout, &owner->mixer_format))
         goto error;
     aout_volume_SetFormat (owner->volume, owner->mixer_format.i_format);
 
     /* Create the audio filtering "input" pipeline */
-    if (aout_FiltersNew (p_aout, p_format, &owner->mixer_format,
-                         p_request_vout))
+    owner->filters = aout_FiltersNew (p_aout, p_format, &owner->mixer_format,
+                                      &owner->request_vout);
+    if (owner->filters == NULL)
     {
         aout_OutputDelete (p_aout);
 error:
         aout_volume_Delete (owner->volume);
-        aout_unlock (p_aout);
+        aout_OutputUnlock (p_aout);
         return -1;
     }
 
     owner->sync.end = VLC_TS_INVALID;
     owner->sync.resamp_type = AOUT_RESAMPLING_NONE;
     owner->sync.discontinuity = true;
-    aout_unlock( p_aout );
+    aout_OutputUnlock (p_aout);
 
     atomic_init (&owner->buffers_lost, 0);
     return 0;
@@ -106,37 +108,36 @@ error:
 /**
  * Stops all plugins involved in the audio output.
  */
-void aout_DecDelete (audio_output_t *p_aout)
+void aout_DecDelete (audio_output_t *aout)
 {
-    aout_owner_t *owner = aout_owner (p_aout);
+    aout_owner_t *owner = aout_owner (aout);
 
-    aout_lock( p_aout );
-    aout_FiltersDelete (p_aout);
-    aout_OutputDelete( p_aout );
+    aout_OutputLock (aout);
+    if (owner->mixer_format.i_format)
+    {
+        aout_FiltersDelete (aout, owner->filters);
+        aout_OutputDelete (aout);
+    }
     aout_volume_Delete (owner->volume);
-
-    var_Destroy( p_aout, "stereo-mode" );
-
-    aout_unlock( p_aout );
+    aout_OutputUnlock (aout);
+    var_Destroy (aout, "stereo-mode");
 }
 
-#define AOUT_RESTART_OUTPUT 1
-#define AOUT_RESTART_INPUT  2
 static int aout_CheckReady (audio_output_t *aout)
 {
     aout_owner_t *owner = aout_owner (aout);
 
-    aout_assert_locked (aout);
-
     int restart = atomic_exchange (&owner->restart, 0);
     if (unlikely(restart))
     {
-        const aout_request_vout_t request_vout = owner->request_vout;
+        if (owner->mixer_format.i_format)
+            aout_FiltersDelete (aout, owner->filters);
 
-        aout_FiltersDelete (aout);
         if (restart & AOUT_RESTART_OUTPUT)
         {   /* Reinitializes the output */
-            aout_OutputDelete (aout);
+            msg_Dbg (aout, "restarting output...");
+            if (owner->mixer_format.i_format)
+                aout_OutputDelete (aout);
             owner->mixer_format = owner->input_format;
             if (aout_OutputNew (aout, &owner->mixer_format))
                 owner->mixer_format.i_format = 0;
@@ -144,15 +145,24 @@ static int aout_CheckReady (audio_output_t *aout)
                                    owner->mixer_format.i_format);
         }
 
+        msg_Dbg (aout, "restarting filters...");
         owner->sync.end = VLC_TS_INVALID;
         owner->sync.resamp_type = AOUT_RESAMPLING_NONE;
 
-        if (aout_FiltersNew (aout, &owner->input_format, &owner->mixer_format,
-                             &request_vout))
+        if (owner->mixer_format.i_format)
         {
-            aout_OutputDelete (aout);
-            owner->mixer_format.i_format = 0;
+            owner->filters = aout_FiltersNew (aout, &owner->input_format,
+                                              &owner->mixer_format,
+                                              &owner->request_vout);
+            if (owner->filters == NULL)
+            {
+                aout_OutputDelete (aout);
+                owner->mixer_format.i_format = 0;
+            }
         }
+        /* TODO: This would be a good time to call clean up any video output
+         * left over by an audio visualization:
+        input_resource_TerminatVout(MAGIC HERE); */
     }
     return (owner->mixer_format.i_format) ? 0 : -1;
 }
@@ -161,80 +171,23 @@ static int aout_CheckReady (audio_output_t *aout)
  * Marks the audio output for restart, to update any parameter of the output
  * plug-in (e.g. output device or channel mapping).
  */
-static void aout_RequestRestart (audio_output_t *aout)
+void aout_RequestRestart (audio_output_t *aout, unsigned mode)
 {
     aout_owner_t *owner = aout_owner (aout);
-
-    /* NOTE: restarting output requires restarting input. */
-    atomic_fetch_or (&owner->restart, AOUT_RESTART_OUTPUT);
-}
-
-int aout_ChannelsRestart (vlc_object_t *obj, const char *varname,
-                          vlc_value_t oldval, vlc_value_t newval, void *data)
-{
-    audio_output_t *aout = (audio_output_t *)obj;
-    (void)oldval; (void)newval; (void)data;
-
-    if (!strcmp (varname, "audio-device"))
-    {
-        /* This is supposed to be a significant change and supposes
-         * rebuilding the channel choices. */
-        var_Destroy (aout, "stereo-mode");
-    }
-    aout_RequestRestart (aout);
-    return 0;
+    atomic_fetch_or (&owner->restart, mode);
+    msg_Dbg (aout, "restart requested (%u)", mode);
 }
 
-/**
- * This function will safely mark aout input to be restarted as soon as
- * possible to take configuration changes into account
- */
-void aout_InputRequestRestart (audio_output_t *aout)
-{
-    aout_owner_t *owner = aout_owner (aout);
-
-    atomic_fetch_or (&owner->restart, AOUT_RESTART_INPUT);
-}
-
-
 /*
  * Buffer management
  */
 
-/*****************************************************************************
- * aout_DecNewBuffer : ask for a new empty buffer
- *****************************************************************************/
-block_t *aout_DecNewBuffer (audio_output_t *aout, size_t samples)
-{
-    /* NOTE: the caller is responsible for serializing input change */
-    aout_owner_t *owner = aout_owner (aout);
-
-    size_t length = samples * owner->input_format.i_bytes_per_frame
-                            / owner->input_format.i_frame_length;
-    block_t *block = block_Alloc( length );
-    if( likely(block != NULL) )
-    {
-        block->i_nb_samples = samples;
-        block->i_pts = block->i_length = 0;
-    }
-    return block;
-}
-
-/*****************************************************************************
- * aout_DecDeleteBuffer : destroy an undecoded buffer
- *****************************************************************************/
-void aout_DecDeleteBuffer (audio_output_t *aout, block_t *block)
-{
-    (void) aout;
-    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_FiltersAdjustResampling (owner->filters, 0);
 }
 
 static void aout_DecSilence (audio_output_t *aout, mtime_t length, mtime_t pts)
@@ -368,7 +321,7 @@ static void aout_DecSynchronize (audio_output_t *aout, mtime_t dec_pts,
          * value, then it is time to switch back the resampling direction. */
         adj *= -1;
 
-    if (!aout_FiltersAdjustResampling (aout, adj))
+    if (!aout_FiltersAdjustResampling (owner->filters, adj))
     {   /* Everything is back to normal: stop resampling. */
         owner->sync.resamp_type = AOUT_RESAMPLING_NONE;
         msg_Dbg (aout, "resampling stopped (drift: %"PRId64" us)", drift);
@@ -389,7 +342,7 @@ int aout_DecPlay (audio_output_t *aout, block_t *block, int input_rate)
     block->i_length = CLOCK_FREQ * block->i_nb_samples
                                  / owner->input_format.i_rate;
 
-    aout_lock (aout);
+    aout_OutputLock (aout);
     if (unlikely(aout_CheckReady (aout)))
         goto drop; /* Pipeline is unrecoverably broken :-( */
 
@@ -410,7 +363,7 @@ int aout_DecPlay (audio_output_t *aout, block_t *block, int input_rate)
     if (block->i_flags & BLOCK_FLAG_DISCONTINUITY)
         owner->sync.discontinuity = true;
 
-    block = aout_FiltersPlay (aout, block, input_rate);
+    block = aout_FiltersPlay (owner->filters, block, input_rate);
     if (block == NULL)
         goto lost;
 
@@ -425,7 +378,7 @@ int aout_DecPlay (audio_output_t *aout, block_t *block, int input_rate)
     owner->sync.discontinuity = false;
     aout_OutputPlay (aout, block);
 out:
-    aout_unlock (aout);
+    aout_OutputUnlock (aout);
     return 0;
 drop:
     owner->sync.discontinuity = true;
@@ -445,7 +398,7 @@ void aout_DecChangePause (audio_output_t *aout, bool paused, mtime_t date)
 {
     aout_owner_t *owner = aout_owner (aout);
 
-    aout_lock (aout);
+    aout_OutputLock (aout);
     if (owner->sync.end != VLC_TS_INVALID)
     {
         if (paused)
@@ -453,18 +406,20 @@ void aout_DecChangePause (audio_output_t *aout, bool paused, mtime_t date)
         else
             owner->sync.end += date;
     }
-    aout_OutputPause (aout, paused, date);
-    aout_unlock (aout);
+    if (owner->mixer_format.i_format)
+        aout_OutputPause (aout, paused, date);
+    aout_OutputUnlock (aout);
 }
 
-void aout_DecFlush (audio_output_t *aout)
+void aout_DecFlush (audio_output_t *aout, bool wait)
 {
     aout_owner_t *owner = aout_owner (aout);
 
-    aout_lock (aout);
+    aout_OutputLock (aout);
     owner->sync.end = VLC_TS_INVALID;
-    aout_OutputFlush (aout, false);
-    aout_unlock (aout);
+    if (owner->mixer_format.i_format)
+        aout_OutputFlush (aout, wait);
+    aout_OutputUnlock (aout);
 }
 
 bool aout_DecIsEmpty (audio_output_t *aout)
@@ -473,14 +428,14 @@ bool aout_DecIsEmpty (audio_output_t *aout)
     mtime_t now = mdate ();
     bool empty = true;
 
-    aout_lock (aout);
+    aout_OutputLock (aout);
     if (owner->sync.end != VLC_TS_INVALID)
         empty = owner->sync.end <= now;
-    if (empty)
+    if (empty && owner->mixer_format.i_format)
         /* The last PTS has elapsed already. So the underlying audio output
          * buffer should be empty or almost. Thus draining should be fast
          * and will not block the caller too long. */
         aout_OutputFlush (aout, true);
-    aout_unlock (aout);
+    aout_OutputUnlock (aout);
     return empty;
 }