diff options
author | Benjamin Otte <otte@gnome.org> | 2004-07-21 21:28:58 +0000 |
---|---|---|
committer | Benjamin Otte <otte@gnome.org> | 2004-07-21 21:28:58 +0000 |
commit | 28bf20507ec4c4877de1ab46dd518d8ad42013b8 (patch) | |
tree | 912d4b1c2b6b3d77791b88b4ace3bc883d54fad8 /testsuite/states | |
parent | d8c591b902343eef70f36ebc4cfaa30b69f6de3c (diff) |
gst/gstbin.c: make state changes work correctly and reentrant (so removing elements from bins during state changes of...
Original commit message from CVS:
* gst/gstbin.c: (gst_bin_get_type), (gst_bin_class_init),
(gst_bin_fix_state), (gst_bin_add_func), (gst_bin_remove_func),
(gst_bin_child_state_change_func), (set_kid_state_func),
(gst_bin_set_state), (gst_bin_change_state_norecurse):
make state changes work correctly and reentrant (so removing
elements from bins during state changes of bins doesn't cause
segfaults or even wrong states)
add debugging category and debugging output to print children states
* gst/gstbin.c: (gst_bin_dispose):
add some assertion checks
* gst/gstbin.h:
* gst/gstbin.c: (gst_bin_sync_children_state):
deprecate this function - it just does gst_bin_set_state (bin,
GST_STATE (bin))
* testsuite/threads/queue.c: (main):
don't use gst_bin_sync_children_state anymore
* testsuite/states/Makefile.am:
* testsuite/states/bin.c:
test that the state changes of bins work as expected
* gst/gstthread.c: (gst_thread_class_init), (gst_thread_set_state):
some adjustments to change states correctly, too
* gst/gstthread.c: (gst_thread_change_state):
don't enable/disable "threadsafe" properties, they're unused and
cause random segfaults
* testsuite/threads/Makefile.am:
the queue check randomly passes now, ignore it
Diffstat (limited to 'testsuite/states')
-rw-r--r-- | testsuite/states/Makefile.am | 2 | ||||
-rw-r--r-- | testsuite/states/bin.c | 150 |
2 files changed, 151 insertions, 1 deletions
diff --git a/testsuite/states/Makefile.am b/testsuite/states/Makefile.am index ac1b2ab81..def43ba40 100644 --- a/testsuite/states/Makefile.am +++ b/testsuite/states/Makefile.am @@ -1,6 +1,6 @@ include ../Rules -tests_pass = locked parent +tests_pass = locked parent bin tests_fail = tests_ignore = diff --git a/testsuite/states/bin.c b/testsuite/states/bin.c new file mode 100644 index 000000000..65cb308ed --- /dev/null +++ b/testsuite/states/bin.c @@ -0,0 +1,150 @@ +/* GStreamer + * Copyright (C) <2004> Benjamin Otte <otte@gnome.org> + * + * bin.c: + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include <gst/gst.h> + +#define RETURN_NAME(x) ((x) == GST_STATE_SUCCESS ? "GST_STATE_SUCCESS" : \ + (x) == GST_STATE_ASYNC ? "GST_STATE_ASYNC" : "GST_STATE_FAILURE") +static void +assert_state (GstElement * element, GstElementState state) +{ + if (gst_element_get_state (element) != state) { + g_printerr ("%s: state is %s instead of %s", + GST_OBJECT_NAME (element), + gst_element_state_get_name (GST_STATE (element)), + gst_element_state_get_name (state)); + g_assert_not_reached (); + } +} + +static void +assert_state_change (GstElement * element, GstElementState new_state, + GstElementStateReturn result, GstElementState result_state) +{ + GstElementStateReturn ret = gst_element_set_state (element, new_state); + + if (ret != result) { + g_printerr ("%s: change state to %s returned %s instead of %s", + GST_OBJECT_NAME (element), gst_element_state_get_name (new_state), + RETURN_NAME (ret), RETURN_NAME (result)); + g_assert_not_reached (); + } + assert_state (element, result_state); +} + +static void +empty_bin (gchar * bin_name) +{ + /* Test the behaviour of empty bins. Since a bin's state is always the state + * of its highest child, nothing should change in here + * Return values when no error occured but the state didn't change should be + * GST_STATE_ASYNC */ + GstElement *bin = gst_element_factory_make (bin_name, NULL); + + /* obvious */ + assert_state (bin, GST_STATE_NULL); + /* see above */ + assert_state_change (bin, GST_STATE_READY, GST_STATE_ASYNC, GST_STATE_NULL); + assert_state_change (bin, GST_STATE_PAUSED, GST_STATE_ASYNC, GST_STATE_NULL); + assert_state_change (bin, GST_STATE_PLAYING, GST_STATE_ASYNC, GST_STATE_NULL); +} + +static void +test_adding_one_element (GstElement * bin) +{ + /* Tests behaviour of adding/removing elements to/from bins. It makes sure the + * state of the bin is always the highest of all contained children. */ + GstElementState test_states[] = { GST_STATE_READY, GST_STATE_PAUSED, + GST_STATE_PLAYING, GST_STATE_PAUSED, GST_STATE_READY, GST_STATE_NULL + }; + GstElement *test = gst_element_factory_make ("identity", NULL); + GstElementState bin_state = gst_element_get_state (bin); + gint i; + + g_assert (test); + gst_object_ref (GST_OBJECT (test)); + assert_state (test, GST_STATE_NULL); + gst_bin_add (GST_BIN (bin), test); + assert_state (bin, MAX (bin_state, GST_STATE_NULL)); + for (i = 0; i < G_N_ELEMENTS (test_states); i++) { + GstElementState test_state = test_states[i]; + + assert_state_change (test, test_state, GST_STATE_SUCCESS, test_state); + assert_state (test, test_state); + assert_state (bin, MAX (bin_state, test_state)); + gst_bin_remove (GST_BIN (bin), test); + assert_state (bin, bin_state); + gst_bin_add (GST_BIN (bin), test); + assert_state (test, test_state); + assert_state (bin, MAX (bin_state, test_state)); + } + gst_bin_remove (GST_BIN (bin), test); + gst_object_unref (GST_OBJECT (test)); + assert_state (bin, bin_state); +} + +static void +test_element_in_bin (gchar * bin_name) +{ + gint i; + GstElementState test_states[] = { GST_STATE_NULL, GST_STATE_READY, + GST_STATE_PAUSED, GST_STATE_PLAYING + }; + GstElement *id, *bin = gst_element_factory_make (bin_name, NULL); + + g_assert (bin); + + /* test correct behaviour in empty bins */ + test_adding_one_element (bin); + + id = gst_element_factory_make ("identity", NULL); + g_assert (id); + assert_state (id, GST_STATE_NULL); + gst_bin_add (GST_BIN (bin), id); + /* test correct behaviour in bins which contain elements in various states */ + for (i = 0; i < G_N_ELEMENTS (test_states); i++) { + GstElementState test_state = test_states[i]; + + assert_state_change (bin, test_state, GST_STATE_SUCCESS, test_state); + assert_state (id, test_state); + test_adding_one_element (bin); + } + + gst_object_unref (GST_OBJECT (bin)); +} + +gint +main (gint argc, gchar * argv[]) +{ + gst_init (&argc, &argv); + + /* test behaviour of empty bins */ + empty_bin ("bin"); + empty_bin ("thread"); + empty_bin ("pipeline"); + + /* test behaviour of adding/removing elements to/from all core bin types */ + test_element_in_bin ("bin"); + test_element_in_bin ("thread"); + test_element_in_bin ("pipeline"); + + return 0; +} |