From c5e2202f207c5a0e8747196e87162a2ef28f648f Mon Sep 17 00:00:00 2001 From: Andy Wingo Date: Wed, 17 Aug 2005 16:33:27 +0000 Subject: [PATCH] gst/base/gstbasetransform.c: Debug changes. Original commit message from CVS: 2005-08-17 Andy Wingo * gst/base/gstbasetransform.c: Debug changes. * gst/gstutils.h: * gst/gstutils.c (gst_bin_watch_for_state_change): Add function to ensure bins post state change messages. A bit of a hack but I can't think of a way to avoid it. * check/gst/gstbin.c (test_watch_for_state_change): Added test. --- ChangeLog | 11 +++++++ check/gst/gstbin.c | 63 ++++++++++++++++++++++++++++++++++++++++ gst/base/gstbasetransform.c | 6 ++-- gst/gstbin.c | 1 + gst/gstutils.c | 46 +++++++++++++++++++++++++++++ gst/gstutils.h | 1 + libs/gst/base/gstbasetransform.c | 6 ++-- tests/check/gst/gstbin.c | 63 ++++++++++++++++++++++++++++++++++++++++ 8 files changed, 189 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index 70f6ed7..00661f3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2005-08-17 Andy Wingo + + * gst/base/gstbasetransform.c: Debug changes. + + * gst/gstutils.h: + * gst/gstutils.c (gst_bin_watch_for_state_change): Add function to + ensure bins post state change messages. A bit of a hack but I can't + think of a way to avoid it. + + * check/gst/gstbin.c (test_watch_for_state_change): Added test. + 2005-08-16 Andy Wingo * gst/base/gstadapter.h: diff --git a/check/gst/gstbin.c b/check/gst/gstbin.c index 0fe0814..bf41dc0 100644 --- a/check/gst/gstbin.c +++ b/check/gst/gstbin.c @@ -270,6 +270,68 @@ GST_START_TEST (test_message_state_changed_children) GST_END_TEST; +GST_START_TEST (test_watch_for_state_change) +{ + GstElement *src, *sink, *bin; + GstBus *bus; + + bin = gst_element_factory_make ("bin", NULL); + fail_unless (bin != NULL, "Could not create bin"); + + src = gst_element_factory_make ("fakesrc", NULL); + fail_if (src == NULL, "Could not create fakesrc"); + sink = gst_element_factory_make ("fakesink", NULL); + fail_if (sink == NULL, "Could not create fakesink"); + + gst_bin_add (GST_BIN (bin), sink); + gst_bin_add (GST_BIN (bin), src); + + fail_unless (gst_element_link (src, sink), "could not link src and sink"); + + bus = GST_ELEMENT_BUS (bin); + + /* change state, spawning two times three messages, minus one async */ + fail_unless (gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PAUSED) + == GST_STATE_ASYNC); + + pop_messages (bus, 5); + + fail_unless (gst_bus_have_pending (bus) == FALSE, + "Unexpected messages on bus"); + + gst_bin_watch_for_state_change (GST_BIN (bin)); + + /* should get the bin's state change message now */ + pop_messages (bus, 1); + + fail_unless (gst_bus_have_pending (bus) == FALSE, + "Unexpected messages on bus"); + + fail_unless (gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PLAYING) + == GST_STATE_SUCCESS); + + pop_messages (bus, 3); + + /* this one might return either SUCCESS or ASYNC, likely SUCCESS */ + gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PAUSED); + + gst_bin_watch_for_state_change (GST_BIN (bin)); + + pop_messages (bus, 3); + + fail_unless (gst_bus_have_pending (bus) == FALSE, + "Unexpected messages on bus"); + + /* setting bin to NULL flushes the bus automatically */ + fail_unless (gst_element_set_state (GST_ELEMENT (bin), GST_STATE_NULL) + == GST_STATE_SUCCESS); + + /* clean up */ + gst_object_unref (bin); +} + +GST_END_TEST; + /* adding an element with linked pads to a bin unlinks the * pads */ GST_START_TEST (test_add_linked) @@ -331,6 +393,7 @@ gst_bin_suite (void) tcase_add_test (tc_chain, test_message_state_changed); tcase_add_test (tc_chain, test_message_state_changed_child); tcase_add_test (tc_chain, test_message_state_changed_children); + tcase_add_test (tc_chain, test_watch_for_state_change); tcase_add_test (tc_chain, test_add_linked); return s; diff --git a/gst/base/gstbasetransform.c b/gst/base/gstbasetransform.c index 3dea71c..aa86771 100644 --- a/gst/base/gstbasetransform.c +++ b/gst/base/gstbasetransform.c @@ -215,8 +215,6 @@ gst_base_transform_transform_caps (GstBaseTransform * trans, GstPad * pad, klass = GST_BASE_TRANSFORM_GET_CLASS (trans); - GST_DEBUG_OBJECT (trans, "from: %" GST_PTR_FORMAT, caps); - /* if there is a custom transform function, use this */ if (klass->transform_caps) { GstCaps *temp; @@ -230,10 +228,10 @@ gst_base_transform_transform_caps (GstBaseTransform * trans, GstPad * pad, GstCaps *nth; nth = gst_caps_copy_nth (caps, i); - GST_DEBUG_OBJECT (trans, " from: %" GST_PTR_FORMAT, nth); + GST_DEBUG_OBJECT (trans, "from[%d]: %" GST_PTR_FORMAT, i, nth); temp = klass->transform_caps (trans, pad, nth); gst_caps_unref (nth); - GST_DEBUG_OBJECT (trans, " to : %" GST_PTR_FORMAT, temp); + GST_DEBUG_OBJECT (trans, " to[%d]: %" GST_PTR_FORMAT, i, temp); gst_caps_append (ret, temp); } diff --git a/gst/gstbin.c b/gst/gstbin.c index bbb9c8e..4119fb1 100644 --- a/gst/gstbin.c +++ b/gst/gstbin.c @@ -1073,6 +1073,7 @@ clear_queue (GQueue * queue, gboolean unref) if (unref) gst_object_unref (p); } + static void remove_all_from_queue (GQueue * queue, gpointer elem, gboolean unref) { diff --git a/gst/gstutils.c b/gst/gstutils.c index cf7d6d0..90234d2 100644 --- a/gst/gstutils.c +++ b/gst/gstutils.c @@ -1786,6 +1786,52 @@ gst_bin_remove_many (GstBin * bin, GstElement * element_1, ...) } static void +get_state_func (GstElement * element, gpointer unused) +{ + GstElementStateReturn ret = GST_STATE_ASYNC; + + GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, + "new thread waiting on state change"); + + /* wait indefinitely */ + while (ret == GST_STATE_ASYNC) + ret = gst_element_get_state (element, NULL, NULL, NULL); + + gst_object_unref (element); +} + +/** + * gst_bin_watch_for_state_change: + * @bin: the bin to watch for state changes + * + * Spawns a thread calling gst_element_get_state on @bin with infinite timeout. + * + * In practice this is done because if a bin returns GST_STATE_ASYNC from a + * state change it will not commit its state until someone calls + * gst_element_get_state on it. Thus having another thread checking the bin's + * state will ensure that a state-changed message gets posted on the bus + * eventually. + * + * This function is admittedly a bit of a hack. Bins should always post + * messages. However this behavior was broken out into this function to avoid + * spawning threads when scrubbing, when the bin's state is changing quickly and + * asynchronously. + */ +void +gst_bin_watch_for_state_change (GstBin * bin) +{ + static GThreadPool *pool = NULL; + static GStaticMutex mutex = G_STATIC_MUTEX_INIT; + + g_static_mutex_lock (&mutex); + if (pool == NULL) + pool = g_thread_pool_new ((GFunc) get_state_func, NULL, -1, FALSE, NULL); + g_static_mutex_unlock (&mutex); + + g_thread_pool_push (pool, gst_object_ref (bin), NULL); +} + +static void gst_element_populate_std_props (GObjectClass * klass, const gchar * prop_name, guint arg_id, GParamFlags flags) { diff --git a/gst/gstutils.h b/gst/gstutils.h index 3e21b9f..fe68681 100644 --- a/gst/gstutils.h +++ b/gst/gstutils.h @@ -302,6 +302,7 @@ gboolean gst_pad_query_convert (GstPad *pad, GstFormat /* bin functions */ void gst_bin_add_many (GstBin *bin, GstElement *element_1, ...); void gst_bin_remove_many (GstBin *bin, GstElement *element_1, ...); +void gst_bin_watch_for_state_change (GstBin *bin); /* buffer functions */ GstBuffer * gst_buffer_merge (GstBuffer * buf1, GstBuffer * buf2); diff --git a/libs/gst/base/gstbasetransform.c b/libs/gst/base/gstbasetransform.c index 3dea71c..aa86771 100644 --- a/libs/gst/base/gstbasetransform.c +++ b/libs/gst/base/gstbasetransform.c @@ -215,8 +215,6 @@ gst_base_transform_transform_caps (GstBaseTransform * trans, GstPad * pad, klass = GST_BASE_TRANSFORM_GET_CLASS (trans); - GST_DEBUG_OBJECT (trans, "from: %" GST_PTR_FORMAT, caps); - /* if there is a custom transform function, use this */ if (klass->transform_caps) { GstCaps *temp; @@ -230,10 +228,10 @@ gst_base_transform_transform_caps (GstBaseTransform * trans, GstPad * pad, GstCaps *nth; nth = gst_caps_copy_nth (caps, i); - GST_DEBUG_OBJECT (trans, " from: %" GST_PTR_FORMAT, nth); + GST_DEBUG_OBJECT (trans, "from[%d]: %" GST_PTR_FORMAT, i, nth); temp = klass->transform_caps (trans, pad, nth); gst_caps_unref (nth); - GST_DEBUG_OBJECT (trans, " to : %" GST_PTR_FORMAT, temp); + GST_DEBUG_OBJECT (trans, " to[%d]: %" GST_PTR_FORMAT, i, temp); gst_caps_append (ret, temp); } diff --git a/tests/check/gst/gstbin.c b/tests/check/gst/gstbin.c index 0fe0814..bf41dc0 100644 --- a/tests/check/gst/gstbin.c +++ b/tests/check/gst/gstbin.c @@ -270,6 +270,68 @@ GST_START_TEST (test_message_state_changed_children) GST_END_TEST; +GST_START_TEST (test_watch_for_state_change) +{ + GstElement *src, *sink, *bin; + GstBus *bus; + + bin = gst_element_factory_make ("bin", NULL); + fail_unless (bin != NULL, "Could not create bin"); + + src = gst_element_factory_make ("fakesrc", NULL); + fail_if (src == NULL, "Could not create fakesrc"); + sink = gst_element_factory_make ("fakesink", NULL); + fail_if (sink == NULL, "Could not create fakesink"); + + gst_bin_add (GST_BIN (bin), sink); + gst_bin_add (GST_BIN (bin), src); + + fail_unless (gst_element_link (src, sink), "could not link src and sink"); + + bus = GST_ELEMENT_BUS (bin); + + /* change state, spawning two times three messages, minus one async */ + fail_unless (gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PAUSED) + == GST_STATE_ASYNC); + + pop_messages (bus, 5); + + fail_unless (gst_bus_have_pending (bus) == FALSE, + "Unexpected messages on bus"); + + gst_bin_watch_for_state_change (GST_BIN (bin)); + + /* should get the bin's state change message now */ + pop_messages (bus, 1); + + fail_unless (gst_bus_have_pending (bus) == FALSE, + "Unexpected messages on bus"); + + fail_unless (gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PLAYING) + == GST_STATE_SUCCESS); + + pop_messages (bus, 3); + + /* this one might return either SUCCESS or ASYNC, likely SUCCESS */ + gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PAUSED); + + gst_bin_watch_for_state_change (GST_BIN (bin)); + + pop_messages (bus, 3); + + fail_unless (gst_bus_have_pending (bus) == FALSE, + "Unexpected messages on bus"); + + /* setting bin to NULL flushes the bus automatically */ + fail_unless (gst_element_set_state (GST_ELEMENT (bin), GST_STATE_NULL) + == GST_STATE_SUCCESS); + + /* clean up */ + gst_object_unref (bin); +} + +GST_END_TEST; + /* adding an element with linked pads to a bin unlinks the * pads */ GST_START_TEST (test_add_linked) @@ -331,6 +393,7 @@ gst_bin_suite (void) tcase_add_test (tc_chain, test_message_state_changed); tcase_add_test (tc_chain, test_message_state_changed_child); tcase_add_test (tc_chain, test_message_state_changed_children); + tcase_add_test (tc_chain, test_watch_for_state_change); tcase_add_test (tc_chain, test_add_linked); return s; -- 2.7.4