Revert "context: use context on buffers instead of caps"
[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 static GstPad *gst_proxy_pad_get_internal (GstPad * pad);
77
78 static void gst_proxy_pad_dispose (GObject * object);
79 static void gst_proxy_pad_finalize (GObject * object);
80
81 static void on_src_target_notify (GstPad * target,
82     GParamSpec * unused, gpointer user_data);
83
84 static GParamSpec *pspec_caps = NULL;
85
86 static const GstQueryType *
87 gst_proxy_pad_do_query_type (GstPad * pad)
88 {
89   GstPad *target = gst_proxy_pad_get_target (pad);
90   const GstQueryType *res = NULL;
91
92   if (target) {
93     res = gst_pad_get_query_types (target);
94     gst_object_unref (target);
95   }
96   return res;
97 }
98
99 static gboolean
100 gst_proxy_pad_do_event (GstPad * pad, GstEvent * event)
101 {
102   gboolean res = FALSE;
103   GstPad *internal = gst_proxy_pad_get_internal (pad);
104
105   if (internal) {
106     res = gst_pad_push_event (internal, event);
107     gst_object_unref (internal);
108   }
109
110   return res;
111 }
112
113 static gboolean
114 gst_proxy_pad_do_query (GstPad * pad, GstQuery * query)
115 {
116   gboolean res = FALSE;
117   GstPad *target = gst_proxy_pad_get_target (pad);
118
119   if (target) {
120     res = gst_pad_query (target, query);
121     gst_object_unref (target);
122   }
123
124   return res;
125 }
126
127 static GstIterator *
128 gst_proxy_pad_do_iterate_internal_links (GstPad * pad)
129 {
130   GstIterator *res = NULL;
131   GstPad *internal = GST_PROXY_PAD_INTERNAL (pad);
132
133   if (internal) {
134     res =
135         gst_iterator_new_single (GST_TYPE_PAD, internal,
136         (GstCopyFunction) gst_object_ref, (GFreeFunc) gst_object_unref);
137   }
138
139   return res;
140 }
141
142 static GstFlowReturn
143 gst_proxy_pad_do_chain (GstPad * pad, GstBuffer * buffer)
144 {
145   GstFlowReturn res;
146   GstPad *internal = GST_PROXY_PAD_INTERNAL (pad);
147
148   res = gst_pad_push (internal, buffer);
149
150   return res;
151 }
152
153 static GstFlowReturn
154 gst_proxy_pad_do_chain_list (GstPad * pad, GstBufferList * list)
155 {
156   GstFlowReturn res;
157   GstPad *internal = GST_PROXY_PAD_INTERNAL (pad);
158
159   res = gst_pad_push_list (internal, list);
160
161   return res;
162 }
163
164 static GstFlowReturn
165 gst_proxy_pad_do_getrange (GstPad * pad, guint64 offset, guint size,
166     GstBuffer ** buffer)
167 {
168   GstFlowReturn res;
169   GstPad *internal = GST_PROXY_PAD_INTERNAL (pad);
170
171   res = gst_pad_pull_range (internal, offset, size, buffer);
172
173   return res;
174 }
175
176 static gboolean
177 gst_proxy_pad_do_checkgetrange (GstPad * pad)
178 {
179   gboolean result;
180   GstPad *internal = GST_PROXY_PAD_INTERNAL (pad);
181
182   result = gst_pad_check_pull_range (internal);
183
184   return result;
185 }
186
187 static GstCaps *
188 gst_proxy_pad_do_getcaps (GstPad * pad)
189 {
190   GstPad *target = gst_proxy_pad_get_target (pad);
191   GstCaps *res;
192   GstPadTemplate *templ = GST_PAD_PAD_TEMPLATE (pad);
193
194   if (target) {
195     /* if we have a real target, proxy the call */
196     res = gst_pad_get_caps (target);
197
198     GST_DEBUG_OBJECT (pad, "get caps of target %s:%s : %" GST_PTR_FORMAT,
199         GST_DEBUG_PAD_NAME (target), res);
200
201     gst_object_unref (target);
202
203     /* filter against the template */
204     if (templ && res) {
205       GstCaps *filt, *tmp;
206
207       filt = GST_PAD_TEMPLATE_CAPS (templ);
208       if (filt) {
209         tmp = gst_caps_intersect (filt, res);
210         gst_caps_unref (res);
211         res = tmp;
212         GST_DEBUG_OBJECT (pad,
213             "filtered against template gives %" GST_PTR_FORMAT, res);
214       }
215     }
216   } else {
217     /* else, if we have a template, use its caps. */
218     if (templ) {
219       res = GST_PAD_TEMPLATE_CAPS (templ);
220       GST_DEBUG_OBJECT (pad,
221           "using pad template %p with caps %p %" GST_PTR_FORMAT, templ, res,
222           res);
223       res = gst_caps_ref (res);
224       goto done;
225     }
226
227     /* last resort, any caps */
228     GST_DEBUG_OBJECT (pad, "pad has no template, returning ANY");
229     res = gst_caps_new_any ();
230   }
231
232 done:
233   return res;
234 }
235
236 static gboolean
237 gst_proxy_pad_do_acceptcaps (GstPad * pad, GstCaps * caps)
238 {
239   GstPad *target = gst_proxy_pad_get_target (pad);
240   gboolean res;
241
242   if (target) {
243     res = gst_pad_accept_caps (target, caps);
244     gst_object_unref (target);
245   } else {
246     /* We don't have a target, we return TRUE and we assume that any future
247      * target will be able to deal with any configured caps. */
248     res = TRUE;
249   }
250
251   return res;
252 }
253
254 static void
255 gst_proxy_pad_do_fixatecaps (GstPad * pad, GstCaps * caps)
256 {
257   GstPad *target = gst_proxy_pad_get_target (pad);
258
259   if (target) {
260     gst_pad_fixate_caps (target, caps);
261     gst_object_unref (target);
262   }
263 }
264
265 static gboolean
266 gst_proxy_pad_do_setcaps (GstPad * pad, GstCaps * caps)
267 {
268   GstPad *target = gst_proxy_pad_get_target (pad);
269   gboolean res;
270
271   if (target) {
272     res = gst_pad_set_caps (target, caps);
273     gst_object_unref (target);
274   } else {
275     /* We don't have any target, but we shouldn't return FALSE since this
276      * would stop the actual push of a buffer (which might trigger a pad block
277      * or probe, or properly return GST_FLOW_NOT_LINKED.
278      */
279     res = TRUE;
280   }
281   return res;
282 }
283
284 static gboolean
285 gst_proxy_pad_set_target_unlocked (GstPad * pad, GstPad * target)
286 {
287   GstPad *oldtarget;
288
289   if (target) {
290     GST_LOG_OBJECT (pad, "setting target %s:%s", GST_DEBUG_PAD_NAME (target));
291
292     if (G_UNLIKELY (GST_PAD_DIRECTION (pad) != GST_PAD_DIRECTION (target)))
293       goto wrong_direction;
294   } else
295     GST_LOG_OBJECT (pad, "clearing target");
296
297   /* clear old target */
298   if ((oldtarget = GST_PROXY_PAD_TARGET (pad)))
299     gst_object_unref (oldtarget);
300
301   /* set and ref new target if any */
302   if (target)
303     GST_PROXY_PAD_TARGET (pad) = gst_object_ref (target);
304   else
305     GST_PROXY_PAD_TARGET (pad) = NULL;
306
307   return TRUE;
308
309   /* ERRORS */
310 wrong_direction:
311   {
312     GST_ERROR_OBJECT (pad,
313         "target pad doesn't have the same direction as ourself");
314     return FALSE;
315   }
316 }
317
318 static gboolean
319 gst_proxy_pad_set_target (GstPad * pad, GstPad * target)
320 {
321   gboolean result;
322
323   GST_PROXY_LOCK (pad);
324   result = gst_proxy_pad_set_target_unlocked (pad, target);
325   GST_PROXY_UNLOCK (pad);
326
327   return result;
328 }
329
330 static GstPad *
331 gst_proxy_pad_get_target (GstPad * pad)
332 {
333   GstPad *target;
334
335   GST_PROXY_LOCK (pad);
336   target = GST_PROXY_PAD_TARGET (pad);
337   if (target)
338     gst_object_ref (target);
339   GST_PROXY_UNLOCK (pad);
340
341   return target;
342 }
343
344 static GstPad *
345 gst_proxy_pad_get_internal (GstPad * pad)
346 {
347   GstPad *internal;
348
349   GST_PROXY_LOCK (pad);
350   internal = GST_PROXY_PAD_INTERNAL (pad);
351   if (internal)
352     gst_object_ref (internal);
353   GST_PROXY_UNLOCK (pad);
354
355   return internal;
356 }
357
358 static void
359 gst_proxy_pad_do_unlink (GstPad * pad)
360 {
361   GstPad *internal;
362
363   /* don't do anything if this unlink resulted from retargeting the pad
364    * controlled by the ghostpad. We only want to invalidate the target pad when
365    * the element suddently unlinked with our internal pad. */
366   if (GST_PROXY_PAD_RETARGET (pad))
367     return;
368
369   internal = GST_PROXY_PAD_INTERNAL (pad);
370
371   GST_DEBUG_OBJECT (pad, "pad is unlinked");
372
373   gst_proxy_pad_set_target (internal, NULL);
374 }
375
376 static void
377 gst_proxy_pad_class_init (GstProxyPadClass * klass)
378 {
379   GObjectClass *gobject_class = (GObjectClass *) klass;
380
381   g_type_class_add_private (klass, sizeof (GstProxyPadPrivate));
382
383   gobject_class->dispose = gst_proxy_pad_dispose;
384   gobject_class->finalize = gst_proxy_pad_finalize;
385
386   /* Register common function pointer descriptions */
387   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_do_query_type);
388   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_do_event);
389   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_do_query);
390   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_do_iterate_internal_links);
391   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_do_getcaps);
392   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_do_acceptcaps);
393   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_do_fixatecaps);
394   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_do_setcaps);
395   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_do_unlink);
396   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_do_chain);
397   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_do_chain_list);
398   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_do_getrange);
399   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_do_checkgetrange);
400 }
401
402 static void
403 gst_proxy_pad_dispose (GObject * object)
404 {
405   GstPad *pad = GST_PAD (object);
406   GstPad **target_p;
407
408   GST_PROXY_LOCK (pad);
409   /* remove and unref the target */
410   target_p = &GST_PROXY_PAD_TARGET (pad);
411   gst_object_replace ((GstObject **) target_p, NULL);
412   /* The internal is only cleared by GstGhostPad::dispose, since it is the 
413    * parent of non-ghost GstProxyPad and owns the refcount on the internal.
414    */
415   GST_PROXY_UNLOCK (pad);
416
417   G_OBJECT_CLASS (gst_proxy_pad_parent_class)->dispose (object);
418 }
419
420 static void
421 gst_proxy_pad_finalize (GObject * object)
422 {
423   GstProxyPad *pad = GST_PROXY_PAD (object);
424
425   g_mutex_free (GST_PROXY_GET_LOCK (pad));
426   GST_PROXY_GET_LOCK (pad) = NULL;
427
428   G_OBJECT_CLASS (gst_proxy_pad_parent_class)->finalize (object);
429 }
430
431 static void
432 gst_proxy_pad_init (GstProxyPad * ppad)
433 {
434   GstPad *pad = (GstPad *) ppad;
435
436   GST_PROXY_PAD_PRIVATE (ppad) = G_TYPE_INSTANCE_GET_PRIVATE (ppad,
437       GST_TYPE_PROXY_PAD, GstProxyPadPrivate);
438   GST_PROXY_GET_LOCK (pad) = g_mutex_new ();
439
440   gst_pad_set_query_type_function (pad, gst_proxy_pad_do_query_type);
441   gst_pad_set_event_function (pad, gst_proxy_pad_do_event);
442   gst_pad_set_query_function (pad, gst_proxy_pad_do_query);
443   gst_pad_set_iterate_internal_links_function (pad,
444       gst_proxy_pad_do_iterate_internal_links);
445
446   gst_pad_set_getcaps_function (pad, gst_proxy_pad_do_getcaps);
447   gst_pad_set_acceptcaps_function (pad, gst_proxy_pad_do_acceptcaps);
448   gst_pad_set_fixatecaps_function (pad, gst_proxy_pad_do_fixatecaps);
449   gst_pad_set_setcaps_function (pad, gst_proxy_pad_do_setcaps);
450   gst_pad_set_unlink_function (pad, gst_proxy_pad_do_unlink);
451 }
452
453
454 /***********************************************************************
455  * Ghost pads, implemented as a pair of proxy pads (sort of)
456  */
457
458
459 #define GST_GHOST_PAD_PRIVATE(obj)      (GST_GHOST_PAD_CAST (obj)->priv)
460
461 struct _GstGhostPadPrivate
462 {
463   /* with PROXY_LOCK */
464   gulong notify_id;
465
466   gboolean constructed;
467 };
468
469 G_DEFINE_TYPE (GstGhostPad, gst_ghost_pad, GST_TYPE_PROXY_PAD);
470
471 static void gst_ghost_pad_dispose (GObject * object);
472
473 /* see gstghostpad design docs */
474 static gboolean
475 gst_ghost_pad_internal_do_activate_push (GstPad * pad, gboolean active)
476 {
477   gboolean ret;
478   GstPad *other;
479
480   GST_LOG_OBJECT (pad, "%sactivate push on %s:%s, we're ok",
481       (active ? "" : "de"), GST_DEBUG_PAD_NAME (pad));
482
483   /* in both cases (SRC and SINK) we activate just the internal pad. The targets
484    * will be activated later (or already in case of a ghost sinkpad). */
485   other = GST_PROXY_PAD_INTERNAL (pad);
486   ret = gst_pad_activate_push (other, active);
487
488   return ret;
489 }
490
491 static gboolean
492 gst_ghost_pad_internal_do_activate_pull (GstPad * pad, gboolean active)
493 {
494   gboolean ret;
495   GstPad *other;
496
497   GST_LOG_OBJECT (pad, "%sactivate pull on %s:%s", (active ? "" : "de"),
498       GST_DEBUG_PAD_NAME (pad));
499
500   if (GST_PAD_DIRECTION (pad) == GST_PAD_SRC) {
501     /* we are activated in pull mode by our peer element, which is a sinkpad
502      * that wants to operate in pull mode. This activation has to propagate
503      * upstream throught the pipeline. We call the internal activation function,
504      * which will trigger gst_ghost_pad_do_activate_pull, which propagates even
505      * further upstream */
506     GST_LOG_OBJECT (pad, "pad is src, activate internal");
507     other = GST_PROXY_PAD_INTERNAL (pad);
508     ret = gst_pad_activate_pull (other, active);
509   } else if (G_LIKELY ((other = gst_pad_get_peer (pad)))) {
510     /* We are SINK, the ghostpad is SRC, we propagate the activation upstream
511      * since we hold a pointer to the upstream peer. */
512     GST_LOG_OBJECT (pad, "activating peer");
513     ret = gst_pad_activate_pull (other, active);
514     gst_object_unref (other);
515   } else {
516     /* this is failure, we can't activate pull if there is no peer */
517     GST_LOG_OBJECT (pad, "not src and no peer, failing");
518     ret = FALSE;
519   }
520
521   return ret;
522 }
523
524 static gboolean
525 gst_ghost_pad_do_activate_push (GstPad * pad, gboolean active)
526 {
527   gboolean ret;
528   GstPad *other;
529
530   GST_LOG_OBJECT (pad, "%sactivate push on %s:%s, proxy internal",
531       (active ? "" : "de"), GST_DEBUG_PAD_NAME (pad));
532
533   /* just activate the internal pad */
534   other = GST_PROXY_PAD_INTERNAL (pad);
535   ret = gst_pad_activate_push (other, active);
536
537   return ret;
538 }
539
540 static gboolean
541 gst_ghost_pad_do_activate_pull (GstPad * pad, gboolean active)
542 {
543   gboolean ret;
544   GstPad *other;
545
546   GST_LOG_OBJECT (pad, "%sactivate pull on %s:%s", (active ? "" : "de"),
547       GST_DEBUG_PAD_NAME (pad));
548
549   if (GST_PAD_DIRECTION (pad) == GST_PAD_SRC) {
550     /* the ghostpad is SRC and activated in pull mode by its peer, call the
551      * activation function of the internal pad to propagate the activation
552      * upstream */
553     GST_LOG_OBJECT (pad, "pad is src, activate internal");
554     other = GST_PROXY_PAD_INTERNAL (pad);
555     ret = gst_pad_activate_pull (other, active);
556   } else if (G_LIKELY ((other = gst_pad_get_peer (pad)))) {
557     /* We are SINK and activated by the internal pad, propagate activation
558      * upstream because we hold a ref to the upstream peer */
559     GST_LOG_OBJECT (pad, "activating peer");
560     ret = gst_pad_activate_pull (other, active);
561     gst_object_unref (other);
562   } else {
563     /* no peer, we fail */
564     GST_LOG_OBJECT (pad, "pad not src and no peer, failing");
565     ret = FALSE;
566   }
567
568   return ret;
569 }
570
571 static GstPadLinkReturn
572 gst_ghost_pad_do_link (GstPad * pad, GstPad * peer)
573 {
574   GstPadLinkReturn ret;
575   GstPad *internal;
576
577   GST_DEBUG_OBJECT (pad, "linking ghostpad");
578
579   internal = GST_PROXY_PAD_INTERNAL (pad);
580   if (!gst_proxy_pad_set_target (internal, peer))
581     goto target_failed;
582
583   ret = GST_PAD_LINK_OK;
584   /* if we are a source pad, we should call the peer link function
585    * if the peer has one, see design docs. */
586   if (GST_PAD_IS_SRC (pad)) {
587     if (GST_PAD_LINKFUNC (peer)) {
588       ret = GST_PAD_LINKFUNC (peer) (peer, pad);
589       if (ret != GST_PAD_LINK_OK)
590         goto link_failed;
591     }
592   }
593   return ret;
594
595   /* ERRORS */
596 target_failed:
597   {
598     GST_DEBUG_OBJECT (pad, "setting target failed");
599     return GST_PAD_LINK_REFUSED;
600   }
601 link_failed:
602   {
603     GST_DEBUG_OBJECT (pad, "linking failed");
604     /* clear target again */
605     gst_proxy_pad_set_target (internal, NULL);
606     return ret;
607   }
608 }
609
610 static void
611 gst_ghost_pad_do_unlink (GstPad * pad)
612 {
613   GstPad *internal;
614
615   internal = GST_PROXY_PAD_INTERNAL (pad);
616
617   GST_DEBUG_OBJECT (pad, "unlinking ghostpad");
618
619   /* The target of the internal pad is no longer valid */
620   gst_proxy_pad_set_target (internal, NULL);
621 }
622
623 static void
624 on_int_notify (GstPad * internal, GParamSpec * unused, GstGhostPad * pad)
625 {
626   GstCaps *caps;
627   gboolean changed;
628
629   g_object_get (internal, "caps", &caps, NULL);
630
631   GST_DEBUG_OBJECT (pad, "notified %p %" GST_PTR_FORMAT, caps, caps);
632
633   GST_OBJECT_LOCK (pad);
634   changed = (GST_PAD_CAPS (pad) != caps);
635   if (changed)
636     gst_caps_replace (&(GST_PAD_CAPS (pad)), caps);
637   GST_OBJECT_UNLOCK (pad);
638
639   if (changed) {
640 #if GLIB_CHECK_VERSION(2,26,0)
641     g_object_notify_by_pspec ((GObject *) pad, pspec_caps);
642 #else
643     g_object_notify ((GObject *) pad, "caps");
644 #endif
645   }
646
647   if (caps)
648     gst_caps_unref (caps);
649 }
650
651 static void
652 on_src_target_notify (GstPad * target, GParamSpec * unused, gpointer user_data)
653 {
654   GstProxyPad *proxypad;
655   GstGhostPad *gpad;
656   GstCaps *caps;
657   gboolean changed;
658
659   g_object_get (target, "caps", &caps, NULL);
660
661   GST_OBJECT_LOCK (target);
662   /* First check if the peer is still available and our proxy pad */
663   if (!GST_PAD_PEER (target) || !GST_IS_PROXY_PAD (GST_PAD_PEER (target))) {
664     GST_OBJECT_UNLOCK (target);
665     goto done;
666   }
667
668   proxypad = GST_PROXY_PAD (GST_PAD_PEER (target));
669   GST_PROXY_LOCK (proxypad);
670   /* Now check if the proxypad's internal pad is still there and
671    * a ghostpad */
672   if (!GST_PROXY_PAD_INTERNAL (proxypad) ||
673       !GST_IS_GHOST_PAD (GST_PROXY_PAD_INTERNAL (proxypad))) {
674     GST_OBJECT_UNLOCK (target);
675     GST_PROXY_UNLOCK (proxypad);
676     goto done;
677   }
678   gpad = GST_GHOST_PAD (GST_PROXY_PAD_INTERNAL (proxypad));
679   g_object_ref (gpad);
680   GST_PROXY_UNLOCK (proxypad);
681   GST_OBJECT_UNLOCK (target);
682
683   GST_OBJECT_LOCK (gpad);
684
685   GST_DEBUG_OBJECT (gpad, "notified %p %" GST_PTR_FORMAT, caps, caps);
686
687   changed = (GST_PAD_CAPS (gpad) != caps);
688   if (changed)
689     gst_caps_replace (&(GST_PAD_CAPS (gpad)), caps);
690   GST_OBJECT_UNLOCK (gpad);
691
692   if (changed) {
693 #if GLIB_CHECK_VERSION(2,26,0)
694     g_object_notify_by_pspec ((GObject *) gpad, pspec_caps);
695 #else
696     g_object_notify ((GObject *) gpad, "caps");
697 #endif
698   }
699
700   g_object_unref (gpad);
701
702 done:
703   if (caps)
704     gst_caps_unref (caps);
705 }
706
707 static gboolean
708 gst_ghost_pad_do_setcaps (GstPad * pad, GstCaps * caps)
709 {
710   if (GST_PAD_DIRECTION (pad) == GST_PAD_SRC)
711     return TRUE;
712
713   return gst_proxy_pad_do_setcaps (pad, caps);
714 }
715
716 static GstIterator *
717 gst_ghost_pad_do_iterate_internal_links (GstPad * pad)
718 {
719   GstIterator *res = NULL;
720   GstPad *internal = GST_PROXY_PAD_INTERNAL (GST_GHOST_PAD_CAST (pad));
721
722   if (internal) {
723     res =
724         gst_iterator_new_single (GST_TYPE_PAD, internal,
725         (GstCopyFunction) gst_object_ref, (GFreeFunc) gst_object_unref);
726   }
727
728   return res;
729 }
730
731 static void
732 gst_ghost_pad_class_init (GstGhostPadClass * klass)
733 {
734   GObjectClass *gobject_class = (GObjectClass *) klass;
735
736   g_type_class_add_private (klass, sizeof (GstGhostPadPrivate));
737
738   pspec_caps = g_object_class_find_property (gobject_class, "caps");
739
740   gobject_class->dispose = gst_ghost_pad_dispose;
741
742   GST_DEBUG_REGISTER_FUNCPTR (gst_ghost_pad_do_setcaps);
743   GST_DEBUG_REGISTER_FUNCPTR (gst_ghost_pad_do_activate_pull);
744   GST_DEBUG_REGISTER_FUNCPTR (gst_ghost_pad_do_activate_push);
745   GST_DEBUG_REGISTER_FUNCPTR (gst_ghost_pad_do_link);
746 }
747
748 static void
749 gst_ghost_pad_init (GstGhostPad * pad)
750 {
751   GST_GHOST_PAD_PRIVATE (pad) = G_TYPE_INSTANCE_GET_PRIVATE (pad,
752       GST_TYPE_GHOST_PAD, GstGhostPadPrivate);
753
754   gst_pad_set_setcaps_function (GST_PAD_CAST (pad), gst_ghost_pad_do_setcaps);
755   gst_pad_set_activatepull_function (GST_PAD_CAST (pad),
756       gst_ghost_pad_do_activate_pull);
757   gst_pad_set_activatepush_function (GST_PAD_CAST (pad),
758       gst_ghost_pad_do_activate_push);
759   gst_pad_set_iterate_internal_links_function (GST_PAD_CAST (pad),
760       gst_ghost_pad_do_iterate_internal_links);
761 }
762
763 static void
764 gst_ghost_pad_dispose (GObject * object)
765 {
766   GstPad *pad;
767   GstPad *internal;
768   GstPad *peer;
769
770   pad = GST_PAD (object);
771
772   GST_DEBUG_OBJECT (pad, "dispose");
773
774   gst_ghost_pad_set_target (GST_GHOST_PAD (pad), NULL);
775
776   /* Unlink here so that gst_pad_dispose doesn't. That would lead to a call to
777    * gst_ghost_pad_do_unlink when the ghost pad is in an inconsistent state */
778   peer = gst_pad_get_peer (pad);
779   if (peer) {
780     if (GST_PAD_IS_SRC (pad))
781       gst_pad_unlink (pad, peer);
782     else
783       gst_pad_unlink (peer, pad);
784
785     gst_object_unref (peer);
786   }
787
788   GST_PROXY_LOCK (pad);
789   internal = GST_PROXY_PAD_INTERNAL (pad);
790
791   gst_pad_set_activatepull_function (internal, NULL);
792   gst_pad_set_activatepush_function (internal, NULL);
793
794   g_signal_handler_disconnect (internal,
795       GST_GHOST_PAD_PRIVATE (pad)->notify_id);
796
797   /* disposes of the internal pad, since the ghostpad is the only possible object
798    * that has a refcount on the internal pad. */
799   gst_object_unparent (GST_OBJECT_CAST (internal));
800   GST_PROXY_PAD_INTERNAL (pad) = NULL;
801
802   GST_PROXY_UNLOCK (pad);
803
804   G_OBJECT_CLASS (gst_ghost_pad_parent_class)->dispose (object);
805 }
806
807 /**
808  * gst_ghost_pad_construct:
809  * @gpad: the newly allocated ghost pad
810  *
811  * Finish initialization of a newly allocated ghost pad.
812  *
813  * This function is most useful in language bindings and when subclassing
814  * #GstGhostPad; plugin and application developers normally will not call this
815  * function. Call this function directly after a call to g_object_new
816  * (GST_TYPE_GHOST_PAD, "direction", @dir, ..., NULL).
817  *
818  * Returns: %TRUE if the construction succeeds, %FALSE otherwise.
819  *
820  * Since: 0.10.22
821  */
822 gboolean
823 gst_ghost_pad_construct (GstGhostPad * gpad)
824 {
825   GstPadDirection dir, otherdir;
826   GstPadTemplate *templ;
827   GstPad *pad, *internal;
828
829   g_return_val_if_fail (GST_IS_GHOST_PAD (gpad), FALSE);
830   g_return_val_if_fail (GST_GHOST_PAD_PRIVATE (gpad)->constructed == FALSE,
831       FALSE);
832
833   g_object_get (gpad, "direction", &dir, "template", &templ, NULL);
834
835   g_return_val_if_fail (dir != GST_PAD_UNKNOWN, FALSE);
836
837   pad = GST_PAD (gpad);
838
839   /* Set directional padfunctions for ghostpad */
840   if (dir == GST_PAD_SINK) {
841     gst_pad_set_chain_function (pad, gst_proxy_pad_do_chain);
842     gst_pad_set_chain_list_function (pad, gst_proxy_pad_do_chain_list);
843   } else {
844     gst_pad_set_getrange_function (pad, gst_proxy_pad_do_getrange);
845     gst_pad_set_checkgetrange_function (pad, gst_proxy_pad_do_checkgetrange);
846   }
847
848   /* link/unlink functions */
849   gst_pad_set_link_function (pad, gst_ghost_pad_do_link);
850   gst_pad_set_unlink_function (pad, gst_ghost_pad_do_unlink);
851
852   /* INTERNAL PAD, it always exists and is child of the ghostpad */
853   otherdir = (dir == GST_PAD_SRC) ? GST_PAD_SINK : GST_PAD_SRC;
854   if (templ) {
855     internal =
856         g_object_new (GST_TYPE_PROXY_PAD, "name", NULL,
857         "direction", otherdir, "template", templ, NULL);
858     /* release ref obtained via g_object_get */
859     gst_object_unref (templ);
860   } else {
861     internal =
862         g_object_new (GST_TYPE_PROXY_PAD, "name", NULL,
863         "direction", otherdir, NULL);
864   }
865   GST_PAD_UNSET_FLUSHING (internal);
866
867   /* Set directional padfunctions for internal pad */
868   if (dir == GST_PAD_SRC) {
869     gst_pad_set_chain_function (internal, gst_proxy_pad_do_chain);
870     gst_pad_set_chain_list_function (internal, gst_proxy_pad_do_chain_list);
871   } else {
872     gst_pad_set_getrange_function (internal, gst_proxy_pad_do_getrange);
873     gst_pad_set_checkgetrange_function (internal,
874         gst_proxy_pad_do_checkgetrange);
875   }
876
877   GST_PROXY_LOCK (pad);
878
879   /* now make the ghostpad a parent of the internal pad */
880   if (!gst_object_set_parent (GST_OBJECT_CAST (internal),
881           GST_OBJECT_CAST (pad)))
882     goto parent_failed;
883
884   /* The ghostpad is the parent of the internal pad and is the only object that
885    * can have a refcount on the internal pad.
886    * At this point, the GstGhostPad has a refcount of 1, and the internal pad has
887    * a refcount of 1.
888    * When the refcount of the GstGhostPad drops to 0, the ghostpad will dispose
889    * its refcount on the internal pad in the dispose method by un-parenting it.
890    * This is why we don't take extra refcounts in the assignments below
891    */
892   GST_PROXY_PAD_INTERNAL (pad) = internal;
893   GST_PROXY_PAD_INTERNAL (internal) = pad;
894
895   /* could be more general here, iterating over all writable properties...
896    * taking the short road for now tho */
897   GST_GHOST_PAD_PRIVATE (pad)->notify_id =
898       g_signal_connect (internal, "notify::caps", G_CALLBACK (on_int_notify),
899       pad);
900
901   /* call function to init values of the pad caps */
902   on_int_notify (internal, NULL, GST_GHOST_PAD_CAST (pad));
903
904   /* special activation functions for the internal pad */
905   gst_pad_set_activatepull_function (internal,
906       gst_ghost_pad_internal_do_activate_pull);
907   gst_pad_set_activatepush_function (internal,
908       gst_ghost_pad_internal_do_activate_push);
909
910   GST_PROXY_UNLOCK (pad);
911
912   GST_GHOST_PAD_PRIVATE (gpad)->constructed = TRUE;
913   return TRUE;
914
915   /* ERRORS */
916 parent_failed:
917   {
918     GST_WARNING_OBJECT (gpad, "Could not set internal pad %s:%s",
919         GST_DEBUG_PAD_NAME (internal));
920     g_critical ("Could not set internal pad %s:%s",
921         GST_DEBUG_PAD_NAME (internal));
922     GST_PROXY_UNLOCK (pad);
923     gst_object_unref (internal);
924     return FALSE;
925   }
926 }
927
928 static GstPad *
929 gst_ghost_pad_new_full (const gchar * name, GstPadDirection dir,
930     GstPadTemplate * templ)
931 {
932   GstGhostPad *ret;
933
934   g_return_val_if_fail (dir != GST_PAD_UNKNOWN, NULL);
935
936   /* OBJECT CREATION */
937   if (templ) {
938     ret = g_object_new (GST_TYPE_GHOST_PAD, "name", name,
939         "direction", dir, "template", templ, NULL);
940   } else {
941     ret = g_object_new (GST_TYPE_GHOST_PAD, "name", name,
942         "direction", dir, NULL);
943   }
944
945   if (!gst_ghost_pad_construct (ret))
946     goto construct_failed;
947
948   return GST_PAD_CAST (ret);
949
950 construct_failed:
951   /* already logged */
952   gst_object_unref (ret);
953   return NULL;
954 }
955
956 /**
957  * gst_ghost_pad_new_no_target:
958  * @name: (allow-none): the name of the new pad, or NULL to assign a default name.
959  * @dir: the direction of the ghostpad
960  *
961  * Create a new ghostpad without a target with the given direction.
962  * A target can be set on the ghostpad later with the
963  * gst_ghost_pad_set_target() function.
964  *
965  * The created ghostpad will not have a padtemplate.
966  *
967  * Returns: (transfer full): a new #GstPad, or NULL in case of an error.
968  */
969 GstPad *
970 gst_ghost_pad_new_no_target (const gchar * name, GstPadDirection dir)
971 {
972   GstPad *ret;
973
974   g_return_val_if_fail (dir != GST_PAD_UNKNOWN, NULL);
975
976   GST_LOG ("name:%s, direction:%d", GST_STR_NULL (name), dir);
977
978   ret = gst_ghost_pad_new_full (name, dir, NULL);
979
980   return ret;
981 }
982
983 /**
984  * gst_ghost_pad_new:
985  * @name: (allow-none): the name of the new pad, or NULL to assign a default name
986  * @target: (transfer none): the pad to ghost.
987  *
988  * Create a new ghostpad with @target as the target. The direction will be taken
989  * from the target pad. @target must be unlinked.
990  *
991  * Will ref the target.
992  *
993  * Returns: (transfer full): a new #GstPad, or NULL in case of an error.
994  */
995 GstPad *
996 gst_ghost_pad_new (const gchar * name, GstPad * target)
997 {
998   GstPad *ret;
999
1000   g_return_val_if_fail (GST_IS_PAD (target), NULL);
1001   g_return_val_if_fail (!gst_pad_is_linked (target), NULL);
1002
1003   GST_LOG ("name:%s, target:%s:%s", GST_STR_NULL (name),
1004       GST_DEBUG_PAD_NAME (target));
1005
1006   if ((ret = gst_ghost_pad_new_no_target (name, GST_PAD_DIRECTION (target))))
1007     if (!gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (ret), target))
1008       goto set_target_failed;
1009
1010   return ret;
1011
1012   /* ERRORS */
1013 set_target_failed:
1014   {
1015     GST_WARNING_OBJECT (ret, "failed to set target %s:%s",
1016         GST_DEBUG_PAD_NAME (target));
1017     gst_object_unref (ret);
1018     return NULL;
1019   }
1020 }
1021
1022 /**
1023  * gst_ghost_pad_new_from_template:
1024  * @name: (allow-none): the name of the new pad, or NULL to assign a default name.
1025  * @target: (transfer none): the pad to ghost.
1026  * @templ: (transfer none): the #GstPadTemplate to use on the ghostpad.
1027  *
1028  * Create a new ghostpad with @target as the target. The direction will be taken
1029  * from the target pad. The template used on the ghostpad will be @template.
1030  *
1031  * Will ref the target.
1032  *
1033  * Returns: (transfer full): a new #GstPad, or NULL in case of an error.
1034  *
1035  * Since: 0.10.10
1036  */
1037
1038 GstPad *
1039 gst_ghost_pad_new_from_template (const gchar * name, GstPad * target,
1040     GstPadTemplate * templ)
1041 {
1042   GstPad *ret;
1043
1044   g_return_val_if_fail (GST_IS_PAD (target), NULL);
1045   g_return_val_if_fail (!gst_pad_is_linked (target), NULL);
1046   g_return_val_if_fail (templ != NULL, NULL);
1047   g_return_val_if_fail (GST_PAD_TEMPLATE_DIRECTION (templ) ==
1048       GST_PAD_DIRECTION (target), NULL);
1049
1050   GST_LOG ("name:%s, target:%s:%s, templ:%p", GST_STR_NULL (name),
1051       GST_DEBUG_PAD_NAME (target), templ);
1052
1053   if ((ret = gst_ghost_pad_new_full (name, GST_PAD_DIRECTION (target), templ)))
1054     if (!gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (ret), target))
1055       goto set_target_failed;
1056
1057   return ret;
1058
1059   /* ERRORS */
1060 set_target_failed:
1061   {
1062     GST_WARNING_OBJECT (ret, "failed to set target %s:%s",
1063         GST_DEBUG_PAD_NAME (target));
1064     gst_object_unref (ret);
1065     return NULL;
1066   }
1067 }
1068
1069 /**
1070  * gst_ghost_pad_new_no_target_from_template:
1071  * @name: (allow-none): the name of the new pad, or NULL to assign a default name
1072  * @templ: (transfer none): the #GstPadTemplate to create the ghostpad from.
1073  *
1074  * Create a new ghostpad based on @templ, without setting a target. The
1075  * direction will be taken from the @templ.
1076  *
1077  * Returns: (transfer full): a new #GstPad, or NULL in case of an error.
1078  *
1079  * Since: 0.10.10
1080  */
1081 GstPad *
1082 gst_ghost_pad_new_no_target_from_template (const gchar * name,
1083     GstPadTemplate * templ)
1084 {
1085   GstPad *ret;
1086
1087   g_return_val_if_fail (templ != NULL, NULL);
1088
1089   ret =
1090       gst_ghost_pad_new_full (name, GST_PAD_TEMPLATE_DIRECTION (templ), templ);
1091
1092   return ret;
1093 }
1094
1095 /**
1096  * gst_ghost_pad_get_target:
1097  * @gpad: the #GstGhostPad
1098  *
1099  * Get the target pad of @gpad. Unref target pad after usage.
1100  *
1101  * Returns: (transfer full): the target #GstPad, can be NULL if the ghostpad
1102  * has no target set. Unref target pad after usage.
1103  */
1104 GstPad *
1105 gst_ghost_pad_get_target (GstGhostPad * gpad)
1106 {
1107   GstPad *ret;
1108
1109   g_return_val_if_fail (GST_IS_GHOST_PAD (gpad), NULL);
1110
1111   ret = gst_proxy_pad_get_target (GST_PAD_CAST (gpad));
1112
1113   GST_DEBUG_OBJECT (gpad, "get target %s:%s", GST_DEBUG_PAD_NAME (ret));
1114
1115   return ret;
1116 }
1117
1118 /**
1119  * gst_ghost_pad_set_target:
1120  * @gpad: the #GstGhostPad
1121  * @newtarget: (transfer none) (allow-none): the new pad target
1122  *
1123  * Set the new target of the ghostpad @gpad. Any existing target
1124  * is unlinked and links to the new target are established. if @newtarget is
1125  * NULL the target will be cleared.
1126  *
1127  * Returns: (transfer full): TRUE if the new target could be set. This function
1128  *     can return FALSE when the internal pads could not be linked.
1129  */
1130 gboolean
1131 gst_ghost_pad_set_target (GstGhostPad * gpad, GstPad * newtarget)
1132 {
1133   GstPad *internal;
1134   GstPad *oldtarget;
1135   gboolean result;
1136   GstPadLinkReturn lret;
1137
1138   g_return_val_if_fail (GST_IS_GHOST_PAD (gpad), FALSE);
1139   g_return_val_if_fail (GST_PAD_CAST (gpad) != newtarget, FALSE);
1140   g_return_val_if_fail (newtarget != GST_PROXY_PAD_INTERNAL (gpad), FALSE);
1141
1142   /* no need for locking, the internal pad's lifecycle is directly linked to the
1143    * ghostpad's */
1144   internal = GST_PROXY_PAD_INTERNAL (gpad);
1145
1146   if (newtarget)
1147     GST_DEBUG_OBJECT (gpad, "set target %s:%s", GST_DEBUG_PAD_NAME (newtarget));
1148   else
1149     GST_DEBUG_OBJECT (gpad, "clearing target");
1150
1151   /* clear old target */
1152   GST_PROXY_LOCK (gpad);
1153   if ((oldtarget = GST_PROXY_PAD_TARGET (gpad))) {
1154     if (GST_PAD_IS_SRC (oldtarget)) {
1155       g_signal_handlers_disconnect_by_func (oldtarget,
1156           (gpointer) on_src_target_notify, NULL);
1157     }
1158
1159     GST_PROXY_PAD_RETARGET (internal) = TRUE;
1160
1161     /* unlink internal pad */
1162     if (GST_PAD_IS_SRC (internal))
1163       gst_pad_unlink (internal, oldtarget);
1164     else
1165       gst_pad_unlink (oldtarget, internal);
1166
1167     GST_PROXY_PAD_RETARGET (internal) = FALSE;
1168   }
1169
1170   result = gst_proxy_pad_set_target_unlocked (GST_PAD_CAST (gpad), newtarget);
1171   GST_PROXY_UNLOCK (gpad);
1172
1173   if (result && newtarget) {
1174     if (GST_PAD_IS_SRC (newtarget)) {
1175       g_signal_connect (newtarget, "notify::caps",
1176           G_CALLBACK (on_src_target_notify), NULL);
1177     }
1178
1179     /* and link to internal pad without any checks */
1180     GST_DEBUG_OBJECT (gpad, "connecting internal pad to target");
1181
1182     if (GST_PAD_IS_SRC (internal))
1183       lret =
1184           gst_pad_link_full (internal, newtarget, GST_PAD_LINK_CHECK_NOTHING);
1185     else
1186       lret =
1187           gst_pad_link_full (newtarget, internal, GST_PAD_LINK_CHECK_NOTHING);
1188
1189     if (lret != GST_PAD_LINK_OK)
1190       goto link_failed;
1191   }
1192
1193   return result;
1194
1195   /* ERRORS */
1196 link_failed:
1197   {
1198     GST_WARNING_OBJECT (gpad, "could not link internal and target, reason:%d",
1199         lret);
1200     /* and unset target again */
1201     GST_PROXY_LOCK (gpad);
1202     gst_proxy_pad_set_target_unlocked (GST_PAD_CAST (gpad), NULL);
1203     GST_PROXY_UNLOCK (gpad);
1204     return FALSE;
1205   }
1206 }