2 * Copyright (C) <2005> Thomas Vander Stichele <thomas at apestaart dot org>
4 * gstpad.c: Unit test for GstPad
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>
23 #include <glib/gthread.h>
25 GST_START_TEST (test_link)
33 src = gst_pad_new ("source", GST_PAD_SRC);
34 fail_if (src == NULL);
35 ASSERT_OBJECT_REFCOUNT (src, "source pad", 1);
37 name = gst_pad_get_name (src);
38 fail_unless (strcmp (name, "source") == 0);
39 ASSERT_OBJECT_REFCOUNT (src, "source pad", 1);
42 sink = gst_pad_new ("sink", GST_PAD_SINK);
43 fail_if (sink == NULL);
45 /* linking without templates or caps should fail */
46 ret = gst_pad_link (src, sink);
47 ASSERT_OBJECT_REFCOUNT (src, "source pad", 1);
48 ASSERT_OBJECT_REFCOUNT (sink, "sink pad", 1);
49 fail_unless (ret == GST_PAD_LINK_NOFORMAT);
51 ASSERT_CRITICAL (gst_pad_get_pad_template (NULL));
53 srct = gst_pad_get_pad_template (src);
54 fail_unless (srct == NULL);
55 ASSERT_OBJECT_REFCOUNT (src, "source pad", 1);
58 ASSERT_OBJECT_REFCOUNT (src, "source pad", 1);
59 gst_object_unref (src);
60 gst_object_unref (sink);
65 /* threaded link/unlink */
67 static GstPad *src, *sink;
70 thread_link_unlink (gpointer data)
74 while (THREAD_TEST_RUNNING ()) {
75 gst_pad_link (src, sink);
76 gst_pad_unlink (src, sink);
81 GST_START_TEST (test_link_unlink_threaded)
86 src = gst_pad_new ("source", GST_PAD_SRC);
87 fail_if (src == NULL);
88 sink = gst_pad_new ("sink", GST_PAD_SINK);
89 fail_if (sink == NULL);
91 caps = gst_caps_from_string ("foo/bar");
92 gst_pad_set_active (src, TRUE);
93 gst_pad_set_caps (src, caps);
94 gst_pad_set_active (sink, TRUE);
95 gst_pad_set_caps (sink, caps);
96 ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
98 MAIN_START_THREADS (5, thread_link_unlink, NULL);
99 for (i = 0; i < 1000; ++i) {
100 gst_pad_is_linked (src);
101 gst_pad_is_linked (sink);
104 MAIN_STOP_THREADS ();
106 ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
107 gst_caps_unref (caps);
109 ASSERT_CAPS_REFCOUNT (caps, "caps", 2);
110 gst_object_unref (src);
111 gst_object_unref (sink);
116 GST_START_TEST (test_refcount)
120 GstPadLinkReturn plr;
122 sink = gst_pad_new ("sink", GST_PAD_SINK);
123 fail_if (sink == NULL);
125 src = gst_pad_new ("src", GST_PAD_SRC);
126 fail_if (src == NULL);
128 caps = gst_caps_from_string ("foo/bar");
130 ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
132 /* can't set caps on flushing sinkpad */
133 fail_if (gst_pad_set_caps (src, caps) == TRUE);
134 fail_if (gst_pad_set_caps (sink, caps) == TRUE);
135 /* one for me and one for each set_caps */
136 ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
138 gst_pad_set_active (src, TRUE);
139 fail_unless (gst_pad_set_caps (src, caps) == TRUE);
140 ASSERT_CAPS_REFCOUNT (caps, "caps", 2);
142 gst_pad_set_active (sink, TRUE);
143 fail_unless (gst_pad_set_caps (sink, caps) == TRUE);
144 ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
146 plr = gst_pad_link (src, sink);
147 fail_unless (GST_PAD_LINK_SUCCESSFUL (plr));
148 /* src caps added to pending caps on sink */
149 ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
151 gst_pad_unlink (src, sink);
152 ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
155 gst_object_unref (src);
156 gst_object_unref (sink);
157 ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
159 gst_caps_unref (caps);
164 GST_START_TEST (test_get_allowed_caps)
167 GstCaps *caps, *gotcaps;
169 GstPadLinkReturn plr;
171 ASSERT_CRITICAL (gst_pad_get_allowed_caps (NULL));
173 buffer = gst_buffer_new ();
174 ASSERT_CRITICAL (gst_pad_get_allowed_caps ((GstPad *) buffer));
175 gst_buffer_unref (buffer);
177 src = gst_pad_new ("src", GST_PAD_SRC);
178 fail_if (src == NULL);
179 caps = gst_pad_get_allowed_caps (src);
180 fail_unless (caps == NULL);
182 caps = gst_caps_from_string ("foo/bar");
184 sink = gst_pad_new ("sink", GST_PAD_SINK);
185 gst_pad_set_active (src, TRUE);
186 /* source pad is active and will accept the caps event */
187 fail_unless (gst_pad_set_caps (src, caps) == TRUE);
188 /* sink pad is not active and will refuse the caps event */
189 fail_if (gst_pad_set_caps (sink, caps) == TRUE);
190 ASSERT_CAPS_REFCOUNT (caps, "caps", 2);
192 gst_pad_set_active (sink, TRUE);
193 /* sink pad is now active and will accept the caps event */
194 fail_unless (gst_pad_set_caps (sink, caps) == TRUE);
195 ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
197 plr = gst_pad_link (src, sink);
198 fail_unless (GST_PAD_LINK_SUCCESSFUL (plr));
200 gotcaps = gst_pad_get_allowed_caps (src);
201 fail_if (gotcaps == NULL);
202 fail_unless (gst_caps_is_equal (gotcaps, caps));
204 ASSERT_CAPS_REFCOUNT (gotcaps, "gotcaps", 1);
205 gst_caps_unref (gotcaps);
207 gst_pad_unlink (src, sink);
210 ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
211 ASSERT_OBJECT_REFCOUNT (src, "src", 1);
212 ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
214 gst_object_unref (src);
215 gst_object_unref (sink);
217 ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
218 gst_caps_unref (caps);
223 static GstCaps *event_caps = NULL;
226 sticky_event (GstPad * pad, GstObject * parent, GstEvent * event)
230 fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_CAPS);
232 /* Ensure we get here just once: */
233 fail_unless (event_caps == NULL);
235 /* The event must arrive before any buffer: */
236 fail_unless_equals_int (g_list_length (buffers), 0);
238 gst_event_parse_caps (event, &caps);
239 event_caps = gst_caps_ref (caps);
241 gst_event_unref (event);
246 /* Tests whether caps get properly forwarded when pads
247 are initially unlinked */
248 GST_START_TEST (test_sticky_caps_unlinked)
251 GstPadTemplate *src_template, *sink_template;
255 caps = gst_caps_from_string ("foo/bar, dummy=(int){1, 2}");
256 src_template = gst_pad_template_new ("src", GST_PAD_SRC,
257 GST_PAD_ALWAYS, caps);
258 sink_template = gst_pad_template_new ("sink", GST_PAD_SINK,
259 GST_PAD_ALWAYS, caps);
260 gst_caps_unref (caps);
262 src = gst_pad_new_from_template (src_template, "src");
263 fail_if (src == NULL);
264 sink = gst_pad_new_from_template (sink_template, "sink");
265 fail_if (sink == NULL);
266 gst_pad_set_event_function (sink, sticky_event);
267 gst_pad_set_chain_function (sink, gst_check_chain_func);
269 gst_object_unref (src_template);
270 gst_object_unref (sink_template);
272 caps = gst_caps_from_string ("foo/bar, dummy=(int)1");
273 ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
275 event = gst_event_new_caps (caps);
276 gst_pad_set_active (src, TRUE);
277 fail_unless (gst_pad_push_event (src, event) == TRUE);
278 fail_unless (event_caps == NULL);
280 /* Linking and activating will not forward the sticky event yet... */
281 fail_unless (GST_PAD_LINK_SUCCESSFUL (gst_pad_link (src, sink)));
282 gst_pad_set_active (sink, TRUE);
283 fail_unless (event_caps == NULL);
285 /* ...but the first buffer will: */
286 fail_unless (gst_pad_push (src, gst_buffer_new ()) == GST_FLOW_OK);
287 fail_unless (event_caps == caps);
288 fail_unless_equals_int (g_list_length (buffers), 1);
290 gst_caps_replace (&caps, NULL);
291 gst_caps_replace (&event_caps, NULL);
293 ASSERT_OBJECT_REFCOUNT (src, "src", 1);
294 ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
295 gst_object_unref (src);
296 gst_object_unref (sink);
301 /* Same as test_sticky_caps_unlinked except that the source pad
302 * has a template of ANY and we will attempt to push
303 * incompatible caps */
304 GST_START_TEST (test_sticky_caps_unlinked_incompatible)
306 GstCaps *caps, *failcaps;
307 GstPadTemplate *src_template, *sink_template;
311 /* Source pad has ANY caps
312 * Sink pad has foobar caps
313 * We will push the pony express caps (which should fail)
315 caps = gst_caps_from_string ("foo/bar, dummy=(int){1, 2}");
316 src_template = gst_pad_template_new ("src", GST_PAD_SRC,
317 GST_PAD_ALWAYS, gst_caps_new_any ());
318 sink_template = gst_pad_template_new ("sink", GST_PAD_SINK,
319 GST_PAD_ALWAYS, caps);
320 gst_caps_unref (caps);
322 src = gst_pad_new_from_template (src_template, "src");
323 fail_if (src == NULL);
324 sink = gst_pad_new_from_template (sink_template, "sink");
325 fail_if (sink == NULL);
326 gst_pad_set_event_function (sink, sticky_event);
327 gst_pad_set_chain_function (sink, gst_check_chain_func);
329 gst_object_unref (src_template);
330 gst_object_unref (sink_template);
332 failcaps = gst_caps_from_string ("pony/express, failure=(boolean)true");
333 ASSERT_CAPS_REFCOUNT (failcaps, "caps", 1);
335 event = gst_event_new_caps (failcaps);
336 gst_pad_set_active (src, TRUE);
337 /* The pad isn't linked yet, and anything matches the source pad template
339 fail_unless (gst_pad_push_event (src, event) == TRUE);
340 fail_unless (event_caps == NULL);
342 /* Linking and activating will not forward the sticky event yet... */
343 fail_unless (GST_PAD_LINK_SUCCESSFUL (gst_pad_link (src, sink)));
344 gst_pad_set_active (sink, TRUE);
345 fail_unless (event_caps == NULL);
347 /* ...but the first buffer will and should FAIL since the caps
348 * are not compatible */
349 fail_unless (gst_pad_push (src,
350 gst_buffer_new ()) == GST_FLOW_NOT_NEGOTIATED);
351 /* We shouldn't have received the caps event since it's incompatible */
352 fail_unless (event_caps == NULL);
353 /* We shouldn't have received any buffers since caps are incompatible */
354 fail_unless_equals_int (g_list_length (buffers), 0);
356 gst_caps_replace (&caps, NULL);
357 gst_caps_replace (&event_caps, NULL);
359 ASSERT_OBJECT_REFCOUNT (src, "src", 1);
360 ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
361 gst_object_unref (src);
362 gst_object_unref (sink);
367 /* Like test_sticky_caps_unlinked, but link before caps: */
369 GST_START_TEST (test_sticky_caps_flushing)
372 GstPadTemplate *src_template, *sink_template;
376 caps = gst_caps_from_string ("foo/bar, dummy=(int){1, 2}");
377 src_template = gst_pad_template_new ("src", GST_PAD_SRC,
378 GST_PAD_ALWAYS, caps);
379 sink_template = gst_pad_template_new ("sink", GST_PAD_SINK,
380 GST_PAD_ALWAYS, caps);
381 gst_caps_unref (caps);
383 src = gst_pad_new_from_template (src_template, "src");
384 fail_if (src == NULL);
385 sink = gst_pad_new_from_template (sink_template, "sink");
386 fail_if (sink == NULL);
387 gst_pad_set_event_function (sink, sticky_event);
388 gst_pad_set_chain_function (sink, gst_check_chain_func);
390 gst_object_unref (src_template);
391 gst_object_unref (sink_template);
393 fail_unless (GST_PAD_LINK_SUCCESSFUL (gst_pad_link (src, sink)));
395 caps = gst_caps_from_string ("foo/bar, dummy=(int)1");
396 ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
398 event = gst_event_new_caps (caps);
399 gst_pad_set_active (src, TRUE);
400 /* The caps event gets accepted by the source pad (and stored) */
401 fail_unless (gst_pad_push_event (src, event) == TRUE);
402 /* But wasn't forwarded since the sink pad is flushing (not activated) */
403 fail_unless (event_caps == NULL);
405 /* Activating will not forward the sticky event yet... */
406 gst_pad_set_active (sink, TRUE);
407 fail_unless (event_caps == NULL);
409 /* ...but the first buffer will: */
410 fail_unless (gst_pad_push (src, gst_buffer_new ()) == GST_FLOW_OK);
411 fail_unless (event_caps == caps);
412 fail_unless_equals_int (g_list_length (buffers), 1);
414 gst_caps_replace (&caps, NULL);
415 gst_caps_replace (&event_caps, NULL);
417 ASSERT_OBJECT_REFCOUNT (src, "src", 1);
418 ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
419 gst_object_unref (src);
420 gst_object_unref (sink);
426 name_is_valid (const gchar * name, GstPadPresence presence)
429 GstCaps *any = gst_caps_new_any ();
431 new = gst_pad_template_new (name, GST_PAD_SRC, presence, any);
432 gst_caps_unref (any);
434 gst_object_unref (GST_OBJECT (new));
440 GST_START_TEST (test_name_is_valid)
442 gboolean result = FALSE;
444 fail_unless (name_is_valid ("src", GST_PAD_ALWAYS));
445 ASSERT_WARNING (name_is_valid ("src%", GST_PAD_ALWAYS));
446 ASSERT_WARNING (result = name_is_valid ("src%d", GST_PAD_ALWAYS));
449 fail_unless (name_is_valid ("src", GST_PAD_REQUEST));
450 ASSERT_WARNING (name_is_valid ("src%s%s", GST_PAD_REQUEST));
451 ASSERT_WARNING (name_is_valid ("src%c", GST_PAD_REQUEST));
452 ASSERT_WARNING (name_is_valid ("src%", GST_PAD_REQUEST));
453 ASSERT_WARNING (name_is_valid ("src%dsrc", GST_PAD_REQUEST));
455 fail_unless (name_is_valid ("src", GST_PAD_SOMETIMES));
456 fail_unless (name_is_valid ("src%c", GST_PAD_SOMETIMES));
461 static GstPadProbeReturn
462 _probe_handler (GstPad * pad, GstPadProbeInfo * info, gpointer userdata)
464 gint ret = GPOINTER_TO_INT (userdata);
467 return GST_PAD_PROBE_OK;
469 return GST_PAD_PROBE_DROP;
472 GST_START_TEST (test_push_unlinked)
479 src = gst_pad_new ("src", GST_PAD_SRC);
480 fail_if (src == NULL);
481 caps = gst_pad_get_allowed_caps (src);
482 fail_unless (caps == NULL);
484 caps = gst_caps_from_string ("foo/bar");
486 /* pushing on an inactive pad will return wrong state */
487 GST_DEBUG ("push buffer inactive");
488 buffer = gst_buffer_new ();
489 gst_buffer_ref (buffer);
490 fail_unless (gst_pad_push (src, buffer) == GST_FLOW_WRONG_STATE);
491 ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
492 gst_buffer_unref (buffer);
494 gst_pad_set_active (src, TRUE);
495 GST_DEBUG ("push caps event inactive");
496 gst_pad_set_caps (src, caps);
497 ASSERT_CAPS_REFCOUNT (caps, "caps", 2);
499 /* pushing on an unlinked pad will drop the buffer */
500 GST_DEBUG ("push buffer unlinked");
501 buffer = gst_buffer_new ();
502 gst_buffer_ref (buffer);
503 fail_unless (gst_pad_push (src, buffer) == GST_FLOW_NOT_LINKED);
504 ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
505 gst_buffer_unref (buffer);
507 /* adding a probe that returns _DROP will drop the buffer without trying
509 GST_DEBUG ("push buffer drop");
510 id = gst_pad_add_probe (src, GST_PAD_PROBE_TYPE_BUFFER,
511 _probe_handler, GINT_TO_POINTER (0), NULL);
512 buffer = gst_buffer_new ();
513 gst_buffer_ref (buffer);
514 fail_unless (gst_pad_push (src, buffer) == GST_FLOW_OK);
515 ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
516 gst_buffer_unref (buffer);
517 gst_pad_remove_probe (src, id);
519 /* adding a probe that returns _OK will still chain the buffer,
520 * and hence drop because pad is unlinked */
521 GST_DEBUG ("push buffer ok");
522 id = gst_pad_add_probe (src, GST_PAD_PROBE_TYPE_BUFFER,
523 _probe_handler, GINT_TO_POINTER (1), NULL);
524 buffer = gst_buffer_new ();
525 gst_buffer_ref (buffer);
526 fail_unless (gst_pad_push (src, buffer) == GST_FLOW_NOT_LINKED);
527 ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
528 gst_buffer_unref (buffer);
529 gst_pad_remove_probe (src, id);
533 ASSERT_CAPS_REFCOUNT (caps, "caps", 2);
534 ASSERT_OBJECT_REFCOUNT (src, "src", 1);
536 gst_object_unref (src);
538 ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
539 gst_caps_unref (caps);
544 GST_START_TEST (test_push_linked)
547 GstPadLinkReturn plr;
553 sink = gst_pad_new ("sink", GST_PAD_SINK);
554 fail_if (sink == NULL);
555 gst_pad_set_chain_function (sink, gst_check_chain_func);
557 src = gst_pad_new ("src", GST_PAD_SRC);
558 fail_if (src == NULL);
560 caps = gst_caps_from_string ("foo/bar");
562 ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
564 gst_pad_set_active (src, TRUE);
565 gst_pad_set_caps (src, caps);
566 gst_pad_set_active (sink, TRUE);
567 gst_pad_set_caps (sink, caps);
568 /* one for me and one for each set_caps */
569 ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
571 plr = gst_pad_link (src, sink);
572 fail_unless (GST_PAD_LINK_SUCCESSFUL (plr));
573 ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
575 buffer = gst_buffer_new ();
578 /* pushing on a linked pad will drop the ref to the buffer */
579 gst_buffer_ref (buffer);
580 fail_unless (gst_pad_push (src, buffer) == GST_FLOW_OK);
581 ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 2);
582 gst_buffer_unref (buffer);
583 fail_unless_equals_int (g_list_length (buffers), 1);
584 buffer = GST_BUFFER (buffers->data);
585 ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
586 gst_buffer_unref (buffer);
587 g_list_free (buffers);
590 /* adding a probe that returns FALSE will drop the buffer without trying
592 id = gst_pad_add_probe (src, GST_PAD_PROBE_TYPE_BUFFER,
593 _probe_handler, GINT_TO_POINTER (0), NULL);
594 buffer = gst_buffer_new ();
595 gst_buffer_ref (buffer);
596 fail_unless (gst_pad_push (src, buffer) == GST_FLOW_OK);
597 ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
598 gst_buffer_unref (buffer);
599 gst_pad_remove_probe (src, id);
600 fail_unless_equals_int (g_list_length (buffers), 0);
602 /* adding a probe that returns TRUE will still chain the buffer */
603 id = gst_pad_add_probe (src, GST_PAD_PROBE_TYPE_BUFFER,
604 _probe_handler, GINT_TO_POINTER (1), NULL);
605 buffer = gst_buffer_new ();
606 gst_buffer_ref (buffer);
607 fail_unless (gst_pad_push (src, buffer) == GST_FLOW_OK);
608 gst_pad_remove_probe (src, id);
610 ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 2);
611 gst_buffer_unref (buffer);
612 fail_unless_equals_int (g_list_length (buffers), 1);
613 buffer = GST_BUFFER (buffers->data);
614 ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
615 gst_buffer_unref (buffer);
616 g_list_free (buffers);
620 gst_pad_unlink (src, sink);
621 ASSERT_CAPS_REFCOUNT (caps, "caps", 2);
622 gst_object_unref (src);
623 gst_object_unref (sink);
624 ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
626 gst_caps_unref (caps);
631 GST_START_TEST (test_push_linked_flushing)
635 GstPadLinkReturn plr;
640 src = gst_pad_new ("src", GST_PAD_SRC);
641 fail_if (src == NULL);
642 sink = gst_pad_new ("sink", GST_PAD_SINK);
643 fail_if (sink == NULL);
644 gst_pad_set_chain_function (sink, gst_check_chain_func);
646 caps = gst_pad_get_allowed_caps (src);
647 fail_unless (caps == NULL);
648 caps = gst_pad_get_allowed_caps (sink);
649 fail_unless (caps == NULL);
651 caps = gst_caps_from_string ("foo/bar");
653 ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
655 gst_pad_set_active (src, TRUE);
656 gst_pad_set_caps (src, caps);
657 /* need to activate to make it accept the caps */
658 gst_pad_set_active (sink, TRUE);
659 gst_pad_set_caps (sink, caps);
660 /* one for me and one for each set_caps */
661 ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
663 plr = gst_pad_link (src, sink);
664 fail_unless (GST_PAD_LINK_SUCCESSFUL (plr));
665 ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
667 /* not activating the pads here, which keeps them flushing */
668 gst_pad_set_active (src, FALSE);
669 gst_pad_set_active (sink, FALSE);
671 /* pushing on a flushing pad will drop the buffer */
672 buffer = gst_buffer_new ();
673 gst_buffer_ref (buffer);
674 fail_unless (gst_pad_push (src, buffer) == GST_FLOW_WRONG_STATE);
675 ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
676 fail_unless_equals_int (g_list_length (buffers), 0);
677 gst_buffer_unref (buffer);
679 gst_pad_set_active (src, TRUE);
680 gst_pad_set_active (sink, FALSE);
682 /* adding a probe that returns FALSE will drop the buffer without trying
684 id = gst_pad_add_probe (src, GST_PAD_PROBE_TYPE_BUFFER, _probe_handler,
685 GINT_TO_POINTER (0), NULL);
686 buffer = gst_buffer_new ();
687 gst_buffer_ref (buffer);
688 fail_unless (gst_pad_push (src, buffer) == GST_FLOW_OK);
689 ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
690 fail_unless_equals_int (g_list_length (buffers), 0);
691 gst_buffer_unref (buffer);
692 gst_pad_remove_probe (src, id);
694 /* adding a probe that returns TRUE will still chain the buffer,
695 * and hence drop because pad is flushing */
696 id = gst_pad_add_probe (src, GST_PAD_PROBE_TYPE_BUFFER, _probe_handler,
697 GINT_TO_POINTER (1), NULL);
698 buffer = gst_buffer_new ();
699 gst_buffer_ref (buffer);
700 fail_unless (gst_pad_push (src, buffer) == GST_FLOW_WRONG_STATE);
701 ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
702 fail_unless_equals_int (g_list_length (buffers), 0);
703 gst_buffer_unref (buffer);
704 gst_pad_remove_probe (src, id);
707 ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
708 ASSERT_OBJECT_REFCOUNT (src, "src", 1);
709 gst_pad_link (src, sink);
710 gst_object_unref (src);
711 gst_object_unref (sink);
712 ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
713 gst_caps_unref (caps);
719 buffer_from_string (const gchar * str)
726 buf = gst_buffer_new_and_alloc (size);
728 data = gst_buffer_map (buf, NULL, NULL, GST_MAP_WRITE);
729 memcpy (data, str, size);
730 gst_buffer_unmap (buf, data, size);
736 buffer_compare (GstBuffer * buf, const gchar * str, gsize size)
741 data = gst_buffer_map (buf, NULL, NULL, GST_MAP_READ);
742 res = memcmp (data, str, size) == 0;
743 GST_DEBUG ("%s <-> %s: %d", (gchar *) data, str, res);
744 gst_buffer_unmap (buf, data, size);
749 GST_START_TEST (test_push_buffer_list_compat)
752 GstPadLinkReturn plr;
758 sink = gst_pad_new ("sink", GST_PAD_SINK);
759 fail_if (sink == NULL);
760 gst_pad_set_chain_function (sink, gst_check_chain_func);
761 /* leave chainlistfunc unset */
763 src = gst_pad_new ("src", GST_PAD_SRC);
764 fail_if (src == NULL);
766 caps = gst_caps_from_string ("foo/bar");
768 gst_pad_set_active (src, TRUE);
769 gst_pad_set_caps (src, caps);
770 gst_pad_set_active (sink, TRUE);
771 gst_pad_set_caps (sink, caps);
773 plr = gst_pad_link (src, sink);
774 fail_unless (GST_PAD_LINK_SUCCESSFUL (plr));
776 list = gst_buffer_list_new ();
779 /* adding to a buffer list will drop the ref to the buffer */
780 gst_buffer_list_add (list, buffer_from_string ("ListGroup"));
781 gst_buffer_list_add (list, buffer_from_string ("AnotherListGroup"));
783 fail_unless (gst_pad_push_list (src, list) == GST_FLOW_OK);
784 fail_unless_equals_int (g_list_length (buffers), 2);
785 buffer = GST_BUFFER (buffers->data);
786 ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
787 fail_unless (buffer_compare (buffer, "ListGroup", 9));
788 gst_buffer_unref (buffer);
789 buffers = g_list_delete_link (buffers, buffers);
790 buffer = GST_BUFFER (buffers->data);
791 ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
792 fail_unless (buffer_compare (buffer, "AnotherListGroup", 16));
793 gst_buffer_unref (buffer);
794 buffers = g_list_delete_link (buffers, buffers);
795 fail_unless (buffers == NULL);
798 gst_pad_unlink (src, sink);
799 gst_object_unref (src);
800 gst_object_unref (sink);
801 ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
802 gst_caps_unref (caps);
807 GST_START_TEST (test_flowreturn)
812 /* test some of the macros */
814 fail_if (strcmp (gst_flow_get_name (ret), "eos"));
815 quark = gst_flow_to_quark (ret);
816 fail_if (strcmp (g_quark_to_string (quark), "eos"));
818 ret = GST_FLOW_RESEND;
819 fail_if (strcmp (gst_flow_get_name (ret), "resend"));
820 quark = gst_flow_to_quark (ret);
821 fail_if (strcmp (g_quark_to_string (quark), "resend"));
824 ret = GST_FLOW_CUSTOM_SUCCESS;
825 fail_if (strcmp (gst_flow_get_name (ret), "custom-success"));
826 quark = gst_flow_to_quark (ret);
827 fail_if (strcmp (g_quark_to_string (quark), "custom-success"));
829 ret = GST_FLOW_CUSTOM_ERROR;
830 fail_if (strcmp (gst_flow_get_name (ret), "custom-error"));
831 quark = gst_flow_to_quark (ret);
832 fail_if (strcmp (g_quark_to_string (quark), "custom-error"));
834 /* custom returns clamping */
835 ret = GST_FLOW_CUSTOM_SUCCESS + 2;
836 fail_if (strcmp (gst_flow_get_name (ret), "custom-success"));
837 quark = gst_flow_to_quark (ret);
838 fail_if (strcmp (g_quark_to_string (quark), "custom-success"));
840 ret = GST_FLOW_CUSTOM_ERROR - 2;
841 fail_if (strcmp (gst_flow_get_name (ret), "custom-error"));
842 quark = gst_flow_to_quark (ret);
843 fail_if (strcmp (g_quark_to_string (quark), "custom-error"));
846 ret = GST_FLOW_CUSTOM_ERROR + 2;
847 fail_if (strcmp (gst_flow_get_name (ret), "unknown"));
848 quark = gst_flow_to_quark (ret);
849 fail_unless (quark == 0);
854 GST_START_TEST (test_push_negotiation)
857 GstPadLinkReturn plr;
859 gst_caps_from_string ("audio/x-raw-int,width={16,32},depth={16,32}");
861 gst_caps_from_string ("audio/x-raw-int,width=32,depth={16,32}");
862 GstPadTemplate *src_template;
863 GstPadTemplate *sink_template;
867 src_template = gst_pad_template_new ("src", GST_PAD_SRC,
868 GST_PAD_ALWAYS, srccaps);
869 sink_template = gst_pad_template_new ("sink", GST_PAD_SINK,
870 GST_PAD_ALWAYS, sinkcaps);
871 gst_caps_unref (srccaps);
872 gst_caps_unref (sinkcaps);
874 sink = gst_pad_new_from_template (sink_template, "sink");
875 fail_if (sink == NULL);
876 gst_pad_set_chain_function (sink, gst_check_chain_func);
878 src = gst_pad_new_from_template (src_template, "src");
879 fail_if (src == NULL);
881 plr = gst_pad_link (src, sink);
882 fail_unless (GST_PAD_LINK_SUCCESSFUL (plr));
885 gst_pad_set_active (src, TRUE);
886 gst_pad_set_active (sink, TRUE);
888 caps = gst_caps_from_string ("audio/x-raw-int,width=16,depth=16");
890 /* Should fail if src pad caps are incompatible with sink pad caps */
891 gst_pad_set_caps (src, caps);
892 fail_unless (gst_pad_set_caps (sink, caps) == FALSE);
895 gst_pad_unlink (src, sink);
896 gst_object_unref (src);
897 gst_object_unref (sink);
898 gst_caps_unref (caps);
899 gst_object_unref (sink_template);
900 gst_object_unref (src_template);
905 /* see that an unref also unlinks the pads */
906 GST_START_TEST (test_src_unref_unlink)
910 GstPadLinkReturn plr;
912 sink = gst_pad_new ("sink", GST_PAD_SINK);
913 fail_if (sink == NULL);
915 src = gst_pad_new ("src", GST_PAD_SRC);
916 fail_if (src == NULL);
918 caps = gst_caps_from_string ("foo/bar");
920 gst_pad_set_active (src, TRUE);
921 gst_pad_set_caps (src, caps);
922 gst_pad_set_active (sink, TRUE);
923 gst_pad_set_caps (sink, caps);
925 plr = gst_pad_link (src, sink);
926 fail_unless (GST_PAD_LINK_SUCCESSFUL (plr));
928 /* unref the srcpad */
929 gst_object_unref (src);
931 /* sink should be unlinked now */
932 fail_if (gst_pad_is_linked (sink));
935 gst_object_unref (sink);
936 gst_caps_unref (caps);
941 /* see that an unref also unlinks the pads */
942 GST_START_TEST (test_sink_unref_unlink)
946 GstPadLinkReturn plr;
948 sink = gst_pad_new ("sink", GST_PAD_SINK);
949 fail_if (sink == NULL);
951 src = gst_pad_new ("src", GST_PAD_SRC);
952 fail_if (src == NULL);
954 caps = gst_caps_from_string ("foo/bar");
956 gst_pad_set_active (src, TRUE);
957 gst_pad_set_caps (src, caps);
958 gst_pad_set_active (sink, TRUE);
959 gst_pad_set_caps (sink, caps);
961 plr = gst_pad_link (src, sink);
962 fail_unless (GST_PAD_LINK_SUCCESSFUL (plr));
964 /* unref the sinkpad */
965 gst_object_unref (sink);
967 /* src should be unlinked now */
968 fail_if (gst_pad_is_linked (src));
971 gst_object_unref (src);
972 gst_caps_unref (caps);
979 static GstPadProbeReturn
980 block_async_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
982 gboolean *bool_user_data = (gboolean *) user_data;
984 fail_unless ((info->type & GST_PAD_PROBE_TYPE_BLOCK) != 0);
986 /* here we should have blocked == 0 unblocked == 0 */
987 fail_unless (bool_user_data[0] == FALSE);
988 fail_unless (bool_user_data[1] == FALSE);
990 bool_user_data[0] = TRUE;
992 gst_pad_remove_probe (pad, id);
993 bool_user_data[1] = TRUE;
995 return GST_PAD_PROBE_OK;
998 GST_START_TEST (test_block_async)
1001 /* we set data[0] = TRUE when the pad is blocked, data[1] = TRUE when it's
1003 gboolean data[2] = { FALSE, FALSE };
1005 pad = gst_pad_new ("src", GST_PAD_SRC);
1006 fail_unless (pad != NULL);
1008 gst_pad_set_active (pad, TRUE);
1009 id = gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BLOCK, block_async_cb, &data,
1012 fail_unless (data[0] == FALSE);
1013 fail_unless (data[1] == FALSE);
1014 gst_pad_push (pad, gst_buffer_new ());
1016 gst_object_unref (pad);
1021 static GstPadProbeReturn
1022 block_async_cb_return_ok (GstPad * pad, GstPadProbeInfo * info,
1025 return GST_PAD_PROBE_OK;
1029 push_buffer_async (GstPad * pad)
1031 return GINT_TO_POINTER (gst_pad_push (pad, gst_buffer_new ()));
1035 test_pad_blocking_with_type (GstPadProbeType type)
1041 pad = gst_pad_new ("src", GST_PAD_SRC);
1042 fail_unless (pad != NULL);
1044 gst_pad_set_active (pad, TRUE);
1045 id = gst_pad_add_probe (pad, type, block_async_cb_return_ok, NULL, NULL);
1048 thread = g_thread_create ((GThreadFunc) push_buffer_async, pad, TRUE, NULL);
1050 /* wait for the block */
1051 while (!gst_pad_is_blocking (pad)) {
1055 /* stop with flushing */
1056 gst_pad_push_event (pad, gst_event_new_flush_start ());
1058 /* get return value from push */
1059 ret = GPOINTER_TO_INT (g_thread_join (thread));
1061 gst_pad_push_event (pad, gst_event_new_flush_stop (FALSE));
1062 /* must be wrong state */
1063 fail_unless (ret == GST_FLOW_WRONG_STATE);
1065 gst_object_unref (pad);
1068 GST_START_TEST (test_pad_blocking_with_probe_type_block)
1070 test_pad_blocking_with_type (GST_PAD_PROBE_TYPE_BLOCK);
1075 GST_START_TEST (test_pad_blocking_with_probe_type_blocking)
1077 test_pad_blocking_with_type (GST_PAD_PROBE_TYPE_BLOCKING);
1084 block_async_second (GstPad * pad, gboolean blocked, gpointer user_data)
1086 gst_pad_set_blocked (pad, FALSE, unblock_async_cb, NULL, NULL);
1090 block_async_first (GstPad * pad, gboolean blocked, gpointer user_data)
1092 static int n_calls = 0;
1093 gboolean *bool_user_data = (gboolean *) user_data;
1096 /* we expect this callback to be called only once */
1097 g_warn_if_reached ();
1099 *bool_user_data = blocked;
1101 /* replace block_async_first with block_async_second so next time the pad is
1102 * blocked the latter should be called */
1103 gst_pad_set_blocked (pad, TRUE, block_async_second, NULL, NULL);
1105 /* unblock temporarily, in the next push block_async_second should be called
1107 gst_pad_push_event (pad, gst_event_new_flush_start ());
1110 GST_START_TEST (test_block_async_replace_callback)
1115 pad = gst_pad_new ("src", GST_PAD_SRC);
1116 fail_unless (pad != NULL);
1117 gst_pad_set_active (pad, TRUE);
1119 gst_pad_set_blocked (pad, TRUE, block_async_first, &blocked, NULL);
1122 gst_pad_push (pad, gst_buffer_new ());
1123 fail_unless (blocked == TRUE);
1124 /* block_async_first flushes to unblock */
1125 gst_pad_push_event (pad, gst_event_new_flush_stop ());
1127 /* push again, this time block_async_second should be called */
1128 gst_pad_push (pad, gst_buffer_new ());
1129 fail_unless (blocked == TRUE);
1131 gst_object_unref (pad);
1138 block_async_full_destroy (gpointer user_data)
1140 gint *state = (gint *) user_data;
1142 fail_unless (*state < 2);
1144 GST_DEBUG ("setting state to 2");
1148 static GstPadProbeReturn
1149 block_async_full_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
1151 *(gint *) user_data = (gint) TRUE;
1153 gst_pad_push_event (pad, gst_event_new_flush_start ());
1154 GST_DEBUG ("setting state to 1");
1156 return GST_PAD_PROBE_OK;
1159 GST_START_TEST (test_block_async_full_destroy)
1162 /* 0 = unblocked, 1 = blocked, 2 = destroyed */
1166 pad = gst_pad_new ("src", GST_PAD_SRC);
1167 fail_unless (pad != NULL);
1168 gst_pad_set_active (pad, TRUE);
1170 id = gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BLOCK, block_async_full_cb,
1171 &state, block_async_full_destroy);
1172 fail_unless (state == 0);
1174 gst_pad_push (pad, gst_buffer_new ());
1175 /* block_async_full_cb sets state to 1 and then flushes to unblock temporarily
1177 fail_unless (state == 1);
1178 gst_pad_push_event (pad, gst_event_new_flush_stop (TRUE));
1180 /* unblock callback is called */
1181 gst_pad_remove_probe (pad, id);
1182 fail_unless (state == 2);
1184 gst_object_unref (pad);
1189 GST_START_TEST (test_block_async_full_destroy_dispose)
1192 /* 0 = unblocked, 1 = blocked, 2 = destroyed */
1195 pad = gst_pad_new ("src", GST_PAD_SRC);
1196 fail_unless (pad != NULL);
1197 gst_pad_set_active (pad, TRUE);
1199 (void) gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BLOCK, block_async_full_cb,
1200 &state, block_async_full_destroy);
1202 gst_pad_push (pad, gst_buffer_new ());
1203 /* block_async_full_cb sets state to 1 and then flushes to unblock temporarily
1205 fail_unless_equals_int (state, 1);
1206 gst_pad_push_event (pad, gst_event_new_flush_stop (TRUE));
1208 /* gst_BLOCK calls the destroy_notify function if necessary */
1209 gst_object_unref (pad);
1211 fail_unless_equals_int (state, 2);
1219 unblock_async_no_flush_cb (GstPad * pad, gboolean blocked, gpointer user_data)
1221 gboolean *bool_user_data = (gboolean *) user_data;
1223 /* here we should have blocked == 1 unblocked == 0 */
1225 fail_unless (blocked == FALSE);
1227 fail_unless (bool_user_data[0] == TRUE);
1228 fail_unless (bool_user_data[1] == TRUE);
1229 fail_unless (bool_user_data[2] == FALSE);
1231 bool_user_data[2] = TRUE;
1238 unblock_async_not_called (GstPad * pad, gboolean blocked, gpointer user_data)
1240 g_warn_if_reached ();
1244 static GstPadProbeReturn
1245 block_async_second_no_flush (GstPad * pad, GstPadProbeInfo * info,
1248 gboolean *bool_user_data = (gboolean *) user_data;
1250 GST_DEBUG ("second probe called");
1252 fail_unless (info->type & GST_PAD_PROBE_TYPE_BLOCK);
1254 fail_unless (bool_user_data[0] == TRUE);
1255 fail_unless (bool_user_data[1] == FALSE);
1256 fail_unless (bool_user_data[2] == FALSE);
1258 bool_user_data[1] = TRUE;
1260 GST_DEBUG ("removing second probe with id %lu", id);
1261 gst_pad_remove_probe (pad, id);
1263 return GST_PAD_PROBE_OK;
1266 static GstPadProbeReturn
1267 block_async_first_no_flush (GstPad * pad, GstPadProbeInfo * info,
1270 static int n_calls = 0;
1271 gboolean *bool_user_data = (gboolean *) user_data;
1273 fail_unless (info->type & GST_PAD_PROBE_TYPE_BLOCK);
1275 GST_DEBUG ("first probe called");
1278 /* we expect this callback to be called only once */
1279 g_warn_if_reached ();
1281 *bool_user_data = TRUE;
1283 fail_unless (bool_user_data[0] == TRUE);
1284 fail_unless (bool_user_data[1] == FALSE);
1285 fail_unless (bool_user_data[2] == FALSE);
1287 GST_DEBUG ("removing first probe with id %lu", id);
1288 gst_pad_remove_probe (pad, id);
1290 GST_DEBUG ("adding second probe");
1291 /* replace block_async_first with block_async_second so next time the pad is
1292 * blocked the latter should be called */
1293 id = gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BLOCK,
1294 block_async_second_no_flush, user_data, NULL);
1295 GST_DEBUG ("added probe with id %lu", id);
1297 return GST_PAD_PROBE_OK;
1300 GST_START_TEST (test_block_async_replace_callback_no_flush)
1303 gboolean bool_user_data[3] = { FALSE, FALSE, FALSE };
1305 pad = gst_pad_new ("src", GST_PAD_SRC);
1306 fail_unless (pad != NULL);
1307 gst_pad_set_active (pad, TRUE);
1309 GST_DEBUG ("adding probe");
1310 id = gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BLOCK,
1311 block_async_first_no_flush, bool_user_data, NULL);
1312 GST_DEBUG ("added probe with id %lu", id);
1315 GST_DEBUG ("pushing buffer");
1316 gst_pad_push (pad, gst_buffer_new ());
1317 fail_unless (bool_user_data[0] == TRUE);
1318 fail_unless (bool_user_data[1] == TRUE);
1319 fail_unless (bool_user_data[2] == FALSE);
1321 gst_object_unref (pad);
1328 gst_pad_suite (void)
1330 Suite *s = suite_create ("GstPad");
1331 TCase *tc_chain = tcase_create ("general");
1333 /* turn off timeout */
1334 tcase_set_timeout (tc_chain, 60);
1336 suite_add_tcase (s, tc_chain);
1337 tcase_add_test (tc_chain, test_link);
1338 tcase_add_test (tc_chain, test_refcount);
1339 tcase_add_test (tc_chain, test_get_allowed_caps);
1340 tcase_add_test (tc_chain, test_sticky_caps_unlinked);
1341 tcase_add_test (tc_chain, test_sticky_caps_unlinked_incompatible);
1342 tcase_add_test (tc_chain, test_sticky_caps_flushing);
1343 tcase_add_test (tc_chain, test_link_unlink_threaded);
1344 tcase_add_test (tc_chain, test_name_is_valid);
1345 tcase_add_test (tc_chain, test_push_unlinked);
1346 tcase_add_test (tc_chain, test_push_linked);
1347 tcase_add_test (tc_chain, test_push_linked_flushing);
1348 tcase_add_test (tc_chain, test_push_buffer_list_compat);
1349 tcase_add_test (tc_chain, test_flowreturn);
1350 tcase_add_test (tc_chain, test_push_negotiation);
1351 tcase_add_test (tc_chain, test_src_unref_unlink);
1352 tcase_add_test (tc_chain, test_sink_unref_unlink);
1353 tcase_add_test (tc_chain, test_block_async);
1354 tcase_add_test (tc_chain, test_pad_blocking_with_probe_type_block);
1355 tcase_add_test (tc_chain, test_pad_blocking_with_probe_type_blocking);
1357 tcase_add_test (tc_chain, test_block_async_replace_callback);
1359 tcase_add_test (tc_chain, test_block_async_full_destroy);
1360 tcase_add_test (tc_chain, test_block_async_full_destroy_dispose);
1361 tcase_add_test (tc_chain, test_block_async_replace_callback_no_flush);
1366 GST_CHECK_MAIN (gst_pad);