aboutsummaryrefslogtreecommitdiff
path: root/gst/gstbin.c
diff options
context:
space:
mode:
Diffstat (limited to 'gst/gstbin.c')
-rw-r--r--gst/gstbin.c98
1 files changed, 95 insertions, 3 deletions
diff --git a/gst/gstbin.c b/gst/gstbin.c
index 6da31e8..c03f9e0 100644
--- a/gst/gstbin.c
+++ b/gst/gstbin.c
@@ -198,6 +198,8 @@ struct _GstBinPrivate
gboolean message_forward;
gboolean posted_eos;
+
+ GList *contexts;
};
typedef struct
@@ -530,6 +532,8 @@ gst_bin_dispose (GObject * object)
GST_STR_NULL (GST_OBJECT_NAME (object)));
}
+ g_list_free_full (bin->priv->contexts, (GDestroyNotify) gst_context_unref);
+
G_OBJECT_CLASS (parent_class)->dispose (object);
}
@@ -1094,6 +1098,7 @@ gst_bin_add_func (GstBin * bin, GstElement * element)
gboolean is_sink, is_source, provides_clock, requires_clock;
GstMessage *clock_message = NULL, *async_message = NULL;
GstStateChangeReturn ret;
+ GList *l;
GST_DEBUG_OBJECT (bin, "element :%s", GST_ELEMENT_NAME (element));
@@ -1165,8 +1170,8 @@ gst_bin_add_func (GstBin * bin, GstElement * element)
* a new clock will be selected */
gst_element_set_clock (element, GST_ELEMENT_CLOCK (bin));
- if (GST_ELEMENT_CAST (bin)->context)
- gst_element_set_context (element, GST_ELEMENT_CAST (bin)->context);
+ for (l = bin->priv->contexts; l; l = l->next)
+ gst_element_set_context (element, l->data);
#if 0
/* set the cached index on the children */
@@ -2579,9 +2584,30 @@ gst_bin_change_state_func (GstElement * element, GstStateChange transition)
goto activate_failure;
break;
case GST_STATE_NULL:
- if (current == GST_STATE_READY)
+ if (current == GST_STATE_READY) {
+ GList *l;
+
if (!(gst_bin_src_pads_activate (bin, FALSE)))
goto activate_failure;
+
+ /* Remove all non-persistent contexts */
+ GST_OBJECT_LOCK (bin);
+ for (l = bin->priv->contexts; l;) {
+ GstContext *context = l->data;
+
+ if (!gst_context_is_persistent (context)) {
+ GList *next;
+
+ gst_context_unref (context);
+ next = l->next;
+ bin->priv->contexts = g_list_delete_link (bin->priv->contexts, l);
+ l = next;
+ } else {
+ l = l->next;
+ }
+ }
+ GST_OBJECT_UNLOCK (bin);
+ }
break;
default:
break;
@@ -3272,6 +3298,34 @@ bin_do_message_forward (GstBin * bin, GstMessage * message)
}
}
+static void
+gst_bin_update_context (GstBin * bin, GstContext * context)
+{
+ GList *l;
+ const gchar *context_type;
+
+ GST_OBJECT_LOCK (bin);
+ context_type = gst_context_get_context_type (context);
+ for (l = bin->priv->contexts; l; l = l->next) {
+ GstContext *tmp = l->data;
+ const gchar *tmp_type = gst_context_get_context_type (tmp);
+
+ /* Always store newest context but never replace
+ * a persistent one by a non-persistent one */
+ if (strcmp (context_type, tmp_type) == 0 &&
+ (gst_context_is_persistent (context) ||
+ !gst_context_is_persistent (tmp))) {
+ gst_context_replace ((GstContext **) & l->data, context);
+ break;
+ }
+ }
+ /* Not found? Add */
+ if (l != NULL)
+ bin->priv->contexts =
+ g_list_prepend (bin->priv->contexts, gst_context_ref (context));
+ GST_OBJECT_UNLOCK (bin);
+}
+
/* handle child messages:
*
* This method is called synchronously when a child posts a message on
@@ -3628,6 +3682,42 @@ gst_bin_handle_message_func (GstBin * bin, GstMessage * message)
break;
}
+ case GST_MESSAGE_NEED_CONTEXT:{
+ const gchar *context_type;
+ GList *l;
+
+ gst_message_parse_context_type (message, &context_type);
+ GST_OBJECT_LOCK (bin);
+ for (l = bin->priv->contexts; l; l = l->next) {
+ GstContext *tmp = l->data;
+ const gchar *tmp_type = gst_context_get_context_type (tmp);
+
+ if (strcmp (context_type, tmp_type) == 0) {
+ gst_element_set_context (GST_ELEMENT (src), l->data);
+ break;
+ }
+ }
+ GST_OBJECT_UNLOCK (bin);
+
+ /* Forward if we couldn't answer the message */
+ if (l == NULL) {
+ goto forward;
+ } else {
+ gst_message_unref (message);
+ }
+
+ break;
+ }
+ case GST_MESSAGE_HAVE_CONTEXT:{
+ GstContext *context;
+
+ gst_message_parse_have_context (message, &context);
+ gst_bin_update_context (bin, context);
+ gst_context_unref (context);
+
+ goto forward;
+ break;
+ }
default:
goto forward;
}
@@ -3992,6 +4082,8 @@ gst_bin_set_context (GstElement * element, GstContext * context)
bin = GST_BIN (element);
+ gst_bin_update_context (bin, context);
+
children = gst_bin_iterate_elements (bin);
while (gst_iterator_foreach (children, set_context,
context) == GST_ITERATOR_RESYNC);