From 4372869e801b1b0a51879e5802a5ad0f170290e7 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Fri, 6 May 2011 11:14:02 +0200 Subject: [PATCH] pad: implement more sticky events Remove the context again, adding an extra layer of refcounting and object creation to manage an array is too complicated and inefficient. Use a simple array again. Also implement event updates when calling gst_pad_chain() and gst_event_send_event() directly. --- gst/Makefile.am | 2 - gst/gst.c | 1 - gst/gstcontext.c | 202 ------------------------------------ gst/gstcontext.h | 148 -------------------------- gst/gstpad.c | 236 +++++++++++++++++++++--------------------- gst/gstpad.h | 9 +- win32/common/libgstreamer.def | 6 -- 7 files changed, 119 insertions(+), 485 deletions(-) delete mode 100644 gst/gstcontext.c delete mode 100644 gst/gstcontext.h diff --git a/gst/Makefile.am b/gst/Makefile.am index 3407e39..e9299f1 100644 --- a/gst/Makefile.am +++ b/gst/Makefile.am @@ -56,7 +56,6 @@ libgstreamer_@GST_MAJORMINOR@_la_SOURCES = \ gstcaps.c \ gstchildproxy.c \ gstclock.c \ - gstcontext.c \ gstdatetime.c \ gstdebugutils.c \ gstelement.c \ @@ -152,7 +151,6 @@ gst_headers = \ gstchildproxy.h \ gstclock.h \ gstcompat.h \ - gstcontext.h \ gstdatetime.h \ gstdebugutils.h \ gstelement.h \ diff --git a/gst/gst.c b/gst/gst.c index 2fbc5a0..c8f431b 100644 --- a/gst/gst.c +++ b/gst/gst.c @@ -756,7 +756,6 @@ init_post (GOptionContext * context, GOptionGroup * group, gpointer data, g_type_class_ref (gst_caps_intersect_mode_get_type ()); gst_structure_get_type (); - gst_context_get_type (); _gst_event_initialize (); _gst_buffer_initialize (); _gst_message_initialize (); diff --git a/gst/gstcontext.c b/gst/gstcontext.c deleted file mode 100644 index d6ca462..0000000 --- a/gst/gstcontext.c +++ /dev/null @@ -1,202 +0,0 @@ -/* GStreamer - * Copyright (C) 2011 Wim Taymans - * - * gstcontext.c: GstContext subsystem - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -/** - * SECTION:gstcontext - * @short_description: Structure containing events describing the context - * for buffers in a pipeline - * @see_also: #GstPad, #GstBuffer - * - * Last reviewed on 2011-05-4 (0.11.0) - */ - - -#include "gst_private.h" - -#include "gstinfo.h" -#include "gstcontext.h" -#include "gstutils.h" -#include "gstquark.h" - -struct _GstContext -{ - GstMiniObject mini_object; - - /*< private > */ - GstEvent *events[GST_EVENT_MAX_STICKY]; - - gpointer _gst_reserved[GST_PADDING]; -}; - -static GType _gst_context_type = 0; - -GType -gst_context_get_type (void) -{ - if (G_UNLIKELY (_gst_context_type == 0)) { - _gst_context_type = gst_mini_object_register ("GstContext"); - } - return _gst_context_type; -} - -static void -_gst_context_free (GstContext * context) -{ - g_return_if_fail (context != NULL); - g_return_if_fail (GST_IS_CONTEXT (context)); - - GST_LOG ("freeing context %p", context); - - gst_context_clear (context); - - g_slice_free1 (GST_MINI_OBJECT_SIZE (context), context); -} - -static void gst_context_init (GstContext * context, gsize size); - -static GstContext * -_gst_context_copy (GstContext * context) -{ - GstContext *copy; - guint i; - - copy = g_slice_new0 (GstContext); - - gst_context_init (copy, sizeof (GstContext)); - - for (i = 0; i < GST_EVENT_MAX_STICKY; i++) - gst_event_replace (©->events[i], context->events[i]); - - return copy; -} - -static void -gst_context_init (GstContext * context, gsize size) -{ - gst_mini_object_init (GST_MINI_OBJECT_CAST (context), _gst_context_type, - size); - - context->mini_object.copy = (GstMiniObjectCopyFunction) _gst_context_copy; - context->mini_object.free = (GstMiniObjectFreeFunction) _gst_context_free; -} - -/** - * gst_context_new: - * - * Create a new #GstContext object that can be used to manage events. - * - * Returns: (transfer full): a new #GstContext - */ -GstContext * -gst_context_new (void) -{ - GstContext *context; - - context = g_slice_new0 (GstContext); - - GST_DEBUG ("creating new context %p", context); - - gst_context_init (context, sizeof (GstContext)); - - return context; -} - -/** - * gst_context_update: - * @context: a #GstContext - * @event: a #GstEvent - * - * Update @context with @event. The context must be writable. - */ -void -gst_context_update (GstContext * context, GstEvent * event) -{ - guint idx; - - g_return_if_fail (context != NULL); - g_return_if_fail (gst_context_is_writable (context)); - - idx = GST_EVENT_STICKY_IDX (event); - - GST_LOG ("storing event %s at index %u", GST_EVENT_TYPE_NAME (event), idx); - - gst_event_replace (&context->events[idx], event); -} - -/** - * gst_context_get: - * @context: a #GstContext - * @type: a #GstEventType - * - * Get the event of @type from @context. - * - * Returns: the last #GstEvent of @type that was updated on @context. This - * function returns NULL when there is no event with the given type. - */ -GstEvent * -gst_context_get (GstContext * context, GstEventType type) -{ - guint idx; - GstEvent *event = NULL; - - g_return_val_if_fail (context != NULL, NULL); - - idx = GST_EVENT_STICKY_IDX_TYPE (type); - - if ((event = context->events[idx])) - gst_event_ref (event); - - return event; -} - -/** - * gst_context_clear: - * @context: a #GstContext - * - * Clear all stored events in @context - */ -void -gst_context_clear (GstContext * context) -{ - guint i; - - for (i = 0; i < GST_EVENT_MAX_STICKY; i++) - gst_event_replace (&context->events[i], NULL); -} - -/** - * gst_context_foreach: - * @context: a #GstContext - * @func: a #GFunc - * @user_data: user data - * - * Call @func with the non NULL event and @user_data. - */ -void -gst_context_foreach (GstContext * context, GFunc func, gpointer user_data) -{ - guint i; - GstEvent *event; - - for (i = 0; i < GST_EVENT_MAX_STICKY; i++) - if ((event = context->events[i])) - func (event, user_data); -} diff --git a/gst/gstcontext.h b/gst/gstcontext.h deleted file mode 100644 index 34e0d49..0000000 --- a/gst/gstcontext.h +++ /dev/null @@ -1,148 +0,0 @@ -/* GStreamer - * Copyright (C) 2011 Wim Taymans - * - * gstcontext.h: Header for GstContext subsystem - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - - -#ifndef __GST_CONTEXT_H__ -#define __GST_CONTEXT_H__ - -#include -#include - -G_BEGIN_DECLS - -#define GST_CONTEXT_TRACE_NAME "GstContext" - -typedef struct _GstContext GstContext; - -#define GST_TYPE_CONTEXT (gst_context_get_type()) -#define GST_IS_CONTEXT(obj) (GST_IS_MINI_OBJECT_TYPE (obj, GST_TYPE_CONTEXT)) -#define GST_CONTEXT(obj) ((GstContext *)(obj)) -#define GST_CONTEXT_CAST(obj) ((GstContext *)(obj)) - - -/** - * gst_context_is_writable: - * @ctx: a #GstContext - * - * Tests if you can safely update @ctx with new events. - */ -#define gst_context_is_writable(ctx) gst_mini_object_is_writable (GST_MINI_OBJECT_CAST (ctx)) - -/** - * gst_context_make_writable: - * @ctx: (transfer full): a #GstContext - * - * Makes a writable context from the given context. If the source context is - * already writable, this will simply return the same context. A copy will - * otherwise be made using gst_context_copy(). - * - * Returns: (transfer full): a writable context which may or may not be the - * same as @ctx - */ -#define gst_context_make_writable(ctx) GST_CONTEXT_CAST (gst_mini_object_make_writable (GST_MINI_OBJECT_CAST (ctx))) - -/** - * gst_context_replace: - * @old_ctx: (inout) (transfer full): pointer to a pointer to a #GstContext - * to be replaced. - * @new_ctx: (allow-none) (transfer none): pointer to a #GstContext that will - * replace the context pointed to by @old_context. - * - * Modifies a pointer to a #GstContext to point to a different #GstContext. The - * modification is done atomically (so this is useful for ensuring thread safety - * in some cases), and the reference counts are updated appropriately (the old - * context is unreffed, the new one is reffed). - * - * Either @new_context or the #GstContext pointed to by @old_context may be NULL. - */ -#define gst_context_replace(old_ctx,new_ctx) \ - gst_mini_object_replace ((GstMiniObject **)(old_ctx), GST_MINI_OBJECT_CAST (new_ctx)) - -GType gst_context_get_type (void); - -/* refcounting */ -/** - * gst_context_ref: - * @context: The context to refcount - * - * Increase the refcount of this context. - * - * Returns: (transfer full): @context (for convenience when doing assignments) - */ -#ifdef _FOOL_GTK_DOC_ -G_INLINE_FUNC GstContext * gst_context_ref (GstContext * context); -#endif - -static inline GstContext * -gst_context_ref (GstContext * context) -{ - return (GstContext *) gst_mini_object_ref (GST_MINI_OBJECT_CAST (context)); -} - -/** - * gst_context_unref: - * @context: (transfer full): the context to refcount - * - * Decrease the refcount of an context, freeing it if the refcount reaches 0. - */ -#ifdef _FOOL_GTK_DOC_ -G_INLINE_FUNC void gst_context_unref (GstContext * context); -#endif - -static inline void -gst_context_unref (GstContext * context) -{ - gst_mini_object_unref (GST_MINI_OBJECT_CAST (context)); -} - -/* copy context */ -/** - * gst_context_copy: - * @context: The context to copy - * - * Copy the context using the context specific copy function. - * - * Returns: (transfer full): the new context - */ -#ifdef _FOOL_GTK_DOC_ -G_INLINE_FUNC GstContext * gst_context_copy (const GstContext * context); -#endif - -static inline GstContext * -gst_context_copy (const GstContext * context) -{ - return GST_CONTEXT_CAST (gst_mini_object_copy (GST_MINI_OBJECT_CONST_CAST (context))); -} - -GstContext * gst_context_new (void); - -/* updating and setting events */ -void gst_context_update (GstContext *context, GstEvent *event); -GstEvent * gst_context_get (GstContext *context, GstEventType type); - -void gst_context_clear (GstContext *context); - -/* foreach */ -void gst_context_foreach (GstContext *context, GFunc func, gpointer user_data); - -G_END_DECLS - -#endif /* __GST_CONTEXT_H__ */ diff --git a/gst/gstpad.c b/gst/gstpad.c index 2a21920..4dcc297 100644 --- a/gst/gstpad.c +++ b/gst/gstpad.c @@ -113,6 +113,8 @@ static GstPadPushCache _pad_cache_invalid = { NULL, }; struct _GstPadPrivate { GstPadPushCache *cache_ptr; + + GstEvent *events[GST_EVENT_MAX_STICKY]; }; static void gst_pad_dispose (GObject * object); @@ -374,6 +376,30 @@ gst_pad_init (GstPad * pad) } static void +clear_events (GstEvent * events[]) +{ + guint i; + + for (i = 0; i < GST_EVENT_MAX_STICKY; i++) + gst_event_replace (&events[i], NULL); +} + +static void +copy_events (GstEvent * events[], GstEvent * dest[]) +{ + guint i; + GstEvent *event; + + for (i = 0; i < GST_EVENT_MAX_STICKY; i++) { + if ((event = events[i])) + dest[i] = gst_event_ref (event); + else + dest[i] = NULL; + } +} + + +static void gst_pad_dispose (GObject * object) { GstPad *pad = GST_PAD_CAST (object); @@ -404,8 +430,7 @@ gst_pad_dispose (GObject * object) pad->block_data = NULL; } - if (GST_PAD_CONTEXT (pad)) - gst_context_replace (&GST_PAD_CONTEXT (pad), NULL); + clear_events (pad->priv->events); G_OBJECT_CLASS (parent_class)->dispose (object); } @@ -618,8 +643,7 @@ post_activate (GstPad * pad, GstActivateMode new_mode) GST_PAD_STREAM_LOCK (pad); GST_DEBUG_OBJECT (pad, "stopped streaming"); GST_OBJECT_LOCK (pad); - if (GST_PAD_CONTEXT (pad)) - gst_context_clear (GST_PAD_CONTEXT (pad)); + clear_events (pad->priv->events); GST_OBJECT_UNLOCK (pad); GST_PAD_STREAM_UNLOCK (pad); break; @@ -2038,8 +2062,10 @@ gst_pad_link_full (GstPad * srcpad, GstPad * sinkpad, GstPadLinkCheck flags) GST_PAD_PEER (srcpad) = sinkpad; GST_PAD_PEER (sinkpad) = srcpad; - /* make sure we push a context to this new peer */ - GST_OBJECT_FLAG_SET (srcpad, GST_PAD_CONTEXT_PENDING); + /* 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 */ + copy_events (srcpad->priv->events, sinkpad->priv->events); + GST_OBJECT_FLAG_SET (sinkpad, GST_PAD_NEED_EVENTS); GST_OBJECT_UNLOCK (sinkpad); GST_OBJECT_UNLOCK (srcpad); @@ -2616,40 +2642,29 @@ could_not_set: } } -typedef struct -{ - GstPadEventFunction eventfunc; - GstPad *pad; - GstFlowReturn ret; -} ContextData; - -static void -context_func (GstEvent * event, ContextData * data) -{ - data->eventfunc (data->pad, gst_event_ref (event)); - /* FIXME, update return value when we can */ -} - static GstFlowReturn -gst_pad_update_context (GstPad * pad, GstContext * context) +gst_pad_update_events (GstPad * pad, GstEvent * events[]) { - ContextData data; + guint i; + GstPadEventFunction eventfunc; + GstEvent *event; - if (G_UNLIKELY ((data.eventfunc = GST_PAD_EVENTFUNC (pad)) == NULL)) + if (G_UNLIKELY ((eventfunc = GST_PAD_EVENTFUNC (pad)) == NULL)) goto no_function; - data.ret = GST_FLOW_OK; - data.pad = pad; - gst_context_foreach (context, (GFunc) context_func, &data); - - return data.ret; + for (i = 0; i < GST_EVENT_MAX_STICKY; i++) { + if ((event = events[i])) + eventfunc (pad, event); + } + return GST_FLOW_OK; /* ERRORS */ no_function: { g_warning ("pad %s:%s has no event handler, file a bug.", GST_DEBUG_PAD_NAME (pad)); - return GST_FLOW_ERROR; + clear_events (events); + return GST_FLOW_NOT_SUPPORTED; } } @@ -3473,12 +3488,13 @@ gst_pad_data_get_caps (gboolean is_buffer, void *data) */ static inline GstFlowReturn gst_pad_chain_data_unchecked (GstPad * pad, gboolean is_buffer, void *data, - GstContext * context, GstPadPushCache * cache) + GstPadPushCache * cache) { GstCaps *caps; - gboolean caps_changed; + gboolean caps_changed, needs_events; GstFlowReturn ret; gboolean emit_signal; + GstEvent *events[GST_EVENT_MAX_STICKY]; GST_PAD_STREAM_LOCK (pad); @@ -3489,10 +3505,12 @@ 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); - if (G_LIKELY (context)) { - GstContext *oldctx = GST_PAD_CONTEXT (pad); - GST_PAD_CONTEXT (pad) = context; - gst_context_unref (oldctx); + needs_events = GST_PAD_NEEDS_EVENTS (pad); + if (G_UNLIKELY (needs_events)) { + /* need to make a copy because when we release the object lock, things + * could just change */ + copy_events (pad->priv->events, events); + GST_OBJECT_FLAG_UNSET (pad, GST_PAD_NEED_EVENTS); } emit_signal = GST_PAD_DO_BUFFER_SIGNALS (pad) > 0; GST_OBJECT_UNLOCK (pad); @@ -3511,9 +3529,9 @@ gst_pad_chain_data_unchecked (GstPad * pad, gboolean is_buffer, void *data, } } - if (G_UNLIKELY (context)) { - GST_DEBUG_OBJECT (pad, "context changed to %p", context); - ret = gst_pad_update_context (pad, context); + if (G_UNLIKELY (needs_events)) { + GST_DEBUG_OBJECT (pad, "need to update all events"); + ret = gst_pad_update_events (pad, events); if (G_UNLIKELY (ret != GST_FLOW_OK)) goto context_error; } @@ -3588,7 +3606,7 @@ chain_groups: buffer = gst_buffer_list_get (list, i); ret = gst_pad_chain_data_unchecked (pad, TRUE, gst_buffer_ref (buffer), - NULL, NULL); + NULL); if (ret != GST_FLOW_OK) break; } @@ -3617,7 +3635,6 @@ dropping: context_error: { gst_pad_data_unref (is_buffer, data); - gst_context_unref (context); GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "context was not accepted"); GST_PAD_STREAM_UNLOCK (pad); return ret; @@ -3677,7 +3694,7 @@ gst_pad_chain (GstPad * pad, GstBuffer * buffer) g_return_val_if_fail (GST_PAD_IS_SINK (pad), GST_FLOW_ERROR); g_return_val_if_fail (GST_IS_BUFFER (buffer), GST_FLOW_ERROR); - return gst_pad_chain_data_unchecked (pad, TRUE, buffer, NULL, NULL); + return gst_pad_chain_data_unchecked (pad, TRUE, buffer, NULL); } /** @@ -3716,7 +3733,7 @@ gst_pad_chain_list (GstPad * pad, GstBufferList * list) g_return_val_if_fail (GST_PAD_IS_SINK (pad), GST_FLOW_ERROR); g_return_val_if_fail (GST_IS_BUFFER_LIST (list), GST_FLOW_ERROR); - return gst_pad_chain_data_unchecked (pad, FALSE, list, NULL, NULL); + return gst_pad_chain_data_unchecked (pad, FALSE, list, NULL); } static GstFlowReturn @@ -3726,7 +3743,6 @@ gst_pad_push_data (GstPad * pad, gboolean is_buffer, void *data, GstPad *peer; GstFlowReturn ret; GstCaps *caps; - GstContext *context = NULL; gboolean caps_changed; GST_OBJECT_LOCK (pad); @@ -3764,13 +3780,6 @@ 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); - /* if we have a context pending, push it along too */ - if (GST_PAD_IS_CONTEXT_PENDING (pad)) { - if (G_LIKELY ((context = GST_PAD_CONTEXT (pad)))) - 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); GST_OBJECT_UNLOCK (pad); @@ -3784,7 +3793,7 @@ gst_pad_push_data (GstPad * pad, gboolean is_buffer, void *data, goto not_negotiated; } - ret = gst_pad_chain_data_unchecked (peer, is_buffer, data, context, cache); + ret = gst_pad_chain_data_unchecked (peer, is_buffer, data, cache); gst_object_unref (peer); @@ -3838,8 +3847,6 @@ not_negotiated: { gst_pad_data_unref (is_buffer, data); gst_object_unref (peer); - if (G_LIKELY (context)) - gst_context_unref (context); GST_CAT_DEBUG_OBJECT (GST_CAT_SCHEDULING, pad, "element pushed data then refused to accept the caps"); return GST_FLOW_NOT_NEGOTIATED; @@ -4207,7 +4214,7 @@ not_connected: static GstFlowReturn gst_pad_get_range_unchecked (GstPad * pad, guint64 offset, guint size, - GstBuffer ** buffer, GstContext ** context) + GstBuffer ** buffer) { GstFlowReturn ret; GstPadGetRangeFunction getrangefunc; @@ -4239,12 +4246,6 @@ gst_pad_get_range_unchecked (GstPad * pad, guint64 offset, guint size, if (!gst_pad_emit_have_data_signal (pad, GST_MINI_OBJECT_CAST (*buffer))) goto dropping; } - - 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)) @@ -4294,8 +4295,6 @@ 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)); @@ -4305,8 +4304,6 @@ 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; @@ -4343,7 +4340,7 @@ gst_pad_get_range (GstPad * pad, guint64 offset, guint size, g_return_val_if_fail (GST_PAD_IS_SRC (pad), GST_FLOW_ERROR); g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR); - return gst_pad_get_range_unchecked (pad, offset, size, buffer, NULL); + return gst_pad_get_range_unchecked (pad, offset, size, buffer); } /** @@ -4384,8 +4381,8 @@ gst_pad_pull_range (GstPad * pad, guint64 offset, guint size, GstFlowReturn ret; gboolean emit_signal; GstCaps *caps; - GstContext *context = NULL; - gboolean caps_changed; + gboolean caps_changed, needs_events; + GstEvent *events[GST_EVENT_MAX_STICKY]; 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); @@ -4406,7 +4403,7 @@ gst_pad_pull_range (GstPad * pad, guint64 offset, guint size, gst_object_ref (peer); GST_OBJECT_UNLOCK (pad); - ret = gst_pad_get_range_unchecked (peer, offset, size, buffer, &context); + ret = gst_pad_get_range_unchecked (peer, offset, size, buffer); gst_object_unref (peer); @@ -4425,18 +4422,18 @@ gst_pad_pull_range (GstPad * pad, guint64 offset, guint size, caps = GST_BUFFER_CAPS (*buffer); caps_changed = caps && caps != GST_PAD_CAPS (pad); - if (G_UNLIKELY (context)) { - GstContext *oldctx = GST_PAD_CONTEXT (pad); - GST_PAD_CONTEXT (pad) = context; - gst_context_unref (oldctx); + needs_events = GST_PAD_NEEDS_EVENTS (pad); + if (G_UNLIKELY (needs_events)) { + copy_events (pad->priv->events, events); + GST_OBJECT_FLAG_UNSET (pad, GST_PAD_NEED_EVENTS); } GST_OBJECT_UNLOCK (pad); - if (G_UNLIKELY (context)) { - GST_DEBUG_OBJECT (pad, "context changed to %p", context); - ret = gst_pad_update_context (pad, context); + if (G_UNLIKELY (needs_events)) { + GST_DEBUG_OBJECT (pad, "we need to update the events"); + ret = gst_pad_update_events (pad, events); if (G_UNLIKELY (ret != GST_FLOW_OK)) - goto context_error; + goto events_error; } /* we got a new datatype on the pad, see if it can handle it */ @@ -4462,8 +4459,6 @@ pull_range_failed: GST_CAT_LEVEL_LOG (GST_CAT_SCHEDULING, (ret >= GST_FLOW_UNEXPECTED) ? GST_LEVEL_INFO : GST_LEVEL_WARNING, pad, "pullrange failed, flow: %s", gst_flow_get_name (ret)); - if (context) - gst_context_unref (context); return ret; } dropping: @@ -4472,16 +4467,14 @@ dropping: "Dropping data after FALSE probe return"); gst_buffer_unref (*buffer); *buffer = NULL; - if (context) - gst_context_unref (context); return GST_FLOW_UNEXPECTED; } -context_error: +events_error: { gst_buffer_unref (*buffer); *buffer = NULL; GST_CAT_WARNING_OBJECT (GST_CAT_SCHEDULING, pad, - "pullrange returned context that was not accepted"); + "pullrange returned events that were not accepted"); return ret; } not_negotiated: @@ -4515,7 +4508,6 @@ gst_pad_push_event (GstPad * pad, GstEvent * event) { GstPad *peerpad; gboolean result; - GstContext *context = NULL; g_return_val_if_fail (GST_IS_PAD (pad), FALSE); g_return_val_if_fail (event != NULL, FALSE); @@ -4575,54 +4567,31 @@ 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)) { - if (context) - context = gst_context_make_writable (GST_PAD_CONTEXT (pad)); - else - context = gst_context_new (); + guint idx; - GST_LOG_OBJECT (pad, "update context %p", context); + idx = GST_EVENT_STICKY_IDX (event); + GST_LOG_OBJECT (pad, "storing sticky event %s at index %u", + GST_EVENT_TYPE_NAME (event), idx); - gst_context_update (context, event); - GST_PAD_CONTEXT (pad) = context; + gst_event_replace (&pad->priv->events[idx], event); } peerpad = GST_PAD_PEER (pad); if (peerpad == NULL) goto not_linked; - if (context) { - /* set the context on the peerpad too */ - GST_LOG_OBJECT (pad, "pushing context %p to peerpad", context); - - GST_OBJECT_LOCK (peerpad); - gst_context_replace (&GST_PAD_CONTEXT (peerpad), context); - GST_OBJECT_UNLOCK (peerpad); - } - gst_object_ref (peerpad); + GST_OBJECT_UNLOCK (pad); - if (context && GST_PAD_IS_CONTEXT_PENDING (pad)) { - GST_OBJECT_FLAG_UNSET (pad, GST_PAD_CONTEXT_PENDING); - GST_OBJECT_UNLOCK (pad); - - GST_LOG_OBJECT (pad, "do full context update to peerpad %" GST_PTR_FORMAT, - peerpad); + GST_LOG_OBJECT (pad, "sending event %s to peerpad %" GST_PTR_FORMAT, + GST_EVENT_TYPE_NAME (event), peerpad); - /* we need to send all events in the context to the peer, this will include - * the newly added event to the context */ - gst_pad_update_context (peerpad, context); - result = TRUE; - } else { - GST_LOG_OBJECT (pad, "sending event %s to peerpad %" GST_PTR_FORMAT, - GST_EVENT_TYPE_NAME (event), peerpad); - GST_OBJECT_UNLOCK (pad); + result = gst_pad_send_event (peerpad, event); - result = gst_pad_send_event (peerpad, event); + /* Note: we gave away ownership of the event at this point */ + GST_LOG_OBJECT (pad, "sent event to peerpad %" GST_PTR_FORMAT ", result %d", + peerpad, result); - /* Note: we gave away ownership of the event at this point */ - GST_LOG_OBJECT (pad, "sent event to peerpad %" GST_PTR_FORMAT ", result %d", - peerpad, result); - } gst_object_unref (peerpad); return result; @@ -4684,7 +4653,8 @@ gst_pad_send_event (GstPad * pad, GstEvent * event) { gboolean result = FALSE; GstPadEventFunction eventfunc; - gboolean serialized, need_unlock = FALSE; + gboolean serialized, need_unlock = FALSE, needs_events; + GstEvent *events[GST_EVENT_MAX_STICKY]; g_return_val_if_fail (GST_IS_PAD (pad), FALSE); g_return_val_if_fail (event != NULL, FALSE); @@ -4759,12 +4729,38 @@ gst_pad_send_event (GstPad * pad, GstEvent * event) } break; } + + /* store the event on the pad, but only on srcpads */ + if (GST_PAD_IS_SINK (pad) && GST_EVENT_IS_STICKY (event)) { + guint idx; + + idx = GST_EVENT_STICKY_IDX (event); + GST_LOG_OBJECT (pad, "storing sticky event %s at index %u", + GST_EVENT_TYPE_NAME (event), idx); + + gst_event_replace (&pad->priv->events[idx], event); + } + if (G_UNLIKELY ((eventfunc = GST_PAD_EVENTFUNC (pad)) == NULL)) goto no_function; + needs_events = GST_PAD_NEEDS_EVENTS (pad); + if (G_UNLIKELY (needs_events)) { + /* need to make a copy because when we release the object lock, things + * could just change */ + GST_DEBUG_OBJECT (pad, "need to update all events"); + copy_events (pad->priv->events, events); + GST_OBJECT_FLAG_UNSET (pad, GST_PAD_NEED_EVENTS); + } GST_OBJECT_UNLOCK (pad); - result = eventfunc (pad, event); + if (G_UNLIKELY (needs_events)) { + GST_DEBUG_OBJECT (pad, "updating all events"); + gst_pad_update_events (pad, events); + result = TRUE; + } else { + result = eventfunc (pad, event); + } if (need_unlock) GST_PAD_STREAM_UNLOCK (pad); diff --git a/gst/gstpad.h b/gst/gstpad.h index ea5c95f..14646ce 100644 --- a/gst/gstpad.h +++ b/gst/gstpad.h @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include @@ -514,7 +513,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_NEED_EVENTS: the pad has pending events * @GST_PAD_FLAG_LAST: offset to define more flags * * Pad state flags @@ -526,7 +525,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), + GST_PAD_NEED_EVENTS = (GST_OBJECT_FLAG_LAST << 6), /* padding */ GST_PAD_FLAG_LAST = (GST_OBJECT_FLAG_LAST << 16) } GstPadFlags; @@ -622,7 +621,6 @@ struct _GstPad { GstPadCheckGetRangeFunction checkgetrangefunc; GstPadGetRangeFunction getrangefunc; GstPadEventFunction eventfunc; - GstContext *context; GstActivateMode mode; @@ -691,7 +689,6 @@ struct _GstPadClass { * The caps for this pad. */ #define GST_PAD_CAPS(pad) (GST_PAD_CAST(pad)->caps) -#define GST_PAD_CONTEXT(pad) (GST_PAD_CAST(pad)->context) #define GST_PAD_GETCAPSFUNC(pad) (GST_PAD_CAST(pad)->getcapsfunc) #define GST_PAD_SETCAPSFUNC(pad) (GST_PAD_CAST(pad)->setcapsfunc) #define GST_PAD_ACCEPTCAPSFUNC(pad) (GST_PAD_CAST(pad)->acceptcapsfunc) @@ -707,7 +704,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_NEEDS_EVENTS(pad) (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_NEED_EVENTS)) #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) diff --git a/win32/common/libgstreamer.def b/win32/common/libgstreamer.def index 7be9c12..c351440 100644 --- a/win32/common/libgstreamer.def +++ b/win32/common/libgstreamer.def @@ -237,12 +237,6 @@ EXPORTS gst_clock_single_shot_id_reinit gst_clock_type_get_type gst_clock_unadjust_unlocked - gst_context_clear - gst_context_foreach - gst_context_get - gst_context_get_type - gst_context_new - gst_context_update gst_core_error_get_type gst_core_error_quark gst_date_get_type -- 2.7.4