}
static GstFlowReturn
-gst_pad_update_context (GstPad * pad, GstContext * context)
+gst_pad_update_context (GstPad * pad, GstContext * old, GstContext * context)
{
ContextData data;
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 */
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);
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
}
}
- 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)))
GstPad *peer;
GstFlowReturn ret;
GstCaps *caps;
- GstContext *context;
+ GstContext *context = NULL;
gboolean caps_changed;
GST_OBJECT_LOCK (pad);
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);
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))
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));
{
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;
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);
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;
}
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);
* 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
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;
#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)