]> git.sesse.net Git - vlc/commitdiff
Prepare for safe (sout)/vout/aout recycling.
authorLaurent Aimar <fenrir@videolan.org>
Tue, 23 Dec 2008 18:45:59 +0000 (19:45 +0100)
committerLaurent Aimar <fenrir@videolan.org>
Mon, 5 Jan 2009 19:49:11 +0000 (20:49 +0100)
src/Makefile.am
src/input/decoder.c
src/input/input.c
src/input/input_interface.h
src/input/input_internal.h
src/input/ressource.c [new file with mode: 0644]
src/input/ressource.h [new file with mode: 0644]
src/input/vlm.c
src/playlist/thread.c

index 57a4ede8f4f1fc962eb759ff3f2586bc19fb6930..33fd13c084caf247490dedd987d1bb8f3cf654be 100644 (file)
@@ -331,6 +331,8 @@ SOURCES_libvlc_common = \
        input/input_internal.h \
        input/input_interface.h \
        input/vlm_internal.h \
+       input/ressource.h \
+       input/ressource.c \
        input/stream.c \
        input/stream_demux.c \
        input/stream_filter.c \
index 485b9165b0de8f893dec0b70dee6ea93a3e4e10c..f0663c03204ab9735bd242365db5ce5296dfbec4 100644 (file)
@@ -48,6 +48,7 @@
 #include "clock.h"
 #include "decoder.h"
 #include "event.h"
+#include "ressource.h"
 
 #include "../video_output/vout_control.h"
 
