[vlc-devel] [PATCH] decoder: reload module if aout restart and fails during playback

Thomas Guillem thomas at gllm.fr
Tue Jul 26 18:19:33 CEST 2016


In order to be able to change from S/PDIF to PCM since there is no S/PDIF
converter anymore.

We can't reload directly from DecoderPlayAudio since this function may be
called from a running asynchronous decoder.
---
 src/audio_output/aout_internal.h |  2 +-
 src/audio_output/dec.c           | 11 ++++++++---
 src/input/decoder.c              | 15 ++++++++++++++-
 3 files changed, 23 insertions(+), 5 deletions(-)

diff --git a/src/audio_output/aout_internal.h b/src/audio_output/aout_internal.h
index 4990597..6e2134c 100644
--- a/src/audio_output/aout_internal.h
+++ b/src/audio_output/aout_internal.h
@@ -137,7 +137,7 @@ bool aout_ChangeFilterString( vlc_object_t *manager, vlc_object_t *aout,
 int aout_DecNew(audio_output_t *, const audio_sample_format_t *,
                 const audio_replay_gain_t *, const aout_request_vout_t *);
 void aout_DecDelete(audio_output_t *);
-void aout_DecPlay(audio_output_t *, block_t *, int i_input_rate);
+void aout_DecPlay(audio_output_t *, block_t *, int i_input_rate, bool *);
 void aout_DecGetResetStats(audio_output_t *, unsigned *, unsigned *);
 void aout_DecChangePause(audio_output_t *, bool b_paused, mtime_t i_date);
 void aout_DecFlush(audio_output_t *, bool wait);
diff --git a/src/audio_output/dec.c b/src/audio_output/dec.c
index 84c2f60..7731f83 100644
--- a/src/audio_output/dec.c
+++ b/src/audio_output/dec.c
@@ -131,10 +131,11 @@ void aout_DecDelete (audio_output_t *aout)
     var_Destroy (aout, "stereo-mode");
 }
 
-static int aout_CheckReady (audio_output_t *aout)
+static int aout_CheckReady (audio_output_t *aout, bool *reload_decoder)
 {
     aout_owner_t *owner = aout_owner (aout);
 
+    *reload_decoder = false;
     int restart = atomic_exchange (&owner->restart, 0);
     if (unlikely(restart))
     {
@@ -166,6 +167,9 @@ static int aout_CheckReady (audio_output_t *aout)
             {
                 aout_OutputDelete (aout);
                 owner->mixer_format.i_format = 0;
+                /* The aout restarted but there is no valid filters anymore:
+                 * ask the decoder to restart */
+                *reload_decoder = restart & AOUT_RESTART_OUTPUT;
             }
         }
         /* TODO: This would be a good time to call clean up any video output
@@ -339,7 +343,8 @@ static void aout_DecSynchronize (audio_output_t *aout, mtime_t dec_pts,
 /*****************************************************************************
  * aout_DecPlay : filter & mix the decoded buffer
  *****************************************************************************/
-void aout_DecPlay (audio_output_t *aout, block_t *block, int input_rate)
+void aout_DecPlay (audio_output_t *aout, block_t *block, int input_rate,
+                   bool *reload_decoder)
 {
     aout_owner_t *owner = aout_owner (aout);
 
@@ -351,7 +356,7 @@ void aout_DecPlay (audio_output_t *aout, block_t *block, int input_rate)
                                  / owner->input_format.i_rate;
 
     aout_OutputLock (aout);
-    if (unlikely(aout_CheckReady (aout)))
+    if (unlikely(aout_CheckReady (aout, reload_decoder)))
         goto drop; /* Pipeline is unrecoverably broken :-( */
 
     const mtime_t now = mdate (), advance = block->i_pts - now;
diff --git a/src/input/decoder.c b/src/input/decoder.c
index 6a847d7..978e2f4 100644
--- a/src/input/decoder.c
+++ b/src/input/decoder.c
@@ -80,6 +80,7 @@ struct decoder_owner_sys_t
     /* */
     bool           b_fmt_description;
     vlc_meta_t     *p_description;
+    atomic_bool    reload;
 
     /* fifo */
     block_fifo_t *p_fifo;
@@ -1123,7 +1124,10 @@ static int DecoderPlayAudio( decoder_t *p_dec, block_t *p_audio,
      && i_rate <= INPUT_RATE_DEFAULT*AOUT_MAX_INPUT_RATE
      && !DecoderTimedWait( p_dec, p_audio->i_pts - AOUT_MAX_PREPARE_TIME ) )
     {
-        aout_DecPlay( p_aout, p_audio, i_rate );
+        bool restart_decoder;
+        aout_DecPlay( p_aout, p_audio, i_rate, &restart_decoder );
+        if( restart_decoder )
+            atomic_store( &p_owner->reload, true );
     }
     else
     {
@@ -1345,6 +1349,14 @@ static void DecoderProcess( decoder_t *p_dec, block_t *p_block )
     if( p_dec->b_error )
         goto error;
 
+    if( atomic_exchange( &p_owner->reload, false ) )
+    {
+        msg_Warn( p_dec, "Reloading the decoder module" );
+
+        if( ReloadDecoder( p_dec, NULL, &p_dec->fmt_in ) != VLC_SUCCESS )
+            goto error;
+    }
+
     if( p_block )
     {
         if( p_block->i_buffer <= 0 )
@@ -1593,6 +1605,7 @@ static decoder_t * CreateDecoder( vlc_object_t *p_parent,
     p_owner->flushing = false;
     p_owner->b_draining = false;
     atomic_init( &p_owner->drained, false );
+    atomic_init( &p_owner->reload, false );
     p_owner->b_idle = false;
 
     es_format_Init( &p_owner->fmt, UNKNOWN_ES, 0 );
-- 
2.8.1



More information about the vlc-devel mailing list