diff --git a/ChangeLog b/ChangeLog index a5c71be3b5..8e9b7c2472 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2005-07-09 Thomas Vander Stichele + + * check/gst/gstbin.c: (pop_messages), (GST_START_TEST), + (gst_bin_suite): + add more things to check + * gst/gstbin.c: (gst_bin_change_state), (bin_bus_handler): + * gst/gstelement.c: + more debug + 2005-07-09 Thomas Vander Stichele * check/elements/gstfakesrc.c: (chain_func), (event_func), diff --git a/check/gst/gstbin.c b/check/gst/gstbin.c index ae29928ccd..d6c87a1435 100644 --- a/check/gst/gstbin.c +++ b/check/gst/gstbin.c @@ -22,6 +22,24 @@ #include "../gstcheck.h" +static void +pop_messages (GstBus * bus, int count) +{ + GstMessage *message; + + int i; + + GST_DEBUG ("popping %d messages", count); + for (i = 0; i < count; ++i) { + fail_unless (gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, -1) + == GST_MESSAGE_STATE_CHANGED, "did not get GST_MESSAGE_STATE_CHANGED"); + + message = gst_bus_pop (bus); + gst_message_unref (message); + } + GST_DEBUG ("popped %d messages", count); +} + GST_START_TEST (test_interface) { GstBin *bin, *bin2; @@ -137,11 +155,12 @@ GST_START_TEST (test_message_state_changed_child) bus = GST_ELEMENT_BUS (bin); - /* change state, spawning three messages: - * - first for fakesrc, causing incref on fakesrc - * - then two on bin, causing an incref on the bin */ + /* change state, spawning two messages: + * - first for fakesrc, forwarded to bin's bus, causing incref on fakesrc + * - second for bin, causing an incref on the bin */ GST_DEBUG ("setting bin to READY"); - gst_element_set_state (GST_ELEMENT (bin), GST_STATE_READY); + fail_unless (gst_element_set_state (GST_ELEMENT (bin), GST_STATE_READY) + == GST_STATE_SUCCESS); ASSERT_OBJECT_REFCOUNT (src, "src", 2); ASSERT_OBJECT_REFCOUNT (bin, "bin", 2); @@ -151,6 +170,7 @@ GST_START_TEST (test_message_state_changed_child) == GST_MESSAGE_STATE_CHANGED, "did not get GST_MESSAGE_STATE_CHANGED"); message = gst_bus_pop (bus); + fail_unless (message->src == GST_OBJECT (src)); gst_message_unref (message); ASSERT_OBJECT_REFCOUNT (src, "src", 1); @@ -161,6 +181,7 @@ GST_START_TEST (test_message_state_changed_child) == GST_MESSAGE_STATE_CHANGED, "did not get GST_MESSAGE_STATE_CHANGED"); message = gst_bus_pop (bus); + fail_unless (message->src == GST_OBJECT (bin)); gst_message_unref (message); ASSERT_OBJECT_REFCOUNT (src, "src", 1); @@ -172,6 +193,72 @@ GST_START_TEST (test_message_state_changed_child) GST_END_TEST; +GST_START_TEST (test_message_state_changed_children) +{ + GstPipeline *pipeline; + GstElement *src, *sink; + GstBus *bus; + + pipeline = GST_PIPELINE (gst_pipeline_new (NULL)); + fail_unless (pipeline != NULL, "Could not create pipeline"); + ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1); + + src = gst_element_factory_make ("fakesrc", NULL); + fail_if (src == NULL, "Could not create fakesrc"); + gst_bin_add (GST_BIN (pipeline), src); + + sink = gst_element_factory_make ("fakesink", NULL); + fail_if (sink == NULL, "Could not create fakesink"); + gst_bin_add (GST_BIN (pipeline), sink); + + fail_unless (gst_element_link (src, sink), "could not link src and sink"); + + ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1); + ASSERT_OBJECT_REFCOUNT (src, "src", 1); + ASSERT_OBJECT_REFCOUNT (src, "sink", 1); + + bus = GST_ELEMENT_BUS (pipeline); + + /* change state, spawning three times three messages */ + GST_DEBUG ("setting pipeline to PLAYING"); + fail_unless (gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING) + == GST_STATE_SUCCESS); + + pop_messages (bus, 9); + + ASSERT_OBJECT_REFCOUNT (src, "src", 1); + ASSERT_OBJECT_REFCOUNT (sink, "sink", 1); + ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1); + + /* go back to READY, spawning six messages */ + GST_DEBUG ("setting pipeline to READY"); + fail_unless (gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_READY) + == GST_STATE_SUCCESS); + + /* each object is referenced by two messages */ + ASSERT_OBJECT_REFCOUNT (src, "src", 3); + ASSERT_OBJECT_REFCOUNT (sink, "sink", 3); + ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 3); + + pop_messages (bus, 6); + + ASSERT_OBJECT_REFCOUNT (src, "src", 1); + ASSERT_OBJECT_REFCOUNT (sink, "sink", 1); + ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1); + + /* setting pipeline to NULL flushes the bus automatically */ + fail_unless (gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL) + == GST_STATE_SUCCESS); + + ASSERT_OBJECT_REFCOUNT (src, "src", 1); + ASSERT_OBJECT_REFCOUNT (sink, "sink", 1); + ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1); + + /* clean up */ + gst_object_unref (pipeline); +} + +GST_END_TEST; Suite * gst_bin_suite (void) @@ -183,6 +270,7 @@ gst_bin_suite (void) tcase_add_test (tc_chain, test_interface); 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); return s; } diff --git a/gst/gstbin.c b/gst/gstbin.c index 6ade4a263f..c8d840c9b0 100644 --- a/gst/gstbin.c +++ b/gst/gstbin.c @@ -1190,8 +1190,12 @@ restart: } GST_LOCK (bin); - if (G_UNLIKELY (children_cookie != bin->children_cookie)) + if (G_UNLIKELY (children_cookie != bin->children_cookie)) { + /* FIXME: we reffed some children already, are we leaking refcounts + * in that case ? */ + GST_INFO_OBJECT (bin, "bin->children_cookie changed, restarting"); goto restart; + } children = g_list_next (children); } GST_UNLOCK (bin); @@ -1445,12 +1449,14 @@ gst_bin_send_event (GstElement * element, GstEvent * event) static GstBusSyncReply bin_bus_handler (GstBus * bus, GstMessage * message, GstBin * bin) { + GST_DEBUG_OBJECT (bin, "[msg %p] handling child message of type %d from %s", + message, GST_MESSAGE_TYPE (message), + gst_object_get_name (GST_MESSAGE_SRC (message))); /* we don't want messages from the streaming thread while we're doing the * state change. We do want them from the state change functions. */ switch (GST_MESSAGE_TYPE (message)) { case GST_MESSAGE_EOS: - GST_DEBUG_OBJECT (bin, "got EOS message from %s", - gst_object_get_name (GST_MESSAGE_SRC (message))); + GST_DEBUG_OBJECT (bin, "got EOS message"); GST_LOCK (bin->child_bus); bin->eosed = g_list_prepend (bin->eosed, GST_MESSAGE_SRC (message)); @@ -1467,6 +1473,7 @@ bin_bus_handler (GstBus * bus, GstMessage * message, GstBin * bin) break; default: /* Send all other messages upward */ + GST_DEBUG_OBJECT (bin, "posting message upward"); gst_bus_post (GST_ELEMENT (bin)->bus, message); break; } diff --git a/gst/gstelement.c b/gst/gstelement.c index 8fde607ade..ec8b6c9ed1 100644 --- a/gst/gstelement.c +++ b/gst/gstelement.c @@ -1231,7 +1231,7 @@ gst_element_query (GstElement * element, GstQuery * query) * @element: a #GstElement posting the message * @message: a #GstMessage to post * - * Post a message on the elements #GstBus. + * Post a message on the element's #GstBus. * * Returns: TRUE if the message was successfully posted. * diff --git a/tests/check/gst/gstbin.c b/tests/check/gst/gstbin.c index ae29928ccd..d6c87a1435 100644 --- a/tests/check/gst/gstbin.c +++ b/tests/check/gst/gstbin.c @@ -22,6 +22,24 @@ #include "../gstcheck.h" +static void +pop_messages (GstBus * bus, int count) +{ + GstMessage *message; + + int i; + + GST_DEBUG ("popping %d messages", count); + for (i = 0; i < count; ++i) { + fail_unless (gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, -1) + == GST_MESSAGE_STATE_CHANGED, "did not get GST_MESSAGE_STATE_CHANGED"); + + message = gst_bus_pop (bus); + gst_message_unref (message); + } + GST_DEBUG ("popped %d messages", count); +} + GST_START_TEST (test_interface) { GstBin *bin, *bin2; @@ -137,11 +155,12 @@ GST_START_TEST (test_message_state_changed_child) bus = GST_ELEMENT_BUS (bin); - /* change state, spawning three messages: - * - first for fakesrc, causing incref on fakesrc - * - then two on bin, causing an incref on the bin */ + /* change state, spawning two messages: + * - first for fakesrc, forwarded to bin's bus, causing incref on fakesrc + * - second for bin, causing an incref on the bin */ GST_DEBUG ("setting bin to READY"); - gst_element_set_state (GST_ELEMENT (bin), GST_STATE_READY); + fail_unless (gst_element_set_state (GST_ELEMENT (bin), GST_STATE_READY) + == GST_STATE_SUCCESS); ASSERT_OBJECT_REFCOUNT (src, "src", 2); ASSERT_OBJECT_REFCOUNT (bin, "bin", 2); @@ -151,6 +170,7 @@ GST_START_TEST (test_message_state_changed_child) == GST_MESSAGE_STATE_CHANGED, "did not get GST_MESSAGE_STATE_CHANGED"); message = gst_bus_pop (bus); + fail_unless (message->src == GST_OBJECT (src)); gst_message_unref (message); ASSERT_OBJECT_REFCOUNT (src, "src", 1); @@ -161,6 +181,7 @@ GST_START_TEST (test_message_state_changed_child) == GST_MESSAGE_STATE_CHANGED, "did not get GST_MESSAGE_STATE_CHANGED"); message = gst_bus_pop (bus); + fail_unless (message->src == GST_OBJECT (bin)); gst_message_unref (message); ASSERT_OBJECT_REFCOUNT (src, "src", 1); @@ -172,6 +193,72 @@ GST_START_TEST (test_message_state_changed_child) GST_END_TEST; +GST_START_TEST (test_message_state_changed_children) +{ + GstPipeline *pipeline; + GstElement *src, *sink; + GstBus *bus; + + pipeline = GST_PIPELINE (gst_pipeline_new (NULL)); + fail_unless (pipeline != NULL, "Could not create pipeline"); + ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1); + + src = gst_element_factory_make ("fakesrc", NULL); + fail_if (src == NULL, "Could not create fakesrc"); + gst_bin_add (GST_BIN (pipeline), src); + + sink = gst_element_factory_make ("fakesink", NULL); + fail_if (sink == NULL, "Could not create fakesink"); + gst_bin_add (GST_BIN (pipeline), sink); + + fail_unless (gst_element_link (src, sink), "could not link src and sink"); + + ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1); + ASSERT_OBJECT_REFCOUNT (src, "src", 1); + ASSERT_OBJECT_REFCOUNT (src, "sink", 1); + + bus = GST_ELEMENT_BUS (pipeline); + + /* change state, spawning three times three messages */ + GST_DEBUG ("setting pipeline to PLAYING"); + fail_unless (gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING) + == GST_STATE_SUCCESS); + + pop_messages (bus, 9); + + ASSERT_OBJECT_REFCOUNT (src, "src", 1); + ASSERT_OBJECT_REFCOUNT (sink, "sink", 1); + ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1); + + /* go back to READY, spawning six messages */ + GST_DEBUG ("setting pipeline to READY"); + fail_unless (gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_READY) + == GST_STATE_SUCCESS); + + /* each object is referenced by two messages */ + ASSERT_OBJECT_REFCOUNT (src, "src", 3); + ASSERT_OBJECT_REFCOUNT (sink, "sink", 3); + ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 3); + + pop_messages (bus, 6); + + ASSERT_OBJECT_REFCOUNT (src, "src", 1); + ASSERT_OBJECT_REFCOUNT (sink, "sink", 1); + ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1); + + /* setting pipeline to NULL flushes the bus automatically */ + fail_unless (gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL) + == GST_STATE_SUCCESS); + + ASSERT_OBJECT_REFCOUNT (src, "src", 1); + ASSERT_OBJECT_REFCOUNT (sink, "sink", 1); + ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1); + + /* clean up */ + gst_object_unref (pipeline); +} + +GST_END_TEST; Suite * gst_bin_suite (void) @@ -183,6 +270,7 @@ gst_bin_suite (void) tcase_add_test (tc_chain, test_interface); 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); return s; }