/** * gst_ghost_pad_set_target: * @gpad: the #GstGhostPad * @newtarget: (transfer none) (allow-none): the new pad target * * Set the new target of the ghostpad @gpad. Any existing target * is unlinked and links to the new target are established. if @newtarget is * %NULL the target will be cleared. * * Returns: (transfer full): %TRUE if the new target could be set. This function * can return %FALSE when the internal pads could not be linked. */ gboolean gst_ghost_pad_set_target (GstGhostPad * gpad, GstPad * newtarget) { GstPad *internal; GstPad *oldtarget; GstPadLinkReturn lret; g_return_val_if_fail (GST_IS_GHOST_PAD (gpad), FALSE); g_return_val_if_fail (GST_PAD_CAST (gpad) != newtarget, FALSE); g_return_val_if_fail (newtarget != GST_PROXY_PAD_INTERNAL (gpad), FALSE); GST_OBJECT_LOCK (gpad); internal = GST_PROXY_PAD_INTERNAL (gpad); if (newtarget) GST_DEBUG_OBJECT (gpad, "set target %s:%s", GST_DEBUG_PAD_NAME (newtarget)); else GST_DEBUG_OBJECT (gpad, "clearing target"); /* clear old target */ if ((oldtarget = gst_pad_get_peer (internal))) { GST_OBJECT_UNLOCK (gpad); /* unlink internal pad */ if (GST_PAD_IS_SRC (internal)) gst_pad_unlink (internal, oldtarget); else gst_pad_unlink (oldtarget, internal); gst_object_unref (oldtarget); } else { GST_OBJECT_UNLOCK (gpad); } if (newtarget) { /* and link to internal pad without any checks */ GST_DEBUG_OBJECT (gpad, "connecting internal pad to target %" GST_PTR_FORMAT, newtarget); if (GST_PAD_IS_SRC (internal)) lret = gst_pad_link_full (internal, newtarget, GST_PAD_LINK_CHECK_NOTHING); else lret = gst_pad_link_full (newtarget, internal, GST_PAD_LINK_CHECK_NOTHING); if (lret != GST_PAD_LINK_OK) goto link_failed; } return TRUE; /* ERRORS */ link_failed: { GST_WARNING_OBJECT (gpad, "could not link internal and target, reason:%s", gst_pad_link_get_name (lret)); return FALSE; } }
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"); other = GST_PROXY_PAD_INTERNAL (pad); ret = gst_pad_activate_mode (other, GST_PAD_MODE_PULL, active); } 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 { /* 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; } return ret; }
static gboolean gst_ghost_pad_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) { /* the ghostpad is SRC and activated in pull mode by its peer, call the * activation function of the internal pad to propagate the activation * upstream */ GST_LOG_OBJECT (pad, "pad is src, activate internal"); other = GST_PROXY_PAD_INTERNAL (pad); ret = gst_pad_activate_mode (other, GST_PAD_MODE_PULL, active); } else if (G_LIKELY ((other = gst_pad_get_peer (pad)))) { /* We are SINK and activated by the internal pad, propagate activation * upstream because we hold a ref 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 { /* no peer, we fail */ GST_LOG_OBJECT (pad, "pad not src and no peer, failing"); ret = FALSE; } return ret; }
EXPORT_C #endif gboolean gst_ghost_pad_set_target (GstGhostPad * gpad, GstPad * newtarget) { GstPad *internal; GstPad *oldtarget; gboolean result; GstPadLinkReturn lret; g_return_val_if_fail (GST_IS_GHOST_PAD (gpad), FALSE); GST_PROXY_LOCK (gpad); internal = GST_PROXY_PAD_INTERNAL (gpad); GST_DEBUG_OBJECT (gpad, "set target %s:%s", GST_DEBUG_PAD_NAME (newtarget)); /* clear old target */ if ((oldtarget = GST_PROXY_PAD_TARGET (gpad))) { /* if we have an internal pad, unlink */ if (internal) { if (GST_PAD_IS_SRC (internal)) gst_pad_unlink (internal, oldtarget); else gst_pad_unlink (oldtarget, internal); } } result = gst_proxy_pad_set_target_unlocked (GST_PAD_CAST (gpad), newtarget); if (result && newtarget) { /* and link to internal pad */ GST_DEBUG_OBJECT (gpad, "connecting internal pad to target"); if (GST_PAD_IS_SRC (internal)) lret = gst_pad_link (internal, newtarget); else lret = gst_pad_link (newtarget, internal); if (lret != GST_PAD_LINK_OK) goto link_failed; } GST_PROXY_UNLOCK (gpad); return result; /* ERRORS */ link_failed: { GST_WARNING_OBJECT (gpad, "could not link internal and target, reason:%d", lret); /* and unset target again */ gst_proxy_pad_set_target_unlocked (GST_PAD_CAST (gpad), NULL); GST_PROXY_UNLOCK (gpad); return FALSE; } }
static gboolean gst_proxy_pad_do_checkgetrange (GstPad * pad) { gboolean result; GstPad *internal = GST_PROXY_PAD_INTERNAL (pad); result = gst_pad_check_pull_range (internal); return result; }
static GstFlowReturn gst_proxy_pad_do_chain (GstPad * pad, GstBuffer * buffer) { GstFlowReturn res; GstPad *internal = GST_PROXY_PAD_INTERNAL (pad); res = gst_pad_push (internal, buffer); return res; }
static gboolean gst_proxy_pad_do_event (GstPad * pad, GstEvent * event) { gboolean res = FALSE; GstPad *internal = GST_PROXY_PAD_INTERNAL (pad); res = gst_pad_push_event (internal, event); return res; }
static void gst_ghost_pad_dispose (GObject * object) { GstPad *pad; GstPad *internal; GstPad *peer; pad = GST_PAD (object); GST_DEBUG_OBJECT (pad, "dispose"); gst_ghost_pad_set_target (GST_GHOST_PAD (pad), NULL); /* Unlink here so that gst_pad_dispose doesn't. That would lead to a call to * gst_ghost_pad_do_unlink when the ghost pad is in an inconsistent state */ peer = gst_pad_get_peer (pad); if (peer) { if (GST_PAD_IS_SRC (pad)) gst_pad_unlink (pad, peer); else gst_pad_unlink (peer, pad); gst_object_unref (peer); } GST_PROXY_LOCK (pad); internal = GST_PROXY_PAD_INTERNAL (pad); gst_pad_set_activatepull_function (internal, NULL); gst_pad_set_activatepush_function (internal, NULL); g_signal_handler_disconnect (internal, GST_GHOST_PAD_PRIVATE (pad)->notify_id); /* disposes of the internal pad, since the ghostpad is the only possible object * that has a refcount on the internal pad. */ gst_object_unparent (GST_OBJECT_CAST (internal)); GST_PROXY_PAD_INTERNAL (pad) = NULL; GST_PROXY_UNLOCK (pad); G_OBJECT_CLASS (gst_ghost_pad_parent_class)->dispose (object); }
static GstFlowReturn gst_proxy_pad_do_getrange (GstPad * pad, guint64 offset, guint size, GstBuffer ** buffer) { GstFlowReturn res; GstPad *internal = GST_PROXY_PAD_INTERNAL (pad); res = gst_pad_pull_range (internal, offset, size, buffer); return res; }
static GstFlowReturn gst_proxy_pad_do_bufferalloc (GstPad * pad, guint64 offset, guint size, GstCaps * caps, GstBuffer ** buf) { GstFlowReturn result; GstPad *internal = GST_PROXY_PAD_INTERNAL (pad); result = gst_pad_alloc_buffer (internal, offset, size, caps, buf); return result; }
static GstPad * gst_proxy_pad_get_target (GstPad * pad) { GstPad *target; GST_OBJECT_LOCK (pad); target = gst_pad_get_peer (GST_PROXY_PAD_INTERNAL (pad)); GST_OBJECT_UNLOCK (pad); return target; }
static void gst_ghost_pad_dispose (GObject * object) { GstPad *pad; GstPad *internal; GstPad *intpeer; pad = GST_PAD (object); GST_DEBUG_OBJECT (pad, "dispose"); GST_PROXY_LOCK (pad); internal = GST_PROXY_PAD_INTERNAL (pad); gst_pad_set_activatepull_function (internal, NULL); gst_pad_set_activatepush_function (internal, NULL); g_signal_handler_disconnect (internal, GST_GHOST_PAD_CAST (pad)->notify_id); intpeer = gst_pad_get_peer (internal); if (intpeer) { if (GST_PAD_IS_SRC (internal)) gst_pad_unlink (internal, intpeer); else gst_pad_unlink (intpeer, internal); gst_object_unref (intpeer); } GST_PROXY_PAD_INTERNAL (internal) = NULL; /* disposes of the internal pad, since the ghostpad is the only possible object * that has a refcount on the internal pad. */ gst_object_unparent (GST_OBJECT_CAST (internal)); GST_PROXY_UNLOCK (pad); G_OBJECT_CLASS (gst_ghost_pad_parent_class)->dispose (object); }
/** * gst_proxy_pad_get_internal: * @pad: the #GstProxyPad * * Get the internal pad of @pad. Unref target pad after usage. * * The internal pad of a #GstGhostPad is the internally used * pad of opposite direction, which is used to link to the target. * * Returns: (transfer full): the target #GstProxyPad, can be NULL. * Unref target pad after usage. */ GstProxyPad * gst_proxy_pad_get_internal (GstProxyPad * pad) { GstPad *internal; g_return_val_if_fail (GST_IS_PROXY_PAD (pad), NULL); GST_OBJECT_LOCK (pad); internal = GST_PROXY_PAD_INTERNAL (pad); if (internal) gst_object_ref (internal); GST_OBJECT_UNLOCK (pad); return GST_PROXY_PAD_CAST (internal); }
static gboolean gst_ghost_pad_do_activate_push (GstPad * pad, gboolean active) { gboolean ret; GstPad *other; GST_LOG_OBJECT (pad, "%sactivate push on %s:%s, proxy internal", (active ? "" : "de"), GST_DEBUG_PAD_NAME (pad)); /* just activate the internal pad */ other = GST_PROXY_PAD_INTERNAL (pad); ret = gst_pad_activate_push (other, active); return ret; }
/** * gst_proxy_pad_getrange_default: * @pad: a src #GstPad, returns #GST_FLOW_ERROR if not. * @parent: the parent of @pad * @offset: The start offset of the buffer * @size: The length of the buffer * @buffer: (out callee-allocates): a pointer to hold the #GstBuffer, * returns #GST_FLOW_ERROR if %NULL. * * Invoke the default getrange function of the proxy pad. * * Returns: a #GstFlowReturn from the pad. */ GstFlowReturn gst_proxy_pad_getrange_default (GstPad * pad, GstObject * parent, guint64 offset, guint size, GstBuffer ** buffer) { GstFlowReturn res; GstPad *internal; g_return_val_if_fail (GST_IS_PROXY_PAD (pad), GST_FLOW_ERROR); g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR); internal = GST_PROXY_PAD_INTERNAL (pad); res = gst_pad_pull_range (internal, offset, size, buffer); return res; }
/** * gst_proxy_pad_chain_list_default: * @pad: a sink #GstPad, returns GST_FLOW_ERROR if not. * @parent: the parent of @pad or NULL * @list: (transfer full): the #GstBufferList to send, return GST_FLOW_ERROR * if not. * * Invoke the default chain list function of the proxy pad. * * Returns: a #GstFlowReturn from the pad. */ GstFlowReturn gst_proxy_pad_chain_list_default (GstPad * pad, GstObject * parent, GstBufferList * list) { GstFlowReturn res; GstPad *internal; g_return_val_if_fail (GST_IS_PROXY_PAD (pad), GST_FLOW_ERROR); g_return_val_if_fail (GST_IS_BUFFER_LIST (list), GST_FLOW_ERROR); internal = GST_PROXY_PAD_INTERNAL (pad); res = gst_pad_push_list (internal, list); return res; }
/** * gst_proxy_pad_chain_default: * @pad: a sink #GstPad, returns GST_FLOW_ERROR if not. * @parent: the parent of @pad or NULL * @buffer: (transfer full): the #GstBuffer to send, return GST_FLOW_ERROR * if not. * * Invoke the default chain function of the proxy pad. * * Returns: a #GstFlowReturn from the pad. */ GstFlowReturn gst_proxy_pad_chain_default (GstPad * pad, GstObject * parent, GstBuffer * buffer) { GstFlowReturn res; GstPad *internal; g_return_val_if_fail (GST_IS_PROXY_PAD (pad), GST_FLOW_ERROR); g_return_val_if_fail (GST_IS_BUFFER (buffer), GST_FLOW_ERROR); internal = GST_PROXY_PAD_INTERNAL (pad); res = gst_pad_push (internal, buffer); return res; }
/* see gstghostpad design docs */ static gboolean gst_ghost_pad_internal_do_activate_push (GstPad * pad, gboolean active) { gboolean ret; GstPad *other; GST_LOG_OBJECT (pad, "%sactivate push on %s:%s, we're ok", (active ? "" : "de"), GST_DEBUG_PAD_NAME (pad)); /* in both cases (SRC and SINK) we activate just the internal pad. The targets * will be activated later (or already in case of a ghost sinkpad). */ other = GST_PROXY_PAD_INTERNAL (pad); ret = gst_pad_activate_push (other, active); return ret; }
/** * gst_proxy_pad_iterate_internal_links_default: * @pad: the #GstPad to get the internal links of. * @parent: the parent of @pad or NULL * * Invoke the default iterate internal links function of the proxy pad. * * Returns: a #GstIterator of #GstPad, or NULL if @pad has no parent. Unref each * returned pad with gst_object_unref(). */ GstIterator * gst_proxy_pad_iterate_internal_links_default (GstPad * pad, GstObject * parent) { GstIterator *res = NULL; GstPad *internal; GValue v = { 0, }; g_return_val_if_fail (GST_IS_PROXY_PAD (pad), NULL); internal = GST_PROXY_PAD_INTERNAL (pad); g_value_init (&v, GST_TYPE_PAD); g_value_set_object (&v, internal); res = gst_iterator_new_single (GST_TYPE_PAD, &v); g_value_unset (&v); return res; }
static gboolean gst_ghost_pad_activate_push_default (GstPad * pad, GstObject * parent, gboolean active) { gboolean ret; GstPad *other; g_return_val_if_fail (GST_IS_GHOST_PAD (pad), FALSE); GST_LOG_OBJECT (pad, "%sactivate push on %s:%s, proxy internal", (active ? "" : "de"), GST_DEBUG_PAD_NAME (pad)); /* just activate the internal pad */ other = GST_PROXY_PAD_INTERNAL (pad); ret = gst_pad_activate_mode (other, GST_PAD_MODE_PUSH, active); return ret; }
static void gst_ghost_pad_do_unlink (GstPad * pad) { GstPad *target; GstPad *internal; target = gst_proxy_pad_get_target (pad); internal = GST_PROXY_PAD_INTERNAL (pad); GST_DEBUG_OBJECT (pad, "unlinking ghostpad"); /* The target of the internal pad is no longer valid */ gst_proxy_pad_set_target (internal, NULL); if (target) { if (GST_PAD_UNLINKFUNC (target)) GST_PAD_UNLINKFUNC (target) (target); gst_object_unref (target); } }
static GstPadLinkReturn gst_ghost_pad_do_link (GstPad * pad, GstPad * peer) { GstPadLinkReturn ret; GstPad *internal; GST_DEBUG_OBJECT (pad, "linking ghostpad"); internal = GST_PROXY_PAD_INTERNAL (pad); if (!gst_proxy_pad_set_target (internal, peer)) goto target_failed; ret = GST_PAD_LINK_OK; /* if we are a source pad, we should call the peer link function * if the peer has one, see design docs. */ if (GST_PAD_IS_SRC (pad)) { if (GST_PAD_LINKFUNC (peer)) { ret = GST_PAD_LINKFUNC (peer) (peer, pad); if (ret != GST_PAD_LINK_OK) goto link_failed; } } return ret; /* ERRORS */ target_failed: { GST_DEBUG_OBJECT (pad, "setting target failed"); return GST_PAD_LINK_REFUSED; } link_failed: { GST_DEBUG_OBJECT (pad, "linking failed"); /* clear target again */ gst_proxy_pad_set_target (internal, NULL); return ret; } }
/** * gst_ghost_pad_construct: * @gpad: the newly allocated ghost pad * * Finish initialization of a newly allocated ghost pad. * * This function is most useful in language bindings and when subclassing * #GstGhostPad; plugin and application developers normally will not call this * function. Call this function directly after a call to g_object_new * (GST_TYPE_GHOST_PAD, "direction", @dir, ..., NULL). * * Returns: %TRUE if the construction succeeds, %FALSE otherwise. */ gboolean gst_ghost_pad_construct (GstGhostPad * gpad) { GstPadDirection dir, otherdir; GstPadTemplate *templ; GstPad *pad, *internal; g_return_val_if_fail (GST_IS_GHOST_PAD (gpad), FALSE); g_return_val_if_fail (GST_GHOST_PAD_PRIVATE (gpad)->constructed == FALSE, FALSE); g_object_get (gpad, "direction", &dir, "template", &templ, NULL); g_return_val_if_fail (dir != GST_PAD_UNKNOWN, FALSE); pad = GST_PAD (gpad); /* Set directional padfunctions for ghostpad */ if (dir == GST_PAD_SINK) { gst_pad_set_chain_function (pad, gst_proxy_pad_chain_default); gst_pad_set_chain_list_function (pad, gst_proxy_pad_chain_list_default); } else { gst_pad_set_getrange_function (pad, gst_proxy_pad_getrange_default); } /* INTERNAL PAD, it always exists and is child of the ghostpad */ otherdir = (dir == GST_PAD_SRC) ? GST_PAD_SINK : GST_PAD_SRC; if (templ) { internal = g_object_new (GST_TYPE_PROXY_PAD, "name", NULL, "direction", otherdir, "template", templ, NULL); /* release ref obtained via g_object_get */ gst_object_unref (templ); } else { internal = g_object_new (GST_TYPE_PROXY_PAD, "name", NULL, "direction", otherdir, NULL); } GST_PAD_UNSET_FLUSHING (internal); /* Set directional padfunctions for internal pad */ if (dir == GST_PAD_SRC) { gst_pad_set_chain_function (internal, gst_proxy_pad_chain_default); gst_pad_set_chain_list_function (internal, gst_proxy_pad_chain_list_default); } else { gst_pad_set_getrange_function (internal, gst_proxy_pad_getrange_default); } GST_OBJECT_LOCK (pad); /* now make the ghostpad a parent of the internal pad */ if (!gst_object_set_parent (GST_OBJECT_CAST (internal), GST_OBJECT_CAST (pad))) goto parent_failed; /* The ghostpad is the parent of the internal pad and is the only object that * can have a refcount on the internal pad. * At this point, the GstGhostPad has a refcount of 1, and the internal pad has * a refcount of 1. * When the refcount of the GstGhostPad drops to 0, the ghostpad will dispose * its refcount on the internal pad in the dispose method by un-parenting it. * This is why we don't take extra refcounts in the assignments below */ GST_PROXY_PAD_INTERNAL (pad) = internal; GST_PROXY_PAD_INTERNAL (internal) = pad; /* special activation functions for the internal pad */ gst_pad_set_activatemode_function (internal, gst_ghost_pad_internal_activate_mode_default); GST_OBJECT_UNLOCK (pad); GST_GHOST_PAD_PRIVATE (gpad)->constructed = TRUE; return TRUE; /* ERRORS */ parent_failed: { GST_WARNING_OBJECT (gpad, "Could not set internal pad %s:%s", GST_DEBUG_PAD_NAME (internal)); g_critical ("Could not set internal pad %s:%s", GST_DEBUG_PAD_NAME (internal)); GST_OBJECT_UNLOCK (pad); gst_object_unref (internal); return FALSE; } }
static GstPad * gst_ghost_pad_new_full (const gchar * name, GstPadDirection dir, GstPadTemplate * templ) { GstPad *ret; GstPad *internal; GstPadDirection otherdir; g_return_val_if_fail (dir != GST_PAD_UNKNOWN, NULL); /* OBJECT CREATION */ if (templ) { ret = g_object_new (GST_TYPE_GHOST_PAD, "name", name, "direction", dir, "template", templ, NULL); } else { ret = g_object_new (GST_TYPE_GHOST_PAD, "name", name, "direction", dir, NULL); } /* Set directional padfunctions for ghostpad */ if (dir == GST_PAD_SINK) { gst_pad_set_bufferalloc_function (ret, GST_DEBUG_FUNCPTR (gst_proxy_pad_do_bufferalloc)); gst_pad_set_chain_function (ret, GST_DEBUG_FUNCPTR (gst_proxy_pad_do_chain)); } else { gst_pad_set_getrange_function (ret, GST_DEBUG_FUNCPTR (gst_proxy_pad_do_getrange)); gst_pad_set_checkgetrange_function (ret, GST_DEBUG_FUNCPTR (gst_proxy_pad_do_checkgetrange)); } /* link/unlink functions */ gst_pad_set_link_function (ret, GST_DEBUG_FUNCPTR (gst_ghost_pad_do_link)); gst_pad_set_unlink_function (ret, GST_DEBUG_FUNCPTR (gst_ghost_pad_do_unlink)); /* INTERNAL PAD, it always exists and is child of the ghostpad */ otherdir = (dir == GST_PAD_SRC) ? GST_PAD_SINK : GST_PAD_SRC; if (templ) { internal = g_object_new (GST_TYPE_PROXY_PAD, "name", NULL, "direction", otherdir, "template", templ, NULL); } else { internal = g_object_new (GST_TYPE_PROXY_PAD, "name", NULL, "direction", otherdir, NULL); } GST_PAD_UNSET_FLUSHING (internal); /* Set directional padfunctions for internal pad */ if (dir == GST_PAD_SRC) { gst_pad_set_bufferalloc_function (internal, GST_DEBUG_FUNCPTR (gst_proxy_pad_do_bufferalloc)); gst_pad_set_chain_function (internal, GST_DEBUG_FUNCPTR (gst_proxy_pad_do_chain)); } else { gst_pad_set_getrange_function (internal, GST_DEBUG_FUNCPTR (gst_proxy_pad_do_getrange)); gst_pad_set_checkgetrange_function (internal, GST_DEBUG_FUNCPTR (gst_proxy_pad_do_checkgetrange)); } GST_PROXY_LOCK (ret); /* now make the ghostpad a parent of the internal pad */ if (!gst_object_set_parent (GST_OBJECT_CAST (internal), GST_OBJECT_CAST (ret))) goto parent_failed; /* The ghostpad is the parent of the internal pad and is the only object that * can have a refcount on the internal pad. * At this point, the GstGhostPad has a refcount of 1, and the internal pad has * a refcount of 1. * When the refcount of the GstGhostPad drops to 0, the ghostpad will dispose * it's refcount on the internal pad in the dispose method by un-parenting it. * This is why we don't take extra refcounts in the assignments below */ GST_PROXY_PAD_INTERNAL (ret) = internal; GST_PROXY_PAD_INTERNAL (internal) = ret; /* could be more general here, iterating over all writable properties... * taking the short road for now tho */ GST_GHOST_PAD_CAST (ret)->notify_id = g_signal_connect (internal, "notify::caps", G_CALLBACK (on_int_notify), ret); /* call function to init values of the pad caps */ on_int_notify (internal, NULL, GST_GHOST_PAD_CAST (ret)); /* special activation functions for the internal pad */ gst_pad_set_activatepull_function (internal, GST_DEBUG_FUNCPTR (gst_ghost_pad_internal_do_activate_pull)); gst_pad_set_activatepush_function (internal, GST_DEBUG_FUNCPTR (gst_ghost_pad_internal_do_activate_push)); GST_PROXY_UNLOCK (ret); return ret; /* ERRORS */ parent_failed: { GST_WARNING_OBJECT (ret, "Could not set internal pad %s:%s", GST_DEBUG_PAD_NAME (internal)); g_critical ("Could not set internal pad %s:%s", GST_DEBUG_PAD_NAME (internal)); GST_PROXY_UNLOCK (ret); gst_object_unref (ret); gst_object_unref (internal); return NULL; } }