gstreamer_core/libs/gst/base/gstcollectpads.c
changeset 8 4a7fac7dd34a
parent 0 0e761a78d257
child 30 7e817e7e631c
--- a/gstreamer_core/libs/gst/base/gstcollectpads.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gstreamer_core/libs/gst/base/gstcollectpads.c	Fri Apr 16 15:15:52 2010 +0300
@@ -95,6 +95,7 @@
     GstCollectPadsClass * g_class);
 static void ref_data (GstCollectData * data);
 static void unref_data (GstCollectData * data);
+static void gst_collect_pads_check_pads_unlocked (GstCollectPads * pads);
 
 static void
 gst_collect_pads_base_init (gpointer g_class)
@@ -545,6 +546,36 @@
   return GST_FLOW_NOT_SUPPORTED;
 }
 
+static gboolean
+gst_collect_pads_is_flushing (GstCollectPads * pads)
+{
+  GSList *walk = NULL;
+  gboolean res = TRUE;
+
+  GST_COLLECT_PADS_PAD_LOCK (pads);
+
+  /* Ensure pads->data state */
+  gst_collect_pads_check_pads_unlocked (pads);
+
+  GST_DEBUG ("Getting flushing state (pads:%p, pads->data:%p)",
+      pads, pads->data);
+
+  for (walk = pads->data; walk; walk = g_slist_next (walk)) {
+    GstCollectData *cdata = walk->data;
+
+    GST_DEBUG_OBJECT (cdata->pad, "flushing:%d", cdata->abidata.ABI.flushing);
+
+    if (cdata->abidata.ABI.flushing) {
+      goto done;
+    }
+  }
+
+  res = FALSE;
+done:
+  GST_COLLECT_PADS_PAD_UNLOCK (pads);
+  return res;
+}
+
 /* FIXME, I think this function is used to work around bad behaviour
  * of elements that add pads to themselves without activating them.
  *
@@ -556,6 +587,8 @@
 {
   GSList *walk = NULL;
 
+  GST_DEBUG ("Setting flushing (%d)", flushing);
+
   /* Update the pads flushing flag */
   for (walk = pads->data; walk; walk = g_slist_next (walk)) {
     GstCollectData *cdata = walk->data;
@@ -571,6 +604,10 @@
       GST_OBJECT_UNLOCK (cdata->pad);
     }
   }
+  /* Setting the pads to flushing means that we changed the values which
+   * are 'protected' by the cookie. We therefore update it to force a 
+   * recalculation of the current pad status. */
+  pads->abidata.ABI.pad_cookie++;
 }
 
 /**
@@ -597,6 +634,8 @@
   g_return_if_fail (GST_IS_COLLECT_PADS (pads));
 
   GST_COLLECT_PADS_PAD_LOCK (pads);
+  /* Ensure pads->data state */
+  gst_collect_pads_check_pads_unlocked (pads);
   gst_collect_pads_set_flushing_unlocked (pads, flushing);
   GST_COLLECT_PADS_PAD_UNLOCK (pads);
 }
@@ -831,19 +870,20 @@
 
     /* ignore pad with EOS */
     if (G_UNLIKELY (pdata->abidata.ABI.eos)) {
-      GST_DEBUG ("pad %p is EOS", pdata);
+      GST_DEBUG ("pad %s:%s is EOS", GST_DEBUG_PAD_NAME (pdata->pad));
       continue;
     }
 
     /* an empty buffer without EOS is weird when we get here.. */
     if (G_UNLIKELY ((buffer = pdata->buffer) == NULL)) {
-      GST_WARNING ("pad %p has no buffer", pdata);
+      GST_WARNING ("pad %s:%s has no buffer", GST_DEBUG_PAD_NAME (pdata->pad));
       goto not_filled;
     }
 
     /* this is the size left of the buffer */
     size = GST_BUFFER_SIZE (buffer) - pdata->pos;
-    GST_DEBUG ("pad %p has %d bytes left", pdata, size);
+    GST_DEBUG ("pad %s:%s has %d bytes left",
+        GST_DEBUG_PAD_NAME (pdata->pad), size);
 
     /* need to return the min of all available data */
     if (size < result)
