3 * unit test for fakesink
5 * Copyright (C) <2005> Thomas Vander Stichele <thomas at apestaart dot org>
6 * <2007> Wim Taymans <wim@fluendo.com>
7 * <2009> Tim-Philipp Müller <tim centricular net>
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
19 * You should have received a copy of the GNU Library General Public
20 * License along with this library; if not, write to the
21 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 * Boston, MA 02111-1307, USA.
27 #include <gst/base/gstpushsrc.h>
28 #include <gst/check/gstcheck.h>
39 chain_async_buffer (gpointer data)
41 ChainData *chain_data = (ChainData *) data;
43 chain_data->ret = gst_pad_chain (chain_data->pad, chain_data->buffer);
49 chain_async (GstPad * pad, GstBuffer * buffer)
52 ChainData *chain_data;
55 chain_data = g_new (ChainData, 1);
56 chain_data->pad = pad;
57 chain_data->buffer = buffer;
58 chain_data->ret = GST_FLOW_ERROR;
60 thread = g_thread_create (chain_async_buffer, chain_data, TRUE, &error);
62 g_warning ("could not create thread reason: %s", error->message);
66 chain_data->thread = thread;
72 chain_async_return (ChainData * data)
76 g_thread_join (data->thread);
83 GST_START_TEST (test_clipping)
87 GstStateChangeReturn ret;
90 sink = gst_element_factory_make ("fakesink", "sink");
91 fail_if (sink == NULL);
93 sinkpad = gst_element_get_static_pad (sink, "sink");
94 fail_if (sinkpad == NULL);
96 /* make element ready to accept data */
97 ret = gst_element_set_state (sink, GST_STATE_PAUSED);
98 fail_unless (ret == GST_STATE_CHANGE_ASYNC);
106 GST_DEBUG ("sending segment");
107 gst_segment_init (&segment, GST_FORMAT_TIME);
108 segment.start = 1 * GST_SECOND;
109 segment.stop = 5 * GST_SECOND;
110 segment.time = 1 * GST_SECOND;
112 event = gst_event_new_segment (&segment);
114 eret = gst_pad_send_event (sinkpad, event);
115 fail_if (eret == FALSE);
118 /* new segment should not have finished preroll */
119 ret = gst_element_get_state (sink, NULL, NULL, 0);
120 fail_unless (ret == GST_STATE_CHANGE_ASYNC);
122 /* send buffer that should be dropped */
127 buffer = gst_buffer_new ();
128 GST_BUFFER_TIMESTAMP (buffer) = 0;
129 GST_BUFFER_DURATION (buffer) = 1 * GST_MSECOND;
131 GST_DEBUG ("sending buffer to be dropped");
132 fret = gst_pad_chain (sinkpad, buffer);
133 fail_if (fret != GST_FLOW_OK);
135 /* dropped buffer should not have finished preroll */
136 ret = gst_element_get_state (sink, NULL, NULL, 0);
137 fail_unless (ret == GST_STATE_CHANGE_ASYNC);
139 /* send buffer that should be dropped */
144 buffer = gst_buffer_new ();
145 GST_BUFFER_TIMESTAMP (buffer) = 5 * GST_SECOND;
146 GST_BUFFER_DURATION (buffer) = 1 * GST_MSECOND;
148 GST_DEBUG ("sending buffer to be dropped");
149 fret = gst_pad_chain (sinkpad, buffer);
150 fail_if (fret != GST_FLOW_OK);
152 /* dropped buffer should not have finished preroll */
153 ret = gst_element_get_state (sink, NULL, NULL, 0);
154 fail_unless (ret == GST_STATE_CHANGE_ASYNC);
156 /* send buffer that should block and finish preroll */
161 GstState current, pending;
163 buffer = gst_buffer_new ();
164 GST_BUFFER_TIMESTAMP (buffer) = 1 * GST_SECOND;
165 GST_BUFFER_DURATION (buffer) = 1 * GST_MSECOND;
167 GST_DEBUG ("sending buffer to finish preroll");
168 data = chain_async (sinkpad, buffer);
169 fail_if (data == NULL);
171 /* state should now eventually change to PAUSED */
172 ret = gst_element_get_state (sink, ¤t, &pending, GST_CLOCK_TIME_NONE);
173 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
174 fail_unless (current == GST_STATE_PAUSED);
175 fail_unless (pending == GST_STATE_VOID_PENDING);
177 /* playing should render the buffer */
178 ret = gst_element_set_state (sink, GST_STATE_PLAYING);
179 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
181 /* and we should get a success return value */
182 fret = chain_async_return (data);
183 fail_if (fret != GST_FLOW_OK);
186 /* send some buffer that will be dropped or clipped, this can
187 * only be observed in the debug log. */
192 buffer = gst_buffer_new ();
193 GST_BUFFER_TIMESTAMP (buffer) = 6 * GST_SECOND;
194 GST_BUFFER_DURATION (buffer) = 1 * GST_MSECOND;
196 /* should be dropped */
197 GST_DEBUG ("sending buffer to drop");
198 fret = gst_pad_chain (sinkpad, buffer);
199 fail_if (fret != GST_FLOW_OK);
201 buffer = gst_buffer_new ();
202 GST_BUFFER_TIMESTAMP (buffer) = 0 * GST_SECOND;
203 GST_BUFFER_DURATION (buffer) = 2 * GST_SECOND;
205 /* should be clipped */
206 GST_DEBUG ("sending buffer to clip");
207 fret = gst_pad_chain (sinkpad, buffer);
208 fail_if (fret != GST_FLOW_OK);
210 buffer = gst_buffer_new ();
211 GST_BUFFER_TIMESTAMP (buffer) = 4 * GST_SECOND;
212 GST_BUFFER_DURATION (buffer) = 2 * GST_SECOND;
214 /* should be clipped */
215 GST_DEBUG ("sending buffer to clip");
216 fret = gst_pad_chain (sinkpad, buffer);
217 fail_if (fret != GST_FLOW_OK);
220 gst_element_set_state (sink, GST_STATE_NULL);
221 gst_element_get_state (sink, NULL, NULL, GST_CLOCK_TIME_NONE);
222 gst_object_unref (sinkpad);
223 gst_object_unref (sink);
228 static gint num_preroll = 0;
231 preroll_count (GstElement * sink)
234 GST_DEBUG ("got preroll handoff %d", num_preroll);
237 GST_START_TEST (test_preroll_sync)
239 GstElement *pipeline, *sink;
241 GstStateChangeReturn ret;
244 pipeline = gst_pipeline_new ("pipeline");
245 fail_if (pipeline == NULL);
247 sink = gst_element_factory_make ("fakesink", "sink");
248 fail_if (sink == NULL);
249 g_object_set (G_OBJECT (sink), "sync", TRUE, NULL);
250 g_object_set (G_OBJECT (sink), "signal-handoffs", TRUE, NULL);
251 g_signal_connect (sink, "preroll-handoff", G_CALLBACK (preroll_count), NULL);
253 fail_unless (num_preroll == 0);
255 gst_bin_add (GST_BIN (pipeline), sink);
257 sinkpad = gst_element_get_static_pad (sink, "sink");
258 fail_if (sinkpad == NULL);
260 /* make pipeline and element ready to accept data */
261 ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
262 fail_unless (ret == GST_STATE_CHANGE_ASYNC);
270 GST_DEBUG ("sending segment");
271 gst_segment_init (&segment, GST_FORMAT_TIME);
272 segment.start = 0 * GST_SECOND;
273 segment.stop = 102 * GST_SECOND;
274 segment.time = 0 * GST_SECOND;
276 event = gst_event_new_segment (&segment);
277 eret = gst_pad_send_event (sinkpad, event);
278 fail_if (eret == FALSE);
281 /* send buffer that should block and finish preroll */
286 GstState current, pending;
288 buffer = gst_buffer_new ();
289 GST_BUFFER_TIMESTAMP (buffer) = 1 * GST_SECOND;
290 GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND;
292 GST_DEBUG ("sending buffer to finish preroll");
293 data = chain_async (sinkpad, buffer);
294 fail_if (data == NULL);
296 /* state should now eventually change to PAUSED */
298 gst_element_get_state (pipeline, ¤t, &pending,
299 GST_CLOCK_TIME_NONE);
300 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
301 fail_unless (current == GST_STATE_PAUSED);
302 fail_unless (pending == GST_STATE_VOID_PENDING);
304 fail_unless (num_preroll == 1);
306 /* playing should render the buffer */
307 ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
308 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
310 /* and we should get a success return value */
311 fret = chain_async_return (data);
312 fail_if (fret != GST_FLOW_OK);
314 /* now we are playing no new preroll was done */
315 fail_unless (num_preroll == 1);
317 buffer = gst_buffer_new ();
318 /* far in the future to make sure we block */
319 GST_BUFFER_TIMESTAMP (buffer) = 100 * GST_SECOND;
320 GST_BUFFER_DURATION (buffer) = 100 * GST_SECOND;
321 data = chain_async (sinkpad, buffer);
322 fail_if (data == NULL);
326 /* pause again. Since the buffer has a humongous timestamp we likely
327 * interrupt the clock_wait and we should preroll on this buffer again */
328 ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
329 fail_unless (ret == GST_STATE_CHANGE_ASYNC);
332 gst_element_get_state (pipeline, ¤t, &pending,
333 GST_CLOCK_TIME_NONE);
334 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
335 fail_unless (current == GST_STATE_PAUSED);
336 fail_unless (pending == GST_STATE_VOID_PENDING);
338 fail_unless (num_preroll == 2);
341 ret = gst_element_set_state (pipeline, GST_STATE_READY);
342 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
344 /* should be wrong state now */
345 fret = chain_async_return (data);
346 fail_if (fret != GST_FLOW_WRONG_STATE);
348 gst_element_set_state (pipeline, GST_STATE_NULL);
349 gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
350 gst_object_unref (sinkpad);
351 gst_object_unref (pipeline);
356 /* after EOS, we refuse everything */
357 GST_START_TEST (test_eos)
359 GstElement *pipeline, *sink;
361 GstStateChangeReturn ret;
366 pipeline = gst_pipeline_new ("pipeline");
367 fail_if (pipeline == NULL);
369 bus = gst_pipeline_get_bus (GST_PIPELINE_CAST (pipeline));
370 fail_if (bus == NULL);
372 sink = gst_element_factory_make ("fakesink", "sink");
373 fail_if (sink == NULL);
374 g_object_set (G_OBJECT (sink), "sync", TRUE, NULL);
376 gst_bin_add (GST_BIN (pipeline), sink);
378 sinkpad = gst_element_get_static_pad (sink, "sink");
379 fail_if (sinkpad == NULL);
381 /* make pipeline and element ready to accept data */
382 ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
383 fail_unless (ret == GST_STATE_CHANGE_ASYNC);
385 /* send EOS, this should work fine */
390 GST_DEBUG ("sending EOS");
391 eos = gst_event_new_eos ();
393 eret = gst_pad_send_event (sinkpad, eos);
394 fail_if (eret == FALSE);
397 /* wait for preroll */
398 gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
400 /* EOS should be on the bus at some point */
404 /* blocking wait for messages */
405 message = gst_bus_timed_pop (bus, GST_CLOCK_TIME_NONE);
406 type = GST_MESSAGE_TYPE (message);
407 gst_message_unref (message);
409 GST_DEBUG ("got message %s", gst_message_type_get_name (type));
411 if (type == GST_MESSAGE_EOS)
414 gst_object_unref (bus);
416 /* send another EOS, this should fail */
421 GST_DEBUG ("sending second EOS");
422 eos = gst_event_new_eos ();
424 eret = gst_pad_send_event (sinkpad, eos);
425 fail_if (eret == TRUE);
428 /* send segment, this should fail */
434 GST_DEBUG ("sending segment");
435 gst_segment_init (&segment, GST_FORMAT_TIME);
436 segment.start = 0 * GST_SECOND;
437 segment.stop = 2 * GST_SECOND;
438 segment.time = 0 * GST_SECOND;
439 event = gst_event_new_segment (&segment);
441 eret = gst_pad_send_event (sinkpad, event);
442 fail_if (eret == TRUE);
445 /* send buffer that should fail after EOS */
450 buffer = gst_buffer_new ();
451 GST_BUFFER_TIMESTAMP (buffer) = 1 * GST_SECOND;
452 GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND;
454 GST_DEBUG ("sending buffer");
456 /* buffer after EOS is not UNEXPECTED */
457 fret = gst_pad_chain (sinkpad, buffer);
458 fail_unless (fret == GST_FLOW_UNEXPECTED);
461 /* flush, EOS state is flushed again. */
466 GST_DEBUG ("sending FLUSH_START");
467 event = gst_event_new_flush_start ();
468 eret = gst_pad_send_event (sinkpad, event);
469 fail_unless (eret == TRUE);
471 GST_DEBUG ("sending FLUSH_STOP");
472 event = gst_event_new_flush_stop ();
473 eret = gst_pad_send_event (sinkpad, event);
474 fail_unless (eret == TRUE);
477 /* send segment, this should now work again */
483 GST_DEBUG ("sending segment");
484 gst_segment_init (&segment, GST_FORMAT_TIME);
485 segment.start = 0 * GST_SECOND;
486 segment.stop = 2 * GST_SECOND;
487 segment.time = 0 * GST_SECOND;
488 event = gst_event_new_segment (&segment);
490 eret = gst_pad_send_event (sinkpad, event);
491 fail_unless (eret == TRUE);
494 /* send buffer that should work and block */
499 buffer = gst_buffer_new ();
500 GST_BUFFER_TIMESTAMP (buffer) = 1 * GST_SECOND;
501 GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND;
503 GST_DEBUG ("sending buffer");
505 fret = gst_pad_chain (sinkpad, buffer);
506 fail_unless (fret == GST_FLOW_OK);
509 gst_element_set_state (pipeline, GST_STATE_NULL);
510 gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
511 gst_object_unref (sinkpad);
512 gst_object_unref (pipeline);
517 /* test EOS triggered by the element */
518 GST_START_TEST (test_eos2)
520 GstElement *pipeline, *sink;
522 GstStateChangeReturn ret;
525 pipeline = gst_pipeline_new ("pipeline");
526 fail_if (pipeline == NULL);
528 sink = gst_element_factory_make ("fakesink", "sink");
529 fail_if (sink == NULL);
530 g_object_set (G_OBJECT (sink), "sync", TRUE, NULL);
531 g_object_set (G_OBJECT (sink), "num-buffers", 1, NULL);
533 gst_bin_add (GST_BIN (pipeline), sink);
535 sinkpad = gst_element_get_static_pad (sink, "sink");
536 fail_if (sinkpad == NULL);
538 /* make pipeline and element ready to accept data */
539 ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
540 fail_unless (ret == GST_STATE_CHANGE_ASYNC);
542 /* send segment, this should work */
548 GST_DEBUG ("sending segment");
549 gst_segment_init (&segment, GST_FORMAT_TIME);
550 segment.start = 0 * GST_SECOND;
551 segment.stop = 2 * GST_SECOND;
552 segment.time = 0 * GST_SECOND;
553 event = gst_event_new_segment (&segment);
555 eret = gst_pad_send_event (sinkpad, event);
556 fail_if (eret == FALSE);
559 /* send buffer that should return UNEXPECTED */
564 buffer = gst_buffer_new ();
565 GST_BUFFER_TIMESTAMP (buffer) = 1 * GST_SECOND;
566 GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND;
568 GST_DEBUG ("sending buffer");
570 /* this buffer will generate UNEXPECTED */
571 fret = gst_pad_chain (sinkpad, buffer);
572 fail_unless (fret == GST_FLOW_UNEXPECTED);
575 /* send buffer that should return UNEXPECTED */
580 buffer = gst_buffer_new ();
581 GST_BUFFER_TIMESTAMP (buffer) = 1 * GST_SECOND;
582 GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND;
584 GST_DEBUG ("sending buffer");
586 fret = gst_pad_chain (sinkpad, buffer);
587 fail_unless (fret == GST_FLOW_UNEXPECTED);
590 gst_element_set_state (pipeline, GST_STATE_NULL);
591 gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
592 gst_object_unref (sinkpad);
593 gst_object_unref (pipeline);
598 /* test position reporting before, during and after flush
599 * in PAUSED and PLAYING */
600 GST_START_TEST (test_position)
602 GstElement *pipeline, *sink;
604 GstStateChangeReturn ret;
616 pipeline = gst_pipeline_new ("pipeline");
617 fail_if (pipeline == NULL);
619 sink = gst_element_factory_make ("fakesink", "sink");
620 fail_if (sink == NULL);
621 g_object_set (G_OBJECT (sink), "sync", TRUE, NULL);
622 g_object_set (G_OBJECT (sink), "num-buffers", 2, NULL);
624 gst_bin_add (GST_BIN (pipeline), sink);
626 sinkpad = gst_element_get_static_pad (sink, "sink");
627 fail_if (sinkpad == NULL);
629 /* do position query, this should fail, we have nothing received yet */
630 qformat = GST_FORMAT_TIME;
631 qret = gst_element_query_position (sink, &qformat, &qcur);
632 fail_unless (qret == FALSE);
634 ret = gst_element_set_state (pipeline, GST_STATE_READY);
635 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
637 /* do position query, this should fail, we have nothing received yet */
638 qformat = GST_FORMAT_TIME;
639 qret = gst_element_query_position (sink, &qformat, &qcur);
640 fail_unless (qret == FALSE);
642 /* make pipeline and element ready to accept data */
643 ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
644 fail_unless (ret == GST_STATE_CHANGE_ASYNC);
646 /* do position query, this should fail, we have nothing received yet */
647 qformat = GST_FORMAT_TIME;
648 qret = gst_element_query_position (sink, &qformat, &qcur);
649 fail_unless (qret == FALSE);
651 /* send segment, this should work */
655 GST_DEBUG ("sending segment");
656 gst_segment_init (&segment, GST_FORMAT_TIME);
657 segment.start = 1 * GST_SECOND;
658 segment.stop = 3 * GST_SECOND;
659 segment.time = 1 * GST_SECOND;
660 event = gst_event_new_segment (&segment);
662 eret = gst_pad_send_event (sinkpad, event);
663 fail_if (eret == FALSE);
666 /* FIXME, do position query, this should succeed with the time value from the
668 qformat = GST_FORMAT_TIME;
669 qret = gst_element_query_position (sink, &qformat, &qcur);
670 fail_unless (qret == TRUE);
671 fail_unless (qcur == 1 * GST_SECOND);
673 /* send buffer that we will flush out */
674 buffer = gst_buffer_new ();
675 GST_BUFFER_TIMESTAMP (buffer) = 2 * GST_SECOND;
676 GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND;
678 GST_DEBUG ("sending buffer");
680 /* this buffer causes the sink to preroll */
681 data = chain_async (sinkpad, buffer);
682 fail_if (data == NULL);
684 /* wait for preroll */
685 ret = gst_element_get_state (pipeline, NULL, NULL, -1);
687 /* do position query, this should succeed with the time value from the
689 qformat = GST_FORMAT_TIME;
690 qret = gst_element_query_position (sink, &qformat, &qcur);
691 fail_unless (qret == TRUE);
692 fail_unless (qcur == 1 * GST_SECOND);
694 /* start flushing, no timing is affected yet */
696 GST_DEBUG ("sending flush_start");
697 event = gst_event_new_flush_start ();
699 eret = gst_pad_send_event (sinkpad, event);
700 fail_if (eret == FALSE);
703 /* preroll buffer is flushed out */
704 fret = chain_async_return (data);
705 fail_unless (fret == GST_FLOW_WRONG_STATE);
707 /* do position query, this should succeed with the time value from the
708 * segment before the flush. */
709 qformat = GST_FORMAT_TIME;
710 qret = gst_element_query_position (sink, &qformat, &qcur);
711 fail_unless (qret == TRUE);
712 fail_unless (qcur == 1 * GST_SECOND);
714 /* stop flushing, timing is affected now */
716 GST_DEBUG ("sending flush_stop");
717 event = gst_event_new_flush_stop ();
719 eret = gst_pad_send_event (sinkpad, event);
720 fail_if (eret == FALSE);
723 /* do position query, this should fail, the segment is flushed */
724 qformat = GST_FORMAT_TIME;
725 qret = gst_element_query_position (sink, &qformat, &qcur);
726 fail_unless (qret == FALSE);
728 /* send segment, this should work */
732 GST_DEBUG ("sending segment");
733 gst_segment_init (&segment, GST_FORMAT_TIME);
734 segment.start = 2 * GST_SECOND;
735 segment.stop = 4 * GST_SECOND;
736 segment.time = 1 * GST_SECOND;
737 event = gst_event_new_segment (&segment);
739 eret = gst_pad_send_event (sinkpad, event);
740 fail_if (eret == FALSE);
743 /* send buffer that should return OK */
744 buffer = gst_buffer_new ();
745 GST_BUFFER_TIMESTAMP (buffer) = 3 * GST_SECOND;
746 GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND;
748 GST_DEBUG ("sending buffer");
750 /* this buffer causes the sink to preroll */
751 data = chain_async (sinkpad, buffer);
752 fail_if (data == NULL);
754 /* wait for preroll */
755 ret = gst_element_get_state (pipeline, NULL, NULL, -1);
757 /* do position query, this should succeed with the time value from the
759 qformat = GST_FORMAT_TIME;
760 qret = gst_element_query_position (sink, &qformat, &qcur);
761 fail_unless (qret == TRUE);
762 fail_unless (qcur == 1 * GST_SECOND);
764 ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
765 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
767 /* position now is increasing but never exceeds the boundaries of the segment */
768 for (i = 0; i < 5; i++) {
769 qformat = GST_FORMAT_TIME;
770 qret = gst_element_query_position (sink, &qformat, &qcur);
771 GST_DEBUG ("position %" GST_TIME_FORMAT, GST_TIME_ARGS (qcur));
772 fail_unless (qret == TRUE);
773 fail_unless (qcur >= 1 * GST_SECOND && qcur <= 3 * GST_SECOND);
774 g_usleep (1000 * 250);
777 /* preroll buffer is rendered, we expect one more buffer after this one */
778 fret = chain_async_return (data);
779 fail_unless (fret == GST_FLOW_OK);
781 /* after rendering the position must be bigger then the stream_time of the
783 qformat = GST_FORMAT_TIME;
784 qret = gst_element_query_position (sink, &qformat, &qcur);
785 fail_unless (qret == TRUE);
786 fail_unless (qcur >= 2 * GST_SECOND && qcur <= 3 * GST_SECOND);
788 /* start flushing in PLAYING */
790 GST_DEBUG ("sending flush_start");
791 event = gst_event_new_flush_start ();
793 eret = gst_pad_send_event (sinkpad, event);
794 fail_if (eret == FALSE);
797 /* this should now just report the stream time of the last buffer */
798 qformat = GST_FORMAT_TIME;
799 qret = gst_element_query_position (sink, &qformat, &qcur);
800 fail_unless (qret == TRUE);
801 fail_unless (qcur == 2 * GST_SECOND);
804 GST_DEBUG ("sending flush_stop");
805 event = gst_event_new_flush_stop ();
807 eret = gst_pad_send_event (sinkpad, event);
808 fail_if (eret == FALSE);
811 /* do position query, this should fail, the segment is flushed */
812 qformat = GST_FORMAT_TIME;
813 qret = gst_element_query_position (sink, &qformat, &qcur);
814 fail_unless (qret == FALSE);
816 /* send segment, this should work */
820 GST_DEBUG ("sending segment");
821 gst_segment_init (&segment, GST_FORMAT_TIME);
822 segment.start = 2 * GST_SECOND;
823 segment.stop = 4 * GST_SECOND;
824 segment.time = 1 * GST_SECOND;
825 event = gst_event_new_segment (&segment);
827 eret = gst_pad_send_event (sinkpad, event);
828 fail_if (eret == FALSE);
831 /* send buffer that should return UNEXPECTED */
832 buffer = gst_buffer_new ();
833 GST_BUFFER_TIMESTAMP (buffer) = 3 * GST_SECOND;
834 GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND;
836 GST_DEBUG ("sending buffer");
838 /* this buffer causes the sink to preroll */
839 data = chain_async (sinkpad, buffer);
840 fail_if (data == NULL);
842 /* wait for preroll */
843 ret = gst_element_get_state (pipeline, NULL, NULL, -1);
845 /* preroll buffer is rendered, we expect no more buffer after this one */
846 fret = chain_async_return (data);
847 fail_unless (fret == GST_FLOW_UNEXPECTED);
849 /* do position query, this should succeed with the stream time of the buffer
850 * against the clock. Since the buffer is synced against the clock, the time
851 * should be at least the stream time of the buffer. */
852 qformat = GST_FORMAT_TIME;
853 qret = gst_element_query_position (sink, &qformat, &qcur);
854 fail_unless (qret == TRUE);
855 fail_unless (qcur >= 2 * GST_SECOND && qcur <= 3 * GST_SECOND);
857 /* wait 2 more seconds, enough to test if the position was clipped correctly
858 * against the segment */
859 g_usleep (2 * G_USEC_PER_SEC);
861 qformat = GST_FORMAT_TIME;
862 qret = gst_element_query_position (sink, &qformat, &qcur);
863 fail_unless (qret == TRUE);
864 fail_unless (qcur == 3 * GST_SECOND);
866 GST_DEBUG ("going to PAUSED");
868 ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
869 fail_unless (ret == GST_STATE_CHANGE_ASYNC);
871 /* we report the time of the last start of the buffer. This is slightly
872 * incorrect, we should report the exact time when we paused but there is no
873 * record of that anywhere */
874 qformat = GST_FORMAT_TIME;
875 qret = gst_element_query_position (sink, &qformat, &qcur);
876 fail_unless (qret == TRUE);
877 fail_unless (qcur >= 4 * GST_SECOND);
879 ret = gst_element_set_state (pipeline, GST_STATE_READY);
880 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
882 /* fails again because we are in the wrong state */
883 qformat = GST_FORMAT_TIME;
884 qret = gst_element_query_position (sink, &qformat, &qcur);
885 fail_unless (qret == FALSE);
887 gst_element_set_state (pipeline, GST_STATE_NULL);
889 qformat = GST_FORMAT_TIME;
890 qret = gst_element_query_position (sink, &qformat, &qcur);
891 fail_unless (qret == FALSE);
893 gst_object_unref (sinkpad);
894 gst_object_unref (pipeline);
899 /* like fakesrc, but also pushes an OOB event after each buffer */
900 typedef GstPushSrc OOBSource;
901 typedef GstPushSrcClass OOBSourceClass;
903 GType oob_source_get_type (void);
904 G_DEFINE_TYPE (OOBSource, oob_source, GST_TYPE_PUSH_SRC);
907 oob_source_create (GstPushSrc * src, GstBuffer ** p_buf)
909 *p_buf = gst_buffer_new ();
911 gst_pad_push_event (GST_BASE_SRC_PAD (src),
912 gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM_OOB, NULL));
918 oob_source_class_init (OOBSourceClass * klass)
920 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("src",
921 GST_PAD_SRC, GST_PAD_ALWAYS, GST_STATIC_CAPS_ANY);
922 GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
923 GstPushSrcClass *pushsrc_class = GST_PUSH_SRC_CLASS (klass);
925 gst_element_class_add_pad_template (element_class,
926 gst_static_pad_template_get (&sinktemplate));
928 pushsrc_class->create = GST_DEBUG_FUNCPTR (oob_source_create);
932 oob_source_init (OOBSource * src)
937 #define NOTIFY_RACE_NUM_PIPELINES 10
945 } NotifyRacePipeline;
948 test_notify_race_setup_pipeline (NotifyRacePipeline * p)
950 GST_DEBUG ("Creating pipeline");
951 p->pipe = gst_pipeline_new ("pipeline");
952 p->src = g_object_new (oob_source_get_type (), NULL);
954 p->queue = gst_element_factory_make ("queue", NULL);
955 g_object_set (p->queue, "max-size-buffers", 2, NULL);
957 p->sink = gst_element_factory_make ("fakesink", NULL);
958 gst_bin_add (GST_BIN (p->pipe), p->src);
959 gst_bin_add (GST_BIN (p->pipe), p->queue);
960 gst_bin_add (GST_BIN (p->pipe), p->sink);
961 gst_element_link_many (p->src, p->queue, p->sink, NULL);
963 GST_DEBUG ("Setting pipeline to PLAYING");
964 fail_unless_equals_int (gst_element_set_state (p->pipe, GST_STATE_PLAYING),
965 GST_STATE_CHANGE_ASYNC);
966 GST_DEBUG ("Getting state");
967 fail_unless_equals_int (gst_element_get_state (p->pipe, NULL, NULL, -1),
968 GST_STATE_CHANGE_SUCCESS);
972 test_notify_race_cleanup_pipeline (NotifyRacePipeline * p)
974 gst_element_set_state (p->pipe, GST_STATE_NULL);
975 gst_object_unref (p->pipe);
976 memset (p, 0, sizeof (NotifyRacePipeline));
979 /* we create N pipelines to make sure the notify race isn't per-class, but
980 * only per instance */
981 GST_START_TEST (test_notify_race)
983 NotifyRacePipeline pipelines[NOTIFY_RACE_NUM_PIPELINES];
986 for (i = 0; i < G_N_ELEMENTS (pipelines); ++i) {
987 GST_DEBUG ("Starting up pipeline %d", i);
988 test_notify_race_setup_pipeline (&pipelines[i]);
991 g_usleep (2 * G_USEC_PER_SEC);
993 for (i = 0; i < G_N_ELEMENTS (pipelines); ++i) {
994 GST_DEBUG ("Cleaning up pipeline %d", i);
995 test_notify_race_cleanup_pipeline (&pipelines[i]);
1002 fakesink_suite (void)
1004 Suite *s = suite_create ("fakesink");
1005 TCase *tc_chain = tcase_create ("general");
1007 tcase_set_timeout (tc_chain, 20);
1009 suite_add_tcase (s, tc_chain);
1010 tcase_add_test (tc_chain, test_clipping);
1011 tcase_add_test (tc_chain, test_preroll_sync);
1012 tcase_add_test (tc_chain, test_eos);
1013 tcase_add_test (tc_chain, test_eos2);
1014 tcase_add_test (tc_chain, test_position);
1015 tcase_add_test (tc_chain, test_notify_race);
1020 GST_CHECK_MAIN (fakesink);