2 * Copyright (C) 2005 Wim Taymans <wim@fluendo.com>
4 * gstghostpad.c: Unit test for GstGhostPad
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
22 #include <gst/check/gstcheck.h>
24 /* test if removing a bin also cleans up the ghostpads
26 GST_START_TEST (test_remove1)
28 GstElement *b1, *b2, *src, *sink;
29 GstPad *srcpad, *sinkpad;
32 b1 = gst_element_factory_make ("pipeline", NULL);
33 b2 = gst_element_factory_make ("bin", NULL);
34 src = gst_element_factory_make ("fakesrc", NULL);
35 sink = gst_element_factory_make ("fakesink", NULL);
36 ASSERT_OBJECT_REFCOUNT (b1, "pipeline", 1);
37 ASSERT_OBJECT_REFCOUNT (b2, "bin", 1);
39 fail_unless (gst_bin_add (GST_BIN (b2), sink));
40 fail_unless (gst_bin_add (GST_BIN (b1), src));
41 ASSERT_OBJECT_REFCOUNT (b1, "pipeline", 1);
42 ASSERT_OBJECT_REFCOUNT (b2, "bin", 1);
43 fail_unless (gst_bin_add (GST_BIN (b1), b2));
44 ASSERT_OBJECT_REFCOUNT (b1, "pipeline", 1);
45 ASSERT_OBJECT_REFCOUNT (b2, "bin", 1);
47 sinkpad = gst_element_get_static_pad (sink, "sink");
48 gst_element_add_pad (b2, gst_ghost_pad_new ("sink", sinkpad));
49 gst_object_unref (sinkpad);
51 srcpad = gst_element_get_static_pad (src, "src");
52 /* get the ghostpad */
53 sinkpad = gst_element_get_static_pad (b2, "sink");
55 ret = gst_pad_link (srcpad, sinkpad);
56 fail_unless (ret == GST_PAD_LINK_OK);
57 gst_object_unref (srcpad);
58 gst_object_unref (sinkpad);
60 /* now remove the bin with the ghostpad, b2 is disposed now. */
61 ASSERT_OBJECT_REFCOUNT (b1, "pipeline", 1);
62 ASSERT_OBJECT_REFCOUNT (b2, "bin", 1);
63 gst_bin_remove (GST_BIN (b1), b2);
65 srcpad = gst_element_get_static_pad (src, "src");
66 /* pad cannot be linked now */
67 fail_if (gst_pad_is_linked (srcpad));
68 gst_object_unref (srcpad);
70 ASSERT_OBJECT_REFCOUNT (b1, "pipeline", 1);
71 gst_object_unref (b1);
76 /* test if removing a bin also cleans up the ghostpads
78 GST_START_TEST (test_remove2)
80 GstElement *b1, *b2, *src, *sink;
81 GstPad *srcpad, *sinkpad;
84 b1 = gst_element_factory_make ("pipeline", NULL);
85 b2 = gst_element_factory_make ("bin", NULL);
86 src = gst_element_factory_make ("fakesrc", NULL);
87 sink = gst_element_factory_make ("fakesink", NULL);
88 ASSERT_OBJECT_REFCOUNT (src, "src", 1);
90 fail_unless (gst_bin_add (GST_BIN (b2), sink));
91 fail_unless (gst_bin_add (GST_BIN (b1), src));
92 fail_unless (gst_bin_add (GST_BIN (b1), b2));
93 ASSERT_OBJECT_REFCOUNT (src, "src", 1);
95 sinkpad = gst_element_get_static_pad (sink, "sink");
96 gst_element_add_pad (b2, gst_ghost_pad_new ("sink", sinkpad));
97 gst_object_unref (sinkpad);
99 srcpad = gst_element_get_static_pad (src, "src");
100 ASSERT_OBJECT_REFCOUNT (srcpad, "srcpad", 2); /* since we got one */
101 /* get the ghostpad */
102 sinkpad = gst_element_get_static_pad (b2, "sink");
103 ASSERT_OBJECT_REFCOUNT (sinkpad, "sinkpad", 2); /* since we got one */
105 GST_DEBUG ("linking srcpad and sinkpad");
106 ret = gst_pad_link (srcpad, sinkpad);
107 GST_DEBUG ("linked srcpad and sinkpad");
108 fail_unless (ret == GST_PAD_LINK_OK);
109 /* the linking causes a proxypad to be created for srcpad,
110 * to which sinkpad gets linked. This proxypad has a ref to srcpad */
111 ASSERT_OBJECT_REFCOUNT (srcpad, "srcpad", 3);
112 ASSERT_OBJECT_REFCOUNT (sinkpad, "sinkpad", 2);
113 gst_object_unref (srcpad);
114 gst_object_unref (sinkpad);
116 /* now remove the sink from the bin */
117 gst_bin_remove (GST_BIN (b2), sink);
119 srcpad = gst_element_get_static_pad (src, "src");
120 /* pad is still linked to ghostpad */
121 fail_if (!gst_pad_is_linked (srcpad));
122 ASSERT_OBJECT_REFCOUNT (src, "src", 1);
123 ASSERT_OBJECT_REFCOUNT (srcpad, "srcpad", 3);
124 gst_object_unref (srcpad);
125 ASSERT_OBJECT_REFCOUNT (sinkpad, "sinkpad", 1);
128 /* now unlink the pads */
129 gst_pad_unlink (srcpad, sinkpad);
130 ASSERT_OBJECT_REFCOUNT (srcpad, "srcpad", 1); /* proxy has dropped ref */
131 ASSERT_OBJECT_REFCOUNT (sinkpad, "sinkpad", 1);
133 ASSERT_OBJECT_REFCOUNT (src, "src", 1);
134 ASSERT_OBJECT_REFCOUNT (b2, "bin", 1);
135 /* remove b2 from b1 */
136 gst_bin_remove (GST_BIN (b1), b2);
138 /* flush the message, dropping the b1 refcount to 1 */
139 gst_element_set_state (b1, GST_STATE_READY);
140 gst_element_set_state (b1, GST_STATE_NULL);
141 ASSERT_OBJECT_REFCOUNT (b1, "pipeline", 1);
142 gst_object_unref (b1);
149 /* test if a ghost pad without a target can be linked and
150 * unlinked. An untargeted ghostpad has a default ANY caps unless there
151 * is a padtemplate that says something else.
153 GST_START_TEST (test_ghost_pads_notarget)
155 GstElement *b1, *b2, *sink;
156 GstPad *srcpad, *sinkpad, *peer;
157 GstPadLinkReturn ret;
162 b1 = gst_element_factory_make ("pipeline", NULL);
164 /* make sure all messages are discarded */
165 bus = gst_pipeline_get_bus (GST_PIPELINE (b1));
166 gst_bus_set_flushing (bus, TRUE);
167 gst_object_unref (bus);
169 b2 = gst_element_factory_make ("bin", NULL);
170 sink = gst_element_factory_make ("fakesink", NULL);
172 fail_unless (gst_bin_add (GST_BIN (b1), sink));
173 fail_unless (gst_bin_add (GST_BIN (b1), b2));
175 srcpad = gst_ghost_pad_new_no_target ("src", GST_PAD_SRC);
176 fail_unless (srcpad != NULL);
177 sinkpad = gst_element_get_static_pad (sink, "sink");
178 fail_unless (sinkpad != NULL);
180 ret = gst_pad_link (srcpad, sinkpad);
181 fail_unless (ret == GST_PAD_LINK_OK);
183 /* check if the peers are ok */
184 peer = gst_pad_get_peer (srcpad);
185 fail_unless (peer == sinkpad);
186 gst_object_unref (peer);
188 peer = gst_pad_get_peer (sinkpad);
189 fail_unless (peer == srcpad);
190 gst_object_unref (peer);
192 /* check caps, untargetted pad should return ANY or the padtemplate caps
193 * when it was created from a template */
194 caps = gst_pad_get_caps (srcpad, NULL);
195 fail_unless (gst_caps_is_any (caps));
196 gst_caps_unref (caps);
199 bret = gst_pad_unlink (srcpad, sinkpad);
200 fail_unless (bret == TRUE);
203 gst_object_unref (srcpad);
204 gst_object_unref (sinkpad);
205 gst_object_unref (b1);
210 /* Test that removing the target of a ghostpad properly sets the target of the
211 * ghostpad to NULL */
212 GST_START_TEST (test_remove_target)
214 GstElement *b1, *b2, *src, *sink;
215 GstPad *sinkpad, *ghost, *target;
217 b1 = gst_element_factory_make ("pipeline", NULL);
218 b2 = gst_element_factory_make ("bin", NULL);
219 src = gst_element_factory_make ("fakesrc", NULL);
220 sink = gst_element_factory_make ("fakesink", NULL);
221 ASSERT_OBJECT_REFCOUNT (src, "src", 1);
223 fail_unless (gst_bin_add (GST_BIN (b2), sink));
224 fail_unless (gst_bin_add (GST_BIN (b1), src));
225 fail_unless (gst_bin_add (GST_BIN (b1), b2));
226 ASSERT_OBJECT_REFCOUNT (src, "src", 1);
228 sinkpad = gst_element_get_static_pad (sink, "sink");
229 gst_element_add_pad (b2, gst_ghost_pad_new ("sink", sinkpad));
231 ghost = gst_element_get_static_pad (b2, "sink");
233 target = gst_ghost_pad_get_target (GST_GHOST_PAD (ghost));
234 fail_unless (target == sinkpad);
235 gst_object_unref (target);
236 gst_object_unref (sinkpad);
238 gst_bin_remove (GST_BIN (b2), sink);
240 target = gst_ghost_pad_get_target (GST_GHOST_PAD (ghost));
241 fail_unless (target == NULL);
243 gst_object_unref (b1);
244 gst_object_unref (ghost);
250 /* test if linking fails over different bins using a pipeline
253 * fakesrc num_buffers=10 ! ( fakesink )
256 GST_START_TEST (test_link)
258 GstElement *b1, *b2, *src, *sink;
259 GstPad *srcpad, *sinkpad, *gpad, *ppad, *tmp;
260 GstPadLinkReturn ret;
262 b1 = gst_element_factory_make ("pipeline", NULL);
263 b2 = gst_element_factory_make ("bin", NULL);
264 src = gst_element_factory_make ("fakesrc", NULL);
265 sink = gst_element_factory_make ("fakesink", NULL);
267 fail_unless (gst_bin_add (GST_BIN (b2), sink));
268 fail_unless (gst_bin_add (GST_BIN (b1), src));
269 fail_unless (gst_bin_add (GST_BIN (b1), b2));
271 srcpad = gst_element_get_static_pad (src, "src");
272 fail_unless (srcpad != NULL);
273 sinkpad = gst_element_get_static_pad (sink, "sink");
274 fail_unless (sinkpad != NULL);
276 /* linking in different hierarchies should fail */
277 ret = gst_pad_link (srcpad, sinkpad);
278 fail_unless (ret == GST_PAD_LINK_WRONG_HIERARCHY);
280 /* now setup a ghostpad */
281 gpad = gst_ghost_pad_new ("sink", sinkpad);
283 /* Check if the internal pads are set correctly */
284 ppad = GST_PAD (gst_proxy_pad_get_internal (GST_PROXY_PAD (gpad)));
285 fail_unless (ppad == GST_PAD_PEER (sinkpad));
286 tmp = GST_PAD (gst_proxy_pad_get_internal (GST_PROXY_PAD (ppad)));
287 fail_unless (tmp == gpad);
288 gst_object_unref (tmp);
289 gst_object_unref (ppad);
290 gst_object_unref (sinkpad);
291 /* need to ref as _add_pad takes ownership */
292 gst_object_ref (gpad);
293 gst_element_add_pad (b2, gpad);
295 /* our new sinkpad */
298 /* and linking should work now */
299 ret = gst_pad_link (srcpad, sinkpad);
300 fail_unless (ret == GST_PAD_LINK_OK);
302 /* flush the message, dropping the b1 refcount to 1 */
303 gst_element_set_state (b1, GST_STATE_READY);
304 gst_element_set_state (b1, GST_STATE_NULL);
305 ASSERT_OBJECT_REFCOUNT (b1, "pipeline", 1);
307 gst_object_unref (srcpad);
308 gst_object_unref (sinkpad);
309 gst_object_unref (b1);
314 /* test if ghostpads are created automagically when using
315 * gst_element_link_pads.
317 * fakesrc num_buffers=10 ! ( identity ) ! fakesink
319 GST_START_TEST (test_ghost_pads)
321 GstElement *b1, *b2, *src, *i1, *sink;
322 GstPad *gsink, *gsrc, *gisrc, *gisink, *isink, *isrc, *fsrc, *fsink;
323 GstStateChangeReturn ret;
325 b1 = gst_element_factory_make ("pipeline", NULL);
326 b2 = gst_element_factory_make ("bin", NULL);
327 src = gst_element_factory_make ("fakesrc", NULL);
328 g_object_set (src, "num-buffers", (int) 10, NULL);
329 i1 = gst_element_factory_make ("identity", NULL);
330 sink = gst_element_factory_make ("fakesink", NULL);
332 fail_unless (gst_bin_add (GST_BIN (b2), i1));
333 fail_unless (gst_bin_add (GST_BIN (b1), src));
334 fail_unless (gst_bin_add (GST_BIN (b1), b2));
335 fail_unless (gst_bin_add (GST_BIN (b1), sink));
336 fail_unless (gst_element_link_pads (src, NULL, i1, NULL));
337 fail_unless (gst_element_link_pads (i1, NULL, sink, NULL));
338 GST_OBJECT_LOCK (b2);
339 fail_unless (b2->numsinkpads == 1);
340 fail_unless (GST_IS_GHOST_PAD (b2->sinkpads->data));
341 fail_unless (b2->numsrcpads == 1);
342 fail_unless (GST_IS_GHOST_PAD (b2->srcpads->data));
343 GST_OBJECT_UNLOCK (b2);
345 fsrc = gst_element_get_static_pad (src, "src");
346 fail_unless (fsrc != NULL);
347 gsink = GST_PAD (gst_object_ref (b2->sinkpads->data));
348 fail_unless (gsink != NULL);
349 gsrc = GST_PAD (gst_object_ref (b2->srcpads->data));
350 fail_unless (gsrc != NULL);
351 fsink = gst_element_get_static_pad (sink, "sink");
352 fail_unless (fsink != NULL);
354 isink = gst_element_get_static_pad (i1, "sink");
355 fail_unless (isink != NULL);
356 isrc = gst_element_get_static_pad (i1, "src");
357 fail_unless (isrc != NULL);
358 gisrc = gst_pad_get_peer (isink);
359 fail_unless (gisrc != NULL);
360 gisink = gst_pad_get_peer (isrc);
361 fail_unless (gisink != NULL);
363 /* all objects above have one refcount owned by us as well */
365 ASSERT_OBJECT_REFCOUNT (fsrc, "fsrc", 3); /* parent and gisrc */
366 ASSERT_OBJECT_REFCOUNT (gsink, "gsink", 2); /* parent */
367 ASSERT_OBJECT_REFCOUNT (gsrc, "gsrc", 2); /* parent */
368 ASSERT_OBJECT_REFCOUNT (fsink, "fsink", 3); /* parent and gisink */
370 ASSERT_OBJECT_REFCOUNT (gisrc, "gisrc", 2); /* parent */
371 ASSERT_OBJECT_REFCOUNT (isink, "isink", 3); /* parent and gsink */
372 ASSERT_OBJECT_REFCOUNT (gisink, "gisink", 2); /* parent */
373 ASSERT_OBJECT_REFCOUNT (isrc, "isrc", 3); /* parent and gsrc */
375 ret = gst_element_set_state (b1, GST_STATE_PLAYING);
376 ret = gst_element_get_state (b1, NULL, NULL, GST_CLOCK_TIME_NONE);
377 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
379 ret = gst_element_set_state (b1, GST_STATE_NULL);
380 ret = gst_element_get_state (b1, NULL, NULL, GST_CLOCK_TIME_NONE);
381 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
383 gst_object_unref (b1);
384 /* unreffing the bin will unref all elements, which will unlink and unparent
387 /* wait for thread to settle down */
388 while (GST_OBJECT_REFCOUNT_VALUE (fsrc) > 1)
391 ASSERT_OBJECT_REFCOUNT (fsrc, "fsrc", 1);
392 ASSERT_OBJECT_REFCOUNT (gsink, "gsink", 1);
393 ASSERT_OBJECT_REFCOUNT (gsrc, "gsink", 1);
394 ASSERT_OBJECT_REFCOUNT (fsink, "fsink", 1);
396 ASSERT_OBJECT_REFCOUNT (gisrc, "gisrc", 2); /* gsink */
397 ASSERT_OBJECT_REFCOUNT (isink, "isink", 1); /* gsink */
398 ASSERT_OBJECT_REFCOUNT (gisink, "gisink", 2); /* gsrc */
399 ASSERT_OBJECT_REFCOUNT (isrc, "isrc", 1); /* gsrc */
401 gst_object_unref (gsink);
402 ASSERT_OBJECT_REFCOUNT (isink, "isink", 1);
403 ASSERT_OBJECT_REFCOUNT (gisrc, "gisrc", 1);
404 ASSERT_OBJECT_REFCOUNT (fsrc, "fsrc", 1);
405 gst_object_unref (gisrc);
406 ASSERT_OBJECT_REFCOUNT (fsrc, "fsrc", 1);
408 gst_object_unref (gsrc);
409 ASSERT_OBJECT_REFCOUNT (isrc, "isrc", 1);
410 ASSERT_OBJECT_REFCOUNT (gisink, "gisink", 1);
411 ASSERT_OBJECT_REFCOUNT (fsink, "fsink", 1);
412 gst_object_unref (gisink);
413 ASSERT_OBJECT_REFCOUNT (fsink, "fsink", 1);
415 gst_object_unref (fsrc);
416 gst_object_unref (isrc);
417 gst_object_unref (isink);
418 gst_object_unref (fsink);
423 GST_START_TEST (test_ghost_pads_bin)
430 GstPad *srcpad, *srcghost, *target;
431 GstPad *sinkpad, *sinkghost;
433 pipeline = GST_BIN (gst_pipeline_new ("pipe"));
434 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
436 srcbin = GST_BIN (gst_bin_new ("srcbin"));
437 gst_bin_add (pipeline, GST_ELEMENT (srcbin));
438 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
440 sinkbin = GST_BIN (gst_bin_new ("sinkbin"));
441 gst_bin_add (pipeline, GST_ELEMENT (sinkbin));
442 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
444 src = gst_element_factory_make ("fakesrc", "src");
445 gst_bin_add (srcbin, src);
446 srcpad = gst_element_get_static_pad (src, "src");
447 srcghost = gst_ghost_pad_new ("src", srcpad);
448 gst_object_unref (srcpad);
449 gst_element_add_pad (GST_ELEMENT (srcbin), srcghost);
451 sink = gst_element_factory_make ("fakesink", "sink");
452 gst_bin_add (sinkbin, sink);
453 sinkpad = gst_element_get_static_pad (sink, "sink");
454 sinkghost = gst_ghost_pad_new ("sink", sinkpad);
455 gst_object_unref (sinkpad);
456 gst_element_add_pad (GST_ELEMENT (sinkbin), sinkghost);
458 gst_element_link (GST_ELEMENT (srcbin), GST_ELEMENT (sinkbin));
460 fail_unless (GST_PAD_PEER (srcghost) != NULL);
461 fail_unless (GST_PAD_PEER (sinkghost) != NULL);
462 target = gst_ghost_pad_get_target (GST_GHOST_PAD (srcghost));
463 fail_unless (GST_PAD_PEER (target) != NULL);
464 gst_object_unref (target);
465 target = gst_ghost_pad_get_target (GST_GHOST_PAD (sinkghost));
466 fail_unless (GST_PAD_PEER (target) != NULL);
467 gst_object_unref (target);
469 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
471 gst_object_unref (pipeline);
482 static GstProbeReturn
483 block_callback (GstPad * pad, GstProbeType type, gpointer type_data,
486 BlockData *block_data = (BlockData *) user_data;
488 g_mutex_lock (block_data->mutex);
489 GST_DEBUG ("blocked\n");
490 g_cond_signal (block_data->cond);
491 g_mutex_unlock (block_data->mutex);
496 GST_START_TEST (test_ghost_pads_block)
503 BlockData block_data;
505 pipeline = GST_BIN (gst_pipeline_new ("pipeline"));
507 srcbin = GST_BIN (gst_bin_new ("srcbin"));
508 gst_bin_add (pipeline, GST_ELEMENT (srcbin));
510 src = gst_element_factory_make ("fakesrc", "src");
511 gst_bin_add (srcbin, src);
512 srcpad = gst_element_get_static_pad (src, "src");
513 srcghost = gst_ghost_pad_new ("src", srcpad);
514 gst_element_add_pad (GST_ELEMENT (srcbin), srcghost);
515 gst_object_unref (srcpad);
517 block_data.mutex = g_mutex_new ();
518 block_data.cond = g_cond_new ();
520 g_mutex_lock (block_data.mutex);
521 gst_pad_add_probe (srcghost, GST_PROBE_TYPE_BLOCK, block_callback,
523 gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING);
525 g_cond_wait (block_data.cond, block_data.mutex);
526 gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL);
527 g_mutex_unlock (block_data.mutex);
529 g_mutex_free (block_data.mutex);
530 g_cond_free (block_data.cond);
532 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
533 gst_object_unref (pipeline);
538 GST_START_TEST (test_ghost_pads_probes)
545 BlockData block_data;
547 pipeline = GST_BIN (gst_pipeline_new ("pipeline"));
549 srcbin = GST_BIN (gst_bin_new ("srcbin"));
550 gst_bin_add (pipeline, GST_ELEMENT (srcbin));
552 src = gst_element_factory_make ("fakesrc", "src");
553 gst_bin_add (srcbin, src);
554 srcpad = gst_element_get_static_pad (src, "src");
555 srcghost = gst_ghost_pad_new ("src", srcpad);
556 gst_element_add_pad (GST_ELEMENT (srcbin), srcghost);
557 gst_object_unref (srcpad);
559 block_data.mutex = g_mutex_new ();
560 block_data.cond = g_cond_new ();
562 g_mutex_lock (block_data.mutex);
563 gst_pad_add_probe (srcghost, GST_PROBE_TYPE_BLOCK, block_callback,
565 gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING);
567 g_cond_wait (block_data.cond, block_data.mutex);
568 gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL);
569 g_mutex_unlock (block_data.mutex);
571 g_mutex_free (block_data.mutex);
572 g_cond_free (block_data.cond);
574 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
575 gst_object_unref (pipeline);
580 GST_START_TEST (test_ghost_pads_new_from_template)
582 GstPad *sinkpad, *ghostpad;
583 GstPadTemplate *padtempl, *ghosttempl;
584 GstCaps *padcaps, *ghostcaps, *newcaps;
586 padcaps = gst_caps_from_string ("some/caps");
587 fail_unless (padcaps != NULL);
588 ghostcaps = gst_caps_from_string ("some/caps;some/other-caps");
589 fail_unless (ghostcaps != NULL);
591 padtempl = gst_pad_template_new ("padtempl", GST_PAD_SINK,
592 GST_PAD_ALWAYS, padcaps);
593 fail_unless (padtempl != NULL);
594 ghosttempl = gst_pad_template_new ("ghosttempl", GST_PAD_SINK,
595 GST_PAD_ALWAYS, ghostcaps);
597 sinkpad = gst_pad_new_from_template (padtempl, "sinkpad");
598 fail_unless (sinkpad != NULL);
600 ghostpad = gst_ghost_pad_new_from_template ("ghostpad", sinkpad, ghosttempl);
601 fail_unless (ghostpad != NULL);
603 /* check template is properly set */
604 fail_unless (GST_PAD_PAD_TEMPLATE (ghostpad) == ghosttempl);
606 /* check ghostpad caps are from the sinkpad */
607 newcaps = gst_pad_get_caps (ghostpad, NULL);
608 fail_unless (newcaps != NULL);
609 fail_unless (gst_caps_is_equal (newcaps, padcaps));
610 gst_caps_unref (newcaps);
611 gst_caps_unref (padcaps);
612 gst_caps_unref (ghostcaps);
614 gst_object_unref (sinkpad);
615 gst_object_unref (ghostpad);
617 gst_object_unref (padtempl);
618 gst_object_unref (ghosttempl);
623 GST_START_TEST (test_ghost_pads_new_no_target_from_template)
625 GstPad *sinkpad, *ghostpad;
626 GstPadTemplate *padtempl, *ghosttempl;
627 GstCaps *padcaps, *ghostcaps, *newcaps;
629 padcaps = gst_caps_from_string ("some/caps");
630 fail_unless (padcaps != NULL);
631 ghostcaps = gst_caps_from_string ("some/caps;some/other-caps");
632 fail_unless (ghostcaps != NULL);
634 padtempl = gst_pad_template_new ("padtempl", GST_PAD_SINK,
635 GST_PAD_ALWAYS, padcaps);
636 fail_unless (padtempl != NULL);
637 ghosttempl = gst_pad_template_new ("ghosttempl", GST_PAD_SINK,
638 GST_PAD_ALWAYS, ghostcaps);
640 sinkpad = gst_pad_new_from_template (padtempl, "sinkpad");
641 fail_unless (sinkpad != NULL);
643 ghostpad = gst_ghost_pad_new_no_target_from_template ("ghostpad", ghosttempl);
644 fail_unless (ghostpad != NULL);
646 /* check template is properly set */
647 fail_unless (GST_PAD_PAD_TEMPLATE (ghostpad) == ghosttempl);
649 /* check ghostpad caps are from the ghostpad template */
650 newcaps = gst_pad_get_caps (ghostpad, NULL);
651 fail_unless (newcaps != NULL);
652 fail_unless (gst_caps_is_equal (newcaps, ghostcaps));
653 gst_caps_unref (newcaps);
655 fail_unless (gst_ghost_pad_set_target ((GstGhostPad *) ghostpad, sinkpad));
657 /* check ghostpad caps are now from the target pad */
658 newcaps = gst_pad_get_caps (ghostpad, NULL);
659 fail_unless (newcaps != NULL);
660 fail_unless (gst_caps_is_equal (newcaps, padcaps));
661 gst_caps_unref (newcaps);
663 gst_object_unref (sinkpad);
664 gst_object_unref (ghostpad);
666 gst_object_unref (padtempl);
667 gst_object_unref (ghosttempl);
669 gst_caps_unref (padcaps);
670 gst_caps_unref (ghostcaps);
676 ghost_notify_caps (GObject * object, GParamSpec * pspec, gpointer * user_data)
678 GST_DEBUG ("caps notify called");
679 (*(gint *) user_data)++;
682 GST_START_TEST (test_ghost_pads_forward_setcaps)
684 GstCaps *templ_caps, *caps1, *caps2;
685 GstPadTemplate *src_template, *sink_template;
686 GstPad *src, *ghost, *sink;
687 gint notify_counter = 0;
689 templ_caps = gst_caps_from_string ("meh; muh");
690 src_template = gst_pad_template_new ("src", GST_PAD_SRC,
691 GST_PAD_ALWAYS, templ_caps);
692 gst_caps_unref (templ_caps);
694 templ_caps = gst_caps_from_string ("muh; meh");
695 sink_template = gst_pad_template_new ("sink", GST_PAD_SINK,
696 GST_PAD_ALWAYS, templ_caps);
697 gst_caps_unref (templ_caps);
699 src = gst_pad_new_from_template (src_template, "src");
700 sink = gst_pad_new_from_template (sink_template, "sink");
702 /* ghost source pad, setting caps on the source influences the caps of the
704 ghost = gst_ghost_pad_new ("ghostsrc", src);
705 g_signal_connect (ghost, "notify::caps",
706 G_CALLBACK (ghost_notify_caps), ¬ify_counter);
707 fail_unless (gst_pad_link (ghost, sink) == GST_PAD_LINK_OK);
709 /* Activate pads for caps forwarding/setting to work */
710 gst_pad_set_active (src, TRUE);
711 gst_pad_set_active (ghost, TRUE);
713 caps1 = gst_caps_from_string ("meh");
714 fail_unless (gst_pad_set_caps (src, caps1));
715 caps2 = gst_pad_get_current_caps (ghost);
716 fail_unless (gst_caps_is_equal (caps1, caps2));
717 fail_unless_equals_int (notify_counter, 1);
719 gst_object_unref (ghost);
720 gst_caps_unref (caps1);
721 gst_caps_unref (caps2);
723 /* source 2, setting the caps on the ghostpad does not influence the caps of
726 ghost = gst_ghost_pad_new ("ghostsrc", src);
727 g_signal_connect (ghost, "notify::caps",
728 G_CALLBACK (ghost_notify_caps), ¬ify_counter);
729 fail_unless (gst_pad_link (ghost, sink) == GST_PAD_LINK_OK);
731 gst_pad_set_active (ghost, TRUE);
732 gst_pad_set_active (sink, TRUE);
734 caps1 = gst_caps_from_string ("meh");
735 fail_unless (gst_pad_set_caps (ghost, caps1));
737 caps2 = gst_pad_get_current_caps (src);
738 fail_unless (caps2 == NULL);
740 fail_unless_equals_int (notify_counter, 1);
742 gst_object_unref (ghost);
743 gst_caps_unref (caps1);
746 /* ghost sink pad. Setting caps on the ghostpad will also set those caps on
749 ghost = gst_ghost_pad_new ("ghostsink", sink);
750 g_signal_connect (ghost, "notify::caps",
751 G_CALLBACK (ghost_notify_caps), ¬ify_counter);
752 fail_unless (gst_pad_link (src, ghost) == GST_PAD_LINK_OK);
754 gst_pad_set_active (src, TRUE);
755 gst_pad_set_active (ghost, TRUE);
757 caps1 = gst_caps_from_string ("muh");
758 fail_unless (gst_pad_set_caps (ghost, caps1));
759 caps2 = gst_pad_get_current_caps (sink);
760 fail_unless (gst_caps_is_equal (caps1, caps2));
761 fail_unless_equals_int (notify_counter, 1);
763 gst_object_unref (ghost);
764 gst_caps_unref (caps1);
765 gst_caps_unref (caps2);
767 /* clear caps on pads */
768 gst_pad_set_active (src, FALSE);
769 gst_pad_set_active (src, TRUE);
770 gst_pad_set_active (sink, FALSE);
771 gst_pad_set_active (sink, TRUE);
773 /* sink pad 2, setting caps just on the target pad should not influence the caps
774 * on the ghostpad. */
776 ghost = gst_ghost_pad_new ("ghostsink", sink);
777 fail_unless (gst_pad_get_current_caps (ghost) == NULL);
778 g_signal_connect (ghost, "notify::caps",
779 G_CALLBACK (ghost_notify_caps), ¬ify_counter);
780 fail_unless (gst_pad_link (src, ghost) == GST_PAD_LINK_OK);
782 gst_pad_set_active (ghost, TRUE);
784 caps1 = gst_caps_from_string ("muh");
785 fail_unless (gst_pad_set_caps (sink, caps1));
786 caps2 = gst_pad_get_current_caps (ghost);
787 fail_unless (caps2 == NULL);
788 fail_unless_equals_int (notify_counter, 0);
790 gst_object_unref (ghost);
791 gst_caps_unref (caps1);
793 gst_object_unref (src);
794 gst_object_unref (sink);
795 gst_object_unref (src_template);
796 gst_object_unref (sink_template);
801 static gint linked_count1;
802 static gint unlinked_count1;
803 static gint linked_count2;
804 static gint unlinked_count2;
806 static GstPadLinkReturn
807 pad_linked1 (GstPad * pad, GstPad * peer)
811 return GST_PAD_LINK_OK;
815 pad_unlinked1 (GstPad * pad)
820 static GstPadLinkReturn
821 pad_linked2 (GstPad * pad, GstPad * peer)
825 return GST_PAD_LINK_OK;
829 pad_unlinked2 (GstPad * pad)
834 GST_START_TEST (test_ghost_pads_sink_link_unlink)
837 GstPad *srcpad, *sinkpad, *ghostpad;
838 GstPadTemplate *srctempl, *sinktempl;
839 GstPadLinkReturn ret;
842 padcaps = gst_caps_from_string ("some/caps");
843 fail_unless (padcaps != NULL);
844 srctempl = gst_pad_template_new ("srctempl", GST_PAD_SRC,
845 GST_PAD_ALWAYS, padcaps);
846 gst_caps_unref (padcaps);
848 padcaps = gst_caps_from_string ("some/caps");
849 fail_unless (padcaps != NULL);
850 sinktempl = gst_pad_template_new ("sinktempl", GST_PAD_SINK,
851 GST_PAD_ALWAYS, padcaps);
852 gst_caps_unref (padcaps);
854 srcpad = gst_pad_new_from_template (srctempl, "src");
855 fail_unless (srcpad != NULL);
856 sinkpad = gst_pad_new_from_template (sinktempl, "sink");
857 fail_unless (sinkpad != NULL);
859 /* set up link/unlink functions for the pad */
860 linked_count1 = unlinked_count1 = 0;
861 gst_pad_set_link_function (sinkpad, pad_linked1);
862 gst_pad_set_unlink_function (sinkpad, pad_unlinked1);
863 linked_count2 = unlinked_count2 = 0;
864 gst_pad_set_link_function (srcpad, pad_linked2);
865 gst_pad_set_unlink_function (srcpad, pad_unlinked2);
867 /* this should trigger a link from the internal pad to the sinkpad */
868 ghostpad = gst_ghost_pad_new ("ghostpad", sinkpad);
869 fail_unless (ghostpad != NULL);
870 fail_unless (linked_count1 == 1);
871 fail_unless (unlinked_count1 == 0);
872 fail_unless (linked_count2 == 0);
873 fail_unless (unlinked_count2 == 0);
875 /* this should not trigger anything because we are not directly
876 * linking/unlinking the sink pad. */
877 ret = gst_pad_link (srcpad, ghostpad);
878 fail_unless (ret == GST_PAD_LINK_OK);
879 fail_unless (linked_count1 == 1);
880 fail_unless (unlinked_count1 == 0);
881 fail_unless (linked_count2 == 1);
882 fail_unless (unlinked_count2 == 0);
884 res = gst_pad_unlink (srcpad, ghostpad);
885 fail_unless (res == TRUE);
886 fail_unless (linked_count1 == 1);
887 fail_unless (unlinked_count1 == 0);
888 fail_unless (linked_count2 == 1);
889 fail_unless (unlinked_count2 == 1);
891 /* this should trigger the unlink */
892 res = gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (ghostpad), NULL);
893 fail_unless (res == TRUE);
894 fail_unless (linked_count1 == 1);
895 fail_unless (unlinked_count1 == 1);
896 fail_unless (linked_count2 == 1);
897 fail_unless (unlinked_count2 == 1);
899 gst_object_unref (ghostpad);
900 gst_object_unref (sinkpad);
901 gst_object_unref (srcpad);
902 gst_object_unref (srctempl);
903 gst_object_unref (sinktempl);
908 GST_START_TEST (test_ghost_pads_src_link_unlink)
911 GstPad *srcpad, *sinkpad, *ghostpad, *dummy;
912 GstPadTemplate *srctempl, *sinktempl;
913 GstPadLinkReturn ret;
916 padcaps = gst_caps_from_string ("some/caps");
917 fail_unless (padcaps != NULL);
918 srctempl = gst_pad_template_new ("srctempl", GST_PAD_SRC,
919 GST_PAD_ALWAYS, padcaps);
920 gst_caps_unref (padcaps);
922 padcaps = gst_caps_from_string ("some/caps");
923 fail_unless (padcaps != NULL);
924 sinktempl = gst_pad_template_new ("sinktempl", GST_PAD_SINK,
925 GST_PAD_ALWAYS, padcaps);
926 gst_caps_unref (padcaps);
928 srcpad = gst_pad_new_from_template (srctempl, "src");
929 fail_unless (srcpad != NULL);
930 sinkpad = gst_pad_new_from_template (sinktempl, "sink");
931 fail_unless (sinkpad != NULL);
933 /* set up link/unlink functions for the pad */
934 linked_count1 = unlinked_count1 = 0;
935 gst_pad_set_link_function (srcpad, pad_linked1);
936 gst_pad_set_unlink_function (srcpad, pad_unlinked1);
937 linked_count2 = unlinked_count2 = 0;
938 gst_pad_set_link_function (sinkpad, pad_linked2);
939 gst_pad_set_unlink_function (sinkpad, pad_unlinked2);
941 /* this should trigger a link from the internal pad to the srcpad */
942 ghostpad = gst_ghost_pad_new ("ghostpad", srcpad);
943 fail_unless (ghostpad != NULL);
944 fail_unless (linked_count1 == 1);
945 fail_unless (unlinked_count1 == 0);
946 fail_unless (linked_count2 == 0);
947 fail_unless (unlinked_count2 == 0);
949 /* this should fail with a critial */
950 ASSERT_CRITICAL (dummy = gst_ghost_pad_new ("ghostpad", srcpad));
951 fail_unless (dummy == NULL);
952 fail_unless (linked_count1 == 1);
953 fail_unless (unlinked_count1 == 0);
954 fail_unless (linked_count2 == 0);
955 fail_unless (unlinked_count2 == 0);
957 /* this should not trigger anything because we are not directly
958 * linking/unlinking the src pad. */
959 ret = gst_pad_link (ghostpad, sinkpad);
960 fail_unless (ret == GST_PAD_LINK_OK);
961 fail_unless (linked_count1 == 1);
962 fail_unless (unlinked_count1 == 0);
963 fail_unless (linked_count2 == 1);
964 fail_unless (unlinked_count2 == 0);
966 /* this link should fail because we are already linked. Let's make sure the
967 * link functions are not called */
968 ret = gst_pad_link (ghostpad, sinkpad);
969 fail_unless (ret == GST_PAD_LINK_WAS_LINKED);
970 fail_unless (linked_count1 == 1);
971 fail_unless (unlinked_count1 == 0);
972 fail_unless (linked_count2 == 1);
973 fail_unless (unlinked_count2 == 0);
975 res = gst_pad_unlink (ghostpad, sinkpad);
976 fail_unless (res == TRUE);
977 fail_unless (linked_count1 == 1);
978 fail_unless (unlinked_count1 == 0);
979 fail_unless (linked_count2 == 1);
980 fail_unless (unlinked_count2 == 1);
982 res = gst_pad_unlink (ghostpad, sinkpad);
983 fail_unless (res == FALSE);
984 fail_unless (linked_count1 == 1);
985 fail_unless (unlinked_count1 == 0);
986 fail_unless (linked_count2 == 1);
987 fail_unless (unlinked_count2 == 1);
989 /* this should trigger the unlink function */
990 res = gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (ghostpad), NULL);
991 fail_unless (res == TRUE);
992 fail_unless (linked_count1 == 1);
993 fail_unless (unlinked_count1 == 1);
994 fail_unless (linked_count2 == 1);
995 fail_unless (unlinked_count2 == 1);
997 /* and this the link function again */
998 res = gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (ghostpad), srcpad);
999 fail_unless (res == TRUE);
1000 fail_unless (linked_count1 == 2);
1001 fail_unless (unlinked_count1 == 1);
1002 fail_unless (linked_count2 == 1);
1003 fail_unless (unlinked_count2 == 1);
1005 gst_object_unref (ghostpad);
1006 gst_object_unref (sinkpad);
1007 gst_object_unref (srcpad);
1008 gst_object_unref (srctempl);
1009 gst_object_unref (sinktempl);
1014 GST_START_TEST (test_ghost_pads_change_when_linked)
1016 GstElement *b1, *b2, *src, *fmt, *sink1, *sink2;
1017 GstPad *sinkpad, *ghostpad;
1020 b1 = gst_element_factory_make ("pipeline", NULL);
1021 b2 = gst_element_factory_make ("bin", NULL);
1022 src = gst_element_factory_make ("fakesrc", NULL);
1023 fmt = gst_element_factory_make ("capsfilter", NULL);
1024 sink1 = gst_element_factory_make ("fakesink", NULL);
1025 sink2 = gst_element_factory_make ("fakesink", NULL);
1027 gst_bin_add (GST_BIN (b2), sink1);
1028 gst_bin_add (GST_BIN (b2), sink2);
1029 gst_bin_add (GST_BIN (b1), src);
1030 gst_bin_add (GST_BIN (b1), fmt);
1031 gst_bin_add (GST_BIN (b1), b2);
1033 caps = gst_caps_from_string ("audio/x-raw-int, width=16, channels=1");
1034 g_object_set (fmt, "caps", caps, NULL);
1035 gst_caps_unref (caps);
1037 /* create the ghostpad as a sink-pad for bin 2 */
1038 ghostpad = gst_ghost_pad_new_no_target ("sink", GST_PAD_SINK);
1039 gst_element_add_pad (b2, ghostpad);
1041 sinkpad = gst_element_get_static_pad (sink1, "sink");
1042 fail_unless (gst_ghost_pad_set_target ((GstGhostPad *) ghostpad, sinkpad));
1043 gst_object_unref (sinkpad);
1045 fail_unless (gst_element_link_many (src, fmt, b2, NULL));
1047 /* set different target after ghostpad is linked */
1048 sinkpad = gst_element_get_static_pad (sink2, "sink");
1049 fail_unless (gst_ghost_pad_set_target ((GstGhostPad *) ghostpad, sinkpad));
1050 gst_object_unref (sinkpad);
1053 gst_object_unref (b1);
1060 gst_ghost_pad_suite (void)
1062 Suite *s = suite_create ("GstGhostPad");
1064 TCase *tc_chain = tcase_create ("ghost pad tests");
1066 suite_add_tcase (s, tc_chain);
1067 tcase_add_test (tc_chain, test_remove1);
1068 tcase_add_test (tc_chain, test_remove2);
1069 tcase_add_test (tc_chain, test_remove_target);
1070 tcase_add_test (tc_chain, test_link);
1071 tcase_add_test (tc_chain, test_ghost_pads);
1072 tcase_add_test (tc_chain, test_ghost_pads_bin);
1073 tcase_add_test (tc_chain, test_ghost_pads_notarget);
1074 tcase_add_test (tc_chain, test_ghost_pads_block);
1075 tcase_add_test (tc_chain, test_ghost_pads_probes);
1076 tcase_add_test (tc_chain, test_ghost_pads_new_from_template);
1077 tcase_add_test (tc_chain, test_ghost_pads_new_no_target_from_template);
1078 tcase_add_test (tc_chain, test_ghost_pads_forward_setcaps);
1079 tcase_add_test (tc_chain, test_ghost_pads_sink_link_unlink);
1080 tcase_add_test (tc_chain, test_ghost_pads_src_link_unlink);
1081 tcase_add_test (tc_chain, test_ghost_pads_change_when_linked);
1086 GST_CHECK_MAIN (gst_ghost_pad);