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