tests: improve segment tests
[platform/upstream/gstreamer.git] / tests / check / gst / gstsegment.c
1 /* GStreamer
2  * Copyright (C) 2005 Jan Schmidt <thaytan@mad.scientist.com>
3  *               2009 Wim Taymans <wim.taymans@gmail.com>
4  *
5  * gstsegment.c: Unit test for segments
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 <gst/check/gstcheck.h>
24
25 static void
26 check_times (GstSegment * segment, guint64 position, guint64 stream_time,
27     guint64 running_time)
28 {
29   guint64 st, rt;
30
31   st = gst_segment_to_stream_time (segment, segment->format, position);
32   rt = gst_segment_to_running_time (segment, segment->format, position);
33
34   fail_unless (st == stream_time);
35   fail_unless (rt == running_time);
36 }
37
38 /* mess with the segment structure in the bytes format */
39 GST_START_TEST (segment_seek_nosize)
40 {
41   GstSegment segment;
42   gboolean res;
43   guint64 cstart, cstop;
44   gboolean update;
45
46   gst_segment_init (&segment, GST_FORMAT_BYTES);
47
48   /* configure segment to start 100 */
49   gst_segment_do_seek (&segment, 1.0,
50       GST_FORMAT_BYTES,
51       GST_SEEK_FLAG_NONE,
52       GST_SEEK_TYPE_SET, 100, GST_SEEK_TYPE_NONE, -1, &update);
53   fail_unless (segment.start == 100);
54   fail_unless (segment.position == 100);
55   fail_unless (segment.stop == -1);
56   fail_unless (update == TRUE);
57   /* appended after current position 0 */
58   check_times (&segment, 100, 100, 0);
59
60   /* do some clipping on the open range */
61   /* completely outside */
62   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 0, 50, &cstart, &cstop);
63   fail_unless (res == FALSE);
64
65   /* touching lower bound, still outside of the segment */
66   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, 100, &cstart, &cstop);
67   fail_unless (res == FALSE);
68
69   /* partially inside */
70   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, 150, &cstart, &cstop);
71   fail_unless (res == TRUE);
72   fail_unless (cstart == 100);
73   fail_unless (cstop == 150);
74
75   /* inside, touching lower bound */
76   res = gst_segment_clip (&segment, GST_FORMAT_BYTES,
77       100, 150, &cstart, &cstop);
78   fail_unless (res == TRUE);
79   fail_unless (cstart == 100);
80   fail_unless (cstop == 150);
81
82   /* special case, 0 duration and outside segment */
83   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 90, 90, &cstart, &cstop);
84   fail_unless (res == FALSE);
85
86   /* special case, 0 duration and touching lower bound, i.e. inside segment */
87   res = gst_segment_clip (&segment, GST_FORMAT_BYTES,
88       100, 100, &cstart, &cstop);
89   fail_unless (res == TRUE);
90   fail_unless (cstart == 100);
91   fail_unless (cstop == 100);
92
93   /* special case, 0 duration and inside the segment */
94   res = gst_segment_clip (&segment, GST_FORMAT_BYTES,
95       120, 120, &cstart, &cstop);
96   fail_unless (res == TRUE);
97   fail_unless (cstart == 120);
98   fail_unless (cstop == 120);
99
100   /* completely inside */
101   res = gst_segment_clip (&segment, GST_FORMAT_BYTES,
102       150, 200, &cstart, &cstop);
103   fail_unless (res == TRUE);
104   fail_unless (cstart == 150);
105   fail_unless (cstop == 200);
106
107   /* invalid start */
108   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, -1, 100, &cstart, &cstop);
109   fail_unless (res == FALSE);
110
111   /* start outside, we don't know the stop */
112   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, -1, &cstart, &cstop);
113   fail_unless (res == TRUE);
114   fail_unless (cstart == 100);
115   fail_unless (cstop == -1);
116
117   /* start on lower bound */
118   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 100, -1, &cstart, &cstop);
119   fail_unless (res == TRUE);
120   fail_unless (cstart == 100);
121   fail_unless (cstop == -1);
122
123   /* start inside */
124   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 150, -1, &cstart, &cstop);
125   fail_unless (res == TRUE);
126   fail_unless (cstart == 150);
127   fail_unless (cstop == -1);
128
129   /* move to 150, this is a running_time of 50 */
130   segment.position = 150;
131   check_times (&segment, 150, 150, 50);
132
133   /* add 100 to start, set stop to 300 */
134   gst_segment_do_seek (&segment, 1.0,
135       GST_FORMAT_BYTES,
136       GST_SEEK_FLAG_NONE,
137       GST_SEEK_TYPE_SET, 100 + 100, GST_SEEK_TYPE_SET, 300, &update);
138   fail_unless (segment.start == 200);
139   fail_unless (segment.position == 200);
140   fail_unless (segment.stop == 300);
141   fail_unless (update == TRUE);
142   check_times (&segment, 200, 200, 50);
143
144   update = FALSE;
145   /* add 100 to start (to 300), set stop to 200, this is not allowed.
146    * nothing should be updated in the segment. A g_warning is
147    * emited. */
148   ASSERT_CRITICAL (gst_segment_do_seek (&segment, 1.0,
149           GST_FORMAT_BYTES,
150           GST_SEEK_FLAG_NONE,
151           GST_SEEK_TYPE_SET, 200 + 100, GST_SEEK_TYPE_SET, 200, &update));
152   fail_unless (segment.start == 200);
153   fail_unless (segment.position == 200);
154   fail_unless (segment.stop == 300);
155   /* update didn't change */
156   fail_unless (update == FALSE);
157   check_times (&segment, 250, 250, 100);
158
159   update = TRUE;
160   /* seek relative to end, should not do anything since size is
161    * unknown. */
162   gst_segment_do_seek (&segment, 1.0,
163       GST_FORMAT_BYTES,
164       GST_SEEK_FLAG_NONE,
165       GST_SEEK_TYPE_END, -300, GST_SEEK_TYPE_END, -100, &update);
166   fail_unless (segment.start == 200);
167   fail_unless (segment.position == 200);
168   fail_unless (segment.stop == 300);
169   fail_unless (update == FALSE);
170   check_times (&segment, 250, 250, 100);
171
172   /* completely outside */
173   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 0, 50, &cstart, &cstop);
174   fail_unless (res == FALSE);
175
176   /* touching lower bound */
177   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, 200, &cstart, &cstop);
178   fail_unless (res == FALSE);
179
180   /* partially inside */
181   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, 250, &cstart, &cstop);
182   fail_unless (res == TRUE);
183   fail_unless (cstart == 200);
184   fail_unless (cstop == 250);
185
186   /* inside, touching lower bound */
187   res = gst_segment_clip (&segment, GST_FORMAT_BYTES,
188       200, 250, &cstart, &cstop);
189   fail_unless (res == TRUE);
190   fail_unless (cstart == 200);
191   fail_unless (cstop == 250);
192
193   /* completely inside */
194   res = gst_segment_clip (&segment, GST_FORMAT_BYTES,
195       250, 290, &cstart, &cstop);
196   fail_unless (res == TRUE);
197   fail_unless (cstart == 250);
198   fail_unless (cstop == 290);
199
200   /* partially inside */
201   res = gst_segment_clip (&segment, GST_FORMAT_BYTES,
202       250, 350, &cstart, &cstop);
203   fail_unless (res == TRUE);
204   fail_unless (cstart == 250);
205   fail_unless (cstop == 300);
206
207   /* invalid start */
208   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, -1, 100, &cstart, &cstop);
209   fail_unless (res == FALSE);
210
211   /* start outside */
212   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, -1, &cstart, &cstop);
213   fail_unless (res == TRUE);
214   fail_unless (cstart == 200);
215   fail_unless (cstop == 300);
216
217   /* start on lower bound */
218   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 200, -1, &cstart, &cstop);
219   fail_unless (res == TRUE);
220   fail_unless (cstart == 200);
221   fail_unless (cstop == 300);
222
223   /* start inside */
224   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 250, -1, &cstart, &cstop);
225   fail_unless (res == TRUE);
226   fail_unless (cstart == 250);
227   fail_unless (cstop == 300);
228
229   /* start outside on boundary */
230   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 300, -1, &cstart, &cstop);
231   fail_unless (res == FALSE);
232
233   /* start completely outside */
234   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 350, -1, &cstart, &cstop);
235   fail_unless (res == FALSE);
236 }
237
238 GST_END_TEST;
239
240 /* mess with the segment structure in the bytes format */
241 GST_START_TEST (segment_seek_size)
242 {
243   GstSegment segment;
244   gboolean res;
245   guint64 cstart, cstop;
246   gboolean update;
247
248   gst_segment_init (&segment, GST_FORMAT_BYTES);
249   segment.duration = 200;
250
251   /* configure segment to start 100 */
252   gst_segment_do_seek (&segment, 1.0,
253       GST_FORMAT_BYTES,
254       GST_SEEK_FLAG_NONE,
255       GST_SEEK_TYPE_SET, 100, GST_SEEK_TYPE_NONE, -1, &update);
256   fail_unless (segment.start == 100);
257   fail_unless (segment.position == 100);
258   fail_unless (segment.stop == -1);
259   fail_unless (update == TRUE);
260   check_times (&segment, 100, 100, 0);
261
262   /* do some clipping on the open range */
263   /* completely outside */
264   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 0, 50, &cstart, &cstop);
265   fail_unless (res == FALSE);
266
267   /* touching lower bound */
268   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, 100, &cstart, &cstop);
269   fail_unless (res == FALSE);
270
271   /* partially inside */
272   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, 150, &cstart, &cstop);
273   fail_unless (res == TRUE);
274   fail_unless (cstart == 100);
275   fail_unless (cstop == 150);
276
277   /* inside, touching lower bound */
278   res = gst_segment_clip (&segment, GST_FORMAT_BYTES,
279       100, 150, &cstart, &cstop);
280   fail_unless (res == TRUE);
281   fail_unless (cstart == 100);
282   fail_unless (cstop == 150);
283
284   /* completely inside */
285   res = gst_segment_clip (&segment, GST_FORMAT_BYTES,
286       150, 200, &cstart, &cstop);
287   fail_unless (res == TRUE);
288   fail_unless (cstart == 150);
289   fail_unless (cstop == 200);
290
291   /* invalid start */
292   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, -1, 100, &cstart, &cstop);
293   fail_unless (res == FALSE);
294
295   /* start outside */
296   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, -1, &cstart, &cstop);
297   fail_unless (res == TRUE);
298   fail_unless (cstart == 100);
299   fail_unless (cstop == -1);
300
301   /* start on lower bound */
302   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 100, -1, &cstart, &cstop);
303   fail_unless (res == TRUE);
304   fail_unless (cstart == 100);
305   fail_unless (cstop == -1);
306
307   /* start inside */
308   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 150, -1, &cstart, &cstop);
309   fail_unless (res == TRUE);
310   fail_unless (cstart == 150);
311   fail_unless (cstop == -1);
312
313   /* add 100 to start, set stop to 300, stop clips to 200 */
314   gst_segment_do_seek (&segment, 1.0,
315       GST_FORMAT_BYTES,
316       GST_SEEK_FLAG_NONE,
317       GST_SEEK_TYPE_SET, 100 + 100, GST_SEEK_TYPE_SET, 300, &update);
318   fail_unless (segment.start == 200);
319   fail_unless (segment.position == 200);
320   fail_unless (segment.stop == 200);
321   check_times (&segment, 200, 200, 0);
322
323   /* add 100 to start (to 300), set stop to 200, this clips start
324    * to duration */
325   gst_segment_do_seek (&segment, 1.0,
326       GST_FORMAT_BYTES,
327       GST_SEEK_FLAG_NONE,
328       GST_SEEK_TYPE_SET, 200 + 100, GST_SEEK_TYPE_SET, 200, &update);
329   fail_unless (segment.start == 200);
330   fail_unless (segment.position == 200);
331   fail_unless (segment.stop == 200);
332   fail_unless (update == FALSE);
333   check_times (&segment, 200, 200, 0);
334
335   /* seek relative to end */
336   gst_segment_do_seek (&segment, 1.0,
337       GST_FORMAT_BYTES,
338       GST_SEEK_FLAG_NONE,
339       GST_SEEK_TYPE_END, -100, GST_SEEK_TYPE_END, -20, &update);
340   fail_unless (segment.start == 100);
341   fail_unless (segment.position == 100);
342   fail_unless (segment.stop == 180);
343   fail_unless (update == TRUE);
344   check_times (&segment, 150, 150, 50);
345
346   /* completely outside */
347   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 0, 50, &cstart, &cstop);
348   fail_unless (res == FALSE);
349
350   /* touching lower bound */
351   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, 100, &cstart, &cstop);
352   fail_unless (res == FALSE);
353
354   /* partially inside */
355   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, 150, &cstart, &cstop);
356   fail_unless (res == TRUE);
357   fail_unless (cstart == 100);
358   fail_unless (cstop == 150);
359
360   /* inside, touching lower bound */
361   res = gst_segment_clip (&segment, GST_FORMAT_BYTES,
362       100, 150, &cstart, &cstop);
363   fail_unless (res == TRUE);
364   fail_unless (cstart == 100);
365   fail_unless (cstop == 150);
366
367   /* completely inside */
368   res = gst_segment_clip (&segment, GST_FORMAT_BYTES,
369       150, 170, &cstart, &cstop);
370   fail_unless (res == TRUE);
371   fail_unless (cstart == 150);
372   fail_unless (cstop == 170);
373
374   /* partially inside */
375   res = gst_segment_clip (&segment, GST_FORMAT_BYTES,
376       150, 250, &cstart, &cstop);
377   fail_unless (res == TRUE);
378   fail_unless (cstart == 150);
379   fail_unless (cstop == 180);
380
381   /* invalid start */
382   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, -1, 100, &cstart, &cstop);
383   fail_unless (res == FALSE);
384
385   /* start outside */
386   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, -1, &cstart, &cstop);
387   fail_unless (res == TRUE);
388   fail_unless (cstart == 100);
389   fail_unless (cstop == 180);
390
391   /* start on lower bound */
392   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 100, -1, &cstart, &cstop);
393   fail_unless (res == TRUE);
394   fail_unless (cstart == 100);
395   fail_unless (cstop == 180);
396
397   /* start inside */
398   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 150, -1, &cstart, &cstop);
399   fail_unless (res == TRUE);
400   fail_unless (cstart == 150);
401   fail_unless (cstop == 180);
402
403   /* start outside on boundary */
404   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 180, -1, &cstart, &cstop);
405   fail_unless (res == FALSE);
406
407   /* start completely outside */
408   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 250, -1, &cstart, &cstop);
409   fail_unless (res == FALSE);
410 }
411
412 GST_END_TEST;
413
414 GST_START_TEST (segment_seek_reverse)
415 {
416   GstSegment segment;
417   gboolean update;
418
419   gst_segment_init (&segment, GST_FORMAT_BYTES);
420   segment.duration = 200;
421
422   /* configure segment to stop 100 */
423   gst_segment_do_seek (&segment, -1.0,
424       GST_FORMAT_BYTES,
425       GST_SEEK_FLAG_NONE,
426       GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_SET, 100, &update);
427   fail_unless (segment.start == 0);
428   fail_unless (segment.stop == 100);
429   fail_unless (segment.time == 0);
430   fail_unless (segment.position == 100);
431   fail_unless (update == TRUE);
432   check_times (&segment, 100, 100, 0);
433   check_times (&segment, 50, 50, 50);
434   check_times (&segment, 0, 0, 100);
435
436   /* update */
437   gst_segment_do_seek (&segment, -1.0,
438       GST_FORMAT_BYTES,
439       GST_SEEK_FLAG_NONE,
440       GST_SEEK_TYPE_SET, 10, GST_SEEK_TYPE_SET, 100 - 20, &update);
441   fail_unless (segment.start == 10);
442   fail_unless (segment.stop == 80);
443   fail_unless (segment.time == 10);
444   fail_unless (segment.position == 80);
445   fail_unless (update == TRUE);
446   check_times (&segment, 80, 80, 0);
447   check_times (&segment, 40, 40, 40);
448   check_times (&segment, 10, 10, 70);
449
450   gst_segment_do_seek (&segment, -1.0,
451       GST_FORMAT_BYTES,
452       GST_SEEK_FLAG_NONE,
453       GST_SEEK_TYPE_SET, 20, GST_SEEK_TYPE_NONE, 0, &update);
454   fail_unless (segment.start == 20);
455   fail_unless (segment.stop == 80);
456   fail_unless (segment.time == 20);
457   fail_unless (segment.position == 80);
458   fail_unless (update == FALSE);
459   check_times (&segment, 80, 80, 0);
460   check_times (&segment, 20, 20, 60);
461 }
462
463 GST_END_TEST;
464
465 /* mess with the segment structure in the bytes format */
466 GST_START_TEST (segment_seek_rate)
467 {
468   GstSegment segment;
469   gboolean update;
470
471   gst_segment_init (&segment, GST_FORMAT_BYTES);
472
473   /* configure segment to rate 2.0 */
474   gst_segment_do_seek (&segment, 2.0,
475       GST_FORMAT_BYTES,
476       GST_SEEK_FLAG_NONE,
477       GST_SEEK_TYPE_NONE, -1, GST_SEEK_TYPE_NONE, -1, &update);
478   fail_unless (segment.format == GST_FORMAT_BYTES);
479   fail_unless (segment.start == 0);
480   fail_unless (segment.stop == -1);
481   fail_unless (segment.rate == 2.0);
482   fail_unless (update == FALSE);
483
484   /* set a real stop position, this must happen in bytes */
485   gst_segment_do_seek (&segment, 3.0,
486       GST_FORMAT_BYTES,
487       GST_SEEK_FLAG_NONE,
488       GST_SEEK_TYPE_NONE, -1, GST_SEEK_TYPE_SET, 100, &update);
489   fail_unless (segment.format == GST_FORMAT_BYTES);
490   fail_unless (segment.start == 0);
491   fail_unless (segment.stop == 100);
492   fail_unless (segment.rate == 3.0);
493   /* no seek should happen, we just updated the stop position in forward
494    * playback mode.*/
495   fail_unless (update == FALSE);
496
497   /* set some duration, stop -1 END seeks will now work with the
498    * duration, if the formats match */
499   segment.duration = 200;
500   fail_unless (segment.duration == 200);
501
502   /* seek to end with 0 should set the stop to the duration */
503   gst_segment_do_seek (&segment, 2.0,
504       GST_FORMAT_BYTES, GST_SEEK_FLAG_NONE,
505       GST_SEEK_TYPE_NONE, -1, GST_SEEK_TYPE_END, 0, &update);
506   fail_unless (segment.stop == 200);
507   fail_unless (segment.duration == 200);
508
509   /* subtract 100 from the end */
510   gst_segment_do_seek (&segment, 2.0,
511       GST_FORMAT_BYTES, GST_SEEK_FLAG_NONE,
512       GST_SEEK_TYPE_NONE, -1, GST_SEEK_TYPE_END, -100, &update);
513   fail_unless (segment.stop == 100);
514   fail_unless (segment.duration == 200);
515
516   /* add 100 to the duration, this should be clamped to the duration */
517   gst_segment_do_seek (&segment, 2.0,
518       GST_FORMAT_BYTES, GST_SEEK_FLAG_NONE,
519       GST_SEEK_TYPE_NONE, -1, GST_SEEK_TYPE_END, 100, &update);
520   fail_unless (segment.stop == 200);
521   fail_unless (segment.duration == 200);
522 }
523
524 GST_END_TEST;
525
526 GST_START_TEST (segment_copy)
527 {
528   GstSegment *copy;
529   GstSegment segment = { 0.0, };
530
531   /* this is a boxed type copy function, we support copying NULL */
532   fail_unless (gst_segment_copy (NULL) == NULL);
533
534   gst_segment_init (&segment, GST_FORMAT_TIME);
535
536   segment.rate = -1.0;
537   segment.applied_rate = 1.0;
538   segment.start = 0;
539   segment.stop = 200;
540   segment.time = 0;
541
542   copy = gst_segment_copy (&segment);
543   fail_unless (copy != NULL);
544   /* we inited the struct on the stack to zeroes, so direct comparison should
545    * be ok here despite the padding field and regardless of implementation */
546   fail_unless (memcmp (copy, &segment, sizeof (GstSegment)) == 0);
547   gst_segment_free (copy);
548 }
549
550 GST_END_TEST;
551
552 static Suite *
553 gst_segment_suite (void)
554 {
555   Suite *s = suite_create ("GstSegment");
556   TCase *tc_chain = tcase_create ("segments");
557
558   tcase_set_timeout (tc_chain, 20);
559
560   suite_add_tcase (s, tc_chain);
561   tcase_add_test (tc_chain, segment_seek_nosize);
562   tcase_add_test (tc_chain, segment_seek_size);
563   tcase_add_test (tc_chain, segment_seek_reverse);
564   tcase_add_test (tc_chain, segment_seek_rate);
565   tcase_add_test (tc_chain, segment_copy);
566
567   return s;
568 }
569
570 GST_CHECK_MAIN (gst_segment);