]> git.sesse.net Git - vlc/blobdiff - src/input/resource.c
Use var_Inherit* instead of var_CreateGet*.
[vlc] / src / input / resource.c
index b3e140fc2ef3b18cab80bfc29773da5209b05ae0..f683e61b3679d7c3b8b5c276075236ee6f522e4e 100644 (file)
 # include "config.h"
 #endif
 
+#include <assert.h>
+
 #include <vlc_common.h>
 #include <vlc_vout.h>
-#include <vlc_osd.h>
+#include <vlc_spu.h>
 #include <vlc_aout.h>
 #include <vlc_sout.h>
 #include "../libvlc.h"
 
 struct input_resource_t
 {
+    VLC_GC_MEMBERS
+
+    vlc_object_t   *p_parent;
+
     /* This lock is used to serialize request and protect
      * our variables */
     vlc_mutex_t    lock;
@@ -51,14 +57,20 @@ struct input_resource_t
 
     sout_instance_t *p_sout;
     vout_thread_t   *p_vout_free;
-    aout_instance_t *p_aout;
 
     /* This lock is used to protect vout resources access (for hold)
      * It is a special case because of embed video (possible deadlock
-     * between vout window request and vout holds in some(qt4) interface) */
-    vlc_mutex_t    lock_vout;
+     * between vout window request and vout holds in some(qt4) interface)
+     */
+    vlc_mutex_t    lock_hold;
+
+    /* You need lock+lock_hold to write to the following variables and
+     * only lock or lock_hold to read them */
+
     int             i_vout;
     vout_thread_t   **pp_vout;
+
+    aout_instance_t *p_aout;
 };
 
 /* */
@@ -70,6 +82,7 @@ static void DestroySout( input_resource_t *p_resource )
 #endif
     p_resource->p_sout = NULL;
 }
