basesrc: use new GCond for async state change
authorWim Taymans <wim.taymans@collabora.co.uk>
Wed, 24 Oct 2012 09:16:12 +0000 (11:16 +0200)
committerWim Taymans <wim.taymans@collabora.co.uk>
Wed, 24 Oct 2012 09:16:12 +0000 (11:16 +0200)
Use a new GCond, protected with the object lock, to signal completion
of the async state change. We can't reuse the live lock because that
one can be locked when the create function blocks.

Fixes https://bugzilla.gnome.org/show_bug.cgi?id=686723

libs/gst/base/gstbasesrc.c

index 679a33d..f8f3302 100644 (file)
@@ -183,6 +183,12 @@ GST_DEBUG_CATEGORY_STATIC (gst_base_src_debug);
 #define GST_LIVE_SIGNAL(elem)                 g_cond_signal (GST_LIVE_GET_COND (elem));
 #define GST_LIVE_BROADCAST(elem)              g_cond_broadcast (GST_LIVE_GET_COND (elem));
 
+
+#define GST_ASYNC_GET_COND(elem)              (&GST_BASE_SRC_CAST(elem)->priv->async_cond)
+#define GST_ASYNC_WAIT(elem)                  g_cond_wait (GST_ASYNC_GET_COND (elem), GST_OBJECT_GET_LOCK (elem))
+#define GST_ASYNC_SIGNAL(elem)                g_cond_signal (GST_ASYNC_GET_COND (elem));
+
+
 /* BaseSrc signals and args */
 enum
 {
@@ -251,6 +257,8 @@ struct _GstBaseSrcPrivate
   GstBufferPool *pool;
   GstAllocator *allocator;
   GstAllocationParams params;
+
+  GCond async_cond;
 };
 
 static GstElementClass *parent_class = NULL;
@@ -444,6 +452,7 @@ gst_base_src_init (GstBaseSrc * basesrc, gpointer g_class)
   basesrc->priv->do_timestamp = DEFAULT_DO_TIMESTAMP;
   g_atomic_int_set (&basesrc->priv->have_events, FALSE);
 
+  g_cond_init (&basesrc->priv->async_cond);
   basesrc->priv->start_result = GST_FLOW_FLUSHING;
   GST_OBJECT_FLAG_UNSET (basesrc, GST_BASE_SRC_FLAG_STARTED);
   GST_OBJECT_FLAG_UNSET (basesrc, GST_BASE_SRC_FLAG_STARTING);
@@ -462,6 +471,7 @@ gst_base_src_finalize (GObject * object)
 
   g_mutex_clear (&basesrc->live_lock);
   g_cond_clear (&basesrc->live_cond);
+  g_cond_clear (&basesrc->priv->async_cond);
 
   event_p = &basesrc->pending_seek;
   gst_event_replace (event_p, NULL);
@@ -3091,6 +3101,8 @@ gst_base_src_start (GstBaseSrc * basesrc)
   gboolean result;
 
   GST_LIVE_LOCK (basesrc);
+
+  GST_OBJECT_LOCK (basesrc);
   if (GST_BASE_SRC_IS_STARTING (basesrc))
     goto was_starting;
   if (GST_BASE_SRC_IS_STARTED (basesrc))
@@ -3098,12 +3110,12 @@ gst_base_src_start (GstBaseSrc * basesrc)
 
   basesrc->priv->start_result = GST_FLOW_FLUSHING;
   GST_OBJECT_FLAG_SET (basesrc, GST_BASE_SRC_FLAG_STARTING);
+  gst_segment_init (&basesrc->segment, basesrc->segment.format);
+  GST_OBJECT_UNLOCK (basesrc);
+
   basesrc->num_buffers_left = basesrc->num_buffers;
   basesrc->running = FALSE;
   basesrc->priv->segment_pending = FALSE;
-  GST_OBJECT_LOCK (basesrc);
-  gst_segment_init (&basesrc->segment, basesrc->segment.format);
-  GST_OBJECT_UNLOCK (basesrc);
   GST_LIVE_UNLOCK (basesrc);
 
   bclass = GST_BASE_SRC_GET_CLASS (basesrc);
@@ -3128,12 +3140,14 @@ gst_base_src_start (GstBaseSrc * basesrc)
 was_starting:
   {
     GST_DEBUG_OBJECT (basesrc, "was starting");
+    GST_OBJECT_UNLOCK (basesrc);
     GST_LIVE_UNLOCK (basesrc);
     return TRUE;
   }
 was_started:
   {
     GST_DEBUG_OBJECT (basesrc, "was started");
+    GST_OBJECT_UNLOCK (basesrc);
     GST_LIVE_UNLOCK (basesrc);
     return TRUE;
   }
