From: <tho...@fr...> - 2004-07-29 20:34:04
|
CVS Root: /cvs/gstreamer Module: gstreamer Changes by: thomasvs Date: Fri Jul 30 2004 06:34:01 EST Log message: revert state change changes as agreed so we can rework them gradually Modified files: . : ChangeLog gst : gstbin.c gstbin.h gstthread.c testsuite/states: Makefile.am Links: http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gstreamer/ChangeLog.diff?r1=1.742&r2=1.743 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gstreamer/gst/gstbin.c.diff?r1=1.200&r2=1.201 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gstreamer/gst/gstbin.h.diff?r1=1.64&r2=1.65 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gstreamer/gst/gstthread.c.diff?r1=1.131&r2=1.132 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gstreamer/testsuite/states/Makefile.am.diff?r1=1.7&r2=1.8 ====Begin Diffs==== Index: ChangeLog =================================================================== RCS file: /cvs/gstreamer/gstreamer/ChangeLog,v retrieving revision 1.742 retrieving revision 1.743 diff -u -d -r1.742 -r1.743 --- ChangeLog 29 Jul 2004 18:51:49 -0000 1.742 +++ ChangeLog 29 Jul 2004 20:33:47 -0000 1.743 @@ -1,3 +1,18 @@ +2004-07-29 Thomas Vander Stichele <thomas at apestaart dot org> + + * gst/gstbin.c: (gst_bin_get_type), (gst_bin_class_init), + (gst_bin_add_func), (gst_bin_remove_func), + (gst_bin_child_state_change), (gst_bin_child_state_change_func), + (set_kid_state_func), (gst_bin_change_state), (gst_bin_set_state), + (gst_bin_change_state_norecurse), (gst_bin_dispose), + (gst_bin_sync_children_state): + * gst/gstbin.h: + * gst/gstthread.c: (gst_thread_class_init), (gst_thread_release), + (gst_thread_change_state): + * testsuite/states/Makefile.am: + revert state change patches as agreed so we can rework them + gradually 2004-07-29 Benjamin Otte <ot...@gn...> * libs/gst/control/Makefile.am: Index: gstbin.c RCS file: /cvs/gstreamer/gstreamer/gst/gstbin.c,v retrieving revision 1.200 retrieving revision 1.201 diff -u -d -r1.200 -r1.201 --- gstbin.c 28 Jul 2004 20:12:48 -0000 1.200 +++ gstbin.c 29 Jul 2004 20:33:48 -0000 1.201 @@ -34,14 +34,6 @@ #include "gstindex.h" #include "gstutils.h" -GST_DEBUG_CATEGORY_STATIC (bin_debug); -#define GST_CAT_DEFAULT bin_debug -#define GST_LOG_BIN_CONTENTS(bin, text) GST_LOG_OBJECT ((bin), \ - text ": %d elements: %u PLAYING, %u PAUSED, %u READY, %u NULL, own state: %s", \ - (bin)->numchildren, (guint) (bin)->child_states[3], \ - (guint) (bin)->child_states[2], (bin)->child_states[1], \ - (bin)->child_states[0], gst_element_state_get_name (GST_STATE (bin))) - static GstElementDetails gst_bin_details = GST_ELEMENT_DETAILS ("Generic bin", "Generic/Bin", "Simple container object", @@ -54,6 +46,7 @@ static void gst_bin_dispose (GObject * object); +static GstElementStateReturn gst_bin_change_state (GstElement * element); static GstElementStateReturn gst_bin_change_state_norecurse (GstBin * bin); #ifndef GST_DISABLE_INDEX @@ -123,8 +116,6 @@ _gst_bin_type = g_type_register_static (GST_TYPE_ELEMENT, "GstBin", &bin_info, 0); - GST_DEBUG_CATEGORY_INIT (bin_debug, "bin", GST_DEBUG_BOLD, - "debugging info for the 'bin' container element"); } return _gst_bin_type; } @@ -172,6 +163,7 @@ GST_DEBUG_FUNCPTR (gst_bin_restore_thyself); #endif + gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_bin_change_state); gstelement_class->set_state = GST_DEBUG_FUNCPTR (gst_bin_set_state); gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_bin_set_index); @@ -449,34 +441,6 @@ va_end (args); -/* after adding or removing elements, we need to fix the state of the bin - * in a reentrant way. This is done here */ -static void -gst_bin_fix_state (GstBin * bin) -{ - gint i; - GstElementState desired; - while (TRUE) { - /* find the highest child state */ - for (i = GST_NUM_STATES - 1; i > 0; i--) { - if (bin->child_states[i] > 0) - break; - } - g_assert (i < GST_NUM_STATES && i >= 0); - desired = 1 << i; - if (desired == GST_STATE (bin)) { - break; - } else if (desired < GST_STATE (bin)) { - GST_STATE_PENDING (bin) = GST_STATE (bin) >> 1; - } else { /* if (desired > GST_STATE (bin)) */ - GST_STATE_PENDING (bin) = GST_STATE (bin) << 1; - /* this part is reentrant */ - gst_bin_change_state_norecurse (bin); - } -} static void gst_bin_add_func (GstBin * bin, GstElement * element) { @@ -495,14 +459,15 @@ return; - /* ref to guard unrefs in callbacks */ - gst_object_ref (GST_OBJECT (bin)); - gst_object_ref (GST_OBJECT (element)); + if (GST_STATE (element) > GST_STATE (bin)) { + GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin, + "setting state to receive element \"%s\"", GST_OBJECT_NAME (element)); + gst_element_set_state ((GstElement *) bin, GST_STATE (element)); + } /* set the element's parent and add the element to the bin's list of children */ gst_object_set_parent (GST_OBJECT (element), GST_OBJECT (bin)); - GST_LOG_BIN_CONTENTS (bin, "before adding element"); bin->children = g_list_append (bin->children, element); bin->numchildren++; @@ -520,16 +485,10 @@ gst_bin_set_element_sched (element, sched); - /* check if we need to bump state because a high state element was added */ - gst_bin_fix_state (bin); GST_CAT_DEBUG_OBJECT (GST_CAT_PARENTAGE, bin, "added element \"%s\"", GST_OBJECT_NAME (element)); - GST_LOG_BIN_CONTENTS (bin, "after adding element"); g_signal_emit (G_OBJECT (bin), gst_bin_signals[ELEMENT_ADDED], 0, element); - /* we reffed above */ - gst_object_unref (GST_OBJECT (element)); - gst_object_unref (GST_OBJECT (bin)); /** @@ -578,13 +537,9 @@ /* remove this element from the list of managed elements */ gst_bin_unset_element_sched (element, GST_ELEMENT_SCHED (bin)); - GST_LOG_BIN_CONTENTS (bin, "before removing element"); /* now remove the element from the list of elements */ bin->children = g_list_remove (bin->children, element); bin->numchildren--; @@ -595,22 +550,30 @@ state_idx++; bin->child_states[state_idx]--; - GST_CAT_INFO_OBJECT (GST_CAT_PARENTAGE, bin, - "removed child \"%s\", %d children left", GST_OBJECT_NAME (element), - bin->numchildren); + GST_CAT_INFO_OBJECT (GST_CAT_PARENTAGE, bin, "removed child \"%s\"", + GST_OBJECT_NAME (element)); /* ref as we're going to emit a signal */ gst_object_ref (GST_OBJECT (element)); gst_object_unparent (GST_OBJECT (element)); - /* check the state */ - GST_LOG_BIN_CONTENTS (bin, "after removing element"); + /* if we're down to zero children, force state to NULL */ + while (bin->numchildren == 0 && GST_ELEMENT_SCHED (bin) != NULL && + GST_STATE (bin) > GST_STATE_NULL) { + GstElementState next = GST_STATE (bin) >> 1; + GST_STATE_PENDING (bin) = next; + gst_bin_change_state_norecurse (bin); + if (!GST_STATE (bin) == next) { + g_warning ("bin %s failed state change to %d", GST_ELEMENT_NAME (bin), + next); + break; + } g_signal_emit (G_OBJECT (bin), gst_bin_signals[ELEMENT_REMOVED], 0, element); /* element is really out of our control now */ gst_object_unref (GST_OBJECT (element)); @@ -693,8 +656,7 @@ g_return_if_fail (GST_IS_ELEMENT (child)); GST_CAT_LOG (GST_CAT_STATES, "child %s changed state in bin %s from %s to %s", - GST_ELEMENT_NAME (child) ? GST_ELEMENT_NAME (child) : "(null)", - GST_ELEMENT_NAME (bin) ? GST_ELEMENT_NAME (bin) : "(null)", + GST_ELEMENT_NAME (child), GST_ELEMENT_NAME (bin), gst_element_state_get_name (oldstate), gst_element_state_get_name (newstate)); @@ -722,7 +684,7 @@ while (new >>= 1) new_idx++; - GST_LOG_BIN_CONTENTS (bin, "before child state change"); + GST_LOCK (bin); bin->child_states[old_idx]--; bin->child_states[new_idx]++; @@ -735,17 +697,18 @@ "highest child state is %s, changing bin state accordingly", gst_element_state_get_name (state)); GST_STATE_PENDING (bin) = state; + GST_UNLOCK (bin); gst_bin_change_state_norecurse (bin); if (state != GST_STATE (bin)) { - GST_INFO_OBJECT (bin, "state change in callback %d %d", - state, GST_STATE (bin)); + g_warning ("%s: state change in callback %d %d", + GST_ELEMENT_NAME (bin), state, GST_STATE (bin)); } return; } break; } - GST_LOG_BIN_CONTENTS (bin, "after child state change"); + GST_UNLOCK (bin); typedef gboolean (*GstBinForeachFunc) (GstBin * bin, GstElement * element, @@ -794,12 +757,10 @@ typedef struct - GstElementState intermediate; GstElementState pending; GstElementStateReturn result; SetKidStateData; static int set_kid_state_func (GstBin * bin, GstElement * child, gpointer user_data) @@ -812,49 +773,17 @@ old_child_state = GST_STATE (child); - /* are we moving up or down? */ - if (data->intermediate < data->pending) { - /* up, check if we are already closer to target */ - if (old_child_state >= data->intermediate && - old_child_state < data->pending) { - GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin, - "state of child %s is %s, inbetween intermediate %s and pending %s", - GST_ELEMENT_NAME (child), - gst_element_state_get_name (old_child_state), - gst_element_state_get_name (data->intermediate), - gst_element_state_get_name (data->pending)); - return TRUE; - } else if (data->intermediate > data->pending) { - /* down, check if we are already closer to target */ - if (old_child_state < data->intermediate) { - } else { - /* same state */ - GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin, - "setting final state on child %s, now in %s, going to %s", - GST_ELEMENT_NAME (child), gst_element_state_get_name (old_child_state), - gst_element_state_get_name (data->intermediate)); GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin, - "changing state of child %s from current %s to intermediate %s", + "changing state of child %s from current %s to pending %s", GST_ELEMENT_NAME (child), gst_element_state_get_name (old_child_state), - gst_element_state_get_name (data->intermediate)); + gst_element_state_get_name (data->pending)); - switch (gst_element_set_state (child, data->intermediate)) { + switch (gst_element_set_state (child, data->pending)) { case GST_STATE_FAILURE: GST_CAT_INFO_OBJECT (GST_CAT_STATES, bin, "child '%s' failed to go to state %d(%s)", GST_ELEMENT_NAME (child), - data->intermediate, gst_element_state_get_name (data->intermediate)); + data->pending, gst_element_state_get_name (data->pending)); gst_element_set_state (child, old_child_state); return FALSE; /* error out to the caller */ @@ -863,14 +792,14 @@ "child '%s' is changing state asynchronously", GST_ELEMENT_NAME (child)); + data->result = GST_STATE_ASYNC; return TRUE; case GST_STATE_SUCCESS: GST_CAT_DEBUG (GST_CAT_STATES, "child '%s' changed state to %d(%s) successfully", - GST_ELEMENT_NAME (child), data->intermediate, - gst_element_state_get_name (data->intermediate)); - data->result = GST_STATE_SUCCESS; + GST_ELEMENT_NAME (child), data->pending, + gst_element_state_get_name (data->pending)); default: @@ -879,66 +808,87 @@ -GstElementStateReturn -gst_bin_set_state (GstElement * element, GstElementState state) +static GstElementStateReturn +gst_bin_change_state (GstElement * element) - GstBin *bin = GST_BIN (element); + GstBin *bin; + GstElementStateReturn ret; + GstElementState old_state, pending; SetKidStateData data; - GstElementStateReturn ret = GST_STATE_FAILURE; - GstElementState pending; - /* we start with the state of the bin */ - intermediate = GST_STATE (element); - pending = state; + g_return_val_if_fail (GST_IS_BIN (element), GST_STATE_FAILURE); - GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin, - "setting state of bin %s from current %s to pending %s", - GST_ELEMENT_NAME (element), gst_element_state_get_name (intermediate), + bin = GST_BIN (element); + old_state = GST_STATE (element); + pending = GST_STATE_PENDING (element); + GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element, + "changing state of children from %s to %s", + gst_element_state_get_name (old_state), gst_element_state_get_name (pending)); - do { - data.intermediate = intermediate; - data.pending = pending; - data.result = GST_STATE_ASYNC; + if (pending == GST_STATE_VOID_PENDING) + return GST_STATE_SUCCESS; - "setting state of children to intermediate %s", - gst_element_state_get_name (intermediate)); + data.pending = pending; + data.result = GST_STATE_SUCCESS; + if (!gst_bin_foreach (bin, set_kid_state_func, &data)) { + GST_STATE_PENDING (element) = old_state; + return GST_STATE_FAILURE; + "done changing bin's state from %s to %s, now in %s", + gst_element_state_get_name (pending), + gst_element_state_get_name (GST_STATE (element))); + if (data.result == GST_STATE_ASYNC) + ret = GST_STATE_ASYNC; + else { + /* FIXME: this should have been done by the children already, no? */ + if (parent_class->change_state) { + ret = parent_class->change_state (element); + } else + ret = GST_STATE_SUCCESS; + return ret; +} +GstElementStateReturn +gst_bin_set_state (GstElement * element, GstElementState state) +{ + GstBin *bin = GST_BIN (element); + if (GST_STATE (bin) == state) { + SetKidStateData data; + data.pending = state; + data.result = GST_STATE_SUCCESS; if (!gst_bin_foreach (bin, set_kid_state_func, &data)) { - ret = GST_STATE_FAILURE; - /* break out of the loop after failure */ + return GST_STATE_FAILURE; } else { - ret = data.result; + return data.result; - /* if we have reached the target state, we can stop */ - if (intermediate == pending) - /* move intermediate state closer to target state */ - if (intermediate < pending) - intermediate <<= 1; - else - intermediate >>= 1; + } else { + return GST_CALL_PARENT_WITH_DEFAULT (GST_ELEMENT_CLASS, set_state, (element, + state), GST_STATE_FAILURE); - while (TRUE); - return ret; static GstElementStateReturn gst_bin_change_state_norecurse (GstBin * bin) - GstElementClass *klass; - klass = GST_ELEMENT_GET_CLASS (bin); - g_return_val_if_fail (klass->change_state, GST_STATE_FAILURE); + if (parent_class->change_state) { + GST_CAT_LOG_OBJECT (GST_CAT_STATES, bin, "setting bin's own state"); + ret = parent_class->change_state (GST_ELEMENT (bin)); - GST_CAT_LOG_OBJECT (GST_CAT_STATES, bin, "setting bin's own state"); - return klass->change_state (GST_ELEMENT (bin)); + return ret; + } else @@ -955,10 +905,6 @@ g_assert (bin->children == NULL); g_assert (bin->numchildren == 0); - g_assert (bin->child_states[3] == 0); /* playing */ - g_assert (bin->child_states[2] == 0); /* paused */ - g_assert (bin->child_states[1] == 0); /* ready */ - g_assert (bin->child_states[0] == 0); /* null */ G_OBJECT_CLASS (parent_class)->dispose (object); @@ -1141,10 +1087,40 @@ GstElementStateReturn gst_bin_sync_children_state (GstBin * bin) + GList *children; + GstElement *element; + GstElementState state; + GstElementStateReturn ret = GST_STATE_SUCCESS; g_return_val_if_fail (GST_IS_BIN (bin), GST_STATE_FAILURE); - return gst_element_set_state (GST_ELEMENT (bin), - gst_element_get_state (GST_ELEMENT (bin))); + state = GST_STATE (bin); + children = bin->children; + GST_CAT_INFO (GST_CAT_STATES, + "syncing state of children with bin \"%s\"'s state %s", + GST_ELEMENT_NAME (bin), gst_element_state_get_name (state)); + while (children) { + element = GST_ELEMENT (children->data); + children = children->next; + if (GST_STATE (element) != state) { + switch (gst_element_set_state (element, state)) { + case GST_STATE_SUCCESS: + break; + case GST_STATE_ASYNC: + if (ret == GST_STATE_SUCCESS) + ret = GST_STATE_ASYNC; + case GST_STATE_FAILURE: + ret = GST_STATE_FAILURE; + default: + /* make sure gst_element_set_state never returns this */ + g_assert_not_reached (); + } #ifndef GST_DISABLE_LOADSAVE Index: gstbin.h RCS file: /cvs/gstreamer/gstreamer/gst/gstbin.h,v retrieving revision 1.64 retrieving revision 1.65 diff -u -d -r1.64 -r1.65 --- gstbin.h 21 Jul 2004 21:28:57 -0000 1.64 +++ gstbin.h 29 Jul 2004 20:33:48 -0000 1.65 @@ -63,7 +63,6 @@ gint numchildren; GList *children; -/* FIXME 0.9: important!! make this guint instead of GstElementState */ GstElementState child_states[GST_NUM_STATES]; gpointer _gst_reserved[GST_PADDING]; @@ -111,9 +110,7 @@ GstClock* gst_bin_get_clock (GstBin *bin); void gst_bin_auto_clock (GstBin *bin); -#ifndef GST_DISABLE_DEPRECATED GstElementStateReturn gst_bin_sync_children_state (GstBin *bin); -#endif /* internal */ /* one of our childs signaled a state change */ Index: gstthread.c RCS file: /cvs/gstreamer/gstreamer/gst/gstthread.c,v retrieving revision 1.131 retrieving revision 1.132 diff -u -d -r1.131 -r1.132 --- gstthread.c 28 Jul 2004 10:15:08 -0000 1.131 +++ gstthread.c 29 Jul 2004 20:33:48 -0000 1.132 @@ -27,7 +27,6 @@ #include "gstmarshal.h" #include "gstscheduler.h" #include "gstinfo.h" -#include "gstutils.h" #define GST_CAT_DEFAULT GST_CAT_THREAD #define STACK_SIZE 0x200000 @@ -72,8 +71,6 @@ static void gst_thread_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); static GstElementStateReturn gst_thread_change_state (GstElement * element); -static GstElementStateReturn gst_thread_set_state (GstElement * element, - GstElementState state); static void gst_thread_child_state_change (GstBin * bin, GstElementState oldstate, GstElementState newstate, GstElement * element); @@ -184,7 +181,6 @@ gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_thread_change_state); - gstelement_class->set_state = GST_DEBUG_FUNCPTR (gst_thread_set_state); gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_thread_set_property); gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_thread_get_property); @@ -406,35 +402,12 @@ gst_thread_release (GstThread * thread) if (thread != gst_thread_get_current ()) { - GST_DEBUG_OBJECT (thread, "releasing lock"); g_cond_signal (thread->cond); g_mutex_unlock (thread->lock); -gst_thread_set_state (GstElement * element, GstElementState state) - GstElementStateReturn result; - GstThread *thread = GST_THREAD (element); - if (thread != gst_thread_get_current ()) { - gst_thread_catch (thread); - g_mutex_unlock (thread->lock); - result = - GST_CALL_PARENT_WITH_DEFAULT (GST_ELEMENT_CLASS, set_state, (element, - state), GST_STATE_FAILURE); - GST_DEBUG_OBJECT (thread, "grabbing lock"); - g_mutex_lock (thread->lock); - gst_thread_release (thread); - return result; -static GstElementStateReturn gst_thread_change_state (GstElement * element) GstThread *thread; @@ -478,13 +451,30 @@ case GST_STATE_PAUSED_TO_PLAYING: { + /* FIXME: recurse into sub-bins */ + GList *elements = (GList *) gst_bin_get_list (GST_BIN (thread)); + while (elements) { + gst_element_enable_threadsafe_properties ((GstElement *) elements-> + data); + elements = g_list_next (elements); /* reset self to spinning */ if (thread == gst_thread_get_current ()) GST_FLAG_SET (thread, GST_THREAD_STATE_SPINNING); case GST_STATE_PLAYING_TO_PAUSED: + { + gst_element_disable_threadsafe_properties ((GstElement *) elements-> case GST_STATE_PAUSED_TO_READY: case GST_STATE_READY_TO_NULL: Index: Makefile.am RCS file: /cvs/gstreamer/gstreamer/testsuite/states/Makefile.am,v retrieving revision 1.7 retrieving revision 1.8 diff -u -d -r1.7 -r1.8 --- Makefile.am 28 Jul 2004 11:43:02 -0000 1.7 +++ Makefile.am 29 Jul 2004 20:33:49 -0000 1.8 @@ -1,5 +1,5 @@ include ../Rules -tests_pass = locked parent bin +tests_pass = locked parent tests_fail = -tests_ignore = +tests_ignore = bin |