+
 static sout_instance_t *RequestSout( input_resource_t *p_resource,
                                      sout_instance_t *p_sout, const char *psz_sout )
 {
@@ -89,7 +102,7 @@ static sout_instance_t *RequestSout( input_resource_t *p_resource,
     if( p_resource->p_sout &&
         strcmp( p_resource->p_sout->psz_sout, psz_sout ) )
     {
-        msg_Dbg( p_resource->p_input, "destroying unusable sout" );
+        msg_Dbg( p_resource->p_parent, "destroying unusable sout" );
         DestroySout( p_resource );
     }
 
@@ -98,14 +111,13 @@ static sout_instance_t *RequestSout( input_resource_t *p_resource,
         if( p_resource->p_sout )
         {
             /* Reuse it */
-            msg_Dbg( p_resource->p_input, "reusing sout" );
-            msg_Dbg( p_resource->p_input, "you probably want to use gather stream_out" );
-            vlc_object_attach( p_resource->p_sout, p_resource->p_input );
+            msg_Dbg( p_resource->p_parent, "reusing sout" );
+            msg_Dbg( p_resource->p_parent, "you probably want to use gather stream_out" );
         }
         else
         {
             /* Create a new one */
-            p_resource->p_sout = sout_NewInstance( p_resource->p_input, psz_sout );
+            p_resource->p_sout = sout_NewInstance( p_resource->p_parent, psz_sout );
         }
 
         p_sout = p_resource->p_sout;
@@ -115,9 +127,7 @@ static sout_instance_t *RequestSout( input_resource_t *p_resource,
     }
     else
     {
-        vlc_object_detach( p_sout );
         p_resource->p_sout = p_sout;
-
         return NULL;
     }
 #else
@@ -135,6 +145,7 @@ static void DestroyVout( input_resource_t *p_resource )
 
     p_resource->p_vout_free = NULL;
 }
+
 static void DisplayVoutTitle( input_resource_t *p_resource,
                               vout_thread_t *p_vout )
 {
@@ -178,9 +189,12 @@ static void DisplayVoutTitle( input_resource_t *p_resource,
     free( psz_nowplaying );
 }
 static vout_thread_t *RequestVout( input_resource_t *p_resource,
-                                   vout_thread_t *p_vout, video_format_t *p_fmt,
+                                   vout_thread_t *p_vout,
+                                   video_format_t *p_fmt, unsigned dpb_size,
                                    bool b_recycle )
 {
+    vlc_assert_locked( &p_resource->lock );
+
     if( !p_vout && !p_fmt )
     {
         if( p_resource->p_vout_free )
@@ -198,7 +212,7 @@ static vout_thread_t *RequestVout( input_resource_t *p_resource,
         /* */
         if( !p_vout && p_resource->p_vout_free )
         {
-            msg_Dbg( p_resource->p_input, "trying to reuse free vout" );
+            msg_Dbg( p_resource->p_parent, "trying to reuse free vout" );
             p_vout = p_resource->p_vout_free;
 
             p_resource->p_vout_free = NULL;
@@ -207,21 +221,28 @@ static vout_thread_t *RequestVout( input_resource_t *p_resource,
         {
             assert( p_vout != p_resource->p_vout_free );
 
-            vlc_mutex_lock( &p_resource->lock_vout );
+            vlc_mutex_lock( &p_resource->lock_hold );
             TAB_REMOVE( p_resource->i_vout, p_resource->pp_vout, p_vout );
-            vlc_mutex_unlock( &p_resource->lock_vout );
+            vlc_mutex_unlock( &p_resource->lock_hold );
         }
 
         /* */
-        p_vout = vout_Request( p_resource->p_input, p_vout, p_fmt );
+        vout_configuration_t cfg = {
+            .vout       = p_vout,
+            .input      = VLC_OBJECT(p_resource->p_input),
+            .change_fmt = true,
+            .fmt        = p_fmt,
+            .dpb_size   = dpb_size,
+        };
+        p_vout = vout_Request( p_resource->p_parent, &cfg );
         if( !p_vout )
             return NULL;
 
         DisplayVoutTitle( p_resource, p_vout );
 
-        vlc_mutex_lock( &p_resource->lock_vout );
+        vlc_mutex_lock( &p_resource->lock_hold );
         TAB_APPEND( p_resource->i_vout, p_resource->pp_vout, p_vout );
-        vlc_mutex_unlock( &p_resource->lock_vout );
+        vlc_mutex_unlock( &p_resource->lock_hold );
 
         return p_vout;
     }
@@ -229,57 +250,63 @@ static vout_thread_t *RequestVout( input_resource_t *p_resource,
     {
         assert( p_vout );
 
-        vlc_mutex_lock( &p_resource->lock_vout );
+        vlc_mutex_lock( &p_resource->lock_hold );
         TAB_REMOVE( p_resource->i_vout, p_resource->pp_vout, p_vout );
         const int i_vout_active = p_resource->i_vout;
-        vlc_mutex_unlock( &p_resource->lock_vout );
+        vlc_mutex_unlock( &p_resource->lock_hold );
 
         if( p_resource->p_vout_free || i_vout_active > 0 || !b_recycle )
         {
             if( b_recycle )
-                msg_Dbg( p_resource->p_input, "detroying vout (already one saved or active)" );
+                msg_Dbg( p_resource->p_parent, "detroying vout (already one saved or active)" );
             vout_CloseAndRelease( p_vout );
         }
         else
         {
-            msg_Dbg( p_resource->p_input, "saving a free vout" );
+            msg_Dbg( p_resource->p_parent, "saving a free vout" );
             vout_Flush( p_vout, 1 );
-            spu_Control( p_vout->p_spu, SPU_CHANNEL_CLEAR, -1 );
-
-            p_resource->p_vout_free = p_vout;
+            vout_FlushSubpictureChannel( p_vout, -1 );
+
+            vout_configuration_t cfg = {
+                .vout       = p_vout,
+                .input      = NULL,
+                .change_fmt = false,
+                .fmt        = NULL,
+                .dpb_size   = 0,
+            };
+            p_resource->p_vout_free = vout_Request( p_resource->p_parent, &cfg );
         }
         return NULL;
     }
 }
 static vout_thread_t *HoldVout( input_resource_t *p_resource )
 {
-    if( p_resource->i_vout <= 0 )
-        return NULL;
-
     /* TODO FIXME: p_resource->pp_vout order is NOT stable */
-    vlc_mutex_lock( &p_resource->lock_vout );
+    vlc_mutex_lock( &p_resource->lock_hold );
 
-    vout_thread_t *p_vout = p_resource->pp_vout[0];
+    vout_thread_t *p_vout = p_resource->i_vout > 0 ? p_resource->pp_vout[0] : NULL;
+    if( p_vout )
+        vlc_object_hold( p_vout );
 
-    vlc_object_hold( p_vout );
-
-    vlc_mutex_unlock( &p_resource->lock_vout );
+    vlc_mutex_unlock( &p_resource->lock_hold );
 
     return p_vout;
 }
-static void HoldVouts( input_resource_t *p_resource, vout_thread_t ***ppp_vout, int *pi_vout )
+
+static void HoldVouts( input_resource_t *p_resource, vout_thread_t ***ppp_vout,
+                       size_t *pi_vout )
 {
     vout_thread_t **pp_vout;
 
     *pi_vout = 0;
     *ppp_vout = NULL;
 
-    vlc_mutex_lock( &p_resource->lock_vout );
+    vlc_mutex_lock( &p_resource->lock_hold );
 
     if( p_resource->i_vout <= 0 )
         goto exit;
 
-    pp_vout = calloc( p_resource->i_vout, sizeof(*pp_vout) );
+    pp_vout = malloc( p_resource->i_vout * sizeof(*pp_vout) );
     if( !pp_vout )
         goto exit;
 
@@ -293,7 +320,7 @@ static void HoldVouts( input_resource_t *p_resource, vout_thread_t ***ppp_vout,
     }
 
 exit:
-    vlc_mutex_unlock( &p_resource->lock_vout );
+    vlc_mutex_unlock( &p_resource->lock_hold );
 }
 
 /* */
@@ -305,68 +332,99 @@ static void DestroyAout( input_resource_t *p_resource )
 }
 static aout_instance_t *RequestAout( input_resource_t *p_resource, aout_instance_t *p_aout )
 {
+    vlc_assert_locked( &p_resource->lock );
     assert( p_resource->p_input );
 
     if( p_aout )
     {
-        msg_Dbg( p_resource->p_input, "releasing aout" );
+        msg_Dbg( p_resource->p_parent, "releasing aout" );
         vlc_object_release( p_aout );
         return NULL;
     }
     else
     {
-        if( !p_resource->p_aout )
+        p_aout = p_resource->p_aout;
+        if( !p_aout )
         {
-            msg_Dbg( p_resource->p_input, "creating aout" );
-            p_resource->p_aout = aout_New( p_resource->p_input );
+            msg_Dbg( p_resource->p_parent, "creating aout" );
+            p_aout = aout_New( p_resource->p_parent );
+
+            vlc_mutex_lock( &p_resource->lock_hold );
+            p_resource->p_aout = p_aout;
+            vlc_mutex_unlock( &p_resource->lock_hold );
         }
         else
         {
-            msg_Dbg( p_resource->p_input, "reusing aout" );
+            msg_Dbg( p_resource->p_parent, "reusing aout" );
         }
 
-        if( !p_resource->p_aout )
+        if( !p_aout )
             return NULL;
-
-        vlc_object_detach( p_resource->p_aout );
-        vlc_object_attach( p_resource->p_aout, p_resource->p_input );
-        vlc_object_hold( p_resource->p_aout );
-        return p_resource->p_aout;
+        vlc_object_hold( p_aout );
+        return p_aout;
     }
 }
 static aout_instance_t *HoldAout( input_resource_t *p_resource )
 {
-    if( !p_resource->p_aout )
-        return NULL;
+    vlc_mutex_lock( &p_resource->lock_hold );
 
     aout_instance_t *p_aout = p_resource->p_aout;
+    if( p_aout )
+        vlc_object_hold( p_aout );
 
-    vlc_object_hold( p_aout );
+    vlc_mutex_unlock( &p_resource->lock_hold );
 
     return p_aout;
 }
+static void TerminateAout( input_resource_t *p_resource )
+{
+    vlc_mutex_lock( &p_resource->lock_hold );
+
+    aout_instance_t *p_aout = p_resource->p_aout;
+    p_resource->p_aout = NULL;
+
+    vlc_mutex_unlock( &p_resource->lock_hold );
+
+    if( p_aout )
+        vlc_object_release( p_aout );
+}
+
+static void Destructor( gc_object_t *p_gc )
+{
+    input_resource_t *p_resource = vlc_priv( p_gc, input_resource_t );
+
+    DestroySout( p_resource );
+    DestroyVout( p_resource );
+    DestroyAout( p_resource );
+
+    vlc_mutex_destroy( &p_resource->lock_hold );
+    vlc_mutex_destroy( &p_resource->lock );
+    free( p_resource );
+}
 
 /* */
-input_resource_t *input_resource_New( void )
+input_resource_t *input_resource_New( vlc_object_t *p_parent )
 {
     input_resource_t *p_resource = calloc( 1, sizeof(*p_resource) );
     if( !p_resource )
         return NULL;
 
+    vlc_gc_init( p_resource, Destructor );
+    p_resource->p_parent = p_parent;
     vlc_mutex_init( &p_resource->lock );
-    vlc_mutex_init( &p_resource->lock_vout );
+    vlc_mutex_init( &p_resource->lock_hold );
     return p_resource;
 }
 
-void input_resource_Delete( input_resource_t *p_resource )
+void input_resource_Release( input_resource_t *p_resource )
 {
-    DestroySout( p_resource );
-    DestroyVout( p_resource );
-    DestroyAout( p_resource );
+    vlc_gc_decref( p_resource );
+}
 
-    vlc_mutex_destroy( &p_resource->lock_vout );
-    vlc_mutex_destroy( &p_resource->lock );
-    free( p_resource );
+input_resource_t *input_resource_Hold( input_resource_t *p_resource )
+{
+    vlc_gc_incref( p_resource );
+    return p_resource;
 }
 
 void input_resource_SetInput( input_resource_t *p_resource, input_thread_t *p_input )
@@ -374,17 +432,7 @@ void input_resource_SetInput( input_resource_t *p_resource, input_thread_t *p_in
     vlc_mutex_lock( &p_resource->lock );
 
     if( p_resource->p_input && !p_input )
-    {
-        if( p_resource->p_aout )
-            vlc_object_detach( p_resource->p_aout );
-
         assert( p_resource->i_vout == 0 );
-        if( p_resource->p_vout_free )
-            vlc_object_detach( p_resource->p_vout_free );
-
-        if( p_resource->p_sout )
-            vlc_object_detach( p_resource->p_sout );
-    }
 
     /* */
     p_resource->p_input = p_input;
@@ -393,10 +441,12 @@ void input_resource_SetInput( input_resource_t *p_resource, input_thread_t *p_in
 }
 
 vout_thread_t *input_resource_RequestVout( input_resource_t *p_resource,
-                                            vout_thread_t *p_vout, video_format_t *p_fmt, bool b_recycle )
+                                            vout_thread_t *p_vout,
+                                            video_format_t *p_fmt, unsigned dpb_size,
+                                            bool b_recycle )
 {
     vlc_mutex_lock( &p_resource->lock );
-    vout_thread_t *p_ret = RequestVout( p_resource, p_vout, p_fmt, b_recycle );
+    vout_thread_t *p_ret = RequestVout( p_resource, p_vout, p_fmt, dpb_size, b_recycle );
     vlc_mutex_unlock( &p_resource->lock );
 
     return p_ret;
@@ -405,13 +455,16 @@ vout_thread_t *input_resource_HoldVout( input_resource_t *p_resource )
 {
     return HoldVout( p_resource );
 }
-void input_resource_HoldVouts( input_resource_t *p_resource, vout_thread_t ***ppp_vout, int *pi_vout )
+
+void input_resource_HoldVouts( input_resource_t *p_resource, vout_thread_t ***ppp_vout,
+                               size_t *pi_vout )
 {
     HoldVouts( p_resource, ppp_vout, pi_vout );
 }
+
 void input_resource_TerminateVout( input_resource_t *p_resource )
 {
-    input_resource_RequestVout( p_resource, NULL, NULL, false );
+    input_resource_RequestVout( p_resource, NULL, NULL, 0, false );
 }
 bool input_resource_HasVout( input_resource_t *p_resource )
 {
@@ -434,12 +487,9 @@ aout_instance_t *input_resource_RequestAout( input_resource_t *p_resource, aout_
 }
 aout_instance_t *input_resource_HoldAout( input_resource_t *p_resource )
 {
-    vlc_mutex_lock( &p_resource->lock );
-    aout_instance_t *p_ret = HoldAout( p_resource );
-    vlc_mutex_unlock( &p_resource->lock );
-
-    return p_ret;
+    return HoldAout( p_resource );
 }
+
 /* */
 sout_instance_t *input_resource_RequestSout( input_resource_t *p_resource, sout_instance_t *p_sout, const char *psz_sout )
 {
@@ -454,3 +504,14 @@ void input_resource_TerminateSout( input_resource_t *p_resource )
     input_resource_RequestSout( p_resource, NULL, NULL );
 }
 
+void input_resource_Terminate( input_resource_t *p_resource )
+{
+    input_resource_TerminateSout( p_resource );
+
+    vlc_mutex_lock( &p_resource->lock );
+    TerminateAout( p_resource );
+    vlc_mutex_unlock( &p_resource->lock );
+
+    input_resource_TerminateVout( p_resource );
+}
+