summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Dröge <slomo@circular-chaos.org>2013-09-18 22:05:36 +0200
committerSebastian Dröge <slomo@circular-chaos.org>2013-09-18 22:39:25 +0200
commit78b0e167736b1399e41b300c54353f13245ace3e (patch)
tree634d057930017c532cdb7536c2904bc7bf6c275a
parente21d3d214a0de806f40f5f04b9537a2bc6dfcf27 (diff)
playbin: Implement context caching for sinks that are not in playsink yet
-rw-r--r--gst/playback/gstplaybin2.c83
1 files changed, 83 insertions, 0 deletions
diff --git a/gst/playback/gstplaybin2.c b/gst/playback/gstplaybin2.c
index 51ee43c73..49565c837 100644
--- a/gst/playback/gstplaybin2.c
+++ b/gst/playback/gstplaybin2.c
@@ -470,6 +470,8 @@ struct _GstPlayBin
} duration[5]; /* cached durations */
guint64 ring_buffer_max_size; /* 0 means disabled */
+
+ GList *contexts;
};
struct _GstPlayBinClass
@@ -1530,6 +1532,8 @@ gst_play_bin_finalize (GObject * object)
if (playbin->velements)
g_sequence_free (playbin->velements);
+ g_list_free_full (playbin->contexts, (GDestroyNotify) gst_context_unref);
+
g_rec_mutex_clear (&playbin->lock);
g_mutex_clear (&playbin->dyn_lock);
g_mutex_clear (&playbin->elements_lock);
@@ -4061,6 +4065,34 @@ gst_play_bin_set_context (GstElement * element, GstContext * context)
}
/* Pass sink messages to the application, e.g. NEED_CONTEXT messages */
+static void
+gst_play_bin_update_context (GstPlayBin * playbin, GstContext * context)
+{
+ GList *l;
+ const gchar *context_type;
+
+ GST_OBJECT_LOCK (playbin);
+ context_type = gst_context_get_context_type (context);
+ for (l = playbin->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)
+ playbin->contexts =
+ g_list_prepend (playbin->contexts, gst_context_ref (context));
+ GST_OBJECT_UNLOCK (playbin);
+}
+
static GstBusSyncReply
activate_sink_bus_handler (GstBus * bus, GstMessage * msg, GstPlayBin * playbin)
{
@@ -4081,6 +4113,37 @@ activate_sink_bus_handler (GstBus * bus, GstMessage * msg, GstPlayBin * playbin)
gst_element_post_message (GST_ELEMENT_CAST (playbin), msg);
else
gst_message_unref (msg);
+ } else if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_NEED_CONTEXT) {
+ const gchar *context_type;
+ GList *l;
+
+ gst_message_parse_context_type (msg, &context_type);
+ GST_OBJECT_LOCK (playbin);
+ for (l = playbin->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 (GST_MESSAGE_SRC (msg)), l->data);
+ break;
+ }
+ }
+ GST_OBJECT_UNLOCK (playbin);
+
+ /* Forward if we couldn't answer the message */
+ if (l == NULL) {
+ gst_element_post_message (GST_ELEMENT_CAST (playbin), msg);
+ } else {
+ gst_message_unref (msg);
+ }
+ } else if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_HAVE_CONTEXT) {
+ GstContext *context;
+
+ gst_message_parse_have_context (msg, &context);
+ gst_play_bin_update_context (playbin, context);
+ gst_context_unref (context);
+
+ gst_element_post_message (GST_ELEMENT_CAST (playbin), msg);
} else {
gst_element_post_message (GST_ELEMENT_CAST (playbin), msg);
}
@@ -5379,6 +5442,7 @@ gst_play_bin_change_state (GstElement * element, GstStateChange transition)
case GST_STATE_CHANGE_READY_TO_NULL:
{
guint i;
+ GList *l;
/* also do missed state change down to READY */
if (do_save)
@@ -5425,6 +5489,25 @@ gst_play_bin_change_state (GstElement * element, GstStateChange transition)
/* make sure the groups don't perform a state change anymore until we
* enable them again */
groups_set_locked_state (playbin, TRUE);
+
+ /* Remove all non-persistent contexts */
+ GST_OBJECT_LOCK (playbin);
+ for (l = playbin->contexts; l;) {
+ GstContext *context = l->data;
+
+ if (!gst_context_is_persistent (context)) {
+ GList *next;
+
+ gst_context_unref (context);
+
+ next = l->next;
+ playbin->contexts = g_list_delete_link (playbin->contexts, l);
+ l = next;
+ } else {
+ l = l->next;
+ }
+ }
+ GST_OBJECT_UNLOCK (playbin);
break;
}
default: