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.
28 #include <gst/base/gstpushsrc.h>
29 #include <gst/check/gstcheck.h>
40 chain_async_buffer (gpointer data)
42 ChainData *chain_data = (ChainData *) data;
44 chain_data->ret = gst_pad_chain (chain_data->pad, chain_data->buffer);
50 chain_async (GstPad * pad, GstBuffer * buffer)
53 ChainData *chain_data;
56 chain_data = g_new (ChainData, 1);
57 chain_data->pad = pad;
58 chain_data->buffer = buffer;
59 chain_data->ret = GST_FLOW_ERROR;
62 g_thread_try_new ("gst-check", chain_async_buffer, chain_data, &error);
64 g_warning ("could not create thread reason: %s", error->message);
68 chain_data->thread = thread;
74 chain_async_return (ChainData * data)
78 g_thread_join (data->thread);
85 GST_START_TEST (test_clipping)
89 GstStateChangeReturn ret;
92 sink = gst_element_factory_make ("fakesink", "sink");
93 fail_if (sink == NULL);
95 sinkpad = gst_element_get_static_pad (sink, "sink");
96 fail_if (sinkpad == NULL);
98 /* make element ready to accept data */
99 ret = gst_element_set_state (sink, GST_STATE_PAUSED);
100 fail_unless (ret == GST_STATE_CHANGE_ASYNC);
102 gst_pad_send_event (sinkpad, gst_event_new_stream_start ("test"));
110 GST_DEBUG ("sending segment");
111 gst_segment_init (&segment, GST_FORMAT_TIME);
112 segment.start = 1 * GST_SECOND;
113 segment.stop = 5 * GST_SECOND;
114 segment.time = 1 * GST_SECOND;
116 event = gst_event_new_segment (&segment);
118 eret = gst_pad_send_event (sinkpad, event);
119 fail_if (eret == FALSE);
122 /* new segment should not have finished preroll */
123 ret = gst_element_get_state (sink, NULL, NULL, 0);
124 fail_unless (ret == GST_STATE_CHANGE_ASYNC);
126 /* send buffer that should be dropped */
131 buffer = gst_buffer_new ();
132 GST_BUFFER_TIMESTAMP (buffer) = 0;
133 GST_BUFFER_DURATION (buffer) = 1 * GST_MSECOND;
135 GST_DEBUG ("sending buffer to be dropped");
136 fret = gst_pad_chain (sinkpad, buffer);
137 fail_if (fret != GST_FLOW_OK);
139 /* dropped buffer should not have finished preroll */
140 ret = gst_element_get_state (sink, NULL, NULL, 0);
141 fail_unless (ret == GST_STATE_CHANGE_ASYNC);
143 /* send buffer that should be dropped */
148 buffer = gst_buffer_new ();
149 GST_BUFFER_TIMESTAMP (buffer) = 5 * GST_SECOND;
150 GST_BUFFER_DURATION (buffer) = 1 * GST_MSECOND;
152 GST_DEBUG ("sending buffer to be dropped");
153 fret = gst_pad_chain (sinkpad, buffer);
154 fail_if (fret != GST_FLOW_OK);
156 /* dropped buffer should not have finished preroll */
157 ret = gst_element_get_state (sink, NULL, NULL, 0);
158 fail_unless (ret == GST_STATE_CHANGE_ASYNC);
160 /* send buffer that should block and finish preroll */
165 GstState current, pending;
167 buffer = gst_buffer_new ();
168 GST_BUFFER_TIMESTAMP (buffer) = 1 * GST_SECOND;
169 GST_BUFFER_DURATION (buffer) = 1 * GST_MSECOND;
171 GST_DEBUG ("sending buffer to finish preroll");
172 data = chain_async (sinkpad, buffer);
173 fail_if (data == NULL);
175 /* state should now eventually change to PAUSED */
176 ret = gst_element_get_state (sink, ¤t, &pending, GST_CLOCK_TIME_NONE);
177 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
178 fail_unless (current == GST_STATE_PAUSED);
179 fail_unless (pending == GST_STATE_VOID_PENDING);
181 /* playing should render the buffer */
182 ret = gst_element_set_state (sink, GST_STATE_PLAYING);
183 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
185 /* and we should get a success return value */
186 fret = chain_async_return (data);
187 fail_if (fret != GST_FLOW_OK);
190 /* send some buffer that will be dropped or clipped, this can
191 * only be observed in the debug log. */
196 buffer = gst_buffer_new ();
197 GST_BUFFER_TIMESTAMP (buffer) = 6 * GST_SECOND;
198 GST_BUFFER_DURATION (buffer) = 1 * GST_MSECOND;
200 /* should be dropped */
201 GST_DEBUG ("sending buffer to drop");
202 fret = gst_pad_chain (sinkpad, buffer);
203 fail_if (fret != GST_FLOW_OK);
205 buffer = gst_buffer_new ();
206 GST_BUFFER_TIMESTAMP (buffer) = 0 * GST_SECOND;
207 GST_BUFFER_DURATION (buffer) = 2 * GST_SECOND;
209 /* should be clipped */
210 GST_DEBUG ("sending buffer to clip");
211 fret = gst_pad_chain (sinkpad, buffer);
212 fail_if (fret != GST_FLOW_OK);
214 buffer = gst_buffer_new ();
215 GST_BUFFER_TIMESTAMP (buffer) = 4 * GST_SECOND;
216 GST_BUFFER_DURATION (buffer) = 2 * GST_SECOND;
218 /* should be clipped */
219 GST_DEBUG ("sending buffer to clip");
220 fret = gst_pad_chain (sinkpad, buffer);
221 fail_if (fret != GST_FLOW_OK);
224 gst_element_set_state (sink, GST_STATE_NULL);
225 gst_element_get_state (sink, NULL, NULL, GST_CLOCK_TIME_NONE);
226 gst_object_unref (sinkpad);
227 gst_object_unref (sink);
232 static gint num_preroll = 0;
235 preroll_count (GstElement * sink)
238 GST_DEBUG ("got preroll handoff %d", num_preroll);
241 GST_START_TEST (test_preroll_sync)
243 GstElement *pipeline, *sink;
245 GstStateChangeReturn ret;
248 pipeline = gst_pipeline_new ("pipeline");
249 fail_if (pipeline == NULL);
251 sink = gst_element_factory_make ("fakesink", "sink");
252 fail_if (sink == NULL);
253 g_object_set (G_OBJECT (sink), "sync", TRUE, NULL);
254 g_object_set (G_OBJECT (sink), "signal-handoffs", TRUE, NULL);
255 g_signal_connect (sink, "preroll-handoff", G_CALLBACK (preroll_count), NULL);
257 fail_unless (num_preroll == 0);
259 gst_bin_add (GST_BIN (pipeline), sink);
261 sinkpad = gst_element_get_static_pad (sink, "sink");
262 fail_if (sinkpad == NULL);
264 /* make pipeline and element ready to accept data */
265 ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
266 fail_unless (ret == GST_STATE_CHANGE_ASYNC);
268 gst_pad_send_event (sinkpad, gst_event_new_stream_start ("test"));
276 GST_DEBUG ("sending segment");
277 gst_segment_init (&segment, GST_FORMAT_TIME);
278 segment.start = 0 * GST_SECOND;
279 segment.stop = 102 * GST_SECOND;
280 segment.time = 0 * GST_SECOND;
282 event = gst_event_new_segment (&segment);
283 eret = gst_pad_send_event (sinkpad, event);
284 fail_if (eret == FALSE);
287 /* send buffer that should block and finish preroll */
292 GstState current, pending;
294 buffer = gst_buffer_new ();
295 GST_BUFFER_TIMESTAMP (buffer) = 1 * GST_SECOND;
296 GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND;
298 GST_DEBUG ("sending buffer to finish preroll");
299 data = chain_async (sinkpad, buffer);
300 fail_if (data == NULL);
302 /* state should now eventually change to PAUSED */
304 gst_element_get_state (pipeline, ¤t, &pending,
305 GST_CLOCK_TIME_NONE);
306 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
307 fail_unless (current == GST_STATE_PAUSED);
308 fail_unless (pending == GST_STATE_VOID_PENDING);
310 fail_unless (num_preroll == 1);
312 /* playing should render the buffer */
313 ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
314 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
316 /* and we should get a success return value */
317 fret = chain_async_return (data);
318 fail_if (fret != GST_FLOW_OK);
320 /* now we are playing no new preroll was done */
321 fail_unless (num_preroll == 1);
323 buffer = gst_buffer_new ();
324 /* far in the future to make sure we block */
325 GST_BUFFER_TIMESTAMP (buffer) = 100 * GST_SECOND;
326 GST_BUFFER_DURATION (buffer) = 100 * GST_SECOND;
327 data = chain_async (sinkpad, buffer);
328 fail_if (data == NULL);
332 /* pause again. Since the buffer has a humongous timestamp we likely
333 * interrupt the clock_wait and we should preroll on this buffer again */
334 ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
335 fail_unless (ret == GST_STATE_CHANGE_ASYNC);
338 gst_element_get_state (pipeline, ¤t, &pending,
339 GST_CLOCK_TIME_NONE);
340 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
341 fail_unless (current == GST_STATE_PAUSED);
342 fail_unless (pending == GST_STATE_VOID_PENDING);
344 fail_unless (num_preroll == 2);
347 ret = gst_element_set_state (pipeline, GST_STATE_READY);
348 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
350 /* should be wrong state now */
351 fret = chain_async_return (data);
352 fail_if (fret != GST_FLOW_FLUSHING);
354 gst_element_set_state (pipeline, GST_STATE_NULL);
355 gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
356 gst_object_unref (sinkpad);
357 gst_object_unref (pipeline);
362 /* after EOS, we refuse everything */
363 GST_START_TEST (test_eos)
365 GstElement *pipeline, *sink;
367 GstStateChangeReturn ret;
372 pipeline = gst_pipeline_new ("pipeline");
373 fail_if (pipeline == NULL);
375 bus = gst_pipeline_get_bus (GST_PIPELINE_CAST (pipeline));
376 fail_if (bus == NULL);
378 sink = gst_element_factory_make ("fakesink", "sink");
379 fail_if (sink == NULL);
380 g_object_set (G_OBJECT (sink), "sync", TRUE, NULL);
382 gst_bin_add (GST_BIN (pipeline), sink);
384 sinkpad = gst_element_get_static_pad (sink, "sink");
385 fail_if (sinkpad == NULL);
387 /* make pipeline and element ready to accept data */
388 ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
389 fail_unless (ret == GST_STATE_CHANGE_ASYNC);
391 /* send EOS, this should work fine */
396 GST_DEBUG ("sending EOS");
397 eos = gst_event_new_eos ();
399 eret = gst_pad_send_event (sinkpad, eos);
400 fail_if (eret == FALSE);
403 /* wait for preroll */
404 gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
406 /* EOS should be on the bus at some point */
410 /* blocking wait for messages */
411 message = gst_bus_timed_pop (bus, GST_CLOCK_TIME_NONE);
412 type = GST_MESSAGE_TYPE (message);
413 gst_message_unref (message);
415 GST_DEBUG ("got message %s", gst_message_type_get_name (type));
417 if (type == GST_MESSAGE_EOS)
420 gst_object_unref (bus);
422 /* send another EOS, this should fail */
427 GST_DEBUG ("sending second EOS");
428 eos = gst_event_new_eos ();
430 eret = gst_pad_send_event (sinkpad, eos);
431 fail_if (eret == TRUE);
434 /* send segment, this should fail */
440 GST_DEBUG ("sending segment");
441 gst_segment_init (&segment, GST_FORMAT_TIME);
442 segment.start = 0 * GST_SECOND;
443 segment.stop = 2 * GST_SECOND;
444 segment.time = 0 * GST_SECOND;
445 event = gst_event_new_segment (&segment);
447 eret = gst_pad_send_event (sinkpad, event);
448 fail_if (eret == TRUE);
451 /* send buffer that should fail after EOS */
456 buffer = gst_buffer_new ();
457 GST_BUFFER_TIMESTAMP (buffer) = 1 * GST_SECOND;
458 GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND;
460 GST_DEBUG ("sending buffer");
462 /* buffer after EOS is not EOS */
463 fret = gst_pad_chain (sinkpad, buffer);
464 fail_unless (fret == GST_FLOW_EOS);
467 /* flush, EOS state is flushed again. */
472 GST_DEBUG ("sending FLUSH_START");
473 event = gst_event_new_flush_start ();
474 eret = gst_pad_send_event (sinkpad, event);
475 fail_unless (eret == TRUE);
477 GST_DEBUG ("sending FLUSH_STOP");
478 event = gst_event_new_flush_stop (TRUE);
479 eret = gst_pad_send_event (sinkpad, event);
480 fail_unless (eret == TRUE);
483 gst_pad_send_event (sinkpad, gst_event_new_stream_start ("test"));
485 /* send segment, this should now work again */
491 GST_DEBUG ("sending segment");
492 gst_segment_init (&segment, GST_FORMAT_TIME);
493 segment.start = 0 * GST_SECOND;
494 segment.stop = 2 * GST_SECOND;
495 segment.time = 0 * GST_SECOND;
496 event = gst_event_new_segment (&segment);
498 eret = gst_pad_send_event (sinkpad, event);
499 fail_unless (eret == TRUE);
502 /* send buffer that should work and block */
507 buffer = gst_buffer_new ();
508 GST_BUFFER_TIMESTAMP (buffer) = 1 * GST_SECOND;
509 GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND;
511 GST_DEBUG ("sending buffer");
513 fret = gst_pad_chain (sinkpad, buffer);
514 fail_unless (fret == GST_FLOW_OK);
517 gst_element_set_state (pipeline, GST_STATE_NULL);
518 gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
519 gst_object_unref (sinkpad);
520 gst_object_unref (pipeline);
525 /* test EOS triggered by the element */
526 GST_START_TEST (test_eos2)
528 GstElement *pipeline, *sink;
530 GstStateChangeReturn ret;
533 pipeline = gst_pipeline_new ("pipeline");
534 fail_if (pipeline == NULL);
536 sink = gst_element_factory_make ("fakesink", "sink");
537 fail_if (sink == NULL);
538 g_object_set (G_OBJECT (sink), "sync", TRUE, NULL);
539 g_object_set (G_OBJECT (sink), "num-buffers", 1, NULL);
541 gst_bin_add (GST_BIN (pipeline), sink);
543 sinkpad = gst_element_get_static_pad (sink, "sink");
544 fail_if (sinkpad == NULL);
546 /* make pipeline and element ready to accept data */
547 ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
548 fail_unless (ret == GST_STATE_CHANGE_ASYNC);
550 gst_pad_send_event (sinkpad, gst_event_new_stream_start ("test"));
552 /* send segment, this should work */
558 GST_DEBUG ("sending segment");
559 gst_segment_init (&segment, GST_FORMAT_TIME);
560 segment.start = 0 * GST_SECOND;
561 segment.stop = 2 * GST_SECOND;
562 segment.time = 0 * GST_SECOND;
563 event = gst_event_new_segment (&segment);
565 eret = gst_pad_send_event (sinkpad, event);
566 fail_if (eret == FALSE);
569 /* send buffer that should return EOS */
574 buffer = gst_buffer_new ();
575 GST_BUFFER_TIMESTAMP (buffer) = 1 * GST_SECOND;
576 GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND;
578 GST_DEBUG ("sending buffer");
580 /* this buffer will generate EOS */
581 fret = gst_pad_chain (sinkpad, buffer);
582 fail_unless (fret == GST_FLOW_EOS);
585 /* send buffer that should return EOS */
590 buffer = gst_buffer_new ();
591 GST_BUFFER_TIMESTAMP (buffer) = 1 * GST_SECOND;
592 GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND;
594 GST_DEBUG ("sending buffer");
596 fret = gst_pad_chain (sinkpad, buffer);
597 fail_unless (fret == GST_FLOW_EOS);
600 gst_element_set_state (pipeline, GST_STATE_NULL);
601 gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
602 gst_object_unref (sinkpad);
603 gst_object_unref (pipeline);
608 /* test position reporting before, during and after flush
609 * in PAUSED and PLAYING */
610 GST_START_TEST (test_position)
612 GstElement *pipeline, *sink;
614 GstStateChangeReturn ret;
625 pipeline = gst_pipeline_new ("pipeline");
626 fail_if (pipeline == NULL);
628 sink = gst_element_factory_make ("fakesink", "sink");
629 fail_if (sink == NULL);
630 g_object_set (G_OBJECT (sink), "sync", TRUE, NULL);
631 g_object_set (G_OBJECT (sink), "num-buffers", 2, NULL);
633 gst_bin_add (GST_BIN (pipeline), sink);
635 sinkpad = gst_element_get_static_pad (sink, "sink");
636 fail_if (sinkpad == NULL);
638 /* do position query, this should fail, we have nothing received yet */
639 qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur);
640 fail_unless (qret == FALSE);
642 ret = gst_element_set_state (pipeline, GST_STATE_READY);
643 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
645 /* do position query, this should fail, we have nothing received yet */
646 qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur);
647 fail_unless (qret == FALSE);
649 /* make pipeline and element ready to accept data */
650 ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
651 fail_unless (ret == GST_STATE_CHANGE_ASYNC);
653 /* do position query, this should fail, we have nothing received yet */
654 qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur);
655 fail_unless (qret == FALSE);
657 gst_pad_send_event (sinkpad, gst_event_new_stream_start ("test"));
659 /* send segment, this should work */
663 GST_DEBUG ("sending segment");
664 gst_segment_init (&segment, GST_FORMAT_TIME);
665 segment.start = 1 * GST_SECOND;
666 segment.stop = 3 * GST_SECOND;
667 segment.time = 1 * GST_SECOND;
668 event = gst_event_new_segment (&segment);
670 eret = gst_pad_send_event (sinkpad, event);
671 fail_if (eret == FALSE);
674 /* FIXME, do position query, this should succeed with the time value from the
676 qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur);
677 fail_unless (qret == TRUE);
678 fail_unless (qcur == 1 * GST_SECOND);
680 /* send buffer that we will flush out */
681 buffer = gst_buffer_new ();
682 GST_BUFFER_TIMESTAMP (buffer) = 2 * GST_SECOND;
683 GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND;
685 GST_DEBUG ("sending buffer");
687 /* this buffer causes the sink to preroll */
688 data = chain_async (sinkpad, buffer);
689 fail_if (data == NULL);
691 /* wait for preroll */
692 ret = gst_element_get_state (pipeline, NULL, NULL, -1);
694 /* do position query, this should succeed with the time value from the
696 qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur);
697 fail_unless (qret == TRUE);
698 fail_unless (qcur == 1 * GST_SECOND);
700 /* start flushing, no timing is affected yet */
702 GST_DEBUG ("sending flush_start");
703 event = gst_event_new_flush_start ();
705 eret = gst_pad_send_event (sinkpad, event);
706 fail_if (eret == FALSE);
709 /* preroll buffer is flushed out */
710 fret = chain_async_return (data);
711 fail_unless (fret == GST_FLOW_FLUSHING);
713 /* do position query, this should succeed with the time value from the
714 * segment before the flush. */
715 qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur);
716 fail_unless (qret == TRUE);
717 fail_unless (qcur == 1 * GST_SECOND);
719 /* stop flushing, timing is affected now */
721 GST_DEBUG ("sending flush_stop");
722 event = gst_event_new_flush_stop (TRUE);
724 eret = gst_pad_send_event (sinkpad, event);
725 fail_if (eret == FALSE);
728 /* do position query, this should fail, the segment is flushed */
729 qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur);
730 fail_unless (qret == FALSE);
732 /* send segment, this should work */
736 GST_DEBUG ("sending segment");
737 gst_segment_init (&segment, GST_FORMAT_TIME);
738 segment.start = 2 * GST_SECOND;
739 segment.stop = 4 * GST_SECOND;
740 segment.time = 1 * GST_SECOND;
741 event = gst_event_new_segment (&segment);
743 eret = gst_pad_send_event (sinkpad, event);
744 fail_if (eret == FALSE);
747 /* send buffer that should return OK */
748 buffer = gst_buffer_new ();
749 GST_BUFFER_TIMESTAMP (buffer) = 3 * GST_SECOND;
750 GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND;
752 GST_DEBUG ("sending buffer");
754 /* this buffer causes the sink to preroll */
755 data = chain_async (sinkpad, buffer);
756 fail_if (data == NULL);
758 /* wait for preroll */
759 ret = gst_element_get_state (pipeline, NULL, NULL, -1);
761 /* do position query, this should succeed with the time value from the
763 qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur);
764 fail_unless (qret == TRUE);
765 fail_unless (qcur == 1 * GST_SECOND);
767 ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
768 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
770 /* position now is increasing but never exceeds the boundaries of the segment */
771 for (i = 0; i < 5; i++) {
772 qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur);
773 GST_DEBUG ("position %" GST_TIME_FORMAT, GST_TIME_ARGS (qcur));
774 fail_unless (qret == TRUE);
775 fail_unless (qcur >= 1 * GST_SECOND && qcur <= 3 * GST_SECOND);
776 g_usleep (1000 * 250);
779 /* preroll buffer is rendered, we expect one more buffer after this one */
780 fret = chain_async_return (data);
781 fail_unless (fret == GST_FLOW_OK);
783 /* after rendering the position must be bigger then the stream_time of the
785 qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur);
786 fail_unless (qret == TRUE);
787 fail_unless (qcur >= 2 * GST_SECOND && qcur <= 3 * GST_SECOND);
789 /* start flushing in PLAYING */
791 GST_DEBUG ("sending flush_start");
792 event = gst_event_new_flush_start ();
794 eret = gst_pad_send_event (sinkpad, event);
795 fail_if (eret == FALSE);
798 /* this should now just report the last stream time */
799 qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur);
800 fail_unless (qret == TRUE);
801 fail_unless (qcur >= 2 * GST_SECOND && qcur <= 3 * GST_SECOND);
804 GST_DEBUG ("sending flush_stop");
805 event = gst_event_new_flush_stop (TRUE);
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 qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur);
813 fail_unless (qret == FALSE);
815 /* send segment, this should work */
819 GST_DEBUG ("sending segment");
820 gst_segment_init (&segment, GST_FORMAT_TIME);
821 segment.start = 2 * GST_SECOND;
822 segment.stop = 4 * GST_SECOND;
823 segment.time = 1 * GST_SECOND;
824 event = gst_event_new_segment (&segment);
826 eret = gst_pad_send_event (sinkpad, event);
827 fail_if (eret == FALSE);
830 /* send buffer that should return EOS */
831 buffer = gst_buffer_new ();
832 GST_BUFFER_TIMESTAMP (buffer) = 3 * GST_SECOND;
833 GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND;
835 GST_DEBUG ("sending buffer");
837 /* this buffer causes the sink to preroll */
838 data = chain_async (sinkpad, buffer);
839 fail_if (data == NULL);
841 /* wait for preroll */
842 ret = gst_element_get_state (pipeline, NULL, NULL, -1);
844 /* preroll buffer is rendered, we expect no more buffer after this one */
845 fret = chain_async_return (data);
846 fail_unless (fret == GST_FLOW_EOS);
848 /* do position query, this should succeed with the stream time of the buffer
849 * against the clock. Since the buffer is synced against the clock, the time
850 * should be at least the stream time of the buffer. */
851 qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur);
852 fail_unless (qret == TRUE);
853 fail_unless (qcur >= 2 * GST_SECOND && qcur <= 3 * GST_SECOND);
855 /* wait 2 more seconds, enough to test if the position was clipped correctly
856 * against the segment */
857 g_usleep (2 * G_USEC_PER_SEC);
859 qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur);
860 fail_unless (qret == TRUE);
861 fail_unless (qcur == 3 * GST_SECOND);
863 GST_DEBUG ("going to PAUSED");
865 ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
866 fail_unless (ret == GST_STATE_CHANGE_ASYNC);
868 /* we report the time of the last start of the buffer. This is slightly
869 * incorrect, we should report the exact time when we paused but there is no
870 * record of that anywhere */
871 qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur);
872 fail_unless (qret == TRUE);
873 fail_unless (qcur == 3 * GST_SECOND);
875 ret = gst_element_set_state (pipeline, GST_STATE_READY);
876 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
878 /* fails again because we are in the wrong state */
879 qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur);
880 fail_unless (qret == FALSE);
882 gst_element_set_state (pipeline, GST_STATE_NULL);
884 qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur);
885 fail_unless (qret == FALSE);
887 gst_object_unref (sinkpad);
888 gst_object_unref (pipeline);
893 /* like fakesrc, but also pushes an OOB event after each buffer */
894 typedef GstPushSrc OOBSource;
895 typedef GstPushSrcClass OOBSourceClass;
897 GType oob_source_get_type (void);
898 G_DEFINE_TYPE (OOBSource, oob_source, GST_TYPE_PUSH_SRC);
901 oob_source_create (GstPushSrc * src, GstBuffer ** p_buf)
903 *p_buf = gst_buffer_new ();
905 gst_pad_push_event (GST_BASE_SRC_PAD (src),
906 gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM_OOB, NULL));
912 oob_source_class_init (OOBSourceClass * klass)
914 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("src",
915 GST_PAD_SRC, GST_PAD_ALWAYS, GST_STATIC_CAPS_ANY);
916 GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
917 GstPushSrcClass *pushsrc_class = GST_PUSH_SRC_CLASS (klass);
919 gst_element_class_add_static_pad_template (element_class, &sinktemplate);
921 pushsrc_class->create = GST_DEBUG_FUNCPTR (oob_source_create);
925 oob_source_init (OOBSource * src)
930 #define NOTIFY_RACE_NUM_PIPELINES 10
938 } NotifyRacePipeline;
941 test_notify_race_setup_pipeline (NotifyRacePipeline * p)
943 GST_DEBUG ("Creating pipeline");
944 p->pipe = gst_pipeline_new ("pipeline");
945 p->src = g_object_new (oob_source_get_type (), NULL);
947 p->queue = gst_element_factory_make ("queue", NULL);
948 g_object_set (p->queue, "max-size-buffers", 2, NULL);
950 p->sink = gst_element_factory_make ("fakesink", NULL);
951 gst_bin_add (GST_BIN (p->pipe), p->src);
952 gst_bin_add (GST_BIN (p->pipe), p->queue);
953 gst_bin_add (GST_BIN (p->pipe), p->sink);
954 gst_element_link_many (p->src, p->queue, p->sink, NULL);
956 GST_DEBUG ("Setting pipeline to PAUSED..");
957 fail_unless_equals_int (gst_element_set_state (p->pipe, GST_STATE_PAUSED),
958 GST_STATE_CHANGE_ASYNC);
959 GST_DEBUG ("Waiting for pipeline to preroll..");
960 fail_unless_equals_int (gst_element_get_state (p->pipe, NULL, NULL, -1),
961 GST_STATE_CHANGE_SUCCESS);
962 GST_DEBUG ("Ready to party!");
966 test_notify_race_cleanup_pipeline (NotifyRacePipeline * p)
968 gst_element_set_state (p->pipe, GST_STATE_NULL);
969 gst_object_unref (p->pipe);
970 memset (p, 0, sizeof (NotifyRacePipeline));
973 /* we create N pipelines to make sure the notify race isn't per-class, but
974 * only per instance */
975 GST_START_TEST (test_notify_race)
977 NotifyRacePipeline pipelines[NOTIFY_RACE_NUM_PIPELINES];
980 for (i = 0; i < G_N_ELEMENTS (pipelines); ++i) {
981 GST_DEBUG ("Setting up pipeline %d", i);
982 test_notify_race_setup_pipeline (&pipelines[i]);
985 for (i = 0; i < G_N_ELEMENTS (pipelines); ++i) {
986 GST_DEBUG ("Starting pipeline %d", i);
987 gst_element_set_state (pipelines[i].pipe, GST_STATE_PLAYING);
990 g_usleep (2 * G_USEC_PER_SEC);
992 for (i = 0; i < G_N_ELEMENTS (pipelines); ++i) {
993 GST_DEBUG ("Cleaning up pipeline %d", i);
994 test_notify_race_cleanup_pipeline (&pipelines[i]);
1001 last_message_cb (GObject * obj, GParamSpec * pspec, gpointer user_data)
1003 gint *p_counter = user_data;
1004 gchar *s, *end, *last_msg = NULL;
1005 guint64 offset, count;
1007 g_object_get (obj, "last-message", &last_msg, NULL);
1008 fail_unless (last_msg != NULL);
1010 if (!strstr (last_msg, "chain"))
1013 GST_LOG_OBJECT (obj, "%s", last_msg);
1015 s = strstr (last_msg, "offset: ");
1016 fail_unless (s != NULL);
1018 s += strlen ("offset: ");
1020 offset = g_ascii_strtoull (s, &end, 10);
1021 fail_unless (offset < G_MAXUINT64);
1026 fail_unless_equals_int (count, offset);
1028 *p_counter = count + 1;
1035 #define NUM_BUFFERS 500
1037 GST_START_TEST (test_last_message_notify)
1039 GstElement *pipe, *src, *tee, *q1, *q2, *sink1, *sink2;
1044 pipe = gst_pipeline_new ("pipeline");
1045 src = gst_element_factory_make ("fakesrc", NULL);
1046 gst_util_set_object_arg (G_OBJECT (src), "sizetype", "fixed");
1047 g_object_set (src, "num-buffers", NUM_BUFFERS, "sizemax", 1, NULL);
1049 tee = gst_element_factory_make ("tee", NULL);
1051 q1 = gst_element_factory_make ("queue", NULL);
1052 sink1 = gst_element_factory_make ("fakesink", NULL);
1053 g_object_set (sink1, "silent", FALSE, NULL);
1055 q2 = gst_element_factory_make ("queue", NULL);
1056 sink2 = gst_element_factory_make ("fakesink", NULL);
1057 g_object_set (sink2, "silent", FALSE, NULL);
1059 gst_bin_add_many (GST_BIN (pipe), src, tee, q1, q2, sink1, sink2, NULL);
1060 fail_unless (gst_element_link_many (src, tee, NULL));
1061 fail_unless (gst_element_link_many (tee, q1, sink1, NULL));
1062 fail_unless (gst_element_link_many (tee, q2, sink2, NULL));
1064 g_signal_connect (sink1, "notify::last-message",
1065 G_CALLBACK (last_message_cb), &counter1);
1066 g_signal_connect (sink2, "notify::last-message",
1067 G_CALLBACK (last_message_cb), &counter2);
1069 GST_DEBUG ("Setting pipeline to PLAYING");
1070 fail_unless_equals_int (gst_element_set_state (pipe, GST_STATE_PLAYING),
1071 GST_STATE_CHANGE_ASYNC);
1073 m = gst_bus_timed_pop_filtered (GST_ELEMENT_BUS (pipe), -1, GST_MESSAGE_EOS);
1074 gst_message_unref (m);
1076 fail_unless_equals_int (gst_element_set_state (pipe, GST_STATE_NULL),
1077 GST_STATE_CHANGE_SUCCESS);
1079 fail_unless_equals_int (counter1, NUM_BUFFERS);
1080 fail_unless_equals_int (counter2, NUM_BUFFERS);
1082 gst_object_unref (pipe);
1088 deep_notify_last_message_cb (GstObject * obj, GstObject * prop_obj,
1089 GParamSpec * pspec, gpointer user_data)
1091 gint *counter_array = user_data;
1093 gchar *s, *end, *last_msg = NULL;
1094 guint64 offset, count;
1096 if (strcmp (GST_OBJECT_NAME (prop_obj), "fakesink0") == 0)
1097 p_counter = counter_array;
1098 else if (strcmp (GST_OBJECT_NAME (prop_obj), "fakesink1") == 0)
1099 p_counter = counter_array + 1;
1101 g_assert_not_reached ();
1103 g_object_get (prop_obj, "last-message", &last_msg, NULL);
1104 fail_unless (last_msg != NULL);
1106 if (!strstr (last_msg, "chain"))
1109 GST_LOG_OBJECT (prop_obj, "%s", last_msg);
1111 s = strstr (last_msg, "offset: ");
1112 fail_unless (s != NULL);
1114 s += strlen ("offset: ");
1116 offset = g_ascii_strtoull (s, &end, 10);
1117 fail_unless (offset < G_MAXUINT64);
1122 // fail_unless_equals_int (count, offset);
1124 *p_counter = count + 1;
1131 GST_START_TEST (test_last_message_deep_notify)
1133 GstElement *pipe, *src, *tee, *q1, *q2, *sink1, *sink2;
1134 gint counter[2] = { 0, 0 };
1137 pipe = gst_pipeline_new ("pipeline");
1138 src = gst_element_factory_make ("fakesrc", NULL);
1139 gst_util_set_object_arg (G_OBJECT (src), "sizetype", "fixed");
1140 g_object_set (src, "num-buffers", NUM_BUFFERS, "sizemax", 1, NULL);
1142 tee = gst_element_factory_make ("tee", NULL);
1144 q1 = gst_element_factory_make ("queue", NULL);
1145 sink1 = gst_element_factory_make ("fakesink", NULL);
1146 g_object_set (sink1, "silent", FALSE, NULL);
1148 q2 = gst_element_factory_make ("queue", NULL);
1149 sink2 = gst_element_factory_make ("fakesink", NULL);
1150 g_object_set (sink2, "silent", FALSE, NULL);
1152 gst_bin_add_many (GST_BIN (pipe), src, tee, q1, q2, sink1, sink2, NULL);
1153 fail_unless (gst_element_link_many (src, tee, NULL));
1154 fail_unless (gst_element_link_many (tee, q1, sink1, NULL));
1155 fail_unless (gst_element_link_many (tee, q2, sink2, NULL));
1157 g_signal_connect (pipe, "deep-notify::last-message",
1158 G_CALLBACK (deep_notify_last_message_cb), counter);
1160 GST_DEBUG ("Setting pipeline to PLAYING");
1161 fail_unless_equals_int (gst_element_set_state (pipe, GST_STATE_PLAYING),
1162 GST_STATE_CHANGE_ASYNC);
1164 m = gst_bus_timed_pop_filtered (GST_ELEMENT_BUS (pipe), -1, GST_MESSAGE_EOS);
1165 gst_message_unref (m);
1167 fail_unless_equals_int (gst_element_set_state (pipe, GST_STATE_NULL),
1168 GST_STATE_CHANGE_SUCCESS);
1170 GST_ERROR ("sink1: %d, sink2: %d, total: %d", counter[0], counter[1],
1171 counter[0] + counter[1]);
1173 fail_unless_equals_int (counter[0], NUM_BUFFERS);
1174 fail_unless_equals_int (counter[1], NUM_BUFFERS);
1180 fakesink_suite (void)
1182 Suite *s = suite_create ("fakesink");
1183 TCase *tc_chain = tcase_create ("general");
1185 tcase_set_timeout (tc_chain, 20);
1187 suite_add_tcase (s, tc_chain);
1188 tcase_add_test (tc_chain, test_clipping);
1189 tcase_add_test (tc_chain, test_preroll_sync);
1190 tcase_add_test (tc_chain, test_eos);
1191 tcase_add_test (tc_chain, test_eos2);
1192 tcase_add_test (tc_chain, test_position);
1193 tcase_add_test (tc_chain, test_notify_race);
1194 tcase_add_test (tc_chain, test_last_message_notify);
1195 tcase_skip_broken_test (tc_chain, test_last_message_deep_notify);
1200 GST_CHECK_MAIN (fakesink);