From ef17d9b6bb220c24623d855cde4331de02af973e Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Tue, 25 Oct 2005 17:41:24 +0000 Subject: [PATCH] gst/gstbin.c: Some doc and debug updates. Original commit message from CVS: * gst/gstbin.c: (message_check), (bin_replace_message), (bin_remove_messages), (is_eos), (gst_bin_add_func), (update_degree), (gst_bin_sort_iterator_next), (bin_bus_handler), (bin_query_duration_init), (bin_query_duration_fold), (bin_query_duration_done), (bin_query_generic_fold), (gst_bin_query): Some doc and debug updates. Cache previously requested query DURATION for speed. invalidate cached duration if element posts a DURATION message. --- ChangeLog | 12 +++++++ gst/gstbin.c | 116 +++++++++++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 118 insertions(+), 10 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7091fee..f8d0b80 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,17 @@ 2005-10-25 Wim Taymans + * gst/gstbin.c: (message_check), (bin_replace_message), + (bin_remove_messages), (is_eos), (gst_bin_add_func), + (update_degree), (gst_bin_sort_iterator_next), (bin_bus_handler), + (bin_query_duration_init), (bin_query_duration_fold), + (bin_query_duration_done), (bin_query_generic_fold), + (gst_bin_query): + Some doc and debug updates. + Cache previously requested query DURATION for speed. invalidate + cached duration if element posts a DURATION message. + +2005-10-25 Wim Taymans + * docs/design/part-TODO.txt: Update TODO. diff --git a/gst/gstbin.c b/gst/gstbin.c index 5b10c1c..2bf8e2d 100644 --- a/gst/gstbin.c +++ b/gst/gstbin.c @@ -52,6 +52,35 @@ * bin. Likewise the "element_removed" signal is fired whenever an element is * removed from the bin. * + * A GstBin internally interceps all #GstMessage posted by its children and + * implements the following default behaviour for each of them. + * + * GST_MESSAGE_EOS: This message is only posted by sinks + * in the PLAYING state. If all sinks posted the EOS message, this bin + * will post and EOS message upwards. + * + * GST_MESSAGE_SEGMENT_START: just collected and never forwarded upwards. + * The messages are used to decide when all elements have completed playback + * of their segment. + * + * GST_MESSAGE_SEGMENT_DONE: Is posted by GstBin when all elements that posted + * a SEGMENT_START have posted a SEGMENT_DONE. + * + * OTHERS: posted upwards. + * + * A GstBin implements the following default behaviour for answering to a + * #GstQuery: + * + * GST_QUERY_DURATION: If the query has been asked before with the same + * format, use the cached previous value. If no previous value + * was cached, the query is sent to all sink elements in the bin + * and the MAXIMUM of all values is returned and cached. If no + * sinks are available in the bin, the query fails. + * + * OTHERS: the query is forwarded to all sink elements, the result of the + * first sink that answers the query successfully is returned. If + * no sink is in the bin, the query fails. + * * gst_object_unref() is used to destroy the bin. */ @@ -1708,6 +1737,31 @@ gst_bin_recalc_func (GstBin * bin, gpointer data) gst_object_unref (bin); } +/* handle child messages: + * + * GST_MESSAGE_EOS: This message is only posted by sinks + * in the PLAYING state. If all sinks posted the EOS message, post + * one upwards. + * + * GST_MESSAGE_STATE_DIRTY: if we are the toplevel bin we do a state + * recalc. If we are not toplevel (we have a parent) we just post + * the message upwards. + * + * GST_MESSAGE_SEGMENT_START: just collect, never forward upwards. If an + * element posts segment_start twice, only the last message is kept. + * + * GST_MESSAGE_SEGMENT_DONE: replace SEGMENT_START message from same poster + * with the segment_done message. If there are no more segment_start + * messages, post segment_done message upwards. + * + * GST_MESSAGE_DURATION: remove all previously cached duration messages. + * Whenever someone performs a duration query on the bin, we store the + * result so we can answer it quicker the next time. Any element that + * changes its duration marks our cached values invalid. + * This message is also posted upwards. + * + * OTHER: post upwards. + */ static GstBusSyncReply bin_bus_handler (GstBus * bus, GstMessage * message, GstBin * bin) { @@ -1878,6 +1932,12 @@ bin_query_duration_done (GstBin * bin, QueryFold * fold) gst_query_set_duration (fold->query, format, fold->max); GST_DEBUG_OBJECT (bin, "max duration %" G_GINT64_FORMAT, fold->max); + + /* and cache now */ + GST_LOCK (bin); + bin->messages = g_list_prepend (bin->messages, + gst_message_new_duration (GST_OBJECT_CAST (bin), format, fold->max)); + GST_UNLOCK (bin); } /* generic fold, return first valid result */ @@ -1888,7 +1948,7 @@ bin_query_generic_fold (GstElement * item, GValue * ret, QueryFold * fold) if ((res = gst_element_query (item, fold->query))) { g_value_set_boolean (ret, TRUE); - GST_DEBUG_OBJECT (item, "answered query"); + GST_DEBUG_OBJECT (item, "answered query %p", fold->query); } /* and stop as soon as we have a valid result */ @@ -1907,24 +1967,59 @@ gst_bin_query (GstElement * element, GstQuery * query) QueryFold fold_data; GValue ret = { 0 }; - fold_data.query = query; - - g_value_init (&ret, G_TYPE_BOOLEAN); - g_value_set_boolean (&ret, FALSE); - switch (GST_QUERY_TYPE (query)) { case GST_QUERY_DURATION: + { + GList *cached; + GstFormat qformat; + + gst_query_parse_duration (query, &qformat, NULL); + + /* find cached duration query */ + GST_LOCK (bin); + for (cached = bin->messages; cached; cached = g_list_next (cached)) { + GstMessage *message = (GstMessage *) cached->data; + + if (GST_MESSAGE_TYPE (message) == GST_MESSAGE_DURATION && + GST_MESSAGE_SRC (message) == GST_OBJECT_CAST (bin)) { + GstFormat format; + gint64 duration; + + gst_message_parse_duration (message, &format, &duration); + + /* if cached same format, copy duration in query result */ + if (format == qformat) { + GST_DEBUG_OBJECT (bin, "return cached duration %" G_GINT64_FORMAT, + duration); + GST_UNLOCK (bin); + + + gst_query_set_duration (query, qformat, duration); + res = TRUE; + goto exit; + } + } + } + GST_UNLOCK (bin); + fold_func = (GstIteratorFoldFunction) bin_query_duration_fold; fold_init = bin_query_duration_init; fold_done = bin_query_duration_done; break; + } default: fold_func = (GstIteratorFoldFunction) bin_query_generic_fold; break; } + fold_data.query = query; + + g_value_init (&ret, G_TYPE_BOOLEAN); + g_value_set_boolean (&ret, FALSE); + iter = gst_bin_iterate_sinks (bin); - GST_DEBUG_OBJECT (bin, "Sending query to sink children"); + GST_DEBUG_OBJECT (bin, "Sending query %p (type %d) to sink children", + query, GST_QUERY_TYPE (query)); if (fold_init) fold_init (bin, &fold_data); @@ -1943,9 +2038,9 @@ gst_bin_query (GstElement * element, GstQuery * query) break; case GST_ITERATOR_OK: case GST_ITERATOR_DONE: - if (fold_done) - fold_done (bin, &fold_data); res = g_value_get_boolean (&ret); + if (fold_done != NULL && res) + fold_done (bin, &fold_data); goto done; default: res = FALSE; @@ -1955,7 +2050,8 @@ gst_bin_query (GstElement * element, GstQuery * query) done: gst_iterator_free (iter); - GST_DEBUG_OBJECT (bin, "query result %d", res); +exit: + GST_DEBUG_OBJECT (bin, "query %p result %d", query, res); return res; } -- 2.7.4