diff -r 567bb019e3e3 -r 7e817e7e631c gstreamer_core/gst/gstbin.c --- a/gstreamer_core/gst/gstbin.c Tue Aug 31 15:30:33 2010 +0300 +++ b/gstreamer_core/gst/gstbin.c Wed Sep 01 12:16:41 2010 +0100 @@ -51,9 +51,10 @@ * * gst_object_unref() is used to drop your reference to the bin. * - * The #GstBin::element-added signal is fired whenever a new element is added to - * the bin. Likewise the #GstBin::element-removed signal is fired whenever an - * element is removed from the bin. + * The element-added signal is + * fired whenever a new element is added to the bin. Likewise the element-removed signal is fired + * whenever an element is removed from the bin. * * Notes * @@ -173,6 +174,7 @@ #ifdef __SYMBIAN32__ #include #endif + /* enable for DURATION caching. * FIXME currently too many elements don't update * their duration when it changes so we return inaccurate values. */ @@ -191,20 +193,9 @@ * a toplevel bin */ #define BIN_IS_TOPLEVEL(bin) ((GST_OBJECT_PARENT (bin) == NULL) || bin->priv->asynchandling) -#define GST_BIN_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_BIN, GstBinPrivate)) - struct _GstBinPrivate { gboolean asynchandling; - /* if we get an ASYNC_DONE message from ourselves, this means that the - * subclass will simulate ASYNC behaviour without having ASYNC children. When - * such an ASYNC_DONE message is posted while we are doing a state change, we - * have to process the message after finishing the state change even when no - * child returned GST_STATE_CHANGE_ASYNC. */ - gboolean pending_async_done; - - guint32 structure_cookie; }; typedef struct @@ -225,15 +216,16 @@ GstStateChange transition); static GstStateChangeReturn gst_bin_get_state_func (GstElement * element, GstState * state, GstState * pending, GstClockTime timeout); -static void bin_handle_async_done (GstBin * bin, GstStateChangeReturn ret, - gboolean flag_pending); +static void bin_handle_async_done (GstBin * bin, GstStateChangeReturn ret); static void bin_handle_async_start (GstBin * bin, gboolean new_base_time); static void bin_push_state_continue (BinContinueData * data); static gboolean gst_bin_add_func (GstBin * bin, GstElement * element); static gboolean gst_bin_remove_func (GstBin * bin, GstElement * element); +#ifndef GST_DISABLE_INDEX static void gst_bin_set_index_func (GstElement * element, GstIndex * index); +#endif static GstClock *gst_bin_provide_clock_func (GstElement * element); static gboolean gst_bin_set_clock_func (GstElement * element, GstClock * clock); @@ -243,8 +235,6 @@ GstMessage * message, GstBin * bin); static gboolean gst_bin_query (GstElement * element, GstQuery * query); -static gboolean gst_bin_do_latency_func (GstBin * bin); - #ifndef GST_DISABLE_LOADSAVE static xmlNodePtr gst_bin_save_thyself (GstObject * object, xmlNodePtr parent); static void gst_bin_restore_thyself (GstObject * object, xmlNodePtr self); @@ -263,7 +253,6 @@ { ELEMENT_ADDED, ELEMENT_REMOVED, - DO_LATENCY, LAST_SIGNAL }; @@ -276,35 +265,69 @@ /* FILL ME */ }; +static void gst_bin_base_init (gpointer g_class); +static void gst_bin_class_init (GstBinClass * klass); +static void gst_bin_init (GstBin * bin); static void gst_bin_child_proxy_init (gpointer g_iface, gpointer iface_data); +static GstElementClass *parent_class = NULL; static guint gst_bin_signals[LAST_SIGNAL] = { 0 }; -#define _do_init(type) \ -{ \ - const gchar *compat; \ - static const GInterfaceInfo iface_info = { \ - gst_bin_child_proxy_init, \ - NULL, \ - NULL}; \ - \ - g_type_add_interface_static (type, GST_TYPE_CHILD_PROXY, &iface_info); \ - \ - GST_DEBUG_CATEGORY_INIT (bin_debug, "bin", GST_DEBUG_BOLD, \ - "debugging info for the 'bin' container element"); \ - \ - /* compatibility stuff */ \ - compat = g_getenv ("GST_COMPAT"); \ - if (compat != NULL) { \ - if (strstr (compat, "no-live-preroll")) \ - enable_latency = FALSE; \ - else if (strstr (compat, "live-preroll")) \ - enable_latency = TRUE; \ - } \ +/** + * gst_bin_get_type: + * + * Returns: the type of #GstBin + */ +#ifdef __SYMBIAN32__ +EXPORT_C +#endif + +GType +gst_bin_get_type (void) +{ + static GType gst_bin_type = 0; + const gchar *compat; + + if (G_UNLIKELY (gst_bin_type == 0)) { + static const GTypeInfo bin_info = { + sizeof (GstBinClass), + gst_bin_base_init, + NULL, + (GClassInitFunc) gst_bin_class_init, + NULL, + NULL, + sizeof (GstBin), + 0, + (GInstanceInitFunc) gst_bin_init, + NULL + }; + static const GInterfaceInfo child_proxy_info = { + gst_bin_child_proxy_init, + NULL, + NULL + }; + + gst_bin_type = + g_type_register_static (GST_TYPE_ELEMENT, "GstBin", &bin_info, 0); + + g_type_add_interface_static (gst_bin_type, GST_TYPE_CHILD_PROXY, + &child_proxy_info); + + GST_DEBUG_CATEGORY_INIT (bin_debug, "bin", GST_DEBUG_BOLD, + "debugging info for the 'bin' container element"); + + /* compatibility stuff */ + compat = g_getenv ("GST_COMPAT"); + if (compat != NULL) { + if (strstr (compat, "no-live-preroll")) + enable_latency = FALSE; + else if (strstr (compat, "live-preroll")) + enable_latency = TRUE; + } + } + return gst_bin_type; } -GST_BOILERPLATE_FULL (GstBin, gst_bin, GstElement, GST_TYPE_ELEMENT, _do_init); - static void gst_bin_base_init (gpointer g_class) { @@ -362,22 +385,6 @@ iface->get_child_by_index = gst_bin_child_proxy_get_child_by_index; } -static gboolean -_gst_boolean_accumulator (GSignalInvocationHint * ihint, - GValue * return_accu, const GValue * handler_return, gpointer dummy) -{ - gboolean myboolean; - - myboolean = g_value_get_boolean (handler_return); - if (!(ihint->run_type & G_SIGNAL_RUN_CLEANUP)) - g_value_set_boolean (return_accu, myboolean); - - GST_DEBUG ("invocation %d, %d", ihint->run_type, myboolean); - - /* stop emission */ - return FALSE; -} - static void gst_bin_class_init (GstBinClass * klass) { @@ -390,7 +397,7 @@ gstobject_class = (GstObjectClass *) klass; gstelement_class = (GstElementClass *) klass; - g_type_class_add_private (klass, sizeof (GstBinPrivate)); + parent_class = g_type_class_peek_parent (klass); gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_bin_set_property); gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_bin_get_property); @@ -407,7 +414,7 @@ g_object_class_install_property (gobject_class, PROP_ASYNC_HANDLING, g_param_spec_boolean ("async-handling", "Async Handling", "The bin will handle Asynchronous state changes", - DEFAULT_ASYNC_HANDLING, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + DEFAULT_ASYNC_HANDLING, G_PARAM_READWRITE)); /** * GstBin::element-added: @@ -431,29 +438,6 @@ g_signal_new ("element-removed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GstBinClass, element_removed), NULL, NULL, gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_ELEMENT); - /** - * GstBin::do-latency: - * @bin: the #GstBin - * - * Will be emitted when the bin needs to perform latency calculations. This - * signal is only emited for toplevel bins or when async-handling is - * enabled. - * - * Only one signal handler is invoked. If no signals are connected, the - * default handler is invoked, which will query and distribute the lowest - * possible latency to all sinks. - * - * Connect to this signal if the default latency calculations are not - * sufficient, like when you need different latencies for different sinks in - * the same pipeline. - * - * Since: 0.10.22 - */ - gst_bin_signals[DO_LATENCY] = - g_signal_new ("do-latency", G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstBinClass, do_latency), - _gst_boolean_accumulator, NULL, gst_marshal_BOOLEAN__VOID, - G_TYPE_BOOLEAN, 0, G_TYPE_NONE); gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_bin_dispose); @@ -466,7 +450,9 @@ gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_bin_change_state_func); gstelement_class->get_state = GST_DEBUG_FUNCPTR (gst_bin_get_state_func); +#ifndef GST_DISABLE_INDEX gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_bin_set_index_func); +#endif gstelement_class->provide_clock = GST_DEBUG_FUNCPTR (gst_bin_provide_clock_func); gstelement_class->set_clock = GST_DEBUG_FUNCPTR (gst_bin_set_clock_func); @@ -478,8 +464,6 @@ klass->remove_element = GST_DEBUG_FUNCPTR (gst_bin_remove_func); klass->handle_message = GST_DEBUG_FUNCPTR (gst_bin_handle_message_func); - klass->do_latency = GST_DEBUG_FUNCPTR (gst_bin_do_latency_func); - GST_DEBUG ("creating bin thread pool"); err = NULL; klass->pool = @@ -490,7 +474,7 @@ } static void -gst_bin_init (GstBin * bin, GstBinClass * klass) +gst_bin_init (GstBin * bin) { GstBus *bus; @@ -508,9 +492,8 @@ bus); gst_bus_set_sync_handler (bus, (GstBusSyncHandler) bin_bus_handler, bin); - bin->priv = GST_BIN_GET_PRIVATE (bin); + bin->priv = g_new0 (GstBinPrivate, 1); bin->priv->asynchandling = DEFAULT_ASYNC_HANDLING; - bin->priv->structure_cookie = 0; } static void @@ -523,12 +506,11 @@ GST_CAT_DEBUG_OBJECT (GST_CAT_REFCOUNTING, object, "dispose"); - GST_OBJECT_LOCK (object); + bin_remove_messages (bin, NULL, GST_MESSAGE_ANY); + gst_object_replace ((GstObject **) child_bus_p, NULL); gst_object_replace ((GstObject **) provided_clock_p, NULL); gst_object_replace ((GstObject **) clock_provider_p, NULL); - bin_remove_messages (bin, NULL, GST_MESSAGE_ANY); - GST_OBJECT_UNLOCK (object); while (bin->children) { gst_bin_remove (bin, GST_ELEMENT_CAST (bin->children->data)); @@ -538,6 +520,11 @@ GST_STR_NULL (GST_OBJECT_NAME (object))); } + if (bin->priv) { + g_free (bin->priv); + bin->priv = NULL; + } + G_OBJECT_CLASS (parent_class)->dispose (object); } @@ -603,45 +590,24 @@ * * MT safe */ +#ifndef GST_DISABLE_INDEX static void gst_bin_set_index_func (GstElement * element, GstIndex * index) { GstBin *bin; - gboolean done; - GstIterator *it; + GList *children; bin = GST_BIN (element); - it = gst_bin_iterate_elements (bin); - - done = FALSE; - while (!done) { - gpointer data; - - switch (gst_iterator_next (it, &data)) { - case GST_ITERATOR_OK: - { - GstElement *child = GST_ELEMENT_CAST (data); - - GST_DEBUG_OBJECT (bin, "setting index on %s", GST_ELEMENT_NAME (child)); - gst_element_set_index (child, index); - - gst_object_unref (child); - break; - } - case GST_ITERATOR_RESYNC: - GST_DEBUG_OBJECT (bin, "iterator doing resync"); - gst_iterator_resync (it); - break; - default: - case GST_ITERATOR_DONE: - GST_DEBUG_OBJECT (bin, "iterator done"); - done = TRUE; - break; - } + GST_OBJECT_LOCK (bin); + for (children = bin->children; children; children = g_list_next (children)) { + GstElement *child = GST_ELEMENT (children->data); + + gst_element_set_index (child, index); } - gst_iterator_free (it); + GST_OBJECT_UNLOCK (bin); } +#endif /* set the clock on all elements in this bin * @@ -650,42 +616,21 @@ static gboolean gst_bin_set_clock_func (GstElement * element, GstClock * clock) { + GList *children; GstBin *bin; - gboolean done; - GstIterator *it; gboolean res = TRUE; bin = GST_BIN (element); - it = gst_bin_iterate_elements (bin); - - done = FALSE; - while (!done) { - gpointer data; - - switch (gst_iterator_next (it, &data)) { - case GST_ITERATOR_OK: - { - GstElement *child = GST_ELEMENT_CAST (data); - - res &= gst_element_set_clock (child, clock); - - gst_object_unref (child); - break; - } - case GST_ITERATOR_RESYNC: - GST_DEBUG_OBJECT (bin, "iterator doing resync"); - gst_iterator_resync (it); - res = TRUE; - break; - default: - case GST_ITERATOR_DONE: - GST_DEBUG_OBJECT (bin, "iterator done"); - done = TRUE; - break; + GST_OBJECT_LOCK (bin); + if (element->clock != clock) { + for (children = bin->children; children; children = g_list_next (children)) { + GstElement *child = GST_ELEMENT (children->data); + + res &= gst_element_set_clock (child, clock); } } - gst_iterator_free (it); + GST_OBJECT_UNLOCK (bin); return res; } @@ -786,7 +731,6 @@ eq &= GST_MESSAGE_SRC (message) == target->src; if (target->types) eq &= (GST_MESSAGE_TYPE (message) & target->types) != 0; - GST_LOG ("looking at message %p: %d", message, eq); return (eq ? 0 : 1); } @@ -823,7 +767,7 @@ return result; } -/* with LOCK, returns TRUE if message had a valid SRC, takes ownership of +/* with LOCK, returns TRUE if message had a valid SRC, takes ref on * the message. * * A message that is cached and has the same SRC and type is replaced @@ -842,16 +786,12 @@ if ((src = GST_MESSAGE_SRC (message))) { /* first find the previous message posted by this element */ if ((previous = find_message (bin, src, types))) { - GstMessage *previous_msg; - /* if we found a previous message, replace it */ - previous_msg = previous->data; + gst_message_unref (previous->data); previous->data = message; - GST_DEBUG_OBJECT (bin, "replace old message %s from %s with %s message", - GST_MESSAGE_TYPE_NAME (previous_msg), GST_ELEMENT_NAME (src), name); - - gst_message_unref (previous_msg); + GST_DEBUG_OBJECT (bin, "replace old message %s from %s", + name, GST_ELEMENT_NAME (src)); } else { /* keep new message */ bin->messages = g_list_prepend (bin->messages, message); @@ -995,14 +935,12 @@ bin->children = g_list_prepend (bin->children, element); bin->numchildren++; bin->children_cookie++; - bin->priv->structure_cookie++; /* distribute the bus */ gst_element_set_bus (element, bin->child_bus); - /* propagate the current base_time, start_time and clock */ + /* propagate the current base_time and clock */ gst_element_set_base_time (element, GST_ELEMENT (bin)->base_time); - gst_element_set_start_time (element, GST_ELEMENT_START_TIME (bin)); /* it's possible that the element did not accept the clock but * that is not important right now. When the pipeline goes to PLAYING, * a new clock will be selected */ @@ -1030,7 +968,7 @@ } case GST_STATE_CHANGE_NO_PREROLL: /* ignore all async elements we might have and commit our state */ - bin_handle_async_done (bin, ret, FALSE); + bin_handle_async_done (bin, ret); break; case GST_STATE_CHANGE_FAILURE: break; @@ -1149,8 +1087,6 @@ GstIterator *it; gboolean is_sink, othersink, found; GstMessage *clock_message = NULL; - GstClock **provided_clock_p; - GstElement **clock_provider_p; GList *walk, *next; gboolean other_async, this_async, have_no_preroll; GstStateChangeReturn ret; @@ -1212,7 +1148,6 @@ * so that others can detect a change in the children list. */ bin->numchildren--; bin->children_cookie++; - bin->priv->structure_cookie++; if (is_sink && !othersink) { /* we're not a sink anymore */ @@ -1228,10 +1163,6 @@ bin->clock_dirty = TRUE; clock_message = gst_message_new_clock_lost (GST_OBJECT_CAST (bin), bin->provided_clock); - provided_clock_p = &bin->provided_clock; - clock_provider_p = &bin->clock_provider; - gst_object_replace ((GstObject **) provided_clock_p, NULL); - gst_object_replace ((GstObject **) clock_provider_p, NULL); } /* remove messages for the element, if there was a pending ASYNC_START @@ -1242,46 +1173,22 @@ for (walk = bin->messages; walk; walk = next) { GstMessage *message = (GstMessage *) walk->data; GstElement *src = GST_ELEMENT_CAST (GST_MESSAGE_SRC (message)); - gboolean remove; next = g_list_next (walk); - remove = FALSE; - - switch (GST_MESSAGE_TYPE (message)) { - case GST_MESSAGE_ASYNC_START: - if (src == element) - this_async = TRUE; - else - other_async = TRUE; - - GST_DEBUG_OBJECT (src, "looking at message %p", message); - break; - case GST_MESSAGE_STRUCTURE_CHANGE: - { - GstElement *owner; - - GST_DEBUG_OBJECT (src, "looking at structure change message %p", - message); - /* it's unlikely that this message is still in the list of messages - * because this would mean that a link/unlink is busy in another thread - * while we remove the element. We still have to remove the message - * because we might not receive the done message anymore when the element - * is removed from the bin. */ - gst_message_parse_structure_change (message, NULL, &owner, NULL); - if (owner == element) - remove = TRUE; - break; - } - default: - break; + + if (GST_MESSAGE_TYPE (message) == GST_MESSAGE_ASYNC_START) { + if (src == element) + this_async = TRUE; + else + other_async = TRUE; + + GST_DEBUG_OBJECT (GST_MESSAGE_SRC (message), + "looking at message %p", message); } - if (src == element) - remove = TRUE; - - if (remove) { + if (src == element) { /* delete all message types */ - GST_DEBUG_OBJECT (src, "deleting message %p of element \"%s\"", - message, elem_name); + GST_DEBUG_OBJECT (GST_MESSAGE_SRC (message), + "deleting message %p of element \"%s\"", message, elem_name); bin->messages = g_list_delete_link (bin->messages, walk); gst_message_unref (message); } @@ -1308,7 +1215,7 @@ else ret = GST_STATE_CHANGE_SUCCESS; - bin_handle_async_done (bin, ret, FALSE); + bin_handle_async_done (bin, ret); } else { GST_DEBUG_OBJECT (bin, "recalc state preroll: %d, other async: %d, this async %d", @@ -1788,28 +1695,18 @@ gboolean linked = FALSE; GST_OBJECT_LOCK (element); - /* don't touch degree if element has no sinkpads */ + /* don't touch degree if element has no sourcepads */ if (element->numsinkpads != 0) { /* loop over all sinkpads, decrement degree for all connected * elements in this bin */ GList *pads; for (pads = element->sinkpads; pads; pads = g_list_next (pads)) { - GstPad *pad, *peer; - - pad = GST_PAD_CAST (pads->data); - - if ((peer = gst_pad_get_peer (pad))) { + GstPad *peer; + + if ((peer = gst_pad_get_peer (GST_PAD_CAST (pads->data)))) { GstElement *peer_element; - /* we're iterating over the sinkpads, this is the peer and thus the - * srcpad, check if it's busy in a link/unlink */ - if (G_UNLIKELY (find_message (bit->bin, GST_OBJECT_CAST (peer), - GST_MESSAGE_STRUCTURE_CHANGE))) { - gst_object_unref (peer); - continue; - } - if ((peer_element = gst_pad_get_parent_element (peer))) { GST_OBJECT_LOCK (peer_element); /* check that we don't go outside of this bin */ @@ -1832,10 +1729,7 @@ GST_ELEMENT_NAME (peer_element), old_deg, new_deg, GST_ELEMENT_NAME (element)); - /* update degree, it is possible that an element was in 0 and - * reaches -1 here. This would mean that the element had no sinkpads - * but became linked while the state change was happening. We will - * resync on this with the structure change message. */ + /* update degree */ if (new_deg == 0) { /* degree hit 0, add to queue */ add_to_queue (bit, peer_element); @@ -1963,7 +1857,7 @@ gst_iterator_new (sizeof (GstBinSortIterator), GST_TYPE_ELEMENT, GST_OBJECT_GET_LOCK (bin), - &bin->priv->structure_cookie, + &bin->children_cookie, (GstIteratorNextFunction) gst_bin_sort_iterator_next, (GstIteratorItemFunction) NULL, (GstIteratorResyncFunction) gst_bin_sort_iterator_resync, @@ -2015,20 +1909,14 @@ static GstStateChangeReturn gst_bin_element_set_state (GstBin * bin, GstElement * element, - GstClockTime base_time, GstClockTime start_time, GstState current, - GstState next) + GstClockTime base_time, GstState current, GstState next) { GstStateChangeReturn ret; gboolean locked; GList *found; - GST_STATE_LOCK (element); - + /* peel off the locked flag */ GST_OBJECT_LOCK (element); - /* set base_time and start time on child */ - GST_ELEMENT_START_TIME (element) = start_time; - element->base_time = base_time; - /* peel off the locked flag */ locked = GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_LOCKED_STATE); /* get previous state return */ ret = GST_STATE_RETURN (element); @@ -2082,11 +1970,12 @@ GST_ELEMENT_NAME (element), gst_element_state_get_name (next), GST_TIME_ARGS (base_time)); + /* set base_time on child */ + gst_element_set_base_time (element, base_time); + /* change state */ ret = gst_element_set_state (element, next); - GST_STATE_UNLOCK (element); - return ret; locked: @@ -2094,14 +1983,12 @@ GST_DEBUG_OBJECT (element, "element is locked, return previous return %s", gst_element_state_change_return_get_name (ret)); - GST_STATE_UNLOCK (element); return ret; } was_busy: { GST_DEBUG_OBJECT (element, "element was busy, delaying state change"); GST_OBJECT_UNLOCK (bin); - GST_STATE_UNLOCK (element); return GST_STATE_CHANGE_ASYNC; } } @@ -2188,50 +2075,15 @@ } } -/** - * gst_bin_recalculate_latency: - * @bin: a #GstBin - * - * Query @bin for the current latency using and reconfigures this latency to all the - * elements with a LATENCY event. - * - * This method is typically called on the pipeline when a #GST_MESSAGE_LATENCY - * is posted on the bus. - * - * This function simply emits the 'do-latency' signal so any custom latency - * calculations will be performed. - * - * Returns: %TRUE if the latency could be queried and reconfigured. - * - * Since: 0.10.22. - */ -#ifdef __SYMBIAN32__ -EXPORT_C -#endif - -gboolean -gst_bin_recalculate_latency (GstBin * bin) -{ - gboolean res; - - g_signal_emit (G_OBJECT (bin), gst_bin_signals[DO_LATENCY], 0, &res); - GST_DEBUG_OBJECT (bin, "latency returned %d", res); - - return res; -} - +/* do latency correction. We do a latency query on the bin, and then send a + * LATENCY event on the elements fo configure them */ static gboolean -gst_bin_do_latency_func (GstBin * bin) +do_bin_latency (GstElement * element) { GstQuery *query; - GstElement *element; GstClockTime min_latency, max_latency; gboolean res; - g_return_val_if_fail (GST_IS_BIN (bin), FALSE); - - element = GST_ELEMENT_CAST (bin); - GST_DEBUG_OBJECT (element, "querying latency"); query = gst_query_new_latency (); @@ -2284,7 +2136,7 @@ GstState current, next; gboolean have_async; gboolean have_no_preroll; - GstClockTime base_time, start_time; + GstClockTime base_time; GstIterator *it; gboolean done; @@ -2308,7 +2160,7 @@ GST_OBJECT_UNLOCK (bin); if (toplevel) - gst_bin_recalculate_latency (bin); + do_bin_latency (element); break; } case GST_STATE_PAUSED: @@ -2358,7 +2210,6 @@ restart: /* take base_time */ base_time = gst_element_get_base_time (element); - start_time = gst_element_get_start_time (element); have_no_preroll = FALSE; @@ -2374,9 +2225,7 @@ child = GST_ELEMENT_CAST (data); /* set state and base_time now */ - ret = - gst_bin_element_set_state (bin, child, base_time, start_time, - current, next); + ret = gst_bin_element_set_state (bin, child, base_time, current, next); switch (ret) { case GST_STATE_CHANGE_SUCCESS: @@ -2431,13 +2280,8 @@ goto done; if (have_no_preroll) { - GST_CAT_DEBUG (GST_CAT_STATES, - "we have NO_PREROLL elements %s -> NO_PREROLL", - gst_element_state_change_return_get_name (ret)); ret = GST_STATE_CHANGE_NO_PREROLL; } else if (have_async) { - GST_CAT_DEBUG (GST_CAT_STATES, "we have ASYNC elements %s -> ASYNC", - gst_element_state_change_return_get_name (ret)); ret = GST_STATE_CHANGE_ASYNC; } @@ -2446,13 +2290,8 @@ GST_OBJECT_LOCK (bin); bin->polling = FALSE; - /* it's possible that we did not get ASYNC from the children while the bin is - * simulating ASYNC behaviour by posting an ASYNC_DONE message on the bus with - * itself as the source. In that case we still want to check if the state - * change completed. */ - if (ret != GST_STATE_CHANGE_ASYNC && !bin->priv->pending_async_done) { - /* no element returned ASYNC and there are no pending async_done messages, - * we can just complete. */ + if (ret != GST_STATE_CHANGE_ASYNC) { + /* no element returned ASYNC, we can just complete. */ GST_DEBUG_OBJECT (bin, "no async elements"); goto state_end; } @@ -2474,11 +2313,10 @@ bin_remove_messages (bin, NULL, GST_MESSAGE_ASYNC_DONE); GST_DEBUG_OBJECT (bin, "async elements commited"); - bin_handle_async_done (bin, GST_STATE_CHANGE_SUCCESS, FALSE); + bin_handle_async_done (bin, GST_STATE_CHANGE_SUCCESS); } state_end: - bin->priv->pending_async_done = FALSE; GST_OBJECT_UNLOCK (bin); GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element, @@ -2567,6 +2405,7 @@ GstBin *bin; GstState current, next, pending; GstStateChange transition; + GstStateChangeReturn ret; bin = data->bin; pending = data->pending; @@ -2587,7 +2426,6 @@ transition = (GstStateChange) GST_STATE_TRANSITION (current, next); GST_STATE_NEXT (bin) = next; - GST_STATE_PENDING (bin) = pending; /* mark busy */ GST_STATE_RETURN (bin) = GST_STATE_CHANGE_ASYNC; GST_OBJECT_UNLOCK (bin); @@ -2597,7 +2435,7 @@ gst_element_state_get_name (current), gst_element_state_get_name (next), gst_element_state_get_name (pending)); - gst_element_change_state (GST_ELEMENT_CAST (bin), transition); + ret = gst_element_change_state (GST_ELEMENT_CAST (bin), transition); GST_STATE_UNLOCK (bin); GST_DEBUG_OBJECT (bin, "state continue done"); @@ -2675,6 +2513,7 @@ if (GST_STATE_RETURN (bin) == GST_STATE_CHANGE_NO_PREROLL) goto was_no_preroll; + old_state = GST_STATE (bin); /* when we PLAYING we go back to PAUSED, when preroll happens, we go back to @@ -2733,8 +2572,7 @@ * This function is called with the OBJECT lock. */ static void -bin_handle_async_done (GstBin * bin, GstStateChangeReturn ret, - gboolean flag_pending) +bin_handle_async_done (GstBin * bin, GstStateChangeReturn ret) { GstState current, pending, target; GstStateChangeReturn old_ret; @@ -2778,11 +2616,6 @@ /* update current state */ current = GST_STATE (bin) = old_next; } else { - GST_CAT_INFO_OBJECT (GST_CAT_STATES, bin, - "setting state from %s to %s, pending %s", - gst_element_state_get_name (old_state), - gst_element_state_get_name (old_state), - gst_element_state_get_name (pending)); current = old_state; } @@ -2814,7 +2647,7 @@ cont->pending = pending; /* mark busy */ GST_STATE_RETURN (bin) = GST_STATE_CHANGE_ASYNC; - GST_STATE_NEXT (bin) = GST_STATE_GET_NEXT (old_state, pending); + GST_STATE_NEXT (bin) = pending; } if (old_next != GST_STATE_PLAYING) { @@ -2854,10 +2687,6 @@ was_busy: { GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin, "state change busy"); - /* if we were busy with a state change and we are requested to flag a - * pending async done, we do so here */ - if (flag_pending) - bin->priv->pending_async_done = TRUE; return; } nothing_pending: @@ -2926,16 +2755,18 @@ { GstObject *src; GstMessageType type; - GstMessage *tmessage; - guint32 seqnum; src = GST_MESSAGE_SRC (message); type = GST_MESSAGE_TYPE (message); +// Message src can be NULL + if(src) GST_DEBUG_OBJECT (bin, "[msg %p] handling child %s message of type %s", - message, src ? GST_ELEMENT_NAME (src) : "(NULL)", - GST_MESSAGE_TYPE_NAME (message)); - + message, GST_ELEMENT_NAME (src), GST_MESSAGE_TYPE_NAME (message)); + else + GST_DEBUG_OBJECT (bin, "[msg %p] handling child %s message of type %s", + message, "Null ", GST_MESSAGE_TYPE_NAME (message)); + switch (type) { case GST_MESSAGE_EOS: { @@ -2949,13 +2780,9 @@ /* if we are completely EOS, we forward an EOS message */ if (eos) { - seqnum = gst_message_get_seqnum (message); - tmessage = gst_message_new_eos (GST_OBJECT_CAST (bin)); - gst_message_set_seqnum (tmessage, seqnum); - - GST_DEBUG_OBJECT (bin, - "all sinks posted EOS, posting seqnum #%" G_GUINT32_FORMAT, seqnum); - gst_element_post_message (GST_ELEMENT_CAST (bin), tmessage); + GST_DEBUG_OBJECT (bin, "all sinks posted EOS"); + gst_element_post_message (GST_ELEMENT_CAST (bin), + gst_message_new_eos (GST_OBJECT_CAST (bin))); } break; } @@ -2967,37 +2794,13 @@ gst_message_unref (message); break; } - case GST_MESSAGE_SEGMENT_START:{ - gboolean post = FALSE; - GstFormat format; - gint64 position; - - gst_message_parse_segment_start (message, &format, &position); - seqnum = gst_message_get_seqnum (message); - + case GST_MESSAGE_SEGMENT_START: GST_OBJECT_LOCK (bin); - /* if this is the first segment-start, post to parent but not to the - * application */ - if (!find_message (bin, NULL, GST_MESSAGE_SEGMENT_START) && - (GST_OBJECT_PARENT (bin) != NULL)) { - post = TRUE; - } /* replace any previous segment_start message from this source * with the new segment start message */ bin_replace_message (bin, message, GST_MESSAGE_SEGMENT_START); GST_OBJECT_UNLOCK (bin); - if (post) { - tmessage = gst_message_new_segment_start (GST_OBJECT_CAST (bin), - format, position); - gst_message_set_seqnum (tmessage, seqnum); - - /* post segment start with initial format and position. */ - GST_DEBUG_OBJECT (bin, "posting SEGMENT_START (%u) bus message: %p", - seqnum, message); - gst_element_post_message (GST_ELEMENT_CAST (bin), tmessage); - } break; - } case GST_MESSAGE_SEGMENT_DONE: { gboolean post = FALSE; @@ -3005,7 +2808,6 @@ gint64 position; gst_message_parse_segment_done (message, &format, &position); - seqnum = gst_message_get_seqnum (message); GST_OBJECT_LOCK (bin); bin_replace_message (bin, message, GST_MESSAGE_SEGMENT_START); @@ -3021,14 +2823,10 @@ } GST_OBJECT_UNLOCK (bin); if (post) { - tmessage = gst_message_new_segment_done (GST_OBJECT_CAST (bin), - format, position); - gst_message_set_seqnum (tmessage, seqnum); - /* post segment done with latest format and position. */ - GST_DEBUG_OBJECT (bin, "posting SEGMENT_DONE (%u) bus message: %p", - seqnum, message); - gst_element_post_message (GST_ELEMENT_CAST (bin), tmessage); + gst_element_post_message (GST_ELEMENT_CAST (bin), + gst_message_new_segment_done (GST_OBJECT_CAST (bin), + format, position)); } break; } @@ -3099,9 +2897,12 @@ { gboolean new_base_time; GstState target; - + if(src) GST_DEBUG_OBJECT (bin, "ASYNC_START message %p, %s", message, - src ? GST_OBJECT_NAME (src) : "(NULL)"); + GST_OBJECT_NAME (src)); + else + GST_DEBUG_OBJECT (bin, "ASYNC_START message %p, %s", message, + "Null Source"); gst_message_parse_async_start (message, &new_base_time); @@ -3130,9 +2931,13 @@ case GST_MESSAGE_ASYNC_DONE: { GstState target; - + + if(src) GST_DEBUG_OBJECT (bin, "ASYNC_DONE message %p, %s", message, - src ? GST_OBJECT_NAME (src) : "(NULL)"); + GST_OBJECT_NAME (src)); + else + GST_DEBUG_OBJECT (bin, "ASYNC_DONE message %p, %s", message, + "Null Source"); GST_OBJECT_LOCK (bin); target = GST_STATE_TARGET (bin); @@ -3149,13 +2954,7 @@ bin_remove_messages (bin, NULL, GST_MESSAGE_ASYNC_DONE); GST_DEBUG_OBJECT (bin, "async elements commited"); - /* when we get an async done message when a state change was busy, we - * need to set the pending_done flag so that at the end of the state - * change we can see if we need to verify pending async elements, hence - * the TRUE argument here. */ - bin_handle_async_done (bin, GST_STATE_CHANGE_SUCCESS, TRUE); - } else { - GST_DEBUG_OBJECT (bin, "there are more async elements pending"); + bin_handle_async_done (bin, GST_STATE_CHANGE_SUCCESS); } GST_OBJECT_UNLOCK (bin); break; @@ -3169,34 +2968,6 @@ break; } } - case GST_MESSAGE_STRUCTURE_CHANGE: - { - gboolean busy; - - gst_message_parse_structure_change (message, NULL, NULL, &busy); - - GST_OBJECT_LOCK (bin); - if (busy) { - /* while the pad is busy, avoid following it when doing state changes. - * Don't update the cookie yet, we will do that after the structure - * change finished and we are ready to inspect the new updated - * structure. */ - bin_replace_message (bin, message, GST_MESSAGE_STRUCTURE_CHANGE); - message = NULL; - } else { - /* a pad link/unlink ended, signal the state change iterator that we - * need to resync by updating the structure_cookie. */ - bin_remove_messages (bin, GST_MESSAGE_SRC (message), - GST_MESSAGE_STRUCTURE_CHANGE); - bin->priv->structure_cookie++; - } - GST_OBJECT_UNLOCK (bin); - - if (message) - gst_message_unref (message); - - break; - } default: goto forward; } @@ -3252,7 +3023,6 @@ gst_object_unref (item); return TRUE; } - static void bin_query_duration_done (GstBin * bin, QueryFold * fold) { @@ -3292,7 +3062,6 @@ gst_object_unref (item); return TRUE; } - static void bin_query_position_done (GstBin * bin, QueryFold * fold) { @@ -3320,16 +3089,14 @@ /* for the combined latency we collect the MAX of all min latencies and * the MIN of all max latencies */ - if (live) { - if (min > fold->min) - fold->min = min; - if (fold->max == -1) - fold->max = max; - else if (max < fold->max) - fold->max = max; - if (fold->live == FALSE) - fold->live = live; - } + if (min > fold->min) + fold->min = min; + if (fold->max == -1) + fold->max = max; + else if (max < fold->max) + fold->max = max; + if (fold->live == FALSE) + fold->live = live; } else { g_value_set_boolean (ret, FALSE); GST_DEBUG_OBJECT (item, "failed query"); @@ -3443,7 +3210,6 @@ fold_data.query = query; - /* set the result of the query to FALSE initially */ g_value_init (&ret, G_TYPE_BOOLEAN); g_value_set_boolean (&ret, res); @@ -3692,12 +3458,12 @@ GST_CAT_INFO (GST_CAT_XML, "[%s]: saving %d children", GST_ELEMENT_NAME (bin), bin->numchildren); - children = g_list_last (bin->children); + children = bin->children; while (children) { child = GST_ELEMENT (children->data); elementnode = xmlNewChild (childlist, NULL, (xmlChar *) "element", NULL); gst_object_save_thyself (GST_OBJECT (child), elementnode); - children = g_list_previous (children); + children = g_list_next (children); } return childlist; }