summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWim Taymans <wim.taymans@collabora.co.uk>2011-05-26 19:45:14 +0200
committerWim Taymans <wim.taymans@collabora.co.uk>2011-05-26 19:45:14 +0200
commit86c8b721b22910342186d8d5405025ac0a93769b (patch)
tree72f55a6b13e75f1141c5cea6dca9c53e4f6bb515
parentdd9fb5ebfd6b0425620dda9f7a7704ae81c14356 (diff)
pad: refactor _push_event
Rework _push_event() a little so that it drops events on blocking pads. Make sure that events are forwarded when we unblock. Add counter on the pad to keep track of busy pads.
-rw-r--r--gst/gstpad.c178
1 files changed, 107 insertions, 71 deletions
diff --git a/gst/gstpad.c b/gst/gstpad.c
index 7e9fcfdf3..5b784e5a7 100644
--- a/gst/gstpad.c
+++ b/gst/gstpad.c
@@ -425,6 +425,24 @@ replace_event (GstPad * srcpad, GstPad * sinkpad, guint idx)
return pending;
}
+
+static void
+prepare_event_update (GstPad * srcpad, GstPad * sinkpad)
+{
+ gboolean pending;
+ gint i;
+
+ /* make sure we push the events from the source to this new peer, for this we
+ * copy the events on the sinkpad and mark EVENTS_PENDING */
+ pending = FALSE;
+ for (i = 0; i < GST_EVENT_MAX_STICKY; i++)
+ pending |= replace_event (srcpad, sinkpad, i);
+
+ /* we had some new pending events, set our flag */
+ if (pending)
+ GST_OBJECT_FLAG_SET (sinkpad, GST_PAD_NEED_EVENTS);
+}
+
/* should be called with the OBJECT_LOCK */
static GstCaps *
get_pad_caps (GstPad * pad)
@@ -1117,6 +1135,17 @@ gst_pad_set_blocked (GstPad * pad, gboolean blocked,
} else {
GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "unblocking pad");
+ if (GST_PAD_IS_SRC (pad)) {
+ GstPad *peer;
+ /* a pad block dropped all events, make sure we copy any new events on the
+ * srcpad to the sinkpad and schedule an update on the sinkpad */
+ if ((peer = GST_PAD_PEER (pad))) {
+ GST_OBJECT_LOCK (peer);
+ prepare_event_update (pad, peer);
+ GST_OBJECT_UNLOCK (peer);
+ }
+ }
+
GST_OBJECT_FLAG_UNSET (pad, GST_PAD_BLOCKED);
if (pad->block_destroy_data && pad->block_data)
@@ -1987,8 +2016,6 @@ gst_pad_link_full (GstPad * srcpad, GstPad * sinkpad, GstPadLinkCheck flags)
{
GstPadLinkReturn result;
GstElement *parent;
- guint i;
- gboolean pending;
g_return_val_if_fail (GST_IS_PAD (srcpad), GST_PAD_LINK_REFUSED);
g_return_val_if_fail (GST_PAD_IS_SRC (srcpad), GST_PAD_LINK_WRONG_DIRECTION);
@@ -2018,15 +2045,8 @@ gst_pad_link_full (GstPad * srcpad, GstPad * sinkpad, GstPadLinkCheck flags)
GST_PAD_PEER (srcpad) = sinkpad;
GST_PAD_PEER (sinkpad) = srcpad;
- /* make sure we push the events from the source to this new peer, for this we
- * copy the events on the sinkpad and mark EVENTS_PENDING */
- pending = FALSE;
- for (i = 0; i < GST_EVENT_MAX_STICKY; i++)
- pending |= replace_event (srcpad, sinkpad, i);
-
- /* we had some new pending events, set our flag */
- if (pending)
- GST_OBJECT_FLAG_SET (sinkpad, GST_PAD_NEED_EVENTS);
+ /* make sure we update events */
+ prepare_event_update (srcpad, sinkpad);
GST_OBJECT_UNLOCK (sinkpad);
GST_OBJECT_UNLOCK (srcpad);
@@ -4365,7 +4385,7 @@ gboolean
gst_pad_push_event (GstPad * pad, GstEvent * event)
{
GstPad *peerpad;
- gboolean result;
+ gboolean result, need_probes, did_probes = FALSE, did_event_actions = FALSE;
gint64 offset;
g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
@@ -4374,6 +4394,7 @@ gst_pad_push_event (GstPad * pad, GstEvent * event)
GST_LOG_OBJECT (pad, "event: %s", GST_EVENT_TYPE_NAME (event));
+again:
GST_OBJECT_LOCK (pad);
/* Two checks to be made:
@@ -4395,34 +4416,11 @@ gst_pad_push_event (GstPad * pad, GstEvent * event)
break;
case GST_EVENT_FLUSH_STOP:
GST_PAD_UNSET_FLUSHING (pad);
-
- /* if we are blocked, flush away the FLUSH_STOP event */
- if (G_UNLIKELY (GST_PAD_IS_BLOCKED (pad))) {
- GST_LOG_OBJECT (pad, "Pad is blocked, not forwarding flush-stop");
- goto flushed;
- }
break;
- case GST_EVENT_RECONFIGURE:
- if (GST_PAD_IS_SINK (pad))
- GST_OBJECT_FLAG_SET (pad, GST_PAD_NEED_RECONFIGURE);
default:
- while (G_UNLIKELY (GST_PAD_IS_BLOCKED (pad))) {
- /* block the event as long as the pad is blocked */
- if (handle_pad_block (pad) != GST_FLOW_OK)
- goto flushed;
- }
break;
}
- if (G_UNLIKELY (GST_PAD_DO_EVENT_SIGNALS (pad) > 0)) {
- GST_OBJECT_UNLOCK (pad);
-
- if (!gst_pad_emit_have_data_signal (pad, GST_MINI_OBJECT_CAST (event)))
- goto dropping;
-
- GST_OBJECT_LOCK (pad);
- }
-
/* store the event on the pad, but only on srcpads */
if (GST_PAD_IS_SRC (pad) && GST_EVENT_IS_STICKY (event)) {
guint idx;
@@ -4435,48 +4433,81 @@ gst_pad_push_event (GstPad * pad, GstEvent * event)
gst_event_replace (&pad->priv->events[idx].event, event);
}
- if ((peerpad = GST_PAD_PEER (pad)))
- gst_object_ref (peerpad);
+ /* drop all events when blocking. Sticky events will stay on the pad and will
+ * be activated on the peer when unblocking. */
+ if (G_UNLIKELY (GST_PAD_IS_BLOCKED (pad))) {
+ GST_LOG_OBJECT (pad, "Pad is blocked, not forwarding event");
+ goto flushed;
+ }
offset = pad->offset;
- GST_OBJECT_UNLOCK (pad);
+ need_probes = !did_probes && (GST_PAD_DO_EVENT_SIGNALS (pad) > 0);
+ peerpad = GST_PAD_PEER (pad);
/* backwards compatibility mode for caps */
- switch (GST_EVENT_TYPE (event)) {
- case GST_EVENT_CAPS:
- {
- GstCaps *caps;
+ if (!did_event_actions) {
+ did_event_actions = TRUE;
- gst_event_parse_caps (event, &caps);
- /* FIXME, this is awkward because we don't check flushing here which means
- * that we can call the setcaps functions on flushing pads, this is not
- * quite what we want, otoh, this code should just go away and elements
- * that set caps on their sinkpad should just setup stuff themselves. */
- gst_pad_call_setcaps (pad, caps);
- break;
- }
- case GST_EVENT_SEGMENT:
- /* check if we need to adjust the segment */
- if (offset != 0 && peerpad != NULL) {
- GstSegment segment;
+ switch (GST_EVENT_TYPE (event)) {
+ case GST_EVENT_CAPS:
+ {
+ GstCaps *caps;
+
+ GST_OBJECT_UNLOCK (pad);
- /* copy segment values */
- gst_event_copy_segment (event, &segment);
- gst_event_unref (event);
+ gst_event_parse_caps (event, &caps);
+ /* FIXME, this is awkward because we don't check flushing here which means
+ * that we can call the setcaps functions on flushing pads, this is not
+ * quite what we want, otoh, this code should just go away and elements
+ * that set caps on their srcpad should just setup stuff themselves. */
+ gst_pad_call_setcaps (pad, caps);
- /* adjust and make a new event with the offset applied */
- segment.base += offset;
- event = gst_event_new_segment (&segment);
+ /* recheck everything, we released the lock */
+ goto again;
}
- break;
- default:
- break;
+ case GST_EVENT_SEGMENT:
+ /* check if we need to adjust the segment */
+ if (offset != 0 && (need_probes || peerpad != NULL)) {
+ GstSegment segment;
+
+ /* copy segment values */
+ gst_event_copy_segment (event, &segment);
+ gst_event_unref (event);
+
+ /* adjust and make a new event with the offset applied */
+ segment.base += offset;
+ event = gst_event_new_segment (&segment);
+ }
+ break;
+ case GST_EVENT_RECONFIGURE:
+ if (GST_PAD_IS_SINK (pad))
+ GST_OBJECT_FLAG_SET (pad, GST_PAD_NEED_RECONFIGURE);
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* send probes after modifying the events above */
+ if (G_UNLIKELY (need_probes)) {
+ did_probes = TRUE;
+ GST_OBJECT_UNLOCK (pad);
+
+ if (!gst_pad_emit_have_data_signal (pad, GST_MINI_OBJECT_CAST (event)))
+ goto dropping;
+
+ /* retry, we released the lock */
+ goto again;
}
/* now check the peer pad */
if (peerpad == NULL)
goto not_linked;
+ gst_object_ref (peerpad);
+ pad->priv->using++;
+ GST_OBJECT_UNLOCK (pad);
+
GST_LOG_OBJECT (pad, "sending event %s to peerpad %" GST_PTR_FORMAT,
GST_EVENT_TYPE_NAME (event), peerpad);
@@ -4488,9 +4519,21 @@ gst_pad_push_event (GstPad * pad, GstEvent * event)
gst_object_unref (peerpad);
+ GST_OBJECT_LOCK (pad);
+ pad->priv->using--;
+ GST_OBJECT_UNLOCK (pad);
+
return result;
/* ERROR handling */
+flushed:
+ {
+ GST_DEBUG_OBJECT (pad,
+ "Not forwarding event since we're flushing and blocking");
+ gst_event_unref (event);
+ GST_OBJECT_UNLOCK (pad);
+ return TRUE;
+ }
dropping:
{
GST_DEBUG_OBJECT (pad, "Dropping event after FALSE probe return");
@@ -4500,17 +4543,10 @@ dropping:
not_linked:
{
GST_DEBUG_OBJECT (pad, "Dropping event because pad is not linked");
+ GST_OBJECT_UNLOCK (pad);
gst_event_unref (event);
return FALSE;
}
-flushed:
- {
- GST_DEBUG_OBJECT (pad,
- "Not forwarding event since we're flushing and blocking");
- gst_event_unref (event);
- GST_OBJECT_UNLOCK (pad);
- return TRUE;
- }
}
/**