3 * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
4 * 2004 Wim Taymans <wim@fluendo.com>
6 * gstbin.c: GstBin container object and support code
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public
19 * License along with this library; if not, write to the
20 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, USA.
26 #include "gst_private.h"
30 #include "gstmarshal.h"
35 #include "gstscheduler.h"
39 GST_DEBUG_CATEGORY_STATIC (bin_debug);
40 #define GST_CAT_DEFAULT bin_debug
41 #define GST_LOG_BIN_CONTENTS(bin, text) GST_LOG_OBJECT ((bin), \
42 text ": %d elements: %u PLAYING, %u PAUSED, %u READY, %u NULL, own state: %s", \
43 (bin)->numchildren, (guint) (bin)->child_states[3], \
44 (guint) (bin)->child_states[2], (bin)->child_states[1], \
45 (bin)->child_states[0], gst_element_state_get_name (GST_STATE (bin)))
48 static GstElementDetails gst_bin_details = GST_ELEMENT_DETAILS ("Generic bin",
50 "Simple container object",
51 "Erik Walthinsen <omega@cse.ogi.edu>," "Wim Taymans <wim@fluendo.com>");
53 GType _gst_bin_type = 0;
55 static void gst_bin_dispose (GObject * object);
57 static GstElementStateReturn gst_bin_change_state (GstElement * element);
58 static GstElementStateReturn gst_bin_get_state (GstElement * element,
59 GstElementState * state, GstElementState * pending, GTimeVal * timeout);
61 static gboolean gst_bin_add_func (GstBin * bin, GstElement * element);
62 static gboolean gst_bin_remove_func (GstBin * bin, GstElement * element);
64 #ifndef GST_DISABLE_INDEX
65 static void gst_bin_set_index_func (GstElement * element, GstIndex * index);
67 static GstClock *gst_bin_get_clock_func (GstElement * element);
68 static void gst_bin_set_clock_func (GstElement * element, GstClock * clock);
70 static void gst_bin_set_manager (GstElement * element, GstPipeline * manager);
71 static void gst_bin_set_scheduler (GstElement * element, GstScheduler * sched);
73 static gboolean gst_bin_send_event (GstElement * element, GstEvent * event);
74 static GstBusSyncReply bin_bus_handler (GstBus * bus,
75 GstMessage * message, GstBin * bin);
76 static gboolean gst_bin_query (GstElement * element, GstQuery * query);
78 #ifndef GST_DISABLE_LOADSAVE
79 static xmlNodePtr gst_bin_save_thyself (GstObject * object, xmlNodePtr parent);
80 static void gst_bin_restore_thyself (GstObject * object, xmlNodePtr self);
83 static gint bin_element_is_sink (GstElement * child, GstBin * bin);
85 /* Bin signals and args */
99 static void gst_bin_base_init (gpointer g_class);
100 static void gst_bin_class_init (GstBinClass * klass);
101 static void gst_bin_init (GstBin * bin);
103 static GstElementClass *parent_class = NULL;
104 static guint gst_bin_signals[LAST_SIGNAL] = { 0 };
109 * Returns: the type of #GstBin
112 gst_bin_get_type (void)
114 if (!_gst_bin_type) {
115 static const GTypeInfo bin_info = {
116 sizeof (GstBinClass),
119 (GClassInitFunc) gst_bin_class_init,
124 (GInstanceInitFunc) gst_bin_init,
129 g_type_register_static (GST_TYPE_ELEMENT, "GstBin", &bin_info, 0);
131 GST_DEBUG_CATEGORY_INIT (bin_debug, "bin", GST_DEBUG_BOLD,
132 "debugging info for the 'bin' container element");
134 return _gst_bin_type;
138 gst_bin_base_init (gpointer g_class)
140 GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
142 gst_element_class_set_details (gstelement_class, &gst_bin_details);
146 gst_bin_class_init (GstBinClass * klass)
148 GObjectClass *gobject_class;
149 GstObjectClass *gstobject_class;
150 GstElementClass *gstelement_class;
152 gobject_class = (GObjectClass *) klass;
153 gstobject_class = (GstObjectClass *) klass;
154 gstelement_class = (GstElementClass *) klass;
156 parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
158 gst_bin_signals[ELEMENT_ADDED] =
159 g_signal_new ("element-added", G_TYPE_FROM_CLASS (klass),
160 G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GstBinClass, element_added), NULL,
161 NULL, gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_ELEMENT);
162 gst_bin_signals[ELEMENT_REMOVED] =
163 g_signal_new ("element-removed", G_TYPE_FROM_CLASS (klass),
164 G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GstBinClass, element_removed), NULL,
165 NULL, gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_ELEMENT);
167 gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_bin_dispose);
169 #ifndef GST_DISABLE_LOADSAVE
170 gstobject_class->save_thyself = GST_DEBUG_FUNCPTR (gst_bin_save_thyself);
171 gstobject_class->restore_thyself =
172 GST_DEBUG_FUNCPTR (gst_bin_restore_thyself);
175 gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_bin_change_state);
176 gstelement_class->get_state = GST_DEBUG_FUNCPTR (gst_bin_get_state);
177 #ifndef GST_DISABLE_INDEX
178 gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_bin_set_index_func);
180 gstelement_class->get_clock = GST_DEBUG_FUNCPTR (gst_bin_get_clock_func);
181 gstelement_class->set_clock = GST_DEBUG_FUNCPTR (gst_bin_set_clock_func);
182 gstelement_class->set_manager = GST_DEBUG_FUNCPTR (gst_bin_set_manager);
183 gstelement_class->set_scheduler = GST_DEBUG_FUNCPTR (gst_bin_set_scheduler);
185 gstelement_class->send_event = GST_DEBUG_FUNCPTR (gst_bin_send_event);
186 gstelement_class->query = GST_DEBUG_FUNCPTR (gst_bin_query);
188 klass->add_element = GST_DEBUG_FUNCPTR (gst_bin_add_func);
189 klass->remove_element = GST_DEBUG_FUNCPTR (gst_bin_remove_func);
193 gst_bin_init (GstBin * bin)
197 bin->numchildren = 0;
198 bin->children = NULL;
199 bin->children_cookie = 0;
202 /* Set up a bus for listening to child elements,
203 * and one for sending messages up the hierarchy */
204 bus = g_object_new (gst_bus_get_type (), NULL);
205 bin->child_bus = bus;
206 gst_bus_set_sync_handler (bus, (GstBusSyncHandler) bin_bus_handler, bin);
208 bus = g_object_new (gst_bus_get_type (), NULL);
209 gst_element_set_bus (GST_ELEMENT (bin), bus);
210 /* set_bus refs the bus via gst_object_replace, we drop our ref */
211 gst_object_unref (bus);
216 * @name: name of new bin
218 * Create a new bin with given name.
223 gst_bin_new (const gchar * name)
225 return gst_element_factory_make ("bin", name);
228 /* set the index on all elements in this bin
232 #ifndef GST_DISABLE_INDEX
234 gst_bin_set_index_func (GstElement * element, GstIndex * index)
239 bin = GST_BIN (element);
242 for (children = bin->children; children; children = g_list_next (children)) {
243 GstElement *child = GST_ELEMENT (children->data);
245 gst_element_set_index (child, index);
251 /* set the clock on all elements in this bin
256 gst_bin_set_clock_func (GstElement * element, GstClock * clock)
261 bin = GST_BIN (element);
264 for (children = bin->children; children; children = g_list_next (children)) {
265 GstElement *child = GST_ELEMENT (children->data);
267 gst_element_set_clock (child, clock);
272 /* get the clock for this bin by asking all of the children in this bin
277 gst_bin_get_clock_func (GstElement * element)
279 GstClock *result = NULL;
283 bin = GST_BIN (element);
286 for (children = bin->children; children; children = g_list_next (children)) {
287 GstElement *child = GST_ELEMENT (children->data);
289 result = gst_element_get_clock (child);
298 /* set the scheduler on all of the children in this bin
303 gst_bin_set_scheduler (GstElement * element, GstScheduler * sched)
308 bin = GST_BIN (element);
310 parent_class->set_scheduler (element, sched);
313 for (children = bin->children; children; children = g_list_next (children)) {
314 GstElement *child = GST_ELEMENT (children->data);
316 gst_element_set_scheduler (child, sched);
321 /* set the manager on all of the children in this bin
326 gst_bin_set_manager (GstElement * element, GstPipeline * manager)
328 GstBin *bin = GST_BIN (element);
332 GST_ELEMENT_CLASS (parent_class)->set_manager (element, manager);
335 for (kids = bin->children; kids != NULL; kids = kids->next) {
336 kid = GST_ELEMENT (kids->data);
337 gst_element_set_manager (kid, manager);
339 GST_UNLOCK (element);
343 is_eos (GstBin * bin)
346 gboolean result = TRUE;
347 gboolean done = FALSE;
349 sinks = gst_bin_iterate_sinks (bin);
353 switch (gst_iterator_next (sinks, &data)) {
354 case GST_ITERATOR_OK:
356 GstElement *element = GST_ELEMENT (data);
360 name = gst_element_get_name (element);
361 eosed = g_list_find (bin->eosed, element);
363 GST_DEBUG ("element %s did not post EOS yet", name);
367 GST_DEBUG ("element %s posted EOS", name);
370 gst_object_unref (element);
373 case GST_ITERATOR_RESYNC:
375 gst_iterator_resync (sinks);
377 case GST_ITERATOR_DONE:
381 g_assert_not_reached ();
385 gst_iterator_free (sinks);
389 /* add an element to this bin
394 gst_bin_add_func (GstBin * bin, GstElement * element)
398 /* we obviously can't add ourself to ourself */
399 if (G_UNLIKELY (GST_ELEMENT_CAST (element) == GST_ELEMENT_CAST (bin)))
402 /* get the element name to make sure it is unique in this bin, FIXME, another
403 * thread can change the name after the unlock. */
405 elem_name = g_strdup (GST_ELEMENT_NAME (element));
406 GST_UNLOCK (element);
410 /* then check to see if the element's name is already taken in the bin,
411 * we can safely take the lock here. This check is probably bogus because
412 * you can safely change the element name after adding it to the bin. */
413 if (G_UNLIKELY (gst_object_check_uniqueness (bin->children,
414 elem_name) == FALSE))
417 /* set the element's parent and add the element to the bin's list of children */
418 if (G_UNLIKELY (!gst_object_set_parent (GST_OBJECT_CAST (element),
419 GST_OBJECT_CAST (bin))))
422 if (GST_FLAG_IS_SET (element, GST_ELEMENT_IS_SINK))
423 GST_FLAG_SET (bin, GST_ELEMENT_IS_SINK);
425 bin->children = g_list_prepend (bin->children, element);
427 bin->children_cookie++;
429 gst_element_set_manager (element, GST_ELEMENT (bin)->manager);
430 gst_element_set_bus (element, bin->child_bus);
431 gst_element_set_scheduler (element, GST_ELEMENT_SCHEDULER (bin));
432 gst_element_set_clock (element, GST_ELEMENT_CLOCK (bin));
436 GST_CAT_DEBUG_OBJECT (GST_CAT_PARENTAGE, bin, "added element \"%s\"",
440 g_signal_emit (G_OBJECT (bin), gst_bin_signals[ELEMENT_ADDED], 0, element);
444 /* ERROR handling here */
448 g_warning ("Cannot add bin %s to itself", GST_ELEMENT_NAME (bin));
454 g_warning ("Name %s is not unique in bin %s, not adding",
455 elem_name, GST_ELEMENT_NAME (bin));
462 g_warning ("Element %s already has parent", elem_name);
471 * @bin: #GstBin to add element to
472 * @element: #GstElement to add to bin
474 * Adds the given element to the bin. Sets the element's parent, and thus
475 * takes ownership of the element. An element can only be added to one bin.
479 * Returns: TRUE if the element could be added, FALSE on wrong parameters or
480 * the bin does not want to accept the element.
483 gst_bin_add (GstBin * bin, GstElement * element)
488 g_return_val_if_fail (GST_IS_BIN (bin), FALSE);
489 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
491 bclass = GST_BIN_GET_CLASS (bin);
493 if (G_UNLIKELY (bclass->add_element == NULL))
496 GST_CAT_DEBUG (GST_CAT_PARENTAGE, "adding element %s to bin %s",
497 GST_ELEMENT_NAME (element), GST_ELEMENT_NAME (bin));
499 result = bclass->add_element (bin, element);
506 g_warning ("adding elements to bin %s is not supported",
507 GST_ELEMENT_NAME (bin));
512 /* remove an element from the bin
517 gst_bin_remove_func (GstBin * bin, GstElement * element)
521 /* grab element name so we can print it */
523 elem_name = g_strdup (GST_ELEMENT_NAME (element));
524 GST_UNLOCK (element);
527 /* the element must be in the bin's list of children */
528 if (G_UNLIKELY (g_list_find (bin->children, element) == NULL))
531 /* now remove the element from the list of elements */
532 bin->children = g_list_remove (bin->children, element);
534 bin->children_cookie++;
536 /* check if we a sink */
537 if (GST_FLAG_IS_SET (element, GST_ELEMENT_IS_SINK)) {
540 /* check if we removed the last sink */
541 other_sink = g_list_find_custom (bin->children,
542 bin, (GCompareFunc) bin_element_is_sink);
544 /* yups, we're not a sink anymore */
545 GST_FLAG_UNSET (bin, GST_ELEMENT_IS_SINK);
551 GST_CAT_INFO_OBJECT (GST_CAT_PARENTAGE, bin, "removed child \"%s\"",
555 gst_element_set_manager (element, NULL);
556 gst_element_set_bus (element, NULL);
557 gst_element_set_scheduler (element, NULL);
559 /* unlock any waiters for the state change. It is possible that
560 * we are waiting for an ASYNC state change on this element. The
561 * element cannot be added to another bin yet as it is not yet
563 GST_STATE_LOCK (element);
564 GST_STATE_BROADCAST (element);
565 GST_STATE_UNLOCK (element);
567 /* we ref here because after the _unparent() the element can be disposed
568 * and we still need it to fire a signal. */
569 gst_object_ref (element);
570 gst_object_unparent (GST_OBJECT_CAST (element));
572 g_signal_emit (G_OBJECT (bin), gst_bin_signals[ELEMENT_REMOVED], 0, element);
573 /* element is really out of our control now */
574 gst_object_unref (element);
581 g_warning ("Element %s is not in bin %s", elem_name,
582 GST_ELEMENT_NAME (bin));
591 * @bin: #GstBin to remove element from
592 * @element: #GstElement to remove
594 * Remove the element from its associated bin, unparenting it as well.
595 * Unparenting the element means that the element will be dereferenced,
596 * so if the bin holds the only reference to the element, the element
597 * will be freed in the process of removing it from the bin. If you
598 * want the element to still exist after removing, you need to call
599 * #gst_object_ref before removing it from the bin.
603 * Returns: TRUE if the element could be removed, FALSE on wrong parameters or
604 * the bin does not want to remove the element.
607 gst_bin_remove (GstBin * bin, GstElement * element)
612 g_return_val_if_fail (GST_IS_BIN (bin), FALSE);
613 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
615 bclass = GST_BIN_GET_CLASS (bin);
617 if (G_UNLIKELY (bclass->remove_element == NULL))
620 GST_CAT_DEBUG (GST_CAT_PARENTAGE, "removing element %s from bin %s",
621 GST_ELEMENT_NAME (element), GST_ELEMENT_NAME (bin));
623 result = bclass->remove_element (bin, element);
630 g_warning ("removing elements from bin %s is not supported",
631 GST_ELEMENT_NAME (bin));
636 static GstIteratorItem
637 iterate_child (GstIterator * it, GstElement * child)
639 gst_object_ref (child);
640 return GST_ITERATOR_ITEM_PASS;
644 * gst_bin_iterate_elements:
645 * @bin: #Gstbin to iterate the elements of
647 * Get an iterator for the elements in this bin.
648 * Each element will have its refcount increased, so unref
653 * Returns: a #GstIterator of #GstElements. gst_iterator_free after
654 * use. returns NULL when passing bad parameters.
657 gst_bin_iterate_elements (GstBin * bin)
661 g_return_val_if_fail (GST_IS_BIN (bin), NULL);
664 /* add ref because the iterator refs the bin. When the iterator
665 * is freed it will unref the bin again using the provided dispose
667 gst_object_ref (bin);
668 result = gst_iterator_new_list (GST_GET_LOCK (bin),
669 &bin->children_cookie,
672 (GstIteratorItemFunction) iterate_child,
673 (GstIteratorDisposeFunction) gst_object_unref);
679 static GstIteratorItem
680 iterate_child_recurse (GstIterator * it, GstElement * child)
682 gst_object_ref (child);
683 if (GST_IS_BIN (child)) {
684 GstIterator *other = gst_bin_iterate_recurse (GST_BIN (child));
686 gst_iterator_push (it, other);
688 return GST_ITERATOR_ITEM_PASS;
692 * gst_bin_iterate_recurse:
693 * @bin: #Gstbin to iterate the elements of
695 * Get an iterator for the elements in this bin.
696 * Each element will have its refcount increased, so unref
697 * after use. This iterator recurses into GstBin children.
701 * Returns: a #GstIterator of #GstElements. gst_iterator_free after
702 * use. returns NULL when passing bad parameters.
705 gst_bin_iterate_recurse (GstBin * bin)
709 g_return_val_if_fail (GST_IS_BIN (bin), NULL);
712 /* add ref because the iterator refs the bin. When the iterator
713 * is freed it will unref the bin again using the provided dispose
715 gst_object_ref (bin);
716 result = gst_iterator_new_list (GST_GET_LOCK (bin),
717 &bin->children_cookie,
720 (GstIteratorItemFunction) iterate_child_recurse,
721 (GstIteratorDisposeFunction) gst_object_unref);
727 /* returns 0 when TRUE because this is a GCompareFunc */
730 bin_element_is_sink (GstElement * child, GstBin * bin)
734 /* we lock the child here for the remainder of the function to
735 * get its name safely. */
737 is_sink = GST_FLAG_IS_SET (child, GST_ELEMENT_IS_SINK);
739 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin,
740 "child %s %s sink", GST_OBJECT_NAME (child), is_sink ? "is" : "is not");
743 return is_sink ? 0 : 1;
747 has_ancestor (GstObject * object, GstObject * ancestor)
750 gboolean result = FALSE;
755 if (object == ancestor)
758 parent = gst_object_get_parent (object);
759 result = has_ancestor (parent, ancestor);
761 gst_object_unref (parent);
766 /* returns 0 when TRUE because this is a GCompareFunc.
767 * This function returns elements that have no connected srcpads and
768 * are therefore not reachable from a real sink. */
771 bin_element_is_semi_sink (GstElement * child, GstBin * bin)
775 /* we lock the child here for the remainder of the function to
776 * get its pads and name safely. */
779 /* check if this is a sink element, these are the elements
780 * without (linked) source pads. */
781 if (child->numsrcpads == 0) {
783 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin,
784 "adding child %s as sink", GST_OBJECT_NAME (child));
787 /* loop over all pads, try to figure out if this element
788 * is a semi sink because it has no linked source pads */
790 gboolean connected_src = FALSE;
792 for (pads = child->srcpads; pads; pads = g_list_next (pads)) {
795 if ((peer = gst_pad_get_peer (GST_PAD_CAST (pads->data)))) {
797 has_ancestor (GST_OBJECT_CAST (peer), GST_OBJECT_CAST (bin));
798 gst_object_unref (peer);
805 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin,
806 "not adding child %s as sink: linked source pads",
807 GST_OBJECT_NAME (child));
809 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin,
810 "adding child %s as sink since it has unlinked source pads in this bin",
811 GST_OBJECT_NAME (child));
821 sink_iterator_filter (GstElement * child, GstBin * bin)
823 if (bin_element_is_sink (child, bin) == 0) {
824 /* returns 0 because this is a GCompareFunc */
827 /* child carries a ref from gst_bin_iterate_elements -- drop if not passing
829 gst_object_unref ((GstObject *) child);
835 * gst_bin_iterate_sinks:
836 * @bin: #Gstbin to iterate on
838 * Get an iterator for the sink elements in this bin.
839 * Each element will have its refcount increased, so unref
842 * The sink elements are those without any linked srcpads.
846 * Returns: a #GstIterator of #GstElements. gst_iterator_free after use.
849 gst_bin_iterate_sinks (GstBin * bin)
851 GstIterator *children;
854 g_return_val_if_fail (GST_IS_BIN (bin), NULL);
856 children = gst_bin_iterate_elements (bin);
857 result = gst_iterator_filter (children,
858 (GCompareFunc) sink_iterator_filter, bin);
864 * 1) check state of all children with 0 timeout to find ERROR and
865 * NO_PREROLL elements. return if found.
866 * 2) perform full blocking wait with requested timeout.
868 * 2) cannot be performed when 1) returns results as the sinks might
869 * not be able to complete the state change making 2) block forever.
873 static GstElementStateReturn
874 gst_bin_get_state (GstElement * element, GstElementState * state,
875 GstElementState * pending, GTimeVal * timeout)
877 GstBin *bin = GST_BIN (element);
878 GstElementStateReturn ret = GST_STATE_SUCCESS;
880 guint32 children_cookie;
881 gboolean zero_timeout;
882 gboolean have_no_preroll;
884 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "getting state");
886 zero_timeout = timeout != NULL && timeout->tv_sec == 0
887 && timeout->tv_usec == 0;
889 /* lock bin, no element can be added or removed between going into
890 * the quick scan and the blocking wait. */
894 have_no_preroll = FALSE;
896 /* if we have a non zero timeout we must make sure not to block
897 * on the sinks when we have NO_PREROLL elements. This is why we do
898 * a quick check if there are still NO_PREROLL elements. We also
899 * catch the error elements this way. */
902 gboolean have_async = FALSE;
904 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "checking for NO_PREROLL");
905 /* use 0 timeout so we don't block on the sinks */
906 GST_TIME_TO_TIMEVAL (0, tv);
907 children = bin->children;
908 children_cookie = bin->children_cookie;
910 GstElement *child = GST_ELEMENT_CAST (children->data);
912 gst_object_ref (child);
913 /* now we release the lock to enter a non blocking wait. We
914 * release the lock anyway since we can. */
917 ret = gst_element_get_state (child, NULL, NULL, &tv);
919 gst_object_unref (child);
921 /* now grab the lock to iterate to the next child */
923 if (G_UNLIKELY (children_cookie != bin->children_cookie)) {
924 /* child added/removed during state change, restart. We need
925 * to restart with the quick check as a no-preroll element could
926 * have been added here and we don't want to block on sinks then.*/
931 /* report FAILURE or NO_PREROLL immediatly */
932 case GST_STATE_FAILURE:
934 case GST_STATE_NO_PREROLL:
935 /* we have to continue scanning as there might be
937 have_no_preroll = TRUE;
939 case GST_STATE_ASYNC:
945 children = g_list_next (children);
947 /* if we get here, we have no FAILURES, check for any NO_PREROLL
949 if (have_no_preroll) {
950 ret = GST_STATE_NO_PREROLL;
954 /* if we get here, no NO_PREROLL elements are in the pipeline */
955 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "no NO_PREROLL elements");
957 /* if no ASYNC elements exist we don't even have to poll with a
960 ret = GST_STATE_SUCCESS;
965 /* next we poll all children for their state to see if one of them
966 * is still busy with its state change. We did not release the bin lock
967 * yet so the elements are the same as the ones from the quick scan. */
968 children = bin->children;
969 children_cookie = bin->children_cookie;
971 GstElement *child = GST_ELEMENT_CAST (children->data);
973 gst_object_ref (child);
974 /* now we release the lock to enter the potentialy blocking wait */
977 /* ret is ASYNC if some child is still performing the state change
978 * ater the timeout. */
979 ret = gst_element_get_state (child, NULL, NULL, timeout);
981 gst_object_unref (child);
983 /* now grab the lock to iterate to the next child */
985 if (G_UNLIKELY (children_cookie != bin->children_cookie)) {
986 /* child added/removed during state change, restart. We need
987 * to restart with the quick check as a no-preroll element could
988 * have been added here and we don't want to block on sinks then.*/
993 case GST_STATE_SUCCESS:
995 case GST_STATE_FAILURE:
996 case GST_STATE_NO_PREROLL:
997 /* report FAILURE and NO_PREROLL immediatly */
1000 case GST_STATE_ASYNC:
1001 /* since we checked for non prerollable elements before,
1002 * the first ASYNC return is the real return value */
1007 g_assert_not_reached ();
1009 children = g_list_next (children);
1011 /* if we got here, all elements can do preroll */
1012 have_no_preroll = FALSE;
1017 /* now we can take the state lock, it is possible that new elements
1018 * are added now and we still report the old state. No problem though as
1019 * the return is still consistent, the effect is as if the element was
1020 * added after this function completed. */
1021 GST_STATE_LOCK (bin);
1023 case GST_STATE_SUCCESS:
1024 /* we can commit the state */
1025 gst_element_commit_state (element);
1027 case GST_STATE_FAILURE:
1028 /* some element failed, abort the state change */
1029 gst_element_abort_state (element);
1032 /* other cases are just passed along */
1036 /* and report the state if needed */
1038 *state = GST_STATE (element);
1040 *pending = GST_STATE_PENDING (element);
1042 GST_STATE_NO_PREROLL (element) = have_no_preroll;
1044 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
1045 "state current: %s, pending: %s, error: %d, no_preroll: %d, result: %d",
1046 gst_element_state_get_name (GST_STATE (element)),
1047 gst_element_state_get_name (GST_STATE_PENDING (element)),
1048 GST_STATE_ERROR (element), GST_STATE_NO_PREROLL (element), ret);
1050 GST_STATE_UNLOCK (bin);
1056 append_child (gpointer child, GQueue * queue)
1058 g_queue_push_tail (queue, child);
1062 * gst_bin_iterate_state_order:
1063 * @bin: #Gstbin to iterate on
1065 * Get an iterator for the elements in this bin in the order
1066 * in which a state change should be performed on them. This
1067 * means that first the sinks and then the other elements will
1069 * Each element will have its refcount increased, so unref
1074 * Returns: a #GstIterator of #GstElements. gst_iterator_free after use.
1077 gst_bin_iterate_state_order (GstBin * bin)
1079 GstIterator *result;
1081 g_return_val_if_fail (GST_IS_BIN (bin), NULL);
1089 clear_queue (GQueue * queue, gboolean unref)
1093 while ((p = g_queue_pop_head (queue)))
1095 gst_object_unref (p);
1098 remove_all_from_queue (GQueue * queue, gpointer elem, gboolean unref)
1102 while ((p = g_queue_find (queue, elem))) {
1104 gst_object_unref (elem);
1105 g_queue_delete_link (queue, p);
1109 /* this function is called with the STATE_LOCK held. It works
1112 * 1) put all sink elements on the queue.
1113 * 2) put all semisink elements on the queue.
1114 * 3) change state of elements in queue, put linked elements to queue.
1115 * 4) while queue not empty goto 3)
1117 * This will effectively change the state of all elements in the bin
1118 * from the sinks to the sources. We have to change the states this
1119 * way so that when a source element pushes data, the downstream element
1120 * is in the right state to receive the data.
1124 /* FIXME, make me more elegant */
1125 static GstElementStateReturn
1126 gst_bin_change_state (GstElement * element)
1129 GstElementStateReturn ret;
1130 GstElementState old_state, pending;
1131 gboolean have_async = FALSE;
1132 gboolean have_no_preroll = FALSE;
1134 guint32 children_cookie;
1135 GQueue *elem_queue; /* list of elements waiting for a state change */
1136 GQueue *semi_queue; /* list of elements with no connected srcpads */
1137 GQueue *temp; /* queue of leftovers */
1139 bin = GST_BIN (element);
1141 /* we don't need to take the STATE_LOCK, it is already taken */
1142 old_state = GST_STATE (element);
1143 pending = GST_STATE_PENDING (element);
1145 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
1146 "changing state of children from %s to %s",
1147 gst_element_state_get_name (old_state),
1148 gst_element_state_get_name (pending));
1150 if (pending == GST_STATE_VOID_PENDING)
1151 return GST_STATE_SUCCESS;
1153 /* Clear eosed element list on READY-> PAUSED */
1154 if (GST_STATE_TRANSITION (element) == GST_STATE_READY_TO_PAUSED) {
1155 g_list_free (bin->eosed);
1159 /* all elements added to these queues should have their refcount
1161 elem_queue = g_queue_new ();
1162 semi_queue = g_queue_new ();
1163 temp = g_queue_new ();
1165 /* first step, find all sink elements, these are the elements
1166 * without (linked) source pads. */
1170 /* make sure queues are empty, they could be filled when
1172 clear_queue (elem_queue, TRUE);
1173 clear_queue (semi_queue, TRUE);
1174 clear_queue (temp, TRUE);
1176 children = bin->children;
1177 children_cookie = bin->children_cookie;
1179 GstElement *child = GST_ELEMENT_CAST (children->data);
1181 gst_object_ref (child);
1184 if (bin_element_is_sink (child, bin) == 0) {
1185 g_queue_push_tail (elem_queue, child);
1186 } else if (bin_element_is_semi_sink (child, bin) == 0) {
1187 g_queue_push_tail (semi_queue, child);
1189 g_queue_push_tail (temp, child);
1193 if (G_UNLIKELY (children_cookie != bin->children_cookie)) {
1194 /* FIXME: we reffed some children already, are we leaking refcounts
1196 GST_INFO_OBJECT (bin, "bin->children_cookie changed, restarting");
1199 children = g_list_next (children);
1202 /* after this point new elements can be added/removed from the
1203 * bin. We operate on the snapshot taken above. Applications
1204 * should serialize their add/remove and set_state. */
1206 /* now change state for semi sink elements first so add them in
1207 * front of the other elements */
1208 g_queue_foreach (temp, (GFunc) append_child, semi_queue);
1209 clear_queue (temp, FALSE);
1211 /* if we don't have real sinks, we continue with the other elements */
1212 if (g_queue_is_empty (elem_queue) && !g_queue_is_empty (semi_queue)) {
1213 GQueue *q = elem_queue;
1215 /* we swap the queues as oposed to copy them over */
1216 elem_queue = semi_queue;
1220 /* second step, change state of elements in the queue */
1221 while (!g_queue_is_empty (elem_queue)) {
1222 GstElement *qelement;
1227 qelement = g_queue_pop_head (elem_queue);
1228 /* we don't need any duplicates in the other queue anymore */
1229 remove_all_from_queue (semi_queue, qelement, TRUE);
1231 /* queue all elements connected to the sinkpads of this element */
1232 GST_LOCK (qelement);
1233 pads = qelement->sinkpads;
1235 GstPad *pad = GST_PAD_CAST (pads->data);
1238 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
1239 "found sinkpad %s:%s", GST_DEBUG_PAD_NAME (pad));
1241 peer = gst_pad_get_peer (pad);
1243 GstElement *peer_elem;
1245 peer_elem = gst_pad_get_parent (peer);
1250 /* see if this element is in the bin we are currently handling */
1251 parent = gst_object_get_parent (GST_OBJECT_CAST (peer_elem));
1253 if (parent == GST_OBJECT_CAST (bin)) {
1254 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
1255 "adding element %s to queue", GST_ELEMENT_NAME (peer_elem));
1257 /* make sure we don't have duplicates */
1258 remove_all_from_queue (semi_queue, peer_elem, TRUE);
1259 remove_all_from_queue (elem_queue, peer_elem, TRUE);
1261 /* was reffed before pushing on the queue by the
1262 * gst_object_get_parent() call we used to get the element. */
1263 g_queue_push_tail (elem_queue, peer_elem);
1265 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
1266 "not adding element %s to queue, it is in another bin",
1267 GST_ELEMENT_NAME (peer_elem));
1268 gst_object_unref (peer_elem);
1270 gst_object_unref (parent);
1273 gst_object_unref (peer);
1275 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
1276 "pad %s:%s does not have a peer", GST_DEBUG_PAD_NAME (pad));
1278 pads = g_list_next (pads);
1280 /* peel off the locked flag and release the element lock */
1281 locked = GST_FLAG_IS_SET (qelement, GST_ELEMENT_LOCKED_STATE);
1282 GST_UNLOCK (qelement);
1284 /* skip locked elements */
1285 if (G_UNLIKELY (locked))
1288 /* set base time on element */
1289 qelement->base_time = element->base_time;
1290 ret = gst_element_set_state (qelement, pending);
1292 /* the set state could have cause elements to be added/removed,
1293 * we support that. */
1295 if (G_UNLIKELY (children_cookie != bin->children_cookie)) {
1296 gst_object_unref (qelement);
1302 case GST_STATE_SUCCESS:
1303 GST_CAT_DEBUG (GST_CAT_STATES,
1304 "child '%s' changed state to %d(%s) successfully",
1305 GST_ELEMENT_NAME (qelement), pending,
1306 gst_element_state_get_name (pending));
1308 case GST_STATE_ASYNC:
1309 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
1310 "child '%s' is changing state asynchronously",
1311 GST_ELEMENT_NAME (qelement));
1314 case GST_STATE_FAILURE:
1315 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
1316 "child '%s' failed to go to state %d(%s)",
1317 GST_ELEMENT_NAME (qelement),
1318 pending, gst_element_state_get_name (pending));
1319 ret = GST_STATE_FAILURE;
1320 /* release refcount of element we popped off the queue */
1321 gst_object_unref (qelement);
1323 case GST_STATE_NO_PREROLL:
1324 GST_CAT_DEBUG (GST_CAT_STATES,
1325 "child '%s' changed state to %d(%s) successfully without preroll",
1326 GST_ELEMENT_NAME (qelement), pending,
1327 gst_element_state_get_name (pending));
1328 have_no_preroll = TRUE;
1331 g_assert_not_reached ();
1335 gst_object_unref (qelement);
1337 /* if queue is empty now, continue with a non-sink */
1338 if (g_queue_is_empty (elem_queue)) {
1339 GstElement *non_sink;
1341 GST_DEBUG ("sinks and upstream elements exhausted");
1342 non_sink = g_queue_pop_head (semi_queue);
1344 GST_DEBUG ("found lefover non-sink %s", GST_OBJECT_NAME (non_sink));
1345 g_queue_push_tail (elem_queue, non_sink);
1350 if (have_no_preroll) {
1351 ret = GST_STATE_NO_PREROLL;
1352 } else if (have_async) {
1353 ret = GST_STATE_ASYNC;
1355 ret = parent_class->change_state (element);
1358 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
1359 "done changing bin's state from %s to %s, now in %s, ret %d",
1360 gst_element_state_get_name (old_state),
1361 gst_element_state_get_name (pending),
1362 gst_element_state_get_name (GST_STATE (element)), ret);
1365 /* release refcounts in queue, should normally be empty unless we
1367 clear_queue (elem_queue, TRUE);
1368 clear_queue (semi_queue, TRUE);
1369 g_queue_free (elem_queue);
1370 g_queue_free (semi_queue);
1371 g_queue_free (temp);
1377 gst_bin_dispose (GObject * object)
1379 GstBin *bin = GST_BIN (object);
1381 GST_CAT_DEBUG_OBJECT (GST_CAT_REFCOUNTING, object, "dispose");
1383 /* ref to not hit 0 again */
1384 gst_object_ref (object);
1386 g_list_free (bin->eosed);
1387 gst_object_unref (bin->child_bus);
1388 gst_element_set_bus (GST_ELEMENT (bin), NULL);
1390 while (bin->children) {
1391 gst_bin_remove (bin, GST_ELEMENT (bin->children->data));
1393 GST_CAT_DEBUG_OBJECT (GST_CAT_REFCOUNTING, object, "dispose no children");
1394 g_assert (bin->children == NULL);
1395 g_assert (bin->numchildren == 0);
1397 G_OBJECT_CLASS (parent_class)->dispose (object);
1401 * This function is a utility event handler for seek events.
1402 * It will send the event to all sinks.
1403 * Applications are free to override this behaviour and
1404 * implement their own seek handler, but this will work for
1405 * pretty much all cases in practice.
1408 gst_bin_send_event (GstElement * element, GstEvent * event)
1410 GstBin *bin = GST_BIN (element);
1412 gboolean res = TRUE;
1413 gboolean done = FALSE;
1415 iter = gst_bin_iterate_sinks (bin);
1416 GST_DEBUG_OBJECT (bin, "Sending event to sink children");
1421 switch (gst_iterator_next (iter, &data)) {
1422 case GST_ITERATOR_OK:
1426 gst_event_ref (event);
1427 sink = GST_ELEMENT_CAST (data);
1428 res &= gst_element_send_event (sink, event);
1429 gst_object_unref (sink);
1432 case GST_ITERATOR_RESYNC:
1433 gst_iterator_resync (iter);
1437 case GST_ITERATOR_DONE:
1442 gst_iterator_free (iter);
1443 gst_event_unref (event);
1448 /* FIXME, make me threadsafe */
1449 static GstBusSyncReply
1450 bin_bus_handler (GstBus * bus, GstMessage * message, GstBin * bin)
1452 GST_DEBUG_OBJECT (bin, "[msg %p] handling child message of type %d from %s",
1453 message, GST_MESSAGE_TYPE (message),
1454 gst_object_get_name (GST_MESSAGE_SRC (message)));
1455 /* we don't want messages from the streaming thread while we're doing the
1456 * state change. We do want them from the state change functions. */
1457 switch (GST_MESSAGE_TYPE (message)) {
1458 case GST_MESSAGE_EOS:
1459 GST_DEBUG_OBJECT (bin, "got EOS message");
1461 GST_LOCK (bin->child_bus);
1462 bin->eosed = g_list_prepend (bin->eosed, GST_MESSAGE_SRC (message));
1463 GST_UNLOCK (bin->child_bus);
1466 GST_DEBUG_OBJECT (bin, "all sinks posted EOS");
1467 gst_bus_post (GST_ELEMENT (bin)->bus,
1468 gst_message_new_eos (GST_OBJECT (bin)));
1471 /* we drop all EOS messages */
1472 gst_message_unref (message);
1475 /* Send all other messages upward */
1476 GST_DEBUG_OBJECT (bin, "posting message upward");
1477 gst_bus_post (GST_ELEMENT (bin)->bus, message);
1481 return GST_BUS_DROP;
1485 gst_bin_query (GstElement * element, GstQuery * query)
1487 GstBin *bin = GST_BIN (element);
1489 gboolean res = FALSE, done = FALSE;
1491 iter = gst_bin_iterate_sinks (bin);
1492 GST_DEBUG_OBJECT (bin, "Sending event to sink children");
1494 while (!(res || done)) {
1497 switch (gst_iterator_next (iter, &data)) {
1498 case GST_ITERATOR_OK:
1502 sink = GST_ELEMENT_CAST (data);
1503 res = gst_element_query (sink, query);
1504 gst_object_unref (sink);
1507 case GST_ITERATOR_RESYNC:
1508 gst_iterator_resync (iter);
1511 case GST_ITERATOR_DONE:
1516 gst_iterator_free (iter);
1522 compare_name (GstElement * element, const gchar * name)
1527 eq = strcmp (GST_ELEMENT_NAME (element), name);
1528 GST_UNLOCK (element);
1531 gst_object_unref (element);
1537 * gst_bin_get_by_name:
1538 * @bin: #Gstbin to search
1539 * @name: the element name to search for
1541 * Get the element with the given name from this bin. This
1542 * function recurses into subbins.
1546 * Returns: the element with the given name. Returns NULL if the
1547 * element is not found or when bad parameters were given. Unref after
1551 gst_bin_get_by_name (GstBin * bin, const gchar * name)
1553 GstIterator *children;
1554 GstIterator *result;
1556 g_return_val_if_fail (GST_IS_BIN (bin), NULL);
1558 GST_CAT_INFO (GST_CAT_PARENTAGE, "[%s]: looking up child element %s",
1559 GST_ELEMENT_NAME (bin), name);
1561 children = gst_bin_iterate_recurse (bin);
1562 result = gst_iterator_find_custom (children,
1563 (GCompareFunc) compare_name, (gpointer) name);
1564 gst_iterator_free (children);
1566 return GST_ELEMENT_CAST (result);
1570 * gst_bin_get_by_name_recurse_up:
1571 * @bin: #Gstbin to search
1572 * @name: the element name to search for
1576 * Get the element with the given name from this bin. If the
1577 * element is not found, a recursion is performed on the parent bin.
1579 * Returns: the element with the given name or NULL when the element
1580 * was not found or bad parameters were given. Unref after use.
1583 gst_bin_get_by_name_recurse_up (GstBin * bin, const gchar * name)
1587 g_return_val_if_fail (GST_IS_BIN (bin), NULL);
1588 g_return_val_if_fail (name != NULL, NULL);
1590 result = gst_bin_get_by_name (bin, name);
1595 parent = gst_object_get_parent (GST_OBJECT_CAST (bin));
1597 if (GST_IS_BIN (parent)) {
1598 result = gst_bin_get_by_name_recurse_up (GST_BIN_CAST (parent), name);
1600 gst_object_unref (parent);
1608 compare_interface (GstElement * element, gpointer interface)
1612 if (G_TYPE_CHECK_INSTANCE_TYPE (element, GPOINTER_TO_INT (interface))) {
1615 /* we did not find the element, need to release the ref
1616 * added by the iterator */
1617 gst_object_unref (element);
1624 * gst_bin_get_by_interface:
1625 * @bin: bin to find element in
1626 * @interface: interface to be implemented by interface
1628 * Looks for the first element inside the bin that implements the given
1629 * interface. If such an element is found, it returns the element. You can
1630 * cast this element to the given interface afterwards.
1631 * If you want all elements that implement the interface, use
1632 * gst_bin_iterate_all_by_interface(). The function recurses inside bins.
1636 * Returns: An #GstElement inside the bin implementing the interface.
1640 gst_bin_get_by_interface (GstBin * bin, GType interface)
1642 GstIterator *children;
1643 GstIterator *result;
1645 g_return_val_if_fail (GST_IS_BIN (bin), NULL);
1647 children = gst_bin_iterate_recurse (bin);
1648 result = gst_iterator_find_custom (children, (GCompareFunc) compare_interface,
1649 GINT_TO_POINTER (interface));
1650 gst_iterator_free (children);
1652 return GST_ELEMENT_CAST (result);
1656 * gst_bin_get_all_by_interface:
1657 * @bin: bin to find elements in
1658 * @interface: interface to be implemented by interface
1660 * Looks for all elements inside the bin that implements the given
1661 * interface. You can safely cast all returned elements to the given interface.
1662 * The function recurses bins inside bins. The iterator will return a series
1663 * of #GstElement that should be unreffed after use.
1667 * Returns: A #GstIterator for the elements inside the bin implementing the
1671 gst_bin_iterate_all_by_interface (GstBin * bin, GType interface)
1673 GstIterator *children;
1674 GstIterator *result;
1676 g_return_val_if_fail (GST_IS_BIN (bin), NULL);
1678 children = gst_bin_iterate_recurse (bin);
1679 result = gst_iterator_filter (children, (GCompareFunc) compare_interface,
1680 GINT_TO_POINTER (interface));
1685 #ifndef GST_DISABLE_LOADSAVE
1687 gst_bin_save_thyself (GstObject * object, xmlNodePtr parent)
1689 GstBin *bin = GST_BIN (object);
1690 xmlNodePtr childlist, elementnode;
1694 if (GST_OBJECT_CLASS (parent_class)->save_thyself)
1695 GST_OBJECT_CLASS (parent_class)->save_thyself (GST_OBJECT (bin), parent);
1697 childlist = xmlNewChild (parent, NULL, (xmlChar *) "children", NULL);
1699 GST_CAT_INFO (GST_CAT_XML, "[%s]: saving %d children",
1700 GST_ELEMENT_NAME (bin), bin->numchildren);
1702 children = bin->children;
1704 child = GST_ELEMENT (children->data);
1705 elementnode = xmlNewChild (childlist, NULL, (xmlChar *) "element", NULL);
1706 gst_object_save_thyself (GST_OBJECT (child), elementnode);
1707 children = g_list_next (children);
1713 gst_bin_restore_thyself (GstObject * object, xmlNodePtr self)
1715 GstBin *bin = GST_BIN (object);
1716 xmlNodePtr field = self->xmlChildrenNode;
1717 xmlNodePtr childlist;
1720 if (!strcmp ((char *) field->name, "children")) {
1721 GST_CAT_INFO (GST_CAT_XML, "[%s]: loading children",
1722 GST_ELEMENT_NAME (object));
1723 childlist = field->xmlChildrenNode;
1725 if (!strcmp ((char *) childlist->name, "element")) {
1726 GstElement *element =
1727 gst_xml_make_element (childlist, GST_OBJECT (bin));
1729 /* it had to be parented to find the pads, now we ref and unparent so
1730 * we can add it to the bin */
1731 gst_object_ref (element);
1732 gst_object_unparent (GST_OBJECT (element));
1734 gst_bin_add (bin, element);
1736 childlist = childlist->next;
1740 field = field->next;
1742 if (GST_OBJECT_CLASS (parent_class)->restore_thyself)
1743 (GST_OBJECT_CLASS (parent_class)->restore_thyself) (object, self);
1745 #endif /* GST_DISABLE_LOADSAVE */