docs/design/part-block.txt: Further explain the use of flushing on blocked pads.
authorEdward Hervey <bilboed@bilboed.com>
Mon, 2 Oct 2006 16:01:54 +0000 (16:01 +0000)
committerEdward Hervey <bilboed@bilboed.com>
Mon, 2 Oct 2006 16:01:54 +0000 (16:01 +0000)
Original commit message from CVS:
* docs/design/part-block.txt:
Further explain the use of flushing on blocked pads.
* docs/gst/gstreamer-sections.txt:
* gst/gstpad.c: (gst_pad_is_blocking), (handle_pad_block),
(gst_pad_push_event):
* gst/gstpad.h:
Added new GstPadFlag : GST_PAD_BLOCKING.
Adds the notion of pads really blocking, which enables to properly
handle FLUSH_START/FLUSH_STOP events on blocked pads.
Fixes #358999
API: gst_pad_is_blocking()
API: GST_PAD_IS_BLOCKING() macro
API: GST_PAD_BLOCKING GstPadFlag

ChangeLog
docs/design/part-block.txt
docs/gst/gstreamer-sections.txt
gst/gstpad.c
gst/gstpad.h

index 198cf57..2740c66 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+2006-10-02  Edward Hervey  <edward@fluendo.com>
+
+       * docs/design/part-block.txt:
+       Further explain the use of flushing on blocked pads.
+       * docs/gst/gstreamer-sections.txt:
+       * gst/gstpad.c: (gst_pad_is_blocking), (handle_pad_block),
+       (gst_pad_push_event):
+       * gst/gstpad.h:
+       Added new GstPadFlag : GST_PAD_BLOCKING.
+       Adds the notion of pads really blocking, which enables to properly
+       handle FLUSH_START/FLUSH_STOP events on blocked pads.
+       Fixes #358999
+       API: gst_pad_is_blocking()
+       API: GST_PAD_IS_BLOCKING() macro
+       API: GST_PAD_BLOCKING GstPadFlag
+       
+
 2006-10-02  Wim Taymans  <wim@fluendo.com>
 
        Patch by: mrcgran <mrc.gran at gmail dot com>
index c5a3edd..c53a700 100644 (file)
@@ -23,6 +23,8 @@ Flushing
  The flushing event is used to clear any data out of the
  downstream elements.
 
+* Generic case
+
  Consider the following pipeline: 
 
  .-----.      .-------.      .-------.
@@ -48,6 +50,39 @@ Flushing
  fr the same reason. From then on, the new data after the flushing seek 
  will be queued when the pad block is taken again.
 
+* Case where the stream is blocking downstream
+
+ The example above is only valid if the elem1.src pad is really blocking
+ (callback called or sync block returned).
+ In the case where the stream is blocking further downstream (on elem2.src
+ for example, or on a blocking queue), extra care has to be taken.
+
+ Consider the following pipeline:
+
+ .-----.      .-------.      .-------.
+ | src |      | elem1 |\/    | elem2 |
+ |    src -> sink    src -> sink    src .... Blocking somewhere downstream
+ '-----'      '-------'/\    '-------'              
+
+ A pad block has been requested by the user on elem1.src , but since the stream
+ is blocking somewhere downstream, the callback is not called or the sync block
+ does not return.
+
+ In order for the block to happen, a FLUSH_START needs to be:
+ _ either sent directly on the downstream blocking element/pad so that it
+   release the stream lock, and it gives a chance for the elem1.src pad to
+   block.
+ _ A FLUSH_START is sent downstream from an upstream element, causing all the
+   pads down to the blocking element/pad (including elem1.src) to go to the
+   FLUSHING state. A FLUSH_STOP can now be sent downstream, causing all the
+   pads down to the previously blocking element to unset their FLUSHING state.
+   The next push will then properly block on elem1.src.
+
+ In this case, the pads have to be careful when handling the FLUSH events
+ forwarding. Those events should only be forwarded downstream is the BLOCKED
+ pad was previously BLOCKING.
+
 
 Use cases:
 ----------