@@ -3236,12 +3250,12 @@ gst_base_src_start_complete (GstBaseSrc * basesrc, GstFlowReturn ret)
       goto no_get_range;
   }
 
-  GST_LIVE_LOCK (basesrc);
+  GST_OBJECT_LOCK (basesrc);
   GST_OBJECT_FLAG_SET (basesrc, GST_BASE_SRC_FLAG_STARTED);
   GST_OBJECT_FLAG_UNSET (basesrc, GST_BASE_SRC_FLAG_STARTING);
   basesrc->priv->start_result = ret;
-  GST_LIVE_SIGNAL (basesrc);
-  GST_LIVE_UNLOCK (basesrc);
+  GST_ASYNC_SIGNAL (basesrc);
+  GST_OBJECT_UNLOCK (basesrc);
 
   GST_PAD_STREAM_UNLOCK (basesrc->srcpad);
 
@@ -3267,11 +3281,11 @@ no_get_range:
   }
 error:
   {
-    GST_LIVE_LOCK (basesrc);
+    GST_OBJECT_LOCK (basesrc);
     basesrc->priv->start_result = ret;
     GST_OBJECT_FLAG_UNSET (basesrc, GST_BASE_SRC_FLAG_STARTING);
-    GST_LIVE_SIGNAL (basesrc);
-    GST_LIVE_UNLOCK (basesrc);
+    GST_ASYNC_SIGNAL (basesrc);
+    GST_OBJECT_UNLOCK (basesrc);
     return;
   }
 }
@@ -3289,28 +3303,16 @@ gst_base_src_start_wait (GstBaseSrc * basesrc)
 {
   GstFlowReturn result;
 
-  GST_LIVE_LOCK (basesrc);
-  if (G_UNLIKELY (basesrc->priv->flushing))
-    goto flushing;
-
+  GST_OBJECT_LOCK (basesrc);
   while (GST_BASE_SRC_IS_STARTING (basesrc)) {
-    GST_LIVE_WAIT (basesrc);
-    if (G_UNLIKELY (basesrc->priv->flushing))
-      goto flushing;
+    GST_ASYNC_WAIT (basesrc);
   }
   result = basesrc->priv->start_result;
+  GST_OBJECT_UNLOCK (basesrc);
+
   GST_DEBUG_OBJECT (basesrc, "got %s", gst_flow_get_name (result));
-  GST_LIVE_UNLOCK (basesrc);
 
   return result;
-
-  /* ERRORS */
-flushing:
-  {
-    GST_DEBUG_OBJECT (basesrc, "we are flushing");
-    GST_LIVE_UNLOCK (basesrc);
-    return GST_FLOW_FLUSHING;
-  }
 }
 
 static gboolean
@@ -3326,15 +3328,15 @@ gst_base_src_stop (GstBaseSrc * basesrc)
   /* stop the task */
   gst_pad_stop_task (basesrc->srcpad);
 
-  GST_LIVE_LOCK (basesrc);
+  GST_OBJECT_LOCK (basesrc);
   if (!GST_BASE_SRC_IS_STARTED (basesrc) && !GST_BASE_SRC_IS_STARTING (basesrc))
     goto was_stopped;
 
   GST_OBJECT_FLAG_UNSET (basesrc, GST_BASE_SRC_FLAG_STARTING);
   GST_OBJECT_FLAG_UNSET (basesrc, GST_BASE_SRC_FLAG_STARTED);
   basesrc->priv->start_result = GST_FLOW_FLUSHING;
-  GST_LIVE_SIGNAL (basesrc);
-  GST_LIVE_UNLOCK (basesrc);
+  GST_ASYNC_SIGNAL (basesrc);
+  GST_OBJECT_UNLOCK (basesrc);
 
   bclass = GST_BASE_SRC_GET_CLASS (basesrc);
   if (bclass->stop)
@@ -3347,7 +3349,7 @@ gst_base_src_stop (GstBaseSrc * basesrc)
 was_stopped:
   {
     GST_DEBUG_OBJECT (basesrc, "was started");
-    GST_LIVE_UNLOCK (basesrc);
+    GST_OBJECT_UNLOCK (basesrc);
     return TRUE;
   }
 }