gstreamer_core/gst/gstbin.c
branchRCL_3
changeset 30 7e817e7e631c
parent 29 567bb019e3e3
equal deleted inserted replaced
29:567bb019e3e3 30:7e817e7e631c
    49  * gst_bin_iterate_elements(). Various other iterators exist to retrieve the
    49  * gst_bin_iterate_elements(). Various other iterators exist to retrieve the
    50  * elements in a bin.
    50  * elements in a bin.
    51  *
    51  *
    52  * gst_object_unref() is used to drop your reference to the bin.
    52  * gst_object_unref() is used to drop your reference to the bin.
    53  *
    53  *
    54  * The #GstBin::element-added signal is fired whenever a new element is added to
    54  * The <link linkend="GstBin-element-added">element-added</link> signal is
    55  * the bin. Likewise the #GstBin::element-removed signal is fired whenever an
    55  * fired whenever a new element is added to the bin. Likewise the <link
    56  * element is removed from the bin.
    56  * linkend="GstBin-element-removed">element-removed</link> signal is fired
       
    57  * whenever an element is removed from the bin.
    57  *
    58  *
    58  * <refsect2><title>Notes</title>
    59  * <refsect2><title>Notes</title>
    59  * <para>
    60  * <para>
    60  * A #GstBin internally intercepts every #GstMessage posted by its children and
    61  * A #GstBin internally intercepts every #GstMessage posted by its children and
    61  * implements the following default behaviour for each of them:
    62  * implements the following default behaviour for each of them:
   171 #include "gstchildproxy.h"
   172 #include "gstchildproxy.h"
   172 
   173 
   173 #ifdef __SYMBIAN32__
   174 #ifdef __SYMBIAN32__
   174 #include <glib_global.h>
   175 #include <glib_global.h>
   175 #endif
   176 #endif
       
   177 
   176 /* enable for DURATION caching.
   178 /* enable for DURATION caching.
   177  * FIXME currently too many elements don't update
   179  * FIXME currently too many elements don't update
   178  * their duration when it changes so we return inaccurate values. */
   180  * their duration when it changes so we return inaccurate values. */
   179 #undef DURATION_CACHING
   181 #undef DURATION_CACHING
   180 
   182 
   189 
   191 
   190 /* a bin is toplevel if it has no parent or when it is configured to behave like
   192 /* a bin is toplevel if it has no parent or when it is configured to behave like
   191  * a toplevel bin */
   193  * a toplevel bin */
   192 #define BIN_IS_TOPLEVEL(bin) ((GST_OBJECT_PARENT (bin) == NULL) || bin->priv->asynchandling)
   194 #define BIN_IS_TOPLEVEL(bin) ((GST_OBJECT_PARENT (bin) == NULL) || bin->priv->asynchandling)
   193 
   195 
   194 #define GST_BIN_GET_PRIVATE(obj)  \
       
   195    (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_BIN, GstBinPrivate))
       
   196 
       
   197 struct _GstBinPrivate
   196 struct _GstBinPrivate
   198 {
   197 {
   199   gboolean asynchandling;
   198   gboolean asynchandling;
   200   /* if we get an ASYNC_DONE message from ourselves, this means that the
       
   201    * subclass will simulate ASYNC behaviour without having ASYNC children. When
       
   202    * such an ASYNC_DONE message is posted while we are doing a state change, we
       
   203    * have to process the message after finishing the state change even when no
       
   204    * child returned GST_STATE_CHANGE_ASYNC. */
       
   205   gboolean pending_async_done;
       
   206 
       
   207   guint32 structure_cookie;
       
   208 };
   199 };
   209 
   200 
   210 typedef struct
   201 typedef struct
   211 {
   202 {
   212   GstBin *bin;
   203   GstBin *bin;
   223 
   214 
   224 static GstStateChangeReturn gst_bin_change_state_func (GstElement * element,
   215 static GstStateChangeReturn gst_bin_change_state_func (GstElement * element,
   225     GstStateChange transition);
   216     GstStateChange transition);
   226 static GstStateChangeReturn gst_bin_get_state_func (GstElement * element,
   217 static GstStateChangeReturn gst_bin_get_state_func (GstElement * element,
   227     GstState * state, GstState * pending, GstClockTime timeout);
   218     GstState * state, GstState * pending, GstClockTime timeout);
   228 static void bin_handle_async_done (GstBin * bin, GstStateChangeReturn ret,
   219 static void bin_handle_async_done (GstBin * bin, GstStateChangeReturn ret);
   229     gboolean flag_pending);
       
   230 static void bin_handle_async_start (GstBin * bin, gboolean new_base_time);
   220 static void bin_handle_async_start (GstBin * bin, gboolean new_base_time);
   231 static void bin_push_state_continue (BinContinueData * data);
   221 static void bin_push_state_continue (BinContinueData * data);
   232 
   222 
   233 static gboolean gst_bin_add_func (GstBin * bin, GstElement * element);
   223 static gboolean gst_bin_add_func (GstBin * bin, GstElement * element);
   234 static gboolean gst_bin_remove_func (GstBin * bin, GstElement * element);
   224 static gboolean gst_bin_remove_func (GstBin * bin, GstElement * element);
   235 
   225 
       
   226 #ifndef GST_DISABLE_INDEX
   236 static void gst_bin_set_index_func (GstElement * element, GstIndex * index);
   227 static void gst_bin_set_index_func (GstElement * element, GstIndex * index);
       
   228 #endif
   237 static GstClock *gst_bin_provide_clock_func (GstElement * element);
   229 static GstClock *gst_bin_provide_clock_func (GstElement * element);
   238 static gboolean gst_bin_set_clock_func (GstElement * element, GstClock * clock);
   230 static gboolean gst_bin_set_clock_func (GstElement * element, GstClock * clock);
   239 
   231 
   240 static void gst_bin_handle_message_func (GstBin * bin, GstMessage * message);
   232 static void gst_bin_handle_message_func (GstBin * bin, GstMessage * message);
   241 static gboolean gst_bin_send_event (GstElement * element, GstEvent * event);
   233 static gboolean gst_bin_send_event (GstElement * element, GstEvent * event);
   242 static GstBusSyncReply bin_bus_handler (GstBus * bus,
   234 static GstBusSyncReply bin_bus_handler (GstBus * bus,
   243     GstMessage * message, GstBin * bin);
   235     GstMessage * message, GstBin * bin);
   244 static gboolean gst_bin_query (GstElement * element, GstQuery * query);
   236 static gboolean gst_bin_query (GstElement * element, GstQuery * query);
   245 
   237 
   246 static gboolean gst_bin_do_latency_func (GstBin * bin);
       
   247 
       
   248 #ifndef GST_DISABLE_LOADSAVE
   238 #ifndef GST_DISABLE_LOADSAVE
   249 static xmlNodePtr gst_bin_save_thyself (GstObject * object, xmlNodePtr parent);
   239 static xmlNodePtr gst_bin_save_thyself (GstObject * object, xmlNodePtr parent);
   250 static void gst_bin_restore_thyself (GstObject * object, xmlNodePtr self);
   240 static void gst_bin_restore_thyself (GstObject * object, xmlNodePtr self);
   251 #endif
   241 #endif
   252 
   242 
   261 /* Bin signals and properties */
   251 /* Bin signals and properties */
   262 enum
   252 enum
   263 {
   253 {
   264   ELEMENT_ADDED,
   254   ELEMENT_ADDED,
   265   ELEMENT_REMOVED,
   255   ELEMENT_REMOVED,
   266   DO_LATENCY,
       
   267   LAST_SIGNAL
   256   LAST_SIGNAL
   268 };
   257 };
   269 
   258 
   270 #define DEFAULT_ASYNC_HANDLING	FALSE
   259 #define DEFAULT_ASYNC_HANDLING	FALSE
   271 
   260 
   274   PROP_0,
   263   PROP_0,
   275   PROP_ASYNC_HANDLING
   264   PROP_ASYNC_HANDLING
   276       /* FILL ME */
   265       /* FILL ME */
   277 };
   266 };
   278 
   267 
       
   268 static void gst_bin_base_init (gpointer g_class);
       
   269 static void gst_bin_class_init (GstBinClass * klass);
       
   270 static void gst_bin_init (GstBin * bin);
   279 static void gst_bin_child_proxy_init (gpointer g_iface, gpointer iface_data);
   271 static void gst_bin_child_proxy_init (gpointer g_iface, gpointer iface_data);
   280 
   272 
       
   273 static GstElementClass *parent_class = NULL;
   281 static guint gst_bin_signals[LAST_SIGNAL] = { 0 };
   274 static guint gst_bin_signals[LAST_SIGNAL] = { 0 };
   282 
   275 
   283 #define _do_init(type) \
   276 /**
   284 { \
   277  * gst_bin_get_type:
   285   const gchar *compat; \
   278  *
   286   static const GInterfaceInfo iface_info = { \
   279  * Returns: the type of #GstBin
   287     gst_bin_child_proxy_init, \
   280  */
   288     NULL, \
   281 #ifdef __SYMBIAN32__
   289     NULL}; \
   282 EXPORT_C
   290   \
   283 #endif
   291   g_type_add_interface_static (type, GST_TYPE_CHILD_PROXY, &iface_info); \
   284 
   292   \
   285 GType
   293   GST_DEBUG_CATEGORY_INIT (bin_debug, "bin", GST_DEBUG_BOLD, \
   286 gst_bin_get_type (void)
   294       "debugging info for the 'bin' container element"); \
   287 {
   295   \
   288   static GType gst_bin_type = 0;
   296   /* compatibility stuff */ \
   289   const gchar *compat;
   297   compat = g_getenv ("GST_COMPAT"); \
   290 
   298   if (compat != NULL) { \
   291   if (G_UNLIKELY (gst_bin_type == 0)) {
   299     if (strstr (compat, "no-live-preroll")) \
   292     static const GTypeInfo bin_info = {
   300       enable_latency = FALSE; \
   293       sizeof (GstBinClass),
   301     else if (strstr (compat, "live-preroll")) \
   294       gst_bin_base_init,
   302       enable_latency = TRUE; \
   295       NULL,
   303   } \
   296       (GClassInitFunc) gst_bin_class_init,
   304 }
   297       NULL,
   305 
   298       NULL,
   306 GST_BOILERPLATE_FULL (GstBin, gst_bin, GstElement, GST_TYPE_ELEMENT, _do_init);
   299       sizeof (GstBin),
       
   300       0,
       
   301       (GInstanceInitFunc) gst_bin_init,
       
   302       NULL
       
   303     };
       
   304     static const GInterfaceInfo child_proxy_info = {
       
   305       gst_bin_child_proxy_init,
       
   306       NULL,
       
   307       NULL
       
   308     };
       
   309 
       
   310     gst_bin_type =
       
   311         g_type_register_static (GST_TYPE_ELEMENT, "GstBin", &bin_info, 0);
       
   312 
       
   313     g_type_add_interface_static (gst_bin_type, GST_TYPE_CHILD_PROXY,
       
   314         &child_proxy_info);
       
   315 
       
   316     GST_DEBUG_CATEGORY_INIT (bin_debug, "bin", GST_DEBUG_BOLD,
       
   317         "debugging info for the 'bin' container element");
       
   318 
       
   319     /* compatibility stuff */
       
   320     compat = g_getenv ("GST_COMPAT");
       
   321     if (compat != NULL) {
       
   322       if (strstr (compat, "no-live-preroll"))
       
   323         enable_latency = FALSE;
       
   324       else if (strstr (compat, "live-preroll"))
       
   325         enable_latency = TRUE;
       
   326     }
       
   327   }
       
   328   return gst_bin_type;
       
   329 }
   307 
   330 
   308 static void
   331 static void
   309 gst_bin_base_init (gpointer g_class)
   332 gst_bin_base_init (gpointer g_class)
   310 {
   333 {
   311   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
   334   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
   360 
   383 
   361   iface->get_children_count = gst_bin_child_proxy_get_children_count;
   384   iface->get_children_count = gst_bin_child_proxy_get_children_count;
   362   iface->get_child_by_index = gst_bin_child_proxy_get_child_by_index;
   385   iface->get_child_by_index = gst_bin_child_proxy_get_child_by_index;
   363 }
   386 }
   364 
   387 
   365 static gboolean
       
   366 _gst_boolean_accumulator (GSignalInvocationHint * ihint,
       
   367     GValue * return_accu, const GValue * handler_return, gpointer dummy)
       
   368 {
       
   369   gboolean myboolean;
       
   370 
       
   371   myboolean = g_value_get_boolean (handler_return);
       
   372   if (!(ihint->run_type & G_SIGNAL_RUN_CLEANUP))
       
   373     g_value_set_boolean (return_accu, myboolean);
       
   374 
       
   375   GST_DEBUG ("invocation %d, %d", ihint->run_type, myboolean);
       
   376 
       
   377   /* stop emission */
       
   378   return FALSE;
       
   379 }
       
   380 
       
   381 static void
   388 static void
   382 gst_bin_class_init (GstBinClass * klass)
   389 gst_bin_class_init (GstBinClass * klass)
   383 {
   390 {
   384   GObjectClass *gobject_class;
   391   GObjectClass *gobject_class;
   385   GstObjectClass *gstobject_class;
   392   GstObjectClass *gstobject_class;
   388 
   395 
   389   gobject_class = (GObjectClass *) klass;
   396   gobject_class = (GObjectClass *) klass;
   390   gstobject_class = (GstObjectClass *) klass;
   397   gstobject_class = (GstObjectClass *) klass;
   391   gstelement_class = (GstElementClass *) klass;
   398   gstelement_class = (GstElementClass *) klass;
   392 
   399 
   393   g_type_class_add_private (klass, sizeof (GstBinPrivate));
   400   parent_class = g_type_class_peek_parent (klass);
   394 
   401 
   395   gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_bin_set_property);
   402   gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_bin_set_property);
   396   gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_bin_get_property);
   403   gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_bin_get_property);
   397 
   404 
   398   /**
   405   /**
   405    * Since: 0.10.13
   412    * Since: 0.10.13
   406    */
   413    */
   407   g_object_class_install_property (gobject_class, PROP_ASYNC_HANDLING,
   414   g_object_class_install_property (gobject_class, PROP_ASYNC_HANDLING,
   408       g_param_spec_boolean ("async-handling", "Async Handling",
   415       g_param_spec_boolean ("async-handling", "Async Handling",
   409           "The bin will handle Asynchronous state changes",
   416           "The bin will handle Asynchronous state changes",
   410           DEFAULT_ASYNC_HANDLING, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   417           DEFAULT_ASYNC_HANDLING, G_PARAM_READWRITE));
   411 
   418 
   412   /**
   419   /**
   413    * GstBin::element-added:
   420    * GstBin::element-added:
   414    * @bin: the #GstBin
   421    * @bin: the #GstBin
   415    * @element: the #GstElement that was added to the bin
   422    * @element: the #GstElement that was added to the bin
   429    */
   436    */
   430   gst_bin_signals[ELEMENT_REMOVED] =
   437   gst_bin_signals[ELEMENT_REMOVED] =
   431       g_signal_new ("element-removed", G_TYPE_FROM_CLASS (klass),
   438       g_signal_new ("element-removed", G_TYPE_FROM_CLASS (klass),
   432       G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GstBinClass, element_removed), NULL,
   439       G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GstBinClass, element_removed), NULL,
   433       NULL, gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_ELEMENT);
   440       NULL, gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_ELEMENT);
   434   /**
       
   435    * GstBin::do-latency:
       
   436    * @bin: the #GstBin
       
   437    *
       
   438    * Will be emitted when the bin needs to perform latency calculations. This
       
   439    * signal is only emited for toplevel bins or when async-handling is
       
   440    * enabled.
       
   441    *
       
   442    * Only one signal handler is invoked. If no signals are connected, the
       
   443    * default handler is invoked, which will query and distribute the lowest
       
   444    * possible latency to all sinks.
       
   445    *
       
   446    * Connect to this signal if the default latency calculations are not
       
   447    * sufficient, like when you need different latencies for different sinks in
       
   448    * the same pipeline.
       
   449    *
       
   450    * Since: 0.10.22
       
   451    */
       
   452   gst_bin_signals[DO_LATENCY] =
       
   453       g_signal_new ("do-latency", G_TYPE_FROM_CLASS (klass),
       
   454       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstBinClass, do_latency),
       
   455       _gst_boolean_accumulator, NULL, gst_marshal_BOOLEAN__VOID,
       
   456       G_TYPE_BOOLEAN, 0, G_TYPE_NONE);
       
   457 
   441 
   458   gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_bin_dispose);
   442   gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_bin_dispose);
   459 
   443 
   460 #ifndef GST_DISABLE_LOADSAVE
   444 #ifndef GST_DISABLE_LOADSAVE
   461   gstobject_class->save_thyself = GST_DEBUG_FUNCPTR (gst_bin_save_thyself);
   445   gstobject_class->save_thyself = GST_DEBUG_FUNCPTR (gst_bin_save_thyself);
   464 #endif
   448 #endif
   465 
   449 
   466   gstelement_class->change_state =
   450   gstelement_class->change_state =
   467       GST_DEBUG_FUNCPTR (gst_bin_change_state_func);
   451       GST_DEBUG_FUNCPTR (gst_bin_change_state_func);
   468   gstelement_class->get_state = GST_DEBUG_FUNCPTR (gst_bin_get_state_func);
   452   gstelement_class->get_state = GST_DEBUG_FUNCPTR (gst_bin_get_state_func);
       
   453 #ifndef GST_DISABLE_INDEX
   469   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_bin_set_index_func);
   454   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_bin_set_index_func);
       
   455 #endif
   470   gstelement_class->provide_clock =
   456   gstelement_class->provide_clock =
   471       GST_DEBUG_FUNCPTR (gst_bin_provide_clock_func);
   457       GST_DEBUG_FUNCPTR (gst_bin_provide_clock_func);
   472   gstelement_class->set_clock = GST_DEBUG_FUNCPTR (gst_bin_set_clock_func);
   458   gstelement_class->set_clock = GST_DEBUG_FUNCPTR (gst_bin_set_clock_func);
   473 
   459 
   474   gstelement_class->send_event = GST_DEBUG_FUNCPTR (gst_bin_send_event);
   460   gstelement_class->send_event = GST_DEBUG_FUNCPTR (gst_bin_send_event);
   475   gstelement_class->query = GST_DEBUG_FUNCPTR (gst_bin_query);
   461   gstelement_class->query = GST_DEBUG_FUNCPTR (gst_bin_query);
   476 
   462 
   477   klass->add_element = GST_DEBUG_FUNCPTR (gst_bin_add_func);
   463   klass->add_element = GST_DEBUG_FUNCPTR (gst_bin_add_func);
   478   klass->remove_element = GST_DEBUG_FUNCPTR (gst_bin_remove_func);
   464   klass->remove_element = GST_DEBUG_FUNCPTR (gst_bin_remove_func);
   479   klass->handle_message = GST_DEBUG_FUNCPTR (gst_bin_handle_message_func);
   465   klass->handle_message = GST_DEBUG_FUNCPTR (gst_bin_handle_message_func);
   480 
       
   481   klass->do_latency = GST_DEBUG_FUNCPTR (gst_bin_do_latency_func);
       
   482 
   466 
   483   GST_DEBUG ("creating bin thread pool");
   467   GST_DEBUG ("creating bin thread pool");
   484   err = NULL;
   468   err = NULL;
   485   klass->pool =
   469   klass->pool =
   486       g_thread_pool_new ((GFunc) gst_bin_continue_func, NULL, -1, FALSE, &err);
   470       g_thread_pool_new ((GFunc) gst_bin_continue_func, NULL, -1, FALSE, &err);
   488     g_critical ("could alloc threadpool %s", err->message);
   472     g_critical ("could alloc threadpool %s", err->message);
   489   }
   473   }
   490 }
   474 }
   491 
   475 
   492 static void
   476 static void
   493 gst_bin_init (GstBin * bin, GstBinClass * klass)
   477 gst_bin_init (GstBin * bin)
   494 {
   478 {
   495   GstBus *bus;
   479   GstBus *bus;
   496 
   480 
   497   bin->numchildren = 0;
   481   bin->numchildren = 0;
   498   bin->children = NULL;
   482   bin->children = NULL;
   506   bin->child_bus = bus;
   490   bin->child_bus = bus;
   507   GST_DEBUG_OBJECT (bin, "using bus %" GST_PTR_FORMAT " to listen to children",
   491   GST_DEBUG_OBJECT (bin, "using bus %" GST_PTR_FORMAT " to listen to children",
   508       bus);
   492       bus);
   509   gst_bus_set_sync_handler (bus, (GstBusSyncHandler) bin_bus_handler, bin);
   493   gst_bus_set_sync_handler (bus, (GstBusSyncHandler) bin_bus_handler, bin);
   510 
   494 
   511   bin->priv = GST_BIN_GET_PRIVATE (bin);
   495   bin->priv = g_new0 (GstBinPrivate, 1);
   512   bin->priv->asynchandling = DEFAULT_ASYNC_HANDLING;
   496   bin->priv->asynchandling = DEFAULT_ASYNC_HANDLING;
   513   bin->priv->structure_cookie = 0;
       
   514 }
   497 }
   515 
   498 
   516 static void
   499 static void
   517 gst_bin_dispose (GObject * object)
   500 gst_bin_dispose (GObject * object)
   518 {
   501 {
   521   GstClock **provided_clock_p = &bin->provided_clock;
   504   GstClock **provided_clock_p = &bin->provided_clock;
   522   GstElement **clock_provider_p = &bin->clock_provider;
   505   GstElement **clock_provider_p = &bin->clock_provider;
   523 
   506 
   524   GST_CAT_DEBUG_OBJECT (GST_CAT_REFCOUNTING, object, "dispose");
   507   GST_CAT_DEBUG_OBJECT (GST_CAT_REFCOUNTING, object, "dispose");
   525 
   508 
   526   GST_OBJECT_LOCK (object);
   509   bin_remove_messages (bin, NULL, GST_MESSAGE_ANY);
       
   510 
   527   gst_object_replace ((GstObject **) child_bus_p, NULL);
   511   gst_object_replace ((GstObject **) child_bus_p, NULL);
   528   gst_object_replace ((GstObject **) provided_clock_p, NULL);
   512   gst_object_replace ((GstObject **) provided_clock_p, NULL);
   529   gst_object_replace ((GstObject **) clock_provider_p, NULL);
   513   gst_object_replace ((GstObject **) clock_provider_p, NULL);
   530   bin_remove_messages (bin, NULL, GST_MESSAGE_ANY);
       
   531   GST_OBJECT_UNLOCK (object);
       
   532 
   514 
   533   while (bin->children) {
   515   while (bin->children) {
   534     gst_bin_remove (bin, GST_ELEMENT_CAST (bin->children->data));
   516     gst_bin_remove (bin, GST_ELEMENT_CAST (bin->children->data));
   535   }
   517   }
   536   if (G_UNLIKELY (bin->children != NULL)) {
   518   if (G_UNLIKELY (bin->children != NULL)) {
   537     g_critical ("could not remove elements from bin %s",
   519     g_critical ("could not remove elements from bin %s",
   538         GST_STR_NULL (GST_OBJECT_NAME (object)));
   520         GST_STR_NULL (GST_OBJECT_NAME (object)));
       
   521   }
       
   522 
       
   523   if (bin->priv) {
       
   524     g_free (bin->priv);
       
   525     bin->priv = NULL;
   539   }
   526   }
   540 
   527 
   541   G_OBJECT_CLASS (parent_class)->dispose (object);
   528   G_OBJECT_CLASS (parent_class)->dispose (object);
   542 }
   529 }
   543 
   530 
   601 
   588 
   602 /* set the index on all elements in this bin
   589 /* set the index on all elements in this bin
   603  *
   590  *
   604  * MT safe
   591  * MT safe
   605  */
   592  */
       
   593 #ifndef GST_DISABLE_INDEX
   606 static void
   594 static void
   607 gst_bin_set_index_func (GstElement * element, GstIndex * index)
   595 gst_bin_set_index_func (GstElement * element, GstIndex * index)
   608 {
   596 {
   609   GstBin *bin;
   597   GstBin *bin;
   610   gboolean done;
   598   GList *children;
   611   GstIterator *it;
       
   612 
   599 
   613   bin = GST_BIN (element);
   600   bin = GST_BIN (element);
   614 
   601 
   615   it = gst_bin_iterate_elements (bin);
   602   GST_OBJECT_LOCK (bin);
   616 
   603   for (children = bin->children; children; children = g_list_next (children)) {
   617   done = FALSE;
   604     GstElement *child = GST_ELEMENT (children->data);
   618   while (!done) {
   605 
   619     gpointer data;
   606     gst_element_set_index (child, index);
   620 
   607   }
   621     switch (gst_iterator_next (it, &data)) {
   608   GST_OBJECT_UNLOCK (bin);
   622       case GST_ITERATOR_OK:
   609 }
   623       {
   610 #endif
   624         GstElement *child = GST_ELEMENT_CAST (data);
       
   625 
       
   626         GST_DEBUG_OBJECT (bin, "setting index on %s", GST_ELEMENT_NAME (child));
       
   627         gst_element_set_index (child, index);
       
   628 
       
   629         gst_object_unref (child);
       
   630         break;
       
   631       }
       
   632       case GST_ITERATOR_RESYNC:
       
   633         GST_DEBUG_OBJECT (bin, "iterator doing resync");
       
   634         gst_iterator_resync (it);
       
   635         break;
       
   636       default:
       
   637       case GST_ITERATOR_DONE:
       
   638         GST_DEBUG_OBJECT (bin, "iterator done");
       
   639         done = TRUE;
       
   640         break;
       
   641     }
       
   642   }
       
   643   gst_iterator_free (it);
       
   644 }
       
   645 
   611 
   646 /* set the clock on all elements in this bin
   612 /* set the clock on all elements in this bin
   647  *
   613  *
   648  * MT safe
   614  * MT safe
   649  */
   615  */
   650 static gboolean
   616 static gboolean
   651 gst_bin_set_clock_func (GstElement * element, GstClock * clock)
   617 gst_bin_set_clock_func (GstElement * element, GstClock * clock)
   652 {
   618 {
       
   619   GList *children;
   653   GstBin *bin;
   620   GstBin *bin;
   654   gboolean done;
       
   655   GstIterator *it;
       
   656   gboolean res = TRUE;
   621   gboolean res = TRUE;
   657 
   622 
   658   bin = GST_BIN (element);
   623   bin = GST_BIN (element);
   659 
   624 
   660   it = gst_bin_iterate_elements (bin);
   625   GST_OBJECT_LOCK (bin);
   661 
   626   if (element->clock != clock) {
   662   done = FALSE;
   627     for (children = bin->children; children; children = g_list_next (children)) {
   663   while (!done) {
   628       GstElement *child = GST_ELEMENT (children->data);
   664     gpointer data;
   629 
   665 
   630       res &= gst_element_set_clock (child, clock);
   666     switch (gst_iterator_next (it, &data)) {
   631     }
   667       case GST_ITERATOR_OK:
   632   }
   668       {
   633   GST_OBJECT_UNLOCK (bin);
   669         GstElement *child = GST_ELEMENT_CAST (data);
       
   670 
       
   671         res &= gst_element_set_clock (child, clock);
       
   672 
       
   673         gst_object_unref (child);
       
   674         break;
       
   675       }
       
   676       case GST_ITERATOR_RESYNC:
       
   677         GST_DEBUG_OBJECT (bin, "iterator doing resync");
       
   678         gst_iterator_resync (it);
       
   679         res = TRUE;
       
   680         break;
       
   681       default:
       
   682       case GST_ITERATOR_DONE:
       
   683         GST_DEBUG_OBJECT (bin, "iterator done");
       
   684         done = TRUE;
       
   685         break;
       
   686     }
       
   687   }
       
   688   gst_iterator_free (it);
       
   689 
   634 
   690   return res;
   635   return res;
   691 }
   636 }
   692 
   637 
   693 /* get the clock for this bin by asking all of the children in this bin
   638 /* get the clock for this bin by asking all of the children in this bin
   784 
   729 
   785   if (target->src)
   730   if (target->src)
   786     eq &= GST_MESSAGE_SRC (message) == target->src;
   731     eq &= GST_MESSAGE_SRC (message) == target->src;
   787   if (target->types)
   732   if (target->types)
   788     eq &= (GST_MESSAGE_TYPE (message) & target->types) != 0;
   733     eq &= (GST_MESSAGE_TYPE (message) & target->types) != 0;
   789   GST_LOG ("looking at message %p: %d", message, eq);
       
   790 
   734 
   791   return (eq ? 0 : 1);
   735   return (eq ? 0 : 1);
   792 }
   736 }
   793 
   737 
   794 static GList *
   738 static GList *
   821   }
   765   }
   822 
   766 
   823   return result;
   767   return result;
   824 }
   768 }
   825 
   769 
   826 /* with LOCK, returns TRUE if message had a valid SRC, takes ownership of
   770 /* with LOCK, returns TRUE if message had a valid SRC, takes ref on
   827  * the message.
   771  * the message.
   828  *
   772  *
   829  * A message that is cached and has the same SRC and type is replaced
   773  * A message that is cached and has the same SRC and type is replaced
   830  * by the given message.
   774  * by the given message.
   831  */
   775  */
   840   name = GST_MESSAGE_TYPE_NAME (message);
   784   name = GST_MESSAGE_TYPE_NAME (message);
   841 
   785 
   842   if ((src = GST_MESSAGE_SRC (message))) {
   786   if ((src = GST_MESSAGE_SRC (message))) {
   843     /* first find the previous message posted by this element */
   787     /* first find the previous message posted by this element */
   844     if ((previous = find_message (bin, src, types))) {
   788     if ((previous = find_message (bin, src, types))) {
   845       GstMessage *previous_msg;
       
   846 
       
   847       /* if we found a previous message, replace it */
   789       /* if we found a previous message, replace it */
   848       previous_msg = previous->data;
   790       gst_message_unref (previous->data);
   849       previous->data = message;
   791       previous->data = message;
   850 
   792 
   851       GST_DEBUG_OBJECT (bin, "replace old message %s from %s with %s message",
   793       GST_DEBUG_OBJECT (bin, "replace old message %s from %s",
   852           GST_MESSAGE_TYPE_NAME (previous_msg), GST_ELEMENT_NAME (src), name);
   794           name, GST_ELEMENT_NAME (src));
   853 
       
   854       gst_message_unref (previous_msg);
       
   855     } else {
   795     } else {
   856       /* keep new message */
   796       /* keep new message */
   857       bin->messages = g_list_prepend (bin->messages, message);
   797       bin->messages = g_list_prepend (bin->messages, message);
   858 
   798 
   859       GST_DEBUG_OBJECT (bin, "got new message %p, %s from %s",
   799       GST_DEBUG_OBJECT (bin, "got new message %p, %s from %s",
   993   }
   933   }
   994 
   934 
   995   bin->children = g_list_prepend (bin->children, element);
   935   bin->children = g_list_prepend (bin->children, element);
   996   bin->numchildren++;
   936   bin->numchildren++;
   997   bin->children_cookie++;
   937   bin->children_cookie++;
   998   bin->priv->structure_cookie++;
       
   999 
   938 
  1000   /* distribute the bus */
   939   /* distribute the bus */
  1001   gst_element_set_bus (element, bin->child_bus);
   940   gst_element_set_bus (element, bin->child_bus);
  1002 
   941 
  1003   /* propagate the current base_time, start_time and clock */
   942   /* propagate the current base_time and clock */
  1004   gst_element_set_base_time (element, GST_ELEMENT (bin)->base_time);
   943   gst_element_set_base_time (element, GST_ELEMENT (bin)->base_time);
  1005   gst_element_set_start_time (element, GST_ELEMENT_START_TIME (bin));
       
  1006   /* it's possible that the element did not accept the clock but
   944   /* it's possible that the element did not accept the clock but
  1007    * that is not important right now. When the pipeline goes to PLAYING,
   945    * that is not important right now. When the pipeline goes to PLAYING,
  1008    * a new clock will be selected */
   946    * a new clock will be selected */
  1009   gst_element_set_clock (element, GST_ELEMENT_CLOCK (bin));
   947   gst_element_set_clock (element, GST_ELEMENT_CLOCK (bin));
  1010 
   948 
  1028           gst_message_new_async_start (GST_OBJECT_CAST (element), FALSE);
   966           gst_message_new_async_start (GST_OBJECT_CAST (element), FALSE);
  1029       break;
   967       break;
  1030     }
   968     }
  1031     case GST_STATE_CHANGE_NO_PREROLL:
   969     case GST_STATE_CHANGE_NO_PREROLL:
  1032       /* ignore all async elements we might have and commit our state */
   970       /* ignore all async elements we might have and commit our state */
  1033       bin_handle_async_done (bin, ret, FALSE);
   971       bin_handle_async_done (bin, ret);
  1034       break;
   972       break;
  1035     case GST_STATE_CHANGE_FAILURE:
   973     case GST_STATE_CHANGE_FAILURE:
  1036       break;
   974       break;
  1037     default:
   975     default:
  1038       break;
   976       break;
  1147 {
  1085 {
  1148   gchar *elem_name;
  1086   gchar *elem_name;
  1149   GstIterator *it;
  1087   GstIterator *it;
  1150   gboolean is_sink, othersink, found;
  1088   gboolean is_sink, othersink, found;
  1151   GstMessage *clock_message = NULL;
  1089   GstMessage *clock_message = NULL;
  1152   GstClock **provided_clock_p;
       
  1153   GstElement **clock_provider_p;
       
  1154   GList *walk, *next;
  1090   GList *walk, *next;
  1155   gboolean other_async, this_async, have_no_preroll;
  1091   gboolean other_async, this_async, have_no_preroll;
  1156   GstStateChangeReturn ret;
  1092   GstStateChangeReturn ret;
  1157 
  1093 
  1158   GST_DEBUG_OBJECT (bin, "element :%s", GST_ELEMENT_NAME (element));
  1094   GST_DEBUG_OBJECT (bin, "element :%s", GST_ELEMENT_NAME (element));
  1210 
  1146 
  1211   /* we now removed the element from the list of elements, increment the cookie
  1147   /* we now removed the element from the list of elements, increment the cookie
  1212    * so that others can detect a change in the children list. */
  1148    * so that others can detect a change in the children list. */
  1213   bin->numchildren--;
  1149   bin->numchildren--;
  1214   bin->children_cookie++;
  1150   bin->children_cookie++;
  1215   bin->priv->structure_cookie++;
       
  1216 
  1151 
  1217   if (is_sink && !othersink) {
  1152   if (is_sink && !othersink) {
  1218     /* we're not a sink anymore */
  1153     /* we're not a sink anymore */
  1219     GST_DEBUG_OBJECT (bin, "we removed the last sink");
  1154     GST_DEBUG_OBJECT (bin, "we removed the last sink");
  1220     GST_OBJECT_FLAG_UNSET (bin, GST_ELEMENT_IS_SINK);
  1155     GST_OBJECT_FLAG_UNSET (bin, GST_ELEMENT_IS_SINK);
  1226   if (bin->clock_provider == element) {
  1161   if (bin->clock_provider == element) {
  1227     GST_DEBUG_OBJECT (bin, "element \"%s\" provided the clock", elem_name);
  1162     GST_DEBUG_OBJECT (bin, "element \"%s\" provided the clock", elem_name);
  1228     bin->clock_dirty = TRUE;
  1163     bin->clock_dirty = TRUE;
  1229     clock_message =
  1164     clock_message =
  1230         gst_message_new_clock_lost (GST_OBJECT_CAST (bin), bin->provided_clock);
  1165         gst_message_new_clock_lost (GST_OBJECT_CAST (bin), bin->provided_clock);
  1231     provided_clock_p = &bin->provided_clock;
       
  1232     clock_provider_p = &bin->clock_provider;
       
  1233     gst_object_replace ((GstObject **) provided_clock_p, NULL);
       
  1234     gst_object_replace ((GstObject **) clock_provider_p, NULL);
       
  1235   }
  1166   }
  1236 
  1167 
  1237   /* remove messages for the element, if there was a pending ASYNC_START
  1168   /* remove messages for the element, if there was a pending ASYNC_START
  1238    * message we must see if removing the element caused the bin to lose its
  1169    * message we must see if removing the element caused the bin to lose its
  1239    * async state. */
  1170    * async state. */
  1240   this_async = FALSE;
  1171   this_async = FALSE;
  1241   other_async = FALSE;
  1172   other_async = FALSE;
  1242   for (walk = bin->messages; walk; walk = next) {
  1173   for (walk = bin->messages; walk; walk = next) {
  1243     GstMessage *message = (GstMessage *) walk->data;
  1174     GstMessage *message = (GstMessage *) walk->data;
  1244     GstElement *src = GST_ELEMENT_CAST (GST_MESSAGE_SRC (message));
  1175     GstElement *src = GST_ELEMENT_CAST (GST_MESSAGE_SRC (message));
  1245     gboolean remove;
       
  1246 
  1176 
  1247     next = g_list_next (walk);
  1177     next = g_list_next (walk);
  1248     remove = FALSE;
  1178 
  1249 
  1179     if (GST_MESSAGE_TYPE (message) == GST_MESSAGE_ASYNC_START) {
  1250     switch (GST_MESSAGE_TYPE (message)) {
  1180       if (src == element)
  1251       case GST_MESSAGE_ASYNC_START:
  1181         this_async = TRUE;
  1252         if (src == element)
  1182       else
  1253           this_async = TRUE;
  1183         other_async = TRUE;
  1254         else
  1184 
  1255           other_async = TRUE;
  1185       GST_DEBUG_OBJECT (GST_MESSAGE_SRC (message),
  1256 
  1186           "looking at message %p", message);
  1257         GST_DEBUG_OBJECT (src, "looking at message %p", message);
  1187     }
  1258         break;
  1188     if (src == element) {
  1259       case GST_MESSAGE_STRUCTURE_CHANGE:
       
  1260       {
       
  1261         GstElement *owner;
       
  1262 
       
  1263         GST_DEBUG_OBJECT (src, "looking at structure change message %p",
       
  1264             message);
       
  1265         /* it's unlikely that this message is still in the list of messages
       
  1266          * because this would mean that a link/unlink is busy in another thread
       
  1267          * while we remove the element. We still have to remove the message
       
  1268          * because we might not receive the done message anymore when the element
       
  1269          * is removed from the bin. */
       
  1270         gst_message_parse_structure_change (message, NULL, &owner, NULL);
       
  1271         if (owner == element)
       
  1272           remove = TRUE;
       
  1273         break;
       
  1274       }
       
  1275       default:
       
  1276         break;
       
  1277     }
       
  1278     if (src == element)
       
  1279       remove = TRUE;
       
  1280 
       
  1281     if (remove) {
       
  1282       /* delete all message types */
  1189       /* delete all message types */
  1283       GST_DEBUG_OBJECT (src, "deleting message %p of element \"%s\"",
  1190       GST_DEBUG_OBJECT (GST_MESSAGE_SRC (message),
  1284           message, elem_name);
  1191           "deleting message %p of element \"%s\"", message, elem_name);
  1285       bin->messages = g_list_delete_link (bin->messages, walk);
  1192       bin->messages = g_list_delete_link (bin->messages, walk);
  1286       gst_message_unref (message);
  1193       gst_message_unref (message);
  1287     }
  1194     }
  1288   }
  1195   }
  1289 
  1196 
  1306     if (have_no_preroll)
  1213     if (have_no_preroll)
  1307       ret = GST_STATE_CHANGE_NO_PREROLL;
  1214       ret = GST_STATE_CHANGE_NO_PREROLL;
  1308     else
  1215     else
  1309       ret = GST_STATE_CHANGE_SUCCESS;
  1216       ret = GST_STATE_CHANGE_SUCCESS;
  1310 
  1217 
  1311     bin_handle_async_done (bin, ret, FALSE);
  1218     bin_handle_async_done (bin, ret);
  1312   } else {
  1219   } else {
  1313     GST_DEBUG_OBJECT (bin,
  1220     GST_DEBUG_OBJECT (bin,
  1314         "recalc state preroll: %d, other async: %d, this async %d",
  1221         "recalc state preroll: %d, other async: %d, this async %d",
  1315         have_no_preroll, other_async, this_async);
  1222         have_no_preroll, other_async, this_async);
  1316 
  1223 
  1786 update_degree (GstElement * element, GstBinSortIterator * bit)
  1693 update_degree (GstElement * element, GstBinSortIterator * bit)
  1787 {
  1694 {
  1788   gboolean linked = FALSE;
  1695   gboolean linked = FALSE;
  1789 
  1696 
  1790   GST_OBJECT_LOCK (element);
  1697   GST_OBJECT_LOCK (element);
  1791   /* don't touch degree if element has no sinkpads */
  1698   /* don't touch degree if element has no sourcepads */
  1792   if (element->numsinkpads != 0) {
  1699   if (element->numsinkpads != 0) {
  1793     /* loop over all sinkpads, decrement degree for all connected
  1700     /* loop over all sinkpads, decrement degree for all connected
  1794      * elements in this bin */
  1701      * elements in this bin */
  1795     GList *pads;
  1702     GList *pads;
  1796 
  1703 
  1797     for (pads = element->sinkpads; pads; pads = g_list_next (pads)) {
  1704     for (pads = element->sinkpads; pads; pads = g_list_next (pads)) {
  1798       GstPad *pad, *peer;
  1705       GstPad *peer;
  1799 
  1706 
  1800       pad = GST_PAD_CAST (pads->data);
  1707       if ((peer = gst_pad_get_peer (GST_PAD_CAST (pads->data)))) {
  1801 
       
  1802       if ((peer = gst_pad_get_peer (pad))) {
       
  1803         GstElement *peer_element;
  1708         GstElement *peer_element;
  1804 
       
  1805         /* we're iterating over the sinkpads, this is the peer and thus the
       
  1806          * srcpad, check if it's busy in a link/unlink */
       
  1807         if (G_UNLIKELY (find_message (bit->bin, GST_OBJECT_CAST (peer),
       
  1808                     GST_MESSAGE_STRUCTURE_CHANGE))) {
       
  1809           gst_object_unref (peer);
       
  1810           continue;
       
  1811         }
       
  1812 
  1709 
  1813         if ((peer_element = gst_pad_get_parent_element (peer))) {
  1710         if ((peer_element = gst_pad_get_parent_element (peer))) {
  1814           GST_OBJECT_LOCK (peer_element);
  1711           GST_OBJECT_LOCK (peer_element);
  1815           /* check that we don't go outside of this bin */
  1712           /* check that we don't go outside of this bin */
  1816           if (GST_OBJECT_CAST (peer_element)->parent ==
  1713           if (GST_OBJECT_CAST (peer_element)->parent ==
  1830             GST_DEBUG_OBJECT (bit->bin,
  1727             GST_DEBUG_OBJECT (bit->bin,
  1831                 "change element %s, degree %d->%d, linked to %s",
  1728                 "change element %s, degree %d->%d, linked to %s",
  1832                 GST_ELEMENT_NAME (peer_element), old_deg, new_deg,
  1729                 GST_ELEMENT_NAME (peer_element), old_deg, new_deg,
  1833                 GST_ELEMENT_NAME (element));
  1730                 GST_ELEMENT_NAME (element));
  1834 
  1731 
  1835             /* update degree, it is possible that an element was in 0 and
  1732             /* update degree */
  1836              * reaches -1 here. This would mean that the element had no sinkpads
       
  1837              * but became linked while the state change was happening. We will
       
  1838              * resync on this with the structure change message. */
       
  1839             if (new_deg == 0) {
  1733             if (new_deg == 0) {
  1840               /* degree hit 0, add to queue */
  1734               /* degree hit 0, add to queue */
  1841               add_to_queue (bit, peer_element);
  1735               add_to_queue (bit, peer_element);
  1842             } else {
  1736             } else {
  1843               HASH_SET_DEGREE (bit, peer_element, new_deg);
  1737               HASH_SET_DEGREE (bit, peer_element, new_deg);
  1961    * method already */
  1855    * method already */
  1962   result = (GstBinSortIterator *)
  1856   result = (GstBinSortIterator *)
  1963       gst_iterator_new (sizeof (GstBinSortIterator),
  1857       gst_iterator_new (sizeof (GstBinSortIterator),
  1964       GST_TYPE_ELEMENT,
  1858       GST_TYPE_ELEMENT,
  1965       GST_OBJECT_GET_LOCK (bin),
  1859       GST_OBJECT_GET_LOCK (bin),
  1966       &bin->priv->structure_cookie,
  1860       &bin->children_cookie,
  1967       (GstIteratorNextFunction) gst_bin_sort_iterator_next,
  1861       (GstIteratorNextFunction) gst_bin_sort_iterator_next,
  1968       (GstIteratorItemFunction) NULL,
  1862       (GstIteratorItemFunction) NULL,
  1969       (GstIteratorResyncFunction) gst_bin_sort_iterator_resync,
  1863       (GstIteratorResyncFunction) gst_bin_sort_iterator_resync,
  1970       (GstIteratorFreeFunction) gst_bin_sort_iterator_free);
  1864       (GstIteratorFreeFunction) gst_bin_sort_iterator_free);
  1971   result->queue = g_queue_new ();
  1865   result->queue = g_queue_new ();
  2013   return result;
  1907   return result;
  2014 }
  1908 }
  2015 
  1909 
  2016 static GstStateChangeReturn
  1910 static GstStateChangeReturn
  2017 gst_bin_element_set_state (GstBin * bin, GstElement * element,
  1911 gst_bin_element_set_state (GstBin * bin, GstElement * element,
  2018     GstClockTime base_time, GstClockTime start_time, GstState current,
  1912     GstClockTime base_time, GstState current, GstState next)
  2019     GstState next)
       
  2020 {
  1913 {
  2021   GstStateChangeReturn ret;
  1914   GstStateChangeReturn ret;
  2022   gboolean locked;
  1915   gboolean locked;
  2023   GList *found;
  1916   GList *found;
  2024 
  1917 
  2025   GST_STATE_LOCK (element);
  1918   /* peel off the locked flag */
  2026 
       
  2027   GST_OBJECT_LOCK (element);
  1919   GST_OBJECT_LOCK (element);
  2028   /* set base_time and start time on child */
       
  2029   GST_ELEMENT_START_TIME (element) = start_time;
       
  2030   element->base_time = base_time;
       
  2031   /* peel off the locked flag */
       
  2032   locked = GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_LOCKED_STATE);
  1920   locked = GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_LOCKED_STATE);
  2033   /* get previous state return */
  1921   /* get previous state return */
  2034   ret = GST_STATE_RETURN (element);
  1922   ret = GST_STATE_RETURN (element);
  2035   GST_OBJECT_UNLOCK (element);
  1923   GST_OBJECT_UNLOCK (element);
  2036 
  1924 
  2080   GST_DEBUG_OBJECT (bin,
  1968   GST_DEBUG_OBJECT (bin,
  2081       "setting element %s to %s, base_time %" GST_TIME_FORMAT,
  1969       "setting element %s to %s, base_time %" GST_TIME_FORMAT,
  2082       GST_ELEMENT_NAME (element), gst_element_state_get_name (next),
  1970       GST_ELEMENT_NAME (element), gst_element_state_get_name (next),
  2083       GST_TIME_ARGS (base_time));
  1971       GST_TIME_ARGS (base_time));
  2084 
  1972 
       
  1973   /* set base_time on child */
       
  1974   gst_element_set_base_time (element, base_time);
       
  1975 
  2085   /* change state */
  1976   /* change state */
  2086   ret = gst_element_set_state (element, next);
  1977   ret = gst_element_set_state (element, next);
  2087 
       
  2088   GST_STATE_UNLOCK (element);
       
  2089 
  1978 
  2090   return ret;
  1979   return ret;
  2091 
  1980 
  2092 locked:
  1981 locked:
  2093   {
  1982   {
  2094     GST_DEBUG_OBJECT (element,
  1983     GST_DEBUG_OBJECT (element,
  2095         "element is locked, return previous return %s",
  1984         "element is locked, return previous return %s",
  2096         gst_element_state_change_return_get_name (ret));
  1985         gst_element_state_change_return_get_name (ret));
  2097     GST_STATE_UNLOCK (element);
       
  2098     return ret;
  1986     return ret;
  2099   }
  1987   }
  2100 was_busy:
  1988 was_busy:
  2101   {
  1989   {
  2102     GST_DEBUG_OBJECT (element, "element was busy, delaying state change");
  1990     GST_DEBUG_OBJECT (element, "element was busy, delaying state change");
  2103     GST_OBJECT_UNLOCK (bin);
  1991     GST_OBJECT_UNLOCK (bin);
  2104     GST_STATE_UNLOCK (element);
       
  2105     return GST_STATE_CHANGE_ASYNC;
  1992     return GST_STATE_CHANGE_ASYNC;
  2106   }
  1993   }
  2107 }
  1994 }
  2108 
  1995 
  2109 /* gst_iterator_fold functions for pads_activate
  1996 /* gst_iterator_fold functions for pads_activate
  2186     GST_DEBUG_OBJECT (bin, "source pads_activate failed");
  2073     GST_DEBUG_OBJECT (bin, "source pads_activate failed");
  2187     return FALSE;
  2074     return FALSE;
  2188   }
  2075   }
  2189 }
  2076 }
  2190 
  2077 
  2191 /**
  2078 /* do latency correction. We do a latency query on the bin, and then send a
  2192  * gst_bin_recalculate_latency:
  2079  * LATENCY event on the elements fo configure them */
  2193  * @bin: a #GstBin
       
  2194  *
       
  2195  * Query @bin for the current latency using and reconfigures this latency to all the
       
  2196  * elements with a LATENCY event.
       
  2197  *
       
  2198  * This method is typically called on the pipeline when a #GST_MESSAGE_LATENCY
       
  2199  * is posted on the bus.
       
  2200  *
       
  2201  * This function simply emits the 'do-latency' signal so any custom latency
       
  2202  * calculations will be performed.
       
  2203  *
       
  2204  * Returns: %TRUE if the latency could be queried and reconfigured.
       
  2205  *
       
  2206  * Since: 0.10.22.
       
  2207  */
       
  2208 #ifdef __SYMBIAN32__
       
  2209 EXPORT_C
       
  2210 #endif
       
  2211 
       
  2212 gboolean
       
  2213 gst_bin_recalculate_latency (GstBin * bin)
       
  2214 {
       
  2215   gboolean res;
       
  2216 
       
  2217   g_signal_emit (G_OBJECT (bin), gst_bin_signals[DO_LATENCY], 0, &res);
       
  2218   GST_DEBUG_OBJECT (bin, "latency returned %d", res);
       
  2219 
       
  2220   return res;
       
  2221 }
       
  2222 
       
  2223 static gboolean
  2080 static gboolean
  2224 gst_bin_do_latency_func (GstBin * bin)
  2081 do_bin_latency (GstElement * element)
  2225 {
  2082 {
  2226   GstQuery *query;
  2083   GstQuery *query;
  2227   GstElement *element;
       
  2228   GstClockTime min_latency, max_latency;
  2084   GstClockTime min_latency, max_latency;
  2229   gboolean res;
  2085   gboolean res;
  2230 
       
  2231   g_return_val_if_fail (GST_IS_BIN (bin), FALSE);
       
  2232 
       
  2233   element = GST_ELEMENT_CAST (bin);
       
  2234 
  2086 
  2235   GST_DEBUG_OBJECT (element, "querying latency");
  2087   GST_DEBUG_OBJECT (element, "querying latency");
  2236 
  2088 
  2237   query = gst_query_new_latency ();
  2089   query = gst_query_new_latency ();
  2238   if ((res = gst_element_query (element, query))) {
  2090   if ((res = gst_element_query (element, query))) {
  2282   GstBin *bin;
  2134   GstBin *bin;
  2283   GstStateChangeReturn ret;
  2135   GstStateChangeReturn ret;
  2284   GstState current, next;
  2136   GstState current, next;
  2285   gboolean have_async;
  2137   gboolean have_async;
  2286   gboolean have_no_preroll;
  2138   gboolean have_no_preroll;
  2287   GstClockTime base_time, start_time;
  2139   GstClockTime base_time;
  2288   GstIterator *it;
  2140   GstIterator *it;
  2289   gboolean done;
  2141   gboolean done;
  2290 
  2142 
  2291   /* we don't need to take the STATE_LOCK, it is already taken */
  2143   /* we don't need to take the STATE_LOCK, it is already taken */
  2292   current = (GstState) GST_STATE_TRANSITION_CURRENT (transition);
  2144   current = (GstState) GST_STATE_TRANSITION_CURRENT (transition);
  2306       GST_OBJECT_LOCK (bin);
  2158       GST_OBJECT_LOCK (bin);
  2307       toplevel = BIN_IS_TOPLEVEL (bin);
  2159       toplevel = BIN_IS_TOPLEVEL (bin);
  2308       GST_OBJECT_UNLOCK (bin);
  2160       GST_OBJECT_UNLOCK (bin);
  2309 
  2161 
  2310       if (toplevel)
  2162       if (toplevel)
  2311         gst_bin_recalculate_latency (bin);
  2163         do_bin_latency (element);
  2312       break;
  2164       break;
  2313     }
  2165     }
  2314     case GST_STATE_PAUSED:
  2166     case GST_STATE_PAUSED:
  2315       /* Clear EOS list on next PAUSED */
  2167       /* Clear EOS list on next PAUSED */
  2316       GST_OBJECT_LOCK (bin);
  2168       GST_OBJECT_LOCK (bin);
  2356   have_async = FALSE;
  2208   have_async = FALSE;
  2357 
  2209 
  2358 restart:
  2210 restart:
  2359   /* take base_time */
  2211   /* take base_time */
  2360   base_time = gst_element_get_base_time (element);
  2212   base_time = gst_element_get_base_time (element);
  2361   start_time = gst_element_get_start_time (element);
       
  2362 
  2213 
  2363   have_no_preroll = FALSE;
  2214   have_no_preroll = FALSE;
  2364 
  2215 
  2365   done = FALSE;
  2216   done = FALSE;
  2366   while (!done) {
  2217   while (!done) {
  2372         GstElement *child;
  2223         GstElement *child;
  2373 
  2224 
  2374         child = GST_ELEMENT_CAST (data);
  2225         child = GST_ELEMENT_CAST (data);
  2375 
  2226 
  2376         /* set state and base_time now */
  2227         /* set state and base_time now */
  2377         ret =
  2228         ret = gst_bin_element_set_state (bin, child, base_time, current, next);
  2378             gst_bin_element_set_state (bin, child, base_time, start_time,
       
  2379             current, next);
       
  2380 
  2229 
  2381         switch (ret) {
  2230         switch (ret) {
  2382           case GST_STATE_CHANGE_SUCCESS:
  2231           case GST_STATE_CHANGE_SUCCESS:
  2383             GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
  2232             GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
  2384                 "child '%s' changed state to %d(%s) successfully",
  2233                 "child '%s' changed state to %d(%s) successfully",
  2429   ret = parent_class->change_state (element, transition);
  2278   ret = parent_class->change_state (element, transition);
  2430   if (G_UNLIKELY (ret == GST_STATE_CHANGE_FAILURE))
  2279   if (G_UNLIKELY (ret == GST_STATE_CHANGE_FAILURE))
  2431     goto done;
  2280     goto done;
  2432 
  2281 
  2433   if (have_no_preroll) {
  2282   if (have_no_preroll) {
  2434     GST_CAT_DEBUG (GST_CAT_STATES,
       
  2435         "we have NO_PREROLL elements %s -> NO_PREROLL",
       
  2436         gst_element_state_change_return_get_name (ret));
       
  2437     ret = GST_STATE_CHANGE_NO_PREROLL;
  2283     ret = GST_STATE_CHANGE_NO_PREROLL;
  2438   } else if (have_async) {
  2284   } else if (have_async) {
  2439     GST_CAT_DEBUG (GST_CAT_STATES, "we have ASYNC elements %s -> ASYNC",
       
  2440         gst_element_state_change_return_get_name (ret));
       
  2441     ret = GST_STATE_CHANGE_ASYNC;
  2285     ret = GST_STATE_CHANGE_ASYNC;
  2442   }
  2286   }
  2443 
  2287 
  2444 done:
  2288 done:
  2445   gst_iterator_free (it);
  2289   gst_iterator_free (it);
  2446 
  2290 
  2447   GST_OBJECT_LOCK (bin);
  2291   GST_OBJECT_LOCK (bin);
  2448   bin->polling = FALSE;
  2292   bin->polling = FALSE;
  2449   /* it's possible that we did not get ASYNC from the children while the bin is
  2293   if (ret != GST_STATE_CHANGE_ASYNC) {
  2450    * simulating ASYNC behaviour by posting an ASYNC_DONE message on the bus with
  2294     /* no element returned ASYNC, we can just complete. */
  2451    * itself as the source. In that case we still want to check if the state
       
  2452    * change completed. */
       
  2453   if (ret != GST_STATE_CHANGE_ASYNC && !bin->priv->pending_async_done) {
       
  2454     /* no element returned ASYNC and there are no pending async_done messages,
       
  2455      * we can just complete. */
       
  2456     GST_DEBUG_OBJECT (bin, "no async elements");
  2295     GST_DEBUG_OBJECT (bin, "no async elements");
  2457     goto state_end;
  2296     goto state_end;
  2458   }
  2297   }
  2459   /* when we get here an ASYNC element was found */
  2298   /* when we get here an ASYNC element was found */
  2460   if (GST_STATE_TARGET (bin) <= GST_STATE_READY) {
  2299   if (GST_STATE_TARGET (bin) <= GST_STATE_READY) {
  2472      * change. We will still return ASYNC for consistency but we commit the
  2311      * change. We will still return ASYNC for consistency but we commit the
  2473      * state already so that a _get_state() will return immediatly. */
  2312      * state already so that a _get_state() will return immediatly. */
  2474     bin_remove_messages (bin, NULL, GST_MESSAGE_ASYNC_DONE);
  2313     bin_remove_messages (bin, NULL, GST_MESSAGE_ASYNC_DONE);
  2475 
  2314 
  2476     GST_DEBUG_OBJECT (bin, "async elements commited");
  2315     GST_DEBUG_OBJECT (bin, "async elements commited");
  2477     bin_handle_async_done (bin, GST_STATE_CHANGE_SUCCESS, FALSE);
  2316     bin_handle_async_done (bin, GST_STATE_CHANGE_SUCCESS);
  2478   }
  2317   }
  2479 
  2318 
  2480 state_end:
  2319 state_end:
  2481   bin->priv->pending_async_done = FALSE;
       
  2482   GST_OBJECT_UNLOCK (bin);
  2320   GST_OBJECT_UNLOCK (bin);
  2483 
  2321 
  2484   GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
  2322   GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
  2485       "done changing bin's state from %s to %s, now in %s, ret %s",
  2323       "done changing bin's state from %s to %s, now in %s, ret %s",
  2486       gst_element_state_get_name (current),
  2324       gst_element_state_get_name (current),
  2565 gst_bin_continue_func (BinContinueData * data)
  2403 gst_bin_continue_func (BinContinueData * data)
  2566 {
  2404 {
  2567   GstBin *bin;
  2405   GstBin *bin;
  2568   GstState current, next, pending;
  2406   GstState current, next, pending;
  2569   GstStateChange transition;
  2407   GstStateChange transition;
       
  2408   GstStateChangeReturn ret;
  2570 
  2409 
  2571   bin = data->bin;
  2410   bin = data->bin;
  2572   pending = data->pending;
  2411   pending = data->pending;
  2573 
  2412 
  2574   GST_DEBUG_OBJECT (bin, "waiting for state lock");
  2413   GST_DEBUG_OBJECT (bin, "waiting for state lock");
  2585   current = GST_STATE (bin);
  2424   current = GST_STATE (bin);
  2586   next = GST_STATE_GET_NEXT (current, pending);
  2425   next = GST_STATE_GET_NEXT (current, pending);
  2587   transition = (GstStateChange) GST_STATE_TRANSITION (current, next);
  2426   transition = (GstStateChange) GST_STATE_TRANSITION (current, next);
  2588 
  2427 
  2589   GST_STATE_NEXT (bin) = next;
  2428   GST_STATE_NEXT (bin) = next;
  2590   GST_STATE_PENDING (bin) = pending;
       
  2591   /* mark busy */
  2429   /* mark busy */
  2592   GST_STATE_RETURN (bin) = GST_STATE_CHANGE_ASYNC;
  2430   GST_STATE_RETURN (bin) = GST_STATE_CHANGE_ASYNC;
  2593   GST_OBJECT_UNLOCK (bin);
  2431   GST_OBJECT_UNLOCK (bin);
  2594 
  2432 
  2595   GST_CAT_INFO_OBJECT (GST_CAT_STATES, bin,
  2433   GST_CAT_INFO_OBJECT (GST_CAT_STATES, bin,
  2596       "continue state change %s to %s, final %s",
  2434       "continue state change %s to %s, final %s",
  2597       gst_element_state_get_name (current),
  2435       gst_element_state_get_name (current),
  2598       gst_element_state_get_name (next), gst_element_state_get_name (pending));
  2436       gst_element_state_get_name (next), gst_element_state_get_name (pending));
  2599 
  2437 
  2600   gst_element_change_state (GST_ELEMENT_CAST (bin), transition);
  2438   ret = gst_element_change_state (GST_ELEMENT_CAST (bin), transition);
  2601 
  2439 
  2602   GST_STATE_UNLOCK (bin);
  2440   GST_STATE_UNLOCK (bin);
  2603   GST_DEBUG_OBJECT (bin, "state continue done");
  2441   GST_DEBUG_OBJECT (bin, "state continue done");
  2604   gst_object_unref (bin);
  2442   gst_object_unref (bin);
  2605   g_free (data);
  2443   g_free (data);
  2673 
  2511 
  2674   /* async starts are ignored when we are NO_PREROLL */
  2512   /* async starts are ignored when we are NO_PREROLL */
  2675   if (GST_STATE_RETURN (bin) == GST_STATE_CHANGE_NO_PREROLL)
  2513   if (GST_STATE_RETURN (bin) == GST_STATE_CHANGE_NO_PREROLL)
  2676     goto was_no_preroll;
  2514     goto was_no_preroll;
  2677 
  2515 
       
  2516 
  2678   old_state = GST_STATE (bin);
  2517   old_state = GST_STATE (bin);
  2679 
  2518 
  2680   /* when we PLAYING we go back to PAUSED, when preroll happens, we go back to
  2519   /* when we PLAYING we go back to PAUSED, when preroll happens, we go back to
  2681    * PLAYING after optionally redistributing the base_time. */
  2520    * PLAYING after optionally redistributing the base_time. */
  2682   if (old_state > GST_STATE_PAUSED)
  2521   if (old_state > GST_STATE_PAUSED)
  2731 /* this function is called when there are no more async elements in the bin. We
  2570 /* this function is called when there are no more async elements in the bin. We
  2732  * post a state changed message and an ASYNC_DONE message.
  2571  * post a state changed message and an ASYNC_DONE message.
  2733  * This function is called with the OBJECT lock.
  2572  * This function is called with the OBJECT lock.
  2734  */
  2573  */
  2735 static void
  2574 static void
  2736 bin_handle_async_done (GstBin * bin, GstStateChangeReturn ret,
  2575 bin_handle_async_done (GstBin * bin, GstStateChangeReturn ret)
  2737     gboolean flag_pending)
       
  2738 {
  2576 {
  2739   GstState current, pending, target;
  2577   GstState current, pending, target;
  2740   GstStateChangeReturn old_ret;
  2578   GstStateChangeReturn old_ret;
  2741   GstState old_state, old_next;
  2579   GstState old_state, old_next;
  2742   gboolean toplevel;
  2580   gboolean toplevel;
  2776         gst_element_state_get_name (pending));
  2614         gst_element_state_get_name (pending));
  2777 
  2615 
  2778     /* update current state */
  2616     /* update current state */
  2779     current = GST_STATE (bin) = old_next;
  2617     current = GST_STATE (bin) = old_next;
  2780   } else {
  2618   } else {
  2781     GST_CAT_INFO_OBJECT (GST_CAT_STATES, bin,
       
  2782         "setting state from %s to %s, pending %s",
       
  2783         gst_element_state_get_name (old_state),
       
  2784         gst_element_state_get_name (old_state),
       
  2785         gst_element_state_get_name (pending));
       
  2786     current = old_state;
  2619     current = old_state;
  2787   }
  2620   }
  2788 
  2621 
  2789   /* get our toplevel state */
  2622   /* get our toplevel state */
  2790   toplevel = BIN_IS_TOPLEVEL (bin);
  2623   toplevel = BIN_IS_TOPLEVEL (bin);
  2812     cont->cookie = GST_ELEMENT_CAST (bin)->state_cookie;
  2645     cont->cookie = GST_ELEMENT_CAST (bin)->state_cookie;
  2813     /* pending target state */
  2646     /* pending target state */
  2814     cont->pending = pending;
  2647     cont->pending = pending;
  2815     /* mark busy */
  2648     /* mark busy */
  2816     GST_STATE_RETURN (bin) = GST_STATE_CHANGE_ASYNC;
  2649     GST_STATE_RETURN (bin) = GST_STATE_CHANGE_ASYNC;
  2817     GST_STATE_NEXT (bin) = GST_STATE_GET_NEXT (old_state, pending);
  2650     GST_STATE_NEXT (bin) = pending;
  2818   }
  2651   }
  2819 
  2652 
  2820   if (old_next != GST_STATE_PLAYING) {
  2653   if (old_next != GST_STATE_PLAYING) {
  2821     if (old_state != old_next || old_ret == GST_STATE_CHANGE_ASYNC) {
  2654     if (old_state != old_next || old_ret == GST_STATE_CHANGE_ASYNC) {
  2822       smessage = gst_message_new_state_changed (GST_OBJECT_CAST (bin),
  2655       smessage = gst_message_new_state_changed (GST_OBJECT_CAST (bin),
  2852     return;
  2685     return;
  2853   }
  2686   }
  2854 was_busy:
  2687 was_busy:
  2855   {
  2688   {
  2856     GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin, "state change busy");
  2689     GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin, "state change busy");
  2857     /* if we were busy with a state change and we are requested to flag a
       
  2858      * pending async done, we do so here */
       
  2859     if (flag_pending)
       
  2860       bin->priv->pending_async_done = TRUE;
       
  2861     return;
  2690     return;
  2862   }
  2691   }
  2863 nothing_pending:
  2692 nothing_pending:
  2864   {
  2693   {
  2865     GST_CAT_INFO_OBJECT (GST_CAT_STATES, bin, "nothing pending");
  2694     GST_CAT_INFO_OBJECT (GST_CAT_STATES, bin, "nothing pending");
  2924 static void
  2753 static void
  2925 gst_bin_handle_message_func (GstBin * bin, GstMessage * message)
  2754 gst_bin_handle_message_func (GstBin * bin, GstMessage * message)
  2926 {
  2755 {
  2927   GstObject *src;
  2756   GstObject *src;
  2928   GstMessageType type;
  2757   GstMessageType type;
  2929   GstMessage *tmessage;
       
  2930   guint32 seqnum;
       
  2931 
  2758 
  2932   src = GST_MESSAGE_SRC (message);
  2759   src = GST_MESSAGE_SRC (message);
  2933   type = GST_MESSAGE_TYPE (message);
  2760   type = GST_MESSAGE_TYPE (message);
  2934 
  2761 
       
  2762 // Message src can be NULL
       
  2763   if(src)
  2935   GST_DEBUG_OBJECT (bin, "[msg %p] handling child %s message of type %s",
  2764   GST_DEBUG_OBJECT (bin, "[msg %p] handling child %s message of type %s",
  2936       message, src ? GST_ELEMENT_NAME (src) : "(NULL)",
  2765       message, GST_ELEMENT_NAME (src), GST_MESSAGE_TYPE_NAME (message));
  2937       GST_MESSAGE_TYPE_NAME (message));
  2766   else
  2938 
  2767   GST_DEBUG_OBJECT (bin, "[msg %p] handling child %s message of type %s",
       
  2768             message, "Null ", GST_MESSAGE_TYPE_NAME (message));
       
  2769   
  2939   switch (type) {
  2770   switch (type) {
  2940     case GST_MESSAGE_EOS:
  2771     case GST_MESSAGE_EOS:
  2941     {
  2772     {
  2942       gboolean eos;
  2773       gboolean eos;
  2943 
  2774 
  2947       eos = is_eos (bin);
  2778       eos = is_eos (bin);
  2948       GST_OBJECT_UNLOCK (bin);
  2779       GST_OBJECT_UNLOCK (bin);
  2949 
  2780 
  2950       /* if we are completely EOS, we forward an EOS message */
  2781       /* if we are completely EOS, we forward an EOS message */
  2951       if (eos) {
  2782       if (eos) {
  2952         seqnum = gst_message_get_seqnum (message);
  2783         GST_DEBUG_OBJECT (bin, "all sinks posted EOS");
  2953         tmessage = gst_message_new_eos (GST_OBJECT_CAST (bin));
  2784         gst_element_post_message (GST_ELEMENT_CAST (bin),
  2954         gst_message_set_seqnum (tmessage, seqnum);
  2785             gst_message_new_eos (GST_OBJECT_CAST (bin)));
  2955 
       
  2956         GST_DEBUG_OBJECT (bin,
       
  2957             "all sinks posted EOS, posting seqnum #%" G_GUINT32_FORMAT, seqnum);
       
  2958         gst_element_post_message (GST_ELEMENT_CAST (bin), tmessage);
       
  2959       }
  2786       }
  2960       break;
  2787       break;
  2961     }
  2788     }
  2962     case GST_MESSAGE_STATE_DIRTY:
  2789     case GST_MESSAGE_STATE_DIRTY:
  2963     {
  2790     {
  2965 
  2792 
  2966       /* free message */
  2793       /* free message */
  2967       gst_message_unref (message);
  2794       gst_message_unref (message);
  2968       break;
  2795       break;
  2969     }
  2796     }
  2970     case GST_MESSAGE_SEGMENT_START:{
  2797     case GST_MESSAGE_SEGMENT_START:
  2971       gboolean post = FALSE;
       
  2972       GstFormat format;
       
  2973       gint64 position;
       
  2974 
       
  2975       gst_message_parse_segment_start (message, &format, &position);
       
  2976       seqnum = gst_message_get_seqnum (message);
       
  2977 
       
  2978       GST_OBJECT_LOCK (bin);
  2798       GST_OBJECT_LOCK (bin);
  2979       /* if this is the first segment-start, post to parent but not to the
       
  2980        * application */
       
  2981       if (!find_message (bin, NULL, GST_MESSAGE_SEGMENT_START) &&
       
  2982           (GST_OBJECT_PARENT (bin) != NULL)) {
       
  2983         post = TRUE;
       
  2984       }
       
  2985       /* replace any previous segment_start message from this source
  2799       /* replace any previous segment_start message from this source
  2986        * with the new segment start message */
  2800        * with the new segment start message */
  2987       bin_replace_message (bin, message, GST_MESSAGE_SEGMENT_START);
  2801       bin_replace_message (bin, message, GST_MESSAGE_SEGMENT_START);
  2988       GST_OBJECT_UNLOCK (bin);
  2802       GST_OBJECT_UNLOCK (bin);
  2989       if (post) {
       
  2990         tmessage = gst_message_new_segment_start (GST_OBJECT_CAST (bin),
       
  2991             format, position);
       
  2992         gst_message_set_seqnum (tmessage, seqnum);
       
  2993 
       
  2994         /* post segment start with initial format and position. */
       
  2995         GST_DEBUG_OBJECT (bin, "posting SEGMENT_START (%u) bus message: %p",
       
  2996             seqnum, message);
       
  2997         gst_element_post_message (GST_ELEMENT_CAST (bin), tmessage);
       
  2998       }
       
  2999       break;
  2803       break;
  3000     }
       
  3001     case GST_MESSAGE_SEGMENT_DONE:
  2804     case GST_MESSAGE_SEGMENT_DONE:
  3002     {
  2805     {
  3003       gboolean post = FALSE;
  2806       gboolean post = FALSE;
  3004       GstFormat format;
  2807       GstFormat format;
  3005       gint64 position;
  2808       gint64 position;
  3006 
  2809 
  3007       gst_message_parse_segment_done (message, &format, &position);
  2810       gst_message_parse_segment_done (message, &format, &position);
  3008       seqnum = gst_message_get_seqnum (message);
       
  3009 
  2811 
  3010       GST_OBJECT_LOCK (bin);
  2812       GST_OBJECT_LOCK (bin);
  3011       bin_replace_message (bin, message, GST_MESSAGE_SEGMENT_START);
  2813       bin_replace_message (bin, message, GST_MESSAGE_SEGMENT_START);
  3012       /* if there are no more segment_start messages, everybody posted
  2814       /* if there are no more segment_start messages, everybody posted
  3013        * a segment_done and we can post one on the bus. */
  2815        * a segment_done and we can post one on the bus. */
  3019         /* remove all old segment_done messages */
  2821         /* remove all old segment_done messages */
  3020         bin_remove_messages (bin, NULL, GST_MESSAGE_SEGMENT_DONE);
  2822         bin_remove_messages (bin, NULL, GST_MESSAGE_SEGMENT_DONE);
  3021       }
  2823       }
  3022       GST_OBJECT_UNLOCK (bin);
  2824       GST_OBJECT_UNLOCK (bin);
  3023       if (post) {
  2825       if (post) {
  3024         tmessage = gst_message_new_segment_done (GST_OBJECT_CAST (bin),
       
  3025             format, position);
       
  3026         gst_message_set_seqnum (tmessage, seqnum);
       
  3027 
       
  3028         /* post segment done with latest format and position. */
  2826         /* post segment done with latest format and position. */
  3029         GST_DEBUG_OBJECT (bin, "posting SEGMENT_DONE (%u) bus message: %p",
  2827         gst_element_post_message (GST_ELEMENT_CAST (bin),
  3030             seqnum, message);
  2828             gst_message_new_segment_done (GST_OBJECT_CAST (bin),
  3031         gst_element_post_message (GST_ELEMENT_CAST (bin), tmessage);
  2829                 format, position));
  3032       }
  2830       }
  3033       break;
  2831       break;
  3034     }
  2832     }
  3035     case GST_MESSAGE_DURATION:
  2833     case GST_MESSAGE_DURATION:
  3036     {
  2834     {
  3097     }
  2895     }
  3098     case GST_MESSAGE_ASYNC_START:
  2896     case GST_MESSAGE_ASYNC_START:
  3099     {
  2897     {
  3100       gboolean new_base_time;
  2898       gboolean new_base_time;
  3101       GstState target;
  2899       GstState target;
  3102 
  2900 	if(src)
  3103       GST_DEBUG_OBJECT (bin, "ASYNC_START message %p, %s", message,
  2901       GST_DEBUG_OBJECT (bin, "ASYNC_START message %p, %s", message,
  3104           src ? GST_OBJECT_NAME (src) : "(NULL)");
  2902           GST_OBJECT_NAME (src));
       
  2903 	else
       
  2904 	GST_DEBUG_OBJECT (bin, "ASYNC_START message %p, %s", message,
       
  2905           "Null Source");
  3105 
  2906 
  3106       gst_message_parse_async_start (message, &new_base_time);
  2907       gst_message_parse_async_start (message, &new_base_time);
  3107 
  2908 
  3108       GST_OBJECT_LOCK (bin);
  2909       GST_OBJECT_LOCK (bin);
  3109       /* we ignore the message if we are going to <= READY */
  2910       /* we ignore the message if we are going to <= READY */
  3128       }
  2929       }
  3129     }
  2930     }
  3130     case GST_MESSAGE_ASYNC_DONE:
  2931     case GST_MESSAGE_ASYNC_DONE:
  3131     {
  2932     {
  3132       GstState target;
  2933       GstState target;
  3133 
  2934 	  
       
  2935 	  if(src)
  3134       GST_DEBUG_OBJECT (bin, "ASYNC_DONE message %p, %s", message,
  2936       GST_DEBUG_OBJECT (bin, "ASYNC_DONE message %p, %s", message,
  3135           src ? GST_OBJECT_NAME (src) : "(NULL)");
  2937           GST_OBJECT_NAME (src));
       
  2938 	  else
       
  2939 	  GST_DEBUG_OBJECT (bin, "ASYNC_DONE message %p, %s", message,
       
  2940           "Null Source");
  3136 
  2941 
  3137       GST_OBJECT_LOCK (bin);
  2942       GST_OBJECT_LOCK (bin);
  3138       target = GST_STATE_TARGET (bin);
  2943       target = GST_STATE_TARGET (bin);
  3139       /* ignore messages if we are shutting down */
  2944       /* ignore messages if we are shutting down */
  3140       if (target <= GST_STATE_READY)
  2945       if (target <= GST_STATE_READY)
  3147       if (!find_message (bin, NULL, GST_MESSAGE_ASYNC_START)) {
  2952       if (!find_message (bin, NULL, GST_MESSAGE_ASYNC_START)) {
  3148         /* nothing found, remove all old ASYNC_DONE messages */
  2953         /* nothing found, remove all old ASYNC_DONE messages */
  3149         bin_remove_messages (bin, NULL, GST_MESSAGE_ASYNC_DONE);
  2954         bin_remove_messages (bin, NULL, GST_MESSAGE_ASYNC_DONE);
  3150 
  2955 
  3151         GST_DEBUG_OBJECT (bin, "async elements commited");
  2956         GST_DEBUG_OBJECT (bin, "async elements commited");
  3152         /* when we get an async done message when a state change was busy, we
  2957         bin_handle_async_done (bin, GST_STATE_CHANGE_SUCCESS);
  3153          * need to set the pending_done flag so that at the end of the state
       
  3154          * change we can see if we need to verify pending async elements, hence
       
  3155          * the TRUE argument here. */
       
  3156         bin_handle_async_done (bin, GST_STATE_CHANGE_SUCCESS, TRUE);
       
  3157       } else {
       
  3158         GST_DEBUG_OBJECT (bin, "there are more async elements pending");
       
  3159       }
  2958       }
  3160       GST_OBJECT_UNLOCK (bin);
  2959       GST_OBJECT_UNLOCK (bin);
  3161       break;
  2960       break;
  3162 
  2961 
  3163     ignore_done_message:
  2962     ignore_done_message:
  3167         GST_OBJECT_UNLOCK (bin);
  2966         GST_OBJECT_UNLOCK (bin);
  3168         gst_message_unref (message);
  2967         gst_message_unref (message);
  3169         break;
  2968         break;
  3170       }
  2969       }
  3171     }
  2970     }
  3172     case GST_MESSAGE_STRUCTURE_CHANGE:
       
  3173     {
       
  3174       gboolean busy;
       
  3175 
       
  3176       gst_message_parse_structure_change (message, NULL, NULL, &busy);
       
  3177 
       
  3178       GST_OBJECT_LOCK (bin);
       
  3179       if (busy) {
       
  3180         /* while the pad is busy, avoid following it when doing state changes.
       
  3181          * Don't update the cookie yet, we will do that after the structure
       
  3182          * change finished and we are ready to inspect the new updated
       
  3183          * structure. */
       
  3184         bin_replace_message (bin, message, GST_MESSAGE_STRUCTURE_CHANGE);
       
  3185         message = NULL;
       
  3186       } else {
       
  3187         /* a pad link/unlink ended, signal the state change iterator that we
       
  3188          * need to resync by updating the structure_cookie. */
       
  3189         bin_remove_messages (bin, GST_MESSAGE_SRC (message),
       
  3190             GST_MESSAGE_STRUCTURE_CHANGE);
       
  3191         bin->priv->structure_cookie++;
       
  3192       }
       
  3193       GST_OBJECT_UNLOCK (bin);
       
  3194 
       
  3195       if (message)
       
  3196         gst_message_unref (message);
       
  3197 
       
  3198       break;
       
  3199     }
       
  3200     default:
  2971     default:
  3201       goto forward;
  2972       goto forward;
  3202   }
  2973   }
  3203   return;
  2974   return;
  3204 
  2975 
  3250   }
  3021   }
  3251 
  3022 
  3252   gst_object_unref (item);
  3023   gst_object_unref (item);
  3253   return TRUE;
  3024   return TRUE;
  3254 }
  3025 }
  3255 
       
  3256 static void
  3026 static void
  3257 bin_query_duration_done (GstBin * bin, QueryFold * fold)
  3027 bin_query_duration_done (GstBin * bin, QueryFold * fold)
  3258 {
  3028 {
  3259   GstFormat format;
  3029   GstFormat format;
  3260 
  3030 
  3290   }
  3060   }
  3291 
  3061 
  3292   gst_object_unref (item);
  3062   gst_object_unref (item);
  3293   return TRUE;
  3063   return TRUE;
  3294 }
  3064 }
  3295 
       
  3296 static void
  3065 static void
  3297 bin_query_position_done (GstBin * bin, QueryFold * fold)
  3066 bin_query_position_done (GstBin * bin, QueryFold * fold)
  3298 {
  3067 {
  3299   GstFormat format;
  3068   GstFormat format;
  3300 
  3069 
  3318         "got latency min %" GST_TIME_FORMAT ", max %" GST_TIME_FORMAT
  3087         "got latency min %" GST_TIME_FORMAT ", max %" GST_TIME_FORMAT
  3319         ", live %d", GST_TIME_ARGS (min), GST_TIME_ARGS (max), live);
  3088         ", live %d", GST_TIME_ARGS (min), GST_TIME_ARGS (max), live);
  3320 
  3089 
  3321     /* for the combined latency we collect the MAX of all min latencies and
  3090     /* for the combined latency we collect the MAX of all min latencies and
  3322      * the MIN of all max latencies */
  3091      * the MIN of all max latencies */
  3323     if (live) {
  3092     if (min > fold->min)
  3324       if (min > fold->min)
  3093       fold->min = min;
  3325         fold->min = min;
  3094     if (fold->max == -1)
  3326       if (fold->max == -1)
  3095       fold->max = max;
  3327         fold->max = max;
  3096     else if (max < fold->max)
  3328       else if (max < fold->max)
  3097       fold->max = max;
  3329         fold->max = max;
  3098     if (fold->live == FALSE)
  3330       if (fold->live == FALSE)
  3099       fold->live = live;
  3331         fold->live = live;
       
  3332     }
       
  3333   } else {
  3100   } else {
  3334     g_value_set_boolean (ret, FALSE);
  3101     g_value_set_boolean (ret, FALSE);
  3335     GST_DEBUG_OBJECT (item, "failed query");
  3102     GST_DEBUG_OBJECT (item, "failed query");
  3336   }
  3103   }
  3337 
  3104 
  3441       break;
  3208       break;
  3442   }
  3209   }
  3443 
  3210 
  3444   fold_data.query = query;
  3211   fold_data.query = query;
  3445 
  3212 
  3446   /* set the result of the query to FALSE initially */
       
  3447   g_value_init (&ret, G_TYPE_BOOLEAN);
  3213   g_value_init (&ret, G_TYPE_BOOLEAN);
  3448   g_value_set_boolean (&ret, res);
  3214   g_value_set_boolean (&ret, res);
  3449 
  3215 
  3450   iter = gst_bin_iterate_sinks (bin);
  3216   iter = gst_bin_iterate_sinks (bin);
  3451   GST_DEBUG_OBJECT (bin, "Sending query %p (type %s) to sink children",
  3217   GST_DEBUG_OBJECT (bin, "Sending query %p (type %s) to sink children",
  3690   childlist = xmlNewChild (parent, NULL, (xmlChar *) "children", NULL);
  3456   childlist = xmlNewChild (parent, NULL, (xmlChar *) "children", NULL);
  3691 
  3457 
  3692   GST_CAT_INFO (GST_CAT_XML, "[%s]: saving %d children",
  3458   GST_CAT_INFO (GST_CAT_XML, "[%s]: saving %d children",
  3693       GST_ELEMENT_NAME (bin), bin->numchildren);
  3459       GST_ELEMENT_NAME (bin), bin->numchildren);
  3694 
  3460 
  3695   children = g_list_last (bin->children);
  3461   children = bin->children;
  3696   while (children) {
  3462   while (children) {
  3697     child = GST_ELEMENT (children->data);
  3463     child = GST_ELEMENT (children->data);
  3698     elementnode = xmlNewChild (childlist, NULL, (xmlChar *) "element", NULL);
  3464     elementnode = xmlNewChild (childlist, NULL, (xmlChar *) "element", NULL);
  3699     gst_object_save_thyself (GST_OBJECT (child), elementnode);
  3465     gst_object_save_thyself (GST_OBJECT (child), elementnode);
  3700     children = g_list_previous (children);
  3466     children = g_list_next (children);
  3701   }
  3467   }
  3702   return childlist;
  3468   return childlist;
  3703 }
  3469 }
  3704 
  3470 
  3705 static void
  3471 static void