index 2c260bd..072e689 100644 (file)
@@ -1183,6 +1183,7 @@ gst_pad_set_blocked
 gst_pad_set_blocked_async
 GstPadBlockCallback
 gst_pad_is_blocked
+gst_pad_is_blocking
 
 gst_pad_add_data_probe
 gst_pad_add_buffer_probe
@@ -1345,6 +1346,7 @@ GST_PAD_ACTIVATE_MODE
 GST_PAD_DO_BUFFER_SIGNALS
 GST_PAD_DO_EVENT_SIGNALS
 GST_PAD_IS_BLOCKED
+GST_PAD_IS_BLOCKING
 GST_PAD_IS_IN_SETCAPS
 GST_PAD_SET_FLUSHING
 GST_PAD_TASK
index 689a42a..54c1c57 100644 (file)
@@ -1049,6 +1049,35 @@ gst_pad_is_blocked (GstPad * pad)
 }
 
 /**
+ * gst_pad_is_blocking:
+ * @pad: the #GstPad to query
+ *
+ * Checks if the pad is blocking or not. This is a guaranteed state
+ * of whether the pad is actually blocking on a #GstBuffer or a #GstEvent.
+ *
+ * Returns: TRUE if the pad is blocking.
+ *
+ * MT safe.
+ */
+gboolean
+gst_pad_is_blocking (GstPad * pad)
+{
+  gboolean result = FALSE;
+
+  g_return_val_if_fail (GST_IS_PAD (pad), result);
+
+  GST_OBJECT_LOCK (pad);
+
+  /* the blocking flag is only valid if the pad is not flushing */
+
+  result = GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_BLOCKING) &&
+      !GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLUSHING);
+  GST_OBJECT_UNLOCK (pad);
+
+  return result;
+}
+
+/**
  * gst_pad_set_activate_function:
  * @pad: a #GstPad.
  * @activate: the #GstPadActivateFunction to set.
@@ -3141,7 +3170,7 @@ gst_ghost_pad_save_thyself (GstPad * pad, xmlNodePtr parent)
 
 /*
  * should be called with pad OBJECT_LOCK and STREAM_LOCK held. 
- * GST_PAD_IS_BLOCK (pad) == TRUE when this function is
+ * GST_PAD_IS_BLOCKED (pad) == TRUE when this function is
  * called.
  *
  * This function perform the pad blocking when an event, buffer push
@@ -3163,6 +3192,11 @@ gst_ghost_pad_save_thyself (GstPad * pad, xmlNodePtr parent)
  * - the GCond signal method, which makes any thread unblock when
  *   the pad block happens.
  *
+ * During the actual blocking state, the GST_PAD_BLOCKING flag is set.
+ * The GST_PAD_BLOCKING flag is unset when the GST_PAD_FLUSHING flag is
+ * unset. This is to know whether the pad was blocking when GST_PAD_FLUSHING
+ * was set.
+ *
  * MT safe.
  */
 static GstFlowReturn
@@ -3215,6 +3249,9 @@ handle_pad_block (GstPad * pad)
      * deactivate the pad (which will also set the FLUSHING flag) or
      * when the pad is unblocked. A flushing event will also unblock
      * the pad after setting the FLUSHING flag. */
+    GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
+        "Waiting to be unblocked or set flushing");
+    GST_OBJECT_FLAG_SET (pad, GST_PAD_BLOCKING);
     GST_PAD_BLOCK_WAIT (pad);
 
     /* see if we got unlocked by a flush or not */
@@ -3222,6 +3259,10 @@ handle_pad_block (GstPad * pad)
       goto flushing;
   }
 
