gstreamer/testsuite/states/bin.c
Benjamin Otte 28bf20507e 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
2004-07-21 21:28:58 +00:00

151 lines
4.9 KiB
C

/* 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;
}