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