+  /* If we made it here we either never blocked, or were unblocked because we
+   * weren't flushing, it is therefore safe to remove the BLOCKING flag */
+  GST_OBJECT_FLAG_UNSET (pad, GST_PAD_BLOCKING);
+
   GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "got unblocked");
 
   /* when we get here, the pad is unblocked again and we perform
@@ -3821,9 +3862,9 @@ gst_pad_push_event (GstPad * pad, GstEvent * event)
     case GST_EVENT_FLUSH_START:
       GST_PAD_SET_FLUSHING (pad);
 
-      if (G_UNLIKELY (GST_PAD_IS_BLOCKED (pad))) {
+      if (G_UNLIKELY (GST_PAD_IS_BLOCKING (pad))) {
         /* flush start will have set the FLUSHING flag and will then
-         * unlock all threads doing a GCond wait on the blocked pad. This
+         * unlock all threads doing a GCond wait on the blocking pad. This
          * will typically unblock the STREAMING thread blocked on a pad. */
         GST_PAD_BLOCK_SIGNAL (pad);
         goto flushed;
@@ -3832,8 +3873,15 @@ gst_pad_push_event (GstPad * pad, GstEvent * event)
     case GST_EVENT_FLUSH_STOP:
       GST_PAD_UNSET_FLUSHING (pad);
 
-      if (G_UNLIKELY (GST_PAD_IS_BLOCKED (pad)))
+      /* If pad was blocking on something when the pad received flush-start, we
+       * don't forward the flush-stop event either. */
+      if (G_UNLIKELY (GST_PAD_IS_BLOCKING (pad))) {
+        GST_OBJECT_FLAG_UNSET (pad, GST_PAD_BLOCKING);
+        GST_LOG_OBJECT (pad,
+            "Pad was previously blocking, not forwarding flush-stop");
         goto flushed;
+      }
+      GST_OBJECT_FLAG_UNSET (pad, GST_PAD_BLOCKING);
       break;
     default:
       if (G_UNLIKELY (GST_PAD_IS_BLOCKED (pad))) {
index 8079ee6..9d1e751 100644 (file)
@@ -479,6 +479,7 @@ typedef enum {
  * @GST_PAD_FLUSHING: is pad refusing buffers
  * @GST_PAD_IN_GETCAPS: GstPadGetCapsFunction() is running now
  * @GST_PAD_IN_SETCAPS: GstPadSetCapsFunction() is running now
+ * @GST_PAD_BLOCKING: is pad currently blocking on a buffer or event
  * @GST_PAD_FLAG_LAST: offset to define more flags
  *
  * Pad state flags
@@ -488,6 +489,7 @@ typedef enum {
   GST_PAD_FLUSHING      = (GST_OBJECT_FLAG_LAST << 1),
   GST_PAD_IN_GETCAPS    = (GST_OBJECT_FLAG_LAST << 2),
   GST_PAD_IN_SETCAPS    = (GST_OBJECT_FLAG_LAST << 3),
+  GST_PAD_BLOCKING     = (GST_OBJECT_FLAG_LAST << 4),
   /* padding */
   GST_PAD_FLAG_LAST     = (GST_OBJECT_FLAG_LAST << 8)
 } GstPadFlags;
@@ -655,6 +657,7 @@ struct _GstPadClass {
 
 #define GST_PAD_IS_LINKED(pad)         (GST_PAD_PEER(pad) != NULL)
 #define GST_PAD_IS_BLOCKED(pad)                (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_BLOCKED))
+#define GST_PAD_IS_BLOCKING(pad)       (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_BLOCKING))
 #define GST_PAD_IS_FLUSHING(pad)       (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLUSHING))
 #define GST_PAD_IS_IN_GETCAPS(pad)     (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_IN_GETCAPS))
 #define GST_PAD_IS_IN_SETCAPS(pad)     (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_IN_SETCAPS))
@@ -771,6 +774,7 @@ gboolean            gst_pad_set_blocked                     (GstPad *pad, gboolean blocked);
 gboolean               gst_pad_set_blocked_async               (GstPad *pad, gboolean blocked,
                                                                 GstPadBlockCallback callback, gpointer user_data);
 gboolean               gst_pad_is_blocked                      (GstPad *pad);
+gboolean               gst_pad_is_blocking                     (GstPad *pad);
 
 void                   gst_pad_set_element_private             (GstPad *pad, gpointer priv);
 gpointer               gst_pad_get_element_private             (GstPad *pad);