@@ -1875,7 +1876,7 @@ static void DecoderProcessSpu( decoder_t *p_dec, block_t *p_block, bool b_flush
         stats_UpdateInteger( p_dec, p_input->p->counters.p_decoded_sub, 1, NULL );
         vlc_mutex_unlock( &p_input->p->counters.counters_lock );
 
-        p_vout = vlc_object_find( p_dec, VLC_OBJECT_VOUT, FIND_ANYWHERE );
+        p_vout = input_ressource_HoldVout( p_input->p->p_ressource );
         if( p_vout && p_owner->p_spu_vout == p_vout )
         {
             /* Preroll does not work very well with subtitle */
@@ -1900,7 +1901,7 @@ static void DecoderProcessSpu( decoder_t *p_dec, block_t *p_block, bool b_flush
 
     if( b_flush && p_owner->p_spu_vout )
     {
-        p_vout = vlc_object_find( p_dec, VLC_OBJECT_VOUT, FIND_ANYWHERE );
+        p_vout = input_ressource_HoldVout( p_input->p->p_ressource );
 
         if( p_vout && p_owner->p_spu_vout == p_vout )
             spu_Control( p_vout->p_spu, SPU_CHANNEL_CLEAR,
@@ -2029,7 +2030,8 @@ static void DeleteDecoder( decoder_t * p_dec )
         aout_DecDelete( p_owner->p_aout, p_owner->p_aout_input );
     if( p_owner->p_aout )
     {
-        vlc_object_release( p_owner->p_aout );
+        input_ressource_RequestAout( p_owner->p_input->p->p_ressource,
+                                     p_owner->p_aout );
         p_owner->p_aout = NULL;
     }
     if( p_owner->p_vout )
@@ -2038,7 +2040,7 @@ static void DeleteDecoder( decoder_t * p_dec )
         vout_FixLeaks( p_owner->p_vout, true );
 
         /* We are about to die. Reattach video output to p_vlc. */
-        vout_Request( p_dec, p_owner->p_vout, NULL );
+        input_ressource_RequestVout( p_owner->p_input->p->p_ressource, p_owner->p_vout, NULL );
         input_SendEventVout( p_owner->p_input );
     }
 
@@ -2054,7 +2056,7 @@ static void DeleteDecoder( decoder_t * p_dec )
     {
         vout_thread_t *p_vout;
 
-        p_vout = vlc_object_find( p_dec, VLC_OBJECT_VOUT, FIND_ANYWHERE );
+        p_vout = input_ressource_HoldVout( p_owner->p_input->p->p_ressource );
         if( p_vout )
         {
             if( p_owner->p_spu_vout == p_vout )
@@ -2117,7 +2119,7 @@ static vout_thread_t *aout_request_vout( void *p_private,
 {
     decoder_t *p_dec = p_private;
 
-    p_vout =  vout_Request( p_dec, p_vout, p_fmt );
+    p_vout = input_ressource_RequestVout( p_dec->p_owner->p_input->p->p_ressource, p_vout, p_fmt );
     input_SendEventVout( p_dec->p_owner->p_input );
 
     return p_vout;
@@ -2180,6 +2182,8 @@ static aout_buffer_t *aout_new_buffer( decoder_t *p_dec, int i_samples )
         request_vout.p_private = p_dec;
 
         p_aout = p_owner->p_aout;
+        if( !p_aout )
+            p_aout = input_ressource_RequestAout( p_owner->p_input->p->p_ressource, NULL );
         p_aout_input = aout_DecNew( p_dec, &p_aout,
                                     &format, &p_dec->fmt_out.audio_replay_gain, &request_vout );
 
@@ -2291,7 +2295,8 @@ static picture_t *vout_new_buffer( decoder_t *p_dec )
         p_owner->p_vout = NULL;
         vlc_mutex_unlock( &p_owner->lock );
 
-        p_vout = vout_Request( p_dec, p_vout, &p_dec->fmt_out.video );
+        p_vout = input_ressource_RequestVout( p_owner->p_input->p->p_ressource,
+                                              p_vout, &p_dec->fmt_out.video );
 
         vlc_mutex_lock( &p_owner->lock );
         p_owner->p_vout = p_vout;
@@ -2378,7 +2383,7 @@ static subpicture_t *spu_new_buffer( decoder_t *p_dec )
         if( p_dec->b_die || p_dec->b_error )
             break;
 
-        p_vout = vlc_object_find( p_dec, VLC_OBJECT_VOUT, FIND_ANYWHERE );
+        p_vout = input_ressource_HoldVout( p_owner->p_input->p->p_ressource );
         if( p_vout )
             break;
 
@@ -2423,7 +2428,7 @@ static void spu_del_buffer( decoder_t *p_dec, subpicture_t *p_subpic )
     decoder_owner_sys_t *p_owner = p_dec->p_owner;
     vout_thread_t *p_vout = NULL;
 
-    p_vout = vlc_object_find( p_dec, VLC_OBJECT_VOUT, FIND_ANYWHERE );
+    p_vout = input_ressource_HoldVout( p_owner->p_input->p->p_ressource );
     if( !p_vout || p_owner->p_spu_vout != p_vout )
     {
         if( p_vout )
index af6ee7ada96d97fa7c8e44f4384bf41132021e6c..6a697d8e18d3704d4d6372e82fab24577cc8960b 100644 (file)
@@ -43,6 +43,7 @@
 #include "demux.h"
 #include "stream.h"
 #include "item.h"
+#include "ressource.h"
 
 #include <vlc_sout.h>
 #include "../stream_output/stream_output.h"
@@ -212,6 +213,10 @@ static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item,
     p_input->p->i_slave = 0;
     p_input->p->slave   = NULL;
 
+    /* */
+    p_input->p->p_ressource = input_ressource_New();
+    input_ressource_SetInput( p_input->p->p_ressource, p_input );
+
     /* Init control buffer */
     vlc_mutex_init( &p_input->p->lock_control );
     vlc_cond_init( &p_input->p->wait_control );
@@ -294,7 +299,7 @@ static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item,
 
     /* */
     if( p_sout )
-        p_input->p->p_sout = 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 );
@@ -321,10 +326,10 @@ static void Destructor( input_thread_t * p_input )
 
     stats_TimerDump( p_input, STATS_TIMER_INPUT_LAUNCHING );
     stats_TimerClean( p_input, STATS_TIMER_INPUT_LAUNCHING );
-#ifdef ENABLE_SOUT
-    if( p_input->p->p_sout )
-        sout_DeleteInstance( p_input->p->p_sout );
-#endif
+
+    if( p_input->p->p_ressource )
+        input_ressource_Delete( p_input->p->p_ressource );
+
     vlc_gc_decref( p_input->p->p_item );
 
     vlc_mutex_destroy( &p_input->p->counters.counters_lock );
@@ -451,13 +456,17 @@ void input_StopThread( input_thread_t *p_input )
     input_ControlPush( p_input, INPUT_CONTROL_SET_DIE, NULL );
 }
 
-sout_instance_t *input_DetachSout( input_thread_t *p_input )
+input_ressource_t *input_DetachRessource( input_thread_t *p_input )
 {
     assert( p_input->b_dead );
-    sout_instance_t *p_sout = p_input->p->p_sout;
-    vlc_object_detach( p_sout );
+
+    input_ressource_t *p_ressource = p_input->p->p_ressource;
+    input_ressource_SetInput( p_ressource, NULL );
+
+    p_input->p->p_ressource = NULL;
     p_input->p->p_sout = NULL;
-    return p_sout;
+
+    return p_ressource;
 }
 
 /**
@@ -843,46 +852,21 @@ static void InitStatistics( input_thread_t * p_input )
 #ifdef ENABLE_SOUT
 static int InitSout( input_thread_t * p_input )
 {
-    char *psz;
-
-    if( p_input->b_preparsing ) return VLC_SUCCESS;
+    if( p_input->b_preparsing )
+        return VLC_SUCCESS;
 
     /* Find a usable sout and attach it to p_input */
-    psz = var_GetNonEmptyString( p_input, "sout" );
+    char *psz = var_GetNonEmptyString( p_input, "sout" );
     if( psz && strncasecmp( p_input->p->p_item->psz_uri, "vlc:", 4 ) )
     {
-        /* Check the validity of the provided sout */
-        if( p_input->p->p_sout )
+        p_input->p->p_sout  = input_ressource_RequestSout( p_input->p->p_ressource, NULL, psz );
+        if( !p_input->p->p_sout )
         {
-            if( strcmp( p_input->p->p_sout->psz_sout, psz ) )
-            {
-                msg_Dbg( p_input, "destroying unusable sout" );
-
-                sout_DeleteInstance( p_input->p->p_sout );
-                p_input->p->p_sout = NULL;
-            }
-        }
-
-        if( p_input->p->p_sout )
-        {
-            /* Reuse it */
-            msg_Dbg( p_input, "sout keep: reusing sout" );
-            msg_Dbg( p_input, "sout keep: you probably want to use "
-                              "gather stream_out" );
-            vlc_object_attach( p_input->p->p_sout, p_input );
-        }
-        else
-        {
-            /* Create a new one */
-            p_input->p->p_sout = sout_NewInstance( p_input, psz );
-            if( !p_input->p->p_sout )
-            {
-                input_ChangeState( p_input, ERROR_S );
-                msg_Err( p_input, "cannot start stream output instance, " \
-                                  "aborting" );
-                free( psz );
-                return VLC_EGENERIC;
-            }
+            input_ChangeState( p_input, ERROR_S );
+            msg_Err( p_input, "cannot start stream output instance, " \
+                              "aborting" );
+            free( psz );
+            return VLC_EGENERIC;
         }
         if( libvlc_stats( p_input ) )
         {
@@ -894,12 +878,9 @@ static int InitSout( input_thread_t * p_input )
                          1000000;
         }
     }
-    else if( p_input->p->p_sout )
+    else
     {
-        msg_Dbg( p_input, "destroying useless sout" );
-
-        sout_DeleteInstance( p_input->p->p_sout );
-        p_input->p->p_sout = NULL;
+        input_ressource_RequestSout( p_input->p->p_ressource, NULL, NULL );
     }
     free( psz );
 
@@ -1254,13 +1235,13 @@ error:
         es_out_Delete( p_input->p->p_es_out );
     if( p_input->p->p_es_out_display )
         es_out_Delete( p_input->p->p_es_out_display );
-#ifdef ENABLE_SOUT
-    if( p_input->p->p_sout )
+    if( p_input->p->p_ressource )
     {
-        vlc_object_detach( p_input->p->p_sout );
-        sout_DeleteInstance( p_input->p->p_sout );
+        if( p_input->p->p_sout )
+            input_ressource_RequestSout( p_input->p->p_ressource,
+                                         p_input->p->p_sout, NULL );
+        input_ressource_SetInput( p_input->p->p_ressource, NULL );
     }
-#endif
 
     if( !p_input->b_preparsing && libvlc_stats( p_input ) )
     {
@@ -1386,8 +1367,6 @@ static void End( input_thread_t * p_input )
             CL_CO( sout_sent_packets );
             CL_CO( sout_sent_bytes );
             CL_CO( sout_send_bitrate );
-
-            vlc_object_detach( p_input->p->p_sout );
         }
 #undef CL_CO
     }
@@ -1399,6 +1378,11 @@ static void End( input_thread_t * p_input )
         TAB_CLEAN( p_input->p->i_attachment, p_input->p->attachment );
     }
 
+    /* */
+    input_ressource_RequestSout( p_input->p->p_ressource,
+                                 p_input->p->p_sout, NULL );
+    input_ressource_SetInput( p_input->p->p_ressource, NULL );
+
     /* Tell we're dead */
     input_SendEventDead( p_input );
 }
index a585666253d20ad18f73333ebc7e59ee810e9ade..c134b40f577bf0964f43a55a58c3480b0515680f 100644 (file)
@@ -42,11 +42,36 @@ void input_item_SetArtFetched( input_item_t *p_i, bool b_art_fetched );
  * FIXME it should NOT be defined here or not coded in misc/stats.c */
 input_stats_t *stats_NewInputStats( input_thread_t *p_input );
 
+/**
+ * This defines an opaque input ressource handler.
+ */
+typedef struct input_ressource_t input_ressource_t;
+
+/**
+ * This function releases an input_ressource_t and all associated ressources.
+ */
+void input_ressource_Delete( input_ressource_t * );
+
+/**
+ * This function return the current sout (if any) from the ressource
+ * and stop tracking it.
+ *
+ * You are then responsible of its release.
+ */
+sout_instance_t *input_ressource_ExtractSout( 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 * );
 
-sout_instance_t * input_DetachSout( input_thread_t *p_input );
+/**
+ * This function detaches ressources from a dead input.
+ *
+ * It MUST be called on a dead input (p_input->b_dead true) otherwise
+ * it will assert.
+ * It does not support concurrent calls.
+ */
+input_ressource_t *input_DetachRessource( input_thread_t * );
 
 /* */
 typedef enum
index 13fd9950c1febb1551037110fef26db0c1124f0f..c6f5488aec7dc47a713d663255dbc5a9f2fdb81c 100644 (file)
@@ -123,6 +123,9 @@ struct input_thread_private_t
     int            i_slave;
     input_source_t **slave;
 
+    /* Ressources */
+    input_ressource_t *p_ressource;
+
     /* Stats counters */
     struct {
         counter_t *p_read_packets;
diff --git a/src/input/ressource.c b/src/input/ressource.c
new file mode 100644 (file)
index 0000000..5313879
--- /dev/null
@@ -0,0 +1,327 @@
+/*****************************************************************************
+ * ressource.c
+ *****************************************************************************
+ * Copyright (C) 2008 Laurent Aimar
+ * $Id$
+ *
+ * Authors: Laurent Aimar < fenrir _AT_ videolan _DOT_ org >
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <vlc_common.h>
+#include <vlc_vout.h>
+#include <vlc_aout.h>
+#include <vlc_sout.h>
+#include "../libvlc.h"
+#include "../stream_output/stream_output.h"
+#include "../audio_output/aout_internal.h"
+#include "input_interface.h"
+#include "ressource.h"
+
+struct input_ressource_t
+{
+    vlc_mutex_t    lock;
+
+    input_thread_t *p_input;
+
+    sout_instance_t *p_sout;
+
+    int             i_vout;
+    vout_thread_t   **pp_vout;
+    vout_thread_t   *p_vout_free;
+
+    aout_instance_t *p_aout;
+};
+
+/* */
+static void DestroySout( input_ressource_t *p_ressource )
+{
+    if( p_ressource->p_sout )
+        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" );
+        DestroySout( p_ressource );
+        return NULL;
+    }
+
+    /* Check the validity of the sout */
+    if( p_ressource->p_sout &&
+        strcmp( p_ressource->p_sout->psz_sout, psz_sout ) )
+    {
+        msg_Dbg( p_ressource->p_input, "destroying unusable sout" );
+        DestroySout( p_ressource );
+    }
+
+    if( psz_sout )
+    {
+        if( p_ressource->p_sout )
+        {
+            /* Reuse it */
+            msg_Dbg( p_ressource->p_input, "reusing sout" );
+            msg_Dbg( p_ressource->p_input, "you probably want to use gather stream_out" );
+            vlc_object_attach( p_ressource->p_sout, p_ressource->p_input );
+        }
+        else
+        {
+            /* Create a new one */
+            p_ressource->p_sout = sout_NewInstance( p_ressource->p_input, psz_sout );
+        }
+        return ExtractSout( p_ressource );
+    }
+    else
+    {
+        vlc_object_detach( p_sout );
+        p_ressource->p_sout = p_sout;
+
+        return NULL;
+    }
+}
+
+/* */
+static void DestroyVout( input_ressource_t *p_ressource )
+{
+    assert( p_ressource->i_vout == 0 );
+
+    if( p_ressource->p_vout_free )
+        vout_CloseAndRelease( p_ressource->p_vout_free );
+
+    p_ressource->p_vout_free = NULL;
+}
+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" );
+            vout_CloseAndRelease( p_ressource->p_vout_free );
+            p_ressource->p_vout_free = NULL;
+        }
+        return NULL;
+    }
+
+    if( p_fmt )
+    {
+        /* */
+        if( !p_vout && p_ressource->p_vout_free )
+        {
+            msg_Err( p_ressource->p_input, "trying to reuse free vout" );
+            p_vout = p_ressource->p_vout_free;
+
+            p_ressource->p_vout_free = NULL;
+        }
+        else if( p_vout )
+        {
+            assert( p_vout != p_ressource->p_vout_free );
+            TAB_REMOVE( p_ressource->i_vout, p_ressource->pp_vout, p_vout );
+        }
+
+        /* */
+        p_vout = vout_Request( p_ressource->p_input, p_vout, p_fmt );
+        if( !p_vout )
+            return NULL;
+
+        TAB_APPEND( p_ressource->i_vout, p_ressource->pp_vout, p_vout );
+        return p_vout;
+    }
+    else
+    {
+        assert( p_vout );
+        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)" );
+            vout_CloseAndRelease( p_vout );
+        }
+        else
+        {
+            msg_Err( p_ressource->p_input, "saving a free vout" );
+            p_ressource->p_vout_free = p_vout;
+        }
+        return NULL;
+    }
+}
+static vout_thread_t *HoldVout( input_ressource_t *p_ressource )
+{
+    if( p_ressource->i_vout <= 0 )
+        return NULL;
+
+    /* TODO FIXME: p_ressource->pp_vout order is NOT stable */
+    vout_thread_t *p_vout = p_ressource->pp_vout[0];
+
+    vlc_object_hold( p_vout );
+
+    return p_vout;
+}
+
+/* */
+static void DestroyAout( input_ressource_t *p_ressource )
+{
+    if( p_ressource->p_aout )
+        vlc_object_release( p_ressource->p_aout );
+    p_ressource->p_aout = NULL;
+}
+static aout_instance_t *RequestAout( input_ressource_t *p_ressource, aout_instance_t *p_aout )
+{
+    assert( p_ressource->p_input );
+
+    if( p_aout )
+    {
+        msg_Err( p_ressource->p_input, "releasing aout" );
+        vlc_object_release( p_aout );
+        return NULL;
+    }
+    else
+    {
+        if( !p_ressource->p_aout )
+        {
+            msg_Err( 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 );
+        }
+
+
+        if( !p_ressource->p_aout )
+            return NULL;
+
+        vlc_object_hold( p_ressource->p_aout );
+        return p_ressource->p_aout;
+    }
+}
+
+/* */
+input_ressource_t *input_ressource_New( void )
+{
+    input_ressource_t *p_ressource = calloc( 1, sizeof(*p_ressource) );
+    if( !p_ressource )
+        return NULL;
+
+    vlc_mutex_init( &p_ressource->lock );
+    return p_ressource;
+}
+
+void input_ressource_Delete( input_ressource_t *p_ressource )
+{
+    DestroySout( p_ressource );
+    DestroyVout( p_ressource );
+    DestroyAout( p_ressource );
+
+    vlc_mutex_destroy( &p_ressource->lock );
+    free( p_ressource );
+}
+
+void input_ressource_SetInput( input_ressource_t *p_ressource, input_thread_t *p_input )
+{
+    vlc_mutex_lock( &p_ressource->lock );
+
+    if( p_ressource->p_input && !p_input )
+    {
+        if( p_ressource->p_aout )
+            vlc_object_detach( p_ressource->p_aout );
+
+        assert( p_ressource->i_vout == 0 );
+        if( p_ressource->p_vout_free )
+            vlc_object_detach( p_ressource->p_vout_free );
+
+        if( p_ressource->p_sout )
+            vlc_object_detach( p_ressource->p_sout );
+    }
+
+    /* */
+    p_ressource->p_input = p_input;
+
+    vlc_mutex_unlock( &p_ressource->lock );
+}
+
+vout_thread_t *input_ressource_RequestVout( input_ressource_t *p_ressource,
+                                            vout_thread_t *p_vout, video_format_t *p_fmt )
+{
+    vlc_mutex_lock( &p_ressource->lock );
+    vout_thread_t *p_ret = RequestVout( p_ressource, p_vout, p_fmt );
+    vlc_mutex_unlock( &p_ressource->lock );
+
+    return p_ret;
+}
+vout_thread_t *input_ressource_HoldVout( input_ressource_t *p_ressource )
+{
+    vlc_mutex_lock( &p_ressource->lock );
+    vout_thread_t *p_ret = HoldVout( p_ressource );
+    vlc_mutex_unlock( &p_ressource->lock );
+
+    return p_ret;
+}
+
+/* */
+aout_instance_t *input_ressource_RequestAout( input_ressource_t *p_ressource, aout_instance_t *p_aout )
+{
+    vlc_mutex_lock( &p_ressource->lock );
+    aout_instance_t *p_ret = RequestAout( p_ressource, p_aout );
+    vlc_mutex_unlock( &p_ressource->lock );
+
+    return p_ret;
+}
+
+/* */
+sout_instance_t *input_ressource_RequestSout( input_ressource_t *p_ressource, sout_instance_t *p_sout, const char *psz_sout )
+{
+    vlc_mutex_lock( &p_ressource->lock );
+    sout_instance_t *p_ret = RequestSout( p_ressource, p_sout, psz_sout );
+    vlc_mutex_unlock( &p_ressource->lock );
+
+    return p_ret;
+}
+sout_instance_t *input_ressource_ExtractSout( 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;
+}
+
+
diff --git a/src/input/ressource.h b/src/input/ressource.h
new file mode 100644 (file)
index 0000000..ec49c2a
--- /dev/null
@@ -0,0 +1,66 @@
+/*****************************************************************************
+ * ressource.h
+ *****************************************************************************
+ * Copyright (C) 2008 Laurent Aimar
+ * $Id$
+ *
+ * Authors: Laurent Aimar < fenrir _AT_ videolan _DOT_ org >
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#if defined(__PLUGIN__) || defined(__BUILTIN__) || !defined(__LIBVLC__)
+# error This header file can only be included from LibVLC.
+#endif
+
+#ifndef _INPUT_RESSOURCE_H
+#define _INPUT_RESSOURCE_H 1
+
+#include <vlc_common.h>
+
+/**
+ * This function creates an empty input_ressource_t.
+ */
+input_ressource_t *input_ressource_New( void );
+
+/**
+ * This function set the associated input.
+ */
+void input_ressource_SetInput( input_ressource_t *, input_thread_t * );
+
+/**
+ * This function handles sout request.
+ */
+sout_instance_t *input_ressource_RequestSout( input_ressource_t *, sout_instance_t *, const char *psz_sout );
+
+/**
+ * This function handles aout request.
+ */
+aout_instance_t *input_ressource_RequestAout( input_ressource_t *, aout_instance_t * );
+
+/**
+ * This function handles vout request.
+ */
+vout_thread_t *input_ressource_RequestVout( input_ressource_t *, vout_thread_t *, video_format_t * );
+
+/**
+ * This function return the current vout if any.
+ *
+ * You must call vlc_object_release on the value returned (if non NULL).
+ */
+vout_thread_t *input_ressource_HoldVout( input_ressource_t * );
+
+#endif
+
index dd249619a437cc3df4dd05bc68b2a79237c47461..3d6bea15c9eb04ac354f89ea93b19ded4e31c4fa 100644 (file)
@@ -764,9 +764,14 @@ static void vlm_MediaInstanceDelete( vlm_media_instance_sys_t *p_instance )
     input_thread_t *p_input = p_instance->p_input;
     if( p_input )
     {
+        input_ressource_t *p_ressource;
+
         input_StopThread( p_input );
         vlc_thread_join( p_input );
-        p_instance->p_sout = input_DetachSout( p_input );
+
+        p_ressource = input_DetachRessource( p_input );
+        input_ressource_Delete( p_ressource );
+
         vlc_object_release( p_input );
     }
     if( p_instance->p_sout )
