<xi:include href="xml/gstchildproxy.xml" />
<xi:include href="xml/gstclock.xml" />
<xi:include href="xml/gstconfig.xml" />
+ <xi:include href="xml/gstcontext.xml" />
<xi:include href="xml/gstcontrolbinding.xml" />
<xi:include href="xml/gstcontrolsource.xml" />
<xi:include href="xml/gstdatetime.xml" />
GST_USING_PRINTF_EXTENSION
</SECTION>
+<SECTION>
+<FILE>gstcontext</FILE>
+<TITLE>GstContext</TITLE>
+GstContext
+gst_context_new
+gst_context_ref
+gst_context_unref
+gst_context_copy
+gst_context_get_structure
+gst_context_make_writable
+gst_context_is_writable
+gst_context_replace
+<SUBSECTION Standard>
+GST_CONTEXT
+GST_CONTEXT_CAST
+GST_IS_CONTEXT
+GST_TYPE_CONTEXT
+<SUBSECTION Private>
+gst_context_get_type
+</SECTION>
<SECTION>
<FILE>gstcontrolbinding</FILE>
gst_element_get_start_time
gst_element_set_bus
gst_element_get_bus
+gst_element_set_context
gst_element_get_factory
gst_element_set_name
gst_element_get_name
gst_event_new_segment_done
gst_event_parse_segment_done
+
+gst_event_new_context
+gst_event_parse_context
<SUBSECTION Standard>
GstEventClass
GST_EVENT
gst_message_new_progress
gst_message_parse_progress
+gst_message_new_need_context
+gst_message_add_context_type
+gst_message_get_n_context_types
+gst_message_parse_nth_context_type
+gst_message_new_have_context
+gst_message_parse_have_context
+
<SUBSECTION Standard>
GstMessageClass
GST_MESSAGE
gst_query_has_scheduling_mode_with_flags
gst_query_new_drain
+
+gst_query_new_context
+gst_query_set_context
+gst_query_parse_context
+gst_query_add_context_type
+gst_query_get_n_context_types
+gst_query_parse_nth_context_type
<SUBSECTION Standard>
GstQueryClass
GST_QUERY
gstcaps.c \
gstchildproxy.c \
gstclock.c \
+ gstcontext.c \
gstcontrolbinding.c \
gstcontrolsource.c \
gstdatetime.c \
gstchildproxy.h \
gstclock.h \
gstcompat.h \
+ gstcontext.h \
gstcontrolbinding.h \
gstcontrolsource.h \
gstdatetime.h \
_priv_gst_buffer_list_initialize ();
_priv_gst_sample_initialize ();
_priv_gst_value_initialize ();
+ _priv_gst_context_initialize ();
g_type_class_ref (gst_param_spec_fraction_get_type ());
_priv_gst_tag_initialize ();
G_GNUC_INTERNAL void _priv_gst_tag_initialize (void);
G_GNUC_INTERNAL void _priv_gst_value_initialize (void);
G_GNUC_INTERNAL void _priv_gst_debug_init (void);
+G_GNUC_INTERNAL void _priv_gst_context_initialize (void);
/* Private registry functions */
G_GNUC_INTERNAL
GST_EXPORT GstDebugCategory *GST_CAT_QOS;
GST_EXPORT GstDebugCategory *GST_CAT_META;
GST_EXPORT GstDebugCategory *GST_CAT_LOCKING;
+GST_EXPORT GstDebugCategory *GST_CAT_CONTEXT;
/* Categories that should be completely private to
* libgstreamer should be done like this: */
#define GST_CAT_POLL NULL
#define GST_CAT_META NULL
#define GST_CAT_LOCKING NULL
+#define GST_CAT_CONTEXT NULL
#endif
guint32 structure_cookie;
+ GstContext *context;
+
#if 0
/* cached index */
GstIndex *index;
static GstBusSyncReply bin_bus_handler (GstBus * bus,
GstMessage * message, GstBin * bin);
static gboolean gst_bin_query (GstElement * element, GstQuery * query);
+static void gst_bin_set_context (GstElement * element, GstContext * context);
static gboolean gst_bin_do_latency_func (GstBin * bin);
gstelement_class->send_event = GST_DEBUG_FUNCPTR (gst_bin_send_event);
gstelement_class->query = GST_DEBUG_FUNCPTR (gst_bin_query);
+ gstelement_class->set_context = GST_DEBUG_FUNCPTR (gst_bin_set_context);
klass->add_element = GST_DEBUG_FUNCPTR (gst_bin_add_func);
klass->remove_element = GST_DEBUG_FUNCPTR (gst_bin_remove_func);
* a new clock will be selected */
gst_element_set_clock (element, GST_ELEMENT_CLOCK (bin));
+ if (bin->priv->context)
+ gst_element_set_context (element, bin->priv->context);
+
#if 0
/* set the cached index on the children */
if (bin->priv->index)
return res;
}
+static void
+set_context (const GValue * item, gpointer user_data)
+{
+ GstElement *element = g_value_get_object (item);
+
+ gst_element_set_context (element, user_data);
+}
+
+static void
+gst_bin_set_context (GstElement * element, GstContext * context)
+{
+ GstBin *bin;
+ GstIterator *children;
+
+ g_return_if_fail (GST_IS_BIN (element));
+
+ bin = GST_BIN (element);
+
+ children = gst_bin_iterate_elements (bin);
+ while (gst_iterator_foreach (children, set_context,
+ context) == GST_ITERATOR_RESYNC);
+ gst_iterator_free (children);
+ GST_OBJECT_LOCK (bin);
+ gst_context_replace (&bin->priv->context, context);
+ GST_OBJECT_UNLOCK (bin);
+}
+
static gint
compare_name (const GValue * velement, const gchar * name)
{
--- /dev/null
+/* GStreamer
+ * Copyright (C) 2013 Collabora Ltd.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ *
+ * 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., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * SECTION:gstcontext
+ * @short_description: Lightweight objects to represent element contexts
+ * @see_also: #GstMiniObject, #GstElement
+ *
+ * #GstContext is a container object used to store contexts like a device
+ * context, a display server connection and similar concepts that should
+ * be shared between multiple elements.
+ *
+ * Applications can set a context on a complete pipeline by using
+ * gst_element_set_context(), which will then be propagated to all
+ * child elements. Elements can handle these in GstElement::set_context()
+ * and merge them with the context information they already have.
+ *
+ * When an element needs a context it will do the following actions in this
+ * order until one step succeeds:
+ * 1) Check if the element already has a context
+ * 2) Query downstream with GST_QUERY_CONTEXT for the context
+ * 3) Post a GST_MESSAGE_NEED_CONTEXT message on the bus with the required
+ * context types and afterwards check if a usable context was set now
+ * 4) Create a context by itself and post a GST_MESSAGE_HAVE_CONTEXT message
+ * and send a GST_EVENT_CONTEXT event downstream, containing the complete
+ * context information at this time.
+ *
+ * Applications should catch the GST_MESSAGE_HAVE_CONTEXT messages and remember
+ * any content from it unless it has a custom version of a specific context. If
+ * later an element is posting a GST_MESSAGE_NEED_CONTEXT message for a specific
+ * context that was created by an element before the application should pass it
+ * to the complete pipeline.
+ */
+
+#include "gst_private.h"
+#include <string.h>
+#include "gstcontext.h"
+#include "gstquark.h"
+
+struct _GstContext
+{
+ GstMiniObject mini_object;
+
+ GstStructure *structure;
+};
+
+#define GST_CONTEXT_STRUCTURE(c) (((GstContext *)(c))->structure)
+
+static GType _gst_context_type = 0;
+GST_DEFINE_MINI_OBJECT_TYPE (GstContext, gst_context);
+
+void
+_priv_gst_context_initialize (void)
+{
+ GST_CAT_INFO (GST_CAT_GST_INIT, "init contexts");
+
+ /* the GstMiniObject types need to be class_ref'd once before it can be
+ * done from multiple threads;
+ * see http://bugzilla.gnome.org/show_bug.cgi?id=304551 */
+ gst_context_get_type ();
+
+ _gst_context_type = gst_context_get_type ();
+}
+
+static void
+_gst_context_free (GstContext * context)
+{
+ GstStructure *structure;
+
+ g_return_if_fail (context != NULL);
+
+ GST_CAT_LOG (GST_CAT_CONTEXT, "finalize context %p: %" GST_PTR_FORMAT,
+ context, GST_CONTEXT_STRUCTURE (context));
+
+ structure = GST_CONTEXT_STRUCTURE (context);
+ if (structure) {
+ gst_structure_set_parent_refcount (structure, NULL);
+ gst_structure_free (structure);
+ }
+
+ g_slice_free1 (sizeof (GstContext), context);
+}
+
+static void gst_context_init (GstContext * context);
+
+static GstContext *
+_gst_context_copy (GstContext * context)
+{
+ GstContext *copy;
+ GstStructure *structure;
+
+ GST_CAT_LOG (GST_CAT_CONTEXT, "copy context %p: %" GST_PTR_FORMAT, context,
+ GST_CONTEXT_STRUCTURE (context));
+
+ copy = g_slice_new0 (GstContext);
+
+ gst_context_init (copy);
+
+ structure = GST_CONTEXT_STRUCTURE (context);
+ GST_CONTEXT_STRUCTURE (copy) = gst_structure_copy (structure);
+ gst_structure_set_parent_refcount (GST_CONTEXT_STRUCTURE (copy),
+ ©->mini_object.refcount);
+
+ return GST_CONTEXT_CAST (copy);
+}
+
+static void
+gst_context_init (GstContext * context)
+{
+ gst_mini_object_init (GST_MINI_OBJECT_CAST (context), 0, _gst_context_type,
+ (GstMiniObjectCopyFunction) _gst_context_copy, NULL,
+ (GstMiniObjectFreeFunction) _gst_context_free);
+}
+
+/**
+ * gst_context_new:
+ *
+ * Create a new context.
+ *
+ * Returns: (transfer full): The new context.
+ *
+ * MT safe.
+ */
+GstContext *
+gst_context_new (void)
+{
+ GstContext *context;
+ GstStructure *structure;
+
+ context = g_slice_new0 (GstContext);
+
+ GST_CAT_LOG (GST_CAT_CONTEXT, "creating new context %p", context);
+
+ structure = gst_structure_new_id_empty (GST_QUARK (CONTEXT));
+ gst_structure_set_parent_refcount (structure, &context->mini_object.refcount);
+ gst_context_init (context);
+
+ GST_CONTEXT_STRUCTURE (context) = structure;
+
+ return context;
+}
+
+/**
+ * gst_context_get_structure:
+ * @context: The #GstContext.
+ *
+ * Access the structure of the context.
+ *
+ * Returns: (transfer none): The structure of the context. The structure is
+ * still owned by the context, which means that you should not modify it,
+ * free it and that the pointer becomes invalid when you free the context.
+ *
+ * MT safe.
+ */
+const GstStructure *
+gst_context_get_structure (GstContext * context)
+{
+ g_return_val_if_fail (GST_IS_CONTEXT (context), NULL);
+
+ return GST_CONTEXT_STRUCTURE (context);
+}
--- /dev/null
+/* GStreamer
+ * Copyright (C) 2013 Collabora Ltd.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ *
+ * 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., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __GST_CONTEXT_H__
+#define __GST_CONTEXT_H__
+
+G_BEGIN_DECLS
+
+typedef struct _GstContext GstContext;
+
+#include <gst/gstminiobject.h>
+#include <gst/gststructure.h>
+
+#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_CAST(obj) ((GstContext*)(obj))
+#define GST_CONTEXT(obj) (GST_CONTEXT_CAST(obj))
+
+
+
+GType gst_context_get_type (void);
+
+
+/* refcounting */
+/**
+ * gst_context_ref:
+ * @context: the context to ref
+ *
+ * Convenience macro to increase the reference count of the context.
+ *
+ * Returns: @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: the context to unref
+ *
+ * Convenience macro to decrease the reference count of the context, possibly
+ * freeing it.
+ */
+#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
+ *
+ * Creates a copy of the context. Returns a copy of the context.
+ *
+ * Returns: (transfer full): a new copy of @context.
+ *
+ * MT safe
+ */
+#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)));
+}
+
+/**
+ * gst_context_is_writable:
+ * @context: a #GstContext
+ *
+ * Tests if you can safely write into a context's structure or validly
+ * modify the seqnum and timestamp fields.
+ */
+#define gst_context_is_writable(context) gst_mini_object_is_writable (GST_MINI_OBJECT_CAST (context))
+/**
+ * gst_context_make_writable:
+ * @context: (transfer full): the context to make writable
+ *
+ * Checks if a context is writable. If not, a writable copy is made and
+ * returned.
+ *
+ * Returns: (transfer full): a context (possibly a duplicate) that is writable.
+ *
+ * MT safe
+ */
+#define gst_context_make_writable(context) GST_CONTEXT_CAST (gst_mini_object_make_writable (GST_MINI_OBJECT_CAST (context)))
+/**
+ * gst_context_replace:
+ * @old_context: (inout) (transfer full): pointer to a pointer to a #GstContext
+ * to be replaced.
+ * @new_context: (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.
+ *
+ * Returns: TRUE if @new_context was different from @old_context
+ */
+#ifdef _FOOL_GTK_DOC_
+G_INLINE_FUNC gboolean gst_context_replace (GstContext **old_context, GstContext *new_context);
+#endif
+
+static inline gboolean
+gst_context_replace (GstContext **old_context, GstContext *new_context)
+{
+ return gst_mini_object_replace ((GstMiniObject **) old_context, (GstMiniObject *) new_context);
+}
+
+GstContext * gst_context_new (void) G_GNUC_MALLOC;
+
+const GstStructure *
+ gst_context_get_structure (GstContext *context);
+
+G_END_DECLS
+
+#endif /* __GST_CONTEXT_H__ */
return result;
}
+
+/**
+ * gst_element_set_context:
+ * @element: a #GstElement to set the bus of.
+ * @context: (transfer none): the #GstContext to set.
+ *
+ * Sets the context of the element. Increases the refcount of the context.
+ *
+ * MT safe.
+ */
+void
+gst_element_set_context (GstElement * element, GstContext * context)
+{
+ GstElementClass *oclass;
+
+ g_return_if_fail (GST_IS_ELEMENT (element));
+
+ oclass = GST_ELEMENT_GET_CLASS (element);
+
+ GST_CAT_DEBUG_OBJECT (GST_CAT_CONTEXT, element,
+ "set context %p %" GST_PTR_FORMAT, context,
+ gst_context_get_structure (context));
+
+ if (oclass->set_context)
+ oclass->set_context (element, context);
+}
* @state_changed: called immediately after a new state was set.
* @post_message: called when a message is posted on the element. Chain up to
* the parent class' handler to have it posted on the bus.
+ * @set_context: set a #GstContext on the element
*
* GStreamer element class. Override the vmethods to implement the element
* functionality.
gboolean (*post_message) (GstElement *element, GstMessage *message);
+ void (*set_context) (GstElement *element, GstContext *context);
+
/*< private >*/
- gpointer _gst_reserved[GST_PADDING_LARGE-1];
+ gpointer _gst_reserved[GST_PADDING_LARGE-2];
};
/* element class pad templates */
void gst_element_set_bus (GstElement * element, GstBus * bus);
GstBus * gst_element_get_bus (GstElement * element);
+/* context */
+void gst_element_set_context (GstElement * element, GstContext * context);
+
/* pad management */
gboolean gst_element_add_pad (GstElement *element, GstPad *pad);
gboolean gst_element_remove_pad (GstElement *element, GstPad *pad);
{GST_EVENT_BUFFERSIZE, "buffersize", 0},
{GST_EVENT_SINK_MESSAGE, "sink-message", 0},
{GST_EVENT_EOS, "eos", 0},
+ {GST_EVENT_CONTEXT, "context", 0},
{GST_EVENT_SEGMENT_DONE, "segment-done", 0},
{GST_EVENT_GAP, "gap", 0},
{GST_EVENT_QOS, "qos", 0},
if (position != NULL)
*position = g_value_get_int64 (val);
}
+
+/**
+ * gst_event_new_context:
+ * @msg: (transfer full): the #GstContext
+ *
+ * Create a new context event. The purpose of the context event is
+ * to pass a pipeline-local context to downstream elements.
+ *
+ * Returns: (transfer full): a new #GstEvent
+ */
+GstEvent *
+gst_event_new_context (GstContext * context)
+{
+ GstEvent *event;
+ GstStructure *structure;
+
+ g_return_val_if_fail (context != NULL, NULL);
+
+ GST_CAT_INFO (GST_CAT_EVENT, "creating context event");
+
+ structure = gst_structure_new_id (GST_QUARK (EVENT_SEEK),
+ GST_QUARK (CONTEXT), GST_TYPE_CONTEXT, context, NULL);
+ event = gst_event_new_custom (GST_EVENT_CONTEXT, structure);
+ gst_context_unref (context);
+
+ return event;
+}
+
+/**
+ * gst_event_parse_context:
+ * @event: The event to query
+ * @context: (out) (transfer full): a pointer to store the #GstContext in.
+ *
+ * Parse the context event. Unref @context after usage.
+ */
+void
+gst_event_parse_context (GstEvent * event, GstContext ** context)
+{
+ const GstStructure *structure;
+
+ g_return_if_fail (GST_IS_EVENT (event));
+ g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_CONTEXT);
+
+ structure = GST_EVENT_STRUCTURE (event);
+ if (context)
+ *context =
+ GST_CONTEXT (g_value_dup_boxed (gst_structure_id_get_value
+ (structure, GST_QUARK (CONTEXT))));
+}
GST_EVENT_SINK_MESSAGE = GST_EVENT_MAKE_TYPE (100, FLAG(DOWNSTREAM) | FLAG(SERIALIZED) | FLAG(STICKY) | FLAG(STICKY_MULTI)),
GST_EVENT_EOS = GST_EVENT_MAKE_TYPE (110, FLAG(DOWNSTREAM) | FLAG(SERIALIZED) | FLAG(STICKY)),
GST_EVENT_TOC = GST_EVENT_MAKE_TYPE (120, FLAG(DOWNSTREAM) | FLAG(SERIALIZED) | FLAG(STICKY) | FLAG(STICKY_MULTI)),
+ GST_EVENT_CONTEXT = GST_EVENT_MAKE_TYPE (130, FLAG(DOWNSTREAM) | FLAG(SERIALIZED) | FLAG(STICKY) | FLAG(STICKY_MULTI)),
/* non-sticky downstream serialized */
GST_EVENT_SEGMENT_DONE = GST_EVENT_MAKE_TYPE (150, FLAG(DOWNSTREAM) | FLAG(SERIALIZED)),
#include <gst/gstsegment.h>
#include <gst/gstsegment.h>
#include <gst/gstmessage.h>
+#include <gst/gstcontext.h>
G_BEGIN_DECLS
GstEvent* gst_event_new_segment_done (GstFormat format, gint64 position) G_GNUC_MALLOC;
void gst_event_parse_segment_done (GstEvent *event, GstFormat *format, gint64 *position);
+/* context */
+GstEvent* gst_event_new_context (GstContext * context) G_GNUC_MALLOC;
+void gst_event_parse_context (GstEvent *event, GstContext **context);
+
G_END_DECLS
#endif /* __GST_EVENT_H__ */
GstDebugCategory *_priv_GST_CAT_POLL = NULL;
GstDebugCategory *GST_CAT_META = NULL;
GstDebugCategory *GST_CAT_LOCKING = NULL;
+GstDebugCategory *GST_CAT_CONTEXT = NULL;
#endif /* !defined(GST_DISABLE_GST_DEBUG) || !defined(GST_REMOVE_DISABLED) */
_priv_GST_CAT_POLL = _gst_debug_category_new ("GST_POLL", 0, "poll");
GST_CAT_META = _gst_debug_category_new ("GST_META", 0, "meta");
GST_CAT_LOCKING = _gst_debug_category_new ("GST_LOCKING", 0, "locking");
-
+ GST_CAT_CONTEXT = _gst_debug_category_new ("GST_CONTEXT", 0, NULL);
/* print out the valgrind message if we're in valgrind */
_priv_gst_in_valgrind ();
g_free (s);
return ret;
}
+ if (GST_IS_CONTEXT (object)) {
+ GstContext *context = GST_CONTEXT_CAST (object);
+ gchar *s, *ret;
+ const GstStructure *structure;
+
+ structure = gst_context_get_structure (context);
+
+ if (structure) {
+ s = gst_info_structure_to_string (structure);
+ } else {
+ s = g_strdup ("(NULL)");
+ }
+
+ ret = g_strdup_printf ("context '%s'", s);
+ g_free (s);
+ return ret;
+ }
return g_strdup_printf ("%p", ptr);
}
return message;
}
+
+/**
+ * gst_message_new_need_context:
+ * @src: (transfer none): The object originating the message.
+ *
+ * This message is posted when an element needs a specific #GstContext.
+ *
+ * Returns: (transfer full): The new need-context message.
+ *
+ * MT safe.
+ */
+GstMessage *
+gst_message_new_need_context (GstObject * src)
+{
+ GstMessage *message;
+ GstStructure *structure;
+
+ structure = gst_structure_new_id_empty (GST_QUARK (MESSAGE_NEED_CONTEXT));
+ message = gst_message_new_custom (GST_MESSAGE_NEED_CONTEXT, src, structure);
+
+ return message;
+}
+
+static GArray *
+ensure_array (GstStructure * s, GQuark quark, gsize element_size,
+ GDestroyNotify clear_func)
+{
+ GArray *array;
+ const GValue *value;
+
+ value = gst_structure_id_get_value (s, quark);
+ if (value) {
+ array = (GArray *) g_value_get_boxed (value);
+ } else {
+ GValue new_array_val = { 0, };
+
+ array = g_array_new (FALSE, TRUE, element_size);
+ if (clear_func)
+ g_array_set_clear_func (array, clear_func);
+
+ g_value_init (&new_array_val, G_TYPE_ARRAY);
+ g_value_take_boxed (&new_array_val, array);
+
+ gst_structure_id_take_value (s, quark, &new_array_val);
+ }
+ return array;
+}
+
+static void
+free_array_string (gpointer ptr)
+{
+ gchar *str = *(gchar **) ptr;
+ g_free (str);
+}
+
+/**
+ * gst_message_add_context_type:
+ * @message: a GST_MESSAGE_NEED_CONTEXT type message
+ * @context_type: a context type
+ *
+ * Add a new context type to @message.
+ */
+void
+gst_message_add_context_type (GstMessage * message, const gchar * context_type)
+{
+ GstStructure *structure;
+ GArray *array;
+ gchar *copy;
+
+ g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_NEED_CONTEXT);
+ g_return_if_fail (gst_message_is_writable (message));
+
+ structure = GST_MESSAGE_STRUCTURE (message);
+ array = ensure_array (structure, GST_QUARK (CONTEXT_TYPES),
+ sizeof (gchar *), free_array_string);
+
+ copy = g_strdup (context_type);
+ g_array_append_val (array, copy);
+}
+
+/**
+ * gst_message_get_n_context_types:
+ * @message: a GST_MESSAGE_NEED_CONTEXT type message
+ *
+ * Retrieve the number of values currently stored in the
+ * context-types array of the message's structure.
+ *
+ * Returns: the context-types array size as a #guint.
+ */
+guint
+gst_message_get_n_context_types (GstMessage * message)
+{
+ GstStructure *structure;
+ GArray *array;
+
+ g_return_val_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_NEED_CONTEXT,
+ 0);
+
+ structure = GST_MESSAGE_STRUCTURE (message);
+ array = ensure_array (structure, GST_QUARK (CONTEXT_TYPES),
+ sizeof (gchar *), free_array_string);
+
+ return array->len;
+}
+
+/**
+ * gst_message_parse_nth_context_type:
+ * @message: a GST_MESSAGE_NEED_CONTEXT type message
+ * @context_type: (out) (allow-none): the context type, or NULL
+ *
+ * Parse a context type from an existing GST_MESSAGE_NEED_CONTEXT message
+ * from @index.
+ *
+ * Returns: a #gboolean indicating if the parsing succeeded.
+ */
+gboolean
+gst_message_parse_nth_context_type (GstMessage * message, guint index,
+ const gchar ** context_type)
+{
+ GstStructure *structure;
+ GArray *array;
+
+ g_return_val_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_NEED_CONTEXT,
+ FALSE);
+
+ structure = GST_MESSAGE_STRUCTURE (message);
+
+ array = ensure_array (structure, GST_QUARK (CONTEXT_TYPES),
+ sizeof (gchar *), free_array_string);
+ g_return_val_if_fail (index < array->len, FALSE);
+
+ if (context_type)
+ *context_type = g_array_index (array, gchar *, index);
+
+ return TRUE;
+}
+
+/**
+ * gst_message_new_have_context:
+ * @src: (transfer none): The object originating the message.
+ * @context: (transfer full): the context
+ *
+ * This message is posted when an element has a new local #GstContext.
+ *
+ * Returns: (transfer full): The new have-context message.
+ *
+ * MT safe.
+ */
+GstMessage *
+gst_message_new_have_context (GstObject * src, GstContext * context)
+{
+ GstMessage *message;
+ GstStructure *structure;
+
+ structure = gst_structure_new_id (GST_QUARK (MESSAGE_HAVE_CONTEXT),
+ GST_QUARK (CONTEXT), GST_TYPE_CONTEXT, context, NULL);
+ message = gst_message_new_custom (GST_MESSAGE_HAVE_CONTEXT, src, structure);
+ gst_context_unref (context);
+
+ return message;
+}
+
+/**
+ * gst_message_parse_have_context:
+ * @message: A valid #GstMessage of type GST_MESSAGE_HAVE_CONTEXT.
+ * @context: (out) (transfer full): Result location for the context or NULL
+ *
+ * Extract the context from the HAVE_CONTEXT message.
+ *
+ * MT safe.
+ */
+void
+gst_message_parse_have_context (GstMessage * message, GstContext ** context)
+{
+ g_return_if_fail (GST_IS_MESSAGE (message));
+ g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_HAVE_CONTEXT);
+
+ if (context)
+ gst_structure_id_get (GST_MESSAGE_STRUCTURE (message),
+ GST_QUARK (CONTEXT), GST_TYPE_CONTEXT, context, NULL);
+}
GST_MESSAGE_TOC = (1 << 26),
GST_MESSAGE_RESET_TIME = (1 << 27),
GST_MESSAGE_STREAM_START = (1 << 28),
+ GST_MESSAGE_NEED_CONTEXT = (1 << 29),
+ GST_MESSAGE_HAVE_CONTEXT = (1 << 30),
GST_MESSAGE_ANY = ~0
} GstMessageType;
/* STREAM_START */
GstMessage * gst_message_new_stream_start (GstObject * src) G_GNUC_MALLOC;
+/* NEED_CONTEXT */
+GstMessage * gst_message_new_need_context (GstObject * src) G_GNUC_MALLOC;
+void gst_message_add_context_type (GstMessage * message, const gchar * context_type);
+guint gst_message_get_n_context_types (GstMessage * message);
+gboolean gst_message_parse_nth_context_type (GstMessage * message, guint i, const gchar ** context_type);
+
+/* HAVE_CONTEXT */
+GstMessage * gst_message_new_have_context (GstObject * src, GstContext *context) G_GNUC_MALLOC;
+void gst_message_parse_have_context (GstMessage *message, GstContext **context);
+
G_END_DECLS
#endif /* __GST_MESSAGE_H__ */
"GstMessageResetTime",
"GstMessageToc", "GstEventTocGlobal", "GstEventTocCurrent",
"GstEventSegmentDone",
- "GstEventStreamStart", "stream-id"
+ "GstEventStreamStart", "stream-id", "GstEventContext", "GstQueryContext",
+ "GstMessageNeedContext", "GstMessageHaveContext", "context", "context-types"
};
GQuark _priv_gst_quark_table[GST_QUARK_MAX];
GST_QUARK_EVENT_SEGMENT_DONE = 159,
GST_QUARK_EVENT_STREAM_START = 160,
GST_QUARK_STREAM_ID = 161,
- GST_QUARK_MAX = 162
+ GST_QUARK_EVENT_CONTEXT = 162,
+ GST_QUARK_QUERY_CONTEXT = 163,
+ GST_QUARK_MESSAGE_NEED_CONTEXT = 164,
+ GST_QUARK_MESSAGE_HAVE_CONTEXT = 165,
+ GST_QUARK_CONTEXT = 166,
+ GST_QUARK_CONTEXT_TYPES = 167,
+ GST_QUARK_MAX = 168
} GstQuarkId;
extern GQuark _priv_gst_quark_table[GST_QUARK_MAX];
{GST_QUERY_ACCEPT_CAPS, "accept-caps", 0},
{GST_QUERY_CAPS, "caps", 0},
{GST_QUERY_DRAIN, "drain", 0},
+ {GST_QUERY_CONTEXT, "context", 0},
{0, NULL, 0}
};
return query;
}
+
+/**
+ * gst_query_new_context:
+ *
+ * Constructs a new query object for querying the pipeline-local context.
+ *
+ * Free-function: gst_query_unref
+ *
+ * Returns: (transfer full): a new #GstQuery
+ */
+GstQuery *
+gst_query_new_context (void)
+{
+ GstQuery *query;
+ GstStructure *structure;
+
+ structure = gst_structure_new_id_empty (GST_QUARK (QUERY_CONTEXT));
+ query = gst_query_new_custom (GST_QUERY_CONTEXT, structure);
+
+ return query;
+}
+
+/**
+ * gst_query_set_context:
+ * @query: a #GstQuery with query type GST_QUERY_CONTEXT
+ * @context: the requested #GstContext
+ *
+ * Answer a context query by setting the requested context.
+ */
+void
+gst_query_set_context (GstQuery * query, GstContext * context)
+{
+ GstStructure *s;
+
+ g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CONTEXT);
+
+ s = GST_QUERY_STRUCTURE (query);
+
+ gst_structure_id_set (s,
+ GST_QUARK (CONTEXT), GST_TYPE_CONTEXT, context, NULL);
+}
+
+/**
+ * gst_query_parse_context:
+ * @query: The query to parse
+ * @context: (out): A pointer to store the #GstContext
+ *
+ * Get the context from the context @query. The context remains valid as long as
+ * @query remains valid.
+ */
+void
+gst_query_parse_context (GstQuery * query, GstContext ** context)
+{
+ GstStructure *structure;
+
+ g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CONTEXT);
+ g_return_if_fail (context != NULL);
+
+ structure = GST_QUERY_STRUCTURE (query);
+ *context = g_value_get_boxed (gst_structure_id_get_value (structure,
+ GST_QUARK (CONTEXT)));
+}
+
+static void
+free_array_string (gpointer ptr)
+{
+ gchar *str = *(gchar **) ptr;
+ g_free (str);
+}
+
+/**
+ * gst_query_add_context_type:
+ * @query: a GST_QUERY_NEED_CONTEXT type query
+ * @context_type: a context type
+ *
+ * Add a new context type to @query.
+ */
+void
+gst_query_add_context_type (GstQuery * query, const gchar * context_type)
+{
+ GstStructure *structure;
+ GArray *array;
+ gchar *copy;
+
+ g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CONTEXT);
+ g_return_if_fail (gst_query_is_writable (query));
+
+ structure = GST_QUERY_STRUCTURE (query);
+ array = ensure_array (structure, GST_QUARK (CONTEXT_TYPES),
+ sizeof (gchar *), free_array_string);
+
+ copy = g_strdup (context_type);
+ g_array_append_val (array, copy);
+}
+
+/**
+ * gst_query_get_n_context_types:
+ * @query: a GST_QUERY_NEED_CONTEXT type query
+ *
+ * Retrieve the number of values currently stored in the
+ * context-types array of the query's structure.
+ *
+ * Returns: the context-types array size as a #guint.
+ */
+guint
+gst_query_get_n_context_types (GstQuery * query)
+{
+ GstStructure *structure;
+ GArray *array;
+
+ g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CONTEXT, 0);
+
+ structure = GST_QUERY_STRUCTURE (query);
+ array = ensure_array (structure, GST_QUARK (CONTEXT_TYPES),
+ sizeof (gchar *), free_array_string);
+
+ return array->len;
+}
+
+/**
+ * gst_query_parse_nth_context_type:
+ * @query: a GST_QUERY_NEED_CONTEXT type query
+ * @context_type: (out) (allow-none): the context type, or NULL
+ *
+ * Parse a context type from an existing GST_QUERY_NEED_CONTEXT query
+ * from @index.
+ *
+ * Returns: a #gboolean indicating if the parsing succeeded.
+ */
+gboolean
+gst_query_parse_nth_context_type (GstQuery * query, guint index,
+ const gchar ** context_type)
+{
+ GstStructure *structure;
+ GArray *array;
+
+ g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CONTEXT, FALSE);
+
+ structure = GST_QUERY_STRUCTURE (query);
+
+ array = ensure_array (structure, GST_QUARK (CONTEXT_TYPES),
+ sizeof (gchar *), free_array_string);
+ g_return_val_if_fail (index < array->len, FALSE);
+
+ if (context_type)
+ *context_type = g_array_index (array, gchar *, index);
+
+ return TRUE;
+}
#include <gst/gstpad.h>
#include <gst/gstallocator.h>
#include <gst/gsttoc.h>
+#include <gst/gstcontext.h>
G_BEGIN_DECLS
* @GST_QUERY_ACCEPT_CAPS: the accept caps query
* @GST_QUERY_CAPS: the caps query
* @GST_QUERY_DRAIN: wait till all serialized data is consumed downstream
+ * @GST_QUERY_CONTEXT: query the pipeline-local context from downstream
*
* Standard predefined Query types
*/
GST_QUERY_SCHEDULING = GST_QUERY_MAKE_TYPE (150, FLAG(UPSTREAM)),
GST_QUERY_ACCEPT_CAPS = GST_QUERY_MAKE_TYPE (160, FLAG(BOTH)),
GST_QUERY_CAPS = GST_QUERY_MAKE_TYPE (170, FLAG(BOTH)),
- GST_QUERY_DRAIN = GST_QUERY_MAKE_TYPE (180, FLAG(DOWNSTREAM) | FLAG(SERIALIZED))
+ GST_QUERY_DRAIN = GST_QUERY_MAKE_TYPE (180, FLAG(DOWNSTREAM) | FLAG(SERIALIZED)),
+ GST_QUERY_CONTEXT = GST_QUERY_MAKE_TYPE (190, FLAG(DOWNSTREAM))
} GstQueryType;
#undef FLAG
/* drain query */
GstQuery * gst_query_new_drain (void) G_GNUC_MALLOC;
+/* context query */
+GstQuery * gst_query_new_context (void) G_GNUC_MALLOC;
+void gst_query_add_context_type (GstQuery * query, const gchar * context_type);
+guint gst_query_get_n_context_types (GstQuery * query);
+gboolean gst_query_parse_nth_context_type (GstQuery * query, guint i, const gchar ** context_type);
+void gst_query_set_context (GstQuery *query, GstContext *context);
+void gst_query_parse_context (GstQuery *query, GstContext **context);
+
G_END_DECLS
#endif /* __GST_QUERY_H__ */
gst_base_parse_set_duration
gst_base_parse_set_frame_rate
gst_base_parse_set_has_timing_info
+ gst_base_parse_set_infer_ts
gst_base_parse_set_latency
gst_base_parse_set_min_frame_size
gst_base_parse_set_passthrough
GST_CAT_CALL_TRACE DATA
GST_CAT_CAPS DATA
GST_CAT_CLOCK DATA
+ GST_CAT_CONTEXT DATA
GST_CAT_DEFAULT DATA
GST_CAT_ELEMENT_PADS DATA
GST_CAT_ERROR_SYSTEM DATA
gst_clock_single_shot_id_reinit
gst_clock_type_get_type
gst_clock_unadjust_unlocked
+ gst_context_get_structure
+ gst_context_get_type
+ gst_context_new
gst_control_binding_get_g_value_array
gst_control_binding_get_type
gst_control_binding_get_value
gst_element_set_base_time
gst_element_set_bus
gst_element_set_clock
+ gst_element_set_context
gst_element_set_locked_state
gst_element_set_start_time
gst_element_set_state
gst_event_has_name
gst_event_new_buffer_size
gst_event_new_caps
+ gst_event_new_context
gst_event_new_custom
gst_event_new_eos
gst_event_new_flush_start
gst_event_new_toc_select
gst_event_parse_buffer_size
gst_event_parse_caps
+ gst_event_parse_context
gst_event_parse_flush_stop
gst_event_parse_gap
gst_event_parse_latency
gst_memory_resize
gst_memory_share
gst_memory_unmap
+ gst_message_add_context_type
+ gst_message_get_n_context_types
gst_message_get_seqnum
gst_message_get_stream_status_object
gst_message_get_structure
gst_message_new_element
gst_message_new_eos
gst_message_new_error
+ gst_message_new_have_context
gst_message_new_info
gst_message_new_latency
+ gst_message_new_need_context
gst_message_new_new_clock
gst_message_new_progress
gst_message_new_qos
gst_message_parse_clock_lost
gst_message_parse_clock_provide
gst_message_parse_error
+ gst_message_parse_have_context
gst_message_parse_info
gst_message_parse_new_clock
+ gst_message_parse_nth_context_type
gst_message_parse_progress
gst_message_parse_qos
gst_message_parse_qos_stats
gst_query_add_allocation_param
gst_query_add_allocation_pool
gst_query_add_buffering_range
+ gst_query_add_context_type
gst_query_add_scheduling_mode
gst_query_find_allocation_meta
gst_query_get_n_allocation_metas
gst_query_get_n_allocation_params
gst_query_get_n_allocation_pools
gst_query_get_n_buffering_ranges
+ gst_query_get_n_context_types
gst_query_get_n_scheduling_modes
gst_query_get_structure
gst_query_get_type
gst_query_new_allocation
gst_query_new_buffering
gst_query_new_caps
+ gst_query_new_context
gst_query_new_convert
gst_query_new_custom
gst_query_new_drain
gst_query_parse_buffering_stats
gst_query_parse_caps
gst_query_parse_caps_result
+ gst_query_parse_context
gst_query_parse_convert
gst_query_parse_duration
gst_query_parse_latency
gst_query_parse_nth_allocation_param
gst_query_parse_nth_allocation_pool
gst_query_parse_nth_buffering_range
+ gst_query_parse_nth_context_type
gst_query_parse_nth_format
gst_query_parse_nth_scheduling_mode
gst_query_parse_position
gst_query_set_buffering_range
gst_query_set_buffering_stats
gst_query_set_caps_result
+ gst_query_set_context
gst_query_set_convert
gst_query_set_duration
gst_query_set_formats