diff options
Diffstat (limited to 'gst/playback/gstplaybin2.c')
-rw-r--r-- | gst/playback/gstplaybin2.c | 95 |
1 files changed, 85 insertions, 10 deletions
diff --git a/gst/playback/gstplaybin2.c b/gst/playback/gstplaybin2.c index b9feb99..49565c8 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 @@ -1185,8 +1187,8 @@ gst_play_bin_class_init (GstPlayBinClass * klass) * If @caps is %NULL, no conversion will be performed and this function is * equivalent to the #GstPlayBin::frame property. * - * Returns: a #GstBuffer of the current video frame converted to #caps. - * The caps on the buffer will describe the final layout of the buffer data. + * Returns: a #GstSample of the current video frame converted to #caps. + * The caps on the sample will describe the final layout of the buffer data. * %NULL is returned when no current buffer can be retrieved or when the * conversion failed. */ @@ -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); } @@ -4096,7 +4159,6 @@ activate_sink (GstPlayBin * playbin, GstElement * sink, gboolean * activated) GstBus *bus = NULL; GstStateChangeReturn sret; gboolean ret = FALSE; - GstContext *context; if (activated) *activated = FALSE; @@ -4109,13 +4171,6 @@ activate_sink (GstPlayBin * playbin, GstElement * sink, gboolean * activated) goto done; } - /* Proxy the playbin context to the sink, just in case */ - context = gst_element_get_context (GST_ELEMENT_CAST (playbin)); - if (context) { - gst_element_set_context (sink, context); - gst_context_unref (context); - } - if (!GST_OBJECT_PARENT (sink)) { bus = gst_bus_new (); gst_bus_set_sync_handler (bus, @@ -5387,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) @@ -5433,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: |