@@ -1024,6 +1064,8 @@
 
   data->pos += size;
 
+  GST_LOG_OBJECT (pads, "Flushing %d bytes, requested %u", flushsize, size);
+
   if (data->pos >= GST_BUFFER_SIZE (buffer))
     /* _clear will also reset data->pos to 0 */
     gst_collect_pads_clear (pads, data);
@@ -1041,10 +1083,10 @@
  * Must be called with LOCK.
  */
 static void
-gst_collect_pads_check_pads (GstCollectPads * pads)
+gst_collect_pads_check_pads_unlocked (GstCollectPads * pads)
 {
-  /* the master list and cookie are protected with the PAD_LOCK */
-  GST_COLLECT_PADS_PAD_LOCK (pads);
+  GST_DEBUG ("stored cookie : %d, used_cookie:%d",
+      pads->abidata.ABI.pad_cookie, pads->cookie);
   if (G_UNLIKELY (pads->abidata.ABI.pad_cookie != pads->cookie)) {
     GSList *collected;
 
@@ -1064,10 +1106,13 @@
       /* update the stats */
       pads->numpads++;
       data = collected->data;
-      if (data->buffer)
-        pads->queuedpads++;
-      if (data->abidata.ABI.eos)
-        pads->eospads++;
+
+      if (G_LIKELY (!data->abidata.ABI.flushing)) {
+        if (data->buffer)
+          pads->queuedpads++;
+        if (data->abidata.ABI.eos)
+          pads->eospads++;
+      }
 
       /* add to the list of pads to collect */
       ref_data (data);
@@ -1076,6 +1121,14 @@
     /* and update the cookie */
     pads->cookie = pads->abidata.ABI.pad_cookie;
   }
+}
+
+static inline void
+gst_collect_pads_check_pads (GstCollectPads * pads)
+{
+  /* the master list and cookie are protected with the PAD_LOCK */
+  GST_COLLECT_PADS_PAD_LOCK (pads);
+  gst_collect_pads_check_pads_unlocked (pads);
   GST_COLLECT_PADS_PAD_UNLOCK (pads);
 }
 
@@ -1185,10 +1238,16 @@
         pads->eospads--;
         data->abidata.ABI.eos = FALSE;
       }
+
+      if (!gst_collect_pads_is_flushing (pads)) {
+        /* forward event if all pads are no longer flushing */
+        GST_DEBUG ("No more pads are flushing, forwarding FLUSH_STOP");
+        GST_OBJECT_UNLOCK (pads);
+        goto forward;
+      }
+      gst_event_unref (event);
       GST_OBJECT_UNLOCK (pads);
-
-      /* forward event */
-      goto forward;
+      goto done;
     }
     case GST_EVENT_EOS:
     {
@@ -1249,6 +1308,8 @@
   }
 
 forward:
+  GST_DEBUG_OBJECT (pads, "forward unhandled event: %s",
+      GST_EVENT_TYPE_NAME (event));
   res = gst_pad_event_default (pad, event);
 
 done:
@@ -1275,7 +1336,6 @@
 {
   GstCollectData *data;
   GstCollectPads *pads;
-  guint64 size;
   GstFlowReturn ret;
   GstBuffer **buffer_p;
 
@@ -1290,7 +1350,6 @@
   GST_OBJECT_UNLOCK (pad);
 
   pads = data->collect;
-  size = GST_BUFFER_SIZE (buffer);
 
   GST_OBJECT_LOCK (pads);
   /* if not started, bail out */
@@ -1321,6 +1380,7 @@
 
   /* While we have data queued on this pad try to collect stuff */
   do {
+    GST_DEBUG ("Pad %s:%s checking", GST_DEBUG_PAD_NAME (pad));
     /* Check if our collected condition is matched and call the collected function
      * if it is */
     ret = gst_collect_pads_check_collected (pads);
@@ -1363,6 +1423,7 @@
   while (data->buffer != NULL);
 
 unlock_done:
+  GST_DEBUG ("Pad %s:%s done", GST_DEBUG_PAD_NAME (pad));
   GST_OBJECT_UNLOCK (pads);
   unref_data (data);
   gst_buffer_unref (buffer);