Merge branch 'master' into 0.11
[platform/upstream/gstreamer.git] / 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., 59 Temple Place - Suite 330,
22  * Boston, MA 02111-1307, USA.
23  */
24
25 /**
26  * SECTION:gstghostpad
27  * @short_description: Pseudo link pads
28  * @see_also: #GstPad
29  *
30  * GhostPads are useful when organizing pipelines with #GstBin like elements.
31  * The idea here is to create hierarchical element graphs. The bin element
32  * contains a sub-graph. Now one would like to treat the bin-element like any
33  * other #GstElement. This is where GhostPads come into play. A GhostPad acts as
34  * a proxy for another pad. Thus the bin can have sink and source ghost-pads
35  * that are associated with sink and source pads of the child elements.
36  *
37  * If the target pad is known at creation time, gst_ghost_pad_new() is the
38  * function to use to get a ghost-pad. Otherwise one can use gst_ghost_pad_new_no_target()
39  * to create the ghost-pad and use gst_ghost_pad_set_target() to establish the
40  * association later on.
41  *
42  * Note that GhostPads add overhead to the data processing of a pipeline.
43  *
44  * Last reviewed on 2005-11-18 (0.9.5)
45  */
46
47 #include "gst_private.h"
48 #include "gstinfo.h"
49
50 #include "gstghostpad.h"
51 #include "gst.h"
52
53 #define GST_CAT_DEFAULT GST_CAT_PADS
54
55 #define GST_PROXY_PAD_CAST(obj)         ((GstProxyPad *)obj)
56 #define GST_PROXY_PAD_PRIVATE(obj)      (GST_PROXY_PAD_CAST (obj)->priv)
57 #define GST_PROXY_PAD_TARGET(pad)       (GST_PROXY_PAD_PRIVATE (pad)->target)
58 #define GST_PROXY_PAD_INTERNAL(pad)     (GST_PROXY_PAD_PRIVATE (pad)->internal)
59 #define GST_PROXY_PAD_RETARGET(pad)     (GST_PROXY_PAD_PRIVATE (pad)->retarget)
60 #define GST_PROXY_GET_LOCK(pad) (GST_PROXY_PAD_PRIVATE (pad)->proxy_lock)
61 #define GST_PROXY_LOCK(pad)     (g_mutex_lock (GST_PROXY_GET_LOCK (pad)))
62 #define GST_PROXY_UNLOCK(pad)   (g_mutex_unlock (GST_PROXY_GET_LOCK (pad)))
63
64 struct _GstProxyPadPrivate
65 {
66   /* with PROXY_LOCK */
67   GMutex *proxy_lock;
68   GstPad *target;
69   GstPad *internal;
70   gboolean retarget;
71 };
72
73 G_DEFINE_TYPE (GstProxyPad, gst_proxy_pad, GST_TYPE_PAD);
74
75 static GstPad *gst_proxy_pad_get_target (GstPad * pad);
76
77 static void gst_proxy_pad_dispose (GObject * object);
78 static void gst_proxy_pad_finalize (GObject * object);
79
80 /**
81  * gst_proxy_pad_query_type_default:
82  * @pad: a #GstPad.
83  *
84  * Invoke the default query type handler of the proxy pad.
85  *
86  * Returns: (transfer none) (array zero-terminated=1): a zero-terminated array
87  *     of #GstQueryType.
88  *
89  * Since: 0.10.35
90  */
91 const GstQueryType *
92 gst_proxy_pad_query_type_default (GstPad * pad)
93 {
94   GstPad *target;
95   const GstQueryType *res = NULL;
96
97   g_return_val_if_fail (GST_IS_PROXY_PAD (pad), NULL);
98
99   target = gst_proxy_pad_get_target (pad);
100   if (target) {
101     res = gst_pad_get_query_types (target);
102     gst_object_unref (target);
103   }
104   return res;
105 }
106
107 /**
108  * gst_proxy_pad_event_default:
109  * @pad: a #GstPad to push the event to.
110  * @event: (transfer full): the #GstEvent to send to the pad.
111  *
112  * Invoke the default event of the proxy pad.
113  *
114  * Returns: TRUE if the event was handled.
115  *
116  * Since: 0.10.35
117  */
118 gboolean
119 gst_proxy_pad_event_default (GstPad * pad, GstEvent * event)
120 {
121   gboolean res = FALSE;
122   GstPad *internal;
123
124   g_return_val_if_fail (GST_IS_PROXY_PAD (pad), FALSE);
125   g_return_val_if_fail (GST_IS_EVENT (event), FALSE);
126
127   internal =
128       GST_PAD_CAST (gst_proxy_pad_get_internal (GST_PROXY_PAD_CAST (pad)));
129   if (internal) {
130     res = gst_pad_push_event (internal, event);
131     gst_object_unref (internal);
132   }
133
134   return res;
135 }
136
137 /**
138  * gst_proxy_pad_query_default:
139  * @pad: a #GstPad to invoke the default query on.
140  * @query: (transfer none): the #GstQuery to perform.
141  *
142  * Invoke the default query function of the proxy pad.
143  *
144  * Returns: TRUE if the query could be performed.
145  *
146  * Since: 0.10.35
147  */
148 gboolean
149 gst_proxy_pad_query_default (GstPad * pad, GstQuery * query)
150 {
151   gboolean res = FALSE;
152   GstPad *target;
153
154   g_return_val_if_fail (GST_IS_PROXY_PAD (pad), FALSE);
155   g_return_val_if_fail (GST_IS_QUERY (query), FALSE);
156
157   target = gst_proxy_pad_get_target (pad);
158   if (target) {
159     res = gst_pad_query (target, query);
160     gst_object_unref (target);
161   }
162
163   return res;
164 }
165
166 /**
167  * gst_proyx_pad_iterate_internal_links_default:
168  * @pad: the #GstPad to get the internal links of.
169  *
170  * Invoke the default iterate internal links function of the proxy pad.
171  *
172  * Returns: a #GstIterator of #GstPad, or NULL if @pad has no parent. Unref each
173  * returned pad with gst_object_unref().
174  *
175  * Since: 0.10.35
176  */
177 GstIterator *
178 gst_proxy_pad_iterate_internal_links_default (GstPad * pad)
179 {
180   GstIterator *res = NULL;
181   GstPad *internal;
182
183   g_return_val_if_fail (GST_IS_PROXY_PAD (pad), NULL);
184
185   internal =
186       GST_PAD_CAST (gst_proxy_pad_get_internal (GST_PROXY_PAD_CAST (pad)));
187
188   if (internal) {
189     GValue v = { 0, };
190
191     g_value_init (&v, GST_TYPE_PAD);
192     g_value_set_object (&v, internal);
193     res = gst_iterator_new_single (GST_TYPE_PAD, &v);
194     g_value_unset (&v);
195     gst_object_unref (internal);
196   }
197
198   return res;
199 }
200
201 /**
202  * gst_proxy_pad_chain_default:
203  * @pad: a sink #GstPad, returns GST_FLOW_ERROR if not.
204  * @buffer: (transfer full): the #GstBuffer to send, return GST_FLOW_ERROR
205  *     if not.
206  *
207  * Invoke the default chain function of the proxy pad.
208  *
209  * Returns: a #GstFlowReturn from the pad.
210  *
211  * Since: 0.10.35
212  */
213 GstFlowReturn
214 gst_proxy_pad_chain_default (GstPad * pad, GstBuffer * buffer)
215 {
216   GstFlowReturn res;
217   GstPad *internal;
218
219   g_return_val_if_fail (GST_IS_PROXY_PAD (pad), GST_FLOW_ERROR);
220   g_return_val_if_fail (GST_IS_BUFFER (buffer), GST_FLOW_ERROR);
221
222   internal = GST_PROXY_PAD_INTERNAL (pad);
223   res = gst_pad_push (internal, buffer);
224
225   return res;
226 }
227
228 /**
229  * gst_proxy_pad_chain_list_default:
230  * @pad: a sink #GstPad, returns GST_FLOW_ERROR if not.
231  * @list: (transfer full): the #GstBufferList to send, return GST_FLOW_ERROR
232  *     if not.
233  *
234  * Invoke the default chain list function of the proxy pad.
235  *
236  * Returns: a #GstFlowReturn from the pad.
237  *
238  * Since: 0.10.35
239  */
240 GstFlowReturn
241 gst_proxy_pad_chain_list_default (GstPad * pad, GstBufferList * list)
242 {
243   GstFlowReturn res;
244   GstPad *internal;
245
246   g_return_val_if_fail (GST_IS_PROXY_PAD (pad), GST_FLOW_ERROR);
247   g_return_val_if_fail (GST_IS_BUFFER_LIST (list), GST_FLOW_ERROR);
248
249   internal = GST_PROXY_PAD_INTERNAL (pad);
250   res = gst_pad_push_list (internal, list);
251
252   return res;
253 }
254
255 /**
256  * gst_proxy_pad_get_range_default:
257  * @pad: a src #GstPad, returns #GST_FLOW_ERROR if not.
258  * @offset: The start offset of the buffer
259  * @size: The length of the buffer
260  * @buffer: (out callee-allocates): a pointer to hold the #GstBuffer,
261  *     returns #GST_FLOW_ERROR if %NULL.
262  *
263  * Invoke the default getrange function of the proxy pad.
264  *
265  * Returns: a #GstFlowReturn from the pad.
266  *
267  * Since: 0.10.35
268  */
269 GstFlowReturn
270 gst_proxy_pad_getrange_default (GstPad * pad, guint64 offset, guint size,
271     GstBuffer ** buffer)
272 {
273   GstFlowReturn res;
274   GstPad *internal;
275
276   g_return_val_if_fail (GST_IS_PROXY_PAD (pad), GST_FLOW_ERROR);
277   g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR);
278
279   internal = GST_PROXY_PAD_INTERNAL (pad);
280   res = gst_pad_pull_range (internal, offset, size, buffer);
281
282   return res;
283 }
284
285 /**
286  * gst_proxy_pad_getcaps_default:
287  * @pad: a #GstPad to get the capabilities of.
288  * @filter: a #GstCaps filter.
289  *
290  * Invoke the default getcaps function of the proxy pad.
291  *
292  * Returns: (transfer full): the caps of the pad with incremented ref-count
293  *
294  * Since: 0.10.35
295  */
296 GstCaps *
297 gst_proxy_pad_getcaps_default (GstPad * pad, GstCaps * filter)
298 {
299   GstPad *target;
300   GstCaps *res;
301   GstPadTemplate *templ;
302
303   g_return_val_if_fail (GST_IS_PROXY_PAD (pad), NULL);
304
305   templ = GST_PAD_PAD_TEMPLATE (pad);
306   target = gst_proxy_pad_get_target (pad);
307   if (target) {
308     /* if we have a real target, proxy the call */
309     res = gst_pad_get_caps (target, filter);
310
311     GST_DEBUG_OBJECT (pad, "get caps of target %s:%s : %" GST_PTR_FORMAT,
312         GST_DEBUG_PAD_NAME (target), res);
313
314     gst_object_unref (target);
315
316     /* filter against the template */
317     if (templ && res) {
318       GstCaps *filt, *tmp;
319
320       filt = GST_PAD_TEMPLATE_CAPS (templ);
321       if (filt) {
322         tmp = gst_caps_intersect_full (res, filt, GST_CAPS_INTERSECT_FIRST);
323         gst_caps_unref (res);
324         res = tmp;
325         GST_DEBUG_OBJECT (pad,
326             "filtered against template gives %" GST_PTR_FORMAT, res);
327       }
328     }
329   } else {
330     /* else, if we have a template, use its caps. */
331     if (templ) {
332       res = GST_PAD_TEMPLATE_CAPS (templ);
333       GST_DEBUG_OBJECT (pad,
334           "using pad template %p with caps %p %" GST_PTR_FORMAT, templ, res,
335           res);
336       res = gst_caps_ref (res);
337
338       if (filter) {
339         GstCaps *intersection =
340             gst_caps_intersect_full (filter, res, GST_CAPS_INTERSECT_FIRST);
341
342         gst_caps_unref (res);
343         res = intersection;
344       }
345
346       goto done;
347     }
348
349     /* last resort, any caps */
350     GST_DEBUG_OBJECT (pad, "pad has no template, returning ANY");
351     res = gst_caps_new_any ();
352   }
353
354 done:
355   return res;
356 }
357
358 /**
359  * gst_proxy_pad_acceptcaps_default:
360  * @pad: a #GstPad to check
361  * @caps: a #GstCaps to check on the pad
362  *
363  * Invoke the default acceptcaps function of the proxy pad.
364  *
365  * Returns: TRUE if the pad can accept the caps.
366  *
367  * Since: 0.10.35
368  */
369 gboolean
370 gst_proxy_pad_acceptcaps_default (GstPad * pad, GstCaps * caps)
371 {
372   GstPad *target;
373   gboolean res;
374
375   g_return_val_if_fail (GST_IS_PROXY_PAD (pad), FALSE);
376   g_return_val_if_fail (caps == NULL || GST_IS_CAPS (caps), FALSE);
377
378   target = gst_proxy_pad_get_target (pad);
379   if (target) {
380     res = gst_pad_accept_caps (target, caps);
381     gst_object_unref (target);
382   } else {
383     /* We don't have a target, we return TRUE and we assume that any future
384      * target will be able to deal with any configured caps. */
385     res = TRUE;
386   }
387
388   return res;
389 }
390
391 /**
392  * gst_proxy_pad_fixatecaps_default:
393  * @pad: a  #GstPad to fixate
394  * @caps: the  #GstCaps to fixate
395  *
396  * Invoke the default fixatecaps function of the proxy pad.
397  *
398  * Since: 0.10.35
399  */
400 void
401 gst_proxy_pad_fixatecaps_default (GstPad * pad, GstCaps * caps)
402 {
403   GstPad *target;
404
405   g_return_if_fail (GST_IS_PROXY_PAD (pad));
406   g_return_if_fail (GST_IS_CAPS (caps));
407
408   target = gst_proxy_pad_get_target (pad);
409   if (target) {
410     gst_pad_fixate_caps (target, caps);
411     gst_object_unref (target);
412   }
413 }
414
415 /**
416  * gst_proxy_pad_setcaps_default:
417  * @pad: a  #GstPad to set the capabilities of.
418  * @caps: (transfer none): a #GstCaps to set.
419  *
420  * Invoke the default setcaps function of the proxy pad.
421  *
422  * Returns: TRUE if the caps could be set. FALSE if the caps were not fixed
423  * or bad parameters were provided to this function.
424  *
425  * Since: 0.10.35
426  */
427 gboolean
428 gst_proxy_pad_setcaps_default (GstPad * pad, GstCaps * caps)
429 {
430   GstPad *target;
431   gboolean res;
432
433   g_return_val_if_fail (GST_IS_PROXY_PAD (pad), FALSE);
434   g_return_val_if_fail (caps == NULL || GST_IS_CAPS (caps), FALSE);
435
436   target = gst_proxy_pad_get_target (pad);
437   if (target) {
438 #if 0
439     /* FIXME, not needed, the caps event will propagate over the pads
440      * correctly */
441     res = gst_pad_set_caps (target, caps);
442 #endif
443     res = TRUE;
444     gst_object_unref (target);
445   } else {
446     /* We don't have any target, but we shouldn't return FALSE since this
447      * would stop the actual push of a buffer (which might trigger a pad block
448      * or probe, or properly return GST_FLOW_NOT_LINKED.
449      */
450     res = TRUE;
451   }
452   return res;
453 }
454
455 static gboolean
456 gst_proxy_pad_set_target_unlocked (GstPad * pad, GstPad * target)
457 {
458   GstPad *oldtarget;
459
460   if (target) {
461     GST_LOG_OBJECT (pad, "setting target %s:%s", GST_DEBUG_PAD_NAME (target));
462
463     if (G_UNLIKELY (GST_PAD_DIRECTION (pad) != GST_PAD_DIRECTION (target)))
464       goto wrong_direction;
465   } else
466     GST_LOG_OBJECT (pad, "clearing target");
467
468   /* clear old target */
469   if ((oldtarget = GST_PROXY_PAD_TARGET (pad)))
470     gst_object_unref (oldtarget);
471
472   /* set and ref new target if any */
473   if (target)
474     GST_PROXY_PAD_TARGET (pad) = gst_object_ref (target);
475   else
476     GST_PROXY_PAD_TARGET (pad) = NULL;
477
478   return TRUE;
479
480   /* ERRORS */
481 wrong_direction:
482   {
483     GST_ERROR_OBJECT (pad,
484         "target pad doesn't have the same direction as ourself");
485     return FALSE;
486   }
487 }
488
489 static gboolean
490 gst_proxy_pad_set_target (GstPad * pad, GstPad * target)
491 {
492   gboolean result;
493
494   GST_PROXY_LOCK (pad);
495   result = gst_proxy_pad_set_target_unlocked (pad, target);
496   GST_PROXY_UNLOCK (pad);
497
498   return result;
499 }
500
501 static GstPad *
502 gst_proxy_pad_get_target (GstPad * pad)
503 {
504   GstPad *target;
505
506   GST_PROXY_LOCK (pad);
507   target = GST_PROXY_PAD_TARGET (pad);
508   if (target)
509     gst_object_ref (target);
510   GST_PROXY_UNLOCK (pad);
511
512   return target;
513 }
514
515 /**
516  * gst_proxy_pad_get_internal:
517  * @pad: the #GstProxyPad
518  *
519  * Get the internal pad of @pad. Unref target pad after usage.
520  *
521  * The internal pad of a #GstGhostPad is the internally used
522  * pad of opposite direction, which is used to link to the target.
523  *
524  * Returns: (transfer full): the target #GstProxyPad, can be NULL.
525  * Unref target pad after usage.
526  *
527  * Since: 0.10.35
528  */
529 GstProxyPad *
530 gst_proxy_pad_get_internal (GstProxyPad * pad)
531 {
532   GstPad *internal;
533
534   g_return_val_if_fail (GST_IS_PROXY_PAD (pad), NULL);
535
536   GST_PROXY_LOCK (pad);
537   internal = GST_PROXY_PAD_INTERNAL (pad);
538   if (internal)
539     gst_object_ref (internal);
540   GST_PROXY_UNLOCK (pad);
541
542   return GST_PROXY_PAD_CAST (internal);
543 }
544
545 /**
546  * gst_proxy_pad_unlink_default:
547  * @pad: a #GstPad to unlink
548  *
549  * Invoke the default unlink function of the proxy pad.
550  *
551  * Since: 0.10.35
552  */
553 void
554 gst_proxy_pad_unlink_default (GstPad * pad)
555 {
556   GstPad *internal;
557
558   /* don't do anything if this unlink resulted from retargeting the pad
559    * controlled by the ghostpad. We only want to invalidate the target pad when
560    * the element suddently unlinked with our internal pad. */
561   if (GST_PROXY_PAD_RETARGET (pad))
562     return;
563
564   internal = GST_PROXY_PAD_INTERNAL (pad);
565
566   GST_DEBUG_OBJECT (pad, "pad is unlinked");
567
568   gst_proxy_pad_set_target (internal, NULL);
569 }
570
571 static void
572 gst_proxy_pad_class_init (GstProxyPadClass * klass)
573 {
574   GObjectClass *gobject_class = (GObjectClass *) klass;
575
576   g_type_class_add_private (klass, sizeof (GstProxyPadPrivate));
577
578   gobject_class->dispose = gst_proxy_pad_dispose;
579   gobject_class->finalize = gst_proxy_pad_finalize;
580
581   /* Register common function pointer descriptions */
582   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_query_type_default);
583   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_event_default);
584   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_query_default);
585   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_iterate_internal_links_default);
586   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_getcaps_default);
587   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_acceptcaps_default);
588   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_fixatecaps_default);
589   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_setcaps_default);
590   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_unlink_default);
591   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_chain_default);
592   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_chain_list_default);
593   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_getrange_default);
594 }
595
596 static void
597 gst_proxy_pad_dispose (GObject * object)
598 {
599   GstPad *pad = GST_PAD (object);
600   GstPad **target_p;
601
602   GST_PROXY_LOCK (pad);
603   /* remove and unref the target */
604   target_p = &GST_PROXY_PAD_TARGET (pad);
605   gst_object_replace ((GstObject **) target_p, NULL);
606   /* The internal is only cleared by GstGhostPad::dispose, since it is the 
607    * parent of non-ghost GstProxyPad and owns the refcount on the internal.
608    */
609   GST_PROXY_UNLOCK (pad);
610
611   G_OBJECT_CLASS (gst_proxy_pad_parent_class)->dispose (object);
612 }
613
614 static void
615 gst_proxy_pad_finalize (GObject * object)
616 {
617   GstProxyPad *pad = GST_PROXY_PAD (object);
618
619   g_mutex_free (GST_PROXY_GET_LOCK (pad));
620   GST_PROXY_GET_LOCK (pad) = NULL;
621
622   G_OBJECT_CLASS (gst_proxy_pad_parent_class)->finalize (object);
623 }
624
625 static void
626 gst_proxy_pad_init (GstProxyPad * ppad)
627 {
628   GstPad *pad = (GstPad *) ppad;
629
630   GST_PROXY_PAD_PRIVATE (ppad) = G_TYPE_INSTANCE_GET_PRIVATE (ppad,
631       GST_TYPE_PROXY_PAD, GstProxyPadPrivate);
632   GST_PROXY_GET_LOCK (pad) = g_mutex_new ();
633
634   gst_pad_set_query_type_function (pad, gst_proxy_pad_query_type_default);
635   gst_pad_set_event_function (pad, gst_proxy_pad_event_default);
636   gst_pad_set_query_function (pad, gst_proxy_pad_query_default);
637   gst_pad_set_iterate_internal_links_function (pad,
638       gst_proxy_pad_iterate_internal_links_default);
639
640   gst_pad_set_getcaps_function (pad, gst_proxy_pad_getcaps_default);
641   gst_pad_set_acceptcaps_function (pad, gst_proxy_pad_acceptcaps_default);
642   gst_pad_set_fixatecaps_function (pad, gst_proxy_pad_fixatecaps_default);
643   gst_pad_set_setcaps_function (pad, gst_proxy_pad_setcaps_default);
644   gst_pad_set_unlink_function (pad, gst_proxy_pad_unlink_default);
645 }
646
647
648 /***********************************************************************
649  * Ghost pads, implemented as a pair of proxy pads (sort of)
650  */
651
652
653 #define GST_GHOST_PAD_PRIVATE(obj)      (GST_GHOST_PAD_CAST (obj)->priv)
654
655 struct _GstGhostPadPrivate
656 {
657   /* with PROXY_LOCK */
658   gboolean constructed;
659 };
660
661 G_DEFINE_TYPE (GstGhostPad, gst_ghost_pad, GST_TYPE_PROXY_PAD);
662
663 static void gst_ghost_pad_dispose (GObject * object);
664
665 /**
666  * gst_ghost_pad_internal_activate_push_default:
667  * @pad: the #GstPad to activate or deactivate.
668  * @active: whether the pad should be active or not.
669  *
670  * Invoke the default activate push function of a proxy pad that is
671  * owned by a ghost pad.
672  *
673  * Returns: %TRUE if the operation was successful.
674  *
675  * Since: 0.10.35
676  */
677 gboolean
678 gst_ghost_pad_internal_activate_push_default (GstPad * pad, gboolean active)
679 {
680   gboolean ret;
681   GstPad *other;
682
683   g_return_val_if_fail (GST_IS_PROXY_PAD (pad), FALSE);
684
685   GST_LOG_OBJECT (pad, "%sactivate push on %s:%s, we're ok",
686       (active ? "" : "de"), GST_DEBUG_PAD_NAME (pad));
687
688   /* in both cases (SRC and SINK) we activate just the internal pad. The targets
689    * will be activated later (or already in case of a ghost sinkpad). */
690   other = GST_PROXY_PAD_INTERNAL (pad);
691   ret = gst_pad_activate_push (other, active);
692
693   return ret;
694 }
695
696 /**
697  * gst_ghost_pad_internal_activate_pull_default:
698  * @pad: the #GstPad to activate or deactivate.
699  * @active: whether the pad should be active or not.
700  *
701  * Invoke the default activate pull function of a proxy pad that is
702  * owned by a ghost pad.
703  *
704  * Returns: %TRUE if the operation was successful.
705  *
706  * Since: 0.10.35
707  */
708 gboolean
709 gst_ghost_pad_internal_activate_pull_default (GstPad * pad, gboolean active)
710 {
711   gboolean ret;
712   GstPad *other;
713
714   g_return_val_if_fail (GST_IS_PROXY_PAD (pad), FALSE);
715
716   GST_LOG_OBJECT (pad, "%sactivate pull on %s:%s", (active ? "" : "de"),
717       GST_DEBUG_PAD_NAME (pad));
718
719   if (GST_PAD_DIRECTION (pad) == GST_PAD_SRC) {
720     /* we are activated in pull mode by our peer element, which is a sinkpad
721      * that wants to operate in pull mode. This activation has to propagate
722      * upstream throught the pipeline. We call the internal activation function,
723      * which will trigger gst_ghost_pad_activate_pull_default, which propagates even
724      * further upstream */
725     GST_LOG_OBJECT (pad, "pad is src, activate internal");
726     other = GST_PROXY_PAD_INTERNAL (pad);
727     ret = gst_pad_activate_pull (other, active);
728   } else if (G_LIKELY ((other = gst_pad_get_peer (pad)))) {
729     /* We are SINK, the ghostpad is SRC, we propagate the activation upstream
730      * since we hold a pointer to the upstream peer. */
731     GST_LOG_OBJECT (pad, "activating peer");
732     ret = gst_pad_activate_pull (other, active);
733     gst_object_unref (other);
734   } else {
735     /* this is failure, we can't activate pull if there is no peer */
736     GST_LOG_OBJECT (pad, "not src and no peer, failing");
737     ret = FALSE;
738   }
739
740   return ret;
741 }
742
743 /**
744  * gst_ghost_pad_activate_push_default:
745  * @pad: the #GstPad to activate or deactivate.
746  * @active: whether the pad should be active or not.
747  *
748  * Invoke the default activate push function of a ghost pad.
749  *
750  * Returns: %TRUE if the operation was successful.
751  *
752  * Since: 0.10.35
753  */
754 gboolean
755 gst_ghost_pad_activate_push_default (GstPad * pad, gboolean active)
756 {
757   gboolean ret;
758   GstPad *other;
759
760   g_return_val_if_fail (GST_IS_GHOST_PAD (pad), FALSE);
761
762   GST_LOG_OBJECT (pad, "%sactivate push on %s:%s, proxy internal",
763       (active ? "" : "de"), GST_DEBUG_PAD_NAME (pad));
764
765   /* just activate the internal pad */
766   other = GST_PROXY_PAD_INTERNAL (pad);
767   ret = gst_pad_activate_push (other, active);
768
769   return ret;
770 }
771
772 /**
773  * gst_ghost_pad_activate_pull_default:
774  * @pad: the #GstPad to activate or deactivate.
775  * @active: whether the pad should be active or not.
776  *
777  * Invoke the default activate pull function of a ghost pad.
778  *
779  * Returns: %TRUE if the operation was successful.
780  *
781  * Since: 0.10.35
782  */
783 gboolean
784 gst_ghost_pad_activate_pull_default (GstPad * pad, gboolean active)
785 {
786   gboolean ret;
787   GstPad *other;
788
789   g_return_val_if_fail (GST_IS_GHOST_PAD (pad), FALSE);
790
791   GST_LOG_OBJECT (pad, "%sactivate pull on %s:%s", (active ? "" : "de"),
792       GST_DEBUG_PAD_NAME (pad));
793
794   if (GST_PAD_DIRECTION (pad) == GST_PAD_SRC) {
795     /* the ghostpad is SRC and activated in pull mode by its peer, call the
796      * activation function of the internal pad to propagate the activation
797      * upstream */
798     GST_LOG_OBJECT (pad, "pad is src, activate internal");
799     other = GST_PROXY_PAD_INTERNAL (pad);
800     ret = gst_pad_activate_pull (other, active);
801   } else if (G_LIKELY ((other = gst_pad_get_peer (pad)))) {
802     /* We are SINK and activated by the internal pad, propagate activation
803      * upstream because we hold a ref to the upstream peer */
804     GST_LOG_OBJECT (pad, "activating peer");
805     ret = gst_pad_activate_pull (other, active);
806     gst_object_unref (other);
807   } else {
808     /* no peer, we fail */
809     GST_LOG_OBJECT (pad, "pad not src and no peer, failing");
810     ret = FALSE;
811   }
812
813   return ret;
814 }
815
816 /**
817  * gst_ghost_pad_link_default:
818  * @pad: the #GstPad to link.
819  * @peer: the #GstPad peer
820  *
821  * Invoke the default link function of a ghost pad.
822  *
823  * Returns: #GstPadLinkReturn of the operation
824  *
825  * Since: 0.10.35
826  */
827 GstPadLinkReturn
828 gst_ghost_pad_link_default (GstPad * pad, GstPad * peer)
829 {
830   GstPadLinkReturn ret;
831   GstPad *internal;
832
833   g_return_val_if_fail (GST_IS_GHOST_PAD (pad), GST_PAD_LINK_REFUSED);
834   g_return_val_if_fail (GST_IS_PAD (peer), GST_PAD_LINK_REFUSED);
835
836   GST_DEBUG_OBJECT (pad, "linking ghostpad");
837
838   internal = GST_PROXY_PAD_INTERNAL (pad);
839   if (!gst_proxy_pad_set_target (internal, peer))
840     goto target_failed;
841
842   ret = GST_PAD_LINK_OK;
843   /* if we are a source pad, we should call the peer link function
844    * if the peer has one, see design docs. */
845   if (GST_PAD_IS_SRC (pad)) {
846     if (GST_PAD_LINKFUNC (peer)) {
847       ret = GST_PAD_LINKFUNC (peer) (peer, pad);
848       if (ret != GST_PAD_LINK_OK)
849         goto link_failed;
850     }
851   }
852   return ret;
853
854   /* ERRORS */
855 target_failed:
856   {
857     GST_DEBUG_OBJECT (pad, "setting target failed");
858     return GST_PAD_LINK_REFUSED;
859   }
860 link_failed:
861   {
862     GST_DEBUG_OBJECT (pad, "linking failed");
863     /* clear target again */
864     gst_proxy_pad_set_target (internal, NULL);
865     return ret;
866   }
867 }
868
869 /**
870  * gst_ghost_pad_unlink_default:
871  * @pad: the #GstPad to link.
872  *
873  * Invoke the default unlink function of a ghost pad.
874  *
875  * Since: 0.10.35
876  */
877 void
878 gst_ghost_pad_unlink_default (GstPad * pad)
879 {
880   GstPad *internal;
881
882   g_return_if_fail (GST_IS_GHOST_PAD (pad));
883
884   internal = GST_PROXY_PAD_INTERNAL (pad);
885
886   GST_DEBUG_OBJECT (pad, "unlinking ghostpad");
887
888   /* The target of the internal pad is no longer valid */
889   gst_proxy_pad_set_target (internal, NULL);
890 }
891
892 /**
893  * gst_ghost_pad_setcaps_default:
894  * @pad: the #GstPad to link.
895  * @caps: (transfer none): the #GstCaps to set
896  *
897  * Invoke the default setcaps function of a ghost pad.
898  *
899  * Returns: %TRUE if the operation was successful
900  *
901  * Since: 0.10.35
902  */
903 gboolean
904 gst_ghost_pad_setcaps_default (GstPad * pad, GstCaps * caps)
905 {
906   g_return_val_if_fail (GST_IS_GHOST_PAD (pad), FALSE);
907   g_return_val_if_fail (caps == NULL || GST_IS_CAPS (caps), FALSE);
908
909   if (GST_PAD_DIRECTION (pad) == GST_PAD_SRC)
910     return TRUE;
911
912   return gst_proxy_pad_setcaps_default (pad, caps);
913 }
914
915 static void
916 gst_ghost_pad_class_init (GstGhostPadClass * klass)
917 {
918   GObjectClass *gobject_class = (GObjectClass *) klass;
919
920   g_type_class_add_private (klass, sizeof (GstGhostPadPrivate));
921
922   gobject_class->dispose = gst_ghost_pad_dispose;
923
924   GST_DEBUG_REGISTER_FUNCPTR (gst_ghost_pad_setcaps_default);
925   GST_DEBUG_REGISTER_FUNCPTR (gst_ghost_pad_activate_pull_default);
926   GST_DEBUG_REGISTER_FUNCPTR (gst_ghost_pad_activate_push_default);
927   GST_DEBUG_REGISTER_FUNCPTR (gst_ghost_pad_link_default);
928 }
929
930 static void
931 gst_ghost_pad_init (GstGhostPad * pad)
932 {
933   GST_GHOST_PAD_PRIVATE (pad) = G_TYPE_INSTANCE_GET_PRIVATE (pad,
934       GST_TYPE_GHOST_PAD, GstGhostPadPrivate);
935
936   gst_pad_set_setcaps_function (GST_PAD_CAST (pad),
937       gst_ghost_pad_setcaps_default);
938   gst_pad_set_activatepull_function (GST_PAD_CAST (pad),
939       gst_ghost_pad_activate_pull_default);
940   gst_pad_set_activatepush_function (GST_PAD_CAST (pad),
941       gst_ghost_pad_activate_push_default);
942 }
943
944 static void
945 gst_ghost_pad_dispose (GObject * object)
946 {
947   GstPad *pad;
948   GstPad *internal;
949   GstPad *peer;
950
951   pad = GST_PAD (object);
952
953   GST_DEBUG_OBJECT (pad, "dispose");
954
955   gst_ghost_pad_set_target (GST_GHOST_PAD (pad), NULL);
956
957   /* Unlink here so that gst_pad_dispose doesn't. That would lead to a call to
958    * gst_ghost_pad_unlink_default when the ghost pad is in an inconsistent state */
959   peer = gst_pad_get_peer (pad);
960   if (peer) {
961     if (GST_PAD_IS_SRC (pad))
962       gst_pad_unlink (pad, peer);
963     else
964       gst_pad_unlink (peer, pad);
965
966     gst_object_unref (peer);
967   }
968
969   GST_PROXY_LOCK (pad);
970   internal = GST_PROXY_PAD_INTERNAL (pad);
971
972   gst_pad_set_activatepull_function (internal, NULL);
973   gst_pad_set_activatepush_function (internal, NULL);
974
975   /* disposes of the internal pad, since the ghostpad is the only possible object
976    * that has a refcount on the internal pad. */
977   gst_object_unparent (GST_OBJECT_CAST (internal));
978   GST_PROXY_PAD_INTERNAL (pad) = NULL;
979
980   GST_PROXY_UNLOCK (pad);
981
982   G_OBJECT_CLASS (gst_ghost_pad_parent_class)->dispose (object);
983 }
984
985 /**
986  * gst_ghost_pad_construct:
987  * @gpad: the newly allocated ghost pad
988  *
989  * Finish initialization of a newly allocated ghost pad.
990  *
991  * This function is most useful in language bindings and when subclassing
992  * #GstGhostPad; plugin and application developers normally will not call this
993  * function. Call this function directly after a call to g_object_new
994  * (GST_TYPE_GHOST_PAD, "direction", @dir, ..., NULL).
995  *
996  * Returns: %TRUE if the construction succeeds, %FALSE otherwise.
997  *
998  * Since: 0.10.22
999  */
1000 gboolean
1001 gst_ghost_pad_construct (GstGhostPad * gpad)
1002 {
1003   GstPadDirection dir, otherdir;
1004   GstPadTemplate *templ;
1005   GstPad *pad, *internal;
1006
1007   g_return_val_if_fail (GST_IS_GHOST_PAD (gpad), FALSE);
1008   g_return_val_if_fail (GST_GHOST_PAD_PRIVATE (gpad)->constructed == FALSE,
1009       FALSE);
1010
1011   g_object_get (gpad, "direction", &dir, "template", &templ, NULL);
1012
1013   g_return_val_if_fail (dir != GST_PAD_UNKNOWN, FALSE);
1014
1015   pad = GST_PAD (gpad);
1016
1017   /* Set directional padfunctions for ghostpad */
1018   if (dir == GST_PAD_SINK) {
1019     gst_pad_set_chain_function (pad, gst_proxy_pad_chain_default);
1020     gst_pad_set_chain_list_function (pad, gst_proxy_pad_chain_list_default);
1021   } else {
1022     gst_pad_set_getrange_function (pad, gst_proxy_pad_getrange_default);
1023   }
1024
1025   /* link/unlink functions */
1026   gst_pad_set_link_function (pad, gst_ghost_pad_link_default);
1027   gst_pad_set_unlink_function (pad, gst_ghost_pad_unlink_default);
1028
1029   /* INTERNAL PAD, it always exists and is child of the ghostpad */
1030   otherdir = (dir == GST_PAD_SRC) ? GST_PAD_SINK : GST_PAD_SRC;
1031   if (templ) {
1032     internal =
1033         g_object_new (GST_TYPE_PROXY_PAD, "name", NULL,
1034         "direction", otherdir, "template", templ, NULL);
1035     /* release ref obtained via g_object_get */
1036     gst_object_unref (templ);
1037   } else {
1038     internal =
1039         g_object_new (GST_TYPE_PROXY_PAD, "name", NULL,
1040         "direction", otherdir, NULL);
1041   }
1042   GST_PAD_UNSET_FLUSHING (internal);
1043
1044   /* Set directional padfunctions for internal pad */
1045   if (dir == GST_PAD_SRC) {
1046     gst_pad_set_chain_function (internal, gst_proxy_pad_chain_default);
1047     gst_pad_set_chain_list_function (internal,
1048         gst_proxy_pad_chain_list_default);
1049   } else {
1050     gst_pad_set_getrange_function (internal, gst_proxy_pad_getrange_default);
1051   }
1052
1053   GST_PROXY_LOCK (pad);
1054
1055   /* now make the ghostpad a parent of the internal pad */
1056   if (!gst_object_set_parent (GST_OBJECT_CAST (internal),
1057           GST_OBJECT_CAST (pad)))
1058     goto parent_failed;
1059
1060   /* The ghostpad is the parent of the internal pad and is the only object that
1061    * can have a refcount on the internal pad.
1062    * At this point, the GstGhostPad has a refcount of 1, and the internal pad has
1063    * a refcount of 1.
1064    * When the refcount of the GstGhostPad drops to 0, the ghostpad will dispose
1065    * its refcount on the internal pad in the dispose method by un-parenting it.
1066    * This is why we don't take extra refcounts in the assignments below
1067    */
1068   GST_PROXY_PAD_INTERNAL (pad) = internal;
1069   GST_PROXY_PAD_INTERNAL (internal) = pad;
1070
1071   /* special activation functions for the internal pad */
1072   gst_pad_set_activatepull_function (internal,
1073       gst_ghost_pad_internal_activate_pull_default);
1074   gst_pad_set_activatepush_function (internal,
1075       gst_ghost_pad_internal_activate_push_default);
1076
1077   GST_PROXY_UNLOCK (pad);
1078
1079   GST_GHOST_PAD_PRIVATE (gpad)->constructed = TRUE;
1080   return TRUE;
1081
1082   /* ERRORS */
1083 parent_failed:
1084   {
1085     GST_WARNING_OBJECT (gpad, "Could not set internal pad %s:%s",
1086         GST_DEBUG_PAD_NAME (internal));
1087     g_critical ("Could not set internal pad %s:%s",
1088         GST_DEBUG_PAD_NAME (internal));
1089     GST_PROXY_UNLOCK (pad);
1090     gst_object_unref (internal);
1091     return FALSE;
1092   }
1093 }
1094
1095 static GstPad *
1096 gst_ghost_pad_new_full (const gchar * name, GstPadDirection dir,
1097     GstPadTemplate * templ)
1098 {
1099   GstGhostPad *ret;
1100
1101   g_return_val_if_fail (dir != GST_PAD_UNKNOWN, NULL);
1102
1103   /* OBJECT CREATION */
1104   if (templ) {
1105     ret = g_object_new (GST_TYPE_GHOST_PAD, "name", name,
1106         "direction", dir, "template", templ, NULL);
1107   } else {
1108     ret = g_object_new (GST_TYPE_GHOST_PAD, "name", name,
1109         "direction", dir, NULL);
1110   }
1111
1112   if (!gst_ghost_pad_construct (ret))
1113     goto construct_failed;
1114
1115   return GST_PAD_CAST (ret);
1116
1117 construct_failed:
1118   /* already logged */
1119   gst_object_unref (ret);
1120   return NULL;
1121 }
1122
1123 /**
1124  * gst_ghost_pad_new_no_target:
1125  * @name: (allow-none): the name of the new pad, or NULL to assign a default name.
1126  * @dir: the direction of the ghostpad
1127  *
1128  * Create a new ghostpad without a target with the given direction.
1129  * A target can be set on the ghostpad later with the
1130  * gst_ghost_pad_set_target() function.
1131  *
1132  * The created ghostpad will not have a padtemplate.
1133  *
1134  * Returns: (transfer full): a new #GstPad, or NULL in case of an error.
1135  */
1136 GstPad *
1137 gst_ghost_pad_new_no_target (const gchar * name, GstPadDirection dir)
1138 {
1139   GstPad *ret;
1140
1141   g_return_val_if_fail (dir != GST_PAD_UNKNOWN, NULL);
1142
1143   GST_LOG ("name:%s, direction:%d", GST_STR_NULL (name), dir);
1144
1145   ret = gst_ghost_pad_new_full (name, dir, NULL);
1146
1147   return ret;
1148 }
1149
1150 /**
1151  * gst_ghost_pad_new:
1152  * @name: (allow-none): the name of the new pad, or NULL to assign a default name
1153  * @target: (transfer none): the pad to ghost.
1154  *
1155  * Create a new ghostpad with @target as the target. The direction will be taken
1156  * from the target pad. @target must be unlinked.
1157  *
1158  * Will ref the target.
1159  *
1160  * Returns: (transfer full): a new #GstPad, or NULL in case of an error.
1161  */
1162 GstPad *
1163 gst_ghost_pad_new (const gchar * name, GstPad * target)
1164 {
1165   GstPad *ret;
1166
1167   g_return_val_if_fail (GST_IS_PAD (target), NULL);
1168   g_return_val_if_fail (!gst_pad_is_linked (target), NULL);
1169
1170   GST_LOG ("name:%s, target:%s:%s", GST_STR_NULL (name),
1171       GST_DEBUG_PAD_NAME (target));
1172
1173   if ((ret = gst_ghost_pad_new_no_target (name, GST_PAD_DIRECTION (target))))
1174     if (!gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (ret), target))
1175       goto set_target_failed;
1176
1177   return ret;
1178
1179   /* ERRORS */
1180 set_target_failed:
1181   {
1182     GST_WARNING_OBJECT (ret, "failed to set target %s:%s",
1183         GST_DEBUG_PAD_NAME (target));
1184     gst_object_unref (ret);
1185     return NULL;
1186   }
1187 }
1188
1189 /**
1190  * gst_ghost_pad_new_from_template:
1191  * @name: (allow-none): the name of the new pad, or NULL to assign a default name.
1192  * @target: (transfer none): the pad to ghost.
1193  * @templ: (transfer none): the #GstPadTemplate to use on the ghostpad.
1194  *
1195  * Create a new ghostpad with @target as the target. The direction will be taken
1196  * from the target pad. The template used on the ghostpad will be @template.
1197  *
1198  * Will ref the target.
1199  *
1200  * Returns: (transfer full): a new #GstPad, or NULL in case of an error.
1201  *
1202  * Since: 0.10.10
1203  */
1204
1205 GstPad *
1206 gst_ghost_pad_new_from_template (const gchar * name, GstPad * target,
1207     GstPadTemplate * templ)
1208 {
1209   GstPad *ret;
1210
1211   g_return_val_if_fail (GST_IS_PAD (target), NULL);
1212   g_return_val_if_fail (!gst_pad_is_linked (target), NULL);
1213   g_return_val_if_fail (templ != NULL, NULL);
1214   g_return_val_if_fail (GST_PAD_TEMPLATE_DIRECTION (templ) ==
1215       GST_PAD_DIRECTION (target), NULL);
1216
1217   GST_LOG ("name:%s, target:%s:%s, templ:%p", GST_STR_NULL (name),
1218       GST_DEBUG_PAD_NAME (target), templ);
1219
1220   if ((ret = gst_ghost_pad_new_full (name, GST_PAD_DIRECTION (target), templ)))
1221     if (!gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (ret), target))
1222       goto set_target_failed;
1223
1224   return ret;
1225
1226   /* ERRORS */
1227 set_target_failed:
1228   {
1229     GST_WARNING_OBJECT (ret, "failed to set target %s:%s",
1230         GST_DEBUG_PAD_NAME (target));
1231     gst_object_unref (ret);
1232     return NULL;
1233   }
1234 }
1235
1236 /**
1237  * gst_ghost_pad_new_no_target_from_template:
1238  * @name: (allow-none): the name of the new pad, or NULL to assign a default name
1239  * @templ: (transfer none): the #GstPadTemplate to create the ghostpad from.
1240  *
1241  * Create a new ghostpad based on @templ, without setting a target. The
1242  * direction will be taken from the @templ.
1243  *
1244  * Returns: (transfer full): a new #GstPad, or NULL in case of an error.
1245  *
1246  * Since: 0.10.10
1247  */
1248 GstPad *
1249 gst_ghost_pad_new_no_target_from_template (const gchar * name,
1250     GstPadTemplate * templ)
1251 {
1252   GstPad *ret;
1253
1254   g_return_val_if_fail (templ != NULL, NULL);
1255
1256   ret =
1257       gst_ghost_pad_new_full (name, GST_PAD_TEMPLATE_DIRECTION (templ), templ);
1258
1259   return ret;
1260 }
1261
1262 /**
1263  * gst_ghost_pad_get_target:
1264  * @gpad: the #GstGhostPad
1265  *
1266  * Get the target pad of @gpad. Unref target pad after usage.
1267  *
1268  * Returns: (transfer full): the target #GstPad, can be NULL if the ghostpad
1269  * has no target set. Unref target pad after usage.
1270  */
1271 GstPad *
1272 gst_ghost_pad_get_target (GstGhostPad * gpad)
1273 {
1274   GstPad *ret;
1275
1276   g_return_val_if_fail (GST_IS_GHOST_PAD (gpad), NULL);
1277
1278   ret = gst_proxy_pad_get_target (GST_PAD_CAST (gpad));
1279
1280   GST_DEBUG_OBJECT (gpad, "get target %s:%s", GST_DEBUG_PAD_NAME (ret));
1281
1282   return ret;
1283 }
1284
1285 /**
1286  * gst_ghost_pad_set_target:
1287  * @gpad: the #GstGhostPad
1288  * @newtarget: (transfer none) (allow-none): the new pad target
1289  *
1290  * Set the new target of the ghostpad @gpad. Any existing target
1291  * is unlinked and links to the new target are established. if @newtarget is
1292  * NULL the target will be cleared.
1293  *
1294  * Returns: (transfer full): TRUE if the new target could be set. This function
1295  *     can return FALSE when the internal pads could not be linked.
1296  */
1297 gboolean
1298 gst_ghost_pad_set_target (GstGhostPad * gpad, GstPad * newtarget)
1299 {
1300   GstPad *internal;
1301   GstPad *oldtarget;
1302   gboolean result;
1303   GstPadLinkReturn lret;
1304
1305   g_return_val_if_fail (GST_IS_GHOST_PAD (gpad), FALSE);
1306   g_return_val_if_fail (GST_PAD_CAST (gpad) != newtarget, FALSE);
1307   g_return_val_if_fail (newtarget != GST_PROXY_PAD_INTERNAL (gpad), FALSE);
1308
1309   /* no need for locking, the internal pad's lifecycle is directly linked to the
1310    * ghostpad's */
1311   internal = GST_PROXY_PAD_INTERNAL (gpad);
1312
1313   if (newtarget)
1314     GST_DEBUG_OBJECT (gpad, "set target %s:%s", GST_DEBUG_PAD_NAME (newtarget));
1315   else
1316     GST_DEBUG_OBJECT (gpad, "clearing target");
1317
1318   /* clear old target */
1319   GST_PROXY_LOCK (gpad);
1320   if ((oldtarget = GST_PROXY_PAD_TARGET (gpad))) {
1321
1322     GST_PROXY_PAD_RETARGET (internal) = TRUE;
1323
1324     /* unlink internal pad */
1325     if (GST_PAD_IS_SRC (internal))
1326       gst_pad_unlink (internal, oldtarget);
1327     else
1328       gst_pad_unlink (oldtarget, internal);
1329
1330     GST_PROXY_PAD_RETARGET (internal) = FALSE;
1331   }
1332
1333   result = gst_proxy_pad_set_target_unlocked (GST_PAD_CAST (gpad), newtarget);
1334   GST_PROXY_UNLOCK (gpad);
1335
1336   if (result && newtarget) {
1337     /* and link to internal pad without any checks */
1338     GST_DEBUG_OBJECT (gpad, "connecting internal pad to target");
1339
1340     if (GST_PAD_IS_SRC (internal))
1341       lret =
1342           gst_pad_link_full (internal, newtarget, GST_PAD_LINK_CHECK_NOTHING);
1343     else
1344       lret =
1345           gst_pad_link_full (newtarget, internal, GST_PAD_LINK_CHECK_NOTHING);
1346
1347     if (lret != GST_PAD_LINK_OK)
1348       goto link_failed;
1349   }
1350
1351   return result;
1352
1353   /* ERRORS */
1354 link_failed:
1355   {
1356     GST_WARNING_OBJECT (gpad, "could not link internal and target, reason:%d",
1357         lret);
1358     /* and unset target again */
1359     GST_PROXY_LOCK (gpad);
1360     gst_proxy_pad_set_target_unlocked (GST_PAD_CAST (gpad), NULL);
1361     GST_PROXY_UNLOCK (gpad);
1362     return FALSE;
1363   }
1364 }