[vlc-commits] decoder: add VLCDEC_RELOAD status

Thomas Guillem git at videolan.org
Thu Feb 9 15:57:28 CET 2017


vlc | branch: master | Thomas Guillem <thomas at gllm.fr> | Wed Feb  8 15:58:08 2017 +0100| [c4aabc520043da7f129c1fb1c3508819146cf24e] | committer: Thomas Guillem

decoder: add VLCDEC_RELOAD status

This replaces the decoder_RequestReload() function. The module implementation
that returns this status should not have modified or released the input block
passed in pf_decoder parameter.

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=c4aabc520043da7f129c1fb1c3508819146cf24e
---

 include/vlc_codec.h              | 13 ++++++------
 modules/codec/omxil/mediacodec.c | 43 ++++++++++++++++++----------------------
 modules/codec/videotoolbox.m     | 16 +++++++--------
 src/input/decoder.c              | 23 ++++++++++++++++-----
 src/libvlccore.sym               |  1 -
 5 files changed, 51 insertions(+), 45 deletions(-)

diff --git a/include/vlc_codec.h b/include/vlc_codec.h
index 24b1805..802eeac 100644
--- a/include/vlc_codec.h
+++ b/include/vlc_codec.h
@@ -69,6 +69,7 @@ struct decoder_t
 
 #   define VLCDEC_SUCCESS   VLC_SUCCESS
 #   define VLCDEC_ECRITICAL VLC_EGENERIC
+#   define VLCDEC_RELOAD    (-100)
     /* This function is called to decode one packetized block.
      *
      * The module implementation will own the input block (p_block) and should
@@ -84,6 +85,11 @@ struct decoder_t
      *  VLCDEC_SUCCESS: pf_decode will be called again
      *  VLCDEC_ECRITICAL: in case of critical error, pf_decode won't be called
      *  again.
+     *  VLCDEC_RELOAD: Request that the decoder should be reloaded. The current
+     *  module will be unloaded. Reloading a module may cause a loss of frames.
+     *  When returning this status, the implementation shouldn't release or
+     *  modify the p_block in argument (The same p_block will be feed to the
+     *  next decoder module).
      */
     int                 ( * pf_decode )   ( decoder_t *, block_t *p_block );
 
@@ -352,13 +358,6 @@ VLC_API block_t * decoder_NewAudioBuffer( decoder_t *, int i_size ) VLC_USED;
  */
 VLC_API subpicture_t * decoder_NewSubpicture( decoder_t *, const subpicture_updater_t * ) VLC_USED;
 
-/*
- * Request that the decoder should be reloaded. The current module will be
- * unloaded. Reloading a module may cause a loss of frames. There is no
- * warranty that pf_decode_* callbacks won't be called again after this call.
- */
-VLC_API void decoder_RequestReload( decoder_t * );
-
 /**
  * This function gives all input attachments at once.
  *
diff --git a/modules/codec/omxil/mediacodec.c b/modules/codec/omxil/mediacodec.c
index 36bad57..765c70e 100644
--- a/modules/codec/omxil/mediacodec.c
+++ b/modules/codec/omxil/mediacodec.c
@@ -1362,7 +1362,12 @@ static int DecodeBlock(decoder_t *p_dec, block_t *p_in_block)
     vlc_mutex_lock(&p_sys->lock);
 
     if (p_sys->b_aborted)
-        goto end;
+    {
+        if (p_sys->b_has_format)
+            goto end;
+        else
+            goto reload;
+    }
 
     if (p_in_block != NULL)
     {
@@ -1572,29 +1577,19 @@ static int DecodeBlock(decoder_t *p_dec, block_t *p_in_block)
 end:
     if (p_in_block)
         block_Release(p_in_block);
-    if (p_sys->b_aborted)
-    {
-        if (!p_sys->b_has_format)
-        {
-            /* Add an empty variable so that mediacodec won't be loaded again
-             * for this ES */
-            if (var_Create(p_dec, "mediacodec-failed", VLC_VAR_VOID)
-             == VLC_SUCCESS)
-                decoder_RequestReload(p_dec);
-            vlc_mutex_unlock(&p_sys->lock);
-            return VLCDEC_SUCCESS;
-        }
-        else
-        {
-            vlc_mutex_unlock(&p_sys->lock);
-            return VLCDEC_ECRITICAL;
-        }
-    }
-    else
-    {
-        vlc_mutex_unlock(&p_sys->lock);
-        return VLCDEC_SUCCESS;
-    }
+    /* Too late to reload here, we already modified/released the input block,
+     * do it next time. */
+    int ret = p_sys->b_aborted && p_sys->b_has_format ? VLCDEC_ECRITICAL
+                                                      : VLCDEC_SUCCESS;
+    vlc_mutex_unlock(&p_sys->lock);
+    return ret;
+
+reload:
+    vlc_mutex_unlock(&p_sys->lock);
+    /* Add an empty variable so that mediacodec won't be loaded again
+     * for this ES */
+    var_Create(p_dec, "mediacodec-failed", VLC_VAR_VOID);
+    return VLCDEC_RELOAD;
 }
 
 static int Video_OnNewBlock(decoder_t *p_dec, block_t **pp_block)
diff --git a/modules/codec/videotoolbox.m b/modules/codec/videotoolbox.m
index a63b917..0c0f840 100644
--- a/modules/codec/videotoolbox.m
+++ b/modules/codec/videotoolbox.m
@@ -336,7 +336,7 @@ static int StartVideoToolboxSession(decoder_t *p_dec)
     return VLC_SUCCESS;
 }
 
