From 640a05ff6082230ab01644146732d75a27b98c66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Tue, 17 Sep 2013 14:25:10 +0200 Subject: [PATCH] bin: Implement context caching and propagation again --- gst/gstbin.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 96 insertions(+), 1 deletion(-) diff --git a/gst/gstbin.c b/gst/gstbin.c index baa3580345..c03f9e0529 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,6 +1170,9 @@ gst_bin_add_func (GstBin * bin, GstElement * element) * a new clock will be selected */ gst_element_set_clock (element, GST_ELEMENT_CLOCK (bin)); + 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 */ if (bin->priv->index) @@ -2576,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; @@ -3269,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 @@ -3625,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; } @@ -3989,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);