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: |
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 |
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); |
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 |
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 |
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); |
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), |
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), |
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 |
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 |