From dfef1d027d7cdc7d08959e815f6444ee789fad5f Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Thu, 5 May 2011 16:32:11 +0200 Subject: [PATCH] pad: improve passing around the context Improve passing around the context, only send the context to the peer element when the CONTEXT_PENDING flag is set. --- gst/gstpad.c | 76 +++++++++++++++++++++++++++++++++------------------- gst/gstpad.h | 3 +++ 2 files changed, 51 insertions(+), 28 deletions(-) diff --git a/gst/gstpad.c b/gst/gstpad.c index 34503a9721..9879561001 100644 --- a/gst/gstpad.c +++ b/gst/gstpad.c @@ -2628,7 +2628,7 @@ context_func (GstEvent * event, ContextData * data) } static GstFlowReturn -gst_pad_update_context (GstPad * pad, GstContext * context) +gst_pad_update_context (GstPad * pad, GstContext * old, GstContext * context) { ContextData data; @@ -2639,9 +2639,6 @@ gst_pad_update_context (GstPad * pad, GstContext * context) data.pad = pad; gst_context_foreach (context, (GFunc) context_func, &data); - /* set context on pad if all succeeds */ - gst_context_replace (&GST_PAD_CONTEXT (pad), context); - return data.ret; /* ERRORS */ @@ -3474,9 +3471,10 @@ gst_pad_chain_data_unchecked (GstPad * pad, gboolean is_buffer, void *data, GstContext * context, GstPadPushCache * cache) { GstCaps *caps; - gboolean caps_changed, context_changed; + gboolean caps_changed; GstFlowReturn ret; gboolean emit_signal; + GstContext *oldctx = NULL; GST_PAD_STREAM_LOCK (pad); @@ -3487,10 +3485,16 @@ gst_pad_chain_data_unchecked (GstPad * pad, gboolean is_buffer, void *data, caps = gst_pad_data_get_caps (is_buffer, data); caps_changed = caps && caps != GST_PAD_CAPS (pad); - context_changed = context && context != GST_PAD_CONTEXT (pad); - + if (G_LIKELY (context)) { + oldctx = GST_PAD_CONTEXT (pad); + if (G_UNLIKELY (context != oldctx)) { + GST_PAD_CONTEXT (pad) = context; + } else { + gst_context_unref (context); + context = NULL; + } + } emit_signal = GST_PAD_DO_BUFFER_SIGNALS (pad) > 0; - GST_OBJECT_UNLOCK (pad); /* see if the signal should be emited, we emit before caps nego as @@ -3507,16 +3511,15 @@ gst_pad_chain_data_unchecked (GstPad * pad, gboolean is_buffer, void *data, } } - if (G_UNLIKELY (context_changed)) { + if (G_UNLIKELY (context)) { GST_DEBUG_OBJECT (pad, "context changed to %p", context); - ret = gst_pad_update_context (pad, context); + ret = gst_pad_update_context (pad, oldctx, context); + if (oldctx) + gst_context_unref (oldctx); if (G_UNLIKELY (ret != GST_FLOW_OK)) goto context_error; } - if (context) - gst_context_unref (context); - if (G_UNLIKELY (caps_changed)) { GST_DEBUG_OBJECT (pad, "caps changed to %p %" GST_PTR_FORMAT, caps, caps); if (G_UNLIKELY (!gst_pad_configure_sink (pad, caps))) @@ -3725,7 +3728,7 @@ gst_pad_push_data (GstPad * pad, gboolean is_buffer, void *data, GstPad *peer; GstFlowReturn ret; GstCaps *caps; - GstContext *context; + GstContext *context = NULL; gboolean caps_changed; GST_OBJECT_LOCK (pad); @@ -3763,9 +3766,13 @@ gst_pad_push_data (GstPad * pad, gboolean is_buffer, void *data, caps = gst_pad_data_get_caps (is_buffer, data); caps_changed = caps && caps != GST_PAD_CAPS (pad); - context = GST_PAD_CONTEXT (pad); - if (G_LIKELY (context)) - gst_context_ref (context); + /* if we have a context pending, push it along too */ + if (GST_PAD_IS_CONTEXT_PENDING (pad)) { + context = GST_PAD_CONTEXT (pad); + if (G_LIKELY (context)) + gst_context_ref (context); + GST_OBJECT_FLAG_UNSET (pad, GST_PAD_CONTEXT_PENDING); + } /* take ref to peer pad before releasing the lock */ gst_object_ref (peer); @@ -4236,8 +4243,11 @@ gst_pad_get_range_unchecked (GstPad * pad, guint64 offset, guint size, goto dropping; } - if (context) - gst_context_replace (context, GST_PAD_CONTEXT (pad)); + if (GST_PAD_IS_CONTEXT_PENDING (pad)) { + if (context) + gst_context_replace (context, GST_PAD_CONTEXT (pad)); + GST_OBJECT_FLAG_UNSET (pad, GST_PAD_CONTEXT_PENDING); + } GST_PAD_STREAM_UNLOCK (pad); if (G_UNLIKELY (ret != GST_FLOW_OK)) @@ -4287,6 +4297,8 @@ dropping: get_range_failed: { *buffer = NULL; + if (context && *context) + gst_context_unref (*context); GST_CAT_LEVEL_LOG (GST_CAT_SCHEDULING, (ret >= GST_FLOW_UNEXPECTED) ? GST_LEVEL_INFO : GST_LEVEL_WARNING, pad, "getrange failed, flow: %s", gst_flow_get_name (ret)); @@ -4296,6 +4308,8 @@ not_negotiated: { gst_buffer_unref (*buffer); *buffer = NULL; + if (context && *context) + gst_context_unref (*context); GST_CAT_WARNING_OBJECT (GST_CAT_SCHEDULING, pad, "getrange returned buffer of unaccaptable caps"); return GST_FLOW_NOT_NEGOTIATED; @@ -4373,8 +4387,8 @@ gst_pad_pull_range (GstPad * pad, guint64 offset, guint size, GstFlowReturn ret; gboolean emit_signal; GstCaps *caps; - GstContext *context = NULL; - gboolean caps_changed, context_changed; + GstContext *context = NULL, *oldctx = NULL; + gboolean caps_changed; g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR); g_return_val_if_fail (GST_PAD_IS_SINK (pad), GST_FLOW_ERROR); @@ -4414,15 +4428,22 @@ gst_pad_pull_range (GstPad * pad, guint64 offset, guint size, caps = GST_BUFFER_CAPS (*buffer); caps_changed = caps && caps != GST_PAD_CAPS (pad); - context_changed = context && context != GST_PAD_CONTEXT (pad); + if (G_UNLIKELY (context)) { + oldctx = GST_PAD_CONTEXT (pad); + if (G_UNLIKELY (context != oldctx)) { + GST_PAD_CONTEXT (pad) = context; + } else { + gst_context_unref (context); + context = NULL; + } + } GST_OBJECT_UNLOCK (pad); - if (context) - gst_context_unref (context); - - if (G_UNLIKELY (context_changed)) { + if (G_UNLIKELY (context)) { GST_DEBUG_OBJECT (pad, "context changed to %p", context); - ret = gst_pad_update_context (pad, context); + ret = gst_pad_update_context (pad, oldctx, context); + if (oldctx) + gst_context_unref (oldctx); if (G_UNLIKELY (ret != GST_FLOW_OK)) goto context_error; } @@ -4568,7 +4589,6 @@ gst_pad_push_event (GstPad * pad, GstEvent * event) GST_PAD_CONTEXT (pad) = gst_context_new (); gst_context_update (GST_PAD_CONTEXT (pad), event); - _priv_gst_pad_invalidate_cache (pad); } peerpad = GST_PAD_PEER (pad); diff --git a/gst/gstpad.h b/gst/gstpad.h index 018fa8cf92..ea5c95f5aa 100644 --- a/gst/gstpad.h +++ b/gst/gstpad.h @@ -514,6 +514,7 @@ typedef enum { * The flag has to be unset manually after * reconfiguration happened. * Since: 0.10.34. + * @GST_PAD_CONTEXT_PENDING: the pad has a pending context * @GST_PAD_FLAG_LAST: offset to define more flags * * Pad state flags @@ -525,6 +526,7 @@ typedef enum { GST_PAD_IN_SETCAPS = (GST_OBJECT_FLAG_LAST << 3), GST_PAD_BLOCKING = (GST_OBJECT_FLAG_LAST << 4), GST_PAD_NEED_RECONFIGURE = (GST_OBJECT_FLAG_LAST << 5), + GST_PAD_CONTEXT_PENDING = (GST_OBJECT_FLAG_LAST << 6), /* padding */ GST_PAD_FLAG_LAST = (GST_OBJECT_FLAG_LAST << 16) } GstPadFlags; @@ -705,6 +707,7 @@ struct _GstPadClass { #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_NEEDS_RECONFIGURE(pad) (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_NEED_RECONFIGURE)) +#define GST_PAD_IS_CONTEXT_PENDING(pad) (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_CONTEXT_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)