diff options
author | Thiago Santos <thiagoss@osg.samsung.com> | 2015-04-14 17:06:36 -0300 |
---|---|---|
committer | Thiago Santos <thiagoss@osg.samsung.com> | 2015-04-16 10:09:29 -0300 |
commit | 3d8de8a4f90e464e814c19c128776aa08e6be1b7 (patch) | |
tree | 1f97b63308a183c678100500199140706dcc9ffd /gst | |
parent | ac8a8f90b3249706292e1edc1372184a5e77171c (diff) |
pad: block data flow when idle probe is running
When idle probe runs directly from the gst_pad_add_probe() function
we need to make sure that no data flow happens as idle probe
is a blocking probe. The idle probe will prevent that any
buffer, bufferlist or serialized events and queries are not
flowing while it is running.
https://bugzilla.gnome.org/show_bug.cgi?id=747852
Diffstat (limited to 'gst')
-rw-r--r-- | gst/gstpad.c | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/gst/gstpad.c b/gst/gstpad.c index b762465b8..a7e1c37da 100644 --- a/gst/gstpad.c +++ b/gst/gstpad.c @@ -140,6 +140,11 @@ struct _GstPadPrivate gint using; guint probe_list_cookie; guint probe_cookie; + + /* counter of how many idle probes are running directly from the add_probe + * call. Used to block any data flowing in the pad while the idle callback + * Doesn't finish its work */ + gint idle_running; }; typedef struct @@ -149,6 +154,8 @@ typedef struct } GstProbe; #define PROBE_COOKIE(h) (((GstProbe *)(h))->cookie) +#define GST_PAD_IS_RUNNING_IDLE_PROBE(p) \ + (((GstPad *)(p))->priv->idle_running > 0) typedef struct { @@ -1387,6 +1394,7 @@ gst_pad_add_probe (GstPad * pad, GstPadProbeType mask, /* Keep another ref, the callback could destroy the pad */ gst_object_ref (pad); + pad->priv->idle_running++; /* the pad is idle now, we can signal the idle callback now */ GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, @@ -1416,6 +1424,10 @@ gst_pad_add_probe (GstPad * pad, GstPadProbeType mask, GST_DEBUG_OBJECT (pad, "probe returned %d", ret); break; } + pad->priv->idle_running--; + if (pad->priv->idle_running == 0) { + GST_PAD_BLOCK_BROADCAST (pad); + } GST_OBJECT_UNLOCK (pad); gst_object_unref (pad); @@ -3402,6 +3414,38 @@ no_match: PROBE_FULL(pad, mask, data, offs, size, label); static GstFlowReturn +do_pad_idle_probe_wait (GstPad * pad) +{ + while (GST_PAD_IS_RUNNING_IDLE_PROBE (pad)) { + GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, + "waiting idle probe to be removed"); + GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_BLOCKING); + GST_PAD_BLOCK_WAIT (pad); + GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_BLOCKING); + GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "We got unblocked"); + + if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad))) + return GST_FLOW_FLUSHING; + } + return GST_FLOW_OK; +} + +#define PROBE_TYPE_IS_SERIALIZED(i) \ + ( \ + ( \ + (((i)->type & (GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM | \ + GST_PAD_PROBE_TYPE_EVENT_FLUSH)) && \ + GST_EVENT_IS_SERIALIZED ((i)->data)) \ + ) || ( \ + (((i)->type & GST_PAD_PROBE_TYPE_QUERY_DOWNSTREAM) && \ + GST_QUERY_IS_SERIALIZED ((i)->data)) \ + ) || ( \ + ((i)->type & (GST_PAD_PROBE_TYPE_BUFFER | \ + GST_PAD_PROBE_TYPE_BUFFER_LIST)) \ + ) \ + ) + +static GstFlowReturn do_probe_callbacks (GstPad * pad, GstPadProbeInfo * info, GstFlowReturn defaultval) { @@ -3419,6 +3463,11 @@ do_probe_callbacks (GstPad * pad, GstPadProbeInfo * info, is_block = (info->type & GST_PAD_PROBE_TYPE_BLOCK) == GST_PAD_PROBE_TYPE_BLOCK; + if (is_block && PROBE_TYPE_IS_SERIALIZED (info)) { + if (do_pad_idle_probe_wait (pad) == GST_FLOW_FLUSHING) + goto flushing; + } + again: GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "do probes cookie %u", data.cookie); |