docs/design/part-block.txt: Further explain the use of flushing on blocked pads.

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
This commit is contained in:
Edward Hervey 2006-10-02 16:01:54 +00:00
parent bae90f5955
commit 8923a57a6f
5 changed files with 110 additions and 4 deletions

View file

@ -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>

View 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:
----------

View 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

View file

@ -1048,6 +1048,35 @@ gst_pad_is_blocked (GstPad * pad)
return result;
}
/**
* 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.
@ -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))) {

View 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);