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