gst/gstpad.c: Correctly check flushing and emit probes. fixes #330125
authorWim Taymans <wim.taymans@gmail.com>
Mon, 13 Feb 2006 09:59:03 +0000 (09:59 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Mon, 13 Feb 2006 09:59:03 +0000 (09:59 +0000)
Original commit message from CVS:
* gst/gstpad.c: (gst_pad_send_event):
Correctly check flushing and emit probes. fixes #330125

ChangeLog
gst/gstpad.c

index 4165536..561f133 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2006-02-13  Wim Taymans  <wim@fluendo.com>
+
+       * gst/gstpad.c: (gst_pad_send_event):
+       Correctly check flushing and emit probes. fixes #330125
+
 2006-02-10  Andy Wingo  <wingo@pobox.com>
 
        * gst/gstbus.c (gst_bus_class_init): Declare our private data
index bbc1763..b48267f 100644 (file)
@@ -3632,22 +3632,40 @@ gst_pad_send_event (GstPad * pad, GstEvent * event)
 {
   gboolean result = FALSE;
   GstPadEventFunction eventfunc;
-  gboolean emit_signal, serialized;
+  gboolean serialized, need_unlock = FALSE;
 
   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
   g_return_val_if_fail (event != NULL, FALSE);
 
   GST_OBJECT_LOCK (pad);
-  if (GST_PAD_IS_SINK (pad) && !GST_EVENT_IS_DOWNSTREAM (event))
-    goto wrong_direction;
-  if (GST_PAD_IS_SRC (pad) && !GST_EVENT_IS_UPSTREAM (event))
-    goto wrong_direction;
+  if (GST_PAD_IS_SINK (pad)) {
+    if (G_UNLIKELY (!GST_EVENT_IS_DOWNSTREAM (event)))
+      goto wrong_direction;
+    serialized = GST_EVENT_IS_SERIALIZED (event);
+  } else if (GST_PAD_IS_SRC (pad)) {
+    if (G_UNLIKELY (!GST_EVENT_IS_UPSTREAM (event)))
+      goto wrong_direction;
+    /* events on srcpad never are serialized */
+    serialized = FALSE;
+  } else
+    goto unknown_direction;
 
-  if (GST_EVENT_SRC (event) == NULL) {
+  if (G_UNLIKELY (GST_EVENT_SRC (event) == NULL)) {
     GST_LOG_OBJECT (pad, "event had no source, setting pad as event source");
     GST_EVENT_SRC (event) = gst_object_ref (pad);
   }
 
+  /* pad signals */
+  if (G_UNLIKELY (GST_PAD_DO_EVENT_SIGNALS (pad) > 0)) {
+    GST_OBJECT_UNLOCK (pad);
+
+    if (!gst_pad_emit_have_data_signal (pad, GST_MINI_OBJECT_CAST (event)))
+      goto dropping;
+
+    GST_OBJECT_LOCK (pad);
+  }
+
+
   switch (GST_EVENT_TYPE (event)) {
     case GST_EVENT_FLUSH_START:
       GST_CAT_DEBUG (GST_CAT_EVENT,
@@ -3663,38 +3681,41 @@ gst_pad_send_event (GstPad * pad, GstEvent * event)
     case GST_EVENT_FLUSH_STOP:
       GST_PAD_UNSET_FLUSHING (pad);
       GST_CAT_DEBUG (GST_CAT_EVENT, "cleared flush flag");
+      GST_OBJECT_UNLOCK (pad);
+      /* grab stream lock */
+      GST_PAD_STREAM_LOCK (pad);
+      need_unlock = TRUE;
+      GST_OBJECT_LOCK (pad);
       break;
     default:
       GST_CAT_DEBUG (GST_CAT_EVENT, "have event type %s on pad %s:%s",
           gst_event_type_get_name (GST_EVENT_TYPE (event)),
           GST_DEBUG_PAD_NAME (pad));
 
-      if (GST_PAD_IS_FLUSHING (pad))
+      /* make this a little faster, no point in grabbing the lock
+       * if the pad is allready flushing. */
+      if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad)))
         goto flushing;
+
+      if (serialized) {
+        /* lock order: STREAM_LOCK, LOCK */
+        GST_OBJECT_UNLOCK (pad);
+        GST_PAD_STREAM_LOCK (pad);
+        need_unlock = TRUE;
+        GST_OBJECT_LOCK (pad);
+        if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad)))
+          goto flushing;
+      }
       break;
   }
-
-  if ((eventfunc = GST_PAD_EVENTFUNC (pad)) == NULL)
+  if (G_UNLIKELY ((eventfunc = GST_PAD_EVENTFUNC (pad)) == NULL))
     goto no_function;
 
-  emit_signal = GST_PAD_DO_EVENT_SIGNALS (pad) > 0;
   GST_OBJECT_UNLOCK (pad);
 
-  /* have to check if it's a sink pad, because e.g. CUSTOM_BOTH is serialized
-     when going down but not when going up */
-  serialized = GST_EVENT_IS_SERIALIZED (event) && GST_PAD_IS_SINK (pad);
-
-  if (G_UNLIKELY (emit_signal)) {
-    if (!gst_pad_emit_have_data_signal (pad, GST_MINI_OBJECT (event)))
-      goto dropping;
-  }
-
-  if (serialized)
-    GST_PAD_STREAM_LOCK (pad);
-
-  result = eventfunc (GST_PAD_CAST (pad), event);
+  result = eventfunc (pad, event);
 
-  if (serialized)
+  if (need_unlock)
     GST_PAD_STREAM_UNLOCK (pad);
 
   return result;
@@ -3708,6 +3729,13 @@ wrong_direction:
     gst_event_unref (event);
     return FALSE;
   }
+unknown_direction:
+  {
+    g_warning ("pad %s:%s has invalid direction", GST_DEBUG_PAD_NAME (pad));
+    GST_OBJECT_UNLOCK (pad);
+    gst_event_unref (event);
+    return FALSE;
+  }
 no_function:
   {
     g_warning ("pad %s:%s has no event handler, file a bug.",
@@ -3719,6 +3747,8 @@ no_function:
 flushing:
   {
     GST_OBJECT_UNLOCK (pad);
+    if (need_unlock)
+      GST_PAD_STREAM_UNLOCK (pad);
     GST_CAT_INFO (GST_CAT_EVENT, "Received event on flushing pad. Discarding");
     gst_event_unref (event);
     return FALSE;