-static int StartVideoToolbox(decoder_t *p_dec, block_t *p_block)
+static int StartVideoToolbox(decoder_t *p_dec, const block_t *p_block)
 {
     decoder_sys_t *p_sys = p_dec->p_sys;
     OSStatus status;
@@ -1117,7 +1117,11 @@ static int DecodeBlock(decoder_t *p_dec, block_t *p_block)
             msg_Err(p_dec, "decoder failure: invalid SPS/PPS");
         else if (status == -6661) {
             msg_Err(p_dec, "decoder failure: invalid argument");
-            goto reload;
+            /* The decoder module will be reloaded next time since we already
+             * modified the input block */
+            vlc_mutex_lock(&p_sys->lock);
+            p_dec->p_sys->b_abort = true;
+            vlc_mutex_unlock(&p_sys->lock);
         } else if (status == -8969 || status == -12909) {
             msg_Err(p_dec, "decoder failure: bad data (%i)", (int)status);
             StopVideoToolbox(p_dec);
@@ -1136,14 +1140,10 @@ skip:
     return VLCDEC_SUCCESS;
 
 reload:
-    block_Release(p_block);
     /* Add an empty variable so that videotoolbox won't be loaded again for
      * this ES */
-    if (var_Create(p_dec, "videotoolbox-failed", VLC_VAR_VOID) == VLC_SUCCESS)
-        decoder_RequestReload(p_dec);
-    else
-        return VLCDEC_ECRITICAL;
-    return VLCDEC_SUCCESS;
+    var_Create(p_dec, "videotoolbox-failed", VLC_VAR_VOID);
+    return VLCDEC_RELOAD;
 }
 
 static int UpdateVideoFormat(decoder_t *p_dec, CVPixelBufferRef imageBuffer)
diff --git a/src/input/decoder.c b/src/input/decoder.c
index 417fe3f..bc7eb3c 100644
--- a/src/input/decoder.c
+++ b/src/input/decoder.c
@@ -148,6 +148,7 @@ struct decoder_owner_sys_t
 
 /* */
 #define DECODER_SPU_VOUT_WAIT_DURATION ((int)(0.200*CLOCK_FREQ))
+#define BLOCK_FLAG_CORE_PRIVATE_RELOADED (1 << BLOCK_FLAG_CORE_PRIVATE_SHIFT)
 
 /**
  * Load a decoder module
@@ -620,7 +621,7 @@ subpicture_t *decoder_NewSubpicture( decoder_t *p_decoder,
     return p_subpicture;
 }
 
-void decoder_RequestReload( decoder_t * p_dec )
+static void RequestReload( decoder_t * p_dec )
 {
     decoder_owner_sys_t *p_owner = p_dec->p_owner;
     /* Don't override reload if it's RELOAD_DECODER_AOUT */
@@ -1103,7 +1104,7 @@ static int DecoderPlayAudio( decoder_t *p_dec, block_t *p_audio,
         if( status == AOUT_DEC_CHANGED )
         {
             /* Only reload the decoder */
-            decoder_RequestReload( p_dec );
+            RequestReload( p_dec );
         }
         else if( status == AOUT_DEC_FAILED )
         {
@@ -1244,7 +1245,7 @@ static int DecoderQueueSpu( decoder_t *p_dec, subpicture_t *p_spu )
     return i_ret;
 }
 
-
+static void DecoderProcess( decoder_t *p_dec, block_t *p_block );
 static void DecoderDecode( decoder_t *p_dec, block_t *p_block )
 {
     decoder_owner_sys_t *p_owner = p_dec->p_owner;
@@ -1258,6 +1259,18 @@ static void DecoderDecode( decoder_t *p_dec, block_t *p_block )
         case VLCDEC_ECRITICAL:
             p_owner->error = true;
             break;
+        case VLCDEC_RELOAD:
+            RequestReload( p_dec );
+            if( unlikely( p_block == NULL ) )
+                break;
+            if( !( p_block->i_flags & BLOCK_FLAG_CORE_PRIVATE_RELOADED ) )
+            {
+                p_block->i_flags |= BLOCK_FLAG_CORE_PRIVATE_RELOADED;
+                DecoderProcess( p_dec, p_block );
+            }
+            else /* We prefer loosing this block than an infinite recursion */
+                block_Release( p_block );
+            break;
         default:
             vlc_assert_unreachable();
     }
@@ -1307,8 +1320,8 @@ static void DecoderProcess( decoder_t *p_dec, block_t *p_block )
         return;
     }
 #endif
-
-    if( p_owner->p_packetizer )
+    if( p_owner->p_packetizer
+     && !unlikely( p_block->i_flags & BLOCK_FLAG_CORE_PRIVATE_RELOADED ) )
     {
         block_t *p_packetized_block;
         block_t **pp_block = p_block ? &p_block : NULL;
diff --git a/src/libvlccore.sym b/src/libvlccore.sym
index 7b9657a..150409e 100644
--- a/src/libvlccore.sym
+++ b/src/libvlccore.sym
@@ -81,7 +81,6 @@ decoder_GetDisplayRate
 decoder_GetInputAttachments
 decoder_NewAudioBuffer
 decoder_NewSubpicture
-decoder_RequestReload
 decoder_SynchroChoose
 decoder_SynchroDate
 decoder_SynchroDecode



More information about the vlc-commits mailing list