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