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