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