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