segment: update the 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., 51 Franklin St, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  */
22
23 #include <gst/check/gstcheck.h>
24
25 #define check_times(segment, position, stream_time, running_time) G_STMT_START { \
26   guint64 st, rt, pos; \
27   \
28   st = gst_segment_to_stream_time ((segment), (segment)->format, (position)); \
29   rt = gst_segment_to_running_time ((segment), (segment)->format, (position)); \
30   GST_DEBUG ("position %" G_GUINT64_FORMAT ", st %" G_GUINT64_FORMAT ", rt %" \
31       G_GUINT64_FORMAT, (guint64) (position), (guint64) (stream_time), (guint64) (running_time)); \
32   \
33   fail_unless_equals_int64 (st, (stream_time)); \
34   fail_unless_equals_int64 (rt, (running_time)); \
35   if ((stream_time) != -1) { \
36     pos = gst_segment_position_from_stream_time ((segment), (segment)->format, st); \
37     fail_unless_equals_int64 (pos, (position)); \
38   } \
39   \
40   if ((running_time) != -1) { \
41     pos = gst_segment_position_from_running_time ((segment), (segment)->format, rt); \
42     fail_unless_equals_int64 (pos, (position)); \
43   } \
44 } G_STMT_END;
45
46 /* mess with the segment structure in the bytes format */
47 GST_START_TEST (segment_seek_nosize)
48 {
49   GstSegment segment;
50   gboolean res;
51   guint64 cstart, cstop;
52   gboolean update;
53
54   gst_segment_init (&segment, GST_FORMAT_BYTES);
55
56   /* configure segment to start 100 */
57   gst_segment_do_seek (&segment, 1.0,
58       GST_FORMAT_BYTES,
59       GST_SEEK_FLAG_NONE,
60       GST_SEEK_TYPE_SET, 100, GST_SEEK_TYPE_NONE, -1, &update);
61   fail_unless_equals_uint64 (segment.start, 100);
62   fail_unless_equals_uint64 (segment.position, 100);
63   fail_unless_equals_uint64 (segment.stop, -1);
64   fail_unless (update == TRUE);
65   /* appended after current position 0 */
66   check_times (&segment, 100, 100, 0);
67
68   /* do some clipping on the open range */
69   /* completely outside */
70   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 0, 50, &cstart, &cstop);
71   fail_unless (res == FALSE);
72
73   /* touching lower bound, still outside of the segment */
74   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, 100, &cstart, &cstop);
75   fail_unless (res == FALSE);
76
77   /* partially inside */
78   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, 150, &cstart, &cstop);
79   fail_unless (res == TRUE);
80   fail_unless_equals_uint64 (cstart, 100);
81   fail_unless_equals_uint64 (cstop, 150);
82
83   /* inside, touching lower bound */
84   res = gst_segment_clip (&segment, GST_FORMAT_BYTES,
85       100, 150, &cstart, &cstop);
86   fail_unless (res == TRUE);
87   fail_unless_equals_uint64 (cstart, 100);
88   fail_unless_equals_uint64 (cstop, 150);
89
90   /* special case, 0 duration and outside segment */
91   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 90, 90, &cstart, &cstop);
92   fail_unless (res == FALSE);
93
94   /* special case, 0 duration and touching lower bound, i.e. inside segment */
95   res = gst_segment_clip (&segment, GST_FORMAT_BYTES,
96       100, 100, &cstart, &cstop);
97   fail_unless (res == TRUE);
98   fail_unless_equals_uint64 (cstart, 100);
99   fail_unless_equals_uint64 (cstop, 100);
100
101   /* special case, 0 duration and inside the segment */
102   res = gst_segment_clip (&segment, GST_FORMAT_BYTES,
103       120, 120, &cstart, &cstop);
104   fail_unless (res == TRUE);
105   fail_unless_equals_uint64 (cstart, 120);
106   fail_unless_equals_uint64 (cstop, 120);
107
108   /* completely inside */
109   res = gst_segment_clip (&segment, GST_FORMAT_BYTES,
110       150, 200, &cstart, &cstop);
111   fail_unless (res == TRUE);
112   fail_unless_equals_uint64 (cstart, 150);
113   fail_unless_equals_uint64 (cstop, 200);
114
115   /* invalid start */
116   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, -1, 100, &cstart, &cstop);
117   fail_unless (res == FALSE);
118
119   /* start outside, we don't know the stop */
120   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, -1, &cstart, &cstop);
121   fail_unless (res == TRUE);
122   fail_unless_equals_uint64 (cstart, 100);
123   fail_unless_equals_int64 (cstop, -1);
124
125   /* start on lower bound */
126   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 100, -1, &cstart, &cstop);
127   fail_unless (res == TRUE);
128   fail_unless_equals_uint64 (cstart, 100);
129   fail_unless_equals_int64 (cstop, -1);
130
131   /* start inside */
132   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 150, -1, &cstart, &cstop);
133   fail_unless (res == TRUE);
134   fail_unless_equals_uint64 (cstart, 150);
135   fail_unless_equals_int64 (cstop, -1);
136
137   /* move to 150, this is a running_time of 50 */
138   segment.position = 150;
139   check_times (&segment, 150, 150, 50);
140
141   /* add 100 to start, set stop to 300 */
142   gst_segment_do_seek (&segment, 1.0,
143       GST_FORMAT_BYTES,
144       GST_SEEK_FLAG_NONE,
145       GST_SEEK_TYPE_SET, 100 + 100, GST_SEEK_TYPE_SET, 300, &update);
146   fail_unless_equals_uint64 (segment.start, 200);
147   fail_unless_equals_uint64 (segment.position, 200);
148   fail_unless_equals_uint64 (segment.stop, 300);
149   fail_unless_equals_uint64 (segment.base, 50);
150   fail_unless (update == TRUE);
151   check_times (&segment, 200, 200, 50);
152   check_times (&segment, 250, 250, 100);
153
154   update = FALSE;
155   /* add 100 to start (to 300), set stop to 200, this is not allowed.
156    * nothing should be updated in the segment. A g_warning is
157    * emitted. */
158   ASSERT_CRITICAL (gst_segment_do_seek (&segment, 1.0,
159           GST_FORMAT_BYTES,
160           GST_SEEK_FLAG_NONE,
161           GST_SEEK_TYPE_SET, 200 + 100, GST_SEEK_TYPE_SET, 200, &update));
162   fail_unless_equals_uint64 (segment.start, 200);
163   fail_unless_equals_uint64 (segment.position, 200);
164   fail_unless_equals_uint64 (segment.stop, 300);
165   fail_unless_equals_uint64 (segment.base, 50);
166   /* update didn't change */
167   fail_unless (update == FALSE);
168   check_times (&segment, 200, 200, 50);
169   check_times (&segment, 250, 250, 100);
170
171   update = TRUE;
172   /* seek relative to end, should not do anything since size is
173    * unknown. */
174   gst_segment_do_seek (&segment, 1.0,
175       GST_FORMAT_BYTES,
176       GST_SEEK_FLAG_NONE,
177       GST_SEEK_TYPE_END, -300, GST_SEEK_TYPE_END, -100, &update);
178   fail_unless_equals_uint64 (segment.start, 200);
179   fail_unless_equals_uint64 (segment.position, 200);
180   fail_unless_equals_uint64 (segment.stop, 300);
181   fail_unless_equals_uint64 (segment.base, 50);
182   fail_unless (update == FALSE);
183   check_times (&segment, 250, 250, 100);
184
185   /* completely outside */
186   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 0, 50, &cstart, &cstop);
187   fail_unless (res == FALSE);
188
189   /* touching lower bound */
190   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, 200, &cstart, &cstop);
191   fail_unless (res == FALSE);
192
193   /* partially inside */
194   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, 250, &cstart, &cstop);
195   fail_unless (res == TRUE);
196   fail_unless_equals_uint64 (cstart, 200);
197   fail_unless_equals_uint64 (cstop, 250);
198
199   /* inside, touching lower bound */
200   res = gst_segment_clip (&segment, GST_FORMAT_BYTES,
201       200, 250, &cstart, &cstop);
202   fail_unless (res == TRUE);
203   fail_unless_equals_uint64 (cstart, 200);
204   fail_unless_equals_uint64 (cstop, 250);
205
206   /* completely inside */
207   res = gst_segment_clip (&segment, GST_FORMAT_BYTES,
208       250, 290, &cstart, &cstop);
209   fail_unless (res == TRUE);
210   fail_unless_equals_uint64 (cstart, 250);
211   fail_unless_equals_uint64 (cstop, 290);
212
213   /* partially inside */
214   res = gst_segment_clip (&segment, GST_FORMAT_BYTES,
215       250, 350, &cstart, &cstop);
216   fail_unless (res == TRUE);
217   fail_unless_equals_uint64 (cstart, 250);
218   fail_unless_equals_uint64 (cstop, 300);
219
220   /* invalid start */
221   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, -1, 100, &cstart, &cstop);
222   fail_unless (res == FALSE);
223
224   /* start outside */
225   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, -1, &cstart, &cstop);
226   fail_unless (res == TRUE);
227   fail_unless_equals_uint64 (cstart, 200);
228   fail_unless_equals_uint64 (cstop, 300);
229
230   /* start on lower bound */
231   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 200, -1, &cstart, &cstop);
232   fail_unless (res == TRUE);
233   fail_unless_equals_uint64 (cstart, 200);
234   fail_unless_equals_uint64 (cstop, 300);
235
236   /* start inside */
237   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 250, -1, &cstart, &cstop);
238   fail_unless (res == TRUE);
239   fail_unless_equals_uint64 (cstart, 250);
240   fail_unless_equals_uint64 (cstop, 300);
241
242   /* start outside on boundary */
243   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 300, -1, &cstart, &cstop);
244   fail_unless (res == FALSE);
245
246   /* start completely outside */
247   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 350, -1, &cstart, &cstop);
248   fail_unless (res == FALSE);
249 }
250
251 GST_END_TEST;
252
253 /* mess with the segment structure in the bytes format */
254 GST_START_TEST (segment_seek_size)
255 {
256   GstSegment segment;
257   gboolean res;
258   guint64 cstart, cstop;
259   gboolean update;
260
261   gst_segment_init (&segment, GST_FORMAT_BYTES);
262   segment.duration = 200;
263
264   /* configure segment to start 100 */
265   gst_segment_do_seek (&segment, 1.0,
266       GST_FORMAT_BYTES,
267       GST_SEEK_FLAG_NONE,
268       GST_SEEK_TYPE_SET, 100, GST_SEEK_TYPE_NONE, -1, &update);
269   fail_unless_equals_uint64 (segment.start, 100);
270   fail_unless_equals_uint64 (segment.position, 100);
271   fail_unless_equals_int64 (segment.stop, -1);
272   fail_unless (update == TRUE);
273   check_times (&segment, 100, 100, 0);
274
275   /* do some clipping on the open range */
276   /* completely outside */
277   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 0, 50, &cstart, &cstop);
278   fail_unless (res == FALSE);
279
280   /* touching lower bound */
281   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, 100, &cstart, &cstop);
282   fail_unless (res == FALSE);
283
284   /* partially inside */
285   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, 150, &cstart, &cstop);
286   fail_unless (res == TRUE);
287   fail_unless_equals_uint64 (cstart, 100);
288   fail_unless_equals_uint64 (cstop, 150);
289
290   /* inside, touching lower bound */
291   res = gst_segment_clip (&segment, GST_FORMAT_BYTES,
292       100, 150, &cstart, &cstop);
293   fail_unless (res == TRUE);
294   fail_unless_equals_uint64 (cstart, 100);
295   fail_unless_equals_uint64 (cstop, 150);
296
297   /* completely inside */
298   res = gst_segment_clip (&segment, GST_FORMAT_BYTES,
299       150, 200, &cstart, &cstop);
300   fail_unless (res == TRUE);
301   fail_unless_equals_uint64 (cstart, 150);
302   fail_unless_equals_uint64 (cstop, 200);
303
304   /* invalid start */
305   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, -1, 100, &cstart, &cstop);
306   fail_unless (res == FALSE);
307
308   /* start outside */
309   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, -1, &cstart, &cstop);
310   fail_unless (res == TRUE);
311   fail_unless_equals_uint64 (cstart, 100);
312   fail_unless_equals_int64 (cstop, -1);
313
314   /* start on lower bound */
315   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 100, -1, &cstart, &cstop);
316   fail_unless (res == TRUE);
317   fail_unless_equals_uint64 (cstart, 100);
318   fail_unless_equals_uint64 (cstop, -1);
319
320   /* start inside */
321   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 150, -1, &cstart, &cstop);
322   fail_unless (res == TRUE);
323   fail_unless_equals_uint64 (cstart, 150);
324   fail_unless_equals_uint64 (cstop, -1);
325
326   /* add 100 to start, set stop to 300, stop clips to 200 */
327   gst_segment_do_seek (&segment, 1.0,
328       GST_FORMAT_BYTES,
329       GST_SEEK_FLAG_NONE,
330       GST_SEEK_TYPE_SET, 100 + 100, GST_SEEK_TYPE_SET, 300, &update);
331   fail_unless_equals_uint64 (segment.start, 200);
332   fail_unless_equals_uint64 (segment.position, 200);
333   fail_unless_equals_uint64 (segment.stop, 200);
334   check_times (&segment, 200, 200, 0);
335
336   /* add 100 to start (to 300), set stop to 200, this clips start
337    * to duration */
338   gst_segment_do_seek (&segment, 1.0,
339       GST_FORMAT_BYTES,
340       GST_SEEK_FLAG_NONE,
341       GST_SEEK_TYPE_SET, 200 + 100, GST_SEEK_TYPE_SET, 200, &update);
342   fail_unless_equals_uint64 (segment.start, 200);
343   fail_unless_equals_uint64 (segment.position, 200);
344   fail_unless_equals_uint64 (segment.stop, 200);
345   fail_unless (update == FALSE);
346   check_times (&segment, 200, 200, 0);
347
348   /* special case, segment's start and stop are identical */
349   /* completely outside */
350   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, 100, &cstart, &cstop);
351   fail_unless (res == FALSE);
352
353   /* completely outside also */
354   res = gst_segment_clip (&segment, GST_FORMAT_BYTES,
355       250, 300, &cstart, &cstop);
356   fail_unless (res == FALSE);
357
358   /* stop at boundary point. it's outside because stop is exclusive */
359   res = gst_segment_clip (&segment, GST_FORMAT_BYTES,
360       100, 200, &cstart, &cstop);
361   fail_unless (res == FALSE);
362
363   /* touching boundary point. it's inside because start at segment start */
364   res = gst_segment_clip (&segment, GST_FORMAT_BYTES,
365       200, 300, &cstart, &cstop);
366   fail_unless (res == TRUE);
367   fail_unless_equals_uint64 (cstart, 200);
368   fail_unless_equals_uint64 (cstop, 200);
369
370   /* completely inside */
371   res = gst_segment_clip (&segment, GST_FORMAT_BYTES,
372       200, 200, &cstart, &cstop);
373   fail_unless (res == TRUE);
374   fail_unless_equals_uint64 (cstart, 200);
375   fail_unless_equals_uint64 (cstop, 200);
376
377   /* exclusively cover boundary point */
378   res = gst_segment_clip (&segment, GST_FORMAT_BYTES,
379       150, 250, &cstart, &cstop);
380   fail_unless (res == TRUE);
381   fail_unless_equals_uint64 (cstart, 200);
382   fail_unless_equals_uint64 (cstop, 200);
383
384   /* invalid start */
385   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, -1, 200, &cstart, &cstop);
386   fail_unless (res == FALSE);
387
388   /* start outside */
389   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, -1, &cstart, &cstop);
390   fail_unless (res == TRUE);
391   fail_unless_equals_uint64 (cstart, 200);
392   fail_unless_equals_uint64 (cstop, 200);
393
394   /* start on boundary point */
395   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 200, -1, &cstart, &cstop);
396   fail_unless (res == TRUE);
397   fail_unless_equals_uint64 (cstart, 200);
398   fail_unless_equals_uint64 (cstop, 200);
399
400   /* start completely outside */
401   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 250, -1, &cstart, &cstop);
402   fail_unless (res == FALSE);
403
404   /* seek relative to end */
405   gst_segment_do_seek (&segment, 1.0,
406       GST_FORMAT_BYTES,
407       GST_SEEK_FLAG_NONE,
408       GST_SEEK_TYPE_END, -100, GST_SEEK_TYPE_END, -20, &update);
409   fail_unless_equals_uint64 (segment.start, 100);
410   fail_unless_equals_uint64 (segment.position, 100);
411   fail_unless_equals_uint64 (segment.stop, 180);
412   fail_unless (update == TRUE);
413   check_times (&segment, 150, 150, 50);
414
415   /* completely outside */
416   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 0, 50, &cstart, &cstop);
417   fail_unless (res == FALSE);
418
419   /* touching lower bound */
420   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, 100, &cstart, &cstop);
421   fail_unless (res == FALSE);
422
423   /* partially inside */
424   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, 150, &cstart, &cstop);
425   fail_unless (res == TRUE);
426   fail_unless_equals_uint64 (cstart, 100);
427   fail_unless_equals_uint64 (cstop, 150);
428
429   /* inside, touching lower bound */
430   res = gst_segment_clip (&segment, GST_FORMAT_BYTES,
431       100, 150, &cstart, &cstop);
432   fail_unless (res == TRUE);
433   fail_unless_equals_uint64 (cstart, 100);
434   fail_unless_equals_uint64 (cstop, 150);
435
436   /* completely inside */
437   res = gst_segment_clip (&segment, GST_FORMAT_BYTES,
438       150, 170, &cstart, &cstop);
439   fail_unless (res == TRUE);
440   fail_unless_equals_uint64 (cstart, 150);
441   fail_unless_equals_uint64 (cstop, 170);
442
443   /* partially inside */
444   res = gst_segment_clip (&segment, GST_FORMAT_BYTES,
445       150, 250, &cstart, &cstop);
446   fail_unless (res == TRUE);
447   fail_unless_equals_uint64 (cstart, 150);
448   fail_unless_equals_uint64 (cstop, 180);
449
450   /* invalid start */
451   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, -1, 100, &cstart, &cstop);
452   fail_unless (res == FALSE);
453
454   /* start outside */
455   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, -1, &cstart, &cstop);
456   fail_unless (res == TRUE);
457   fail_unless_equals_uint64 (cstart, 100);
458   fail_unless_equals_uint64 (cstop, 180);
459
460   /* start on lower bound */
461   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 100, -1, &cstart, &cstop);
462   fail_unless (res == TRUE);
463   fail_unless_equals_uint64 (cstart, 100);
464   fail_unless_equals_uint64 (cstop, 180);
465
466   /* start inside */
467   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 150, -1, &cstart, &cstop);
468   fail_unless (res == TRUE);
469   fail_unless_equals_uint64 (cstart, 150);
470   fail_unless_equals_uint64 (cstop, 180);
471
472   /* start outside on boundary */
473   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 180, -1, &cstart, &cstop);
474   fail_unless (res == FALSE);
475
476   /* start completely outside */
477   res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 250, -1, &cstart, &cstop);
478   fail_unless (res == FALSE);
479 }
480
481 GST_END_TEST;
482
483 GST_START_TEST (segment_seek_reverse)
484 {
485   GstSegment segment;
486   gboolean update;
487
488   gst_segment_init (&segment, GST_FORMAT_BYTES);
489   segment.duration = 200;
490
491   /* configure segment to stop 100 */
492   gst_segment_do_seek (&segment, -1.0,
493       GST_FORMAT_BYTES,
494       GST_SEEK_FLAG_NONE,
495       GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_SET, 100, &update);
496   fail_unless_equals_uint64 (segment.start, 0);
497   fail_unless_equals_uint64 (segment.stop, 100);
498   fail_unless_equals_uint64 (segment.time, 0);
499   fail_unless_equals_uint64 (segment.position, 100);
500   fail_unless (update == TRUE);
501   check_times (&segment, 100, 100, 0);
502   check_times (&segment, 50, 50, 50);
503   check_times (&segment, 0, 0, 100);
504
505   /* update */
506   gst_segment_do_seek (&segment, -1.0,
507       GST_FORMAT_BYTES,
508       GST_SEEK_FLAG_NONE,
509       GST_SEEK_TYPE_SET, 10, GST_SEEK_TYPE_SET, 100 - 20, &update);
510   fail_unless_equals_uint64 (segment.start, 10);
511   fail_unless_equals_uint64 (segment.stop, 80);
512   fail_unless_equals_uint64 (segment.time, 10);
513   fail_unless_equals_uint64 (segment.position, 80);
514   fail_unless (update == TRUE);
515   check_times (&segment, 80, 80, 0);
516   check_times (&segment, 40, 40, 40);
517   check_times (&segment, 10, 10, 70);
518
519   gst_segment_do_seek (&segment, -1.0,
520       GST_FORMAT_BYTES,
521       GST_SEEK_FLAG_NONE,
522       GST_SEEK_TYPE_SET, 20, GST_SEEK_TYPE_NONE, 0, &update);
523   fail_unless_equals_uint64 (segment.start, 20);
524   fail_unless_equals_uint64 (segment.stop, 80);
525   fail_unless_equals_uint64 (segment.time, 20);
526   fail_unless_equals_uint64 (segment.position, 80);
527   fail_unless (update == FALSE);
528   check_times (&segment, 80, 80, 0);
529   check_times (&segment, 20, 20, 60);
530 }
531
532 GST_END_TEST;
533
534 /* mess with the segment structure in the bytes format */
535 GST_START_TEST (segment_seek_rate)
536 {
537   GstSegment segment;
538   gboolean update;
539
540   gst_segment_init (&segment, GST_FORMAT_BYTES);
541
542   /* configure segment to rate 2.0 */
543   gst_segment_do_seek (&segment, 2.0,
544       GST_FORMAT_BYTES,
545       GST_SEEK_FLAG_NONE,
546       GST_SEEK_TYPE_NONE, -1, GST_SEEK_TYPE_NONE, -1, &update);
547   fail_unless (segment.format == GST_FORMAT_BYTES);
548   fail_unless_equals_uint64 (segment.start, 0);
549   fail_unless_equals_uint64 (segment.position, 0);
550   fail_unless_equals_int64 (segment.stop, -1);
551   fail_unless_equals_float (segment.rate, 2.0);
552   fail_unless (update == FALSE);
553   check_times (&segment, 50, 50, 25);
554
555   /* set a real stop position, this must happen in bytes */
556   gst_segment_do_seek (&segment, 3.0,
557       GST_FORMAT_BYTES,
558       GST_SEEK_FLAG_NONE,
559       GST_SEEK_TYPE_NONE, -1, GST_SEEK_TYPE_SET, 100, &update);
560   fail_unless (segment.format == GST_FORMAT_BYTES);
561   fail_unless_equals_uint64 (segment.start, 0);
562   fail_unless_equals_uint64 (segment.stop, 100);
563   fail_unless_equals_float (segment.rate, 3.0);
564   /* no seek should happen, we just updated the stop position in forward
565    * playback mode.*/
566   fail_unless (update == FALSE);
567   check_times (&segment, 60, 60, 20);
568
569   /* set some duration, stop -1 END seeks will now work with the
570    * duration, if the formats match */
571   segment.duration = 200;
572
573   /* seek to end with 0 should set the stop to the duration */
574   gst_segment_do_seek (&segment, 2.0,
575       GST_FORMAT_BYTES, GST_SEEK_FLAG_NONE,
576       GST_SEEK_TYPE_NONE, -1, GST_SEEK_TYPE_END, 0, &update);
577   fail_unless_equals_uint64 (segment.stop, 200);
578   fail_unless_equals_uint64 (segment.duration, 200);
579
580   /* subtract 100 from the end */
581   gst_segment_do_seek (&segment, 2.0,
582       GST_FORMAT_BYTES, GST_SEEK_FLAG_NONE,
583       GST_SEEK_TYPE_NONE, -1, GST_SEEK_TYPE_END, -100, &update);
584   fail_unless_equals_uint64 (segment.stop, 100);
585   fail_unless_equals_uint64 (segment.duration, 200);
586
587   /* add 100 to the duration, this should be clamped to the duration */
588   gst_segment_do_seek (&segment, 2.0,
589       GST_FORMAT_BYTES, GST_SEEK_FLAG_NONE,
590       GST_SEEK_TYPE_NONE, -1, GST_SEEK_TYPE_END, 100, &update);
591   fail_unless_equals_uint64 (segment.stop, 200);
592   fail_unless_equals_uint64 (segment.duration, 200);
593 }
594
595 GST_END_TEST;
596
597 GST_START_TEST (segment_copy)
598 {
599   GstSegment *copy;
600   GstSegment segment = { 0.0, };
601
602   /* this is a boxed type copy function, we support copying NULL */
603   fail_unless (gst_segment_copy (NULL) == NULL);
604
605   gst_segment_init (&segment, GST_FORMAT_TIME);
606
607   segment.rate = -1.0;
608   segment.applied_rate = 1.0;
609   segment.start = 0;
610   segment.stop = 200;
611   segment.time = 0;
612
613   copy = gst_segment_copy (&segment);
614   fail_unless (copy != NULL);
615   /* we inited the struct on the stack to zeroes, so direct comparison should
616    * be ok here despite the padding field and regardless of implementation */
617   fail_unless (memcmp (copy, &segment, sizeof (GstSegment)) == 0);
618   gst_segment_free (copy);
619 }
620
621 GST_END_TEST;
622
623 /* mess with the segment structure in the bytes format */
624 GST_START_TEST (segment_seek_noupdate)
625 {
626   GstSegment segment;
627   gboolean update;
628
629   gst_segment_init (&segment, GST_FORMAT_TIME);
630
631   segment.start = 0;
632   segment.position = 50;
633   segment.stop = 200;
634   segment.time = 0;
635
636   /* doesn't change anything */
637   gst_segment_do_seek (&segment, 1.0,
638       GST_FORMAT_TIME,
639       GST_SEEK_FLAG_NONE,
640       GST_SEEK_TYPE_NONE, 0, GST_SEEK_TYPE_NONE, 0, &update);
641   fail_unless (update == FALSE);
642   fail_unless (segment.format == GST_FORMAT_TIME);
643   fail_unless_equals_uint64 (segment.start, 0);
644   fail_unless_equals_uint64 (segment.stop, 200);
645   fail_unless_equals_uint64 (segment.time, 0);
646   fail_unless_equals_uint64 (segment.position, 50);
647   fail_unless_equals_uint64 (segment.base, 50);
648   fail_unless_equals_uint64 (segment.offset, 50);
649
650   gst_segment_do_seek (&segment, 2.0,
651       GST_FORMAT_TIME,
652       GST_SEEK_FLAG_NONE,
653       GST_SEEK_TYPE_NONE, 0, GST_SEEK_TYPE_NONE, 0, &update);
654   fail_unless (update == FALSE);
655   fail_unless (segment.format == GST_FORMAT_TIME);
656   fail_unless_equals_uint64 (segment.start, 0);
657   fail_unless_equals_uint64 (segment.stop, 200);
658   fail_unless_equals_uint64 (segment.time, 0);
659   fail_unless_equals_uint64 (segment.position, 50);
660   fail_unless_equals_uint64 (segment.base, 50);
661   fail_unless_equals_uint64 (segment.offset, 50);
662
663   gst_segment_do_seek (&segment, 1.0,
664       GST_FORMAT_TIME,
665       GST_SEEK_FLAG_FLUSH,
666       GST_SEEK_TYPE_NONE, 0, GST_SEEK_TYPE_NONE, 0, &update);
667   fail_unless (update == FALSE);
668   fail_unless (segment.format == GST_FORMAT_TIME);
669   fail_unless_equals_uint64 (segment.start, 0);
670   fail_unless_equals_uint64 (segment.stop, 200);
671   fail_unless_equals_uint64 (segment.time, 0);
672   fail_unless_equals_uint64 (segment.position, 50);
673   fail_unless_equals_uint64 (segment.base, 0);
674   fail_unless_equals_uint64 (segment.offset, 50);
675 }
676
677 GST_END_TEST;
678
679 GST_START_TEST (segment_offset)
680 {
681   GstSegment segment;
682
683   gst_segment_init (&segment, GST_FORMAT_TIME);
684
685   segment.start = 0;
686   segment.position = 50;
687   segment.stop = 200;
688   segment.time = 0;
689
690   check_times (&segment, 20, 20, 20);
691   check_times (&segment, 220, -1, -1);
692
693   fail_unless (gst_segment_offset_running_time (&segment, GST_FORMAT_TIME,
694           0) == TRUE);
695   fail_unless_equals_uint64 (segment.start, 0);
696   fail_unless_equals_uint64 (segment.stop, 200);
697   fail_unless_equals_uint64 (segment.time, 0);
698   fail_unless_equals_uint64 (segment.position, 50);
699   fail_unless_equals_uint64 (segment.base, 0);
700   fail_unless_equals_uint64 (segment.offset, 0);
701   check_times (&segment, 20, 20, 20);
702
703   fail_unless (gst_segment_offset_running_time (&segment, GST_FORMAT_TIME,
704           100) == TRUE);
705   fail_unless_equals_uint64 (segment.start, 0);
706   fail_unless_equals_uint64 (segment.stop, 200);
707   fail_unless_equals_uint64 (segment.time, 0);
708   fail_unless_equals_uint64 (segment.position, 50);
709   fail_unless_equals_uint64 (segment.base, 100);
710   fail_unless_equals_uint64 (segment.offset, 0);
711   check_times (&segment, 20, 20, 120);
712
713   fail_unless (gst_segment_offset_running_time (&segment, GST_FORMAT_TIME,
714           -50) == TRUE);
715   fail_unless_equals_uint64 (segment.start, 0);
716   fail_unless_equals_uint64 (segment.stop, 200);
717   fail_unless_equals_uint64 (segment.time, 0);
718   fail_unless_equals_uint64 (segment.position, 50);
719   fail_unless_equals_uint64 (segment.base, 50);
720   fail_unless_equals_uint64 (segment.offset, 0);
721   check_times (&segment, 20, 20, 70);
722
723   fail_unless (gst_segment_offset_running_time (&segment, GST_FORMAT_TIME,
724           -100) == TRUE);
725   fail_unless_equals_uint64 (segment.start, 0);
726   fail_unless_equals_uint64 (segment.stop, 200);
727   fail_unless_equals_uint64 (segment.time, 0);
728   fail_unless_equals_uint64 (segment.position, 50);
729   fail_unless_equals_uint64 (segment.base, 0);
730   fail_unless_equals_uint64 (segment.offset, 50);
731   check_times (&segment, 20, 20, -1);
732   check_times (&segment, 200, 200, 150);
733
734   /* can go negative */
735   fail_unless (gst_segment_offset_running_time (&segment, GST_FORMAT_TIME,
736           -151) == FALSE);
737   fail_unless_equals_uint64 (segment.start, 0);
738   fail_unless_equals_uint64 (segment.stop, 200);
739   fail_unless_equals_uint64 (segment.time, 0);
740   fail_unless_equals_uint64 (segment.position, 50);
741   fail_unless_equals_uint64 (segment.base, 0);
742   fail_unless_equals_uint64 (segment.offset, 50);
743   check_times (&segment, 100, 100, 50);
744   check_times (&segment, 200, 200, 150);
745
746   fail_unless (gst_segment_offset_running_time (&segment, GST_FORMAT_TIME,
747           -150) == TRUE);
748   fail_unless_equals_uint64 (segment.start, 0);
749   fail_unless_equals_uint64 (segment.stop, 200);
750   fail_unless_equals_uint64 (segment.time, 0);
751   fail_unless_equals_uint64 (segment.position, 50);
752   fail_unless_equals_uint64 (segment.base, 0);
753   fail_unless_equals_uint64 (segment.offset, 200);
754   check_times (&segment, 200, 200, 0);
755
756   gst_segment_init (&segment, GST_FORMAT_TIME);
757
758   segment.start = 20;
759   segment.position = 50;
760   segment.stop = 220;
761   segment.time = 0;
762
763   check_times (&segment, 40, 20, 20);
764   check_times (&segment, 240, -1, -1);
765
766   fail_unless (gst_segment_offset_running_time (&segment, GST_FORMAT_TIME,
767           0) == TRUE);
768   fail_unless_equals_uint64 (segment.start, 20);
769   fail_unless_equals_uint64 (segment.stop, 220);
770   fail_unless_equals_uint64 (segment.time, 0);
771   fail_unless_equals_uint64 (segment.position, 50);
772   fail_unless_equals_uint64 (segment.base, 0);
773   fail_unless_equals_uint64 (segment.offset, 0);
774   check_times (&segment, 40, 20, 20);
775
776   fail_unless (gst_segment_offset_running_time (&segment, GST_FORMAT_TIME,
777           100) == TRUE);
778   fail_unless_equals_uint64 (segment.start, 20);
779   fail_unless_equals_uint64 (segment.stop, 220);
780   fail_unless_equals_uint64 (segment.time, 0);
781   fail_unless_equals_uint64 (segment.position, 50);
782   fail_unless_equals_uint64 (segment.base, 100);
783   fail_unless_equals_uint64 (segment.offset, 0);
784   check_times (&segment, 40, 20, 120);
785
786   fail_unless (gst_segment_offset_running_time (&segment, GST_FORMAT_TIME,
787           -50) == TRUE);
788   fail_unless_equals_uint64 (segment.start, 20);
789   fail_unless_equals_uint64 (segment.stop, 220);
790   fail_unless_equals_uint64 (segment.time, 0);
791   fail_unless_equals_uint64 (segment.position, 50);
792   fail_unless_equals_uint64 (segment.base, 50);
793   fail_unless_equals_uint64 (segment.offset, 0);
794   check_times (&segment, 40, 20, 70);
795
796   fail_unless (gst_segment_offset_running_time (&segment, GST_FORMAT_TIME,
797           -100) == TRUE);
798   fail_unless_equals_uint64 (segment.start, 20);
799   fail_unless_equals_uint64 (segment.stop, 220);
800   fail_unless_equals_uint64 (segment.time, 0);
801   fail_unless_equals_uint64 (segment.position, 50);
802   fail_unless_equals_uint64 (segment.base, 0);
803   fail_unless_equals_uint64 (segment.offset, 50);
804   check_times (&segment, 40, 20, -1);
805   check_times (&segment, 220, 200, 150);
806 }
807
808 GST_END_TEST;
809
810 GST_START_TEST (segment_full)
811 {
812   GstSegment segment;
813   guint64 rt, pos;
814
815   gst_segment_init (&segment, GST_FORMAT_TIME);
816
817   segment.start = 50;
818   segment.position = 150;
819   segment.stop = 200;
820   segment.time = 0;
821
822   check_times (&segment, 100, 50, 50);
823   check_times (&segment, 220, -1, -1);
824
825   fail_unless (gst_segment_to_running_time_full (&segment, GST_FORMAT_TIME,
826           50, &rt) == 1);
827   fail_unless (rt == 0);
828   fail_unless (gst_segment_position_from_running_time_full (&segment,
829           GST_FORMAT_TIME, rt, &pos) == 1);
830   fail_unless (pos == 50);
831   fail_unless (gst_segment_to_running_time_full (&segment, GST_FORMAT_TIME,
832           200, &rt) == 1);
833   fail_unless (rt == 150);
834   fail_unless (gst_segment_position_from_running_time_full (&segment,
835           GST_FORMAT_TIME, rt, &pos) == 1);
836   fail_unless (pos == 200);
837   fail_unless (!gst_segment_clip (&segment, GST_FORMAT_TIME, 40, 40, NULL,
838           NULL));
839   fail_unless (gst_segment_to_running_time_full (&segment, GST_FORMAT_TIME, 40,
840           &rt) == -1);
841   fail_unless (!gst_segment_clip (&segment, GST_FORMAT_TIME, 49, 49, NULL,
842           NULL));
843   fail_unless (gst_segment_to_running_time_full (&segment, GST_FORMAT_TIME, 49,
844           &rt) == -1);
845   fail_unless (!gst_segment_clip (&segment, GST_FORMAT_TIME, 201, 201, NULL,
846           NULL));
847   fail_unless (gst_segment_to_running_time_full (&segment, GST_FORMAT_TIME, 201,
848           &rt) == 1);
849   fail_unless (gst_segment_position_from_running_time_full (&segment,
850           GST_FORMAT_TIME, rt, &pos) == 1);
851   fail_unless (pos == 201);
852
853   fail_unless (gst_segment_offset_running_time (&segment, GST_FORMAT_TIME,
854           -50) == TRUE);
855   fail_unless (segment.offset == 50);
856
857   fail_unless (gst_segment_to_running_time_full (&segment, GST_FORMAT_TIME,
858           50, &rt) == -1);
859   GST_DEBUG ("%" G_GUINT64_FORMAT, rt);
860   fail_unless (rt == 50);
861
862   segment.start = 50;
863   segment.stop = 300;
864   segment.position = 150;
865   segment.time = 0;
866   segment.offset = 0;
867   gst_segment_set_running_time (&segment, GST_FORMAT_TIME, 100);
868   fail_unless_equals_int (segment.base, 100);
869   fail_unless (gst_segment_position_from_running_time_full (&segment,
870           GST_FORMAT_TIME, 70, &pos) == -1);
871   fail_unless (gst_segment_position_from_running_time_full (&segment,
872           GST_FORMAT_TIME, 140, &pos) == 1);
873   fail_unless_equals_int (pos, 190);
874 }
875
876 GST_END_TEST;
877
878 GST_START_TEST (segment_stream_time_full)
879 {
880   GstSegment segment;
881   guint64 st, pos;
882
883   gst_segment_init (&segment, GST_FORMAT_TIME);
884
885   segment.start = 50;
886   segment.stop = 200;
887   segment.time = 30;
888   segment.position = 0;
889
890   fail_unless (gst_segment_to_stream_time_full (&segment, GST_FORMAT_TIME,
891           0, &st) == -1);
892   fail_unless_equals_int (st, 20);
893   fail_unless (gst_segment_to_stream_time_full (&segment, GST_FORMAT_TIME,
894           20, &st) == 1);
895   fail_unless_equals_int (st, 0);
896   fail_unless (gst_segment_position_from_stream_time_full (&segment,
897           GST_FORMAT_TIME, 0, &pos) == 1);
898   fail_unless_equals_int (pos, 20);
899   fail_unless (gst_segment_to_stream_time_full (&segment, GST_FORMAT_TIME,
900           10, &st) == -1);
901   fail_unless_equals_int (st, 10);
902   fail_unless (gst_segment_to_stream_time_full (&segment, GST_FORMAT_TIME,
903           40, &st) == 1);
904   fail_unless_equals_int (st, 20);
905   fail_unless (gst_segment_position_from_stream_time_full (&segment,
906           GST_FORMAT_TIME, st, &pos) == 1);
907   fail_unless_equals_int (pos, 40);
908   segment.time = 100;
909   fail_unless (gst_segment_position_from_stream_time_full (&segment,
910           GST_FORMAT_TIME, 40, &pos) == -1);
911   fail_unless_equals_int (pos, 10);
912   fail_unless (gst_segment_position_from_stream_time_full (&segment,
913           GST_FORMAT_TIME, 60, &pos) == 1);
914   fail_unless_equals_int (pos, 10);
915
916   segment.start = 50;
917   segment.position = 150;
918   segment.stop = 200;
919   segment.time = 0;
920   segment.applied_rate = -1;
921   segment.rate = -1;
922
923   fail_unless (gst_segment_to_stream_time_full (&segment, GST_FORMAT_TIME,
924           0, &st) == 1);
925   fail_unless_equals_int (st, 200);
926   fail_unless (gst_segment_position_from_stream_time_full (&segment,
927           GST_FORMAT_TIME, 200, &pos) == 1);
928   fail_unless_equals_int (pos, 0);
929   fail_unless (gst_segment_to_stream_time_full (&segment, GST_FORMAT_TIME,
930           250, &st) == -1);
931   fail_unless_equals_int (st, 50);
932   fail_unless (gst_segment_position_from_stream_time_full (&segment,
933           GST_FORMAT_TIME, 200, &pos) == 1);
934   fail_unless_equals_int (pos, 0);
935   fail_unless (gst_segment_position_from_stream_time_full (&segment,
936           GST_FORMAT_TIME, 250, &pos) == -1);
937   fail_unless_equals_int (pos, 50);
938
939   segment.time = 70;
940   fail_unless (gst_segment_to_stream_time_full (&segment, GST_FORMAT_TIME,
941           250, &st) == 1);
942   fail_unless_equals_int (st, 20);
943   fail_unless (gst_segment_position_from_stream_time_full (&segment,
944           GST_FORMAT_TIME, 50, &pos) == 1);
945   fail_unless_equals_int (pos, 220);
946   fail_unless (gst_segment_position_from_stream_time_full (&segment,
947           GST_FORMAT_TIME, 90, &pos) == 1);
948   fail_unless_equals_int (pos, 180);
949
950   segment.stop = 60;
951   fail_unless (gst_segment_position_from_stream_time_full (&segment,
952           GST_FORMAT_TIME, 5, &pos) == 1);
953   fail_unless_equals_int (pos, 125);
954 }
955
956 GST_END_TEST;
957
958 GST_START_TEST (segment_negative_rate)
959 {
960   GstSegment segment;
961
962   gst_segment_init (&segment, GST_FORMAT_TIME);
963
964   segment.start = 50;
965   segment.position = 150;
966   segment.stop = 200;
967   segment.time = 0;
968   segment.applied_rate = -1;
969   segment.rate = -1;
970
971   /* somewhere in the middle */
972   check_times (&segment, 100, 100, 100);
973   /* after stop */
974   check_times (&segment, 220, -1, -1);
975   /* before start */
976   check_times (&segment, 10, -1, -1);
977   /* at segment start */
978   check_times (&segment, 50, 150, 150);
979   /* another place in the middle */
980   check_times (&segment, 150, 50, 50);
981   /* at segment stop */
982   check_times (&segment, 200, 0, 0);
983
984   segment.time = 100;
985   segment.base = 100;
986   /* somewhere in the middle */
987   check_times (&segment, 100, 200, 200);
988   /* at segment start */
989   check_times (&segment, 50, 250, 250);
990   /* another place in the middle */
991   check_times (&segment, 150, 150, 150);
992   /* at segment stop */
993   check_times (&segment, 200, 100, 100);
994 }
995
996 GST_END_TEST;
997
998 GST_START_TEST (segment_negative_applied_rate)
999 {
1000   GstSegment segment;
1001
1002   gst_segment_init (&segment, GST_FORMAT_TIME);
1003
1004   segment.start = 50;
1005   segment.position = 150;
1006   segment.stop = 200;
1007   segment.time = 0;
1008   segment.applied_rate = -1;
1009   segment.rate = 1;
1010
1011   /* somewhere in the middle */
1012   check_times (&segment, 100, 100, 50);
1013   /* after stop */
1014   check_times (&segment, 220, -1, -1);
1015   /* before start */
1016   check_times (&segment, 10, -1, -1);
1017   /* at segment start */
1018   check_times (&segment, 50, 150, 0);
1019   /* another place in the middle */
1020   check_times (&segment, 150, 50, 100);
1021   /* at segment stop */
1022   check_times (&segment, 200, 0, 150);
1023
1024   segment.time = 100;
1025   segment.base = 100;
1026   /* somewhere in the middle */
1027   check_times (&segment, 100, 200, 150);
1028   /* at segment start */
1029   check_times (&segment, 50, 250, 100);
1030   /* another place in the middle */
1031   check_times (&segment, 150, 150, 200);
1032   /* at segment stop */
1033   check_times (&segment, 200, 100, 250);
1034 }
1035
1036 GST_END_TEST;
1037
1038 static Suite *
1039 gst_segment_suite (void)
1040 {
1041   Suite *s = suite_create ("GstSegment");
1042   TCase *tc_chain = tcase_create ("segments");
1043
1044   tcase_set_timeout (tc_chain, 20);
1045
1046   suite_add_tcase (s, tc_chain);
1047   tcase_add_test (tc_chain, segment_seek_nosize);
1048   tcase_add_test (tc_chain, segment_seek_size);
1049   tcase_add_test (tc_chain, segment_seek_reverse);
1050   tcase_add_test (tc_chain, segment_seek_rate);
1051   tcase_add_test (tc_chain, segment_copy);
1052   tcase_add_test (tc_chain, segment_seek_noupdate);
1053   tcase_add_test (tc_chain, segment_offset);
1054   tcase_add_test (tc_chain, segment_full);
1055   tcase_add_test (tc_chain, segment_negative_rate);
1056   tcase_add_test (tc_chain, segment_negative_applied_rate);
1057   tcase_add_test (tc_chain, segment_stream_time_full);
1058
1059   return s;
1060 }
1061
1062 GST_CHECK_MAIN (gst_segment);