gst/gstutils.c (gst_element_link_pads): Instead of calling gst_pad_link, call pad_link_maybe_ghosting,

Original commit message from CVS:
2005-05-13  Andy Wingo  <wingo@pobox.com>

* gst/gstutils.c (gst_element_link_pads): Instead of calling
gst_pad_link, call pad_link_maybe_ghosting,
(pad_link_maybe_ghosting): Links pads, making sure that the
elements being linked are in the same bin.
(find_common_root, object_has_ancestor, ghost_up, remove_pad):
Helpers for pad_link_maybe_ghosting.
This commit is contained in:
Andy Wingo 2005-05-14 15:32:36 +00:00
parent 8eb7e12669
commit 79d4977020
2 changed files with 185 additions and 4 deletions

View file

@ -1,3 +1,12 @@
2005-05-13 Andy Wingo <wingo@pobox.com>
* gst/gstutils.c (gst_element_link_pads): Instead of calling
gst_pad_link, call pad_link_maybe_ghosting,
(pad_link_maybe_ghosting): Links pads, making sure that the
elements being linked are in the same bin.
(find_common_root, object_has_ancestor, ghost_up, remove_pad):
Helpers for pad_link_maybe_ghosting.
2005-05-13 Tim-Philipp Müller <tim at centricular dot net>
* configure.ac:

View file

