check: port to the new GLib thread API
[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_count = 0;
125
126   events = NULL;
127 }
128
129 static void
130 cleanup (void)
131 {
132   GST_DEBUG ("cleanup_queue");
133
134   gst_check_drop_buffers ();
135
136   drop_events ();
137
138   if (mysinkpad != NULL) {
139     gst_pad_set_active (mysinkpad, FALSE);
140     gst_check_teardown_sink_pad (queue);
141   }
142
143   gst_pad_set_active (mysrcpad, FALSE);
144   gst_check_teardown_src_pad (queue);
145
146   gst_check_teardown_element (queue);
147   queue = NULL;
148 }
149
150 /* setup the sinkpad on a playing queue element. gst_check_setup_sink_pad()
151  * does not work in this case since it does not activate the pad before linking
152  * it. */
153 static GstPad *
154 setup_sink_pad (GstElement * element, GstStaticPadTemplate * tmpl)
155 {
156   GstPad *srcpad;
157   GstPad *sinkpad;
158
159   sinkpad = gst_pad_new_from_static_template (tmpl, "sink");
160   fail_if (sinkpad == NULL);
161   srcpad = gst_element_get_static_pad (element, "src");
162   fail_if (srcpad == NULL);
163   gst_pad_set_chain_function (sinkpad, gst_check_chain_func);
164   gst_pad_set_event_function (sinkpad, event_func);
165   gst_pad_set_active (sinkpad, TRUE);
166   fail_unless (gst_pad_link (srcpad, sinkpad) == GST_PAD_LINK_OK);
167   gst_object_unref (srcpad);
168
169   return sinkpad;
170 }
171
172 /* set queue size to 2 buffers
173  * pull 1 buffer
174  * check over/underuns
175  */
176 GST_START_TEST (test_non_leaky_underrun)
177 {
178   g_signal_connect (queue, "overrun", G_CALLBACK (queue_overrun), NULL);
179   g_object_set (G_OBJECT (queue), "max-size-buffers", 2, NULL);
180   mysinkpad = gst_check_setup_sink_pad (queue, &sinktemplate);
181   gst_pad_set_active (mysinkpad, TRUE);
182
183   GST_DEBUG ("starting");
184
185   UNDERRUN_LOCK ();
186   fail_unless (gst_element_set_state (queue,
187           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
188       "could not set to playing");
189   UNDERRUN_WAIT ();
190   UNDERRUN_UNLOCK ();
191
192   fail_unless (overrun_count == 0);
193   fail_unless (underrun_count == 1);
194
195   GST_DEBUG ("stopping");
196   fail_unless (gst_element_set_state (queue,
197           GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null");
198 }
199
200 GST_END_TEST;
201
202 static void
203 queue_overrun_link_and_activate (GstElement * queue, gpointer user_data)
204 {
205   GST_DEBUG ("queue overrun");
206   overrun_count++;
207
208   /* link the src pad of the queue to make it dequeue buffers */
209   mysinkpad = setup_sink_pad (queue, &sinktemplate);
210
211   unblock_src ();
212 }
213
214 /* set queue size to 2 buffers
215  * push 2 buffers
216  * check over/underuns
217  * push 1 more buffer
218  * check over/underuns again
219  */
220 GST_START_TEST (test_non_leaky_overrun)
221 {
222   GstBuffer *buffer1;
223   GstBuffer *buffer2;
224   GstBuffer *buffer3;
225   GstBuffer *buffer;
226
227   g_signal_connect (queue, "overrun",
228       G_CALLBACK (queue_overrun_link_and_activate), NULL);
229   g_object_set (G_OBJECT (queue), "max-size-buffers", 2, NULL);
230
231   block_src ();
232
233   GST_DEBUG ("starting");
234
235   UNDERRUN_LOCK ();
236   fail_unless (gst_element_set_state (queue,
237           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
238       "could not set to playing");
239   UNDERRUN_WAIT ();
240   UNDERRUN_UNLOCK ();
241
242   gst_pad_push_event (mysrcpad, gst_event_new_stream_start ("test"));
243
244   fail_unless (underrun_count == 1);
245   fail_unless (overrun_count == 0);
246
247   buffer1 = gst_buffer_new_and_alloc (4);
248   /* pushing gives away my reference */
249   gst_pad_push (mysrcpad, buffer1);
250
251   GST_DEBUG ("added 1st");
252   fail_unless (overrun_count == 0);
253   fail_unless (underrun_count == 1);
254
255   buffer2 = gst_buffer_new_and_alloc (4);
256   gst_pad_push (mysrcpad, buffer2);
257
258   GST_DEBUG ("added 2nd");
259   fail_unless (overrun_count == 0);
260   fail_unless (underrun_count == 1);
261
262   buffer3 = gst_buffer_new_and_alloc (4);
263   /* the next call to gst_pad_push will emit the overrun signal. The signal
264    * handler queue_overrun_link_and_activate() (above) increases overrun_count,
265    * activates and links mysinkpad. The queue task then dequeues a buffer and
266    * gst_pad_push() will return. */
267   gst_pad_push (mysrcpad, buffer3);
268
269   GST_DEBUG ("added 3rd");
270   fail_unless (overrun_count == 1);
271
272   /* lock the check_mutex to block the first buffer pushed to mysinkpad */
273   g_mutex_lock (&check_mutex);
274   /* now let the queue push all buffers */
275   while (g_list_length (buffers) < 3) {
276     g_cond_wait (&check_cond, &check_mutex);
277   }
278   g_mutex_unlock (&check_mutex);
279
280   fail_unless (overrun_count == 1);
281   /* make sure we get the underrun signal before we check underrun_count */
282   UNDERRUN_LOCK ();
283   while (underrun_count < 2) {
284     UNDERRUN_WAIT ();
285   }
286   /* we can't check the underrun_count here safely because when adding the 3rd
287    * buffer, the queue lock is released to emit the overrun signal and the
288    * downstream part can then push and empty the queue and signal an additional
289    * underrun */
290   /* fail_unless_equals_int (underrun_count, 2); */
291   UNDERRUN_UNLOCK ();
292
293   buffer = g_list_nth (buffers, 0)->data;
294   fail_unless (buffer == buffer1);
295
296   buffer = g_list_nth (buffers, 1)->data;
297   fail_unless (buffer == buffer2);
298
299   GST_DEBUG ("stopping");
300   fail_unless (gst_element_set_state (queue,
301           GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null");
302 }
303
304 GST_END_TEST;
305
306 /* set queue size to 2 buffers
307  * push 2 buffers
308  * check over/underuns
309  * push 1 more buffer
310  * check over/underuns again
311  * check which buffer was leaked
312  */
313 GST_START_TEST (test_leaky_upstream)
314 {
315   GstBuffer *buffer1;
316   GstBuffer *buffer2;
317   GstBuffer *buffer3;
318   GstBuffer *buffer;
319
320   g_signal_connect (queue, "overrun", G_CALLBACK (queue_overrun), NULL);
321   g_object_set (G_OBJECT (queue), "max-size-buffers", 2, "leaky", 1, NULL);
322
323   GST_DEBUG ("starting");
324
325   block_src ();
326
327   UNDERRUN_LOCK ();
328   fail_unless (gst_element_set_state (queue,
329           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
330       "could not set to playing");
331   UNDERRUN_WAIT ();
332   UNDERRUN_UNLOCK ();
333
334   gst_pad_push_event (mysrcpad, gst_event_new_stream_start ("test"));
335
336   fail_unless (overrun_count == 0);
337   fail_unless (underrun_count == 1);
338
339   buffer1 = gst_buffer_new_and_alloc (4);
340   /* pushing gives away my reference */
341   gst_pad_push (mysrcpad, buffer1);
342
343   GST_DEBUG ("added 1st");
344   fail_unless (overrun_count == 0);
345   fail_unless (underrun_count == 1);
346
347   buffer2 = gst_buffer_new_and_alloc (4);
348   gst_pad_push (mysrcpad, buffer2);
349
350   GST_DEBUG ("added 2nd");
351   fail_unless (overrun_count == 0);
352   fail_unless (underrun_count == 1);
353
354   buffer3 = gst_buffer_new_and_alloc (4);
355   /* buffer4 will be leaked, keep a ref so refcount can be checked below */
356   gst_buffer_ref (buffer3);
357   gst_pad_push (mysrcpad, buffer3);
358
359   GST_DEBUG ("added 3nd");
360   /* it still triggers overrun when leaking */
361   fail_unless (overrun_count == 1);
362   fail_unless (underrun_count == 1);
363
364   /* wait for underrun and check that we got buffer1 and buffer2 only */
365   UNDERRUN_LOCK ();
366   mysinkpad = setup_sink_pad (queue, &sinktemplate);
367   unblock_src ();
368   UNDERRUN_WAIT ();
369   UNDERRUN_UNLOCK ();
370
371   fail_unless (overrun_count == 1);
372   fail_unless (underrun_count == 2);
373
374   fail_unless (g_list_length (buffers) == 2);
375
376   buffer = g_list_nth (buffers, 0)->data;
377   fail_unless (buffer == buffer1);
378
379   buffer = g_list_nth (buffers, 1)->data;
380   fail_unless (buffer == buffer2);
381
382   ASSERT_BUFFER_REFCOUNT (buffer3, "buffer", 1);
383   gst_buffer_unref (buffer3);
384
385   GST_DEBUG ("stopping");
386   fail_unless (gst_element_set_state (queue,
387           GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null");
388 }
389
390 GST_END_TEST;
391
392 /* set queue size to 2 buffers
393  * push 2 buffers
394  * check over/underuns
395  * push 1 more buffer
396  * check over/underuns again
397  * check which buffer was leaked
398  */
399 GST_START_TEST (test_leaky_downstream)
400 {
401   GstBuffer *buffer1;
402   GstBuffer *buffer2;
403   GstBuffer *buffer3;
404   GstBuffer *buffer;
405
406   g_signal_connect (queue, "overrun", G_CALLBACK (queue_overrun), NULL);
407   g_object_set (G_OBJECT (queue), "max-size-buffers", 2, "leaky", 2, NULL);
408
409   GST_DEBUG ("starting");
410
411   block_src ();
412
413   UNDERRUN_LOCK ();
414   fail_unless (gst_element_set_state (queue,
415           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
416       "could not set to playing");
417   UNDERRUN_WAIT ();
418   UNDERRUN_UNLOCK ();
419
420   gst_pad_push_event (mysrcpad, gst_event_new_stream_start ("test"));
421
422   fail_unless (overrun_count == 0);
423   fail_unless (underrun_count == 1);
424
425   buffer1 = gst_buffer_new_and_alloc (4);
426   /* pushing gives away one reference */
427   /* buffer1 will be leaked, keep a ref so refcount can be checked below */
428   gst_buffer_ref (buffer1);
429   gst_pad_push (mysrcpad, buffer1);
430
431   GST_DEBUG ("added 1st");
432   fail_unless (overrun_count == 0);
433   fail_unless (underrun_count == 1);
434
435   buffer2 = gst_buffer_new_and_alloc (4);
436   gst_pad_push (mysrcpad, buffer2);
437
438   GST_DEBUG ("added 2nd");
439   fail_unless (overrun_count == 0);
440   fail_unless (underrun_count == 1);
441
442   buffer3 = gst_buffer_new_and_alloc (4);
443   gst_pad_push (mysrcpad, buffer3);
444
445   GST_DEBUG ("added 3rd");
446   /* it still triggers overrun when leaking */
447   fail_unless (overrun_count == 1);
448   fail_unless (underrun_count == 1);
449
450   /* wait for underrun and check that we got buffer1 and buffer2 only */
451   UNDERRUN_LOCK ();
452   mysinkpad = setup_sink_pad (queue, &sinktemplate);
453   unblock_src ();
454   UNDERRUN_WAIT ();
455   UNDERRUN_UNLOCK ();
456
457   fail_unless (overrun_count == 1);
458   fail_unless (underrun_count == 2);
459
460   fail_unless (g_list_length (buffers) == 2);
461
462   ASSERT_BUFFER_REFCOUNT (buffer1, "buffer", 1);
463   gst_buffer_unref (buffer1);
464
465   buffer = g_list_nth (buffers, 0)->data;
466   fail_unless (buffer == buffer2);
467
468   buffer = g_list_nth (buffers, 1)->data;
469   fail_unless (buffer == buffer3);
470
471   GST_DEBUG ("stopping");
472   fail_unless (gst_element_set_state (queue,
473           GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null");
474 }
475
476 GST_END_TEST;
477
478 /* set queue size to 6 buffers and 7 seconds
479  * push 7 buffers with and without duration
480  * check current-level-time
481  */
482 GST_START_TEST (test_time_level)
483 {
484   GstBuffer *buffer = NULL;
485   GstClockTime time;
486
487   g_signal_connect (queue, "overrun",
488       G_CALLBACK (queue_overrun_link_and_activate), NULL);
489   g_object_set (G_OBJECT (queue), "max-size-buffers", 6, NULL);
490   g_object_set (G_OBJECT (queue), "max-size-time", 7 * GST_SECOND, NULL);
491
492   GST_DEBUG ("starting");
493
494   block_src ();
495
496   UNDERRUN_LOCK ();
497   fail_unless (gst_element_set_state (queue,
498           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
499       "could not set to playing");
500   UNDERRUN_WAIT ();
501   UNDERRUN_UNLOCK ();
502
503   gst_pad_push_event (mysrcpad, gst_event_new_stream_start ("test"));
504
505   /* push buffer without duration */
506   buffer = gst_buffer_new_and_alloc (4);
507   GST_BUFFER_TIMESTAMP (buffer) = GST_SECOND;
508   /* pushing gives away my reference */
509   gst_pad_push (mysrcpad, buffer);
510
511   /* level should be 1 seconds because buffer has no duration and starts at 1
512    * SECOND (sparse stream). */
513   g_object_get (G_OBJECT (queue), "current-level-time", &time, NULL);
514   fail_if (time != GST_SECOND);
515
516   /* second push should set the level to 2 second */
517   buffer = gst_buffer_new_and_alloc (4);
518   GST_BUFFER_TIMESTAMP (buffer) = 2 * GST_SECOND;
519   gst_pad_push (mysrcpad, buffer);
520
521   g_object_get (G_OBJECT (queue), "current-level-time", &time, NULL);
522   fail_if (time != 2 * GST_SECOND);
523
524   /* third push should set the level to 4 seconds, the 1 second diff with the
525    * previous buffer (without duration) and the 1 second duration of this
526    * buffer. */
527   buffer = gst_buffer_new_and_alloc (4);
528   GST_BUFFER_TIMESTAMP (buffer) = 3 * GST_SECOND;
529   GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND;
530   ASSERT_BUFFER_REFCOUNT (buffer, "buffer", 1);
531   gst_pad_push (mysrcpad, buffer);
532
533   g_object_get (G_OBJECT (queue), "current-level-time", &time, NULL);
534   fail_if (time != 4 * GST_SECOND);
535
536   /* fourth push should set the level to 6 seconds, the 2 second diff with the
537    * previous buffer, same duration. */
538   buffer = gst_buffer_new_and_alloc (4);
539   GST_BUFFER_TIMESTAMP (buffer) = 5 * GST_SECOND;
540   GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND;
541   ASSERT_BUFFER_REFCOUNT (buffer, "buffer", 1);
542   gst_pad_push (mysrcpad, buffer);
543
544   g_object_get (G_OBJECT (queue), "current-level-time", &time, NULL);
545   fail_if (time != 6 * GST_SECOND);
546
547   /* fifth push should not adjust the level, the timestamp and duration are the
548    * same, meaning the previous buffer did not really have a duration. */
549   buffer = gst_buffer_new_and_alloc (4);
550   GST_BUFFER_TIMESTAMP (buffer) = 5 * GST_SECOND;
551   GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND;
552   gst_pad_push (mysrcpad, buffer);
553
554   g_object_get (G_OBJECT (queue), "current-level-time", &time, NULL);
555   fail_if (time != 6 * GST_SECOND);
556
557   /* sixth push should adjust the level with 1 second, we now know the
558    * previous buffer actually had a duration of 2 SECONDS */
559   buffer = gst_buffer_new_and_alloc (4);
560   GST_BUFFER_TIMESTAMP (buffer) = 7 * GST_SECOND;
561   gst_pad_push (mysrcpad, buffer);
562
563   g_object_get (G_OBJECT (queue), "current-level-time", &time, NULL);
564   fail_if (time != 7 * GST_SECOND);
565
566   /* eighth push should cause overrun */
567   fail_unless (overrun_count == 0);
568   buffer = gst_buffer_new_and_alloc (4);
569   GST_BUFFER_TIMESTAMP (buffer) = 8 * GST_SECOND;
570   /* the next call to gst_pad_push will emit the overrun signal. The signal
571    * handler queue_overrun_link_and_activate() (above) increases overrun_count,
572    * activates and links mysinkpad. The queue task then dequeues a buffer and
573    * gst_pad_push() will return. */
574   gst_pad_push (mysrcpad, buffer);
575
576   fail_unless (overrun_count == 1);
577
578   GST_DEBUG ("stopping");
579   fail_unless (gst_element_set_state (queue,
580           GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null");
581 }
582
583 GST_END_TEST;
584
585 GST_START_TEST (test_time_level_task_not_started)
586 {
587   GstEvent *event;
588   GstClockTime time;
589   GstSegment segment;
590
591   GST_DEBUG ("starting");
592
593   block_src ();
594
595   UNDERRUN_LOCK ();
596   fail_unless (gst_element_set_state (queue,
597           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
598       "could not set to playing");
599   UNDERRUN_WAIT ();
600   UNDERRUN_UNLOCK ();
601
602   gst_pad_push_event (mysrcpad, gst_event_new_stream_start ("test"));
603
604   gst_segment_init (&segment, GST_FORMAT_TIME);
605   segment.start = 1 * GST_SECOND;
606   segment.stop = 5 * GST_SECOND;
607   segment.time = 0;
608   segment.position = 1 * GST_SECOND;
609
610   event = gst_event_new_segment (&segment);
611   gst_pad_push_event (mysrcpad, event);
612
613   g_object_get (G_OBJECT (queue), "current-level-time", &time, NULL);
614   fail_if (time != 0 * GST_SECOND);
615
616   segment.base = 4 * GST_SECOND;
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   GST_DEBUG ("time now %" GST_TIME_FORMAT, GST_TIME_ARGS (time));
622   fail_if (time != 4 * GST_SECOND);
623
624   unblock_src ();
625
626   GST_DEBUG ("stopping");
627   fail_unless (gst_element_set_state (queue,
628           GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null");
629 }
630
631 GST_END_TEST;
632
633 #if 0
634 static gboolean
635 event_equals_newsegment (GstEvent * event, gboolean update, gdouble rate,
636     GstFormat format, gint64 start, gint64 stop, gint64 position)
637 {
638   gboolean ns_update;
639   gdouble ns_rate, ns_arate;
640   GstFormat ns_format;
641   gint64 ns_start;
642   gint64 ns_stop;
643   gint64 ns_position;
644
645   if (GST_EVENT_TYPE (event) != GST_EVENT_SEGMENT) {
646     return FALSE;
647   }
648
649   gst_event_parse_new_segment (event, &ns_update, &ns_rate, &ns_arate,
650       &ns_format, &ns_start, &ns_stop, &ns_position);
651
652   GST_DEBUG ("update %d, rate %lf, format %s, start %" GST_TIME_FORMAT
653       ", stop %" GST_TIME_FORMAT ", position %" GST_TIME_FORMAT, ns_update,
654       ns_rate, gst_format_get_name (ns_format), GST_TIME_ARGS (ns_start),
655       GST_TIME_ARGS (ns_stop), GST_TIME_ARGS (ns_position));
656
657   return (ns_update == update && ns_rate == rate && ns_format == format &&
658       ns_start == start && ns_stop == stop && ns_position == position);
659 }
660
661 GST_START_TEST (test_newsegment)
662 {
663   GstEvent *event;
664   GstBuffer *buffer1;
665   GstBuffer *buffer2;
666   GstBuffer *buffer;
667
668   g_signal_connect (queue, "overrun", G_CALLBACK (queue_overrun), NULL);
669   g_object_set (G_OBJECT (queue), "max-size-buffers", 1, "max-size-time",
670       (guint64) 0, "leaky", 2, NULL);
671
672   GST_DEBUG ("starting");
673
674   fail_unless (gst_element_set_state (queue,
675           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
676       "could not set to playing");
677   fail_unless (overrun_count == 0);
678   fail_unless (underrun_count == 0);
679
680   event = gst_event_new_new_segment (FALSE, 2.0, 1.0, GST_FORMAT_TIME, 0,
681       2 * GST_SECOND, 0);
682   gst_pad_push_event (mysrcpad, event);
683
684   GST_DEBUG ("added 1st newsegment");
685   fail_unless (overrun_count == 0);
686   fail_unless (underrun_count == 0);
687
688   event = gst_event_new_new_segment (FALSE, 1.0, 1.0, GST_FORMAT_TIME, 0,
689       3 * GST_SECOND, 0);
690   gst_pad_push_event (mysrcpad, event);
691
692   GST_DEBUG ("added 2nd newsegment");
693   fail_unless (overrun_count == 0);
694   fail_unless (underrun_count == 0);
695
696   event = gst_event_new_new_segment (FALSE, 1.0, 1.0, GST_FORMAT_TIME,
697       4 * GST_SECOND, 5 * GST_SECOND, 4 * GST_SECOND);
698   gst_pad_push_event (mysrcpad, event);
699
700   GST_DEBUG ("added 3rd newsegment");
701   fail_unless (overrun_count == 0);
702   fail_unless (underrun_count == 0);
703
704   buffer1 = gst_buffer_new_and_alloc (4);
705   /* buffer1 will be leaked, keep a ref so refcount can be checked below */
706   gst_buffer_ref (buffer1);
707   /* pushing gives away one reference */
708   gst_pad_push (mysrcpad, buffer1);
709
710   GST_DEBUG ("added 1st buffer");
711   fail_unless (overrun_count == 0);
712   fail_unless (underrun_count == 0);
713
714   buffer2 = gst_buffer_new_and_alloc (4);
715   /* next push will cause overrun and leak all newsegment events and buffer1 */
716   gst_pad_push (mysrcpad, buffer2);
717
718   GST_DEBUG ("added 2nd buffer");
719   /* it still triggers overrun when leaking */
720   fail_unless (overrun_count == 1);
721   fail_unless (underrun_count == 0);
722
723   /* wait for underrun and check that we got one accumulated newsegment event,
724    * one real newsegment event and buffer2 only */
725   UNDERRUN_LOCK ();
726   mysinkpad = setup_sink_pad (queue, &sinktemplate);
727   UNDERRUN_WAIT ();
728   UNDERRUN_UNLOCK ();
729
730   fail_unless (overrun_count == 1);
731   fail_unless (underrun_count == 1);
732
733   fail_unless (g_list_length (events) == 2);
734
735   event = g_list_nth (events, 0)->data;
736   fail_unless (event_equals_newsegment (event, FALSE, 1.0, GST_FORMAT_TIME, 0,
737           4 * GST_SECOND, 0));
738
739   event = g_list_nth (events, 1)->data;
740   fail_unless (event_equals_newsegment (event, FALSE, 1.0, GST_FORMAT_TIME,
741           4 * GST_SECOND, 5 * GST_SECOND, 4 * GST_SECOND));
742
743   fail_unless (g_list_length (buffers) == 1);
744
745   ASSERT_BUFFER_REFCOUNT (buffer1, "buffer", 1);
746   gst_buffer_unref (buffer1);
747
748   buffer = g_list_nth (buffers, 0)->data;
749   fail_unless (buffer == buffer2);
750
751   GST_DEBUG ("stopping");
752   fail_unless (gst_element_set_state (queue,
753           GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null");
754 }
755
756 GST_END_TEST;
757 #endif
758
759 static Suite *
760 queue_suite (void)
761 {
762   Suite *s = suite_create ("queue");
763   TCase *tc_chain = tcase_create ("general");
764
765   suite_add_tcase (s, tc_chain);
766   tcase_add_checked_fixture (tc_chain, setup, cleanup);
767   tcase_add_test (tc_chain, test_non_leaky_underrun);
768   tcase_add_test (tc_chain, test_non_leaky_overrun);
769   tcase_add_test (tc_chain, test_leaky_upstream);
770   tcase_add_test (tc_chain, test_leaky_downstream);
771   tcase_add_test (tc_chain, test_time_level);
772   tcase_add_test (tc_chain, test_time_level_task_not_started);
773 #if 0
774   tcase_add_test (tc_chain, test_newsegment);
775 #endif
776
777   return s;
778 }
779
780 GST_CHECK_MAIN (queue);