/* Stolen from gst-plugins-good/ext/gconf/gconf.c */ static GstPad * my_gst_bin_find_unconnected_pad (GstBin * bin, GstPadDirection direction) { GstPad *pad = NULL; GList *elements = NULL; const GList *pads = NULL; GstElement *element = NULL; GST_OBJECT_LOCK (bin); elements = bin->children; /* traverse all elements looking for unconnected pads */ while (elements && pad == NULL) { element = GST_ELEMENT (elements->data); GST_OBJECT_LOCK (element); pads = element->pads; while (pads) { GstPad *testpad = GST_PAD (pads->data); /* check if the direction matches */ if (GST_PAD_DIRECTION (testpad) == direction) { GST_OBJECT_LOCK (testpad); if (GST_PAD_PEER (testpad) == NULL) { GST_OBJECT_UNLOCK (testpad); /* found it ! */ pad = testpad; break; } GST_OBJECT_UNLOCK (testpad); } pads = g_list_next (pads); } GST_OBJECT_UNLOCK (element); elements = g_list_next (elements); } GST_OBJECT_UNLOCK (bin); return pad; }
static gboolean gst_ghost_pad_internal_activate_pull_default (GstPad * pad, GstObject * parent, gboolean active) { gboolean ret; GstPad *other; GST_LOG_OBJECT (pad, "%sactivate pull on %s:%s", (active ? "" : "de"), GST_DEBUG_PAD_NAME (pad)); if (GST_PAD_DIRECTION (pad) == GST_PAD_SRC) { /* we are activated in pull mode by our peer element, which is a sinkpad * that wants to operate in pull mode. This activation has to propagate * upstream through the pipeline. We call the internal activation function, * which will trigger gst_ghost_pad_activate_pull_default, which propagates even * further upstream */ GST_LOG_OBJECT (pad, "pad is src, activate internal"); GST_PROXY_PAD_ACQUIRE_INTERNAL (pad, other, FALSE); ret = gst_pad_activate_mode (other, GST_PAD_MODE_PULL, active); GST_PROXY_PAD_RELEASE_INTERNAL (other); } else if (G_LIKELY ((other = gst_pad_get_peer (pad)))) { /* We are SINK, the ghostpad is SRC, we propagate the activation upstream * since we hold a pointer to the upstream peer. */ GST_LOG_OBJECT (pad, "activating peer"); ret = gst_pad_activate_mode (other, GST_PAD_MODE_PULL, active); gst_object_unref (other); } else if (active) { /* this is failure, we can't activate pull if there is no peer */ GST_LOG_OBJECT (pad, "not src and no peer, failing"); ret = FALSE; } else { GST_LOG_OBJECT (pad, "deactivating pull, with no peer - allowing"); ret = TRUE; } return ret; }
/* Clean up output/input pad and respective selector request pad */ void cleanup_pad (GstPad * pad, GstElement * element) { GstPad *selpad = NULL; guint probe_id = 0; fail_if (pad == NULL, "pad doesn't exist"); /* remove probe if necessary */ probe_id = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (pad), "probe_id")); if (probe_id) gst_pad_remove_data_probe (pad, probe_id); /* unlink */ selpad = gst_pad_get_peer (pad); if (GST_PAD_DIRECTION (selpad) == GST_PAD_SRC) { gst_pad_unlink (selpad, pad); } else { gst_pad_unlink (pad, selpad); } /* caps could have been set, make sure they get unset */ gst_pad_set_caps (pad, NULL); GST_DEBUG_OBJECT (pad, "clean up %" GST_PTR_FORMAT " and %" GST_PTR_FORMAT, selpad, pad); /* cleanup the pad */ gst_pad_set_active (pad, FALSE); ASSERT_OBJECT_REFCOUNT (pad, "pad", 1); gst_object_unref (pad); /* cleanup selector pad, reffed by this function (_get_peer) and creator */ gst_element_release_request_pad (element, selpad); gst_object_unref (selpad); }
static GstCaps * gst_deinterleave_sink_getcaps (GstPad * pad) { GstDeinterleave *self = GST_DEINTERLEAVE (gst_pad_get_parent (pad)); GstCaps *ret; GList *l; GST_OBJECT_LOCK (self); /* Intersect all of our pad template caps with the peer caps of the pad * to get all formats that are possible up- and downstream. * * For the pad for which the caps are requested we don't remove the channel * informations as they must be in the returned caps and incompatibilities * will be detected here already */ ret = gst_caps_new_any (); for (l = GST_ELEMENT (self)->pads; l != NULL; l = l->next) { GstPad *ourpad = GST_PAD (l->data); GstCaps *peercaps = NULL, *ourcaps; ourcaps = gst_caps_copy (gst_pad_get_pad_template_caps (ourpad)); if (pad == ourpad) { if (GST_PAD_DIRECTION (pad) == GST_PAD_SINK) __set_channels (ourcaps, self->channels); else __set_channels (ourcaps, 1); } else { __remove_channels (ourcaps); /* Only ask for peer caps for other pads than pad * as otherwise gst_pad_peer_get_caps() might call * back into this function and deadlock */ peercaps = gst_pad_peer_get_caps (ourpad); } /* If the peer exists and has caps add them to the intersection, * otherwise assume that the peer accepts everything */ if (peercaps) { GstCaps *intersection; GstCaps *oldret = ret; __remove_channels (peercaps); intersection = gst_caps_intersect (peercaps, ourcaps); ret = gst_caps_intersect (ret, intersection); gst_caps_unref (intersection); gst_caps_unref (peercaps); gst_caps_unref (oldret); } else { GstCaps *oldret = ret; ret = gst_caps_intersect (ret, ourcaps); gst_caps_unref (oldret); } gst_caps_unref (ourcaps); } GST_OBJECT_UNLOCK (self); gst_object_unref (self); GST_DEBUG_OBJECT (pad, "Intersected caps to %" GST_PTR_FORMAT, ret); return ret; }
/* Fetches a compatible pad on the target element which isn't already * linked */ static GstPad * get_compatible_unlinked_pad (GstElement * element, GstPad * pad) { GstPad *res = NULL; GstIterator *pads; gboolean done = FALSE; GstCaps *srccaps; if (G_UNLIKELY (pad == NULL)) goto no_pad; GST_DEBUG ("element : %s, pad %s:%s", GST_ELEMENT_NAME (element), GST_DEBUG_PAD_NAME (pad)); if (GST_PAD_DIRECTION (pad) == GST_PAD_SRC) pads = gst_element_iterate_sink_pads (element); else pads = gst_element_iterate_src_pads (element); srccaps = gst_pad_get_caps_reffed (pad); GST_DEBUG ("srccaps %" GST_PTR_FORMAT, srccaps); while (!done) { gpointer padptr; switch (gst_iterator_next (pads, &padptr)) { case GST_ITERATOR_OK: { GstPad *testpad = (GstPad *) padptr; if (gst_pad_is_linked (testpad)) { gst_object_unref (testpad); } else { GstCaps *sinkcaps = gst_pad_get_caps_reffed (testpad); GST_DEBUG ("sinkccaps %" GST_PTR_FORMAT, sinkcaps); if (gst_caps_can_intersect (srccaps, sinkcaps)) { res = testpad; done = TRUE; } else gst_object_unref (testpad); gst_caps_unref (sinkcaps); } } break; case GST_ITERATOR_DONE: case GST_ITERATOR_ERROR: done = TRUE; break; case GST_ITERATOR_RESYNC: gst_iterator_resync (pads); break; } } gst_iterator_free (pads); gst_caps_unref (srccaps); return res; no_pad: { GST_ERROR ("No pad to check against"); return NULL; } }