Activated vout/aout recycling with playlist inputs.
authorLaurent Aimar <fenrir@videolan.org>
Sat, 27 Dec 2008 10:44:24 +0000 (11:44 +0100)
committerLaurent Aimar <fenrir@videolan.org>
Mon, 5 Jan 2009 19:49:12 +0000 (20:49 +0100)
src/input/es_out.c
src/input/input.c
src/input/input_interface.h
src/input/ressource.c
src/input/vlm.c
src/input/vlm_internal.h
src/playlist/engine.c
src/playlist/playlist_internal.h
src/playlist/thread.c

index 5cd2cbb..468dea6 100644 (file)
@@ -662,6 +662,10 @@ static void EsOutDecodersStopBuffering( es_out_t *out, bool b_forced )
     msg_Dbg( p_sys->p_input, "Decoder buffering done in %d ms",
               (int)(mdate() - i_decoder_buffering_start)/1000 );
 
+    /* Here is a good place to destroy unused vout with every demuxer */
+    input_ressource_TerminateVout( p_sys->p_input->p->p_ressource );
+
+    /* */
     const mtime_t i_wakeup_delay = 10*1000; /* FIXME CLEANUP thread wake up time*/
     const mtime_t i_current_date = p_sys->b_paused ? p_sys->i_pause_date : mdate();
 
@@ -2014,6 +2018,20 @@ static int EsOutControlLocked( es_out_t *out, int i_query, va_list args )
         case ES_OUT_SET_ACTIVE:
         {
             b = (bool) va_arg( args, int );
+            if( b && !p_sys->b_active && p_sys->i_es > 0 )
+            {
+                /* XXX Terminate vout if there are tracks but no video one.
+                 * This one is not mandatory but is he earliest place where it
+                 * can be done */
+                for( i = 0; i < p_sys->i_es; i++ )
+                {
+                    es_out_id_t *p_es = p_sys->es[i];
+                    if( p_es->fmt.i_cat == VIDEO_ES )
+                        break;
+                }
+                if( i >= p_sys->i_es )
+                    input_ressource_TerminateVout( p_sys->p_input->p->p_ressource );
+            }
             p_sys->b_active = b;
             return VLC_SUCCESS;
         }
@@ -2295,7 +2313,13 @@ static int EsOutControlLocked( es_out_t *out, int i_query, va_list args )
               assert(0);
             }
             /* TODO if the lock is made non recursive it should be changed */
-            return es_out_Control( out, i_new_query, p_es );
+            int i_ret = es_out_Control( out, i_new_query, p_es );
+
+            /* Clean up vout after user action (in active mode only).
+             * FIXME it does not work well with multiple video windows */
+            if( p_sys->b_active )
+                input_ressource_TerminateVout( p_sys->p_input->p->p_ressource );
+            return i_ret;
         }
 
         case ES_OUT_GET_BUFFERING:
index 6a697d8..a22671e 100644 (file)
@@ -66,7 +66,7 @@ static  void *Run            ( vlc_object_t *p_this );
 static  void *RunAndDestroy  ( vlc_object_t *p_this );
 
 static input_thread_t * Create  ( vlc_object_t *, input_item_t *,
-                                  const char *, bool, sout_instance_t * );
+                                  const char *, bool, input_ressource_t * );
 static  int             Init    ( input_thread_t *p_input );
 static void             WaitDie   ( input_thread_t *p_input );
 static void             End     ( input_thread_t *p_input );
@@ -118,7 +118,7 @@ static void input_ChangeState( input_thread_t *p_input, int i_state ); /* TODO f
  *****************************************************************************/
 static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item,
                                const char *psz_header, bool b_quick,
