From 8cc12b05fc6fca30357830f84019ac2bde04e68c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Mon, 4 Jun 2012 11:46:42 +0200 Subject: [PATCH] pad: Don't accept any buffers or events after EOS --- gst/gstpad.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++- gst/gstpad.h | 20 +++++++++++------- 2 files changed, 71 insertions(+), 9 deletions(-) diff --git a/gst/gstpad.c b/gst/gstpad.c index a9dc72250c..058058723c 100644 --- a/gst/gstpad.c +++ b/gst/gstpad.c @@ -3187,7 +3187,7 @@ push_sticky (GstPad * pad, PadEvent * ev, gpointer user_data) /* not linked is not a problem, we are sticky so the event will be * sent later but only for non-EOS events */ GST_DEBUG_OBJECT (pad, "pad was not linked"); - if (GST_EVENT_TYPE (ev) != GST_FLOW_EOS) + if (GST_EVENT_TYPE (ev) != GST_EVENT_EOS) data->ret = GST_FLOW_OK; /* fallthrough */ default: @@ -3504,6 +3504,9 @@ gst_pad_chain_data_unchecked (GstPad * pad, GstPadProbeType type, void *data) if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad))) goto flushing; + if (G_UNLIKELY (GST_PAD_IS_EOS (pad))) + goto eos; + if (G_UNLIKELY (GST_PAD_MODE (pad) != GST_PAD_MODE_PUSH)) goto wrong_mode; @@ -3565,6 +3568,14 @@ flushing: gst_mini_object_unref (GST_MINI_OBJECT_CAST (data)); return GST_FLOW_FLUSHING; } +eos: + { + GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "chaining, but pad was EOS"); + GST_OBJECT_UNLOCK (pad); + GST_PAD_STREAM_UNLOCK (pad); + gst_mini_object_unref (GST_MINI_OBJECT_CAST (data)); + return GST_FLOW_EOS; + } wrong_mode: { g_critical ("chain on pad %s:%s but it was not in push mode", @@ -3713,6 +3724,9 @@ gst_pad_push_data (GstPad * pad, GstPadProbeType type, void *data) if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad))) goto flushing; + if (G_UNLIKELY (GST_PAD_IS_EOS (pad))) + goto eos; + if (G_UNLIKELY (GST_PAD_MODE (pad) != GST_PAD_MODE_PUSH)) goto wrong_mode; @@ -3758,6 +3772,13 @@ flushing: gst_mini_object_unref (GST_MINI_OBJECT_CAST (data)); return GST_FLOW_FLUSHING; } +eos: + { + GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "pushing, but pad was EOS"); + GST_OBJECT_UNLOCK (pad); + gst_mini_object_unref (GST_MINI_OBJECT_CAST (data)); + return GST_FLOW_EOS; + } wrong_mode: { g_critical ("pushing on pad %s:%s but it was not activated in push mode", @@ -4320,6 +4341,7 @@ gst_pad_push_event_unchecked (GstPad * pad, GstEvent * event, /* Remove sticky EOS events */ GST_LOG_OBJECT (pad, "Removing pending EOS events"); remove_event_by_type (pad, GST_EVENT_EOS); + GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_EOS); type |= GST_PAD_PROBE_TYPE_EVENT_FLUSH; break; @@ -4328,6 +4350,11 @@ gst_pad_push_event_unchecked (GstPad * pad, GstEvent * event, if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad))) goto flushed; + /* No need to check for EOS here as either the caller (gst_pad_push_event()) + * checked already or this is called as part of pushing sticky events, + * in which case we still want to forward the EOS event downstream. + */ + switch (GST_EVENT_TYPE (event)) { case GST_EVENT_SEGMENT: /* pass the adjusted segment event on. We need to do this even if @@ -4465,12 +4492,17 @@ gst_pad_push_event (GstPad * pad, GstEvent * event) if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad))) goto flushed; + if (G_UNLIKELY (GST_PAD_IS_EOS (pad))) + goto eos; + /* srcpad sticky events are store immediately, the received flag is set * to FALSE and will be set to TRUE when we can successfully push the * event to the peer pad */ if (gst_pad_store_sticky_event (pad, event, TRUE)) { GST_DEBUG_OBJECT (pad, "event %s updated", GST_EVENT_TYPE_NAME (event)); } + if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) + GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_EOS); } if (GST_PAD_IS_SRC (pad) && (serialized || sticky)) { /* all serialized or sticky events on the srcpad trigger push of @@ -4515,6 +4547,13 @@ flushed: gst_event_unref (event); return FALSE; } +eos: + { + GST_DEBUG_OBJECT (pad, "We're EOS"); + GST_OBJECT_UNLOCK (pad); + gst_event_unref (event); + return FALSE; + } } /* Check if we can call the event function with the given event */ @@ -4584,6 +4623,7 @@ gst_pad_send_event_unchecked (GstPad * pad, GstEvent * event, /* Remove pending EOS events */ GST_LOG_OBJECT (pad, "Removing pending EOS events"); remove_event_by_type (pad, GST_EVENT_EOS); + GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_EOS); GST_OBJECT_UNLOCK (pad); /* grab stream lock */ @@ -4603,6 +4643,9 @@ gst_pad_send_event_unchecked (GstPad * pad, GstEvent * event, if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad))) goto flushing; + if (G_UNLIKELY (GST_PAD_IS_EOS (pad))) + goto eos; + if (serialized) { /* lock order: STREAM_LOCK, LOCK, recheck flushing. */ GST_OBJECT_UNLOCK (pad); @@ -4611,6 +4654,9 @@ gst_pad_send_event_unchecked (GstPad * pad, GstEvent * event, GST_OBJECT_LOCK (pad); if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad))) goto flushing; + + if (G_UNLIKELY (GST_PAD_IS_EOS (pad))) + goto eos; } switch (GST_EVENT_TYPE (event)) { @@ -4665,6 +4711,8 @@ gst_pad_send_event_unchecked (GstPad * pad, GstEvent * event, /* after the event function accepted the event, we can store the sticky * event on the pad */ gst_pad_store_sticky_event (pad, event, FALSE); + if (event_type == GST_EVENT_EOS) + GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_EOS); } gst_event_unref (event); } @@ -4685,6 +4733,16 @@ flushing: gst_event_unref (event); return GST_FLOW_FLUSHING; } +eos: + { + GST_OBJECT_UNLOCK (pad); + if (need_unlock) + GST_PAD_STREAM_UNLOCK (pad); + GST_CAT_INFO_OBJECT (GST_CAT_EVENT, pad, + "Received event on EOS pad. Discarding"); + gst_event_unref (event); + return GST_FLOW_EOS; + } probe_stopped: { GST_OBJECT_UNLOCK (pad); diff --git a/gst/gstpad.h b/gst/gstpad.h index df66794468..4e93f07ed1 100644 --- a/gst/gstpad.h +++ b/gst/gstpad.h @@ -590,7 +590,8 @@ typedef gboolean (*GstPadStickyEventsForeachFunction) (GstPad *pad, GstEvent ** /** * GstPadFlags: * @GST_PAD_FLAG_BLOCKED: is dataflow on a pad blocked - * @GST_PAD_FLAG_FLUSHING: is pad refusing buffers + * @GST_PAD_FLAG_FLUSHING: is pad flushing + * @GST_PAD_FLAG_EOS: is pad in EOS state * @GST_PAD_FLAG_BLOCKING: is pad currently blocking on a buffer or event * @GST_PAD_FLAG_NEED_PARENT: ensure that there is a parent object before calling * into the pad callbacks. @@ -614,13 +615,14 @@ typedef gboolean (*GstPadStickyEventsForeachFunction) (GstPad *pad, GstEvent ** typedef enum { GST_PAD_FLAG_BLOCKED = (GST_OBJECT_FLAG_LAST << 0), GST_PAD_FLAG_FLUSHING = (GST_OBJECT_FLAG_LAST << 1), - GST_PAD_FLAG_BLOCKING = (GST_OBJECT_FLAG_LAST << 2), - GST_PAD_FLAG_NEED_PARENT = (GST_OBJECT_FLAG_LAST << 3), - GST_PAD_FLAG_NEED_RECONFIGURE = (GST_OBJECT_FLAG_LAST << 4), - GST_PAD_FLAG_PENDING_EVENTS = (GST_OBJECT_FLAG_LAST << 5), - GST_PAD_FLAG_FIXED_CAPS = (GST_OBJECT_FLAG_LAST << 6), - GST_PAD_FLAG_PROXY_CAPS = (GST_OBJECT_FLAG_LAST << 7), - GST_PAD_FLAG_PROXY_ALLOCATION = (GST_OBJECT_FLAG_LAST << 8), + GST_PAD_FLAG_EOS = (GST_OBJECT_FLAG_LAST << 2), + GST_PAD_FLAG_BLOCKING = (GST_OBJECT_FLAG_LAST << 3), + GST_PAD_FLAG_NEED_PARENT = (GST_OBJECT_FLAG_LAST << 4), + GST_PAD_FLAG_NEED_RECONFIGURE = (GST_OBJECT_FLAG_LAST << 5), + GST_PAD_FLAG_PENDING_EVENTS = (GST_OBJECT_FLAG_LAST << 6), + GST_PAD_FLAG_FIXED_CAPS = (GST_OBJECT_FLAG_LAST << 7), + GST_PAD_FLAG_PROXY_CAPS = (GST_OBJECT_FLAG_LAST << 8), + GST_PAD_FLAG_PROXY_ALLOCATION = (GST_OBJECT_FLAG_LAST << 9), /* padding */ GST_PAD_FLAG_LAST = (GST_OBJECT_FLAG_LAST << 16) } GstPadFlags; @@ -755,6 +757,8 @@ struct _GstPadClass { #define GST_PAD_SET_FLUSHING(pad) (GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_FLUSHING)) #define GST_PAD_UNSET_FLUSHING(pad) (GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_FLUSHING)) +#define GST_PAD_IS_EOS(pad) (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_EOS)) + #define GST_PAD_NEEDS_RECONFIGURE(pad) (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_NEED_RECONFIGURE)) #define GST_PAD_HAS_PENDING_EVENTS(pad) (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_PENDING_EVENTS)) #define GST_PAD_IS_FIXED_CAPS(pad) (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_FIXED_CAPS))