@ -736,6 +736,178 @@ gst_element_state_get_name (GstElementState state)
return "";
}
/* if return val is true, *direct_child is a caller-owned ref on the direct
* child of ancestor that is part of object's ancestry */
static gboolean
object_has_ancestor (GstObject * object, GstObject * ancestor,
GstObject ** direct_child)
{
GstObject *child, *parent;
if (direct_child)
*direct_child = NULL;
child = gst_object_ref (object);
parent = gst_object_get_parent (object);
while (parent) {
if (ancestor == parent) {
if (direct_child)
*direct_child = child;
else
gst_object_unref (child);
gst_object_unref (parent);
return TRUE;
}
gst_object_unref (child);
child = parent;
parent = gst_object_get_parent (parent);
}
gst_object_unref (child);
return FALSE;
}
/* caller owns return */
static GstObject *
find_common_root (GstObject * o1, GstObject * o2)
{
GstObject *top = o1;
GstObject *kid1, *kid2;
GstObject *root = NULL;
while (GST_OBJECT_PARENT (top))
top = GST_OBJECT_PARENT (top);
/* the itsy-bitsy spider... */
if (!object_has_ancestor (o2, top, &kid2))
return NULL;
root = gst_object_ref (top);
while (TRUE) {
if (!object_has_ancestor (o1, kid2, &kid1)) {
gst_object_unref (kid2);
return root;
}
root = kid2;
if (!object_has_ancestor (o2, kid1, &kid2)) {
gst_object_unref (kid1);
return root;
}
root = kid1;
}
}
/* caller does not own return */
static GstPad *
ghost_up (GstElement * e, GstPad * pad)
{
static gint ghost_pad_index = 0;
GstPad *gpad;
gchar *name;
name = g_strdup_printf ("ghost%d", ghost_pad_index++);
gpad = gst_ghost_pad_new (name, pad);
g_free (name);
if (!gst_element_add_pad ((GstElement *) GST_OBJECT_PARENT (e), gpad)) {
g_warning ("Pad named %s already exists in element %s\n",
GST_OBJECT_NAME (gpad), GST_OBJECT_NAME (GST_OBJECT_PARENT (e)));
gst_object_unref ((GstObject *) gpad);
return NULL;
}
return gpad;
}
static void
remove_pad (gpointer ppad, gpointer unused)
{
GstPad *pad = ppad;
if (!gst_element_remove_pad ((GstElement *) GST_OBJECT_PARENT (pad), pad))
g_warning ("Couldn't remove pad %s from element %s",
GST_OBJECT_NAME (pad), GST_OBJECT_NAME (GST_OBJECT_PARENT (pad)));
}
static gboolean
prepare_link_maybe_ghosting (GstPad ** src, GstPad ** sink,
GSList ** pads_created)
{
GstObject *root;
GstObject *e1, *e2;
GSList *pads_created_local = NULL;
g_assert (pads_created);
e1 = GST_OBJECT_PARENT (*src);
e2 = GST_OBJECT_PARENT (*sink);
if (GST_OBJECT_PARENT (e1) == GST_OBJECT_PARENT (e2)) {
GST_CAT_INFO (GST_CAT_PADS, "%s and %s in same bin, no need for ghost pads",
GST_OBJECT_NAME (e1), GST_OBJECT_NAME (e2));
return TRUE;
}
GST_CAT_INFO (GST_CAT_PADS, "%s and %s not in same bin, making ghost pads",
GST_OBJECT_NAME (e1), GST_OBJECT_NAME (e2));
/* we need to setup some ghost pads */
root = find_common_root (e1, e2);
if (!root) {
g_warning
("Trying to connect elements that don't share a common ancestor: %s and %s\n",
GST_ELEMENT_NAME (e1), GST_ELEMENT_NAME (e2));
return FALSE;
}
while (GST_OBJECT_PARENT (e1) != root) {
*src = ghost_up ((GstElement *) e1, *src);
if (!*src)
goto cleanup_fail;
e1 = GST_OBJECT_PARENT (*src);
pads_created_local = g_slist_prepend (pads_created_local, *src);
}
while (GST_OBJECT_PARENT (e2) != root) {
*sink = ghost_up ((GstElement *) e2, *sink);
if (!*sink)
goto cleanup_fail;
e2 = GST_OBJECT_PARENT (*sink);
pads_created_local = g_slist_prepend (pads_created_local, *sink);
}
*pads_created = g_slist_concat (*pads_created, pads_created_local);
return TRUE;
cleanup_fail:
g_slist_foreach (pads_created_local, remove_pad, NULL);
g_slist_free (pads_created_local);
return FALSE;
}
static gboolean
pad_link_maybe_ghosting (GstPad * src, GstPad * sink)
{
GSList *pads_created = NULL;
gboolean ret;
if (!prepare_link_maybe_ghosting (&src, &sink, &pads_created)) {
ret = FALSE;
} else {
ret = (gst_pad_link (src, sink) == GST_PAD_LINK_OK);
}
if (!ret) {
g_slist_foreach (pads_created, remove_pad, NULL);
}
g_slist_free (pads_created);
return ret;
}
/**
* gst_element_link_pads:
* @src: a #GstElement containing the source pad.
@ -835,7 +1007,7 @@ gst_element_link_pads (GstElement * src, const gchar * srcpadname,
gboolean result;
/* two explicitly specified pads */
result = gst_pad_link (srcpad, destpad);
result = pad_link_maybe_ghosting (srcpad, destpad);
gst_object_unref (GST_OBJECT (srcpad));
gst_object_unref (GST_OBJECT (destpad));
@ -862,7 +1034,7 @@ gst_element_link_pads (GstElement * src, const gchar * srcpadname,
gst_object_ref (GST_OBJECT (temp));
}
if (temp && gst_pad_link (srcpad, temp) == GST_PAD_LINK_OK) {
if (temp && pad_link_maybe_ghosting (srcpad, temp)) {
GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "linked pad %s:%s to pad %s:%s",
GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (temp));
if (destpad)
@ -904,7 +1076,7 @@ gst_element_link_pads (GstElement * src, const gchar * srcpadname,
(GST_PAD_PEER (destpad) == NULL)) {
GstPad *temp = gst_element_get_compatible_pad (src, destpad, NULL);
if (temp && gst_pad_link (temp, destpad) == GST_PAD_LINK_OK) {
if (temp && pad_link_maybe_ghosting (temp, destpad)) {
GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "linked pad %s:%s to pad %s:%s",
GST_DEBUG_PAD_NAME (temp), GST_DEBUG_PAD_NAME (destpad));
gst_object_unref (GST_OBJECT (temp));
@ -958,7 +1130,7 @@ gst_element_link_pads (GstElement * src, const gchar * srcpadname,
gst_element_get_request_pad (src, srctempl->name_template);
destpad =
gst_element_get_request_pad (dest, desttempl->name_template);
if (gst_pad_link (srcpad, destpad) == GST_PAD_LINK_OK) {
if (pad_link_maybe_ghosting (srcpad, destpad)) {
GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
"linked pad %s:%s to pad %s:%s",
GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (destpad));