tee: Check for the removed pad flag also in the slow pushing path
[platform/upstream/gstreamer.git] / gst / gstcontext.c
index 92afb75..c1bbe0a 100644 (file)
@@ -1,6 +1,7 @@
 /* GStreamer
  * Copyright (C) 2013 Collabora Ltd.
  *   Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ * Copyright (C) 2013 Sebastian Dröge <slomo@circular-chaos.org>
  *
  * gstcontext.h: Header for GstContext subsystem
  *
@@ -22,6 +23,7 @@
 
 /**
  * SECTION:gstcontext
+ * @title: GstContext
  * @short_description: Lightweight objects to represent element contexts
  * @see_also: #GstMiniObject, #GstElement
  *
  *
  * 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()
+ * child elements. Elements can handle these in #GstElementClass.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
+ * 1. Check if the element already has a context
+ * 2. Query downstream with GST_QUERY_CONTEXT for the context
+ * 3. Query upstream with GST_QUERY_CONTEXT for the context
+ * 4. 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.
+ * 5. Create a context by itself and post a GST_MESSAGE_HAVE_CONTEXT message
+ *    on the bus.
  *
- * 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 element or the complete pipeline.
+ * Bins will catch GST_MESSAGE_NEED_CONTEXT messages and will set any previously
+ * known context on the element that asks for it if possible. Otherwise the
+ * application should provide one if it can.
+ *
+ * #GstContext<!-- -->s can be persistent.
+ * A persistent #GstContext is kept in elements when they reach
+ * %GST_STATE_NULL, non-persistent ones will be removed.
+ * Also, a non-persistent context won't override a previous persistent
+ * context set to an element.
  *
  * Since: 1.2
  */
@@ -62,12 +68,14 @@ struct _GstContext
 {
   GstMiniObject mini_object;
 
+  gchar *context_type;
   GstStructure *structure;
+  gboolean persistent;
 };
 
 #define GST_CONTEXT_STRUCTURE(c)  (((GstContext *)(c))->structure)
 
-static GType _gst_context_type = 0;
+GType _gst_context_type = 0;
 GST_DEFINE_MINI_OBJECT_TYPE (GstContext, gst_context);
 
 void
@@ -98,6 +106,11 @@ _gst_context_free (GstContext * context)
     gst_structure_set_parent_refcount (structure, NULL);
     gst_structure_free (structure);
   }
+  g_free (context->context_type);
+
+#ifdef USE_POISONING
+  memset (context, 0xff, sizeof (GstContext));
+#endif
 
   g_slice_free1 (sizeof (GstContext), context);
 }
@@ -117,11 +130,15 @@ _gst_context_copy (GstContext * context)
 
   gst_context_init (copy);
 
+  copy->context_type = g_strdup (context->context_type);
+
   structure = GST_CONTEXT_STRUCTURE (context);
   GST_CONTEXT_STRUCTURE (copy) = gst_structure_copy (structure);
   gst_structure_set_parent_refcount (GST_CONTEXT_STRUCTURE (copy),
       &copy->mini_object.refcount);
 
+  copy->persistent = context->persistent;
+
   return GST_CONTEXT_CAST (copy);
 }
 
@@ -135,6 +152,8 @@ gst_context_init (GstContext * context)
 
 /**
  * gst_context_new:
+ * @context_type: Context type
+ * @persistent: Persistent context
  *
  * Create a new context.
  *
@@ -143,11 +162,13 @@ gst_context_init (GstContext * context)
  * Since: 1.2
  */
 GstContext *
-gst_context_new (void)
+gst_context_new (const gchar * context_type, gboolean persistent)
 {
   GstContext *context;
   GstStructure *structure;
 
+  g_return_val_if_fail (context_type != NULL, NULL);
+
   context = g_slice_new0 (GstContext);
 
   GST_CAT_LOG (GST_CAT_CONTEXT, "creating new context %p", context);
@@ -156,12 +177,53 @@ gst_context_new (void)
   gst_structure_set_parent_refcount (structure, &context->mini_object.refcount);
   gst_context_init (context);
 
+  context->context_type = g_strdup (context_type);
   GST_CONTEXT_STRUCTURE (context) = structure;
+  context->persistent = persistent;
 
   return context;
 }
 
 /**
+ * gst_context_get_context_type:
+ * @context: The #GstContext.
+ *
+ * Get the type of @context.
+ *
+ * Returns: The type of the context.
+ *
+ * Since: 1.2
+ */
+const gchar *
+gst_context_get_context_type (const GstContext * context)
+{
+  g_return_val_if_fail (GST_IS_CONTEXT (context), NULL);
+
+  return context->context_type;
+}
+
+/**
+ * gst_context_has_context_type:
+ * @context: The #GstContext.
+ * @context_type: Context type to check.
+ *
+ * Checks if @context has @context_type.
+ *
+ * Returns: %TRUE if @context has @context_type.
+ *
+ * Since: 1.2
+ */
+gboolean
+gst_context_has_context_type (const GstContext * context,
+    const gchar * context_type)
+{
+  g_return_val_if_fail (GST_IS_CONTEXT (context), FALSE);
+  g_return_val_if_fail (context_type != NULL, FALSE);
+
+  return strcmp (context->context_type, context_type) == 0;
+}
+
+/**
  * gst_context_get_structure:
  * @context: The #GstContext.
  *
@@ -174,7 +236,7 @@ gst_context_new (void)
  * Since: 1.2
  */
 const GstStructure *
-gst_context_get_structure (GstContext * context)
+gst_context_get_structure (const GstContext * context)
 {
   g_return_val_if_fail (GST_IS_CONTEXT (context), NULL);
 
@@ -188,8 +250,8 @@ gst_context_get_structure (GstContext * context)
  * Get a writable version of the structure.
  *
  * Returns: The structure of the context. The structure is still
- * owned by the event, which means that you should not free it and
- * that the pointer becomes invalid when you free the event.
+ * owned by the context, which means that you should not free it and
+ * that the pointer becomes invalid when you free the context.
  * This function checks if @context is writable.
  *
  * Since: 1.2
@@ -202,3 +264,21 @@ gst_context_writable_structure (GstContext * context)
 
   return GST_CONTEXT_STRUCTURE (context);
 }
+
+/**
+ * gst_context_is_persistent:
+ * @context: The #GstContext.
+ *
+ * Check if @context is persistent.
+ *
+ * Returns: %TRUE if the context is persistent.
+ *
+ * Since: 1.2
+ */
+gboolean
+gst_context_is_persistent (const GstContext * context)
+{
+  g_return_val_if_fail (GST_IS_CONTEXT (context), FALSE);
+
+  return context->persistent;
+}