mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-17 03:35:21 +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>
|
2006-10-02 Wim Taymans <wim@fluendo.com>
|
||||||
|
|
||||||
Patch by: mrcgran <mrc.gran at gmail dot 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
|
The flushing event is used to clear any data out of the
|
||||||
downstream elements.
|
downstream elements.
|
||||||
|
|
||||||
|
* Generic case
|
||||||
|
|
||||||
Consider the following pipeline:
|
Consider the following pipeline:
|
||||||
|
|
||||||
.-----. .-------. .-------.
|
.-----. .-------. .-------.
|
||||||
|
@ -48,6 +50,39 @@ Flushing
|
||||||
fr the same reason. From then on, the new data after the flushing seek
|
fr the same reason. From then on, the new data after the flushing seek
|
||||||
will be queued when the pad block is taken again.
|
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:
|
Use cases:
|
||||||
----------
|
----------
|
||||||
|
|
|
@ -1183,6 +1183,7 @@ gst_pad_set_blocked
|
||||||
gst_pad_set_blocked_async
|
gst_pad_set_blocked_async
|
||||||
GstPadBlockCallback
|
GstPadBlockCallback
|
||||||
gst_pad_is_blocked
|
gst_pad_is_blocked
|
||||||
|
gst_pad_is_blocking
|
||||||
|
|
||||||
gst_pad_add_data_probe
|
gst_pad_add_data_probe
|
||||||
gst_pad_add_buffer_probe
|
gst_pad_add_buffer_probe
|
||||||
|
@ -1345,6 +1346,7 @@ GST_PAD_ACTIVATE_MODE
|
||||||
GST_PAD_DO_BUFFER_SIGNALS
|
GST_PAD_DO_BUFFER_SIGNALS
|
||||||
GST_PAD_DO_EVENT_SIGNALS
|
GST_PAD_DO_EVENT_SIGNALS
|
||||||
GST_PAD_IS_BLOCKED
|
GST_PAD_IS_BLOCKED
|
||||||
|
GST_PAD_IS_BLOCKING
|
||||||
GST_PAD_IS_IN_SETCAPS
|
GST_PAD_IS_IN_SETCAPS
|
||||||
GST_PAD_SET_FLUSHING
|
GST_PAD_SET_FLUSHING
|
||||||
GST_PAD_TASK
|
GST_PAD_TASK
|
||||||
|
|
56
gst/gstpad.c
56
gst/gstpad.c
|
@ -1048,6 +1048,35 @@ gst_pad_is_blocked (GstPad * pad)
|
||||||
return result;
|
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:
|
* gst_pad_set_activate_function:
|
||||||
* @pad: a #GstPad.
|
* @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.
|
* 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.
|
* called.
|
||||||
*
|
*
|
||||||
* This function perform the pad blocking when an event, buffer push
|
* 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 GCond signal method, which makes any thread unblock when
|
||||||
* the pad block happens.
|
* 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.
|
* MT safe.
|
||||||
*/
|
*/
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
|
@ -3215,6 +3249,9 @@ handle_pad_block (GstPad * pad)
|
||||||
* deactivate the pad (which will also set the FLUSHING flag) or
|
* deactivate the pad (which will also set the FLUSHING flag) or
|
||||||
* when the pad is unblocked. A flushing event will also unblock
|
* when the pad is unblocked. A flushing event will also unblock
|
||||||
* the pad after setting the FLUSHING flag. */
|
* 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);
|
GST_PAD_BLOCK_WAIT (pad);
|
||||||
|
|
||||||
/* see if we got unlocked by a flush or not */
|
/* see if we got unlocked by a flush or not */
|
||||||
|
@ -3222,6 +3259,10 @@ handle_pad_block (GstPad * pad)
|
||||||
goto flushing;
|
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");
|
GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "got unblocked");
|
||||||
|
|
||||||
/* when we get here, the pad is unblocked again and we perform
|
/* 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:
|
case GST_EVENT_FLUSH_START:
|
||||||
GST_PAD_SET_FLUSHING (pad);
|
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
|
/* 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. */
|
* will typically unblock the STREAMING thread blocked on a pad. */
|
||||||
GST_PAD_BLOCK_SIGNAL (pad);
|
GST_PAD_BLOCK_SIGNAL (pad);
|
||||||
goto flushed;
|
goto flushed;
|
||||||
|
@ -3832,8 +3873,15 @@ gst_pad_push_event (GstPad * pad, GstEvent * event)
|
||||||
case GST_EVENT_FLUSH_STOP:
|
case GST_EVENT_FLUSH_STOP:
|
||||||
GST_PAD_UNSET_FLUSHING (pad);
|
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;
|
goto flushed;
|
||||||
|
}
|
||||||
|
GST_OBJECT_FLAG_UNSET (pad, GST_PAD_BLOCKING);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (G_UNLIKELY (GST_PAD_IS_BLOCKED (pad))) {
|
if (G_UNLIKELY (GST_PAD_IS_BLOCKED (pad))) {
|
||||||
|
|
|
@ -479,6 +479,7 @@ typedef enum {
|
||||||
* @GST_PAD_FLUSHING: is pad refusing buffers
|
* @GST_PAD_FLUSHING: is pad refusing buffers
|
||||||
* @GST_PAD_IN_GETCAPS: GstPadGetCapsFunction() is running now
|
* @GST_PAD_IN_GETCAPS: GstPadGetCapsFunction() is running now
|
||||||
* @GST_PAD_IN_SETCAPS: GstPadSetCapsFunction() 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
|
* @GST_PAD_FLAG_LAST: offset to define more flags
|
||||||
*
|
*
|
||||||
* Pad state flags
|
* Pad state flags
|
||||||
|
@ -488,6 +489,7 @@ typedef enum {
|
||||||
GST_PAD_FLUSHING = (GST_OBJECT_FLAG_LAST << 1),
|
GST_PAD_FLUSHING = (GST_OBJECT_FLAG_LAST << 1),
|
||||||
GST_PAD_IN_GETCAPS = (GST_OBJECT_FLAG_LAST << 2),
|
GST_PAD_IN_GETCAPS = (GST_OBJECT_FLAG_LAST << 2),
|
||||||
GST_PAD_IN_SETCAPS = (GST_OBJECT_FLAG_LAST << 3),
|
GST_PAD_IN_SETCAPS = (GST_OBJECT_FLAG_LAST << 3),
|
||||||
|
GST_PAD_BLOCKING = (GST_OBJECT_FLAG_LAST << 4),
|
||||||
/* padding */
|
/* padding */
|
||||||
GST_PAD_FLAG_LAST = (GST_OBJECT_FLAG_LAST << 8)
|
GST_PAD_FLAG_LAST = (GST_OBJECT_FLAG_LAST << 8)
|
||||||
} GstPadFlags;
|
} GstPadFlags;
|
||||||
|
@ -655,6 +657,7 @@ struct _GstPadClass {
|
||||||
|
|
||||||
#define GST_PAD_IS_LINKED(pad) (GST_PAD_PEER(pad) != NULL)
|
#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_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_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_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))
|
#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,
|
gboolean gst_pad_set_blocked_async (GstPad *pad, gboolean blocked,
|
||||||
GstPadBlockCallback callback, gpointer user_data);
|
GstPadBlockCallback callback, gpointer user_data);
|
||||||
gboolean gst_pad_is_blocked (GstPad *pad);
|
gboolean gst_pad_is_blocked (GstPad *pad);
|
||||||
|
gboolean gst_pad_is_blocking (GstPad *pad);
|
||||||
|
|
||||||
void gst_pad_set_element_private (GstPad *pad, gpointer priv);
|
void gst_pad_set_element_private (GstPad *pad, gpointer priv);
|
||||||
gpointer gst_pad_get_element_private (GstPad *pad);
|
gpointer gst_pad_get_element_private (GstPad *pad);
|
||||||
|
|
Loading…
Reference in a new issue