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