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);
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);
249 /* test if linking fails over different bins using a pipeline
252 * fakesrc num_buffers=10 ! ( fakesink )
255 GST_START_TEST (test_link)
257 GstElement *b1, *b2, *src, *sink;
258 GstPad *srcpad, *sinkpad, *gpad, *ppad, *tmp;
259 GstPadLinkReturn ret;
261 b1 = gst_element_factory_make ("pipeline", NULL);
262 b2 = gst_element_factory_make ("bin", NULL);
263 src = gst_element_factory_make ("fakesrc", NULL);
264 sink = gst_element_factory_make ("fakesink", NULL);
266 fail_unless (gst_bin_add (GST_BIN (b2), sink));
267 fail_unless (gst_bin_add (GST_BIN (b1), src));
268 fail_unless (gst_bin_add (GST_BIN (b1), b2));
270 srcpad = gst_element_get_static_pad (src, "src");
271 fail_unless (srcpad != NULL);
272 sinkpad = gst_element_get_static_pad (sink, "sink");
273 fail_unless (sinkpad != NULL);
275 /* linking in different hierarchies should fail */
276 ret = gst_pad_link (srcpad, sinkpad);
277 fail_unless (ret == GST_PAD_LINK_WRONG_HIERARCHY);
279 /* now setup a ghostpad */
280 gpad = gst_ghost_pad_new ("sink", sinkpad);
282 /* Check if the internal pads are set correctly */
283 ppad = GST_PAD (gst_proxy_pad_get_internal (GST_PROXY_PAD (gpad)));
284 fail_unless (ppad == GST_PAD_PEER (sinkpad));
285 tmp = GST_PAD (gst_proxy_pad_get_internal (GST_PROXY_PAD (ppad)));
286 fail_unless (tmp == gpad);
287 gst_object_unref (tmp);
288 gst_object_unref (ppad);
289 gst_object_unref (sinkpad);
290 /* need to ref as _add_pad takes ownership */
291 gst_object_ref (gpad);
292 gst_element_add_pad (b2, gpad);
294 /* our new sinkpad */
297 /* and linking should work now */
298 ret = gst_pad_link (srcpad, sinkpad);
299 fail_unless (ret == GST_PAD_LINK_OK);
301 /* flush the message, dropping the b1 refcount to 1 */
302 gst_element_set_state (b1, GST_STATE_READY);
303 gst_element_set_state (b1, GST_STATE_NULL);
304 ASSERT_OBJECT_REFCOUNT (b1, "pipeline", 1);
306 gst_object_unref (srcpad);
307 gst_object_unref (sinkpad);
308 gst_object_unref (b1);
313 /* test if ghostpads are created automagically when using
314 * gst_element_link_pads.
316 * fakesrc num_buffers=10 ! ( identity ) ! fakesink
318 GST_START_TEST (test_ghost_pads)
320 GstElement *b1, *b2, *src, *i1, *sink;
321 GstPad *gsink, *gsrc, *gisrc, *gisink, *isink, *isrc, *fsrc, *fsink;
322 GstStateChangeReturn ret;
324 b1 = gst_element_factory_make ("pipeline", NULL);
325 b2 = gst_element_factory_make ("bin", NULL);
326 src = gst_element_factory_make ("fakesrc", NULL);
327 g_object_set (src, "num-buffers", (int) 10, NULL);
328 i1 = gst_element_factory_make ("identity", NULL);
329 sink = gst_element_factory_make ("fakesink", NULL);
331 fail_unless (gst_bin_add (GST_BIN (b2), i1));
332 fail_unless (gst_bin_add (GST_BIN (b1), src));
333 fail_unless (gst_bin_add (GST_BIN (b1), b2));
334 fail_unless (gst_bin_add (GST_BIN (b1), sink));
335 fail_unless (gst_element_link_pads (src, NULL, i1, NULL));
336 fail_unless (gst_element_link_pads (i1, NULL, sink, NULL));
337 GST_OBJECT_LOCK (b2);
338 fail_unless (b2->numsinkpads == 1);
339 fail_unless (GST_IS_GHOST_PAD (b2->sinkpads->data));
340 fail_unless (b2->numsrcpads == 1);
341 fail_unless (GST_IS_GHOST_PAD (b2->srcpads->data));
342 GST_OBJECT_UNLOCK (b2);
344 fsrc = gst_element_get_static_pad (src, "src");
345 fail_unless (fsrc != NULL);
346 gsink = GST_PAD (gst_object_ref (b2->sinkpads->data));
347 fail_unless (gsink != NULL);
348 gsrc = GST_PAD (gst_object_ref (b2->srcpads->data));
349 fail_unless (gsrc != NULL);
350 fsink = gst_element_get_static_pad (sink, "sink");
351 fail_unless (fsink != NULL);
353 isink = gst_element_get_static_pad (i1, "sink");
354 fail_unless (isink != NULL);
355 isrc = gst_element_get_static_pad (i1, "src");
356 fail_unless (isrc != NULL);
357 gisrc = gst_pad_get_peer (isink);
358 fail_unless (gisrc != NULL);
359 gisink = gst_pad_get_peer (isrc);
360 fail_unless (gisink != NULL);
362 /* all objects above have one refcount owned by us as well */
364 ASSERT_OBJECT_REFCOUNT (fsrc, "fsrc", 3); /* parent and gisrc */
365 ASSERT_OBJECT_REFCOUNT (gsink, "gsink", 2); /* parent */
366 ASSERT_OBJECT_REFCOUNT (gsrc, "gsrc", 2); /* parent */
367 ASSERT_OBJECT_REFCOUNT (fsink, "fsink", 3); /* parent and gisink */
369 ASSERT_OBJECT_REFCOUNT (gisrc, "gisrc", 2); /* parent */
370 ASSERT_OBJECT_REFCOUNT (isink, "isink", 3); /* parent and gsink */
371 ASSERT_OBJECT_REFCOUNT (gisink, "gisink", 2); /* parent */
372 ASSERT_OBJECT_REFCOUNT (isrc, "isrc", 3); /* parent and gsrc */
374 ret = gst_element_set_state (b1, GST_STATE_PLAYING);
375 ret = gst_element_get_state (b1, NULL, NULL, GST_CLOCK_TIME_NONE);
376 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
378 ret = gst_element_set_state (b1, GST_STATE_NULL);
379 ret = gst_element_get_state (b1, NULL, NULL, GST_CLOCK_TIME_NONE);
380 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
382 gst_object_unref (b1);
383 /* unreffing the bin will unref all elements, which will unlink and unparent
386 /* wait for thread to settle down */
387 while (GST_OBJECT_REFCOUNT_VALUE (fsrc) > 1)
390 ASSERT_OBJECT_REFCOUNT (fsrc, "fsrc", 1);
391 ASSERT_OBJECT_REFCOUNT (gsink, "gsink", 1);
392 ASSERT_OBJECT_REFCOUNT (gsrc, "gsink", 1);
393 ASSERT_OBJECT_REFCOUNT (fsink, "fsink", 1);
395 ASSERT_OBJECT_REFCOUNT (gisrc, "gisrc", 2); /* gsink */
396 ASSERT_OBJECT_REFCOUNT (isink, "isink", 1); /* gsink */
397 ASSERT_OBJECT_REFCOUNT (gisink, "gisink", 2); /* gsrc */
398 ASSERT_OBJECT_REFCOUNT (isrc, "isrc", 1); /* gsrc */
400 gst_object_unref (gsink);
401 ASSERT_OBJECT_REFCOUNT (isink, "isink", 1);
402 ASSERT_OBJECT_REFCOUNT (gisrc, "gisrc", 1);
403 ASSERT_OBJECT_REFCOUNT (fsrc, "fsrc", 1);
404 gst_object_unref (gisrc);
405 ASSERT_OBJECT_REFCOUNT (fsrc, "fsrc", 1);
407 gst_object_unref (gsrc);
408 ASSERT_OBJECT_REFCOUNT (isrc, "isrc", 1);
409 ASSERT_OBJECT_REFCOUNT (gisink, "gisink", 1);
410 ASSERT_OBJECT_REFCOUNT (fsink, "fsink", 1);
411 gst_object_unref (gisink);
412 ASSERT_OBJECT_REFCOUNT (fsink, "fsink", 1);
414 gst_object_unref (fsrc);
415 gst_object_unref (isrc);
416 gst_object_unref (isink);
417 gst_object_unref (fsink);
422 GST_START_TEST (test_ghost_pads_bin)
429 GstPad *srcpad, *srcghost, *target;
430 GstPad *sinkpad, *sinkghost;
432 pipeline = GST_BIN (gst_pipeline_new ("pipe"));
433 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
435 srcbin = GST_BIN (gst_bin_new ("srcbin"));
436 gst_bin_add (pipeline, GST_ELEMENT (srcbin));
437 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
439 sinkbin = GST_BIN (gst_bin_new ("sinkbin"));
440 gst_bin_add (pipeline, GST_ELEMENT (sinkbin));
441 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
443 src = gst_element_factory_make ("fakesrc", "src");
444 gst_bin_add (srcbin, src);
445 srcpad = gst_element_get_static_pad (src, "src");
446 srcghost = gst_ghost_pad_new ("src", srcpad);
447 gst_object_unref (srcpad);
448 gst_element_add_pad (GST_ELEMENT (srcbin), srcghost);
450 sink = gst_element_factory_make ("fakesink", "sink");
451 gst_bin_add (sinkbin, sink);
452 sinkpad = gst_element_get_static_pad (sink, "sink");
453 sinkghost = gst_ghost_pad_new ("sink", sinkpad);
454 gst_object_unref (sinkpad);
455 gst_element_add_pad (GST_ELEMENT (sinkbin), sinkghost);
457 gst_element_link (GST_ELEMENT (srcbin), GST_ELEMENT (sinkbin));
459 fail_unless (GST_PAD_PEER (srcghost) != NULL);
460 fail_unless (GST_PAD_PEER (sinkghost) != NULL);
461 target = gst_ghost_pad_get_target (GST_GHOST_PAD (srcghost));
462 fail_unless (GST_PAD_PEER (target) != NULL);
463 gst_object_unref (target);
464 target = gst_ghost_pad_get_target (GST_GHOST_PAD (sinkghost));
465 fail_unless (GST_PAD_PEER (target) != NULL);
466 gst_object_unref (target);
468 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
470 gst_object_unref (pipeline);
482 block_callback (GstPad * pad, gboolean blocked, gpointer user_data)
484 BlockData *block_data = (BlockData *) user_data;
486 g_mutex_lock (block_data->mutex);
487 GST_DEBUG ("blocked\n");
488 g_cond_signal (block_data->cond);
489 g_mutex_unlock (block_data->mutex);
492 GST_START_TEST (test_ghost_pads_block)
499 BlockData block_data;
501 pipeline = GST_BIN (gst_pipeline_new ("pipeline"));
503 srcbin = GST_BIN (gst_bin_new ("srcbin"));
504 gst_bin_add (pipeline, GST_ELEMENT (srcbin));
506 src = gst_element_factory_make ("fakesrc", "src");
507 gst_bin_add (srcbin, src);
508 srcpad = gst_element_get_static_pad (src, "src");
509 srcghost = gst_ghost_pad_new ("src", srcpad);
510 gst_element_add_pad (GST_ELEMENT (srcbin), srcghost);
511 gst_object_unref (srcpad);
513 block_data.mutex = g_mutex_new ();
514 block_data.cond = g_cond_new ();
516 g_mutex_lock (block_data.mutex);
517 gst_pad_set_blocked_async (srcghost, TRUE, block_callback, &block_data);
518 gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING);
520 g_cond_wait (block_data.cond, block_data.mutex);
521 gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL);
522 g_mutex_unlock (block_data.mutex);
524 g_mutex_free (block_data.mutex);
525 g_cond_free (block_data.cond);
527 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
528 gst_object_unref (pipeline);
533 GST_START_TEST (test_ghost_pads_probes)
540 BlockData block_data;
542 pipeline = GST_BIN (gst_pipeline_new ("pipeline"));
544 srcbin = GST_BIN (gst_bin_new ("srcbin"));
545 gst_bin_add (pipeline, GST_ELEMENT (srcbin));
547 src = gst_element_factory_make ("fakesrc", "src");
548 gst_bin_add (srcbin, src);
549 srcpad = gst_element_get_static_pad (src, "src");
550 srcghost = gst_ghost_pad_new ("src", srcpad);
551 gst_element_add_pad (GST_ELEMENT (srcbin), srcghost);
552 gst_object_unref (srcpad);
554 block_data.mutex = g_mutex_new ();
555 block_data.cond = g_cond_new ();
557 g_mutex_lock (block_data.mutex);
558 gst_pad_set_blocked_async (srcghost, TRUE, block_callback, &block_data);
559 gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING);
561 g_cond_wait (block_data.cond, block_data.mutex);
562 gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL);
563 g_mutex_unlock (block_data.mutex);
565 g_mutex_free (block_data.mutex);
566 g_cond_free (block_data.cond);
568 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
569 gst_object_unref (pipeline);
574 GST_START_TEST (test_ghost_pads_new_from_template)
576 GstPad *sinkpad, *ghostpad;
577 GstPadTemplate *padtempl, *ghosttempl;
578 GstCaps *padcaps, *ghostcaps, *newcaps;
579 GstCaps *copypadcaps;
581 padcaps = gst_caps_from_string ("some/caps");
582 fail_unless (padcaps != NULL);
583 ghostcaps = gst_caps_from_string ("some/caps;some/other-caps");
584 fail_unless (ghostcaps != NULL);
586 copypadcaps = gst_caps_copy (padcaps);
587 padtempl = gst_pad_template_new ("padtempl", GST_PAD_SINK,
588 GST_PAD_ALWAYS, copypadcaps);
589 fail_unless (padtempl != NULL);
590 ghosttempl = gst_pad_template_new ("ghosttempl", GST_PAD_SINK,
591 GST_PAD_ALWAYS, ghostcaps);
593 sinkpad = gst_pad_new_from_template (padtempl, "sinkpad");
594 fail_unless (sinkpad != NULL);
596 ghostpad = gst_ghost_pad_new_from_template ("ghostpad", sinkpad, ghosttempl);
597 fail_unless (ghostpad != NULL);
599 /* check template is properly set */
600 fail_unless (GST_PAD_PAD_TEMPLATE (ghostpad) == ghosttempl);
602 /* check ghostpad caps are from the sinkpad */
603 newcaps = gst_pad_get_caps (ghostpad);
604 fail_unless (newcaps != NULL);
605 fail_unless (gst_caps_is_equal (newcaps, padcaps));
606 gst_caps_unref (newcaps);
607 gst_caps_unref (padcaps);
609 gst_object_unref (sinkpad);
610 gst_object_unref (ghostpad);
612 gst_object_unref (padtempl);
613 gst_object_unref (ghosttempl);
618 GST_START_TEST (test_ghost_pads_new_no_target_from_template)
620 GstPad *sinkpad, *ghostpad;
621 GstPadTemplate *padtempl, *ghosttempl;
622 GstCaps *padcaps, *ghostcaps, *newcaps;
623 GstCaps *copypadcaps, *copyghostcaps;
625 padcaps = gst_caps_from_string ("some/caps");
626 fail_unless (padcaps != NULL);
627 ghostcaps = gst_caps_from_string ("some/caps;some/other-caps");
628 fail_unless (ghostcaps != NULL);
630 copypadcaps = gst_caps_copy (padcaps);
631 copyghostcaps = gst_caps_copy (ghostcaps);
633 padtempl = gst_pad_template_new ("padtempl", GST_PAD_SINK,
634 GST_PAD_ALWAYS, copypadcaps);
635 fail_unless (padtempl != NULL);
636 ghosttempl = gst_pad_template_new ("ghosttempl", GST_PAD_SINK,
637 GST_PAD_ALWAYS, copyghostcaps);
639 sinkpad = gst_pad_new_from_template (padtempl, "sinkpad");
640 fail_unless (sinkpad != NULL);
642 ghostpad = gst_ghost_pad_new_no_target_from_template ("ghostpad", ghosttempl);
643 fail_unless (ghostpad != NULL);
645 /* check template is properly set */
646 fail_unless (GST_PAD_PAD_TEMPLATE (ghostpad) == ghosttempl);
648 /* check ghostpad caps are from the ghostpad template */
649 newcaps = gst_pad_get_caps (ghostpad);
650 fail_unless (newcaps != NULL);
651 fail_unless (gst_caps_is_equal (newcaps, ghostcaps));
652 gst_caps_unref (newcaps);
654 fail_unless (gst_ghost_pad_set_target ((GstGhostPad *) ghostpad, sinkpad));
656 /* check ghostpad caps are now from the target pad */
657 newcaps = gst_pad_get_caps (ghostpad);
658 fail_unless (newcaps != NULL);
659 fail_unless (gst_caps_is_equal (newcaps, padcaps));
660 gst_caps_unref (newcaps);
662 gst_object_unref (sinkpad);
663 gst_object_unref (ghostpad);
665 gst_object_unref (padtempl);
666 gst_object_unref (ghosttempl);
668 gst_caps_unref (padcaps);
669 gst_caps_unref (ghostcaps);
675 ghost_notify_caps (GObject * object, GParamSpec * pspec, gpointer * user_data)
677 GST_DEBUG ("caps notify called");
678 (*(gint *) user_data)++;
681 GST_START_TEST (test_ghost_pads_forward_setcaps)
683 GstCaps *templ_caps, *caps1, *caps2;
684 GstPadTemplate *src_template, *sink_template;
685 GstPad *src, *ghost, *sink;
686 gint notify_counter = 0;
688 templ_caps = gst_caps_from_string ("meh; muh");
689 src_template = gst_pad_template_new ("src", GST_PAD_SRC,
690 GST_PAD_ALWAYS, templ_caps);
692 templ_caps = gst_caps_from_string ("muh; meh");
693 sink_template = gst_pad_template_new ("sink", GST_PAD_SINK,
694 GST_PAD_ALWAYS, templ_caps);
696 src = gst_pad_new_from_template (src_template, "src");
697 sink = gst_pad_new_from_template (sink_template, "sink");
699 /* ghost source pad, setting caps on the source influences the caps of the
701 ghost = gst_ghost_pad_new ("ghostsrc", src);
702 g_signal_connect (ghost, "notify::caps",
703 G_CALLBACK (ghost_notify_caps), ¬ify_counter);
704 fail_unless (gst_pad_link (ghost, sink) == GST_PAD_LINK_OK);
706 caps1 = gst_caps_from_string ("meh");
707 fail_unless (gst_pad_set_caps (src, caps1));
708 caps2 = GST_PAD_CAPS (ghost);
709 fail_unless (gst_caps_is_equal (caps1, caps2));
710 fail_unless_equals_int (notify_counter, 1);
712 gst_object_unref (ghost);
713 gst_caps_unref (caps1);
715 fail_unless (gst_pad_set_caps (src, NULL));
717 /* source 2, setting the caps on the ghostpad does not influence the caps of
720 ghost = gst_ghost_pad_new ("ghostsrc", src);
721 g_signal_connect (ghost, "notify::caps",
722 G_CALLBACK (ghost_notify_caps), ¬ify_counter);
723 fail_unless (gst_pad_link (ghost, sink) == GST_PAD_LINK_OK);
725 caps1 = gst_caps_from_string ("meh");
726 fail_unless (gst_pad_set_caps (ghost, caps1));
727 caps2 = GST_PAD_CAPS (src);
728 fail_unless (caps2 == NULL);
729 fail_unless_equals_int (notify_counter, 1);
731 gst_object_unref (ghost);
732 gst_caps_unref (caps1);
735 /* ghost sink pad. Setting caps on the ghostpad will also set those caps on
738 ghost = gst_ghost_pad_new ("ghostsink", sink);
739 g_signal_connect (ghost, "notify::caps",
740 G_CALLBACK (ghost_notify_caps), ¬ify_counter);
741 fail_unless (gst_pad_link (src, ghost) == GST_PAD_LINK_OK);
743 caps1 = gst_caps_from_string ("muh");
744 fail_unless (gst_pad_set_caps (ghost, caps1));
745 caps2 = GST_PAD_CAPS (sink);
746 fail_unless (gst_caps_is_equal (caps1, caps2));
747 fail_unless_equals_int (notify_counter, 1);
749 gst_object_unref (ghost);
750 gst_caps_unref (caps1);
752 /* sink pad 2, setting caps just on the target pad should not influence the caps
753 * on the ghostpad. */
755 ghost = gst_ghost_pad_new ("ghostsink", sink);
756 g_signal_connect (ghost, "notify::caps",
757 G_CALLBACK (ghost_notify_caps), ¬ify_counter);
758 fail_unless (gst_pad_link (src, ghost) == GST_PAD_LINK_OK);
760 caps1 = gst_caps_from_string ("muh");
761 fail_unless (gst_pad_set_caps (sink, caps1));
762 caps2 = GST_PAD_CAPS (ghost);
763 fail_unless (caps2 == NULL);
764 fail_unless_equals_int (notify_counter, 0);
766 gst_object_unref (ghost);
767 gst_caps_unref (caps1);
769 gst_object_unref (src);
770 gst_object_unref (sink);
771 gst_object_unref (src_template);
772 gst_object_unref (sink_template);
777 static gint linked_count1;
778 static gint unlinked_count1;
779 static gint linked_count2;
780 static gint unlinked_count2;
782 static GstPadLinkReturn
783 pad_linked1 (GstPad * pad, GstPad * peer)
787 return GST_PAD_LINK_OK;
791 pad_unlinked1 (GstPad * pad)
796 static GstPadLinkReturn
797 pad_linked2 (GstPad * pad, GstPad * peer)
801 return GST_PAD_LINK_OK;
805 pad_unlinked2 (GstPad * pad)
810 GST_START_TEST (test_ghost_pads_sink_link_unlink)
813 GstPad *srcpad, *sinkpad, *ghostpad;
814 GstPadTemplate *srctempl, *sinktempl;
815 GstPadLinkReturn ret;
818 padcaps = gst_caps_from_string ("some/caps");
819 fail_unless (padcaps != NULL);
820 srctempl = gst_pad_template_new ("srctempl", GST_PAD_SRC,
821 GST_PAD_ALWAYS, padcaps);
823 padcaps = gst_caps_from_string ("some/caps");
824 fail_unless (padcaps != NULL);
825 sinktempl = gst_pad_template_new ("sinktempl", GST_PAD_SINK,
826 GST_PAD_ALWAYS, padcaps);
828 srcpad = gst_pad_new_from_template (srctempl, "src");
829 fail_unless (srcpad != NULL);
830 sinkpad = gst_pad_new_from_template (sinktempl, "sink");
831 fail_unless (sinkpad != NULL);
833 /* set up link/unlink functions for the pad */
834 linked_count1 = unlinked_count1 = 0;
835 gst_pad_set_link_function (sinkpad, pad_linked1);
836 gst_pad_set_unlink_function (sinkpad, pad_unlinked1);
837 linked_count2 = unlinked_count2 = 0;
838 gst_pad_set_link_function (srcpad, pad_linked2);
839 gst_pad_set_unlink_function (srcpad, pad_unlinked2);
841 /* this should trigger a link from the internal pad to the sinkpad */
842 ghostpad = gst_ghost_pad_new ("ghostpad", sinkpad);
843 fail_unless (ghostpad != NULL);
844 fail_unless (linked_count1 == 1);
845 fail_unless (unlinked_count1 == 0);
846 fail_unless (linked_count2 == 0);
847 fail_unless (unlinked_count2 == 0);
849 /* this should not trigger anything because we are not directly
850 * linking/unlinking the sink pad. */
851 ret = gst_pad_link (srcpad, ghostpad);
852 fail_unless (ret == GST_PAD_LINK_OK);
853 fail_unless (linked_count1 == 1);
854 fail_unless (unlinked_count1 == 0);
855 fail_unless (linked_count2 == 1);
856 fail_unless (unlinked_count2 == 0);
858 res = gst_pad_unlink (srcpad, ghostpad);
859 fail_unless (res == TRUE);
860 fail_unless (linked_count1 == 1);
861 fail_unless (unlinked_count1 == 0);
862 fail_unless (linked_count2 == 1);
863 fail_unless (unlinked_count2 == 1);
865 /* this should trigger the unlink */
866 res = gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (ghostpad), NULL);
867 fail_unless (res == TRUE);
868 fail_unless (linked_count1 == 1);
869 fail_unless (unlinked_count1 == 1);
870 fail_unless (linked_count2 == 1);
871 fail_unless (unlinked_count2 == 1);
873 gst_object_unref (ghostpad);
874 gst_object_unref (sinkpad);
875 gst_object_unref (srcpad);
876 gst_object_unref (srctempl);
877 gst_object_unref (sinktempl);
882 GST_START_TEST (test_ghost_pads_src_link_unlink)
885 GstPad *srcpad, *sinkpad, *ghostpad, *dummy;
886 GstPadTemplate *srctempl, *sinktempl;
887 GstPadLinkReturn ret;
890 padcaps = gst_caps_from_string ("some/caps");
891 fail_unless (padcaps != NULL);
892 srctempl = gst_pad_template_new ("srctempl", GST_PAD_SRC,
893 GST_PAD_ALWAYS, padcaps);
895 padcaps = gst_caps_from_string ("some/caps");
896 fail_unless (padcaps != NULL);
897 sinktempl = gst_pad_template_new ("sinktempl", GST_PAD_SINK,
898 GST_PAD_ALWAYS, padcaps);
900 srcpad = gst_pad_new_from_template (srctempl, "src");
901 fail_unless (srcpad != NULL);
902 sinkpad = gst_pad_new_from_template (sinktempl, "sink");
903 fail_unless (sinkpad != NULL);
905 /* set up link/unlink functions for the pad */
906 linked_count1 = unlinked_count1 = 0;
907 gst_pad_set_link_function (srcpad, pad_linked1);
908 gst_pad_set_unlink_function (srcpad, pad_unlinked1);
909 linked_count2 = unlinked_count2 = 0;
910 gst_pad_set_link_function (sinkpad, pad_linked2);
911 gst_pad_set_unlink_function (sinkpad, pad_unlinked2);
913 /* this should trigger a link from the internal pad to the srcpad */
914 ghostpad = gst_ghost_pad_new ("ghostpad", srcpad);
915 fail_unless (ghostpad != NULL);
916 fail_unless (linked_count1 == 1);
917 fail_unless (unlinked_count1 == 0);
918 fail_unless (linked_count2 == 0);
919 fail_unless (unlinked_count2 == 0);
921 /* this should fail with a critial */
922 ASSERT_CRITICAL (dummy = gst_ghost_pad_new ("ghostpad", srcpad));
923 fail_unless (dummy == NULL);
924 fail_unless (linked_count1 == 1);
925 fail_unless (unlinked_count1 == 0);
926 fail_unless (linked_count2 == 0);
927 fail_unless (unlinked_count2 == 0);
929 /* this should not trigger anything because we are not directly
930 * linking/unlinking the src pad. */
931 ret = gst_pad_link (ghostpad, sinkpad);
932 fail_unless (ret == GST_PAD_LINK_OK);
933 fail_unless (linked_count1 == 1);
934 fail_unless (unlinked_count1 == 0);
935 fail_unless (linked_count2 == 1);
936 fail_unless (unlinked_count2 == 0);
938 /* this link should fail because we are already linked. Let's make sure the
939 * link functions are not called */
940 ret = gst_pad_link (ghostpad, sinkpad);
941 fail_unless (ret == GST_PAD_LINK_WAS_LINKED);
942 fail_unless (linked_count1 == 1);
943 fail_unless (unlinked_count1 == 0);
944 fail_unless (linked_count2 == 1);
945 fail_unless (unlinked_count2 == 0);
947 res = gst_pad_unlink (ghostpad, sinkpad);
948 fail_unless (res == TRUE);
949 fail_unless (linked_count1 == 1);
950 fail_unless (unlinked_count1 == 0);
951 fail_unless (linked_count2 == 1);
952 fail_unless (unlinked_count2 == 1);
954 res = gst_pad_unlink (ghostpad, sinkpad);
955 fail_unless (res == FALSE);
956 fail_unless (linked_count1 == 1);
957 fail_unless (unlinked_count1 == 0);
958 fail_unless (linked_count2 == 1);
959 fail_unless (unlinked_count2 == 1);
961 /* this should trigger the unlink function */
962 res = gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (ghostpad), NULL);
963 fail_unless (res == TRUE);
964 fail_unless (linked_count1 == 1);
965 fail_unless (unlinked_count1 == 1);
966 fail_unless (linked_count2 == 1);
967 fail_unless (unlinked_count2 == 1);
969 /* and this the link function again */
970 res = gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (ghostpad), srcpad);
971 fail_unless (res == TRUE);
972 fail_unless (linked_count1 == 2);
973 fail_unless (unlinked_count1 == 1);
974 fail_unless (linked_count2 == 1);
975 fail_unless (unlinked_count2 == 1);
977 gst_object_unref (ghostpad);
978 gst_object_unref (sinkpad);
979 gst_object_unref (srcpad);
980 gst_object_unref (srctempl);
981 gst_object_unref (sinktempl);
986 GST_START_TEST (test_ghost_pads_change_when_linked)
988 GstElement *b1, *b2, *src, *fmt, *sink1, *sink2;
989 GstPad *sinkpad, *ghostpad;
992 b1 = gst_element_factory_make ("pipeline", NULL);
993 b2 = gst_element_factory_make ("bin", NULL);
994 src = gst_element_factory_make ("fakesrc", NULL);
995 fmt = gst_element_factory_make ("capsfilter", NULL);
996 sink1 = gst_element_factory_make ("fakesink", NULL);
997 sink2 = gst_element_factory_make ("fakesink", NULL);
999 gst_bin_add (GST_BIN (b2), sink1);
1000 gst_bin_add (GST_BIN (b2), sink2);
1001 gst_bin_add (GST_BIN (b1), src);
1002 gst_bin_add (GST_BIN (b1), fmt);
1003 gst_bin_add (GST_BIN (b1), b2);
1005 caps = gst_caps_from_string ("audio/x-raw-int, width=16, channels=1");
1006 g_object_set (fmt, "caps", caps, NULL);
1007 gst_caps_unref (caps);
1009 /* create the ghostpad as a sink-pad for bin 2 */
1010 ghostpad = gst_ghost_pad_new_no_target ("sink", GST_PAD_SINK);
1011 gst_element_add_pad (b2, ghostpad);
1013 sinkpad = gst_element_get_static_pad (sink1, "sink");
1014 fail_unless (gst_ghost_pad_set_target ((GstGhostPad *) ghostpad, sinkpad));
1015 gst_object_unref (sinkpad);
1017 fail_unless (gst_element_link_many (src, fmt, b2, NULL));
1019 /* set different target after ghostpad is linked */
1020 sinkpad = gst_element_get_static_pad (sink2, "sink");
1021 fail_unless (gst_ghost_pad_set_target ((GstGhostPad *) ghostpad, sinkpad));
1022 gst_object_unref (sinkpad);
1025 gst_object_unref (b1);
1032 gst_ghost_pad_suite (void)
1034 Suite *s = suite_create ("GstGhostPad");
1036 TCase *tc_chain = tcase_create ("ghost pad tests");
1038 suite_add_tcase (s, tc_chain);
1039 tcase_add_test (tc_chain, test_remove1);
1040 tcase_add_test (tc_chain, test_remove2);
1041 tcase_add_test (tc_chain, test_remove_target);
1042 tcase_add_test (tc_chain, test_link);
1043 tcase_add_test (tc_chain, test_ghost_pads);
1044 tcase_add_test (tc_chain, test_ghost_pads_bin);
1045 tcase_add_test (tc_chain, test_ghost_pads_notarget);
1046 tcase_add_test (tc_chain, test_ghost_pads_block);
1047 tcase_add_test (tc_chain, test_ghost_pads_probes);
1048 tcase_add_test (tc_chain, test_ghost_pads_new_from_template);
1049 tcase_add_test (tc_chain, test_ghost_pads_new_no_target_from_template);
1050 tcase_add_test (tc_chain, test_ghost_pads_forward_setcaps);
1051 tcase_add_test (tc_chain, test_ghost_pads_sink_link_unlink);
1052 tcase_add_test (tc_chain, test_ghost_pads_src_link_unlink);
1053 tcase_add_test (tc_chain, test_ghost_pads_change_when_linked);
1058 GST_CHECK_MAIN (gst_ghost_pad);