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., 51 Franklin St, Fifth Floor,
22 * Boston, MA 02110-1301, 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;
61 g_thread_try_new ("gst-check", chain_async_buffer, chain_data, &error);
63 g_warning ("could not create thread reason: %s", error->message);
67 chain_data->thread = thread;
73 chain_async_return (ChainData * data)
77 g_thread_join (data->thread);
84 GST_START_TEST (test_clipping)
88 GstStateChangeReturn ret;
91 sink = gst_element_factory_make ("fakesink", "sink");
92 fail_if (sink == NULL);
94 sinkpad = gst_element_get_static_pad (sink, "sink");
95 fail_if (sinkpad == NULL);
97 /* make element ready to accept data */
98 ret = gst_element_set_state (sink, GST_STATE_PAUSED);
99 fail_unless (ret == GST_STATE_CHANGE_ASYNC);
107 GST_DEBUG ("sending segment");
108 gst_segment_init (&segment, GST_FORMAT_TIME);
109 segment.start = 1 * GST_SECOND;
110 segment.stop = 5 * GST_SECOND;
111 segment.time = 1 * GST_SECOND;
113 event = gst_event_new_segment (&segment);
115 eret = gst_pad_send_event (sinkpad, event);
116 fail_if (eret == FALSE);
119 /* new segment should not have finished preroll */
120 ret = gst_element_get_state (sink, NULL, NULL, 0);
121 fail_unless (ret == GST_STATE_CHANGE_ASYNC);
123 /* send buffer that should be dropped */
128 buffer = gst_buffer_new ();
129 GST_BUFFER_TIMESTAMP (buffer) = 0;
130 GST_BUFFER_DURATION (buffer) = 1 * GST_MSECOND;
132 GST_DEBUG ("sending buffer to be dropped");
133 fret = gst_pad_chain (sinkpad, buffer);
134 fail_if (fret != GST_FLOW_OK);
136 /* dropped buffer should not have finished preroll */
137 ret = gst_element_get_state (sink, NULL, NULL, 0);
138 fail_unless (ret == GST_STATE_CHANGE_ASYNC);
140 /* send buffer that should be dropped */
145 buffer = gst_buffer_new ();
146 GST_BUFFER_TIMESTAMP (buffer) = 5 * GST_SECOND;
147 GST_BUFFER_DURATION (buffer) = 1 * GST_MSECOND;
149 GST_DEBUG ("sending buffer to be dropped");
150 fret = gst_pad_chain (sinkpad, buffer);
151 fail_if (fret != GST_FLOW_OK);
153 /* dropped buffer should not have finished preroll */
154 ret = gst_element_get_state (sink, NULL, NULL, 0);
155 fail_unless (ret == GST_STATE_CHANGE_ASYNC);
157 /* send buffer that should block and finish preroll */
162 GstState current, pending;
164 buffer = gst_buffer_new ();
165 GST_BUFFER_TIMESTAMP (buffer) = 1 * GST_SECOND;
166 GST_BUFFER_DURATION (buffer) = 1 * GST_MSECOND;
168 GST_DEBUG ("sending buffer to finish preroll");
169 data = chain_async (sinkpad, buffer);
170 fail_if (data == NULL);
172 /* state should now eventually change to PAUSED */
173 ret = gst_element_get_state (sink, ¤t, &pending, GST_CLOCK_TIME_NONE);
174 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
175 fail_unless (current == GST_STATE_PAUSED);
176 fail_unless (pending == GST_STATE_VOID_PENDING);
178 /* playing should render the buffer */
179 ret = gst_element_set_state (sink, GST_STATE_PLAYING);
180 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
182 /* and we should get a success return value */
183 fret = chain_async_return (data);
184 fail_if (fret != GST_FLOW_OK);
187 /* send some buffer that will be dropped or clipped, this can
188 * only be observed in the debug log. */
193 buffer = gst_buffer_new ();
194 GST_BUFFER_TIMESTAMP (buffer) = 6 * GST_SECOND;
195 GST_BUFFER_DURATION (buffer) = 1 * GST_MSECOND;
197 /* should be dropped */
198 GST_DEBUG ("sending buffer to drop");
199 fret = gst_pad_chain (sinkpad, buffer);
200 fail_if (fret != GST_FLOW_OK);
202 buffer = gst_buffer_new ();
203 GST_BUFFER_TIMESTAMP (buffer) = 0 * GST_SECOND;
204 GST_BUFFER_DURATION (buffer) = 2 * GST_SECOND;
206 /* should be clipped */
207 GST_DEBUG ("sending buffer to clip");
208 fret = gst_pad_chain (sinkpad, buffer);
209 fail_if (fret != GST_FLOW_OK);
211 buffer = gst_buffer_new ();
212 GST_BUFFER_TIMESTAMP (buffer) = 4 * GST_SECOND;
213 GST_BUFFER_DURATION (buffer) = 2 * GST_SECOND;
215 /* should be clipped */
216 GST_DEBUG ("sending buffer to clip");
217 fret = gst_pad_chain (sinkpad, buffer);
218 fail_if (fret != GST_FLOW_OK);
221 gst_element_set_state (sink, GST_STATE_NULL);
222 gst_element_get_state (sink, NULL, NULL, GST_CLOCK_TIME_NONE);
223 gst_object_unref (sinkpad);
224 gst_object_unref (sink);
229 static gint num_preroll = 0;
232 preroll_count (GstElement * sink)
235 GST_DEBUG ("got preroll handoff %d", num_preroll);
238 GST_START_TEST (test_preroll_sync)
240 GstElement *pipeline, *sink;
242 GstStateChangeReturn ret;
245 pipeline = gst_pipeline_new ("pipeline");
246 fail_if (pipeline == NULL);
248 sink = gst_element_factory_make ("fakesink", "sink");
249 fail_if (sink == NULL);
250 g_object_set (G_OBJECT (sink), "sync", TRUE, NULL);
251 g_object_set (G_OBJECT (sink), "signal-handoffs", TRUE, NULL);
252 g_signal_connect (sink, "preroll-handoff", G_CALLBACK (preroll_count), NULL);
254 fail_unless (num_preroll == 0);
256 gst_bin_add (GST_BIN (pipeline), sink);
258 sinkpad = gst_element_get_static_pad (sink, "sink");
259 fail_if (sinkpad == NULL);
261 /* make pipeline and element ready to accept data */
262 ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
263 fail_unless (ret == GST_STATE_CHANGE_ASYNC);
271 GST_DEBUG ("sending segment");
272 gst_segment_init (&segment, GST_FORMAT_TIME);
273 segment.start = 0 * GST_SECOND;
274 segment.stop = 102 * GST_SECOND;
275 segment.time = 0 * GST_SECOND;
277 event = gst_event_new_segment (&segment);
278 eret = gst_pad_send_event (sinkpad, event);
279 fail_if (eret == FALSE);
282 /* send buffer that should block and finish preroll */
287 GstState current, pending;
289 buffer = gst_buffer_new ();
290 GST_BUFFER_TIMESTAMP (buffer) = 1 * GST_SECOND;
291 GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND;
293 GST_DEBUG ("sending buffer to finish preroll");
294 data = chain_async (sinkpad, buffer);
295 fail_if (data == NULL);
297 /* state should now eventually change to PAUSED */
299 gst_element_get_state (pipeline, ¤t, &pending,
300 GST_CLOCK_TIME_NONE);
301 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
302 fail_unless (current == GST_STATE_PAUSED);
303 fail_unless (pending == GST_STATE_VOID_PENDING);
305 fail_unless (num_preroll == 1);
307 /* playing should render the buffer */
308 ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
309 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
311 /* and we should get a success return value */
312 fret = chain_async_return (data);
313 fail_if (fret != GST_FLOW_OK);
315 /* now we are playing no new preroll was done */
316 fail_unless (num_preroll == 1);
318 buffer = gst_buffer_new ();
319 /* far in the future to make sure we block */
320 GST_BUFFER_TIMESTAMP (buffer) = 100 * GST_SECOND;
321 GST_BUFFER_DURATION (buffer) = 100 * GST_SECOND;
322 data = chain_async (sinkpad, buffer);
323 fail_if (data == NULL);
327 /* pause again. Since the buffer has a humongous timestamp we likely
328 * interrupt the clock_wait and we should preroll on this buffer again */
329 ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
330 fail_unless (ret == GST_STATE_CHANGE_ASYNC);
333 gst_element_get_state (pipeline, ¤t, &pending,
334 GST_CLOCK_TIME_NONE);
335 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
336 fail_unless (current == GST_STATE_PAUSED);
337 fail_unless (pending == GST_STATE_VOID_PENDING);
339 fail_unless (num_preroll == 2);
342 ret = gst_element_set_state (pipeline, GST_STATE_READY);
343 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
345 /* should be wrong state now */
346 fret = chain_async_return (data);
347 fail_if (fret != GST_FLOW_FLUSHING);
349 gst_element_set_state (pipeline, GST_STATE_NULL);
350 gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
351 gst_object_unref (sinkpad);
352 gst_object_unref (pipeline);
357 /* after EOS, we refuse everything */
358 GST_START_TEST (test_eos)
360 GstElement *pipeline, *sink;
362 GstStateChangeReturn ret;
367 pipeline = gst_pipeline_new ("pipeline");
368 fail_if (pipeline == NULL);
370 bus = gst_pipeline_get_bus (GST_PIPELINE_CAST (pipeline));
371 fail_if (bus == NULL);
373 sink = gst_element_factory_make ("fakesink", "sink");
374 fail_if (sink == NULL);
375 g_object_set (G_OBJECT (sink), "sync", TRUE, NULL);
377 gst_bin_add (GST_BIN (pipeline), sink);
379 sinkpad = gst_element_get_static_pad (sink, "sink");
380 fail_if (sinkpad == NULL);
382 /* make pipeline and element ready to accept data */
383 ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
384 fail_unless (ret == GST_STATE_CHANGE_ASYNC);
386 /* send EOS, this should work fine */
391 GST_DEBUG ("sending EOS");
392 eos = gst_event_new_eos ();
394 eret = gst_pad_send_event (sinkpad, eos);
395 fail_if (eret == FALSE);
398 /* wait for preroll */
399 gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
401 /* EOS should be on the bus at some point */
405 /* blocking wait for messages */
406 message = gst_bus_timed_pop (bus, GST_CLOCK_TIME_NONE);
407 type = GST_MESSAGE_TYPE (message);
408 gst_message_unref (message);
410 GST_DEBUG ("got message %s", gst_message_type_get_name (type));
412 if (type == GST_MESSAGE_EOS)
415 gst_object_unref (bus);
417 /* send another EOS, this should fail */
422 GST_DEBUG ("sending second EOS");
423 eos = gst_event_new_eos ();
425 eret = gst_pad_send_event (sinkpad, eos);
426 fail_if (eret == TRUE);
429 /* send segment, this should fail */
435 GST_DEBUG ("sending segment");
436 gst_segment_init (&segment, GST_FORMAT_TIME);
437 segment.start = 0 * GST_SECOND;
438 segment.stop = 2 * GST_SECOND;
439 segment.time = 0 * GST_SECOND;
440 event = gst_event_new_segment (&segment);
442 eret = gst_pad_send_event (sinkpad, event);
443 fail_if (eret == TRUE);
446 /* send buffer that should fail after EOS */
451 buffer = gst_buffer_new ();
452 GST_BUFFER_TIMESTAMP (buffer) = 1 * GST_SECOND;
453 GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND;
455 GST_DEBUG ("sending buffer");
457 /* buffer after EOS is not EOS */
458 fret = gst_pad_chain (sinkpad, buffer);
459 fail_unless (fret == GST_FLOW_EOS);
462 /* flush, EOS state is flushed again. */
467 GST_DEBUG ("sending FLUSH_START");
468 event = gst_event_new_flush_start ();
469 eret = gst_pad_send_event (sinkpad, event);
470 fail_unless (eret == TRUE);
472 GST_DEBUG ("sending FLUSH_STOP");
473 event = gst_event_new_flush_stop (TRUE);
474 eret = gst_pad_send_event (sinkpad, event);
475 fail_unless (eret == TRUE);
478 /* send segment, this should now work again */
484 GST_DEBUG ("sending segment");
485 gst_segment_init (&segment, GST_FORMAT_TIME);
486 segment.start = 0 * GST_SECOND;
487 segment.stop = 2 * GST_SECOND;
488 segment.time = 0 * GST_SECOND;
489 event = gst_event_new_segment (&segment);
491 eret = gst_pad_send_event (sinkpad, event);
492 fail_unless (eret == TRUE);
495 /* send buffer that should work and block */
500 buffer = gst_buffer_new ();
501 GST_BUFFER_TIMESTAMP (buffer) = 1 * GST_SECOND;
502 GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND;
504 GST_DEBUG ("sending buffer");
506 fret = gst_pad_chain (sinkpad, buffer);
507 fail_unless (fret == GST_FLOW_OK);
510 gst_element_set_state (pipeline, GST_STATE_NULL);
511 gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
512 gst_object_unref (sinkpad);
513 gst_object_unref (pipeline);
518 /* test EOS triggered by the element */
519 GST_START_TEST (test_eos2)
521 GstElement *pipeline, *sink;
523 GstStateChangeReturn ret;
526 pipeline = gst_pipeline_new ("pipeline");
527 fail_if (pipeline == NULL);
529 sink = gst_element_factory_make ("fakesink", "sink");
530 fail_if (sink == NULL);
531 g_object_set (G_OBJECT (sink), "sync", TRUE, NULL);
532 g_object_set (G_OBJECT (sink), "num-buffers", 1, NULL);
534 gst_bin_add (GST_BIN (pipeline), sink);
536 sinkpad = gst_element_get_static_pad (sink, "sink");
537 fail_if (sinkpad == NULL);
539 /* make pipeline and element ready to accept data */
540 ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
541 fail_unless (ret == GST_STATE_CHANGE_ASYNC);
543 /* send segment, this should work */
549 GST_DEBUG ("sending segment");
550 gst_segment_init (&segment, GST_FORMAT_TIME);
551 segment.start = 0 * GST_SECOND;
552 segment.stop = 2 * GST_SECOND;
553 segment.time = 0 * GST_SECOND;
554 event = gst_event_new_segment (&segment);
556 eret = gst_pad_send_event (sinkpad, event);
557 fail_if (eret == FALSE);
560 /* send buffer that should return EOS */
565 buffer = gst_buffer_new ();
566 GST_BUFFER_TIMESTAMP (buffer) = 1 * GST_SECOND;
567 GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND;
569 GST_DEBUG ("sending buffer");
571 /* this buffer will generate EOS */
572 fret = gst_pad_chain (sinkpad, buffer);
573 fail_unless (fret == GST_FLOW_EOS);
576 /* send buffer that should return EOS */
581 buffer = gst_buffer_new ();
582 GST_BUFFER_TIMESTAMP (buffer) = 1 * GST_SECOND;
583 GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND;
585 GST_DEBUG ("sending buffer");
587 fret = gst_pad_chain (sinkpad, buffer);
588 fail_unless (fret == GST_FLOW_EOS);
591 gst_element_set_state (pipeline, GST_STATE_NULL);
592 gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
593 gst_object_unref (sinkpad);
594 gst_object_unref (pipeline);
599 /* test position reporting before, during and after flush
600 * in PAUSED and PLAYING */
601 GST_START_TEST (test_position)
603 GstElement *pipeline, *sink;
605 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 qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur);
631 fail_unless (qret == FALSE);
633 ret = gst_element_set_state (pipeline, GST_STATE_READY);
634 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
636 /* do position query, this should fail, we have nothing received yet */
637 qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur);
638 fail_unless (qret == FALSE);
640 /* make pipeline and element ready to accept data */
641 ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
642 fail_unless (ret == GST_STATE_CHANGE_ASYNC);
644 /* do position query, this should fail, we have nothing received yet */
645 qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur);
646 fail_unless (qret == FALSE);
648 /* send segment, this should work */
652 GST_DEBUG ("sending segment");
653 gst_segment_init (&segment, GST_FORMAT_TIME);
654 segment.start = 1 * GST_SECOND;
655 segment.stop = 3 * GST_SECOND;
656 segment.time = 1 * GST_SECOND;
657 event = gst_event_new_segment (&segment);
659 eret = gst_pad_send_event (sinkpad, event);
660 fail_if (eret == FALSE);
663 /* FIXME, do position query, this should succeed with the time value from the
665 qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur);
666 fail_unless (qret == TRUE);
667 fail_unless (qcur == 1 * GST_SECOND);
669 /* send buffer that we will flush out */
670 buffer = gst_buffer_new ();
671 GST_BUFFER_TIMESTAMP (buffer) = 2 * GST_SECOND;
672 GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND;
674 GST_DEBUG ("sending buffer");
676 /* this buffer causes the sink to preroll */
677 data = chain_async (sinkpad, buffer);
678 fail_if (data == NULL);
680 /* wait for preroll */
681 ret = gst_element_get_state (pipeline, NULL, NULL, -1);
683 /* do position query, this should succeed with the time value from the
685 qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur);
686 fail_unless (qret == TRUE);
687 fail_unless (qcur == 1 * GST_SECOND);
689 /* start flushing, no timing is affected yet */
691 GST_DEBUG ("sending flush_start");
692 event = gst_event_new_flush_start ();
694 eret = gst_pad_send_event (sinkpad, event);
695 fail_if (eret == FALSE);
698 /* preroll buffer is flushed out */
699 fret = chain_async_return (data);
700 fail_unless (fret == GST_FLOW_FLUSHING);
702 /* do position query, this should succeed with the time value from the
703 * segment before the flush. */
704 qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur);
705 fail_unless (qret == TRUE);
706 fail_unless (qcur == 1 * GST_SECOND);
708 /* stop flushing, timing is affected now */
710 GST_DEBUG ("sending flush_stop");
711 event = gst_event_new_flush_stop (TRUE);
713 eret = gst_pad_send_event (sinkpad, event);
714 fail_if (eret == FALSE);
717 /* do position query, this should fail, the segment is flushed */
718 qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur);
719 fail_unless (qret == FALSE);
721 /* send segment, this should work */
725 GST_DEBUG ("sending segment");
726 gst_segment_init (&segment, GST_FORMAT_TIME);
727 segment.start = 2 * GST_SECOND;
728 segment.stop = 4 * GST_SECOND;
729 segment.time = 1 * GST_SECOND;
730 event = gst_event_new_segment (&segment);
732 eret = gst_pad_send_event (sinkpad, event);
733 fail_if (eret == FALSE);
736 /* send buffer that should return OK */
737 buffer = gst_buffer_new ();
738 GST_BUFFER_TIMESTAMP (buffer) = 3 * GST_SECOND;
739 GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND;
741 GST_DEBUG ("sending buffer");
743 /* this buffer causes the sink to preroll */
744 data = chain_async (sinkpad, buffer);
745 fail_if (data == NULL);
747 /* wait for preroll */
748 ret = gst_element_get_state (pipeline, NULL, NULL, -1);
750 /* do position query, this should succeed with the time value from the
752 qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur);
753 fail_unless (qret == TRUE);
754 fail_unless (qcur == 1 * GST_SECOND);
756 ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
757 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
759 /* position now is increasing but never exceeds the boundaries of the segment */
760 for (i = 0; i < 5; i++) {
761 qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur);
762 GST_DEBUG ("position %" GST_TIME_FORMAT, GST_TIME_ARGS (qcur));
763 fail_unless (qret == TRUE);
764 fail_unless (qcur >= 1 * GST_SECOND && qcur <= 3 * GST_SECOND);
765 g_usleep (1000 * 250);
768 /* preroll buffer is rendered, we expect one more buffer after this one */
769 fret = chain_async_return (data);
770 fail_unless (fret == GST_FLOW_OK);
772 /* after rendering the position must be bigger then the stream_time of the
774 qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur);
775 fail_unless (qret == TRUE);
776 fail_unless (qcur >= 2 * GST_SECOND && qcur <= 3 * GST_SECOND);
778 /* start flushing in PLAYING */
780 GST_DEBUG ("sending flush_start");
781 event = gst_event_new_flush_start ();
783 eret = gst_pad_send_event (sinkpad, event);
784 fail_if (eret == FALSE);
787 /* this should now just report the stream time of the last buffer */
788 qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur);
789 fail_unless (qret == TRUE);
790 fail_unless (qcur == 2 * GST_SECOND);
793 GST_DEBUG ("sending flush_stop");
794 event = gst_event_new_flush_stop (TRUE);
796 eret = gst_pad_send_event (sinkpad, event);
797 fail_if (eret == FALSE);
800 /* do position query, this should fail, the segment is flushed */
801 qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur);
802 fail_unless (qret == FALSE);
804 /* send segment, this should work */
808 GST_DEBUG ("sending segment");
809 gst_segment_init (&segment, GST_FORMAT_TIME);
810 segment.start = 2 * GST_SECOND;
811 segment.stop = 4 * GST_SECOND;
812 segment.time = 1 * GST_SECOND;
813 event = gst_event_new_segment (&segment);
815 eret = gst_pad_send_event (sinkpad, event);
816 fail_if (eret == FALSE);
819 /* send buffer that should return EOS */
820 buffer = gst_buffer_new ();
821 GST_BUFFER_TIMESTAMP (buffer) = 3 * GST_SECOND;
822 GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND;
824 GST_DEBUG ("sending buffer");
826 /* this buffer causes the sink to preroll */
827 data = chain_async (sinkpad, buffer);
828 fail_if (data == NULL);
830 /* wait for preroll */
831 ret = gst_element_get_state (pipeline, NULL, NULL, -1);
833 /* preroll buffer is rendered, we expect no more buffer after this one */
834 fret = chain_async_return (data);
835 fail_unless (fret == GST_FLOW_EOS);
837 /* do position query, this should succeed with the stream time of the buffer
838 * against the clock. Since the buffer is synced against the clock, the time
839 * should be at least the stream time of the buffer. */
840 qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur);
841 fail_unless (qret == TRUE);
842 fail_unless (qcur >= 2 * GST_SECOND && qcur <= 3 * GST_SECOND);
844 /* wait 2 more seconds, enough to test if the position was clipped correctly
845 * against the segment */
846 g_usleep (2 * G_USEC_PER_SEC);
848 qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur);
849 fail_unless (qret == TRUE);
850 fail_unless (qcur == 3 * GST_SECOND);
852 GST_DEBUG ("going to PAUSED");
854 ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
855 fail_unless (ret == GST_STATE_CHANGE_ASYNC);
857 /* we report the time of the last start of the buffer. This is slightly
858 * incorrect, we should report the exact time when we paused but there is no
859 * record of that anywhere */
860 qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur);
861 fail_unless (qret == TRUE);
862 fail_unless (qcur >= 4 * GST_SECOND);
864 ret = gst_element_set_state (pipeline, GST_STATE_READY);
865 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
867 /* fails again because we are in the wrong state */
868 qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur);
869 fail_unless (qret == FALSE);
871 gst_element_set_state (pipeline, GST_STATE_NULL);
873 qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur);
874 fail_unless (qret == FALSE);
876 gst_object_unref (sinkpad);
877 gst_object_unref (pipeline);
882 /* like fakesrc, but also pushes an OOB event after each buffer */
883 typedef GstPushSrc OOBSource;
884 typedef GstPushSrcClass OOBSourceClass;
886 GType oob_source_get_type (void);
887 G_DEFINE_TYPE (OOBSource, oob_source, GST_TYPE_PUSH_SRC);
890 oob_source_create (GstPushSrc * src, GstBuffer ** p_buf)
892 *p_buf = gst_buffer_new ();
894 gst_pad_push_event (GST_BASE_SRC_PAD (src),
895 gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM_OOB, NULL));
901 oob_source_class_init (OOBSourceClass * klass)
903 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("src",
904 GST_PAD_SRC, GST_PAD_ALWAYS, GST_STATIC_CAPS_ANY);
905 GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
906 GstPushSrcClass *pushsrc_class = GST_PUSH_SRC_CLASS (klass);
908 gst_element_class_add_pad_template (element_class,
909 gst_static_pad_template_get (&sinktemplate));
911 pushsrc_class->create = GST_DEBUG_FUNCPTR (oob_source_create);
915 oob_source_init (OOBSource * src)
920 #define NOTIFY_RACE_NUM_PIPELINES 10
928 } NotifyRacePipeline;
931 test_notify_race_setup_pipeline (NotifyRacePipeline * p)
933 GST_DEBUG ("Creating pipeline");
934 p->pipe = gst_pipeline_new ("pipeline");
935 p->src = g_object_new (oob_source_get_type (), NULL);
937 p->queue = gst_element_factory_make ("queue", NULL);
938 g_object_set (p->queue, "max-size-buffers", 2, NULL);
940 p->sink = gst_element_factory_make ("fakesink", NULL);
941 gst_bin_add (GST_BIN (p->pipe), p->src);
942 gst_bin_add (GST_BIN (p->pipe), p->queue);
943 gst_bin_add (GST_BIN (p->pipe), p->sink);
944 gst_element_link_many (p->src, p->queue, p->sink, NULL);
946 GST_DEBUG ("Setting pipeline to PLAYING");
947 fail_unless_equals_int (gst_element_set_state (p->pipe, GST_STATE_PLAYING),
948 GST_STATE_CHANGE_ASYNC);
949 GST_DEBUG ("Getting state");
950 fail_unless_equals_int (gst_element_get_state (p->pipe, NULL, NULL, -1),
951 GST_STATE_CHANGE_SUCCESS);
955 test_notify_race_cleanup_pipeline (NotifyRacePipeline * p)
957 gst_element_set_state (p->pipe, GST_STATE_NULL);
958 gst_object_unref (p->pipe);
959 memset (p, 0, sizeof (NotifyRacePipeline));
962 /* we create N pipelines to make sure the notify race isn't per-class, but
963 * only per instance */
964 GST_START_TEST (test_notify_race)
966 NotifyRacePipeline pipelines[NOTIFY_RACE_NUM_PIPELINES];
969 for (i = 0; i < G_N_ELEMENTS (pipelines); ++i) {
970 GST_DEBUG ("Starting up pipeline %d", i);
971 test_notify_race_setup_pipeline (&pipelines[i]);
974 g_usleep (2 * G_USEC_PER_SEC);
976 for (i = 0; i < G_N_ELEMENTS (pipelines); ++i) {
977 GST_DEBUG ("Cleaning up pipeline %d", i);
978 test_notify_race_cleanup_pipeline (&pipelines[i]);
985 fakesink_suite (void)
987 Suite *s = suite_create ("fakesink");
988 TCase *tc_chain = tcase_create ("general");
990 tcase_set_timeout (tc_chain, 20);
992 suite_add_tcase (s, tc_chain);
993 tcase_add_test (tc_chain, test_clipping);
994 tcase_add_test (tc_chain, test_preroll_sync);
995 tcase_add_test (tc_chain, test_eos);
996 tcase_add_test (tc_chain, test_eos2);
997 tcase_add_test (tc_chain, test_position);
998 tcase_add_test (tc_chain, test_notify_race);
1003 GST_CHECK_MAIN (fakesink);