[vlc-devel] [RFC PATCH 05/12] decoder: handle module fallback

Thomas Guillem thomas at gllm.fr
Tue Jul 19 19:36:27 CEST 2016


---
 include/vlc_codec.h |  5 +++++
 src/input/decoder.c | 44 +++++++++++++++++++++++++++++++++-----------
 2 files changed, 38 insertions(+), 11 deletions(-)

diff --git a/include/vlc_codec.h b/include/vlc_codec.h
index 2d01d26..98b9bdc 100644
--- a/include/vlc_codec.h
+++ b/include/vlc_codec.h
@@ -159,6 +159,11 @@ struct decoder_t
     decoder_owner_sys_t *p_owner;
 
     bool                b_error;
+
+    /* Can be set to true by the module from pf_decode_* callbacks. This will
+     * tell the core to try a next module. The current module will be unloaded
+     * when the pf_decode callback ends. */
+    bool                b_fallback;
 };
 
 /**
diff --git a/src/input/decoder.c b/src/input/decoder.c
index 6a847d7..c04de09 100644
--- a/src/input/decoder.c
+++ b/src/input/decoder.c
@@ -68,6 +68,7 @@ struct decoder_owner_sys_t
     sout_instance_t         *p_sout;
     sout_packetizer_input_t *p_sout_input;
 
+    void             *p_module_savectx;
     vlc_thread_t     thread;
 
     /* Some decoders require already packetized data (ie. not truncated) */
