mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-23 02:01:12 +00:00
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:
parent
bae90f5955
commit
8923a57a6f
5 changed files with 110 additions and 4 deletions
17
ChangeLog
17
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>
|
||||
|
|
|
@ -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:
|
||||
----------
|
||||
|
|
|
@ -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
|
||||
|
|
56
gst/gstpad.c
56
gst/gstpad.c
|
@ -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))) {
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue