docs: fix unnecessary ampersand, < and > escaping in code blocks
[platform/upstream/gstreamer.git] / subprojects / gstreamer / gst / gstghostpad.c
1 /* GStreamer
2  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3  *                    2000 Wim Taymans <wtay@chello.be>
4  *                    2005 Andy Wingo <wingo@pobox.com>
5  *                    2006 Edward Hervey <bilboed@bilboed.com>
6  *
7  * gstghostpad.c: Proxy pads
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Library General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Library General Public License for more details.
18  *
19  * You should have received a copy of the GNU Library General Public
20  * License along with this library; if not, write to the
21  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
22  * Boston, MA 02110-1301, USA.
23  */
24
25 /**
26  * SECTION:gstghostpad
27  * @title: GstGhostPad
28  * @short_description: Pseudo link pads
29  * @see_also: #GstPad
30  *
31  * GhostPads are useful when organizing pipelines with #GstBin like elements.
32  * The idea here is to create hierarchical element graphs. The bin element
33  * contains a sub-graph. Now one would like to treat the bin-element like any
34  * other #GstElement. This is where GhostPads come into play. A GhostPad acts as
35  * a proxy for another pad. Thus the bin can have sink and source ghost-pads
36  * that are associated with sink and source pads of the child elements.
37  *
38  * If the target pad is known at creation time, gst_ghost_pad_new() is the
39  * function to use to get a ghost-pad. Otherwise one can use gst_ghost_pad_new_no_target()
40  * to create the ghost-pad and use gst_ghost_pad_set_target() to establish the
41  * association later on.
42  *
43  * Note that GhostPads add overhead to the data processing of a pipeline.
44  */
45
46 #include "gst_private.h"
47 #include "gstinfo.h"
48
49 #include "gstghostpad.h"
50 #include "gst.h"
51
52 #define GST_CAT_DEFAULT GST_CAT_PADS
53
54 #define GST_PROXY_PAD_CAST(obj)         ((GstProxyPad *)obj)
55 #define GST_PROXY_PAD_PRIVATE(obj)      (GST_PROXY_PAD_CAST (obj)->priv)
56 #define GST_PROXY_PAD_TARGET(pad)       (GST_PAD_PEER (GST_PROXY_PAD_INTERNAL (pad)))
57 #define GST_PROXY_PAD_INTERNAL(pad)     (GST_PROXY_PAD_PRIVATE (pad)->internal)
58
59 #define GST_PROXY_PAD_ACQUIRE_INTERNAL(pad, internal, retval)           \
60   internal =                                                            \
61       GST_PAD_CAST (gst_proxy_pad_get_internal (GST_PROXY_PAD_CAST (pad))); \
62   if (internal == NULL)                                                 \
63     return retval;
64
65 #define GST_PROXY_PAD_RELEASE_INTERNAL(internal) gst_object_unref (internal);
66
67 struct _GstProxyPadPrivate
68 {
69   GstPad *internal;
70 };
71
72 G_DEFINE_TYPE_WITH_PRIVATE (GstProxyPad, gst_proxy_pad, GST_TYPE_PAD);
73
74 static GstPad *gst_proxy_pad_get_target (GstPad * pad);
75
76 /**
77  * gst_proxy_pad_iterate_internal_links_default:
78  * @pad: the #GstPad to get the internal links of.
79  * @parent: (allow-none): the parent of @pad or %NULL
80  *
81  * Invoke the default iterate internal links function of the proxy pad.
82  *
83  * Returns: (nullable): a #GstIterator of #GstPad, or %NULL if @pad
84  * has no parent. Unref each returned pad with gst_object_unref().
85  */
86 GstIterator *
87 gst_proxy_pad_iterate_internal_links_default (GstPad * pad, GstObject * parent)
88 {
89   GstIterator *res = NULL;
90   GstPad *internal;
91   GValue v = { 0, };
92
93   g_return_val_if_fail (GST_IS_PROXY_PAD (pad), NULL);
94
95   GST_PROXY_PAD_ACQUIRE_INTERNAL (pad, internal, NULL);
96
97   g_value_init (&v, GST_TYPE_PAD);
98   g_value_take_object (&v, internal);
99   res = gst_iterator_new_single (GST_TYPE_PAD, &v);
100   g_value_unset (&v);
101
102   return res;
103 }
104
105 /**
106  * gst_proxy_pad_chain_default:
107  * @pad: a sink #GstPad, returns GST_FLOW_ERROR if not.
108  * @parent: (allow-none): the parent of @pad or %NULL
109  * @buffer: (transfer full): the #GstBuffer to send, return GST_FLOW_ERROR
110  *     if not.
111  *
112  * Invoke the default chain function of the proxy pad.
113  *
114  * Returns: a #GstFlowReturn from the pad.
115  */
116 GstFlowReturn
117 gst_proxy_pad_chain_default (GstPad * pad, GstObject * parent,
118     GstBuffer * buffer)
119 {
120   GstFlowReturn res;
121   GstPad *internal;
122
123   g_return_val_if_fail (GST_IS_PROXY_PAD (pad), GST_FLOW_ERROR);
124   g_return_val_if_fail (GST_IS_BUFFER (buffer), GST_FLOW_ERROR);
125
126   GST_PROXY_PAD_ACQUIRE_INTERNAL (pad, internal, GST_FLOW_NOT_LINKED);
127   res = gst_pad_push (internal, buffer);
128   GST_PROXY_PAD_RELEASE_INTERNAL (internal);
129
130   return res;
131 }
132
133 /**
134  * gst_proxy_pad_chain_list_default:
135  * @pad: a sink #GstPad, returns GST_FLOW_ERROR if not.
136  * @parent: (allow-none): the parent of @pad or %NULL
137  * @list: (transfer full): the #GstBufferList to send, return GST_FLOW_ERROR
138  *     if not.
139  *
140  * Invoke the default chain list function of the proxy pad.
141  *
142  * Returns: a #GstFlowReturn from the pad.
143  */
144 GstFlowReturn
145 gst_proxy_pad_chain_list_default (GstPad * pad, GstObject * parent,
146     GstBufferList * list)
147 {
148   GstFlowReturn res;
149   GstPad *internal;
150
151   g_return_val_if_fail (GST_IS_PROXY_PAD (pad), GST_FLOW_ERROR);
152   g_return_val_if_fail (GST_IS_BUFFER_LIST (list), GST_FLOW_ERROR);
153
154   GST_PROXY_PAD_ACQUIRE_INTERNAL (pad, internal, GST_FLOW_NOT_LINKED);
155   res = gst_pad_push_list (internal, list);
156   GST_PROXY_PAD_RELEASE_INTERNAL (internal);
157
158   return res;
159 }
160
161 /**
162  * gst_proxy_pad_getrange_default:
163  * @pad: a src #GstPad, returns #GST_FLOW_ERROR if not.
164  * @parent: the parent of @pad
165  * @offset: The start offset of the buffer
166  * @size: The length of the buffer
167  * @buffer: (out callee-allocates): a pointer to hold the #GstBuffer,
168  *     returns #GST_FLOW_ERROR if %NULL.
169  *
170  * Invoke the default getrange function of the proxy pad.
171  *
172  * Returns: a #GstFlowReturn from the pad.
173  */
174 GstFlowReturn
175 gst_proxy_pad_getrange_default (GstPad * pad, GstObject * parent,
176     guint64 offset, guint size, GstBuffer ** buffer)
177 {
178   GstFlowReturn res;
179   GstPad *internal;
180
181   g_return_val_if_fail (GST_IS_PROXY_PAD (pad), GST_FLOW_ERROR);
182   g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR);
183
184   GST_PROXY_PAD_ACQUIRE_INTERNAL (pad, internal, GST_FLOW_NOT_LINKED);
185   res = gst_pad_pull_range (internal, offset, size, buffer);
186   GST_PROXY_PAD_RELEASE_INTERNAL (internal);
187
188   return res;
189 }
190
191 static GstPad *
192 gst_proxy_pad_get_target (GstPad * pad)
193 {
194   GstPad *target;
195
196   GST_OBJECT_LOCK (pad);
197   target = gst_pad_get_peer (GST_PROXY_PAD_INTERNAL (pad));
198   GST_OBJECT_UNLOCK (pad);
199
200   return target;
201 }
202
203 /**
204  * gst_proxy_pad_get_internal:
205  * @pad: the #GstProxyPad
206  *
207  * Get the internal pad of @pad. Unref target pad after usage.
208  *
209  * The internal pad of a #GstGhostPad is the internally used
210  * pad of opposite direction, which is used to link to the target.
211  *
212  * Returns: (transfer full) (nullable): the target #GstProxyPad, can
213  * be %NULL.  Unref target pad after usage.
214  */
215 GstProxyPad *
216 gst_proxy_pad_get_internal (GstProxyPad * pad)
217 {
218   GstPad *internal;
219
220   g_return_val_if_fail (GST_IS_PROXY_PAD (pad), NULL);
221
222   GST_OBJECT_LOCK (pad);
223   internal = GST_PROXY_PAD_INTERNAL (pad);
224   if (internal)
225     gst_object_ref (internal);
226   GST_OBJECT_UNLOCK (pad);
227
228   return GST_PROXY_PAD_CAST (internal);
229 }
230
231 static void
232 gst_proxy_pad_class_init (GstProxyPadClass * klass)
233 {
234   /* Register common function pointer descriptions */
235   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_iterate_internal_links_default);
236   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_chain_default);
237   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_chain_list_default);
238   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_getrange_default);
239 }
240
241 static void
242 gst_proxy_pad_init (GstProxyPad * ppad)
243 {
244   GstPad *pad = (GstPad *) ppad;
245
246   GST_PROXY_PAD_PRIVATE (ppad) = gst_proxy_pad_get_instance_private (ppad);
247
248   gst_pad_set_iterate_internal_links_function (pad,
249       gst_proxy_pad_iterate_internal_links_default);
250
251   GST_PAD_SET_PROXY_CAPS (pad);
252   GST_PAD_SET_PROXY_SCHEDULING (pad);
253   GST_PAD_SET_PROXY_ALLOCATION (pad);
254 }
255
256
257 /***********************************************************************
258  * Ghost pads, implemented as a pair of proxy pads (sort of)
259  */
260 G_DEFINE_TYPE (GstGhostPad, gst_ghost_pad, GST_TYPE_PROXY_PAD);
261
262 static void gst_ghost_pad_dispose (GObject * object);
263 static void gst_ghost_pad_constructed (GObject * object);
264
265 static gboolean
266 gst_ghost_pad_internal_activate_push_default (GstPad * pad, GstObject * parent,
267     gboolean active)
268 {
269   gboolean ret;
270   GstPad *other;
271
272   GST_LOG_OBJECT (pad, "%sactivate push on %s:%s, we're ok",
273       (active ? "" : "de"), GST_DEBUG_PAD_NAME (pad));
274
275   /* in both cases (SRC and SINK) we activate just the internal pad. The targets
276    * will be activated later (or already in case of a ghost sinkpad). */
277   GST_PROXY_PAD_ACQUIRE_INTERNAL (pad, other, FALSE);
278   ret = gst_pad_activate_mode (other, GST_PAD_MODE_PUSH, active);
279   GST_PROXY_PAD_RELEASE_INTERNAL (other);
280
281   return ret;
282 }
283
284 static gboolean
285 gst_ghost_pad_internal_activate_pull_default (GstPad * pad, GstObject * parent,
286     gboolean active)
287 {
288   gboolean ret;
289   GstPad *other;
290
291   GST_LOG_OBJECT (pad, "%sactivate pull on %s:%s", (active ? "" : "de"),
292       GST_DEBUG_PAD_NAME (pad));
293
294   if (GST_PAD_DIRECTION (pad) == GST_PAD_SRC) {
295     /* we are activated in pull mode by our peer element, which is a sinkpad
296      * that wants to operate in pull mode. This activation has to propagate
297      * upstream through the pipeline. We call the internal activation function,
298      * which will trigger gst_ghost_pad_activate_pull_default, which propagates even
299      * further upstream */
300     GST_LOG_OBJECT (pad, "pad is src, activate internal");
301     GST_PROXY_PAD_ACQUIRE_INTERNAL (pad, other, FALSE);
302     ret = gst_pad_activate_mode (other, GST_PAD_MODE_PULL, active);
303     GST_PROXY_PAD_RELEASE_INTERNAL (other);
304   } else if (G_LIKELY ((other = gst_pad_get_peer (pad)))) {
305     /* We are SINK, the ghostpad is SRC, we propagate the activation upstream
306      * since we hold a pointer to the upstream peer. */
307     GST_LOG_OBJECT (pad, "activating peer");
308     ret = gst_pad_activate_mode (other, GST_PAD_MODE_PULL, active);
309     gst_object_unref (other);
310   } else if (active) {
311     /* this is failure, we can't activate pull if there is no peer */
312     GST_LOG_OBJECT (pad, "not src and no peer, failing");
313     ret = FALSE;
314   } else {
315     GST_LOG_OBJECT (pad, "deactivating pull, with no peer - allowing");
316     ret = TRUE;
317   }
318
319   return ret;
320 }
321
322 /**
323  * gst_ghost_pad_internal_activate_mode_default:
324  * @pad: the #GstPad to activate or deactivate.
325  * @parent: (allow-none): the parent of @pad or %NULL
326  * @mode: the requested activation mode
327  * @active: whether the pad should be active or not.
328  *
329  * Invoke the default activate mode function of a proxy pad that is
330  * owned by a ghost pad.
331  *
332  * Returns: %TRUE if the operation was successful.
333  */
334 gboolean
335 gst_ghost_pad_internal_activate_mode_default (GstPad * pad, GstObject * parent,
336     GstPadMode mode, gboolean active)
337 {
338   gboolean res;
339
340   g_return_val_if_fail (GST_IS_PROXY_PAD (pad), FALSE);
341
342   switch (mode) {
343     case GST_PAD_MODE_PULL:
344       res = gst_ghost_pad_internal_activate_pull_default (pad, parent, active);
345       break;
346     case GST_PAD_MODE_PUSH:
347       res = gst_ghost_pad_internal_activate_push_default (pad, parent, active);
348       break;
349     default:
350       GST_LOG_OBJECT (pad, "unknown activation mode %d", mode);
351       res = FALSE;
352       break;
353   }
354   return res;
355 }
356
357 static gboolean
358 gst_ghost_pad_activate_push_default (GstPad * pad, GstObject * parent,
359     gboolean active)
360 {
361   gboolean ret;
362   GstPad *other;
363
364   g_return_val_if_fail (GST_IS_GHOST_PAD (pad), FALSE);
365
366   GST_LOG_OBJECT (pad, "%sactivate push on %s:%s, proxy internal",
367       (active ? "" : "de"), GST_DEBUG_PAD_NAME (pad));
368
369   /* just activate the internal pad */
370   GST_PROXY_PAD_ACQUIRE_INTERNAL (pad, other, FALSE);
371   ret = gst_pad_activate_mode (other, GST_PAD_MODE_PUSH, active);
372   GST_PROXY_PAD_RELEASE_INTERNAL (other);
373
374   return ret;
375 }
376
377 static gboolean
378 gst_ghost_pad_activate_pull_default (GstPad * pad, GstObject * parent,
379     gboolean active)
380 {
381   gboolean ret;
382   GstPad *other;
383
384   GST_LOG_OBJECT (pad, "%sactivate pull on %s:%s", (active ? "" : "de"),
385       GST_DEBUG_PAD_NAME (pad));
386
387   if (GST_PAD_DIRECTION (pad) == GST_PAD_SRC) {
388     /* the ghostpad is SRC and activated in pull mode by its peer, call the
389      * activation function of the internal pad to propagate the activation
390      * upstream */
391     GST_LOG_OBJECT (pad, "pad is src, activate internal");
392     GST_PROXY_PAD_ACQUIRE_INTERNAL (pad, other, FALSE);
393     ret = gst_pad_activate_mode (other, GST_PAD_MODE_PULL, active);
394     GST_PROXY_PAD_RELEASE_INTERNAL (other);
395   } else if (G_LIKELY ((other = gst_pad_get_peer (pad)))) {
396     /* We are SINK and activated by the internal pad, propagate activation
397      * upstream because we hold a ref to the upstream peer */
398     GST_LOG_OBJECT (pad, "activating peer");
399     ret = gst_pad_activate_mode (other, GST_PAD_MODE_PULL, active);
400     gst_object_unref (other);
401   } else if (active) {
402     /* this is failure, we can't activate pull if there is no peer */
403     GST_LOG_OBJECT (pad, "not src and no peer, failing");
404     ret = FALSE;
405   } else {
406     GST_LOG_OBJECT (pad, "deactivating pull, with no peer - allowing");
407     ret = TRUE;
408   }
409
410   return ret;
411 }
412
413 /**
414  * gst_ghost_pad_activate_mode_default:
415  * @pad: the #GstPad to activate or deactivate.
416  * @parent: (allow-none): the parent of @pad or %NULL
417  * @mode: the requested activation mode
418  * @active: whether the pad should be active or not.
419  *
420  * Invoke the default activate mode function of a ghost pad.
421  *
422  * Returns: %TRUE if the operation was successful.
423  */
424 gboolean
425 gst_ghost_pad_activate_mode_default (GstPad * pad, GstObject * parent,
426     GstPadMode mode, gboolean active)
427 {
428   gboolean res;
429
430   g_return_val_if_fail (GST_IS_GHOST_PAD (pad), FALSE);
431
432   switch (mode) {
433     case GST_PAD_MODE_PULL:
434       res = gst_ghost_pad_activate_pull_default (pad, parent, active);
435       break;
436     case GST_PAD_MODE_PUSH:
437       res = gst_ghost_pad_activate_push_default (pad, parent, active);
438       break;
439     default:
440       GST_LOG_OBJECT (pad, "unknown activation mode %d", mode);
441       res = FALSE;
442       break;
443   }
444   return res;
445 }
446
447 static void
448 gst_ghost_pad_class_init (GstGhostPadClass * klass)
449 {
450   GObjectClass *gobject_class = (GObjectClass *) klass;
451
452   gobject_class->dispose = gst_ghost_pad_dispose;
453   gobject_class->constructed = gst_ghost_pad_constructed;
454
455   GST_DEBUG_REGISTER_FUNCPTR (gst_ghost_pad_activate_pull_default);
456   GST_DEBUG_REGISTER_FUNCPTR (gst_ghost_pad_activate_push_default);
457 }
458
459 static void
460 gst_ghost_pad_init (GstGhostPad * pad)
461 {
462   gst_pad_set_activatemode_function (GST_PAD_CAST (pad),
463       gst_ghost_pad_activate_mode_default);
464 }
465
466 static void
467 gst_ghost_pad_dispose (GObject * object)
468 {
469   GstPad *pad;
470   GstPad *internal;
471   GstPad *peer;
472
473   pad = GST_PAD (object);
474
475   GST_DEBUG_OBJECT (pad, "dispose");
476
477   gst_ghost_pad_set_target (GST_GHOST_PAD (pad), NULL);
478
479   /* Unlink here so that gst_pad_dispose doesn't. That would lead to a call to
480    * gst_ghost_pad_unlink_default when the ghost pad is in an inconsistent state */
481   peer = gst_pad_get_peer (pad);
482   if (peer) {
483     if (GST_PAD_IS_SRC (pad))
484       gst_pad_unlink (pad, peer);
485     else
486       gst_pad_unlink (peer, pad);
487
488     gst_object_unref (peer);
489   }
490
491   GST_OBJECT_LOCK (pad);
492   internal = GST_PROXY_PAD_INTERNAL (pad);
493   if (internal) {
494     gst_pad_set_activatemode_function (internal, NULL);
495
496     GST_PROXY_PAD_INTERNAL (pad) = NULL;
497     GST_PROXY_PAD_INTERNAL (internal) = NULL;
498
499     /* disposes of the internal pad, since the ghostpad is the only possible object
500      * that has a refcount on the internal pad. */
501     gst_object_unparent (GST_OBJECT_CAST (internal));
502   }
503
504   GST_OBJECT_UNLOCK (pad);
505
506   G_OBJECT_CLASS (gst_ghost_pad_parent_class)->dispose (object);
507 }
508
509 static void
510 gst_ghost_pad_constructed (GObject * object)
511 {
512   GstGhostPad *gpad = GST_GHOST_PAD (object);
513   GstPadDirection dir, otherdir;
514   GstPadTemplate *templ;
515   GstPad *pad, *internal;
516
517   G_OBJECT_CLASS (gst_ghost_pad_parent_class)->constructed (object);
518
519   g_object_get (gpad, "direction", &dir, "template", &templ, NULL);
520
521   g_return_if_fail (dir != GST_PAD_UNKNOWN);
522
523   pad = GST_PAD (gpad);
524
525   /* Set directional padfunctions for ghostpad */
526   if (dir == GST_PAD_SINK) {
527     gst_pad_set_chain_function (pad, gst_proxy_pad_chain_default);
528     gst_pad_set_chain_list_function (pad, gst_proxy_pad_chain_list_default);
529   } else {
530     gst_pad_set_getrange_function (pad, gst_proxy_pad_getrange_default);
531   }
532
533   /* INTERNAL PAD, it always exists and is child of the ghostpad */
534   otherdir = (dir == GST_PAD_SRC) ? GST_PAD_SINK : GST_PAD_SRC;
535   if (templ) {
536     internal =
537         g_object_new (GST_TYPE_PROXY_PAD, "name", NULL,
538         "direction", otherdir, "template", templ, NULL);
539     /* release ref obtained via g_object_get */
540     gst_object_unref (templ);
541   } else {
542     internal =
543         g_object_new (GST_TYPE_PROXY_PAD, "name", NULL,
544         "direction", otherdir, NULL);
545   }
546   GST_PAD_UNSET_FLUSHING (internal);
547
548   /* Set directional padfunctions for internal pad */
549   if (dir == GST_PAD_SRC) {
550     gst_pad_set_chain_function (internal, gst_proxy_pad_chain_default);
551     gst_pad_set_chain_list_function (internal,
552         gst_proxy_pad_chain_list_default);
553   } else {
554     gst_pad_set_getrange_function (internal, gst_proxy_pad_getrange_default);
555   }
556
557   /* now make the ghostpad a parent of the internal pad */
558   gst_object_set_parent (GST_OBJECT_CAST (internal), GST_OBJECT_CAST (pad));
559
560   /* The ghostpad is the parent of the internal pad and is the only object that
561    * can have a refcount on the internal pad.
562    * At this point, the GstGhostPad has a refcount of 1, and the internal pad has
563    * a refcount of 1.
564    * When the refcount of the GstGhostPad drops to 0, the ghostpad will dispose
565    * its refcount on the internal pad in the dispose method by un-parenting it.
566    * This is why we don't take extra refcounts in the assignments below
567    */
568   GST_PROXY_PAD_INTERNAL (pad) = internal;
569   GST_PROXY_PAD_INTERNAL (internal) = pad;
570
571   /* special activation functions for the internal pad */
572   gst_pad_set_activatemode_function (internal,
573       gst_ghost_pad_internal_activate_mode_default);
574 }
575
576 #ifndef GST_REMOVE_DEPRECATED
577 /**
578  * gst_ghost_pad_construct:
579  * @gpad: the newly allocated ghost pad
580  *
581  * Finish initialization of a newly allocated ghost pad.
582  *
583  * This function is most useful in language bindings and when subclassing
584  * #GstGhostPad; plugin and application developers normally will not call this
585  * function. Call this function directly after a call to g_object_new
586  * (GST_TYPE_GHOST_PAD, "direction", @dir, ..., NULL).
587  *
588  * Deprecated: This function is deprecated since 1.18 and does nothing
589  * anymore.
590  *
591  * Returns: %TRUE if the construction succeeds, %FALSE otherwise.
592  */
593 gboolean
594 gst_ghost_pad_construct (GstGhostPad * gpad)
595 {
596   return TRUE;
597 }
598 #endif
599
600 static GstPad *
601 gst_ghost_pad_new_full (const gchar * name, GstPadDirection dir,
602     GstPadTemplate * templ)
603 {
604   GstGhostPad *ret;
605   g_return_val_if_fail (dir != GST_PAD_UNKNOWN, NULL);
606
607   /* OBJECT CREATION */
608   if (templ) {
609     GType pad_type =
610         GST_PAD_TEMPLATE_GTYPE (templ) ==
611         G_TYPE_NONE ? GST_TYPE_GHOST_PAD : GST_PAD_TEMPLATE_GTYPE (templ);
612
613     g_return_val_if_fail (g_type_is_a (pad_type, GST_TYPE_GHOST_PAD), NULL);
614
615     ret = g_object_new (pad_type, "name", name,
616         "direction", dir, "template", templ, NULL);
617   } else {
618     ret = g_object_new (GST_TYPE_GHOST_PAD, "name", name,
619         "direction", dir, NULL);
620   }
621
622   return GST_PAD_CAST (ret);
623 }
624
625 /**
626  * gst_ghost_pad_new_no_target:
627  * @name: (allow-none): the name of the new pad, or %NULL to assign a default name.
628  * @dir: the direction of the ghostpad
629  *
630  * Create a new ghostpad without a target with the given direction.
631  * A target can be set on the ghostpad later with the
632  * gst_ghost_pad_set_target() function.
633  *
634  * The created ghostpad will not have a padtemplate.
635  *
636  * Returns: (transfer floating) (nullable): a new #GstPad, or %NULL in
637  * case of an error.
638  */
639 GstPad *
640 gst_ghost_pad_new_no_target (const gchar * name, GstPadDirection dir)
641 {
642   GstPad *ret;
643
644   g_return_val_if_fail (dir != GST_PAD_UNKNOWN, NULL);
645
646   GST_LOG ("name:%s, direction:%d", GST_STR_NULL (name), dir);
647
648   ret = gst_ghost_pad_new_full (name, dir, NULL);
649
650   return ret;
651 }
652
653 /**
654  * gst_ghost_pad_new:
655  * @name: (allow-none): the name of the new pad, or %NULL to assign a default name
656  * @target: (transfer none): the pad to ghost.
657  *
658  * Create a new ghostpad with @target as the target. The direction will be taken
659  * from the target pad. @target must be unlinked.
660  *
661  * Will ref the target.
662  *
663  * Returns: (transfer floating) (nullable): a new #GstPad, or %NULL in
664  * case of an error.
665  */
666 GstPad *
667 gst_ghost_pad_new (const gchar * name, GstPad * target)
668 {
669   GstPad *ret;
670
671   g_return_val_if_fail (GST_IS_PAD (target), NULL);
672   g_return_val_if_fail (!gst_pad_is_linked (target), NULL);
673
674   GST_LOG ("name:%s, target:%s:%s", GST_STR_NULL (name),
675       GST_DEBUG_PAD_NAME (target));
676
677   if ((ret = gst_ghost_pad_new_no_target (name, GST_PAD_DIRECTION (target))))
678     if (!gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (ret), target))
679       goto set_target_failed;
680
681   return ret;
682
683   /* ERRORS */
684 set_target_failed:
685   {
686     GST_WARNING_OBJECT (ret, "failed to set target %s:%s",
687         GST_DEBUG_PAD_NAME (target));
688     gst_object_unref (ret);
689     return NULL;
690   }
691 }
692
693 /**
694  * gst_ghost_pad_new_from_template:
695  * @name: (allow-none): the name of the new pad, or %NULL to assign a default name.
696  * @target: (transfer none): the pad to ghost.
697  * @templ: (transfer none): the #GstPadTemplate to use on the ghostpad.
698  *
699  * Create a new ghostpad with @target as the target. The direction will be taken
700  * from the target pad. The template used on the ghostpad will be @template.
701  *
702  * Will ref the target.
703  *
704  * Returns: (transfer floating) (nullable): a new #GstPad, or %NULL in
705  * case of an error.
706  */
707
708 GstPad *
709 gst_ghost_pad_new_from_template (const gchar * name, GstPad * target,
710     GstPadTemplate * templ)
711 {
712   GstPad *ret;
713
714   g_return_val_if_fail (GST_IS_PAD (target), NULL);
715   g_return_val_if_fail (!gst_pad_is_linked (target), NULL);
716   g_return_val_if_fail (templ != NULL, NULL);
717   g_return_val_if_fail (GST_PAD_TEMPLATE_DIRECTION (templ) ==
718       GST_PAD_DIRECTION (target), NULL);
719
720   GST_LOG ("name:%s, target:%s:%s, templ:%p", GST_STR_NULL (name),
721       GST_DEBUG_PAD_NAME (target), templ);
722
723   if ((ret = gst_ghost_pad_new_full (name, GST_PAD_DIRECTION (target), templ)))
724     if (!gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (ret), target))
725       goto set_target_failed;
726
727   return ret;
728
729   /* ERRORS */
730 set_target_failed:
731   {
732     GST_WARNING_OBJECT (ret, "failed to set target %s:%s",
733         GST_DEBUG_PAD_NAME (target));
734     gst_object_unref (ret);
735     return NULL;
736   }
737 }
738
739 /**
740  * gst_ghost_pad_new_no_target_from_template:
741  * @name: (allow-none): the name of the new pad, or %NULL to assign a default name
742  * @templ: (transfer none): the #GstPadTemplate to create the ghostpad from.
743  *
744  * Create a new ghostpad based on @templ, without setting a target. The
745  * direction will be taken from the @templ.
746  *
747  * Returns: (transfer floating) (nullable): a new #GstPad, or %NULL in
748  * case of an error.
749  */
750 GstPad *
751 gst_ghost_pad_new_no_target_from_template (const gchar * name,
752     GstPadTemplate * templ)
753 {
754   GstPad *ret;
755
756   g_return_val_if_fail (templ != NULL, NULL);
757
758   ret =
759       gst_ghost_pad_new_full (name, GST_PAD_TEMPLATE_DIRECTION (templ), templ);
760
761   return ret;
762 }
763
764 /**
765  * gst_ghost_pad_get_target:
766  * @gpad: the #GstGhostPad
767  *
768  * Get the target pad of @gpad. Unref target pad after usage.
769  *
770  * Returns: (transfer full) (nullable): the target #GstPad, can be
771  * %NULL if the ghostpad has no target set. Unref target pad after
772  * usage.
773  */
774 GstPad *
775 gst_ghost_pad_get_target (GstGhostPad * gpad)
776 {
777   GstPad *ret;
778
779   g_return_val_if_fail (GST_IS_GHOST_PAD (gpad), NULL);
780
781   ret = gst_proxy_pad_get_target (GST_PAD_CAST (gpad));
782
783   GST_DEBUG_OBJECT (gpad, "get target %s:%s", GST_DEBUG_PAD_NAME (ret));
784
785   return ret;
786 }
787
788 /**
789  * gst_ghost_pad_set_target:
790  * @gpad: the #GstGhostPad
791  * @newtarget: (transfer none) (allow-none): the new pad target
792  *
793  * Set the new target of the ghostpad @gpad. Any existing target
794  * is unlinked and links to the new target are established. if @newtarget is
795  * %NULL the target will be cleared.
796  *
797  * Returns: %TRUE if the new target could be set. This function
798  *     can return %FALSE when the internal pads could not be linked.
799  */
800 gboolean
801 gst_ghost_pad_set_target (GstGhostPad * gpad, GstPad * newtarget)
802 {
803   GstPad *internal;
804   GstPad *oldtarget;
805   GstPadLinkReturn lret;
806
807   g_return_val_if_fail (GST_IS_GHOST_PAD (gpad), FALSE);
808   g_return_val_if_fail (GST_PAD_CAST (gpad) != newtarget, FALSE);
809
810   GST_OBJECT_LOCK (gpad);
811   internal = GST_PROXY_PAD_INTERNAL (gpad);
812
813   if (newtarget == internal) {
814     GST_OBJECT_UNLOCK (gpad);
815     GST_WARNING_OBJECT (gpad, "Target has already been set to %s:%s",
816         GST_DEBUG_PAD_NAME (newtarget));
817     return TRUE;
818   }
819
820   if (newtarget)
821     GST_DEBUG_OBJECT (gpad, "set target %s:%s", GST_DEBUG_PAD_NAME (newtarget));
822   else
823     GST_DEBUG_OBJECT (gpad, "clearing target");
824
825   /* clear old target */
826   if ((oldtarget = gst_pad_get_peer (internal))) {
827     GST_OBJECT_UNLOCK (gpad);
828
829     /* unlink internal pad */
830     if (GST_PAD_IS_SRC (internal))
831       gst_pad_unlink (internal, oldtarget);
832     else
833       gst_pad_unlink (oldtarget, internal);
834
835     gst_object_unref (oldtarget);
836   } else {
837     GST_OBJECT_UNLOCK (gpad);
838   }
839
840   if (newtarget) {
841     /* and link to internal pad without any checks */
842     GST_DEBUG_OBJECT (gpad, "connecting internal pad to target %"
843         GST_PTR_FORMAT, newtarget);
844
845     if (GST_PAD_IS_SRC (internal))
846       lret =
847           gst_pad_link_full (internal, newtarget, GST_PAD_LINK_CHECK_NOTHING);
848     else
849       lret =
850           gst_pad_link_full (newtarget, internal, GST_PAD_LINK_CHECK_NOTHING);
851
852     if (lret != GST_PAD_LINK_OK)
853       goto link_failed;
854   }
855
856   return TRUE;
857
858   /* ERRORS */
859 link_failed:
860   {
861     GST_WARNING_OBJECT (gpad, "could not link internal and target, reason:%s",
862         gst_pad_link_get_name (lret));
863     return FALSE;
864   }
865 }