@@ -138,7 +139,8 @@ struct decoder_owner_sys_t
  * Load a decoder module
  */
 static int LoadDecoder( decoder_t *p_dec, bool b_packetizer,
-                        const es_format_t *restrict p_fmt )
+                        const es_format_t *restrict p_fmt,
+                        void **pp_module_savectx )
 {
     p_dec->b_frame_drop_allowed = true;
     p_dec->i_extra_picture_buffers = 0;
@@ -155,9 +157,11 @@ static int LoadDecoder( decoder_t *p_dec, bool b_packetizer,
 
     /* Find a suitable decoder/packetizer module */
     if( !b_packetizer )
-        p_dec->p_module = module_need( p_dec, "decoder", "$codec", false );
+        p_dec->p_module = module_need_next( p_dec, "decoder", "$codec",
+                                            false, pp_module_savectx );
     else
-        p_dec->p_module = module_need( p_dec, "packetizer", "$packetizer", false );
+        p_dec->p_module = module_need_next( p_dec, "packetizer", "$packetizer",
+                                            false, pp_module_savectx );
 
     if( !p_dec->p_module )
     {
@@ -188,10 +192,12 @@ static void UnloadDecoder( decoder_t *p_dec )
     es_format_Clean( &p_dec->fmt_in );
     es_format_Clean( &p_dec->fmt_out );
     p_dec->b_error = false;
+    p_dec->b_fallback = false;
 }
 
 static int ReloadDecoder( decoder_t *p_dec, bool b_packetizer,
-                          const es_format_t *restrict p_fmt )
+                          const es_format_t *restrict p_fmt,
+                          void **pp_module_savectx )
 {
     /* Copy p_fmt since it can be destroyed by UnloadDecoder */
     es_format_t fmt_in;
@@ -200,7 +206,7 @@ static int ReloadDecoder( decoder_t *p_dec, bool b_packetizer,
 
     /* Restart the decoder module */
     UnloadDecoder( p_dec );
-    if( LoadDecoder( p_dec, b_packetizer, &fmt_in ) )
+    if( LoadDecoder( p_dec, b_packetizer, &fmt_in, pp_module_savectx ) )
     {
         p_dec->b_error = true;
         es_format_Clean( &fmt_in );
@@ -1027,8 +1033,11 @@ static void DecoderProcessVideo( decoder_t *p_dec, block_t *p_block )
                 /* Drain the decoder module */
                 DecoderDecodeVideo( p_dec, NULL );
 
+                free( p_owner->p_module_savectx );
+                p_owner->p_module_savectx = NULL;
                 if( ReloadDecoder( p_dec, false,
-                                   &p_packetizer->fmt_out ) != VLC_SUCCESS )
+                                   &p_packetizer->fmt_out,
+                                   &p_owner->p_module_savectx ) != VLC_SUCCESS )
                 {
                     block_ChainRelease( p_packetized_block );
                     return;
@@ -1044,7 +1053,7 @@ static void DecoderProcessVideo( decoder_t *p_dec, block_t *p_block )
                 p_packetized_block->p_next = NULL;
 
                 DecoderDecodeVideo( p_dec, p_packetized_block );
-                if( p_dec->b_error )
+                if( p_dec->b_error || p_dec->b_fallback )
                 {
                     block_ChainRelease( p_next );
                     return;
@@ -1209,8 +1218,11 @@ static void DecoderProcessAudio( decoder_t *p_dec, block_t *p_block )
                 /* Drain the decoder module */
                 DecoderDecodeAudio( p_dec, NULL );
 
+                free( p_owner->p_module_savectx );
+                p_owner->p_module_savectx = NULL;
                 if( ReloadDecoder( p_dec, false,
-                                   &p_packetizer->fmt_out ) != VLC_SUCCESS )
+                                   &p_packetizer->fmt_out,
+                                   &p_owner->p_module_savectx ) != VLC_SUCCESS )
                 {
                     block_ChainRelease( p_packetized_block );
                     return;
@@ -1223,7 +1235,7 @@ static void DecoderProcessAudio( decoder_t *p_dec, block_t *p_block )
                 p_packetized_block->p_next = NULL;
 
                 DecoderDecodeAudio( p_dec, p_packetized_block );
-                if( p_dec->b_error )
+                if( p_dec->b_error || p_dec->b_fallback )
                 {
                     block_ChainRelease( p_next );
                     return;
@@ -1342,6 +1354,12 @@ static void DecoderProcess( decoder_t *p_dec, block_t *p_block )
 {
     decoder_owner_sys_t *p_owner = p_dec->p_owner;
 
+    if( p_dec->b_fallback )
+    {
+        if( ReloadDecoder( p_dec, false, &p_dec->fmt_in,
+                           &p_owner->p_module_savectx ) != VLC_SUCCESS )
+            goto error;
+    }
     if( p_dec->b_error )
         goto error;
 
@@ -1577,6 +1595,7 @@ static decoder_t * CreateDecoder( vlc_object_t *p_parent,
     p_owner->i_spu_order = 0;
     p_owner->p_sout = p_sout;
     p_owner->p_sout_input = NULL;
+    p_owner->p_module_savectx = NULL;
     p_owner->p_packetizer = NULL;
 
     p_owner->b_fmt_description = false;
@@ -1632,7 +1651,7 @@ static decoder_t * CreateDecoder( vlc_object_t *p_parent,
             vlc_custom_create( p_parent, sizeof( decoder_t ), "packetizer" );
         if( p_owner->p_packetizer )
         {
-            if( LoadDecoder( p_owner->p_packetizer, true, fmt ) )
+            if( LoadDecoder( p_owner->p_packetizer, true, fmt, NULL ) )
             {
                 vlc_object_release( p_owner->p_packetizer );
                 p_owner->p_packetizer = NULL;
@@ -1646,7 +1665,8 @@ static decoder_t * CreateDecoder( vlc_object_t *p_parent,
     }
 
     /* Find a suitable decoder/packetizer module */
-    if( LoadDecoder( p_dec, p_sout != NULL, fmt ) )
+    if( LoadDecoder( p_dec, p_sout != NULL, fmt,
+                     p_sout == NULL ? &p_owner->p_module_savectx : NULL ) )
         return p_dec;
 
     /* Copy ourself the input replay gain */
@@ -1757,6 +1777,8 @@ static void DeleteDecoder( decoder_t * p_dec )
         vlc_object_release( p_owner->p_packetizer );
     }
 
+    free( p_owner->p_module_savectx );
+
     vlc_cond_destroy( &p_owner->wait_timed );
     vlc_cond_destroy( &p_owner->wait_fifo );
     vlc_cond_destroy( &p_owner->wait_acknowledge );
-- 
2.8.1



More information about the vlc-devel mailing list