diff --git a/gst/gstevent.h b/gst/gstevent.h index 53210bf05e..e65c30f697 100644 --- a/gst/gstevent.h +++ b/gst/gstevent.h @@ -61,8 +61,9 @@ typedef enum { #define GST_EVENT_TYPE_BOTH \ (GST_EVENT_TYPE_UPSTREAM | GST_EVENT_TYPE_DOWNSTREAM) +#define GST_EVENT_MAX_STICKY 16 #define GST_EVENT_STICKY_SHIFT 8 -#define GST_EVENT_NUM_SHIFT 16 +#define GST_EVENT_NUM_SHIFT (GST_EVENT_STICKY_SHIFT + 4) /** * GST_EVENT_MAKE_TYPE: @@ -78,7 +79,8 @@ typedef enum { #define FLAG(name) GST_EVENT_TYPE_##name -#define GST_EVENT_STICKY_IDX(ev) ((GST_EVENT_TYPE(ev) >> GST_EVENT_STICKY_SHIFT) & 0xff) + +#define GST_EVENT_STICKY_IDX(ev) ((GST_EVENT_TYPE(ev) >> GST_EVENT_STICKY_SHIFT) & 0xf) /** * GstEventType: diff --git a/gst/gstpad.c b/gst/gstpad.c index a0d809150e..96ad674b21 100644 --- a/gst/gstpad.c +++ b/gst/gstpad.c @@ -378,7 +378,7 @@ clear_sticky_events (GstPad * pad) { guint i; - for (i = 0; i < 16; i++) { + for (i = 0; i < GST_EVENT_MAX_STICKY; i++) { GstEvent **eventp = &pad->sticky[i]; gst_event_replace (eventp, NULL); } @@ -679,6 +679,9 @@ gst_pad_set_active (GstPad * pad, gboolean active) GST_DEBUG_OBJECT (pad, "activating pad from none"); ret = (GST_PAD_ACTIVATEFUNC (pad)) (pad); break; + default: + GST_DEBUG_OBJECT (pad, "unknown activation mode!"); + break; } } else { switch (old) { @@ -694,6 +697,9 @@ gst_pad_set_active (GstPad * pad, gboolean active) GST_DEBUG_OBJECT (pad, "deactivating pad from none"); ret = TRUE; break; + default: + GST_DEBUG_OBJECT (pad, "unknown activation mode!"); + break; } } @@ -1687,6 +1693,9 @@ gst_pad_unlink (GstPad * srcpad, GstPad * sinkpad) GST_PAD_PEER (srcpad) = NULL; GST_PAD_PEER (sinkpad) = NULL; + /* clear the events on the sinkpad */ + clear_sticky_events (sinkpad); + GST_OBJECT_UNLOCK (sinkpad); GST_OBJECT_UNLOCK (srcpad); @@ -2004,6 +2013,7 @@ gst_pad_link_full (GstPad * srcpad, GstPad * sinkpad, GstPadLinkCheck flags) { GstPadLinkReturn result; GstElement *parent; + guint i; 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); @@ -2033,6 +2043,15 @@ gst_pad_link_full (GstPad * srcpad, GstPad * sinkpad, GstPadLinkCheck flags) GST_PAD_PEER (srcpad) = sinkpad; GST_PAD_PEER (sinkpad) = srcpad; + /* copy the events */ + for (i = 0; i < GST_EVENT_MAX_STICKY; i++) { + GstEvent **eventp = &sinkpad->sticky[i], *event; + + if ((event = srcpad->sticky[i])) + GST_OBJECT_FLAG_SET (sinkpad, GST_PAD_STICKY_PENDING); + gst_event_replace (eventp, event); + } + GST_OBJECT_UNLOCK (sinkpad); GST_OBJECT_UNLOCK (srcpad); @@ -3440,6 +3459,7 @@ gst_pad_chain_data_unchecked (GstPad * pad, gboolean is_buffer, void *data, GST_PAD_STREAM_LOCK (pad); +again: GST_OBJECT_LOCK (pad); if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad))) goto flushing; @@ -3448,6 +3468,38 @@ gst_pad_chain_data_unchecked (GstPad * pad, gboolean is_buffer, void *data, caps_changed = caps && caps != GST_PAD_CAPS (pad); emit_signal = GST_PAD_DO_BUFFER_SIGNALS (pad) > 0; + + if (G_UNLIKELY (GST_PAD_IS_STICKY_PENDING (pad))) { + GstPadEventFunction eventfunc; + + if (G_LIKELY ((eventfunc = GST_PAD_EVENTFUNC (pad)))) { + GstEvent *events[GST_EVENT_MAX_STICKY]; + GstEvent *event; + guint i; + + /* need to make a copy because when we release the object lock, things + * could just change */ + for (i = 0; i < GST_EVENT_MAX_STICKY; i++) { + if ((event = pad->sticky[i])) + events[i] = gst_event_ref (event); + else + events[i] = NULL; + } + /* clear the flag */ + GST_OBJECT_FLAG_UNSET (pad, GST_PAD_STICKY_PENDING); + GST_OBJECT_UNLOCK (pad); + + /* and push */ + GST_DEBUG_OBJECT (pad, "pushing sticky events"); + for (i = 0; i < GST_EVENT_MAX_STICKY; i++) { + if ((event = events[i])) + eventfunc (pad, event); + } + /* and restart, we released the lock things might have changed */ + goto again; + } + } + GST_OBJECT_UNLOCK (pad); /* see if the signal should be emited, we emit before caps nego as @@ -4463,9 +4515,10 @@ gst_pad_push_event (GstPad * pad, GstEvent * event) /* store the event on the pad, but only on srcpads */ if (GST_PAD_IS_SRC (pad) && GST_EVENT_IS_STICKY (event)) { - GstEvent **eventp = &pad->sticky[GST_EVENT_STICKY_IDX (event)]; - GST_LOG_OBJECT (pad, "storing sticky event %s", - GST_EVENT_TYPE_NAME (event)); + guint idx = GST_EVENT_STICKY_IDX (event); + GstEvent **eventp = &pad->sticky[idx]; + GST_LOG_OBJECT (pad, "storing sticky event %s at index %u", + GST_EVENT_TYPE_NAME (event), idx); gst_event_replace (eventp, event); } diff --git a/gst/gstpad.h b/gst/gstpad.h index 19def6b33e..619ddff801 100644 --- a/gst/gstpad.h +++ b/gst/gstpad.h @@ -509,18 +509,20 @@ typedef enum { * @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_STICKY_PENDING: sticky events should be pushed * @GST_PAD_FLAG_LAST: offset to define more flags * * Pad state flags */ typedef enum { - GST_PAD_BLOCKED = (GST_OBJECT_FLAG_LAST << 0), - 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), + GST_PAD_BLOCKED = (GST_OBJECT_FLAG_LAST << 0), + 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), + GST_PAD_STICKY_PENDING = (GST_OBJECT_FLAG_LAST << 5), /* padding */ - GST_PAD_FLAG_LAST = (GST_OBJECT_FLAG_LAST << 8) + GST_PAD_FLAG_LAST = (GST_OBJECT_FLAG_LAST << 16) } GstPadFlags; /* FIXME: this awful circular dependency need to be resolved properly (see padtemplate.h) */ @@ -614,7 +616,7 @@ struct _GstPad { GstPadCheckGetRangeFunction checkgetrangefunc; GstPadGetRangeFunction getrangefunc; GstPadEventFunction eventfunc; - GstEvent *sticky[16]; + GstEvent *sticky[GST_EVENT_MAX_STICKY]; GstActivateMode mode; @@ -697,6 +699,7 @@ struct _GstPadClass { #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)) +#define GST_PAD_IS_STICKY_PENDING(pad) (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_STICKY_PENDING)) #define GST_PAD_IS_SRC(pad) (GST_PAD_DIRECTION(pad) == GST_PAD_SRC) #define GST_PAD_IS_SINK(pad) (GST_PAD_DIRECTION(pad) == GST_PAD_SINK)