ce69e92f1ace3e0852601e59c90db3bcacc62cd3
[platform/upstream/gstreamer.git] / tests / check / elements / fakesink.c
1 /* GStreamer
2  *
3  * unit test for fakesink
4  *
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>
8  *
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.
13  *
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.
18  *
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.
23  */
24
25 #include <unistd.h>
26
27 #include <gst/base/gstpushsrc.h>
28 #include <gst/check/gstcheck.h>
29
30 typedef struct
31 {
32   GstPad *pad;
33   GstBuffer *buffer;
34   GThread *thread;
35   GstFlowReturn ret;
36 } ChainData;
37
38 static gpointer
39 chain_async_buffer (gpointer data)
40 {
41   ChainData *chain_data = (ChainData *) data;
42
43   chain_data->ret = gst_pad_chain (chain_data->pad, chain_data->buffer);
44
45   return chain_data;
46 }
47
48 static ChainData *
49 chain_async (GstPad * pad, GstBuffer * buffer)
50 {
51   GThread *thread;
52   ChainData *chain_data;
53   GError *error = NULL;
54
55   chain_data = g_new (ChainData, 1);
56   chain_data->pad = pad;
57   chain_data->buffer = buffer;
58   chain_data->ret = GST_FLOW_ERROR;
59
60   thread = g_thread_create (chain_async_buffer, chain_data, TRUE, &error);
61   if (error != NULL) {
62     g_warning ("could not create thread reason: %s", error->message);
63     g_free (chain_data);
64     return NULL;
65   }
66   chain_data->thread = thread;
67
68   return chain_data;
69 }
70
71 static GstFlowReturn
72 chain_async_return (ChainData * data)
73 {
74   GstFlowReturn ret;
75
76   g_thread_join (data->thread);
77   ret = data->ret;
78   g_free (data);
79
80   return ret;
81 }
82
83 GST_START_TEST (test_clipping)
84 {
85   GstElement *sink;
86   GstPad *sinkpad;
87   GstStateChangeReturn ret;
88
89   /* create sink */
90   sink = gst_element_factory_make ("fakesink", "sink");
91   fail_if (sink == NULL);
92
93   sinkpad = gst_element_get_static_pad (sink, "sink");
94   fail_if (sinkpad == NULL);
95
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);
99
100   /* send segment */
101   {
102     GstEvent *segment;
103     gboolean eret;
104
105     GST_DEBUG ("sending segment");
106     segment = gst_event_new_new_segment (FALSE,
107         1.0, 1.0, GST_FORMAT_TIME, 1 * GST_SECOND, 5 * GST_SECOND,
108         1 * GST_SECOND);
109
110     eret = gst_pad_send_event (sinkpad, segment);
111     fail_if (eret == FALSE);
112   }
113
114   /* new segment should not have finished preroll */
115   ret = gst_element_get_state (sink, NULL, NULL, 0);
116   fail_unless (ret == GST_STATE_CHANGE_ASYNC);
117
118   /* send buffer that should be dropped */
119   {
120     GstBuffer *buffer;
121     GstFlowReturn fret;
122
123     buffer = gst_buffer_new ();
124     GST_BUFFER_TIMESTAMP (buffer) = 0;
125     GST_BUFFER_DURATION (buffer) = 1 * GST_MSECOND;
126
127     GST_DEBUG ("sending buffer to be dropped");
128     fret = gst_pad_chain (sinkpad, buffer);
129     fail_if (fret != GST_FLOW_OK);
130   }
131   /* dropped buffer should not have finished preroll */
132   ret = gst_element_get_state (sink, NULL, NULL, 0);
133   fail_unless (ret == GST_STATE_CHANGE_ASYNC);
134
135   /* send buffer that should be dropped */
136   {
137     GstBuffer *buffer;
138     GstFlowReturn fret;
139
140     buffer = gst_buffer_new ();
141     GST_BUFFER_TIMESTAMP (buffer) = 5 * GST_SECOND;
142     GST_BUFFER_DURATION (buffer) = 1 * GST_MSECOND;
143
144     GST_DEBUG ("sending buffer to be dropped");
145     fret = gst_pad_chain (sinkpad, buffer);
146     fail_if (fret != GST_FLOW_OK);
147   }
148   /* dropped buffer should not have finished preroll */
149   ret = gst_element_get_state (sink, NULL, NULL, 0);
150   fail_unless (ret == GST_STATE_CHANGE_ASYNC);
151
152   /* send buffer that should block and finish preroll */
153   {
154     GstBuffer *buffer;
155     GstFlowReturn fret;
156     ChainData *data;
157     GstState current, pending;
158
159     buffer = gst_buffer_new ();
160     GST_BUFFER_TIMESTAMP (buffer) = 1 * GST_SECOND;
161     GST_BUFFER_DURATION (buffer) = 1 * GST_MSECOND;
162
163     GST_DEBUG ("sending buffer to finish preroll");
164     data = chain_async (sinkpad, buffer);
165     fail_if (data == NULL);
166
167     /* state should now eventually change to PAUSED */
168     ret = gst_element_get_state (sink, &current, &pending, GST_CLOCK_TIME_NONE);
169     fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
170     fail_unless (current == GST_STATE_PAUSED);
171     fail_unless (pending == GST_STATE_VOID_PENDING);
172
173     /* playing should render the buffer */
174     ret = gst_element_set_state (sink, GST_STATE_PLAYING);
175     fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
176
177     /* and we should get a success return value */
178     fret = chain_async_return (data);
179     fail_if (fret != GST_FLOW_OK);
180   }
181
182   /* send some buffer that will be dropped or clipped, this can 
183    * only be observed in the debug log. */
184   {
185     GstBuffer *buffer;
186     GstFlowReturn fret;
187
188     buffer = gst_buffer_new ();
189     GST_BUFFER_TIMESTAMP (buffer) = 6 * GST_SECOND;
190     GST_BUFFER_DURATION (buffer) = 1 * GST_MSECOND;
191
192     /* should be dropped */
193     GST_DEBUG ("sending buffer to drop");
194     fret = gst_pad_chain (sinkpad, buffer);
195     fail_if (fret != GST_FLOW_OK);
196
197     buffer = gst_buffer_new ();
198     GST_BUFFER_TIMESTAMP (buffer) = 0 * GST_SECOND;
199     GST_BUFFER_DURATION (buffer) = 2 * GST_SECOND;
200
201     /* should be clipped */
202     GST_DEBUG ("sending buffer to clip");
203     fret = gst_pad_chain (sinkpad, buffer);
204     fail_if (fret != GST_FLOW_OK);
205
206     buffer = gst_buffer_new ();
207     GST_BUFFER_TIMESTAMP (buffer) = 4 * GST_SECOND;
208     GST_BUFFER_DURATION (buffer) = 2 * GST_SECOND;
209
210     /* should be clipped */
211     GST_DEBUG ("sending buffer to clip");
212     fret = gst_pad_chain (sinkpad, buffer);
213     fail_if (fret != GST_FLOW_OK);
214   }
215
216   gst_element_set_state (sink, GST_STATE_NULL);
217   gst_element_get_state (sink, NULL, NULL, GST_CLOCK_TIME_NONE);
218   gst_object_unref (sinkpad);
219   gst_object_unref (sink);
220 }
221
222 GST_END_TEST;
223
224 static gint num_preroll = 0;
225
226 static void
227 preroll_count (GstElement * sink)
228 {
229   num_preroll++;
230   GST_DEBUG ("got preroll handoff %d", num_preroll);
231 }
232
233 GST_START_TEST (test_preroll_sync)
234 {
235   GstElement *pipeline, *sink;
236   GstPad *sinkpad;
237   GstStateChangeReturn ret;
238
239   /* create sink */
240   pipeline = gst_pipeline_new ("pipeline");
241   fail_if (pipeline == NULL);
242
243   sink = gst_element_factory_make ("fakesink", "sink");
244   fail_if (sink == NULL);
245   g_object_set (G_OBJECT (sink), "sync", TRUE, NULL);
246   g_object_set (G_OBJECT (sink), "signal-handoffs", TRUE, NULL);
247   g_signal_connect (sink, "preroll-handoff", G_CALLBACK (preroll_count), NULL);
248
249   fail_unless (num_preroll == 0);
250
251   gst_bin_add (GST_BIN (pipeline), sink);
252
253   sinkpad = gst_element_get_static_pad (sink, "sink");
254   fail_if (sinkpad == NULL);
255
256   /* make pipeline and element ready to accept data */
257   ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
258   fail_unless (ret == GST_STATE_CHANGE_ASYNC);
259
260   /* send segment */
261   {
262     GstEvent *segment;
263     gboolean eret;
264
265     GST_DEBUG ("sending segment");
266     segment = gst_event_new_new_segment (FALSE,
267         1.0, 1.0, GST_FORMAT_TIME, 0 * GST_SECOND, 102 * GST_SECOND,
268         0 * GST_SECOND);
269
270     eret = gst_pad_send_event (sinkpad, segment);
271     fail_if (eret == FALSE);
272   }
273
274   /* send buffer that should block and finish preroll */
275   {
276     GstBuffer *buffer;
277     GstFlowReturn fret;
278     ChainData *data;
279     GstState current, pending;
280
281     buffer = gst_buffer_new ();
282     GST_BUFFER_TIMESTAMP (buffer) = 1 * GST_SECOND;
283     GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND;
284
285     GST_DEBUG ("sending buffer to finish preroll");
286     data = chain_async (sinkpad, buffer);
287     fail_if (data == NULL);
288
289     /* state should now eventually change to PAUSED */
290     ret =
291         gst_element_get_state (pipeline, &current, &pending,
292         GST_CLOCK_TIME_NONE);
293     fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
294     fail_unless (current == GST_STATE_PAUSED);
295     fail_unless (pending == GST_STATE_VOID_PENDING);
296
297     fail_unless (num_preroll == 1);
298
299     /* playing should render the buffer */
300     ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
301     fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
302
303     /* and we should get a success return value */
304     fret = chain_async_return (data);
305     fail_if (fret != GST_FLOW_OK);
306
307     /* now we are playing no new preroll was done */
308     fail_unless (num_preroll == 1);
309
310     buffer = gst_buffer_new ();
311     /* far in the future to make sure we block */
312     GST_BUFFER_TIMESTAMP (buffer) = 100 * GST_SECOND;
313     GST_BUFFER_DURATION (buffer) = 100 * GST_SECOND;
314     data = chain_async (sinkpad, buffer);
315     fail_if (data == NULL);
316
317     g_usleep (1000000);
318
319     /* pause again. Since the buffer has a humongous timestamp we likely
320      * interrupt the clock_wait and we should preroll on this buffer again */
321     ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
322     fail_unless (ret == GST_STATE_CHANGE_ASYNC);
323
324     ret =
325         gst_element_get_state (pipeline, &current, &pending,
326         GST_CLOCK_TIME_NONE);
327     fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
328     fail_unless (current == GST_STATE_PAUSED);
329     fail_unless (pending == GST_STATE_VOID_PENDING);
330
331     fail_unless (num_preroll == 2);
332
333     /* shutdown */
334     ret = gst_element_set_state (pipeline, GST_STATE_READY);
335     fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
336
337     /* should be wrong state now */
338     fret = chain_async_return (data);
339     fail_if (fret != GST_FLOW_WRONG_STATE);
340   }
341   gst_element_set_state (pipeline, GST_STATE_NULL);
342   gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
343   gst_object_unref (sinkpad);
344   gst_object_unref (pipeline);
345 }
346
347 GST_END_TEST;
348
349 /* after EOS, we refuse everything */
350 GST_START_TEST (test_eos)
351 {
352   GstElement *pipeline, *sink;
353   GstPad *sinkpad;
354   GstStateChangeReturn ret;
355   GstMessage *message;
356   GstBus *bus;
357
358   /* create sink */
359   pipeline = gst_pipeline_new ("pipeline");
360   fail_if (pipeline == NULL);
361
362   bus = gst_pipeline_get_bus (GST_PIPELINE_CAST (pipeline));
363   fail_if (bus == NULL);
364
365   sink = gst_element_factory_make ("fakesink", "sink");
366   fail_if (sink == NULL);
367   g_object_set (G_OBJECT (sink), "sync", TRUE, NULL);
368
369   gst_bin_add (GST_BIN (pipeline), sink);
370
371   sinkpad = gst_element_get_static_pad (sink, "sink");
372   fail_if (sinkpad == NULL);
373
374   /* make pipeline and element ready to accept data */
375   ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
376   fail_unless (ret == GST_STATE_CHANGE_ASYNC);
377
378   /* send EOS, this should work fine */
379   {
380     GstEvent *eos;
381     gboolean eret;
382
383     GST_DEBUG ("sending EOS");
384     eos = gst_event_new_eos ();
385
386     eret = gst_pad_send_event (sinkpad, eos);
387     fail_if (eret == FALSE);
388   }
389
390   /* wait for preroll */
391   gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
392
393   /* EOS should be on the bus at some point */
394   while (TRUE) {
395     GstMessageType type;
396
397     /* blocking wait for messages */
398     message = gst_bus_timed_pop (bus, GST_CLOCK_TIME_NONE);
399     type = GST_MESSAGE_TYPE (message);
400     gst_message_unref (message);
401
402     GST_DEBUG ("got message %s", gst_message_type_get_name (type));
403
404     if (type == GST_MESSAGE_EOS)
405       break;
406   }
407   gst_object_unref (bus);
408
409   /* send another EOS, this should fail */
410   {
411     GstEvent *eos;
412     gboolean eret;
413
414     GST_DEBUG ("sending second EOS");
415     eos = gst_event_new_eos ();
416
417     eret = gst_pad_send_event (sinkpad, eos);
418     fail_if (eret == TRUE);
419   }
420
421   /* send segment, this should fail */
422   {
423     GstEvent *segment;
424     gboolean eret;
425
426     GST_DEBUG ("sending segment");
427     segment = gst_event_new_new_segment (FALSE,
428         1.0, 1.0, GST_FORMAT_TIME, 0 * GST_SECOND, 2 * GST_SECOND,
429         0 * GST_SECOND);
430
431     eret = gst_pad_send_event (sinkpad, segment);
432     fail_if (eret == TRUE);
433   }
434
435   /* send buffer that should fail after EOS */
436   {
437     GstBuffer *buffer;
438     GstFlowReturn fret;
439
440     buffer = gst_buffer_new ();
441     GST_BUFFER_TIMESTAMP (buffer) = 1 * GST_SECOND;
442     GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND;
443
444     GST_DEBUG ("sending buffer");
445
446     /* buffer after EOS is not UNEXPECTED */
447     fret = gst_pad_chain (sinkpad, buffer);
448     fail_unless (fret == GST_FLOW_UNEXPECTED);
449   }
450
451   /* flush, EOS state is flushed again. */
452   {
453     GstEvent *event;
454     gboolean eret;
455
456     GST_DEBUG ("sending FLUSH_START");
457     event = gst_event_new_flush_start ();
458     eret = gst_pad_send_event (sinkpad, event);
459     fail_unless (eret == TRUE);
460
461     GST_DEBUG ("sending FLUSH_STOP");
462     event = gst_event_new_flush_stop ();
463     eret = gst_pad_send_event (sinkpad, event);
464     fail_unless (eret == TRUE);
465   }
466
467   /* send segment, this should now work again */
468   {
469     GstEvent *segment;
470     gboolean eret;
471
472     GST_DEBUG ("sending segment");
473     segment = gst_event_new_new_segment (FALSE,
474         1.0, 1.0, GST_FORMAT_TIME, 0 * GST_SECOND, 2 * GST_SECOND,
475         0 * GST_SECOND);
476
477     eret = gst_pad_send_event (sinkpad, segment);
478     fail_unless (eret == TRUE);
479   }
480
481   /* send buffer that should work and block */
482   {
483     GstBuffer *buffer;
484     GstFlowReturn fret;
485
486     buffer = gst_buffer_new ();
487     GST_BUFFER_TIMESTAMP (buffer) = 1 * GST_SECOND;
488     GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND;
489
490     GST_DEBUG ("sending buffer");
491
492     fret = gst_pad_chain (sinkpad, buffer);
493     fail_unless (fret == GST_FLOW_OK);
494   }
495
496   gst_element_set_state (pipeline, GST_STATE_NULL);
497   gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
498   gst_object_unref (sinkpad);
499   gst_object_unref (pipeline);
500 }
501
502 GST_END_TEST;
503
504 /* test EOS triggered by the element */
505 GST_START_TEST (test_eos2)
506 {
507   GstElement *pipeline, *sink;
508   GstPad *sinkpad;
509   GstStateChangeReturn ret;
510
511   /* create sink */
512   pipeline = gst_pipeline_new ("pipeline");
513   fail_if (pipeline == NULL);
514
515   sink = gst_element_factory_make ("fakesink", "sink");
516   fail_if (sink == NULL);
517   g_object_set (G_OBJECT (sink), "sync", TRUE, NULL);
518   g_object_set (G_OBJECT (sink), "num-buffers", 1, NULL);
519
520   gst_bin_add (GST_BIN (pipeline), sink);
521
522   sinkpad = gst_element_get_static_pad (sink, "sink");
523   fail_if (sinkpad == NULL);
524
525   /* make pipeline and element ready to accept data */
526   ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
527   fail_unless (ret == GST_STATE_CHANGE_ASYNC);
528
529   /* send segment, this should work */
530   {
531     GstEvent *segment;
532     gboolean eret;
533
534     GST_DEBUG ("sending segment");
535     segment = gst_event_new_new_segment (FALSE,
536         1.0, 1.0, GST_FORMAT_TIME, 0 * GST_SECOND, 2 * GST_SECOND,
537         0 * GST_SECOND);
538
539     eret = gst_pad_send_event (sinkpad, segment);
540     fail_if (eret == FALSE);
541   }
542
543   /* send buffer that should return UNEXPECTED */
544   {
545     GstBuffer *buffer;
546     GstFlowReturn fret;
547
548     buffer = gst_buffer_new ();
549     GST_BUFFER_TIMESTAMP (buffer) = 1 * GST_SECOND;
550     GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND;
551
552     GST_DEBUG ("sending buffer");
553
554     /* this buffer will generate UNEXPECTED */
555     fret = gst_pad_chain (sinkpad, buffer);
556     fail_unless (fret == GST_FLOW_UNEXPECTED);
557   }
558
559   /* send buffer that should return UNEXPECTED */
560   {
561     GstBuffer *buffer;
562     GstFlowReturn fret;
563
564     buffer = gst_buffer_new ();
565     GST_BUFFER_TIMESTAMP (buffer) = 1 * GST_SECOND;
566     GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND;
567
568     GST_DEBUG ("sending buffer");
569
570     fret = gst_pad_chain (sinkpad, buffer);
571     fail_unless (fret == GST_FLOW_UNEXPECTED);
572   }
573
574   gst_element_set_state (pipeline, GST_STATE_NULL);
575   gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
576   gst_object_unref (sinkpad);
577   gst_object_unref (pipeline);
578 }
579
580 GST_END_TEST;
581
582 /* test position reporting before, during and after flush 
583  * in PAUSED and PLAYING */
584 GST_START_TEST (test_position)
585 {
586   GstElement *pipeline, *sink;
587   GstPad *sinkpad;
588   GstStateChangeReturn ret;
589   gboolean qret;
590   GstFormat qformat;
591   gint64 qcur;
592   GstBuffer *buffer;
593   GstFlowReturn fret;
594   ChainData *data;
595   GstEvent *event;
596   gboolean eret;
597   gint i;
598
599   /* create sink */
600   pipeline = gst_pipeline_new ("pipeline");
601   fail_if (pipeline == NULL);
602
603   sink = gst_element_factory_make ("fakesink", "sink");
604   fail_if (sink == NULL);
605   g_object_set (G_OBJECT (sink), "sync", TRUE, NULL);
606   g_object_set (G_OBJECT (sink), "num-buffers", 2, NULL);
607
608   gst_bin_add (GST_BIN (pipeline), sink);
609
610   sinkpad = gst_element_get_static_pad (sink, "sink");
611   fail_if (sinkpad == NULL);
612
613   /* do position query, this should fail, we have nothing received yet */
614   qformat = GST_FORMAT_TIME;
615   qret = gst_element_query_position (sink, &qformat, &qcur);
616   fail_unless (qret == FALSE);
617
618   ret = gst_element_set_state (pipeline, GST_STATE_READY);
619   fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
620
621   /* do position query, this should fail, we have nothing received yet */
622   qformat = GST_FORMAT_TIME;
623   qret = gst_element_query_position (sink, &qformat, &qcur);
624   fail_unless (qret == FALSE);
625
626   /* make pipeline and element ready to accept data */
627   ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
628   fail_unless (ret == GST_STATE_CHANGE_ASYNC);
629
630   /* do position query, this should fail, we have nothing received yet */
631   qformat = GST_FORMAT_TIME;
632   qret = gst_element_query_position (sink, &qformat, &qcur);
633   fail_unless (qret == FALSE);
634
635   /* send segment, this should work */
636   {
637     GST_DEBUG ("sending segment");
638     event = gst_event_new_new_segment (FALSE,
639         1.0, 1.0, GST_FORMAT_TIME, 1 * GST_SECOND, 3 * GST_SECOND,
640         1 * GST_SECOND);
641
642     eret = gst_pad_send_event (sinkpad, event);
643     fail_if (eret == FALSE);
644   }
645
646   /* FIXME, do position query, this should succeed with the time value from the
647    * segment. */
648   qformat = GST_FORMAT_TIME;
649   qret = gst_element_query_position (sink, &qformat, &qcur);
650   fail_unless (qret == TRUE);
651   fail_unless (qcur == 1 * GST_SECOND);
652
653   /* send buffer that we will flush out */
654   buffer = gst_buffer_new ();
655   GST_BUFFER_TIMESTAMP (buffer) = 2 * GST_SECOND;
656   GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND;
657
658   GST_DEBUG ("sending buffer");
659
660   /* this buffer causes the sink to preroll */
661   data = chain_async (sinkpad, buffer);
662   fail_if (data == NULL);
663
664   /* wait for preroll */
665   ret = gst_element_get_state (pipeline, NULL, NULL, -1);
666
667   /* do position query, this should succeed with the time value from the
668    * segment. */
669   qformat = GST_FORMAT_TIME;
670   qret = gst_element_query_position (sink, &qformat, &qcur);
671   fail_unless (qret == TRUE);
672   fail_unless (qcur == 1 * GST_SECOND);
673
674   /* start flushing, no timing is affected yet */
675   {
676     GST_DEBUG ("sending flush_start");
677     event = gst_event_new_flush_start ();
678
679     eret = gst_pad_send_event (sinkpad, event);
680     fail_if (eret == FALSE);
681   }
682
683   /* preroll buffer is flushed out */
684   fret = chain_async_return (data);
685   fail_unless (fret == GST_FLOW_WRONG_STATE);
686
687   /* do position query, this should succeed with the time value from the
688    * segment before the flush. */
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);
693
694   /* stop flushing, timing is affected now */
695   {
696     GST_DEBUG ("sending flush_stop");
697     event = gst_event_new_flush_stop ();
698
699     eret = gst_pad_send_event (sinkpad, event);
700     fail_if (eret == FALSE);
701   }
702
703   /* do position query, this should fail, the segment is flushed */
704   qformat = GST_FORMAT_TIME;
705   qret = gst_element_query_position (sink, &qformat, &qcur);
706   fail_unless (qret == FALSE);
707
708   /* send segment, this should work */
709   {
710     GST_DEBUG ("sending segment");
711     event = gst_event_new_new_segment (FALSE,
712         1.0, 1.0, GST_FORMAT_TIME, 2 * GST_SECOND, 4 * GST_SECOND,
713         1 * GST_SECOND);
714
715     eret = gst_pad_send_event (sinkpad, event);
716     fail_if (eret == FALSE);
717   }
718
719   /* send buffer that should return OK */
720   buffer = gst_buffer_new ();
721   GST_BUFFER_TIMESTAMP (buffer) = 3 * GST_SECOND;
722   GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND;
723
724   GST_DEBUG ("sending buffer");
725
726   /* this buffer causes the sink to preroll */
727   data = chain_async (sinkpad, buffer);
728   fail_if (data == NULL);
729
730   /* wait for preroll */
731   ret = gst_element_get_state (pipeline, NULL, NULL, -1);
732
733   /* do position query, this should succeed with the time value from the
734    * segment. */
735   qformat = GST_FORMAT_TIME;
736   qret = gst_element_query_position (sink, &qformat, &qcur);
737   fail_unless (qret == TRUE);
738   fail_unless (qcur == 1 * GST_SECOND);
739
740   ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
741   fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
742
743   /* position now is increasing but never exceeds the boundaries of the segment */
744   for (i = 0; i < 5; i++) {
745     qformat = GST_FORMAT_TIME;
746     qret = gst_element_query_position (sink, &qformat, &qcur);
747     GST_DEBUG ("position %" GST_TIME_FORMAT, GST_TIME_ARGS (qcur));
748     fail_unless (qret == TRUE);
749     fail_unless (qcur >= 1 * GST_SECOND && qcur <= 3 * GST_SECOND);
750     g_usleep (1000 * 250);
751   }
752
753   /* preroll buffer is rendered, we expect one more buffer after this one */
754   fret = chain_async_return (data);
755   fail_unless (fret == GST_FLOW_OK);
756
757   /* after rendering the position must be bigger then the stream_time of the
758    * buffer */
759   qformat = GST_FORMAT_TIME;
760   qret = gst_element_query_position (sink, &qformat, &qcur);
761   fail_unless (qret == TRUE);
762   fail_unless (qcur >= 2 * GST_SECOND && qcur <= 3 * GST_SECOND);
763
764   /* start flushing in PLAYING */
765   {
766     GST_DEBUG ("sending flush_start");
767     event = gst_event_new_flush_start ();
768
769     eret = gst_pad_send_event (sinkpad, event);
770     fail_if (eret == FALSE);
771   }
772
773   /* this should now just report the stream time of the last buffer */
774   qformat = GST_FORMAT_TIME;
775   qret = gst_element_query_position (sink, &qformat, &qcur);
776   fail_unless (qret == TRUE);
777   fail_unless (qcur == 2 * GST_SECOND);
778
779   {
780     GST_DEBUG ("sending flush_stop");
781     event = gst_event_new_flush_stop ();
782
783     eret = gst_pad_send_event (sinkpad, event);
784     fail_if (eret == FALSE);
785   }
786
787   /* do position query, this should fail, the segment is flushed */
788   qformat = GST_FORMAT_TIME;
789   qret = gst_element_query_position (sink, &qformat, &qcur);
790   fail_unless (qret == FALSE);
791
792   /* send segment, this should work */
793   {
794     GST_DEBUG ("sending segment");
795     event = gst_event_new_new_segment (FALSE,
796         1.0, 1.0, GST_FORMAT_TIME, 2 * GST_SECOND, 4 * GST_SECOND,
797         1 * GST_SECOND);
798
799     eret = gst_pad_send_event (sinkpad, event);
800     fail_if (eret == FALSE);
801   }
802
803   /* send buffer that should return UNEXPECTED */
804   buffer = gst_buffer_new ();
805   GST_BUFFER_TIMESTAMP (buffer) = 3 * GST_SECOND;
806   GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND;
807
808   GST_DEBUG ("sending buffer");
809
810   /* this buffer causes the sink to preroll */
811   data = chain_async (sinkpad, buffer);
812   fail_if (data == NULL);
813
814   /* wait for preroll */
815   ret = gst_element_get_state (pipeline, NULL, NULL, -1);
816
817   /* preroll buffer is rendered, we expect no more buffer after this one */
818   fret = chain_async_return (data);
819   fail_unless (fret == GST_FLOW_UNEXPECTED);
820
821   /* do position query, this should succeed with the stream time of the buffer
822    * against the clock. Since the buffer is synced against the clock, the time
823    * should be at least the stream time of the buffer. */
824   qformat = GST_FORMAT_TIME;
825   qret = gst_element_query_position (sink, &qformat, &qcur);
826   fail_unless (qret == TRUE);
827   fail_unless (qcur >= 2 * GST_SECOND && qcur <= 3 * GST_SECOND);
828
829   /* wait 2 more seconds, enough to test if the position was clipped correctly
830    * against the segment */
831   g_usleep (2 * G_USEC_PER_SEC);
832
833   qformat = GST_FORMAT_TIME;
834   qret = gst_element_query_position (sink, &qformat, &qcur);
835   fail_unless (qret == TRUE);
836   fail_unless (qcur == 3 * GST_SECOND);
837
838   GST_DEBUG ("going to PAUSED");
839
840   ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
841   fail_unless (ret == GST_STATE_CHANGE_ASYNC);
842
843   /* we report the time of the last start of the buffer. This is slightly
844    * incorrect, we should report the exact time when we paused but there is no
845    * record of that anywhere */
846   qformat = GST_FORMAT_TIME;
847   qret = gst_element_query_position (sink, &qformat, &qcur);
848   fail_unless (qret == TRUE);
849   fail_unless (qcur >= 4 * GST_SECOND);
850
851   ret = gst_element_set_state (pipeline, GST_STATE_READY);
852   fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
853
854   /* fails again because we are in the wrong state */
855   qformat = GST_FORMAT_TIME;
856   qret = gst_element_query_position (sink, &qformat, &qcur);
857   fail_unless (qret == FALSE);
858
859   gst_element_set_state (pipeline, GST_STATE_NULL);
860
861   qformat = GST_FORMAT_TIME;
862   qret = gst_element_query_position (sink, &qformat, &qcur);
863   fail_unless (qret == FALSE);
864
865   gst_object_unref (sinkpad);
866   gst_object_unref (pipeline);
867 }
868
869 GST_END_TEST;
870
871 /* like fakesrc, but also pushes an OOB event after each buffer */
872 typedef GstPushSrc OOBSource;
873 typedef GstPushSrcClass OOBSourceClass;
874
875 GType oob_source_get_type (void);
876 G_DEFINE_TYPE (OOBSource, oob_source, GST_TYPE_PUSH_SRC);
877
878 static GstFlowReturn
879 oob_source_create (GstPushSrc * src, GstBuffer ** p_buf)
880 {
881   *p_buf = gst_buffer_new ();
882
883   gst_pad_push_event (GST_BASE_SRC_PAD (src),
884       gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM_OOB, NULL));
885
886   return GST_FLOW_OK;
887 }
888
889 static void
890 oob_source_class_init (OOBSourceClass * klass)
891 {
892   static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("src",
893       GST_PAD_SRC, GST_PAD_ALWAYS, GST_STATIC_CAPS_ANY);
894   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
895   GstPushSrcClass *pushsrc_class = GST_PUSH_SRC_CLASS (klass);
896
897   gst_element_class_add_pad_template (element_class,
898       gst_static_pad_template_get (&sinktemplate));
899
900   pushsrc_class->create = GST_DEBUG_FUNCPTR (oob_source_create);
901 }
902
903 static void
904 oob_source_init (OOBSource * src)
905 {
906   /* nothing to do */
907 }
908
909 #define NOTIFY_RACE_NUM_PIPELINES 10
910
911 typedef struct
912 {
913   GstElement *src;
914   GstElement *queue;
915   GstElement *sink;
916   GstElement *pipe;
917 } NotifyRacePipeline;
918
919 static void
920 test_notify_race_setup_pipeline (NotifyRacePipeline * p)
921 {
922   GST_DEBUG ("Creating pipeline");
923   p->pipe = gst_pipeline_new ("pipeline");
924   p->src = g_object_new (oob_source_get_type (), NULL);
925
926   p->queue = gst_element_factory_make ("queue", NULL);
927   g_object_set (p->queue, "max-size-buffers", 2, NULL);
928
929   p->sink = gst_element_factory_make ("fakesink", NULL);
930   gst_bin_add (GST_BIN (p->pipe), p->src);
931   gst_bin_add (GST_BIN (p->pipe), p->queue);
932   gst_bin_add (GST_BIN (p->pipe), p->sink);
933   gst_element_link_many (p->src, p->queue, p->sink, NULL);
934
935   GST_DEBUG ("Setting pipeline to PLAYING");
936   fail_unless_equals_int (gst_element_set_state (p->pipe, GST_STATE_PLAYING),
937       GST_STATE_CHANGE_ASYNC);
938   GST_DEBUG ("Getting state");
939   fail_unless_equals_int (gst_element_get_state (p->pipe, NULL, NULL, -1),
940       GST_STATE_CHANGE_SUCCESS);
941 }
942
943 static void
944 test_notify_race_cleanup_pipeline (NotifyRacePipeline * p)
945 {
946   gst_element_set_state (p->pipe, GST_STATE_NULL);
947   gst_object_unref (p->pipe);
948   memset (p, 0, sizeof (NotifyRacePipeline));
949 }
950
951 /* we create N pipelines to make sure the notify race isn't per-class, but
952  * only per instance */
953 GST_START_TEST (test_notify_race)
954 {
955   NotifyRacePipeline pipelines[NOTIFY_RACE_NUM_PIPELINES];
956   int i;
957
958   for (i = 0; i < G_N_ELEMENTS (pipelines); ++i) {
959     GST_DEBUG ("Starting up pipeline %d", i);
960     test_notify_race_setup_pipeline (&pipelines[i]);
961   }
962
963   g_usleep (2 * G_USEC_PER_SEC);
964
965   for (i = 0; i < G_N_ELEMENTS (pipelines); ++i) {
966     GST_DEBUG ("Cleaning up pipeline %d", i);
967     test_notify_race_cleanup_pipeline (&pipelines[i]);
968   }
969 }
970
971 GST_END_TEST;
972
973 static Suite *
974 fakesink_suite (void)
975 {
976   Suite *s = suite_create ("fakesink");
977   TCase *tc_chain = tcase_create ("general");
978
979   tcase_set_timeout (tc_chain, 20);
980
981   suite_add_tcase (s, tc_chain);
982   tcase_add_test (tc_chain, test_clipping);
983   tcase_add_test (tc_chain, test_preroll_sync);
984   tcase_add_test (tc_chain, test_eos);
985   tcase_add_test (tc_chain, test_eos2);
986   tcase_add_test (tc_chain, test_position);
987   tcase_add_test (tc_chain, test_notify_race);
988
989   return s;
990 }
991
992 GST_CHECK_MAIN (fakesink);