Merge branch '0.10'
[platform/upstream/gstreamer.git] / tests / check / elements / queue.c
1 /* GStreamer
2  *
3  * unit test for queue
4  *
5  * Copyright (C) <2006> Stefan Kost <ensonic@users.sf.net>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 #include <unistd.h>
24
25 #include <gst/check/gstcheck.h>
26
27 #define UNDERRUN_LOCK() (g_mutex_lock (underrun_mutex))
28 #define UNDERRUN_UNLOCK() (g_mutex_unlock (underrun_mutex))
29 #define UNDERRUN_SIGNAL() (g_cond_signal (underrun_cond))
30 #define UNDERRUN_WAIT() (g_cond_wait (underrun_cond, underrun_mutex))
31
32 static GstElement *queue;
33
34 /* For ease of programming we use globals to keep refs for our floating
35  * src and sink pads we create; otherwise we always have to do get_pad,
36  * get_peer, and then remove references in every test function */
37 static GstPad *mysrcpad;
38 static GstPad *mysinkpad;
39 static GstPad *qsrcpad;
40 static gulong probe_id;
41
42 static gint overrun_count;
43
44 static GMutex *underrun_mutex;
45 static GCond *underrun_cond;
46 static gint underrun_count;
47
48 static GList *events;
49
50 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
51     GST_PAD_SINK,
52     GST_PAD_ALWAYS,
53     GST_STATIC_CAPS_ANY);
54 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
55     GST_PAD_SRC,
56     GST_PAD_ALWAYS,
57     GST_STATIC_CAPS_ANY);
58
59 static void
60 queue_overrun (GstElement * queue, gpointer user_data)
61 {
62   overrun_count++;
63   GST_DEBUG ("queue overrun %d", overrun_count);
64 }
65
66 static void
67 queue_underrun (GstElement * queue, gpointer user_data)
68 {
69   UNDERRUN_LOCK ();
70   underrun_count++;
71   GST_DEBUG ("queue underrun %d", underrun_count);
72   UNDERRUN_SIGNAL ();
73   UNDERRUN_UNLOCK ();
74 }
75
76 static gboolean
77 event_func (GstPad * pad, GstObject * parent, GstEvent * event)
78 {
79   GST_DEBUG ("%s event", gst_event_type_get_name (GST_EVENT_TYPE (event)));
80   events = g_list_append (events, event);
81
82   return TRUE;
83 }
84
85 static void
86 drop_events (void)
87 {
88   while (events != NULL) {
89     gst_event_unref (GST_EVENT (events->data));
90     events = g_list_delete_link (events, events);
91   }
92 }
93
94 static void
95 block_src (void)
96 {
97   qsrcpad = gst_element_get_static_pad (queue, "src");
98   probe_id = gst_pad_add_probe (qsrcpad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
99       NULL, NULL, NULL);
100 }
101
102 static void
103 unblock_src (void)
104 {
105   gst_pad_remove_probe (qsrcpad, probe_id);
106   gst_object_unref (qsrcpad);
107 }
108
109 static void
110 setup (void)
111 {
112   GST_DEBUG ("setup_queue");
113
114   queue = gst_check_setup_element ("queue");
115   g_signal_connect (queue, "underrun", G_CALLBACK (queue_underrun), NULL);
116
117   mysrcpad = gst_check_setup_src_pad (queue, &srctemplate);
118   gst_pad_set_active (mysrcpad, TRUE);
119
120   mysinkpad = NULL;
121
122   overrun_count = 0;
123
124   underrun_mutex = g_mutex_new ();
125   underrun_cond = g_cond_new ();
126   underrun_count = 0;
127
128   events = NULL;
129 }
130
131 static void
132 cleanup (void)
133 {
134   GST_DEBUG ("cleanup_queue");
135
136   gst_check_drop_buffers ();
137
138   drop_events ();
139
140   g_cond_free (underrun_cond);
141   underrun_cond = NULL;
142   g_mutex_free (underrun_mutex);
143   underrun_mutex = NULL;
144
145   if (mysinkpad != NULL) {
146     gst_pad_set_active (mysinkpad, FALSE);
147     gst_check_teardown_sink_pad (queue);
148   }
149
150   gst_pad_set_active (mysrcpad, FALSE);
151   gst_check_teardown_src_pad (queue);
152
153   gst_check_teardown_element (queue);
154   queue = NULL;
155 }
156
157 /* setup the sinkpad on a playing queue element. gst_check_setup_sink_pad()
158  * does not work in this case since it does not activate the pad before linking
159  * it. */
160 static GstPad *
161 setup_sink_pad (GstElement * element, GstStaticPadTemplate * tmpl)
162 {
163   GstPad *srcpad;
164   GstPad *sinkpad;
165
166   sinkpad = gst_pad_new_from_static_template (tmpl, "sink");
167   fail_if (sinkpad == NULL);
168   srcpad = gst_element_get_static_pad (element, "src");
169   fail_if (srcpad == NULL);
170   gst_pad_set_chain_function (sinkpad, gst_check_chain_func);
171   gst_pad_set_event_function (sinkpad, event_func);
172   gst_pad_set_active (sinkpad, TRUE);
173   fail_unless (gst_pad_link (srcpad, sinkpad) == GST_PAD_LINK_OK);
174   gst_object_unref (srcpad);
175
176   return sinkpad;
177 }
178
179 /* set queue size to 2 buffers
180  * pull 1 buffer
181  * check over/underuns
182  */
183 GST_START_TEST (test_non_leaky_underrun)
184 {
185   g_signal_connect (queue, "overrun", G_CALLBACK (queue_overrun), NULL);
186   g_object_set (G_OBJECT (queue), "max-size-buffers", 2, NULL);
187   mysinkpad = gst_check_setup_sink_pad (queue, &sinktemplate);
188   gst_pad_set_active (mysinkpad, TRUE);
189
190   GST_DEBUG ("starting");
191
192   UNDERRUN_LOCK ();
193   fail_unless (gst_element_set_state (queue,
194           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
195       "could not set to playing");
196   UNDERRUN_WAIT ();
197   UNDERRUN_UNLOCK ();
198
199   fail_unless (overrun_count == 0);
200   fail_unless (underrun_count == 1);
201
202   GST_DEBUG ("stopping");
203   fail_unless (gst_element_set_state (queue,
204           GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null");
205 }
206
207 GST_END_TEST;
208
209 static void
210 queue_overrun_link_and_activate (GstElement * queue, gpointer user_data)
211 {
212   GST_DEBUG ("queue overrun");
213   overrun_count++;
214
215   /* link the src pad of the queue to make it dequeue buffers */
216   mysinkpad = setup_sink_pad (queue, &sinktemplate);
217
218   unblock_src ();
219 }
220
221 /* set queue size to 2 buffers
222  * push 2 buffers
223  * check over/underuns
224  * push 1 more buffer
225  * check over/underuns again
226  */
227 GST_START_TEST (test_non_leaky_overrun)
228 {
229   GstBuffer *buffer1;
230   GstBuffer *buffer2;
231   GstBuffer *buffer3;
232   GstBuffer *buffer;
233
234   g_signal_connect (queue, "overrun",
235       G_CALLBACK (queue_overrun_link_and_activate), NULL);
236   g_object_set (G_OBJECT (queue), "max-size-buffers", 2, NULL);
237
238   block_src ();
239
240   GST_DEBUG ("starting");
241
242   UNDERRUN_LOCK ();
243   fail_unless (gst_element_set_state (queue,
244           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
245       "could not set to playing");
246   UNDERRUN_WAIT ();
247   UNDERRUN_UNLOCK ();
248
249   gst_pad_push_event (mysrcpad, gst_event_new_stream_start ());
250
251   fail_unless (underrun_count == 1);
252   fail_unless (overrun_count == 0);
253
254   buffer1 = gst_buffer_new_and_alloc (4);
255   /* pushing gives away my reference */
256   gst_pad_push (mysrcpad, buffer1);
257
258   GST_DEBUG ("added 1st");
259   fail_unless (overrun_count == 0);
260   fail_unless (underrun_count == 1);
261
262   buffer2 = gst_buffer_new_and_alloc (4);
263   gst_pad_push (mysrcpad, buffer2);
264
265   GST_DEBUG ("added 2nd");
266   fail_unless (overrun_count == 0);
267   fail_unless (underrun_count == 1);
268
269   buffer3 = gst_buffer_new_and_alloc (4);
270   /* the next call to gst_pad_push will emit the overrun signal. The signal
271    * handler queue_overrun_link_and_activate() (above) increases overrun_count,
272    * activates and links mysinkpad. The queue task then dequeues a buffer and
273    * gst_pad_push() will return. */
274   gst_pad_push (mysrcpad, buffer3);
275
276   GST_DEBUG ("added 3rd");
277   fail_unless (overrun_count == 1);
278
279   /* lock the check_mutex to block the first buffer pushed to mysinkpad */
280   g_mutex_lock (check_mutex);
281   /* now let the queue push all buffers */
282   while (g_list_length (buffers) < 3) {
283     g_cond_wait (check_cond, check_mutex);
284   }
285   g_mutex_unlock (check_mutex);
286
287   fail_unless (overrun_count == 1);
288   /* make sure we get the underrun signal before we check underrun_count */
289   UNDERRUN_LOCK ();
290   while (underrun_count < 2) {
291     UNDERRUN_WAIT ();
292   }
293   /* we can't check the underrun_count here safely because when adding the 3rd
294    * buffer, the queue lock is released to emit the overrun signal and the
295    * downstream part can then push and empty the queue and signal an additional
296    * underrun */
297   /* fail_unless_equals_int (underrun_count, 2); */
298   UNDERRUN_UNLOCK ();
299
300   buffer = g_list_nth (buffers, 0)->data;
301   fail_unless (buffer == buffer1);
302
303   buffer = g_list_nth (buffers, 1)->data;
304   fail_unless (buffer == buffer2);
305
306   GST_DEBUG ("stopping");
307   fail_unless (gst_element_set_state (queue,
308           GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null");
309 }
310
311 GST_END_TEST;
312
313 /* set queue size to 2 buffers
314  * push 2 buffers
315  * check over/underuns
316  * push 1 more buffer
317  * check over/underuns again
318  * check which buffer was leaked
319  */
320 GST_START_TEST (test_leaky_upstream)
321 {
322   GstBuffer *buffer1;
323   GstBuffer *buffer2;
324   GstBuffer *buffer3;
325   GstBuffer *buffer;
326
327   g_signal_connect (queue, "overrun", G_CALLBACK (queue_overrun), NULL);
328   g_object_set (G_OBJECT (queue), "max-size-buffers", 2, "leaky", 1, NULL);
329
330   GST_DEBUG ("starting");
331
332   block_src ();
333
334   UNDERRUN_LOCK ();
335   fail_unless (gst_element_set_state (queue,
336           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
337       "could not set to playing");
338   UNDERRUN_WAIT ();
339   UNDERRUN_UNLOCK ();
340
341   gst_pad_push_event (mysrcpad, gst_event_new_stream_start ());
342
343   fail_unless (overrun_count == 0);
344   fail_unless (underrun_count == 1);
345
346   buffer1 = gst_buffer_new_and_alloc (4);
347   /* pushing gives away my reference */
348   gst_pad_push (mysrcpad, buffer1);
349
350   GST_DEBUG ("added 1st");
351   fail_unless (overrun_count == 0);
352   fail_unless (underrun_count == 1);
353
354   buffer2 = gst_buffer_new_and_alloc (4);
355   gst_pad_push (mysrcpad, buffer2);
356
357   GST_DEBUG ("added 2nd");
358   fail_unless (overrun_count == 0);
359   fail_unless (underrun_count == 1);
360
361   buffer3 = gst_buffer_new_and_alloc (4);
362   /* buffer4 will be leaked, keep a ref so refcount can be checked below */
363   gst_buffer_ref (buffer3);
364   gst_pad_push (mysrcpad, buffer3);
365
366   GST_DEBUG ("added 3nd");
367   /* it still triggers overrun when leaking */
368   fail_unless (overrun_count == 1);
369   fail_unless (underrun_count == 1);
370
371   /* wait for underrun and check that we got buffer1 and buffer2 only */
372   UNDERRUN_LOCK ();
373   mysinkpad = setup_sink_pad (queue, &sinktemplate);
374   unblock_src ();
375   UNDERRUN_WAIT ();
376   UNDERRUN_UNLOCK ();
377
378   fail_unless (overrun_count == 1);
379   fail_unless (underrun_count == 2);
380
381   fail_unless (g_list_length (buffers) == 2);
382
383   buffer = g_list_nth (buffers, 0)->data;
384   fail_unless (buffer == buffer1);
385
386   buffer = g_list_nth (buffers, 1)->data;
387   fail_unless (buffer == buffer2);
388
389   ASSERT_BUFFER_REFCOUNT (buffer3, "buffer", 1);
390   gst_buffer_unref (buffer3);
391
392   GST_DEBUG ("stopping");
393   fail_unless (gst_element_set_state (queue,
394           GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null");
395 }
396
397 GST_END_TEST;
398
399 /* set queue size to 2 buffers
400  * push 2 buffers
401  * check over/underuns
402  * push 1 more buffer
403  * check over/underuns again
404  * check which buffer was leaked
405  */
406 GST_START_TEST (test_leaky_downstream)
407 {
408   GstBuffer *buffer1;
409   GstBuffer *buffer2;
410   GstBuffer *buffer3;
411   GstBuffer *buffer;
412
413   g_signal_connect (queue, "overrun", G_CALLBACK (queue_overrun), NULL);
414   g_object_set (G_OBJECT (queue), "max-size-buffers", 2, "leaky", 2, NULL);
415
416   GST_DEBUG ("starting");
417
418   block_src ();
419
420   UNDERRUN_LOCK ();
421   fail_unless (gst_element_set_state (queue,
422           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
423       "could not set to playing");
424   UNDERRUN_WAIT ();
425   UNDERRUN_UNLOCK ();
426
427   gst_pad_push_event (mysrcpad, gst_event_new_stream_start ());
428
429   fail_unless (overrun_count == 0);
430   fail_unless (underrun_count == 1);
431
432   buffer1 = gst_buffer_new_and_alloc (4);
433   /* pushing gives away one reference */
434   /* buffer1 will be leaked, keep a ref so refcount can be checked below */
435   gst_buffer_ref (buffer1);
436   gst_pad_push (mysrcpad, buffer1);
437
438   GST_DEBUG ("added 1st");
439   fail_unless (overrun_count == 0);
440   fail_unless (underrun_count == 1);
441
442   buffer2 = gst_buffer_new_and_alloc (4);
443   gst_pad_push (mysrcpad, buffer2);
444
445   GST_DEBUG ("added 2nd");
446   fail_unless (overrun_count == 0);
447   fail_unless (underrun_count == 1);
448
449   buffer3 = gst_buffer_new_and_alloc (4);
450   gst_pad_push (mysrcpad, buffer3);
451
452   GST_DEBUG ("added 3rd");
453   /* it still triggers overrun when leaking */
454   fail_unless (overrun_count == 1);
455   fail_unless (underrun_count == 1);
456
457   /* wait for underrun and check that we got buffer1 and buffer2 only */
458   UNDERRUN_LOCK ();
459   mysinkpad = setup_sink_pad (queue, &sinktemplate);
460   unblock_src ();
461   UNDERRUN_WAIT ();
462   UNDERRUN_UNLOCK ();
463
464   fail_unless (overrun_count == 1);
465   fail_unless (underrun_count == 2);
466
467   fail_unless (g_list_length (buffers) == 2);
468
469   ASSERT_BUFFER_REFCOUNT (buffer1, "buffer", 1);
470   gst_buffer_unref (buffer1);
471
472   buffer = g_list_nth (buffers, 0)->data;
473   fail_unless (buffer == buffer2);
474
475   buffer = g_list_nth (buffers, 1)->data;
476   fail_unless (buffer == buffer3);
477
478   GST_DEBUG ("stopping");
479   fail_unless (gst_element_set_state (queue,
480           GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null");
481 }
482
483 GST_END_TEST;
484
485 /* set queue size to 6 buffers and 7 seconds
486  * push 7 buffers with and without duration
487  * check current-level-time
488  */
489 GST_START_TEST (test_time_level)
490 {
491   GstBuffer *buffer = NULL;
492   GstClockTime time;
493
494   g_signal_connect (queue, "overrun",
495       G_CALLBACK (queue_overrun_link_and_activate), NULL);
496   g_object_set (G_OBJECT (queue), "max-size-buffers", 6, NULL);
497   g_object_set (G_OBJECT (queue), "max-size-time", 7 * GST_SECOND, NULL);
498
499   GST_DEBUG ("starting");
500
501   block_src ();
502
503   UNDERRUN_LOCK ();
504   fail_unless (gst_element_set_state (queue,
505           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
506       "could not set to playing");
507   UNDERRUN_WAIT ();
508   UNDERRUN_UNLOCK ();
509
510   gst_pad_push_event (mysrcpad, gst_event_new_stream_start ());
511
512   /* push buffer without duration */
513   buffer = gst_buffer_new_and_alloc (4);
514   GST_BUFFER_TIMESTAMP (buffer) = GST_SECOND;
515   /* pushing gives away my reference */
516   gst_pad_push (mysrcpad, buffer);
517
518   /* level should be 1 seconds because buffer has no duration and starts at 1
519    * SECOND (sparse stream). */
520   g_object_get (G_OBJECT (queue), "current-level-time", &time, NULL);
521   fail_if (time != GST_SECOND);
522
523   /* second push should set the level to 2 second */
524   buffer = gst_buffer_new_and_alloc (4);
525   GST_BUFFER_TIMESTAMP (buffer) = 2 * GST_SECOND;
526   gst_pad_push (mysrcpad, buffer);
527
528   g_object_get (G_OBJECT (queue), "current-level-time", &time, NULL);
529   fail_if (time != 2 * GST_SECOND);
530
531   /* third push should set the level to 4 seconds, the 1 second diff with the
532    * previous buffer (without duration) and the 1 second duration of this
533    * buffer. */
534   buffer = gst_buffer_new_and_alloc (4);
535   GST_BUFFER_TIMESTAMP (buffer) = 3 * GST_SECOND;
536   GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND;
537   ASSERT_BUFFER_REFCOUNT (buffer, "buffer", 1);
538   gst_pad_push (mysrcpad, buffer);
539
540   g_object_get (G_OBJECT (queue), "current-level-time", &time, NULL);
541   fail_if (time != 4 * GST_SECOND);
542
543   /* fourth push should set the level to 6 seconds, the 2 second diff with the
544    * previous buffer, same duration. */
545   buffer = gst_buffer_new_and_alloc (4);
546   GST_BUFFER_TIMESTAMP (buffer) = 5 * GST_SECOND;
547   GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND;
548   ASSERT_BUFFER_REFCOUNT (buffer, "buffer", 1);
549   gst_pad_push (mysrcpad, buffer);
550
551   g_object_get (G_OBJECT (queue), "current-level-time", &time, NULL);
552   fail_if (time != 6 * GST_SECOND);
553
554   /* fifth push should not adjust the level, the timestamp and duration are the
555    * same, meaning the previous buffer did not really have a duration. */
556   buffer = gst_buffer_new_and_alloc (4);
557   GST_BUFFER_TIMESTAMP (buffer) = 5 * GST_SECOND;
558   GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND;
559   gst_pad_push (mysrcpad, buffer);
560
561   g_object_get (G_OBJECT (queue), "current-level-time", &time, NULL);
562   fail_if (time != 6 * GST_SECOND);
563
564   /* sixth push should adjust the level with 1 second, we now know the
565    * previous buffer actually had a duration of 2 SECONDS */
566   buffer = gst_buffer_new_and_alloc (4);
567   GST_BUFFER_TIMESTAMP (buffer) = 7 * GST_SECOND;
568   gst_pad_push (mysrcpad, buffer);
569
570   g_object_get (G_OBJECT (queue), "current-level-time", &time, NULL);
571   fail_if (time != 7 * GST_SECOND);
572
573   /* eighth push should cause overrun */
574   fail_unless (overrun_count == 0);
575   buffer = gst_buffer_new_and_alloc (4);
576   GST_BUFFER_TIMESTAMP (buffer) = 8 * GST_SECOND;
577   /* the next call to gst_pad_push will emit the overrun signal. The signal
578    * handler queue_overrun_link_and_activate() (above) increases overrun_count,
579    * activates and links mysinkpad. The queue task then dequeues a buffer and
580    * gst_pad_push() will return. */
581   gst_pad_push (mysrcpad, buffer);
582
583   fail_unless (overrun_count == 1);
584
585   GST_DEBUG ("stopping");
586   fail_unless (gst_element_set_state (queue,
587           GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null");
588 }
589
590 GST_END_TEST;
591
592 GST_START_TEST (test_time_level_task_not_started)
593 {
594   GstEvent *event;
595   GstClockTime time;
596   GstSegment segment;
597
598   GST_DEBUG ("starting");
599
600   block_src ();
601
602   UNDERRUN_LOCK ();
603   fail_unless (gst_element_set_state (queue,
604           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
605       "could not set to playing");
606   UNDERRUN_WAIT ();
607   UNDERRUN_UNLOCK ();
608
609   gst_pad_push_event (mysrcpad, gst_event_new_stream_start ());
610
611   gst_segment_init (&segment, GST_FORMAT_TIME);
612   segment.start = 1 * GST_SECOND;
613   segment.stop = 5 * GST_SECOND;
614   segment.time = 0;
615   segment.position = 1 * GST_SECOND;
616
617   event = gst_event_new_segment (&segment);
618   gst_pad_push_event (mysrcpad, event);
619
620   g_object_get (G_OBJECT (queue), "current-level-time", &time, NULL);
621   fail_if (time != 0 * GST_SECOND);
622
623   segment.base = 4 * GST_SECOND;
624   event = gst_event_new_segment (&segment);
625   gst_pad_push_event (mysrcpad, event);
626
627   g_object_get (G_OBJECT (queue), "current-level-time", &time, NULL);
628   GST_DEBUG ("time now %" GST_TIME_FORMAT, GST_TIME_ARGS (time));
629   fail_if (time != 4 * GST_SECOND);
630
631   unblock_src ();
632
633   GST_DEBUG ("stopping");
634   fail_unless (gst_element_set_state (queue,
635           GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null");
636 }
637
638 GST_END_TEST;
639
640 #if 0
641 static gboolean
642 event_equals_newsegment (GstEvent * event, gboolean update, gdouble rate,
643     GstFormat format, gint64 start, gint64 stop, gint64 position)
644 {
645   gboolean ns_update;
646   gdouble ns_rate, ns_arate;
647   GstFormat ns_format;
648   gint64 ns_start;
649   gint64 ns_stop;
650   gint64 ns_position;
651
652   if (GST_EVENT_TYPE (event) != GST_EVENT_SEGMENT) {
653     return FALSE;
654   }
655
656   gst_event_parse_new_segment (event, &ns_update, &ns_rate, &ns_arate,
657       &ns_format, &ns_start, &ns_stop, &ns_position);
658
659   GST_DEBUG ("update %d, rate %lf, format %s, start %" GST_TIME_FORMAT
660       ", stop %" GST_TIME_FORMAT ", position %" GST_TIME_FORMAT, ns_update,
661       ns_rate, gst_format_get_name (ns_format), GST_TIME_ARGS (ns_start),
662       GST_TIME_ARGS (ns_stop), GST_TIME_ARGS (ns_position));
663
664   return (ns_update == update && ns_rate == rate && ns_format == format &&
665       ns_start == start && ns_stop == stop && ns_position == position);
666 }
667
668 GST_START_TEST (test_newsegment)
669 {
670   GstEvent *event;
671   GstBuffer *buffer1;
672   GstBuffer *buffer2;
673   GstBuffer *buffer;
674
675   g_signal_connect (queue, "overrun", G_CALLBACK (queue_overrun), NULL);
676   g_object_set (G_OBJECT (queue), "max-size-buffers", 1, "max-size-time",
677       (guint64) 0, "leaky", 2, NULL);
678
679   GST_DEBUG ("starting");
680
681   fail_unless (gst_element_set_state (queue,
682           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
683       "could not set to playing");
684   fail_unless (overrun_count == 0);
685   fail_unless (underrun_count == 0);
686
687   event = gst_event_new_new_segment (FALSE, 2.0, 1.0, GST_FORMAT_TIME, 0,
688       2 * GST_SECOND, 0);
689   gst_pad_push_event (mysrcpad, event);
690
691   GST_DEBUG ("added 1st newsegment");
692   fail_unless (overrun_count == 0);
693   fail_unless (underrun_count == 0);
694
695   event = gst_event_new_new_segment (FALSE, 1.0, 1.0, GST_FORMAT_TIME, 0,
696       3 * GST_SECOND, 0);
697   gst_pad_push_event (mysrcpad, event);
698
699   GST_DEBUG ("added 2nd newsegment");
700   fail_unless (overrun_count == 0);
701   fail_unless (underrun_count == 0);
702
703   event = gst_event_new_new_segment (FALSE, 1.0, 1.0, GST_FORMAT_TIME,
704       4 * GST_SECOND, 5 * GST_SECOND, 4 * GST_SECOND);
705   gst_pad_push_event (mysrcpad, event);
706
707   GST_DEBUG ("added 3rd newsegment");
708   fail_unless (overrun_count == 0);
709   fail_unless (underrun_count == 0);
710
711   buffer1 = gst_buffer_new_and_alloc (4);
712   /* buffer1 will be leaked, keep a ref so refcount can be checked below */
713   gst_buffer_ref (buffer1);
714   /* pushing gives away one reference */
715   gst_pad_push (mysrcpad, buffer1);
716
717   GST_DEBUG ("added 1st buffer");
718   fail_unless (overrun_count == 0);
719   fail_unless (underrun_count == 0);
720
721   buffer2 = gst_buffer_new_and_alloc (4);
722   /* next push will cause overrun and leak all newsegment events and buffer1 */
723   gst_pad_push (mysrcpad, buffer2);
724
725   GST_DEBUG ("added 2nd buffer");
726   /* it still triggers overrun when leaking */
727   fail_unless (overrun_count == 1);
728   fail_unless (underrun_count == 0);
729
730   /* wait for underrun and check that we got one accumulated newsegment event,
731    * one real newsegment event and buffer2 only */
732   UNDERRUN_LOCK ();
733   mysinkpad = setup_sink_pad (queue, &sinktemplate);
734   UNDERRUN_WAIT ();
735   UNDERRUN_UNLOCK ();
736
737   fail_unless (overrun_count == 1);
738   fail_unless (underrun_count == 1);
739
740   fail_unless (g_list_length (events) == 2);
741
742   event = g_list_nth (events, 0)->data;
743   fail_unless (event_equals_newsegment (event, FALSE, 1.0, GST_FORMAT_TIME, 0,
744           4 * GST_SECOND, 0));
745
746   event = g_list_nth (events, 1)->data;
747   fail_unless (event_equals_newsegment (event, FALSE, 1.0, GST_FORMAT_TIME,
748           4 * GST_SECOND, 5 * GST_SECOND, 4 * GST_SECOND));
749
750   fail_unless (g_list_length (buffers) == 1);
751
752   ASSERT_BUFFER_REFCOUNT (buffer1, "buffer", 1);
753   gst_buffer_unref (buffer1);
754
755   buffer = g_list_nth (buffers, 0)->data;
756   fail_unless (buffer == buffer2);
757
758   GST_DEBUG ("stopping");
759   fail_unless (gst_element_set_state (queue,
760           GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null");
761 }
762
763 GST_END_TEST;
764 #endif
765
766 static Suite *
767 queue_suite (void)
768 {
769   Suite *s = suite_create ("queue");
770   TCase *tc_chain = tcase_create ("general");
771
772   suite_add_tcase (s, tc_chain);
773   tcase_add_checked_fixture (tc_chain, setup, cleanup);
774   tcase_add_test (tc_chain, test_non_leaky_underrun);
775   tcase_add_test (tc_chain, test_non_leaky_overrun);
776   tcase_add_test (tc_chain, test_leaky_upstream);
777   tcase_add_test (tc_chain, test_leaky_downstream);
778   tcase_add_test (tc_chain, test_time_level);
779   tcase_add_test (tc_chain, test_time_level_task_not_started);
780 #if 0
781   tcase_add_test (tc_chain, test_newsegment);
782 #endif
783
784   return s;
785 }
786
787 GST_CHECK_MAIN (queue);