[vlc-devel] [PATCH 1/2] resource: add input_resource_WaitVout

Thomas Guillem thomas at gllm.fr
Tue Apr 2 17:19:07 CEST 2019


And input_resource_CancelWaitVout to cancel it.

cf. functions comments.
---
 src/input/resource.c | 61 ++++++++++++++++++++++++++++++++++++++++++++
 src/input/resource.h | 18 +++++++++++++
 2 files changed, 79 insertions(+)

diff --git a/src/input/resource.c b/src/input/resource.c
index 0812db6fe6..d84782d301 100644
--- a/src/input/resource.c
+++ b/src/input/resource.c
@@ -65,6 +65,10 @@ struct input_resource_t
      */
     vlc_mutex_t    lock_hold;
 
+    vlc_cond_t     wait_vout;
+    vlc_cond_t     wait_cancelled_vout;
+    void          *wait_vout_cancel_id;
+
     /* You need lock+lock_hold to write to the following variables and
      * only lock or lock_hold to read them */
 
@@ -330,8 +334,11 @@ input_resource_t *input_resource_New( vlc_object_t *p_parent )
 
     vlc_atomic_rc_init( &p_resource->rc );
     p_resource->p_parent = p_parent;
+    p_resource->wait_vout_cancel_id = NULL;
     vlc_mutex_init( &p_resource->lock );
     vlc_mutex_init( &p_resource->lock_hold );
+    vlc_cond_init(&p_resource->wait_vout);
+    vlc_cond_init(&p_resource->wait_cancelled_vout);
     return p_resource;
 }
 
@@ -345,6 +352,8 @@ void input_resource_Release( input_resource_t *p_resource )
     if( p_resource->p_aout != NULL )
         aout_Destroy( p_resource->p_aout );
 
+    vlc_cond_destroy(&p_resource->wait_cancelled_vout);
+    vlc_cond_destroy(&p_resource->wait_vout);
     vlc_mutex_destroy( &p_resource->lock_hold );
     vlc_mutex_destroy( &p_resource->lock );
     free( p_resource );
@@ -415,6 +424,7 @@ vout_thread_t *input_resource_GetVout(input_resource_t *p_resource,
 
     vlc_mutex_lock(&p_resource->lock_hold);
     TAB_APPEND(p_resource->i_vout, p_resource->pp_vout, vout);
+    vlc_cond_broadcast(&p_resource->wait_vout);
     vlc_mutex_unlock(&p_resource->lock_hold);
 
 out:
@@ -449,6 +459,57 @@ vout_thread_t *input_resource_HoldVout( input_resource_t *p_resource )
     return HoldVout( p_resource );
 }
 
+vout_thread_t *input_resource_WaitVout(input_resource_t *resource,
+                                       void *request_id)
+{
+    vlc_mutex_lock(&resource->lock_hold);
+
+    /* Wait for a vout or a cancel */
+    while (resource->i_vout == 0 && resource->wait_vout_cancel_id != request_id)
+        vlc_cond_wait(&resource->wait_vout, &resource->lock_hold);
+
+    const bool cancelled = resource->wait_vout_cancel_id == request_id;
+
+    vout_thread_t *p_vout;
+    if (!cancelled)
+    {
+        p_vout = resource->i_vout > 0 ? resource->pp_vout[0] : NULL;
+        if (p_vout)
+            vout_Hold(p_vout);
+    }
+    else
+        p_vout = NULL;
+
+    vlc_mutex_unlock(&resource->lock_hold);
+
+    return p_vout;
+}
+
+void input_resource_CancelWaitVout(input_resource_t *resource,
+                                   void *request_id)
+{
+    vlc_mutex_lock(&resource->lock_hold);
+
+    /* Make sure that a previous cancel terminated */
+    if (request_id != NULL)
+        while (resource->wait_vout_cancel_id != NULL)
+            vlc_cond_wait(&resource->wait_cancelled_vout, &resource->lock_hold);
+
+    resource->wait_vout_cancel_id = request_id;
+    if (request_id)
+    {
+        /* Signal that the input_resource_WaitVout() caller identified by
+         * request_id should cancel */
+        vlc_cond_broadcast(&resource->wait_vout);
+    }
+    else
+    {
+        /* Unblock future input_resource_CancelWaitVout() calls */
+        vlc_cond_broadcast(&resource->wait_cancelled_vout);
+    }
+    vlc_mutex_unlock(&resource->lock_hold);
+}
+
 void input_resource_HoldVouts( input_resource_t *p_resource, vout_thread_t ***ppp_vout,
                                size_t *pi_vout )
 {
diff --git a/src/input/resource.h b/src/input/resource.h
index 123018064c..57e8756be7 100644
--- a/src/input/resource.h
+++ b/src/input/resource.h
@@ -48,6 +48,24 @@ void input_resource_PutVout(input_resource_t *, vout_thread_t *);
  */
 vout_thread_t *input_resource_HoldVout( input_resource_t * );
 
+/**
+ * This function will wait for a vout
+ *
+ * The request_id is used to identify the caller, in order to cancel this call
+ * via input_resource_CancelWaitVout().
+ */
+vout_thread_t *input_resource_WaitVout(input_resource_t *, void *request_id);
+
+/**
+ * Cancel a call waiting for a vout
+ *
+ * This function must be called called 2 times. One time with a valid
+ * request_id in order to identify the caller to cancel. And a second time,
+ * after making sure that input_resource_WaitVout() returned, with a NULL
+ * request_id.
+ */
+void input_resource_CancelWaitVout(input_resource_t *, void *request_id);
+
 /**
  * This function returns all current vouts if any.
  *
-- 
2.20.1



More information about the vlc-devel mailing list