/** * 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; } }
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 GstPadProbeReturn input_selector_pad_probe (GstPad * pad, GstPadProbeInfo * info, gpointer userdata) { GstPad *sink_pad = NULL; if (info->type == GST_PAD_PROBE_TYPE_BUFFER) { BufferCountData *bcd = g_object_get_data (G_OBJECT (pad), "buffer-count-data"); if (!bcd) { GST_ERROR_OBJECT (pad, "No buffer-count-data found"); return GST_PAD_PROBE_OK; } ++bcd->counter; if (GST_PAD_IS_SRC (pad)) { g_object_get (GST_PAD_PARENT (pad), "active-pad", &sink_pad, NULL); if (sink_pad) { bcd = g_object_get_data (G_OBJECT (sink_pad), "buffer-count-data"); if (!bcd) { gst_object_unref (sink_pad); GST_ERROR_OBJECT (pad, "No buffer-count-data found"); return GST_PAD_PROBE_OK; } ++bcd->back_counter; gst_object_unref (sink_pad); } } } return GST_PAD_PROBE_OK; }
static void Gstreamer_transform_pad_added(GstElement *filter, GstPad *pad, GstTfImpl *This) { int ret; if (!GST_PAD_IS_SRC(pad)) return; ret = gst_pad_link(pad, This->my_sink); if (ret < 0) WARN("Failed to link with %i\n", ret); This->their_src = pad; gst_pad_set_active(pad, TRUE); gst_pad_set_active(This->my_sink, TRUE); }
void Gstreamer_transform_pad_added(GstElement *filter, GstPad *pad, gpointer user) { GstTfImpl *This = (GstTfImpl*)user; int ret; TRACE("%p %p %p\n", This, filter, pad); if (!GST_PAD_IS_SRC(pad)) return; ret = gst_pad_link(pad, This->my_sink); if (ret < 0) WARN("Failed to link with %i\n", ret); This->their_src = pad; }
static void gst_tee_dispose (GObject * object) { GList *item; restart: for (item = GST_ELEMENT_PADS (object); item; item = g_list_next (item)) { GstPad *pad = GST_PAD (item->data); if (GST_PAD_IS_SRC (pad)) { gst_element_release_request_pad (GST_ELEMENT (object), pad); goto restart; } } G_OBJECT_CLASS (parent_class)->dispose (object); }
static int gst_ffmpegdata_open (URLContext * h, const char *filename, int flags) { GstProtocolInfo *info; GstPad *pad; GST_LOG ("Opening %s", filename); info = g_new0 (GstProtocolInfo, 1); info->set_streamheader = flags & GST_FFMPEG_URL_STREAMHEADER; flags &= ~GST_FFMPEG_URL_STREAMHEADER; h->flags &= ~GST_FFMPEG_URL_STREAMHEADER; /* we don't support R/W together */ if (flags != URL_RDONLY && flags != URL_WRONLY) { GST_WARNING ("Only read-only or write-only are supported"); return -EINVAL; } if (sscanf (&filename[12], "%p", &pad) != 1) { GST_WARNING ("could not decode pad from %s", filename); return -EIO; } /* make sure we're a pad and that we're of the right type */ g_return_val_if_fail (GST_IS_PAD (pad), -EINVAL); switch (flags) { case URL_RDONLY: g_return_val_if_fail (GST_PAD_IS_SINK (pad), -EINVAL); break; case URL_WRONLY: g_return_val_if_fail (GST_PAD_IS_SRC (pad), -EINVAL); break; } info->eos = FALSE; info->pad = pad; info->offset = 0; h->priv_data = (void *) info; h->is_streamed = FALSE; h->max_packet_size = 0; return 0; }
static const GstFormat * gst_speex_enc_get_formats (GstPad * pad) { static const GstFormat src_formats[] = { GST_FORMAT_BYTES, GST_FORMAT_TIME, 0 }; static const GstFormat sink_formats[] = { GST_FORMAT_BYTES, GST_FORMAT_DEFAULT, GST_FORMAT_TIME, 0 }; return (GST_PAD_IS_SRC (pad) ? src_formats : sink_formats); }
static const GstFormat * theora_get_formats (GstPad * pad) { static GstFormat src_formats[] = { GST_FORMAT_DEFAULT, /* frames in this case */ GST_FORMAT_TIME, GST_FORMAT_BYTES, 0 }; static GstFormat sink_formats[] = { GST_FORMAT_DEFAULT, GST_FORMAT_TIME, 0 }; return (GST_PAD_IS_SRC (pad) ? src_formats : sink_formats); }
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); }
/** * gst_proxy_pad_save_thyself: * @pad: a ghost #GstPad to save. * @parent: the parent #xmlNodePtr to save the description in. * * Saves the ghost pad into an xml representation. * * Returns: the #xmlNodePtr representation of the pad. */ static xmlNodePtr gst_proxy_pad_save_thyself (GstObject * object, xmlNodePtr parent) { xmlNodePtr self; GstProxyPad *proxypad; GstPad *pad; GstPad *peer; g_return_val_if_fail (GST_IS_PROXY_PAD (object), NULL); self = xmlNewChild (parent, NULL, (xmlChar *) "ghostpad", NULL); xmlNewChild (self, NULL, (xmlChar *) "name", (xmlChar *) GST_OBJECT_NAME (object)); xmlNewChild (self, NULL, (xmlChar *) "parent", (xmlChar *) GST_OBJECT_NAME (GST_OBJECT_PARENT (object))); proxypad = GST_PROXY_PAD_CAST (object); pad = GST_PAD_CAST (proxypad); peer = GST_PAD_CAST (pad->peer); if (GST_IS_PAD (pad)) { if (GST_PAD_IS_SRC (pad)) xmlNewChild (self, NULL, (xmlChar *) "direction", (xmlChar *) "source"); else if (GST_PAD_IS_SINK (pad)) xmlNewChild (self, NULL, (xmlChar *) "direction", (xmlChar *) "sink"); else xmlNewChild (self, NULL, (xmlChar *) "direction", (xmlChar *) "unknown"); } else { xmlNewChild (self, NULL, (xmlChar *) "direction", (xmlChar *) "unknown"); } if (GST_IS_PAD (peer)) { gchar *content = g_strdup_printf ("%s.%s", GST_OBJECT_NAME (GST_PAD_PARENT (peer)), GST_PAD_NAME (peer)); xmlNewChild (self, NULL, (xmlChar *) "peer", (xmlChar *) content); g_free (content); } else { xmlNewChild (self, NULL, (xmlChar *) "peer", NULL); } return self; }
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); }
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; } }
static gboolean gst_tcp_mix_src_stop (GstTCPMixSrc * src, GstTCPMixSrcPad * pad) { GError *err = NULL; GList *item; GST_OBJECT_LOCK (src); GST_DEBUG_OBJECT (src, "Closing client sockets"); for (item = GST_ELEMENT_PADS (src); item; item = g_list_next (item)) { GstPad *p = GST_PAD (item->data); if (GST_PAD_IS_SRC (p)) { gst_tcp_mix_src_pad_reset (GST_TCP_MIX_SRC_PAD (p)); } } GST_OBJECT_UNLOCK (src); if (src->server_socket) { GST_DEBUG_OBJECT (src, "Closing server socket"); if (!g_socket_close (src->server_socket, &err)) { GST_ERROR_OBJECT (src, "Failed to close socket: %s", err->message); g_clear_error (&err); } g_object_unref (src->server_socket); src->server_socket = NULL; gst_tcp_mix_src_stop_acceptor (src); g_atomic_int_set (&src->bound_port, 0); g_object_notify (G_OBJECT (src), "bound-port"); } GST_OBJECT_FLAG_UNSET (src, GST_TCP_MIX_SRC_OPEN); return TRUE; }
static GstElement * setup_multiqueue (GstElement * pipe, GstElement * inputs[], GstElement * outputs[], guint num) { GstElement *mq; guint i; mq = gst_element_factory_make ("multiqueue", NULL); fail_unless (mq != NULL, "failed to create 'multiqueue' element"); gst_bin_add (GST_BIN (pipe), mq); for (i = 0; i < num; ++i) { GstPad *sinkpad = NULL; GstPad *srcpad = NULL; /* create multiqueue sink (and source) pad */ sinkpad = gst_element_get_request_pad (mq, "sink%d"); fail_unless (sinkpad != NULL, "failed to create multiqueue request pad #%u", i); /* link input element N to the N-th multiqueue sink pad we just created */ if (inputs != NULL && inputs[i] != NULL) { gst_bin_add (GST_BIN (pipe), inputs[i]); srcpad = gst_element_get_static_pad (inputs[i], "src"); fail_unless (srcpad != NULL, "failed to find src pad for input #%u", i); fail_unless_equals_int (GST_PAD_LINK_OK, gst_pad_link (srcpad, sinkpad)); gst_object_unref (srcpad); srcpad = NULL; } gst_object_unref (sinkpad); sinkpad = NULL; /* link output element N to the N-th multiqueue src pad */ if (outputs != NULL && outputs[i] != NULL) { gchar padname[10]; /* only the sink pads are by request, the source pads are sometimes pads, * so this should return NULL */ srcpad = gst_element_get_request_pad (mq, "src%d"); fail_unless (srcpad == NULL); g_snprintf (padname, sizeof (padname), "src%d", i); srcpad = gst_element_get_static_pad (mq, padname); fail_unless (srcpad != NULL, "failed to get multiqueue src pad #%u", i); fail_unless (GST_PAD_IS_SRC (srcpad), "%s:%s is not a source pad?!", GST_DEBUG_PAD_NAME (srcpad)); gst_bin_add (GST_BIN (pipe), outputs[i]); sinkpad = gst_element_get_static_pad (outputs[i], "sink"); fail_unless (sinkpad != NULL, "failed to find sink pad of output #%u", i); fail_unless (GST_PAD_IS_SINK (sinkpad)); fail_unless_equals_int (GST_PAD_LINK_OK, gst_pad_link (srcpad, sinkpad)); gst_object_unref (srcpad); gst_object_unref (sinkpad); } } return mq; }
static void gst_insert_bin_block_pad_unlock (GstInsertBin * self) { struct ChangeData *data; GstPad *pad; GstPadProbeType probetype; again: data = g_queue_peek_head (&self->priv->change_queue); if (!data) { GST_OBJECT_UNLOCK (self); return; } if (data->action == GST_INSERT_BIN_ACTION_ADD && !validate_element (self, data->element)) goto error; if (data->action == GST_INSERT_BIN_ACTION_ADD) { if (data->sibling) { if (data->direction == DIRECTION_BEFORE) pad = get_single_pad (data->sibling, GST_PAD_SINK); else pad = get_single_pad (data->sibling, GST_PAD_SRC); } else { if (data->direction == DIRECTION_BEFORE) pad = (GstPad *) gst_proxy_pad_get_internal (GST_PROXY_PAD (self->priv->srcpad)); else pad = (GstPad *) gst_proxy_pad_get_internal (GST_PROXY_PAD (self->priv->sinkpad)); } if (!pad) { GST_WARNING_OBJECT (self, "Can not obtain a sibling pad to block" " before adding"); goto error; } if (!is_right_direction_for_block (pad)) { GstPad *peer = gst_pad_get_peer (pad); if (peer) { gst_object_unref (pad); pad = peer; } } } else { GstPad *element_pad; element_pad = get_single_pad (data->element, GST_PAD_SINK); if (!element_pad) { GST_WARNING_OBJECT (self, "Can not obtain the element's sink pad"); goto error; } if (!is_right_direction_for_block (element_pad)) { pad = gst_pad_get_peer (element_pad); } else { gst_object_unref (element_pad); element_pad = get_single_pad (data->element, GST_PAD_SRC); if (!element_pad) { GST_WARNING_OBJECT (self, "Can not obtain the element's src pad"); goto error; } pad = gst_pad_get_peer (element_pad); } gst_object_unref (element_pad); if (!pad) { GST_WARNING_OBJECT (self, "Can not obtain a sibling pad for removing"); goto error; } } if (GST_PAD_IS_SRC (pad)) probetype = GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM; else probetype = GST_PAD_PROBE_TYPE_BLOCK_UPSTREAM; GST_OBJECT_UNLOCK (self); gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_IDLE | probetype, pad_blocked_cb, self, NULL); gst_object_unref (pad); return; error: g_queue_pop_head (&self->priv->change_queue); gst_insert_bin_change_data_complete (self, data, FALSE); goto again; }
static void gst_tcp_mix_src_add_client (GstTCPMixSrc * src, GSocket * socket) { GstTCPMixSrcPad *pad, *p; GList *item; GError *err; pad = NULL; GST_OBJECT_LOCK (src); for (item = GST_ELEMENT_PADS (src); item; item = g_list_next (item)) { p = pad = GST_TCP_MIX_SRC_PAD (item->data); if (GST_PAD_IS_SRC (p)) { GST_OBJECT_LOCK (p); if (pad->client) { pad = NULL; } else { GST_TCP_MIX_SRC_PAD_CLIENT_LOCK (pad); pad->client = socket; GST_TCP_MIX_SRC_PAD_CLIENT_NOTIFY (pad); GST_TCP_MIX_SRC_PAD_CLIENT_UNLOCK (pad); } GST_OBJECT_UNLOCK (p); if (pad) break; } } GST_OBJECT_UNLOCK (src); if (!pad) { pad = GST_TCP_MIX_SRC_PAD (gst_element_get_request_pad (GST_ELEMENT (src), srctemplate.name_template)); GST_OBJECT_LOCK (pad); GST_TCP_MIX_SRC_PAD_CLIENT_LOCK (pad); pad->client = socket; GST_TCP_MIX_SRC_PAD_CLIENT_NOTIFY (pad); GST_TCP_MIX_SRC_PAD_CLIENT_UNLOCK (pad); GST_OBJECT_UNLOCK (pad); } if (pad) { GST_DEBUG_OBJECT (pad, "New client on %s.%s (%d srcpads)", GST_ELEMENT_NAME (src), GST_PAD_NAME (pad), GST_ELEMENT (src)->numsrcpads); gst_tcp_mix_src_request_link_pad (src, pad); if (!gst_pad_is_linked (GST_PAD (pad))) { GST_ERROR_OBJECT (src, "Pad %s.%s is not linked", GST_ELEMENT_NAME (src), GST_PAD_NAME (pad)); } if (!gst_pad_is_active (GST_PAD (pad))) gst_pad_set_active (GST_PAD (pad), TRUE); g_signal_emit (src, gst_tcpmixsrc_signals[SIGNAL_NEW_CLIENT], 0, pad); } else { GST_WARNING_OBJECT (src, "No pad for new client, closing.."); if (!g_socket_close (socket, &err)) { GST_ERROR_OBJECT (src, "Failed to close socket: %s", err->message); g_clear_error (&err); } g_object_unref (socket); } }
static void gst_tcp_mix_src_request_link_pad (GstTCPMixSrc * src, GstTCPMixSrcPad * pad) { GstTCPMixSrcPad *p; GstPad *pp; GList *item; gboolean linked = FALSE; GstBin *parent; GstElement *target; GstPadLinkReturn linkRet; if (gst_pad_is_linked (GST_PAD (pad))) { #if 1 pp = GST_PAD_PEER (pad); GST_WARNING_OBJECT (src, "Pad %s.%s already linked to %s.%s", GST_ELEMENT_NAME (src), GST_PAD_NAME (pad), GST_ELEMENT_NAME (GST_PAD_PARENT (pp)), GST_PAD_NAME (pp)); #endif return; } GST_LOG_OBJECT (src, "Linking pad '%s.%s'", GST_ELEMENT_NAME (src), GST_PAD_NAME (pad)); INFO ("link"); /** * Don't do GST_OBJECT_LOCK() here, it causes DEADLOCK. */ /* GST_OBJECT_LOCK (src); */ if (!src->autosink) goto find_sink; parent = GST_BIN (GST_ELEMENT_PARENT (src)); target = gst_bin_get_by_name (parent, src->autosink); INFO ("link"); if (!target) goto find_sink; pp = gst_element_get_request_pad (target, "sink_%u"); GST_DEBUG_OBJECT (src, "Link %s.%s-%s.%s", GST_ELEMENT_NAME (src), GST_PAD_NAME (pad), GST_ELEMENT_NAME (GST_PAD_PARENT (pp)), GST_PAD_NAME (pp)); INFO ("link"); linkRet = gst_pad_link (GST_PAD (pad), GST_PAD (pp)); if (GST_PAD_LINK_FAILED (linkRet)) { GST_ERROR_OBJECT (src, "can't link"); } return; find_sink: #if 1 for (item = GST_ELEMENT_PADS (src); item; item = g_list_next (item)) { p = GST_TCP_MIX_SRC_PAD (item->data); if (GST_PAD_IS_SRC (p)) { GST_OBJECT_LOCK (p); if ((pp = GST_PAD_PEER (p))) { GstElement *ele = GST_ELEMENT (GST_PAD_PARENT (pp)); // FIXME: pad name calculation pp = gst_element_get_request_pad (ele, "sink_%u"); GST_DEBUG_OBJECT (src, "Link %s.%s-%s.%s", GST_ELEMENT_NAME (src), GST_PAD_NAME (pad), GST_ELEMENT_NAME (GST_PAD_PARENT (pp)), GST_PAD_NAME (pp)); linkRet = gst_pad_link (GST_PAD (pad), GST_PAD (pp)); if (GST_PAD_LINK_FAILED (linkRet)) { GST_ERROR_OBJECT (src, "can't link"); } else { linked = TRUE; } } GST_OBJECT_UNLOCK (p); if (linked) break; } } #endif /* GST_OBJECT_UNLOCK (src); */ return; }