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