/** * helper for gst_goo_util_find_goo_component() to iterate and search * the members of a bin */ static GooComponent * find_goo_component_in_bin (GstBin *bin, SearchContext *ctx) { GstIterator *itr; gpointer item; GooComponent *component = NULL; GST_INFO ("bin=%s (%s)", gst_element_get_name (bin), G_OBJECT_TYPE_NAME (bin)); /* note: we don't handle the case of the underlying data structure changing * while iterating.. we just bail out and the user needs to restart. */ for( itr = gst_bin_iterate_elements (bin); gst_iterator_next (itr, &item) == GST_ITERATOR_OK && !component; gst_object_unref (item) ) { GstElement *elem = GST_ELEMENT (item); component = check_for_goo_component (elem, ctx); if( component == NULL ) { component = find_goo_component (elem, ctx); } } gst_iterator_free (itr); return component; }
static GooComponent * find_goo_component (GstElement *elem, SearchContext *ctx) { GooComponent *component = check_for_goo_component (elem, ctx); if (component == NULL) { if (GST_IS_BIN (elem)) { component = find_goo_component_in_bin (GST_BIN (elem), ctx); } } if (component == NULL) { component = find_goo_component_in_elem (elem, ctx); } return component; }
/** * recursively iterate all our pads and search adjacent elements */ static GooComponent * find_goo_component (GstElement *elem, SearchContext *ctx) { GstIterator *itr; gpointer item; GooComponent *component = NULL; /* check if we've already examined this element, to prevent loops: */ if (already_visited (ctx->visited_nodes, elem)) { GST_INFO ("already visited elem=%s (%s)", gst_element_get_name (elem), G_OBJECT_TYPE_NAME (elem)); return NULL; } GST_INFO ("elem=%s (%s)", gst_element_get_name (elem), G_OBJECT_TYPE_NAME (elem)); /* note: we don't handle the case of the underlying data structure changing * while iterating.. we just bail out and the user needs to restart. */ for( itr = gst_element_iterate_pads (elem); gst_iterator_next (itr, &item) == GST_ITERATOR_OK && !component; gst_object_unref (item) ) { GstElement *adjacent_elem = NULL; GstPad *pad = GST_PAD (item); GstPad *peer = gst_pad_get_peer (pad); GST_INFO ("found pad: %s (%s)", gst_pad_get_name (pad), G_OBJECT_TYPE_NAME (pad)); if (G_UNLIKELY (peer == NULL)) { GST_INFO ("NULL peer.. not connected yet?"); continue; } /* in the case of GstGhostPad (and probably other proxy pads) * the parent is actually the pad we are a proxy for, so * keep looping until we find the GstElement */ while(TRUE) { GstObject *obj = gst_pad_get_parent (peer); if( GST_IS_PAD(obj) ) { gst_object_unref (peer); peer = GST_PAD (obj); } else { adjacent_elem = GST_ELEMENT (obj); break; } } if (G_UNLIKELY (adjacent_elem == NULL)) { gst_object_unref (peer); GST_INFO ("Cannot find a adjacent element"); continue; } GST_INFO ("found adjacent_elem: %s", gst_element_get_name (adjacent_elem)); component = check_for_goo_component (adjacent_elem, ctx); if (component == NULL) { /* if adjacent_elem is itself a bin, we need to search the * contents of that bin: */ if( GST_IS_BIN (adjacent_elem) ) { component = find_goo_component_in_bin (GST_BIN (adjacent_elem), ctx); } } if (component == NULL) { /* if we didn't find our component, recursively search * the contents of adjacent_elem's pads: */ component = find_goo_component (adjacent_elem, ctx); } /* cleanup: */ gst_object_unref (adjacent_elem); gst_object_unref (peer); } gst_iterator_free (itr); return component; }