@@ -834,6 +839,8 @@ 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 )
         {
@@ -844,13 +851,14 @@ static int vlm_ControlMediaInstanceStart( vlm_t *p_vlm, int64_t id, const char *
 
         input_StopThread( p_input );
         vlc_thread_join( p_input );
-        p_instance->p_sout = input_DetachSout( p_input );
+
+        p_ressource = input_DetachRessource( p_input );
+
         vlc_object_release( p_input );
-        if( !p_instance->b_sout_keep && p_instance->p_sout )
-        {
-            sout_DeleteInstance( p_instance->p_sout );
-            p_instance->p_sout = NULL;
-        }
+
+        if( p_instance->b_sout_keep )
+            p_instance->p_sout = input_ressource_ExtractSout( p_ressource );
+        input_ressource_Delete( p_ressource );
     }
 
     /* Start new one */
@@ -865,6 +873,10 @@ static int vlm_ControlMediaInstanceStart( vlm_t *p_vlm, int64_t id, const char *
             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 f7d8dde733411e4f2d27422cd487f806d719d202..f6606dd7137a1f781d98baa0f5ef6a5585dd974d 100644 (file)
@@ -493,8 +493,12 @@ static int LoopInput( playlist_t *p_playlist )
         PL_DEBUG( "dead input" );
 
         assert( p_sys->p_sout == NULL );
+
+        input_ressource_t *p_ressource = input_DetachRessource( p_input );
+
         if( var_CreateGetBool( p_input, "sout-keep" ) )
-            p_sys->p_sout = input_DetachSout( p_input );
+            p_sys->p_sout = input_ressource_ExtractSout( p_ressource );
+        input_ressource_Delete( p_ressource );
 
         /* The DelCallback must be issued without playlist lock
          * It is not a problem as we return VLC_EGENERIC */