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_bus (GstElement * element, GstBus * bus);
72 static void gst_bin_set_scheduler (GstElement * element, GstScheduler * sched);
74 static gboolean gst_bin_send_event (GstElement * element, GstEvent * event);
75 static gboolean gst_bin_query (GstElement * element, GstQuery * query);
77 #ifndef GST_DISABLE_LOADSAVE
78 static xmlNodePtr gst_bin_save_thyself (GstObject * object, xmlNodePtr parent);
79 static void gst_bin_restore_thyself (GstObject * object, xmlNodePtr self);
82 static gint bin_element_is_sink (GstElement * child, GstBin * bin);
84 /* Bin signals and args */
98 static void gst_bin_base_init (gpointer g_class);
99 static void gst_bin_class_init (GstBinClass * klass);
100 static void gst_bin_init (GstBin * bin);
102 static GstElementClass *parent_class = NULL;
103 static guint gst_bin_signals[LAST_SIGNAL] = { 0 };
108 * Returns: the type of #GstBin
111 gst_bin_get_type (void)
113 if (!_gst_bin_type) {
114 static const GTypeInfo bin_info = {
115 sizeof (GstBinClass),
118 (GClassInitFunc) gst_bin_class_init,
123 (GInstanceInitFunc) gst_bin_init,
128 g_type_register_static (GST_TYPE_ELEMENT, "GstBin", &bin_info, 0);
130 GST_DEBUG_CATEGORY_INIT (bin_debug, "bin", GST_DEBUG_BOLD,
131 "debugging info for the 'bin' container element");
133 return _gst_bin_type;
137 gst_bin_base_init (gpointer g_class)
139 GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
141 gst_element_class_set_details (gstelement_class, &gst_bin_details);
145 gst_bin_class_init (GstBinClass * klass)
147 GObjectClass *gobject_class;
148 GstObjectClass *gstobject_class;
149 GstElementClass *gstelement_class;
151 gobject_class = (GObjectClass *) klass;
152 gstobject_class = (GstObjectClass *) klass;
153 gstelement_class = (GstElementClass *) klass;
155 parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
157 gst_bin_signals[ELEMENT_ADDED] =
158 g_signal_new ("element-added", G_TYPE_FROM_CLASS (klass),
159 G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GstBinClass, element_added), NULL,
160 NULL, gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_ELEMENT);
161 gst_bin_signals[ELEMENT_REMOVED] =
162 g_signal_new ("element-removed", G_TYPE_FROM_CLASS (klass),
163 G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GstBinClass, element_removed), NULL,
164 NULL, gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_ELEMENT);
166 gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_bin_dispose);
168 #ifndef GST_DISABLE_LOADSAVE
169 gstobject_class->save_thyself = GST_DEBUG_FUNCPTR (gst_bin_save_thyself);
170 gstobject_class->restore_thyself =
171 GST_DEBUG_FUNCPTR (gst_bin_restore_thyself);
174 gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_bin_change_state);
175 gstelement_class->get_state = GST_DEBUG_FUNCPTR (gst_bin_get_state);
176 #ifndef GST_DISABLE_INDEX
177 gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_bin_set_index_func);
179 gstelement_class->get_clock = GST_DEBUG_FUNCPTR (gst_bin_get_clock_func);
180 gstelement_class->set_clock = GST_DEBUG_FUNCPTR (gst_bin_set_clock_func);
181 gstelement_class->set_manager = GST_DEBUG_FUNCPTR (gst_bin_set_manager);
182 gstelement_class->set_bus = GST_DEBUG_FUNCPTR (gst_bin_set_bus);
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)
195 bin->numchildren = 0;
196 bin->children = NULL;
197 bin->children_cookie = 0;
202 * @name: name of new bin
204 * Create a new bin with given name.
209 gst_bin_new (const gchar * name)
211 return gst_element_factory_make ("bin", name);
214 /* set the index on all elements in this bin
218 #ifndef GST_DISABLE_INDEX
220 gst_bin_set_index_func (GstElement * element, GstIndex * index)
225 bin = GST_BIN (element);
228 for (children = bin->children; children; children = g_list_next (children)) {
229 GstElement *child = GST_ELEMENT (children->data);
231 gst_element_set_index (child, index);
237 /* set the clock on all elements in this bin
242 gst_bin_set_clock_func (GstElement * element, GstClock * clock)
247 bin = GST_BIN (element);
250 for (children = bin->children; children; children = g_list_next (children)) {
251 GstElement *child = GST_ELEMENT (children->data);
253 gst_element_set_clock (child, clock);
258 /* get the clock for this bin by asking all of the children in this bin
263 gst_bin_get_clock_func (GstElement * element)
265 GstClock *result = NULL;
269 bin = GST_BIN (element);
272 for (children = bin->children; children; children = g_list_next (children)) {
273 GstElement *child = GST_ELEMENT (children->data);
275 result = gst_element_get_clock (child);
284 /* set the bus on all of the children in this bin
289 gst_bin_set_bus (GstElement * element, GstBus * bus)
294 bin = GST_BIN (element);
296 parent_class->set_bus (element, bus);
299 for (children = bin->children; children; children = g_list_next (children)) {
300 GstElement *child = GST_ELEMENT (children->data);
302 gst_element_set_bus (child, bus);
307 /* set the scheduler on all of the children in this bin
312 gst_bin_set_scheduler (GstElement * element, GstScheduler * sched)
317 bin = GST_BIN (element);
319 parent_class->set_scheduler (element, sched);
322 for (children = bin->children; children; children = g_list_next (children)) {
323 GstElement *child = GST_ELEMENT (children->data);
325 gst_element_set_scheduler (child, sched);
330 /* set the manager on all of the children in this bin
335 gst_bin_set_manager (GstElement * element, GstPipeline * manager)
337 GstBin *bin = GST_BIN (element);
341 GST_ELEMENT_CLASS (parent_class)->set_manager (element, manager);
344 for (kids = bin->children; kids != NULL; kids = kids->next) {
345 kid = GST_ELEMENT (kids->data);
346 gst_element_set_manager (kid, manager);
348 GST_UNLOCK (element);
351 /* add an element to this bin
356 gst_bin_add_func (GstBin * bin, GstElement * element)
360 /* we obviously can't add ourself to ourself */
361 if (G_UNLIKELY (GST_ELEMENT_CAST (element) == GST_ELEMENT_CAST (bin)))
364 /* get the element name to make sure it is unique in this bin, FIXME, another
365 * thread can change the name after the unlock. */
367 elem_name = g_strdup (GST_ELEMENT_NAME (element));
368 GST_UNLOCK (element);
372 /* then check to see if the element's name is already taken in the bin,
373 * we can safely take the lock here. This check is probably bogus because
374 * you can safely change the element name after adding it to the bin. */
375 if (G_UNLIKELY (gst_object_check_uniqueness (bin->children,
376 elem_name) == FALSE))
379 /* set the element's parent and add the element to the bin's list of children */
380 if (G_UNLIKELY (!gst_object_set_parent (GST_OBJECT_CAST (element),
381 GST_OBJECT_CAST (bin))))
384 if (GST_FLAG_IS_SET (element, GST_ELEMENT_IS_SINK))
385 GST_FLAG_SET (bin, GST_ELEMENT_IS_SINK);
387 bin->children = g_list_prepend (bin->children, element);
389 bin->children_cookie++;
391 gst_element_set_manager (element, GST_ELEMENT (bin)->manager);
392 gst_element_set_bus (element, GST_ELEMENT (bin)->bus);
393 gst_element_set_scheduler (element, GST_ELEMENT_SCHEDULER (bin));
394 gst_element_set_clock (element, GST_ELEMENT_CLOCK (bin));
398 GST_CAT_DEBUG_OBJECT (GST_CAT_PARENTAGE, bin, "added element \"%s\"",
402 g_signal_emit (G_OBJECT (bin), gst_bin_signals[ELEMENT_ADDED], 0, element);
406 /* ERROR handling here */
410 g_warning ("Cannot add bin %s to itself", GST_ELEMENT_NAME (bin));
416 g_warning ("Name %s is not unique in bin %s, not adding",
417 elem_name, GST_ELEMENT_NAME (bin));
424 g_warning ("Element %s already has parent", elem_name);
433 * @bin: #GstBin to add element to
434 * @element: #GstElement to add to bin
436 * Adds the given element to the bin. Sets the element's parent, and thus
437 * takes ownership of the element. An element can only be added to one bin.
441 * Returns: TRUE if the element could be added, FALSE on wrong parameters or
442 * the bin does not want to accept the element.
445 gst_bin_add (GstBin * bin, GstElement * element)
450 g_return_val_if_fail (GST_IS_BIN (bin), FALSE);
451 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
453 bclass = GST_BIN_GET_CLASS (bin);
455 if (G_UNLIKELY (bclass->add_element == NULL))
458 GST_CAT_DEBUG (GST_CAT_PARENTAGE, "adding element %s to bin %s",
459 GST_ELEMENT_NAME (element), GST_ELEMENT_NAME (bin));
461 result = bclass->add_element (bin, element);
468 g_warning ("adding elements to bin %s is not supported",
469 GST_ELEMENT_NAME (bin));
474 /* remove an element from the bin
479 gst_bin_remove_func (GstBin * bin, GstElement * element)
483 /* grab element name so we can print it */
485 elem_name = g_strdup (GST_ELEMENT_NAME (element));
486 GST_UNLOCK (element);
489 /* the element must be in the bin's list of children */
490 if (G_UNLIKELY (g_list_find (bin->children, element) == NULL))
493 /* now remove the element from the list of elements */
494 bin->children = g_list_remove (bin->children, element);
496 bin->children_cookie++;
498 /* check if we a sink */
499 if (GST_FLAG_IS_SET (element, GST_ELEMENT_IS_SINK)) {
502 /* check if we removed the last sink */
503 other_sink = g_list_find_custom (bin->children,
504 bin, (GCompareFunc) bin_element_is_sink);
506 /* yups, we're not a sink anymore */
507 GST_FLAG_UNSET (bin, GST_ELEMENT_IS_SINK);
513 GST_CAT_INFO_OBJECT (GST_CAT_PARENTAGE, bin, "removed child \"%s\"",
517 gst_element_set_manager (element, NULL);
518 gst_element_set_bus (element, NULL);
519 gst_element_set_scheduler (element, NULL);
521 /* unlock any waiters for the state change. It is possible that
522 * we are waiting for an ASYNC state change on this element. The
523 * element cannot be added to another bin yet as it is not yet
525 GST_STATE_LOCK (element);
526 GST_STATE_BROADCAST (element);
527 GST_STATE_UNLOCK (element);
529 /* we ref here because after the _unparent() the element can be disposed
530 * and we still need it to fire a signal. */
531 gst_object_ref (GST_OBJECT_CAST (element));
532 gst_object_unparent (GST_OBJECT_CAST (element));
534 g_signal_emit (G_OBJECT (bin), gst_bin_signals[ELEMENT_REMOVED], 0, element);
535 /* element is really out of our control now */
536 gst_object_unref (GST_OBJECT_CAST (element));
543 g_warning ("Element %s is not in bin %s", elem_name,
544 GST_ELEMENT_NAME (bin));
553 * @bin: #GstBin to remove element from
554 * @element: #GstElement to remove
556 * Remove the element from its associated bin, unparenting it as well.
557 * Unparenting the element means that the element will be dereferenced,
558 * so if the bin holds the only reference to the element, the element
559 * will be freed in the process of removing it from the bin. If you
560 * want the element to still exist after removing, you need to call
561 * #gst_object_ref before removing it from the bin.
565 * Returns: TRUE if the element could be removed, FALSE on wrong parameters or
566 * the bin does not want to remove the element.
569 gst_bin_remove (GstBin * bin, GstElement * element)
574 g_return_val_if_fail (GST_IS_BIN (bin), FALSE);
575 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
577 bclass = GST_BIN_GET_CLASS (bin);
579 if (G_UNLIKELY (bclass->remove_element == NULL))
582 GST_CAT_DEBUG (GST_CAT_PARENTAGE, "removing element %s from bin %s",
583 GST_ELEMENT_NAME (element), GST_ELEMENT_NAME (bin));
585 result = bclass->remove_element (bin, element);
592 g_warning ("removing elements from bin %s is not supported",
593 GST_ELEMENT_NAME (bin));
598 static GstIteratorItem
599 iterate_child (GstIterator * it, GstElement * child)
601 gst_object_ref (GST_OBJECT (child));
602 return GST_ITERATOR_ITEM_PASS;
606 * gst_bin_iterate_elements:
607 * @bin: #Gstbin to iterate the elements of
609 * Get an iterator for the elements in this bin.
610 * Each element will have its refcount increased, so unref
615 * Returns: a #GstIterator of #GstElements. gst_iterator_free after
616 * use. returns NULL when passing bad parameters.
619 gst_bin_iterate_elements (GstBin * bin)
623 g_return_val_if_fail (GST_IS_BIN (bin), NULL);
626 /* add ref because the iterator refs the bin. When the iterator
627 * is freed it will unref the bin again using the provided dispose
629 gst_object_ref (GST_OBJECT (bin));
630 result = gst_iterator_new_list (GST_GET_LOCK (bin),
631 &bin->children_cookie,
634 (GstIteratorItemFunction) iterate_child,
635 (GstIteratorDisposeFunction) gst_object_unref);
641 static GstIteratorItem
642 iterate_child_recurse (GstIterator * it, GstElement * child)
644 gst_object_ref (GST_OBJECT (child));
645 if (GST_IS_BIN (child)) {
646 GstIterator *other = gst_bin_iterate_recurse (GST_BIN (child));
648 gst_iterator_push (it, other);
650 return GST_ITERATOR_ITEM_PASS;
654 * gst_bin_iterate_recurse:
655 * @bin: #Gstbin to iterate the elements of
657 * Get an iterator for the elements in this bin.
658 * Each element will have its refcount increased, so unref
659 * after use. This iterator recurses into GstBin children.
663 * Returns: a #GstIterator of #GstElements. gst_iterator_free after
664 * use. returns NULL when passing bad parameters.
667 gst_bin_iterate_recurse (GstBin * bin)
671 g_return_val_if_fail (GST_IS_BIN (bin), NULL);
674 /* add ref because the iterator refs the bin. When the iterator
675 * is freed it will unref the bin again using the provided dispose
677 gst_object_ref (GST_OBJECT (bin));
678 result = gst_iterator_new_list (GST_GET_LOCK (bin),
679 &bin->children_cookie,
682 (GstIteratorItemFunction) iterate_child_recurse,
683 (GstIteratorDisposeFunction) gst_object_unref);
689 /* returns 0 when TRUE because this is a GCompareFunc */
692 bin_element_is_sink (GstElement * child, GstBin * bin)
696 /* we lock the child here for the remainder of the function to
697 * get its name safely. */
699 is_sink = GST_FLAG_IS_SET (child, GST_ELEMENT_IS_SINK);
702 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin,
703 "child %s %s sink", GST_OBJECT_NAME (child), is_sink ? "is" : "is not");
705 return is_sink ? 0 : 1;
709 has_ancestor (GstObject * object, GstObject * ancestor)
712 gboolean result = FALSE;
717 if (object == ancestor)
720 parent = gst_object_get_parent (object);
721 result = has_ancestor (parent, ancestor);
723 gst_object_unref (GST_OBJECT_CAST (parent));
728 /* returns 0 when TRUE because this is a GCompareFunc.
729 * This function returns elements that have no connected srcpads and
730 * are therefore not reachable from a real sink. */
733 bin_element_is_semi_sink (GstElement * child, GstBin * bin)
737 /* we lock the child here for the remainder of the function to
738 * get its pads and name safely. */
741 /* check if this is a sink element, these are the elements
742 * without (linked) source pads. */
743 if (child->numsrcpads == 0) {
745 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin,
746 "adding child %s as sink", GST_OBJECT_NAME (child));
749 /* loop over all pads, try to figure out if this element
750 * is a semi sink because it has no linked source pads */
752 gboolean connected_src = FALSE;
754 for (pads = child->srcpads; pads; pads = g_list_next (pads)) {
757 if ((peer = gst_pad_get_peer (GST_PAD_CAST (pads->data)))) {
759 has_ancestor (GST_OBJECT_CAST (peer), GST_OBJECT_CAST (bin));
760 gst_object_unref (GST_OBJECT_CAST (peer));
767 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin,
768 "not adding child %s as sink: linked source pads",
769 GST_OBJECT_NAME (child));
771 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin,
772 "adding child %s as sink since it has unlinked source pads in this bin",
773 GST_OBJECT_NAME (child));
783 sink_iterator_filter (GstElement * child, GstBin * bin)
785 if (bin_element_is_sink (child, bin) == 0) {
786 /* returns 0 because this is a GCompareFunc */
789 /* child carries a ref from gst_bin_iterate_elements -- drop if not passing
791 gst_object_unref ((GstObject *) child);
797 * gst_bin_iterate_sinks:
798 * @bin: #Gstbin to iterate on
800 * Get an iterator for the sink elements in this bin.
801 * Each element will have its refcount increased, so unref
804 * The sink elements are those without any linked srcpads.
808 * Returns: a #GstIterator of #GstElements. gst_iterator_free after use.
811 gst_bin_iterate_sinks (GstBin * bin)
813 GstIterator *children;
816 g_return_val_if_fail (GST_IS_BIN (bin), NULL);
818 children = gst_bin_iterate_elements (bin);
819 result = gst_iterator_filter (children,
820 (GCompareFunc) sink_iterator_filter, bin);
826 * 1) check state of all children with 0 timeout to find ERROR and
827 * NO_PREROLL elements. return if found.
828 * 2) perform full blocking wait with requested timeout.
830 * 2) cannot be performed when 1) returns results as the sinks might
831 * not be able to complete the state change making 2) block forever.
835 static GstElementStateReturn
836 gst_bin_get_state (GstElement * element, GstElementState * state,
837 GstElementState * pending, GTimeVal * timeout)
839 GstBin *bin = GST_BIN (element);
840 GstElementStateReturn ret = GST_STATE_SUCCESS;
842 guint32 children_cookie;
843 gboolean zero_timeout;
844 gboolean have_no_preroll;
846 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "getting state");
848 zero_timeout = timeout != NULL && timeout->tv_sec == 0
849 && timeout->tv_usec == 0;
851 /* lock bin, no element can be added or removed between going into
852 * the quick scan and the blocking wait. */
856 have_no_preroll = FALSE;
858 /* if we have a non zero timeout we must make sure not to block
859 * on the sinks when we have NO_PREROLL elements. This is why we do
860 * a quick check if there are still NO_PREROLL elements. We also
861 * catch the error elements this way. */
864 gboolean have_async = FALSE;
866 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "checking for NO_PREROLL");
867 /* use 0 timeout so we don't block on the sinks */
868 GST_TIME_TO_TIMEVAL (0, tv);
869 children = bin->children;
870 children_cookie = bin->children_cookie;
872 GstElement *child = GST_ELEMENT_CAST (children->data);
874 gst_object_ref (GST_OBJECT_CAST (child));
875 /* now we release the lock to enter a non blocking wait. We
876 * release the lock anyway since we can. */
879 ret = gst_element_get_state (child, NULL, NULL, &tv);
881 gst_object_unref (GST_OBJECT_CAST (child));
883 /* now grab the lock to iterate to the next child */
885 if (G_UNLIKELY (children_cookie != bin->children_cookie)) {
886 /* child added/removed during state change, restart. We need
887 * to restart with the quick check as a no-preroll element could
888 * have been added here and we don't want to block on sinks then.*/
893 /* report FAILURE or NO_PREROLL immediatly */
894 case GST_STATE_FAILURE:
896 case GST_STATE_NO_PREROLL:
897 /* we have to continue scanning as there might be
899 have_no_preroll = TRUE;
901 case GST_STATE_ASYNC:
907 children = g_list_next (children);
909 /* if we get here, we have no FAILURES, check for any NO_PREROLL
911 if (have_no_preroll) {
912 ret = GST_STATE_NO_PREROLL;
916 /* if we get here, no NO_PREROLL elements are in the pipeline */
917 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "no NO_PREROLL elements");
919 /* if no ASYNC elements exist we don't even have to poll with a
922 ret = GST_STATE_SUCCESS;
927 /* next we poll all children for their state to see if one of them
928 * is still busy with its state change. We did not release the bin lock
929 * yet so the elements are the same as the ones from the quick scan. */
930 children = bin->children;
931 children_cookie = bin->children_cookie;
933 GstElement *child = GST_ELEMENT_CAST (children->data);
935 gst_object_ref (GST_OBJECT_CAST (child));
936 /* now we release the lock to enter the potentialy blocking wait */
939 /* ret is ASYNC if some child is still performing the state change
940 * ater the timeout. */
941 ret = gst_element_get_state (child, NULL, NULL, timeout);
943 gst_object_unref (GST_OBJECT_CAST (child));
945 /* now grab the lock to iterate to the next child */
947 if (G_UNLIKELY (children_cookie != bin->children_cookie)) {
948 /* child added/removed during state change, restart. We need
949 * to restart with the quick check as a no-preroll element could
950 * have been added here and we don't want to block on sinks then.*/
955 case GST_STATE_SUCCESS:
957 case GST_STATE_FAILURE:
958 case GST_STATE_NO_PREROLL:
959 /* report FAILURE and NO_PREROLL immediatly */
962 case GST_STATE_ASYNC:
963 /* since we checked for non prerollable elements before,
964 * the first ASYNC return is the real return value */
969 g_assert_not_reached ();
971 children = g_list_next (children);
973 /* if we got here, all elements can do preroll */
974 have_no_preroll = FALSE;
979 /* now we can take the state lock, it is possible that new elements
980 * are added now and we still report the old state. No problem though as
981 * the return is still consistent, the effect is as if the element was
982 * added after this function completed. */
983 GST_STATE_LOCK (bin);
985 case GST_STATE_SUCCESS:
986 /* we can commit the state */
987 gst_element_commit_state (element);
989 case GST_STATE_FAILURE:
990 /* some element failed, abort the state change */
991 gst_element_abort_state (element);
994 /* other cases are just passed along */
998 /* and report the state if needed */
1000 *state = GST_STATE (element);
1002 *pending = GST_STATE_PENDING (element);
1004 GST_STATE_NO_PREROLL (element) = have_no_preroll;
1006 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
1007 "state current: %s, pending: %s, error: %d, no_preroll: %d, result: %d",
1008 gst_element_state_get_name (GST_STATE (element)),
1009 gst_element_state_get_name (GST_STATE_PENDING (element)),
1010 GST_STATE_ERROR (element), GST_STATE_NO_PREROLL (element), ret);
1012 GST_STATE_UNLOCK (bin);
1018 append_child (gpointer child, GQueue * queue)
1020 g_queue_push_tail (queue, child);
1024 * gst_bin_iterate_state_order:
1025 * @bin: #Gstbin to iterate on
1027 * Get an iterator for the elements in this bin in the order
1028 * in which a state change should be performed on them. This
1029 * means that first the sinks and then the other elements will
1031 * Each element will have its refcount increased, so unref
1036 * Returns: a #GstIterator of #GstElements. gst_iterator_free after use.
1039 gst_bin_iterate_state_order (GstBin * bin)
1041 GstIterator *result;
1043 g_return_val_if_fail (GST_IS_BIN (bin), NULL);
1050 /* this function is called with the STATE_LOCK held. It works
1053 * 1) put all sink elements on the queue.
1054 * 2) put all semisink elements on the queue.
1055 * 3) change state of elements in queue, put linked elements to queue.
1056 * 4) while queue not empty goto 3)
1058 * This will effectively change the state of all elements in the bin
1059 * from the sinks to the sources. We have to change the states this
1060 * way so that when a source element pushes data, the downstream element
1061 * is in the right state to receive the data.
1065 static GstElementStateReturn
1066 gst_bin_change_state (GstElement * element)
1069 GstElementStateReturn ret;
1070 GstElementState old_state, pending;
1071 gboolean have_async = FALSE;
1072 gboolean have_no_preroll = FALSE;
1074 guint32 children_cookie;
1075 GQueue *elem_queue; /* list of elements waiting for a state change */
1076 GQueue *semi_queue; /* list of elements with no connected srcpads */
1077 GQueue *temp; /* queue of leftovers */
1079 bin = GST_BIN (element);
1081 /* we don't need to take the STATE_LOCK, it is already taken */
1082 old_state = GST_STATE (element);
1083 pending = GST_STATE_PENDING (element);
1085 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
1086 "changing state of children from %s to %s",
1087 gst_element_state_get_name (old_state),
1088 gst_element_state_get_name (pending));
1090 if (pending == GST_STATE_VOID_PENDING)
1091 return GST_STATE_SUCCESS;
1093 /* all elements added to these queues should have their refcount
1095 elem_queue = g_queue_new ();
1096 semi_queue = g_queue_new ();
1097 temp = g_queue_new ();
1099 /* first step, find all sink elements, these are the elements
1100 * without (linked) source pads. */
1103 children = bin->children;
1104 children_cookie = bin->children_cookie;
1106 GstElement *child = GST_ELEMENT_CAST (children->data);
1108 gst_object_ref (GST_OBJECT_CAST (child));
1111 if (bin_element_is_sink (child, bin) == 0) {
1112 g_queue_push_tail (elem_queue, child);
1113 } else if (bin_element_is_semi_sink (child, bin) == 0) {
1114 g_queue_push_tail (semi_queue, child);
1116 g_queue_push_tail (temp, child);
1120 if (G_UNLIKELY (children_cookie != bin->children_cookie)) {
1121 /* undo what we had */
1122 g_queue_foreach (elem_queue, (GFunc) gst_object_unref, NULL);
1123 g_queue_foreach (semi_queue, (GFunc) gst_object_unref, NULL);
1124 g_queue_foreach (temp, (GFunc) gst_object_unref, NULL);
1125 while (g_queue_pop_head (elem_queue));
1126 while (g_queue_pop_head (semi_queue));
1127 while (g_queue_pop_head (temp));
1131 children = g_list_next (children);
1135 /* now change state for semi sink elements first so add them in
1136 * front of the other elements */
1137 g_queue_foreach (temp, (GFunc) append_child, semi_queue);
1138 g_queue_free (temp);
1140 /* can be the case for a bin like ( identity ) */
1141 if (g_queue_is_empty (elem_queue) && !g_queue_is_empty (semi_queue)) {
1142 GQueue *q = elem_queue;
1144 elem_queue = semi_queue;
1148 /* second step, change state of elements in the queue */
1149 while (!g_queue_is_empty (elem_queue)) {
1150 GstElement *qelement;
1155 qelement = g_queue_pop_head (elem_queue);
1156 /* we don't need it in the semi_queue anymore */
1157 g_queue_remove_all (semi_queue, qelement);
1159 /* if queue is empty now, continue with a non-sink */
1160 if (g_queue_is_empty (elem_queue)) {
1161 GstElement *non_sink;
1163 GST_DEBUG ("sinks and upstream elements exhausted");
1164 non_sink = g_queue_pop_head (semi_queue);
1166 GST_DEBUG ("found lefover non-sink %s", GST_OBJECT_NAME (non_sink));
1167 g_queue_push_tail (elem_queue, non_sink);
1171 /* queue all elements connected to the sinkpads of this element */
1172 GST_LOCK (qelement);
1173 pads = qelement->sinkpads;
1175 GstPad *pad = GST_PAD_CAST (pads->data);
1178 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
1179 "found sinkpad %s:%s", GST_DEBUG_PAD_NAME (pad));
1181 peer = gst_pad_get_peer (pad);
1183 GstElement *peer_elem;
1185 peer_elem = gst_pad_get_parent (peer);
1190 /* see if this element is in the bin we are currently handling */
1191 parent = gst_object_get_parent (GST_OBJECT_CAST (peer_elem));
1192 if (parent && parent == GST_OBJECT_CAST (bin)) {
1195 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
1196 "adding element %s to queue", GST_ELEMENT_NAME (peer_elem));
1198 /* make sure we don't have duplicates */
1199 while ((oldelem = g_queue_find (semi_queue, peer_elem))) {
1200 gst_object_unref (GST_OBJECT (peer_elem));
1201 g_queue_delete_link (semi_queue, oldelem);
1203 while ((oldelem = g_queue_find (elem_queue, peer_elem))) {
1204 gst_object_unref (GST_OBJECT (peer_elem));
1205 g_queue_delete_link (elem_queue, oldelem);
1207 /* was reffed before pushing on the queue by the
1208 * gst_object_get_parent() call we used to get the element. */
1209 g_queue_push_tail (elem_queue, peer_elem);
1211 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
1212 "not adding element %s to queue, it is in another bin",
1213 GST_ELEMENT_NAME (peer_elem));
1214 gst_object_unref (GST_OBJECT_CAST (peer_elem));
1217 gst_object_unref (parent);
1220 gst_object_unref (GST_OBJECT_CAST (peer));
1222 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
1223 "pad %s:%s does not have a peer", GST_DEBUG_PAD_NAME (pad));
1225 pads = g_list_next (pads);
1227 /* peel off the locked flag and release the element lock */
1228 locked = GST_FLAG_IS_SET (qelement, GST_ELEMENT_LOCKED_STATE);
1229 GST_UNLOCK (qelement);
1231 if (G_UNLIKELY (locked))
1234 qelement->base_time = element->base_time;
1235 ret = gst_element_set_state (qelement, pending);
1237 case GST_STATE_SUCCESS:
1238 GST_CAT_DEBUG (GST_CAT_STATES,
1239 "child '%s' changed state to %d(%s) successfully",
1240 GST_ELEMENT_NAME (qelement), pending,
1241 gst_element_state_get_name (pending));
1243 case GST_STATE_ASYNC:
1244 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
1245 "child '%s' is changing state asynchronously",
1246 GST_ELEMENT_NAME (qelement));
1249 case GST_STATE_FAILURE:
1250 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
1251 "child '%s' failed to go to state %d(%s)",
1252 GST_ELEMENT_NAME (qelement),
1253 pending, gst_element_state_get_name (pending));
1254 ret = GST_STATE_FAILURE;
1255 /* release refcount of element we popped off the queue */
1256 gst_object_unref (GST_OBJECT (qelement));
1258 case GST_STATE_NO_PREROLL:
1259 GST_CAT_DEBUG (GST_CAT_STATES,
1260 "child '%s' changed state to %d(%s) successfully without preroll",
1261 GST_ELEMENT_NAME (qelement), pending,
1262 gst_element_state_get_name (pending));
1263 have_no_preroll = TRUE;
1266 g_assert_not_reached ();
1270 gst_object_unref (GST_OBJECT (qelement));
1273 if (have_no_preroll) {
1274 ret = GST_STATE_NO_PREROLL;
1275 } else if (have_async) {
1276 ret = GST_STATE_ASYNC;
1278 if ((ret = parent_class->change_state (element)) == GST_STATE_SUCCESS) {
1279 /* we can commit the state change now */
1280 gst_element_commit_state (element);
1284 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
1285 "done changing bin's state from %s to %s, now in %s",
1286 gst_element_state_get_name (old_state),
1287 gst_element_state_get_name (pending),
1288 gst_element_state_get_name (GST_STATE (element)));
1291 /* release refcounts in queue, should normally be empty unless we
1293 g_queue_foreach (elem_queue, (GFunc) gst_object_unref, NULL);
1294 g_queue_free (elem_queue);
1295 g_queue_foreach (semi_queue, (GFunc) gst_object_unref, NULL);
1296 g_queue_free (semi_queue);
1302 gst_bin_dispose (GObject * object)
1304 GstBin *bin = GST_BIN (object);
1306 GST_CAT_DEBUG_OBJECT (GST_CAT_REFCOUNTING, object, "dispose");
1308 /* ref to not hit 0 again */
1309 gst_object_ref (GST_OBJECT (object));
1311 while (bin->children) {
1312 gst_bin_remove (bin, GST_ELEMENT (bin->children->data));
1314 GST_CAT_DEBUG_OBJECT (GST_CAT_REFCOUNTING, object, "dispose no children");
1315 g_assert (bin->children == NULL);
1316 g_assert (bin->numchildren == 0);
1318 G_OBJECT_CLASS (parent_class)->dispose (object);
1322 * This function is a utility event handler for seek events.
1323 * It will send the event to all sinks.
1324 * Applications are free to override this behaviour and
1325 * implement their own seek handler, but this will work for
1326 * pretty much all cases in practice.
1329 gst_bin_send_event (GstElement * element, GstEvent * event)
1331 GstBin *bin = GST_BIN (element);
1333 gboolean res = TRUE;
1334 gboolean done = FALSE;
1336 iter = gst_bin_iterate_sinks (bin);
1337 GST_DEBUG_OBJECT (bin, "Sending event to sink children");
1342 switch (gst_iterator_next (iter, &data)) {
1343 case GST_ITERATOR_OK:
1347 gst_event_ref (event);
1348 sink = GST_ELEMENT_CAST (data);
1349 res &= gst_element_send_event (sink, event);
1350 gst_object_unref (GST_OBJECT (sink));
1353 case GST_ITERATOR_RESYNC:
1354 gst_iterator_resync (iter);
1358 case GST_ITERATOR_DONE:
1363 gst_iterator_free (iter);
1364 gst_event_unref (event);
1370 gst_bin_query (GstElement * element, GstQuery * query)
1372 GstBin *bin = GST_BIN (element);
1374 gboolean res = FALSE, done = FALSE;
1376 iter = gst_bin_iterate_sinks (bin);
1377 GST_DEBUG_OBJECT (bin, "Sending event to sink children");
1379 while (!(res || done)) {
1382 switch (gst_iterator_next (iter, &data)) {
1383 case GST_ITERATOR_OK:
1387 sink = GST_ELEMENT_CAST (data);
1388 res = gst_element_query (sink, query);
1389 gst_object_unref (GST_OBJECT (sink));
1392 case GST_ITERATOR_RESYNC:
1393 gst_iterator_resync (iter);
1396 case GST_ITERATOR_DONE:
1401 gst_iterator_free (iter);
1407 compare_name (GstElement * element, const gchar * name)
1412 eq = strcmp (GST_ELEMENT_NAME (element), name);
1413 GST_UNLOCK (element);
1416 gst_object_unref (GST_OBJECT (element));
1422 * gst_bin_get_by_name:
1423 * @bin: #Gstbin to search
1424 * @name: the element name to search for
1426 * Get the element with the given name from this bin. This
1427 * function recurses into subbins.
1431 * Returns: the element with the given name. Returns NULL if the
1432 * element is not found or when bad parameters were given. Unref after
1436 gst_bin_get_by_name (GstBin * bin, const gchar * name)
1438 GstIterator *children;
1439 GstIterator *result;
1441 g_return_val_if_fail (GST_IS_BIN (bin), NULL);
1443 GST_CAT_INFO (GST_CAT_PARENTAGE, "[%s]: looking up child element %s",
1444 GST_ELEMENT_NAME (bin), name);
1446 children = gst_bin_iterate_recurse (bin);
1447 result = gst_iterator_find_custom (children,
1448 (GCompareFunc) compare_name, (gpointer) name);
1449 gst_iterator_free (children);
1451 return GST_ELEMENT_CAST (result);
1455 * gst_bin_get_by_name_recurse_up:
1456 * @bin: #Gstbin to search
1457 * @name: the element name to search for
1461 * Get the element with the given name from this bin. If the
1462 * element is not found, a recursion is performed on the parent bin.
1464 * Returns: the element with the given name or NULL when the element
1465 * was not found or bad parameters were given. Unref after use.
1468 gst_bin_get_by_name_recurse_up (GstBin * bin, const gchar * name)
1472 g_return_val_if_fail (GST_IS_BIN (bin), NULL);
1473 g_return_val_if_fail (name != NULL, NULL);
1475 result = gst_bin_get_by_name (bin, name);
1480 parent = gst_object_get_parent (GST_OBJECT_CAST (bin));
1482 if (GST_IS_BIN (parent)) {
1483 result = gst_bin_get_by_name_recurse_up (GST_BIN_CAST (parent), name);
1485 gst_object_unref (parent);
1493 compare_interface (GstElement * element, gpointer interface)
1497 if (G_TYPE_CHECK_INSTANCE_TYPE (element, GPOINTER_TO_INT (interface))) {
1500 /* we did not find the element, need to release the ref
1501 * added by the iterator */
1502 gst_object_unref (GST_OBJECT (element));
1509 * gst_bin_get_by_interface:
1510 * @bin: bin to find element in
1511 * @interface: interface to be implemented by interface
1513 * Looks for the first element inside the bin that implements the given
1514 * interface. If such an element is found, it returns the element. You can
1515 * cast this element to the given interface afterwards.
1516 * If you want all elements that implement the interface, use
1517 * gst_bin_iterate_all_by_interface(). The function recurses inside bins.
1521 * Returns: An #GstElement inside the bin implementing the interface.
1525 gst_bin_get_by_interface (GstBin * bin, GType interface)
1527 GstIterator *children;
1528 GstIterator *result;
1530 g_return_val_if_fail (GST_IS_BIN (bin), NULL);
1532 children = gst_bin_iterate_recurse (bin);
1533 result = gst_iterator_find_custom (children, (GCompareFunc) compare_interface,
1534 GINT_TO_POINTER (interface));
1535 gst_iterator_free (children);
1537 return GST_ELEMENT_CAST (result);
1541 * gst_bin_get_all_by_interface:
1542 * @bin: bin to find elements in
1543 * @interface: interface to be implemented by interface
1545 * Looks for all elements inside the bin that implements the given
1546 * interface. You can safely cast all returned elements to the given interface.
1547 * The function recurses bins inside bins. The iterator will return a series
1548 * of #GstElement that should be unreffed after use.
1552 * Returns: A #GstIterator for the elements inside the bin implementing the
1556 gst_bin_iterate_all_by_interface (GstBin * bin, GType interface)
1558 GstIterator *children;
1559 GstIterator *result;
1561 g_return_val_if_fail (GST_IS_BIN (bin), NULL);
1563 children = gst_bin_iterate_recurse (bin);
1564 result = gst_iterator_filter (children, (GCompareFunc) compare_interface,
1565 GINT_TO_POINTER (interface));
1570 #ifndef GST_DISABLE_LOADSAVE
1572 gst_bin_save_thyself (GstObject * object, xmlNodePtr parent)
1574 GstBin *bin = GST_BIN (object);
1575 xmlNodePtr childlist, elementnode;
1579 if (GST_OBJECT_CLASS (parent_class)->save_thyself)
1580 GST_OBJECT_CLASS (parent_class)->save_thyself (GST_OBJECT (bin), parent);
1582 childlist = xmlNewChild (parent, NULL, (xmlChar *) "children", NULL);
1584 GST_CAT_INFO (GST_CAT_XML, "[%s]: saving %d children",
1585 GST_ELEMENT_NAME (bin), bin->numchildren);
1587 children = bin->children;
1589 child = GST_ELEMENT (children->data);
1590 elementnode = xmlNewChild (childlist, NULL, (xmlChar *) "element", NULL);
1591 gst_object_save_thyself (GST_OBJECT (child), elementnode);
1592 children = g_list_next (children);
1598 gst_bin_restore_thyself (GstObject * object, xmlNodePtr self)
1600 GstBin *bin = GST_BIN (object);
1601 xmlNodePtr field = self->xmlChildrenNode;
1602 xmlNodePtr childlist;
1605 if (!strcmp ((char *) field->name, "children")) {
1606 GST_CAT_INFO (GST_CAT_XML, "[%s]: loading children",
1607 GST_ELEMENT_NAME (object));
1608 childlist = field->xmlChildrenNode;
1610 if (!strcmp ((char *) childlist->name, "element")) {
1611 GstElement *element =
1612 gst_xml_make_element (childlist, GST_OBJECT (bin));
1614 /* it had to be parented to find the pads, now we ref and unparent so
1615 * we can add it to the bin */
1616 gst_object_ref (GST_OBJECT (element));
1617 gst_object_unparent (GST_OBJECT (element));
1619 gst_bin_add (bin, element);
1621 childlist = childlist->next;
1625 field = field->next;
1627 if (GST_OBJECT_CLASS (parent_class)->restore_thyself)
1628 (GST_OBJECT_CLASS (parent_class)->restore_thyself) (object, self);
1630 #endif /* GST_DISABLE_LOADSAVE */