-                               sout_instance_t *p_sout )
+                               input_ressource_t *p_ressource )
 {
     static const char input_name[] = "input";
     input_thread_t *p_input = NULL;                 /* thread descriptor */
@@ -214,7 +214,10 @@ static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item,
     p_input->p->slave   = NULL;
 
     /* */
-    p_input->p->p_ressource = input_ressource_New();
+    if( p_ressource )
+        p_input->p->p_ressource = p_ressource;
+    else
+        p_input->p->p_ressource = input_ressource_New();
     input_ressource_SetInput( p_input->p->p_ressource, p_input );
 
     /* Init control buffer */
@@ -298,9 +301,6 @@ static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item,
         p_input->i_flags |= OBJECT_FLAGS_QUIET | OBJECT_FLAGS_NOINTERACT;
 
     /* */
-    if( p_sout )
-        input_ressource_RequestSout( p_input->p->p_ressource, p_sout, NULL );
-
     memset( &p_input->p->counters, 0, sizeof( p_input->p->counters ) );
     vlc_mutex_init( &p_input->p->counters.counters_lock );
 
@@ -356,11 +356,11 @@ input_thread_t *__input_CreateThread( vlc_object_t *p_parent,
 /* */
 input_thread_t *__input_CreateThreadExtended( vlc_object_t *p_parent,
                                               input_item_t *p_item,
-                                              const char *psz_log, sout_instance_t *p_sout )
+                                              const char *psz_log, input_ressource_t *p_ressource )
 {
     input_thread_t *p_input;
 
-    p_input = Create( p_parent, p_item, psz_log, false, p_sout );
+    p_input = Create( p_parent, p_item, psz_log, false, p_ressource );
     if( !p_input )
         return NULL;
 
index c134b40..7b2490c 100644 (file)
@@ -53,16 +53,23 @@ typedef struct input_ressource_t input_ressource_t;
 void input_ressource_Delete( input_ressource_t * );
 
 /**
- * This function return the current sout (if any) from the ressource
- * and stop tracking it.
+ * This function deletes the current sout in the ressources.
  *
- * You are then responsible of its release.
+ * It can only be called on detached ressources.
  */
-sout_instance_t *input_ressource_ExtractSout( input_ressource_t *p_ressource );
+void input_ressource_TerminateSout( input_ressource_t *p_ressource );
+
+/**
+ * This function deletes the current vout in the ressources.
+ *
+ * It can only be called on detached ressources.
+ */
+void input_ressource_TerminateVout( input_ressource_t *p_ressource );
+
 
 /* input.c */
 #define input_CreateThreadExtended(a,b,c,d) __input_CreateThreadExtended(VLC_OBJECT(a),b,c,d)
-input_thread_t *__input_CreateThreadExtended ( vlc_object_t *, input_item_t *, const char *, sout_instance_t * );
+input_thread_t *__input_CreateThreadExtended ( vlc_object_t *, input_item_t *, const char *, input_ressource_t * );
 
 /**
  * This function detaches ressources from a dead input.
index 5313879..0de570b 100644 (file)
@@ -60,28 +60,20 @@ static void DestroySout( input_ressource_t *p_ressource )
         sout_DeleteInstance( p_ressource->p_sout );
     p_ressource->p_sout = NULL;
 }
-static sout_instance_t *ExtractSout( input_ressource_t *p_ressource )
-{
-    sout_instance_t *p_sout = p_ressource->p_sout;
-
-    p_ressource->p_sout = NULL;
-
-    return p_sout;
-}
 static sout_instance_t *RequestSout( input_ressource_t *p_ressource,
                                      sout_instance_t *p_sout, const char *psz_sout )
 {
-    assert( p_ressource->p_input );
-    assert( !p_sout || ( !p_ressource->p_sout && !psz_sout ) );
-
     if( !p_sout && !psz_sout )
     {
         if( p_ressource->p_sout )
-            msg_Dbg( p_ressource->p_input, "destroying useless sout" );
+            msg_Dbg( p_ressource->p_sout, "destroying useless sout" );
         DestroySout( p_ressource );
         return NULL;
     }
 
+    assert( p_ressource->p_input );
+    assert( !p_sout || ( !p_ressource->p_sout && !psz_sout ) );
+
     /* Check the validity of the sout */
     if( p_ressource->p_sout &&
         strcmp( p_ressource->p_sout->psz_sout, psz_sout ) )
@@ -104,7 +96,11 @@ static sout_instance_t *RequestSout( input_ressource_t *p_ressource,
             /* Create a new one */
             p_ressource->p_sout = sout_NewInstance( p_ressource->p_input, psz_sout );
         }
-        return ExtractSout( p_ressource );
+
+        p_sout = p_ressource->p_sout;
+        p_ressource->p_sout = NULL;
+
+        return p_sout;
     }
     else
     {
@@ -128,25 +124,24 @@ static void DestroyVout( input_ressource_t *p_ressource )
 static vout_thread_t *RequestVout( input_ressource_t *p_ressource,
                                    vout_thread_t *p_vout, video_format_t *p_fmt )
 {
-    assert( p_ressource->p_input );
-
     if( !p_vout && !p_fmt )
     {
         if( p_ressource->p_vout_free )
         {
-            msg_Err( p_ressource->p_input, "destroying useless vout" );
+            msg_Dbg( p_ressource->p_vout_free, "destroying useless vout" );
             vout_CloseAndRelease( p_ressource->p_vout_free );
             p_ressource->p_vout_free = NULL;
         }
         return NULL;
     }
 
+    assert( p_ressource->p_input );
     if( p_fmt )
     {
         /* */
         if( !p_vout && p_ressource->p_vout_free )
         {
-            msg_Err( p_ressource->p_input, "trying to reuse free vout" );
+            msg_Dbg( p_ressource->p_input, "trying to reuse free vout" );
             p_vout = p_ressource->p_vout_free;
 
             p_ressource->p_vout_free = NULL;
@@ -171,12 +166,12 @@ static vout_thread_t *RequestVout( input_ressource_t *p_ressource,
         TAB_REMOVE( p_ressource->i_vout, p_ressource->pp_vout, p_vout );
         if( p_ressource->p_vout_free )
         {
-            msg_Err( p_ressource->p_input, "detroying vout (already one saved)" );
+            msg_Dbg( p_ressource->p_input, "detroying vout (already one saved)" );
             vout_CloseAndRelease( p_vout );
         }
         else
         {
-            msg_Err( p_ressource->p_input, "saving a free vout" );
+            msg_Dbg( p_ressource->p_input, "saving a free vout" );
             p_ressource->p_vout_free = p_vout;
         }
         return NULL;
@@ -208,7 +203,7 @@ static aout_instance_t *RequestAout( input_ressource_t *p_ressource, aout_instan
 
     if( p_aout )
     {
-        msg_Err( p_ressource->p_input, "releasing aout" );
+        msg_Dbg( p_ressource->p_input, "releasing aout" );
         vlc_object_release( p_aout );
         return NULL;
     }
@@ -216,19 +211,19 @@ static aout_instance_t *RequestAout( input_ressource_t *p_ressource, aout_instan
     {
         if( !p_ressource->p_aout )
         {
-            msg_Err( p_ressource->p_input, "creating aout" );
+            msg_Dbg( p_ressource->p_input, "creating aout" );
             p_ressource->p_aout = aout_New( p_ressource->p_input );
         }
         else
         {
-            msg_Err( p_ressource->p_input, "reusing aout" );
-            vlc_object_attach( p_ressource->p_aout, p_ressource->p_input );
+            msg_Dbg( p_ressource->p_input, "reusing aout" );
         }
 
-
         if( !p_ressource->p_aout )
             return NULL;
 
+        vlc_object_detach( p_ressource->p_aout );
+        vlc_object_attach( p_ressource->p_aout, p_ressource->p_input );
         vlc_object_hold( p_ressource->p_aout );
         return p_ressource->p_aout;
     }
@@ -295,6 +290,10 @@ vout_thread_t *input_ressource_HoldVout( input_ressource_t *p_ressource )
 
     return p_ret;
 }
+void input_ressource_TerminateVout( input_ressource_t *p_ressource )
+{
+    input_ressource_RequestVout( p_ressource, NULL, NULL );
+}
 
 /* */
 aout_instance_t *input_ressource_RequestAout( input_ressource_t *p_ressource, aout_instance_t *p_aout )
@@ -315,13 +314,8 @@ sout_instance_t *input_ressource_RequestSout( input_ressource_t *p_ressource, so
 
     return p_ret;
 }
-sout_instance_t *input_ressource_ExtractSout( input_ressource_t *p_ressource )
+void input_ressource_TerminateSout( input_ressource_t *p_ressource )
 {
-    vlc_mutex_lock( &p_ressource->lock );
-    sout_instance_t *p_ret = ExtractSout( p_ressource );
-    vlc_mutex_unlock( &p_ressource->lock );
-
-    return p_ret;
+    input_ressource_RequestSout( p_ressource, NULL, NULL );
 }
 
-
index 3d6bea1..ad6b00b 100644 (file)
@@ -755,7 +755,7 @@ static vlm_media_instance_sys_t *vlm_MediaInstanceNew( vlm_t *p_vlm, const char
     p_instance->i_index = 0;
     p_instance->b_sout_keep = false;
     p_instance->p_input = NULL;
-    p_instance->p_sout = NULL;
+    p_instance->p_input_ressource = NULL;
 
     return p_instance;
 }
@@ -774,8 +774,8 @@ static void vlm_MediaInstanceDelete( vlm_media_instance_sys_t *p_instance )
 
         vlc_object_release( p_input );
     }
-    if( p_instance->p_sout )
-        sout_DeleteInstance( p_instance->p_sout );
+    if( p_instance->p_input_ressource )
+        input_ressource_Delete( p_instance->p_input_ressource );
 
     vlc_gc_decref( p_instance->p_item );
     free( p_instance->psz_name );
@@ -839,8 +839,6 @@ static int vlm_ControlMediaInstanceStart( vlm_t *p_vlm, int64_t id, const char *
     input_thread_t *p_input = p_instance->p_input;
     if( p_input )
     {
-        input_ressource_t *p_ressource;
-
         if( p_instance->i_index == i_input_index &&
             !p_input->b_eof && !p_input->b_error )
         {
@@ -852,13 +850,13 @@ static int vlm_ControlMediaInstanceStart( vlm_t *p_vlm, int64_t id, const char *
         input_StopThread( p_input );
         vlc_thread_join( p_input );
 
-        p_ressource = input_DetachRessource( p_input );
+        p_instance->p_input_ressource = input_DetachRessource( p_input );
 
         vlc_object_release( p_input );
 
-        if( p_instance->b_sout_keep )
-            p_instance->p_sout = input_ressource_ExtractSout( p_ressource );
-        input_ressource_Delete( p_ressource );
+        if( !p_instance->b_sout_keep )
+            input_ressource_TerminateSout( p_instance->p_input_ressource );
+        input_ressource_TerminateVout( p_instance->p_input_ressource );
     }
 
     /* Start new one */
@@ -867,16 +865,15 @@ static int vlm_ControlMediaInstanceStart( vlm_t *p_vlm, int64_t id, const char *
 
     if( asprintf( &psz_log, _("Media: %s"), p_media->cfg.psz_name ) != -1 )
     {
-        p_instance->p_input = input_CreateThreadExtended( p_vlm, p_instance->p_item, psz_log, p_instance->p_sout );
+        p_instance->p_input = input_CreateThreadExtended( p_vlm, p_instance->p_item,
+                                                          psz_log, p_instance->p_input_ressource );
+        p_instance->p_input_ressource = NULL;
+
         if( !p_instance->p_input )
         {
             TAB_REMOVE( p_media->i_instance, p_media->instance, p_instance );
             vlm_MediaInstanceDelete( p_instance );
         }
-        else
-        {
-            p_instance->p_sout = NULL;
-        }
         free( psz_log );
     }
 
index 670f5a1..074c790 100644 (file)
@@ -41,9 +41,9 @@ typedef struct
 
     bool      b_sout_keep;
 
-    input_item_t    *p_item;
-    input_thread_t  *p_input;
-    sout_instance_t *p_sout;
+    input_item_t      *p_item;
+    input_thread_t    *p_input;
+    input_ressource_t *p_input_ressource;
 
 } vlm_media_instance_sys_t;
 
index ed175c6..0952bcf 100644 (file)
@@ -175,7 +175,7 @@ static void playlist_Destructor( vlc_object_t * p_this )
     playlist_private_t *p_sys = pl_priv(p_playlist);
 
     assert( !p_sys->p_input );
-    assert( !p_sys->p_sout );
+    assert( !p_sys->p_input_ressource );
     assert( !p_sys->p_preparser );
     assert( !p_sys->p_fetcher );
 
index efc1d02..dc68225 100644 (file)
@@ -46,7 +46,6 @@ typedef struct playlist_private_t
     playlist_t           public_data;
     playlist_preparser_t *p_preparser;  /**< Preparser data */
     playlist_fetcher_t   *p_fetcher;    /**< Meta and art fetcher data */
-    sout_instance_t      *p_sout;       /**< Kept sout instance */
 
     playlist_item_array_t items_to_delete; /**< Array of items and nodes to
             delete... At the very end. This sucks. */
@@ -60,6 +59,7 @@ typedef struct playlist_private_t
     int                   i_sds;   /**< Number of service discovery modules */
     input_thread_t *      p_input;  /**< the input thread associated
                                      * with the current item */
+    input_ressource_t *   p_input_ressource; /**< input ressources */
     struct {
         /* Current status. These fields are readonly, only the playlist
          * main loop can touch it*/
index f6606dd..4763823 100644 (file)
@@ -98,10 +98,10 @@ void playlist_Deactivate( playlist_t *p_playlist )
     if( p_fetcher )
         playlist_fetcher_Delete( p_fetcher );
 
-    /* close the remaining sout-keep */
-    if( p_sys->p_sout )
-        sout_DeleteInstance( p_sys->p_sout );
-    p_sys->p_sout = NULL;
+    /* release input ressources */
+    if( p_sys->p_input_ressource )
+        input_ressource_Delete( p_sys->p_input_ressource );
+    p_sys->p_input_ressource = NULL;
 
     /* */
     playlist_MLDump( p_playlist );
@@ -263,7 +263,7 @@ static int PlayItem( playlist_t *p_playlist, playlist_item_t *p_item )
     assert( p_sys->p_input == NULL );
 
     input_thread_t *p_input_thread =
-        input_CreateThreadExtended( p_playlist, p_input, NULL, p_sys->p_sout );
+        input_CreateThreadExtended( p_playlist, p_input, NULL, p_sys->p_input_ressource );
 
     if( p_input_thread )
     {
@@ -272,7 +272,7 @@ static int PlayItem( playlist_t *p_playlist, playlist_item_t *p_item )
         var_AddCallback( p_input_thread, "intf-event", InputEvent, p_playlist );
     }
 
-    p_sys->p_sout = NULL;
+    p_sys->p_input_ressource = NULL;
 
     char *psz_uri = input_item_GetURI( p_item->p_input );
     if( psz_uri && ( !strncmp( psz_uri, "directory:", 10 ) ||
@@ -492,13 +492,11 @@ static int LoopInput( playlist_t *p_playlist )
     {
         PL_DEBUG( "dead input" );
 
-        assert( p_sys->p_sout == NULL );
+        assert( p_sys->p_input_ressource == NULL );
 
-        input_ressource_t *p_ressource = input_DetachRessource( p_input );
-
-        if( var_CreateGetBool( p_input, "sout-keep" ) )
-            p_sys->p_sout = input_ressource_ExtractSout( p_ressource );
-        input_ressource_Delete( p_ressource );
+        p_sys->p_input_ressource = input_DetachRessource( p_input );
+        if( !var_CreateGetBool( p_input, "sout-keep" ) )
+            input_ressource_TerminateSout( p_sys->p_input_ressource );
 
         /* The DelCallback must be issued without playlist lock
          * It is not a problem as we return VLC_EGENERIC */
@@ -546,6 +544,9 @@ static void LoopRequest( playlist_t *p_playlist )
     {
         p_sys->status.i_status = PLAYLIST_STOPPED;
 
+        if( p_sys->p_input_ressource )
+            input_ressource_TerminateVout( p_sys->p_input_ressource );
+
         if( vlc_object_alive( p_playlist ) )
             vlc_object_wait( p_playlist );
         return;