3 * unit test for fakesink
5 * Copyright (C) <2005> Thomas Vander Stichele <thomas at apestaart dot org>
6 * <2007> Wim Taymans <wim@fluendo.com>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public
19 * License along with this library; if not, write to the
20 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, USA.
26 #include <gst/check/gstcheck.h>
37 chain_async_buffer (gpointer data)
39 ChainData *chain_data = (ChainData *) data;
41 chain_data->ret = gst_pad_chain (chain_data->pad, chain_data->buffer);
47 chain_async (GstPad * pad, GstBuffer * buffer)
50 ChainData *chain_data;
53 chain_data = g_new (ChainData, 1);
54 chain_data->pad = pad;
55 chain_data->buffer = buffer;
56 chain_data->ret = GST_FLOW_ERROR;
58 thread = g_thread_create (chain_async_buffer, chain_data, TRUE, &error);
60 g_warning ("could not create thread reason: %s", error->message);
64 chain_data->thread = thread;
70 chain_async_return (ChainData * data)
74 g_thread_join (data->thread);
81 GST_START_TEST (test_clipping)
85 GstStateChangeReturn ret;
88 sink = gst_element_factory_make ("fakesink", "sink");
89 fail_if (sink == NULL);
91 sinkpad = gst_element_get_pad (sink, "sink");
92 fail_if (sinkpad == NULL);
94 /* make element ready to accept data */
95 ret = gst_element_set_state (sink, GST_STATE_PAUSED);
96 fail_unless (ret == GST_STATE_CHANGE_ASYNC);
103 GST_DEBUG ("sending segment");
104 segment = gst_event_new_new_segment (FALSE,
105 1.0, GST_FORMAT_TIME, 1 * GST_SECOND, 5 * GST_SECOND, 1 * GST_SECOND);
107 eret = gst_pad_send_event (sinkpad, segment);
108 fail_if (eret == FALSE);
111 /* new segment should not have finished preroll */
112 ret = gst_element_get_state (sink, NULL, NULL, 0);
113 fail_unless (ret == GST_STATE_CHANGE_ASYNC);
115 /* send buffer that should be dropped */
120 buffer = gst_buffer_new ();
121 GST_BUFFER_TIMESTAMP (buffer) = 0;
122 GST_BUFFER_DURATION (buffer) = 1 * GST_MSECOND;
124 GST_DEBUG ("sending buffer to be dropped");
125 fret = gst_pad_chain (sinkpad, buffer);
126 fail_if (fret != GST_FLOW_OK);
128 /* dropped buffer should not have finished preroll */
129 ret = gst_element_get_state (sink, NULL, NULL, 0);
130 fail_unless (ret == GST_STATE_CHANGE_ASYNC);
132 /* send buffer that should be dropped */
137 buffer = gst_buffer_new ();
138 GST_BUFFER_TIMESTAMP (buffer) = 5 * GST_SECOND;
139 GST_BUFFER_DURATION (buffer) = 1 * GST_MSECOND;
141 GST_DEBUG ("sending buffer to be dropped");
142 fret = gst_pad_chain (sinkpad, buffer);
143 fail_if (fret != GST_FLOW_OK);
145 /* dropped buffer should not have finished preroll */
146 ret = gst_element_get_state (sink, NULL, NULL, 0);
147 fail_unless (ret == GST_STATE_CHANGE_ASYNC);
149 /* send buffer that should block and finish preroll */
154 GstState current, pending;
156 buffer = gst_buffer_new ();
157 GST_BUFFER_TIMESTAMP (buffer) = 1 * GST_SECOND;
158 GST_BUFFER_DURATION (buffer) = 1 * GST_MSECOND;
160 GST_DEBUG ("sending buffer to finish preroll");
161 data = chain_async (sinkpad, buffer);
162 fail_if (data == NULL);
164 /* state should now eventually change to PAUSED */
165 ret = gst_element_get_state (sink, ¤t, &pending, GST_CLOCK_TIME_NONE);
166 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
167 fail_unless (current == GST_STATE_PAUSED);
168 fail_unless (pending == GST_STATE_VOID_PENDING);
170 /* playing should render the buffer */
171 ret = gst_element_set_state (sink, GST_STATE_PLAYING);
172 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
174 /* and we should get a success return value */
175 fret = chain_async_return (data);
176 fail_if (fret != GST_FLOW_OK);
179 /* send some buffer that will be dropped or clipped, this can
180 * only be observed in the debug log. */
185 buffer = gst_buffer_new ();
186 GST_BUFFER_TIMESTAMP (buffer) = 6 * GST_SECOND;
187 GST_BUFFER_DURATION (buffer) = 1 * GST_MSECOND;
189 /* should be dropped */
190 GST_DEBUG ("sending buffer to drop");
191 fret = gst_pad_chain (sinkpad, buffer);
192 fail_if (fret != GST_FLOW_OK);
194 buffer = gst_buffer_new ();
195 GST_BUFFER_TIMESTAMP (buffer) = 0 * GST_SECOND;
196 GST_BUFFER_DURATION (buffer) = 2 * GST_SECOND;
198 /* should be clipped */
199 GST_DEBUG ("sending buffer to clip");
200 fret = gst_pad_chain (sinkpad, buffer);
201 fail_if (fret != GST_FLOW_OK);
203 buffer = gst_buffer_new ();
204 GST_BUFFER_TIMESTAMP (buffer) = 4 * GST_SECOND;
205 GST_BUFFER_DURATION (buffer) = 2 * GST_SECOND;
207 /* should be clipped */
208 GST_DEBUG ("sending buffer to clip");
209 fret = gst_pad_chain (sinkpad, buffer);
210 fail_if (fret != GST_FLOW_OK);
213 gst_element_set_state (sink, GST_STATE_NULL);
214 gst_element_get_state (sink, NULL, NULL, GST_CLOCK_TIME_NONE);
215 gst_object_unref (sinkpad);
216 gst_object_unref (sink);
221 GST_START_TEST (test_preroll_sync)
223 GstElement *pipeline, *sink;
225 GstStateChangeReturn ret;
228 pipeline = gst_pipeline_new ("pipeline");
229 fail_if (pipeline == NULL);
231 sink = gst_element_factory_make ("fakesink", "sink");
232 fail_if (sink == NULL);
233 g_object_set (G_OBJECT (sink), "sync", TRUE, NULL);
235 gst_bin_add (GST_BIN (pipeline), sink);
237 sinkpad = gst_element_get_pad (sink, "sink");
238 fail_if (sinkpad == NULL);
240 /* make pipeline and element ready to accept data */
241 ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
242 fail_unless (ret == GST_STATE_CHANGE_ASYNC);
249 GST_DEBUG ("sending segment");
250 segment = gst_event_new_new_segment (FALSE,
251 1.0, GST_FORMAT_TIME, 0 * GST_SECOND, 2 * GST_SECOND, 0 * GST_SECOND);
253 eret = gst_pad_send_event (sinkpad, segment);
254 fail_if (eret == FALSE);
257 /* send buffer that should block and finish preroll */
262 GstState current, pending;
264 buffer = gst_buffer_new ();
265 GST_BUFFER_TIMESTAMP (buffer) = 1 * GST_SECOND;
266 GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND;
268 GST_DEBUG ("sending buffer to finish preroll");
269 data = chain_async (sinkpad, buffer);
270 fail_if (data == NULL);
272 /* state should now eventually change to PAUSED */
274 gst_element_get_state (pipeline, ¤t, &pending,
275 GST_CLOCK_TIME_NONE);
276 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
277 fail_unless (current == GST_STATE_PAUSED);
278 fail_unless (pending == GST_STATE_VOID_PENDING);
280 /* playing should render the buffer */
281 ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
282 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
284 /* and we should get a success return value */
285 fret = chain_async_return (data);
286 fail_if (fret != GST_FLOW_OK);
288 gst_element_set_state (pipeline, GST_STATE_NULL);
289 gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
290 gst_object_unref (sinkpad);
291 gst_object_unref (pipeline);
296 /* after EOS, we refuse everything */
297 GST_START_TEST (test_eos)
299 GstElement *pipeline, *sink;
301 GstStateChangeReturn ret;
306 pipeline = gst_pipeline_new ("pipeline");
307 fail_if (pipeline == NULL);
309 bus = gst_pipeline_get_bus (GST_PIPELINE_CAST (pipeline));
310 fail_if (bus == NULL);
312 sink = gst_element_factory_make ("fakesink", "sink");
313 fail_if (sink == NULL);
314 g_object_set (G_OBJECT (sink), "sync", TRUE, NULL);
316 gst_bin_add (GST_BIN (pipeline), sink);
318 sinkpad = gst_element_get_pad (sink, "sink");
319 fail_if (sinkpad == NULL);
321 /* make pipeline and element ready to accept data */
322 ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
323 fail_unless (ret == GST_STATE_CHANGE_ASYNC);
325 /* send EOS, this should work fine */
330 GST_DEBUG ("sending EOS");
331 eos = gst_event_new_eos ();
333 eret = gst_pad_send_event (sinkpad, eos);
334 fail_if (eret == FALSE);
337 /* wait for preroll */
338 gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
340 /* EOS should be on the bus at some point */
344 /* blocking wait for messages */
345 message = gst_bus_timed_pop (bus, GST_CLOCK_TIME_NONE);
346 type = GST_MESSAGE_TYPE (message);
347 gst_message_unref (message);
349 GST_DEBUG ("got message %s", gst_message_type_get_name (type));
351 if (type == GST_MESSAGE_EOS)
354 gst_object_unref (bus);
356 /* send another EOS, this should fail */
361 GST_DEBUG ("sending second EOS");
362 eos = gst_event_new_eos ();
364 eret = gst_pad_send_event (sinkpad, eos);
365 fail_if (eret == TRUE);
368 /* send segment, this should fail */
373 GST_DEBUG ("sending segment");
374 segment = gst_event_new_new_segment (FALSE,
375 1.0, GST_FORMAT_TIME, 0 * GST_SECOND, 2 * GST_SECOND, 0 * GST_SECOND);
377 eret = gst_pad_send_event (sinkpad, segment);
378 fail_if (eret == TRUE);
381 /* send buffer that should fail after EOS */
386 buffer = gst_buffer_new ();
387 GST_BUFFER_TIMESTAMP (buffer) = 1 * GST_SECOND;
388 GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND;
390 GST_DEBUG ("sending buffer");
392 /* buffer after EOS is not UNEXPECTED */
393 fret = gst_pad_chain (sinkpad, buffer);
394 fail_unless (fret == GST_FLOW_UNEXPECTED);
397 /* flush, EOS state is flushed again. */
402 GST_DEBUG ("sending FLUSH_START");
403 event = gst_event_new_flush_start ();
404 eret = gst_pad_send_event (sinkpad, event);
405 fail_unless (eret == TRUE);
407 GST_DEBUG ("sending FLUSH_STOP");
408 event = gst_event_new_flush_stop ();
409 eret = gst_pad_send_event (sinkpad, event);
410 fail_unless (eret == TRUE);
413 /* send segment, this should now work again */
418 GST_DEBUG ("sending segment");
419 segment = gst_event_new_new_segment (FALSE,
420 1.0, GST_FORMAT_TIME, 0 * GST_SECOND, 2 * GST_SECOND, 0 * GST_SECOND);
422 eret = gst_pad_send_event (sinkpad, segment);
423 fail_unless (eret == TRUE);
426 /* send buffer that should work and block */
431 buffer = gst_buffer_new ();
432 GST_BUFFER_TIMESTAMP (buffer) = 1 * GST_SECOND;
433 GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND;
435 GST_DEBUG ("sending buffer");
437 fret = gst_pad_chain (sinkpad, buffer);
438 fail_unless (fret == GST_FLOW_OK);
441 gst_element_set_state (pipeline, GST_STATE_NULL);
442 gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
443 gst_object_unref (sinkpad);
444 gst_object_unref (pipeline);
449 /* test EOS triggered by the element */
450 GST_START_TEST (test_eos2)
452 GstElement *pipeline, *sink;
454 GstStateChangeReturn ret;
457 pipeline = gst_pipeline_new ("pipeline");
458 fail_if (pipeline == NULL);
460 sink = gst_element_factory_make ("fakesink", "sink");
461 fail_if (sink == NULL);
462 g_object_set (G_OBJECT (sink), "sync", TRUE, NULL);
463 g_object_set (G_OBJECT (sink), "num-buffers", 1, NULL);
465 gst_bin_add (GST_BIN (pipeline), sink);
467 sinkpad = gst_element_get_pad (sink, "sink");
468 fail_if (sinkpad == NULL);
470 /* make pipeline and element ready to accept data */
471 ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
472 fail_unless (ret == GST_STATE_CHANGE_ASYNC);
474 /* send segment, this should work */
479 GST_DEBUG ("sending segment");
480 segment = gst_event_new_new_segment (FALSE,
481 1.0, GST_FORMAT_TIME, 0 * GST_SECOND, 2 * GST_SECOND, 0 * GST_SECOND);
483 eret = gst_pad_send_event (sinkpad, segment);
484 fail_if (eret == FALSE);
487 /* send buffer that should return UNEXPECTED */
492 buffer = gst_buffer_new ();
493 GST_BUFFER_TIMESTAMP (buffer) = 1 * GST_SECOND;
494 GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND;
496 GST_DEBUG ("sending buffer");
498 /* this buffer will generate UNEXPECTED */
499 fret = gst_pad_chain (sinkpad, buffer);
500 fail_unless (fret == GST_FLOW_UNEXPECTED);
503 /* send buffer that should return UNEXPECTED */
508 buffer = gst_buffer_new ();
509 GST_BUFFER_TIMESTAMP (buffer) = 1 * GST_SECOND;
510 GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND;
512 GST_DEBUG ("sending buffer");
514 fret = gst_pad_chain (sinkpad, buffer);
515 fail_unless (fret == GST_FLOW_UNEXPECTED);
518 gst_element_set_state (pipeline, GST_STATE_NULL);
519 gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
520 gst_object_unref (sinkpad);
521 gst_object_unref (pipeline);
527 fakesink_suite (void)
529 Suite *s = suite_create ("fakesink");
530 TCase *tc_chain = tcase_create ("general");
532 suite_add_tcase (s, tc_chain);
533 tcase_add_test (tc_chain, test_clipping);
534 tcase_add_test (tc_chain, test_preroll_sync);
535 tcase_add_test (tc_chain, test_eos);
536 tcase_add_test (tc_chain, test_eos2);
541 GST_CHECK_MAIN (fakesink);