60a0d6f5168fcf3508f9570a5ae7c3fe340668a7
[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 (segment.start == 100);
62   fail_unless (segment.position == 100);
63   fail_unless (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 (cstart == 100);
81   fail_unless (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 (cstart == 100);
88   fail_unless (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 (cstart == 100);
99   fail_unless (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 (cstart == 120);
106   fail_unless (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 (cstart == 150);
113   fail_unless (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 (cstart == 100);
123   fail_unless (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 (cstart == 100);
129   fail_unless (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 (cstart == 150);
135   fail_unless (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 (segment.start == 200);
147   fail_unless (segment.position == 200);
148   fail_unless (segment.stop == 300);
149   fail_unless (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 (segment.start == 200);
163   fail_unless (segment.position == 200);
164   fail_unless (segment.stop == 300);
165   fail_unless (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 (segment.start == 200);
179   fail_unless (segment.position == 200);
180   fail_unless (segment.stop == 300);
181   fail_unless (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 (cstart == 200);
197   fail_unless (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 (cstart == 200);
204   fail_unless (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 (cstart == 250);
211   fail_unless (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 (cstart == 250);
218   fail_unless (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 (cstart == 200);
228   fail_unless (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 (cstart == 200);
234   fail_unless (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 (cstart == 250);
240   fail_unless (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 (segment.start == 100);
270   fail_unless (segment.position == 100);
271   fail_unless (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 (cstart == 100);
288   fail_unless (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 (cstart == 100);
295   fail_unless (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 (cstart == 150);
302   fail_unless (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 (cstart == 100);
312   fail_unless (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 (cstart == 100);
318   fail_unless (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 (cstart == 150);
324   fail_unless (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 (segment.start == 200);
332   fail_unless (segment.position == 200);
333   fail_unless (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 (segment.start == 200);
343   fail_unless (segment.position == 200);
344   fail_unless (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 (cstart == 200);
368   fail_unless (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 (cstart == 200);
375   fail_unless (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 (cstart == 200);
382   fail_unless (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 (cstart == 200);
392   fail_unless (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 (cstart == 200);
398   fail_unless (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 (segment.start == 100);
410   fail_unless (segment.position == 100);
411   fail_unless (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 (cstart == 100);
427   fail_unless (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 (cstart == 100);
434   fail_unless (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 (cstart == 150);
441   fail_unless (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 (cstart == 150);
448   fail_unless (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 (cstart == 100);
458   fail_unless (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 (cstart == 100);
464   fail_unless (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 (cstart == 150);
470   fail_unless (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 (segment.start == 0);
497   fail_unless (segment.stop == 100);
498   fail_unless (segment.time == 0);
499   fail_unless (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 (segment.start == 10);
511   fail_unless (segment.stop == 80);
512   fail_unless (segment.time == 10);
513   fail_unless (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 (segment.start == 20);
524   fail_unless (segment.stop == 80);
525   fail_unless (segment.time == 20);
526   fail_unless (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 (segment.start == 0);
549   fail_unless (segment.position == 0);
550   fail_unless (segment.stop == -1);
551   fail_unless (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 (segment.start == 0);
562   fail_unless (segment.stop == 100);
563   fail_unless (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   fail_unless (segment.duration == 200);
573
574   /* seek to end with 0 should set the stop to the duration */
575   gst_segment_do_seek (&segment, 2.0,
576       GST_FORMAT_BYTES, GST_SEEK_FLAG_NONE,
577       GST_SEEK_TYPE_NONE, -1, GST_SEEK_TYPE_END, 0, &update);
578   fail_unless (segment.stop == 200);
579   fail_unless (segment.duration == 200);
580
581   /* subtract 100 from the end */
582   gst_segment_do_seek (&segment, 2.0,
583       GST_FORMAT_BYTES, GST_SEEK_FLAG_NONE,
584       GST_SEEK_TYPE_NONE, -1, GST_SEEK_TYPE_END, -100, &update);
585   fail_unless (segment.stop == 100);
586   fail_unless (segment.duration == 200);
587
588   /* add 100 to the duration, this should be clamped to the duration */
589   gst_segment_do_seek (&segment, 2.0,
590       GST_FORMAT_BYTES, GST_SEEK_FLAG_NONE,
591       GST_SEEK_TYPE_NONE, -1, GST_SEEK_TYPE_END, 100, &update);
592   fail_unless (segment.stop == 200);
593   fail_unless (segment.duration == 200);
594 }
595
596 GST_END_TEST;
597
598 GST_START_TEST (segment_copy)
599 {
600   GstSegment *copy;
601   GstSegment segment = { 0.0, };
602
603   /* this is a boxed type copy function, we support copying NULL */
604   fail_unless (gst_segment_copy (NULL) == NULL);
605
606   gst_segment_init (&segment, GST_FORMAT_TIME);
607
608   segment.rate = -1.0;
609   segment.applied_rate = 1.0;
610   segment.start = 0;
611   segment.stop = 200;
612   segment.time = 0;
613
614   copy = gst_segment_copy (&segment);
615   fail_unless (copy != NULL);
616   /* we inited the struct on the stack to zeroes, so direct comparison should
617    * be ok here despite the padding field and regardless of implementation */
618   fail_unless (memcmp (copy, &segment, sizeof (GstSegment)) == 0);
619   gst_segment_free (copy);
620 }
621
622 GST_END_TEST;
623
624 /* mess with the segment structure in the bytes format */
625 GST_START_TEST (segment_seek_noupdate)
626 {
627   GstSegment segment;
628   gboolean update;
629
630   gst_segment_init (&segment, GST_FORMAT_TIME);
631
632   segment.start = 0;
633   segment.position = 50;
634   segment.stop = 200;
635   segment.time = 0;
636
637   /* doesn't change anything */
638   gst_segment_do_seek (&segment, 1.0,
639       GST_FORMAT_TIME,
640       GST_SEEK_FLAG_NONE,
641       GST_SEEK_TYPE_NONE, 0, GST_SEEK_TYPE_NONE, 0, &update);
642   fail_unless (update == FALSE);
643   fail_unless (segment.format == GST_FORMAT_TIME);
644   fail_unless (segment.start == 0);
645   fail_unless (segment.stop == 200);
646   fail_unless (segment.time == 0);
647   fail_unless (segment.position == 50);
648   fail_unless (segment.base == 50);
649   fail_unless (segment.offset == 50);
650
651   gst_segment_do_seek (&segment, 2.0,
652       GST_FORMAT_TIME,
653       GST_SEEK_FLAG_NONE,
654       GST_SEEK_TYPE_NONE, 0, GST_SEEK_TYPE_NONE, 0, &update);
655   fail_unless (update == FALSE);
656   fail_unless (segment.format == GST_FORMAT_TIME);
657   fail_unless (segment.start == 0);
658   fail_unless (segment.stop == 200);
659   fail_unless (segment.time == 0);
660   fail_unless (segment.position == 50);
661   fail_unless (segment.base == 50);
662   fail_unless_equals_int (segment.offset, 50);
663
664   gst_segment_do_seek (&segment, 1.0,
665       GST_FORMAT_TIME,
666       GST_SEEK_FLAG_FLUSH,
667       GST_SEEK_TYPE_NONE, 0, GST_SEEK_TYPE_NONE, 0, &update);
668   fail_unless (update == FALSE);
669   fail_unless (segment.format == GST_FORMAT_TIME);
670   fail_unless (segment.start == 0);
671   fail_unless (segment.stop == 200);
672   fail_unless (segment.time == 0);
673   fail_unless (segment.position == 50);
674   fail_unless (segment.base == 0);
675   fail_unless (segment.offset == 50);
676 }
677
678 GST_END_TEST;
679
680 GST_START_TEST (segment_offset)
681 {
682   GstSegment segment;
683
684   gst_segment_init (&segment, GST_FORMAT_TIME);
685
686   segment.start = 0;
687   segment.position = 50;
688   segment.stop = 200;
689   segment.time = 0;
690
691   check_times (&segment, 20, 20, 20);
692   check_times (&segment, 220, -1, -1);
693
694   fail_unless (gst_segment_offset_running_time (&segment, GST_FORMAT_TIME,
695           0) == TRUE);
696   fail_unless (segment.start == 0);
697   fail_unless (segment.stop == 200);
698   fail_unless (segment.time == 0);
699   fail_unless (segment.position == 50);
700   fail_unless (segment.base == 0);
701   fail_unless (segment.offset == 0);
702   check_times (&segment, 20, 20, 20);
703
704   fail_unless (gst_segment_offset_running_time (&segment, GST_FORMAT_TIME,
705           100) == TRUE);
706   fail_unless (segment.start == 0);
707   fail_unless (segment.stop == 200);
708   fail_unless (segment.time == 0);
709   fail_unless (segment.position == 50);
710   fail_unless (segment.base == 100);
711   fail_unless (segment.offset == 0);
712   check_times (&segment, 20, 20, 120);
713
714   fail_unless (gst_segment_offset_running_time (&segment, GST_FORMAT_TIME,
715           -50) == TRUE);
716   fail_unless (segment.start == 0);
717   fail_unless (segment.stop == 200);
718   fail_unless (segment.time == 0);
719   fail_unless (segment.position == 50);
720   fail_unless (segment.base == 50);
721   fail_unless (segment.offset == 0);
722   check_times (&segment, 20, 20, 70);
723
724   fail_unless (gst_segment_offset_running_time (&segment, GST_FORMAT_TIME,
725           -100) == TRUE);
726   fail_unless (segment.start == 0);
727   fail_unless (segment.stop == 200);
728   fail_unless (segment.time == 0);
729   fail_unless (segment.position == 50);
730   fail_unless (segment.base == 0);
731   fail_unless (segment.offset == 50);
732   check_times (&segment, 20, 20, -1);
733   check_times (&segment, 200, 200, 150);
734
735   /* can go negative */
736   fail_unless (gst_segment_offset_running_time (&segment, GST_FORMAT_TIME,
737           -151) == FALSE);
738   fail_unless (segment.start == 0);
739   fail_unless (segment.stop == 200);
740   fail_unless (segment.time == 0);
741   fail_unless (segment.position == 50);
742   fail_unless (segment.base == 0);
743   fail_unless (segment.offset == 50);
744   check_times (&segment, 100, 100, 50);
745   check_times (&segment, 200, 200, 150);
746
747   fail_unless (gst_segment_offset_running_time (&segment, GST_FORMAT_TIME,
748           -150) == TRUE);
749   fail_unless (segment.start == 0);
750   fail_unless (segment.stop == 200);
751   fail_unless (segment.time == 0);
752   fail_unless (segment.position == 50);
753   fail_unless (segment.base == 0);
754   fail_unless (segment.offset == 200);
755   check_times (&segment, 200, 200, 0);
756
757   gst_segment_init (&segment, GST_FORMAT_TIME);
758
759   segment.start = 20;
760   segment.position = 50;
761   segment.stop = 220;
762   segment.time = 0;
763
764   check_times (&segment, 40, 20, 20);
765   check_times (&segment, 240, -1, -1);
766
767   fail_unless (gst_segment_offset_running_time (&segment, GST_FORMAT_TIME,
768           0) == TRUE);
769   fail_unless (segment.start == 20);
770   fail_unless (segment.stop == 220);
771   fail_unless (segment.time == 0);
772   fail_unless (segment.position == 50);
773   fail_unless (segment.base == 0);
774   fail_unless (segment.offset == 0);
775   check_times (&segment, 40, 20, 20);
776
777   fail_unless (gst_segment_offset_running_time (&segment, GST_FORMAT_TIME,
778           100) == TRUE);
779   fail_unless (segment.start == 20);
780   fail_unless (segment.stop == 220);
781   fail_unless (segment.time == 0);
782   fail_unless (segment.position == 50);
783   fail_unless (segment.base == 100);
784   fail_unless (segment.offset == 0);
785   check_times (&segment, 40, 20, 120);
786
787   fail_unless (gst_segment_offset_running_time (&segment, GST_FORMAT_TIME,
788           -50) == TRUE);
789   fail_unless (segment.start == 20);
790   fail_unless (segment.stop == 220);
791   fail_unless (segment.time == 0);
792   fail_unless (segment.position == 50);
793   fail_unless (segment.base == 50);
794   fail_unless (segment.offset == 0);
795   check_times (&segment, 40, 20, 70);
796
797   fail_unless (gst_segment_offset_running_time (&segment, GST_FORMAT_TIME,
798           -100) == TRUE);
799   fail_unless (segment.start == 20);
800   fail_unless (segment.stop == 220);
801   fail_unless (segment.time == 0);
802   fail_unless (segment.position == 50);
803   fail_unless (segment.base == 0);
804   fail_unless (segment.offset == 50);
805   check_times (&segment, 40, 20, -1);
806   check_times (&segment, 220, 200, 150);
807 }
808
809 GST_END_TEST;
810
811 GST_START_TEST (segment_full)
812 {
813   GstSegment segment;
814   guint64 rt, pos;
815
816   gst_segment_init (&segment, GST_FORMAT_TIME);
817
818   segment.start = 50;
819   segment.position = 150;
820   segment.stop = 200;
821   segment.time = 0;
822
823   check_times (&segment, 100, 50, 50);
824   check_times (&segment, 220, -1, -1);
825
826   fail_unless (gst_segment_to_running_time_full (&segment, GST_FORMAT_TIME,
827           50, &rt) == 1);
828   fail_unless (rt == 0);
829   fail_unless (gst_segment_position_from_running_time_full (&segment,
830           GST_FORMAT_TIME, rt, &pos) == 1);
831   fail_unless (pos == 50);
832   fail_unless (gst_segment_to_running_time_full (&segment, GST_FORMAT_TIME,
833           200, &rt) == 1);
834   fail_unless (rt == 150);
835   fail_unless (gst_segment_position_from_running_time_full (&segment,
836           GST_FORMAT_TIME, rt, &pos) == 1);
837   fail_unless (pos == 200);
838   fail_unless (!gst_segment_clip (&segment, GST_FORMAT_TIME, 40, 40, NULL,
839           NULL));
840   fail_unless (gst_segment_to_running_time_full (&segment, GST_FORMAT_TIME, 40,
841           &rt) == -1);
842   fail_unless (!gst_segment_clip (&segment, GST_FORMAT_TIME, 49, 49, NULL,
843           NULL));
844   fail_unless (gst_segment_to_running_time_full (&segment, GST_FORMAT_TIME, 49,
845           &rt) == -1);
846   fail_unless (!gst_segment_clip (&segment, GST_FORMAT_TIME, 201, 201, NULL,
847           NULL));
848   fail_unless (gst_segment_to_running_time_full (&segment, GST_FORMAT_TIME, 201,
849           &rt) == 1);
850   fail_unless (gst_segment_position_from_running_time_full (&segment,
851           GST_FORMAT_TIME, rt, &pos) == 1);
852   fail_unless (pos == 201);
853
854   fail_unless (gst_segment_offset_running_time (&segment, GST_FORMAT_TIME,
855           -50) == TRUE);
856   fail_unless (segment.offset == 50);
857
858   fail_unless (gst_segment_to_running_time_full (&segment, GST_FORMAT_TIME,
859           50, &rt) == -1);
860   GST_DEBUG ("%" G_GUINT64_FORMAT, rt);
861   fail_unless (rt == 50);
862
863   segment.start = 50;
864   segment.stop = 300;
865   segment.position = 150;
866   segment.time = 0;
867   segment.offset = 0;
868   gst_segment_set_running_time (&segment, GST_FORMAT_TIME, 100);
869   fail_unless_equals_int (segment.base, 100);
870   fail_unless (gst_segment_position_from_running_time_full (&segment,
871           GST_FORMAT_TIME, 70, &pos) == -1);
872   fail_unless (gst_segment_position_from_running_time_full (&segment,
873           GST_FORMAT_TIME, 140, &pos) == 1);
874   fail_unless_equals_int (pos, 190);
875 }
876
877 GST_END_TEST;
878
879 GST_START_TEST (segment_stream_time_full)
880 {
881   GstSegment segment;
882   guint64 st, pos;
883
884   gst_segment_init (&segment, GST_FORMAT_TIME);
885
886   segment.start = 50;
887   segment.stop = 200;
888   segment.time = 30;
889   segment.position = 0;
890
891   fail_unless (gst_segment_to_stream_time_full (&segment, GST_FORMAT_TIME,
892           0, &st) == -1);
893   fail_unless_equals_int (st, 20);
894   fail_unless (gst_segment_to_stream_time_full (&segment, GST_FORMAT_TIME,
895           20, &st) == 1);
896   fail_unless_equals_int (st, 0);
897   fail_unless (gst_segment_position_from_stream_time_full (&segment,
898           GST_FORMAT_TIME, 0, &pos) == 1);
899   fail_unless_equals_int (pos, 20);
900   fail_unless (gst_segment_to_stream_time_full (&segment, GST_FORMAT_TIME,
901           10, &st) == -1);
902   fail_unless_equals_int (st, 10);
903   fail_unless (gst_segment_to_stream_time_full (&segment, GST_FORMAT_TIME,
904           40, &st) == 1);
905   fail_unless_equals_int (st, 20);
906   fail_unless (gst_segment_position_from_stream_time_full (&segment,
907           GST_FORMAT_TIME, st, &pos) == 1);
908   fail_unless_equals_int (pos, 40);
909   segment.time = 100;
910   fail_unless (gst_segment_position_from_stream_time_full (&segment,
911           GST_FORMAT_TIME, 40, &pos) == -1);
912   fail_unless_equals_int (pos, 10);
913   fail_unless (gst_segment_position_from_stream_time_full (&segment,
914           GST_FORMAT_TIME, 60, &pos) == 1);
915   fail_unless_equals_int (pos, 10);
916
917   segment.start = 50;
918   segment.position = 150;
919   segment.stop = 200;
920   segment.time = 0;
921   segment.applied_rate = -1;
922   segment.rate = -1;
923
924   fail_unless (gst_segment_to_stream_time_full (&segment, GST_FORMAT_TIME,
925           0, &st) == 1);
926   fail_unless_equals_int (st, 200);
927   fail_unless (gst_segment_position_from_stream_time_full (&segment,
928           GST_FORMAT_TIME, 200, &pos) == 1);
929   fail_unless_equals_int (pos, 0);
930   fail_unless (gst_segment_to_stream_time_full (&segment, GST_FORMAT_TIME,
931           250, &st) == -1);
932   fail_unless_equals_int (st, 50);
933   fail_unless (gst_segment_position_from_stream_time_full (&segment,
934           GST_FORMAT_TIME, 200, &pos) == 1);
935   fail_unless_equals_int (pos, 0);
936   fail_unless (gst_segment_position_from_stream_time_full (&segment,
937           GST_FORMAT_TIME, 250, &pos) == -1);
938   fail_unless_equals_int (pos, 50);
939
940   segment.time = 70;
941   fail_unless (gst_segment_to_stream_time_full (&segment, GST_FORMAT_TIME,
942           250, &st) == 1);
943   fail_unless_equals_int (st, 20);
944   fail_unless (gst_segment_position_from_stream_time_full (&segment,
945           GST_FORMAT_TIME, 50, &pos) == 1);
946   fail_unless_equals_int (pos, 220);
947   fail_unless (gst_segment_position_from_stream_time_full (&segment,
948           GST_FORMAT_TIME, 90, &pos) == 1);
949   fail_unless_equals_int (pos, 180);
950
951   segment.stop = 60;
952   fail_unless (gst_segment_position_from_stream_time_full (&segment,
953           GST_FORMAT_TIME, 5, &pos) == 1);
954   fail_unless_equals_int (pos, 125);
955 }
956
957 GST_END_TEST;
958
959 GST_START_TEST (segment_negative_rate)
960 {
961   GstSegment segment;
962
963   gst_segment_init (&segment, GST_FORMAT_TIME);
964
965   segment.start = 50;
966   segment.position = 150;
967   segment.stop = 200;
968   segment.time = 0;
969   segment.applied_rate = -1;
970   segment.rate = -1;
971
972   /* somewhere in the middle */
973   check_times (&segment, 100, 100, 100);
974   /* after stop */
975   check_times (&segment, 220, -1, -1);
976   /* before start */
977   check_times (&segment, 10, -1, -1);
978   /* at segment start */
979   check_times (&segment, 50, 150, 150);
980   /* another place in the middle */
981   check_times (&segment, 150, 50, 50);
982   /* at segment stop */
983   check_times (&segment, 200, 0, 0);
984
985   segment.time = 100;
986   segment.base = 100;
987   /* somewhere in the middle */
988   check_times (&segment, 100, 200, 200);
989   /* at segment start */
990   check_times (&segment, 50, 250, 250);
991   /* another place in the middle */
992   check_times (&segment, 150, 150, 150);
993   /* at segment stop */
994   check_times (&segment, 200, 100, 100);
995 }
996
997 GST_END_TEST;
998
999 GST_START_TEST (segment_negative_applied_rate)
1000 {
1001   GstSegment segment;
1002
1003   gst_segment_init (&segment, GST_FORMAT_TIME);
1004
1005   segment.start = 50;
1006   segment.position = 150;
1007   segment.stop = 200;
1008   segment.time = 0;
1009   segment.applied_rate = -1;
1010   segment.rate = 1;
1011
1012   /* somewhere in the middle */
1013   check_times (&segment, 100, 100, 50);
1014   /* after stop */
1015   check_times (&segment, 220, -1, -1);
1016   /* before start */
1017   check_times (&segment, 10, -1, -1);
1018   /* at segment start */
1019   check_times (&segment, 50, 150, 0);
1020   /* another place in the middle */
1021   check_times (&segment, 150, 50, 100);
1022   /* at segment stop */
1023   check_times (&segment, 200, 0, 150);
1024
1025   segment.time = 100;
1026   segment.base = 100;
1027   /* somewhere in the middle */
1028   check_times (&segment, 100, 200, 150);
1029   /* at segment start */
1030   check_times (&segment, 50, 250, 100);
1031   /* another place in the middle */
1032   check_times (&segment, 150, 150, 200);
1033   /* at segment stop */
1034   check_times (&segment, 200, 100, 250);
1035 }
1036
1037 GST_END_TEST;
1038
1039 static Suite *
1040 gst_segment_suite (void)
1041 {
1042   Suite *s = suite_create ("GstSegment");
1043   TCase *tc_chain = tcase_create ("segments");
1044
1045   tcase_set_timeout (tc_chain, 20);
1046
1047   suite_add_tcase (s, tc_chain);
1048   tcase_add_test (tc_chain, segment_seek_nosize);
1049   tcase_add_test (tc_chain, segment_seek_size);
1050   tcase_add_test (tc_chain, segment_seek_reverse);
1051   tcase_add_test (tc_chain, segment_seek_rate);
1052   tcase_add_test (tc_chain, segment_copy);
1053   tcase_add_test (tc_chain, segment_seek_noupdate);
1054   tcase_add_test (tc_chain, segment_offset);
1055   tcase_add_test (tc_chain, segment_full);
1056   tcase_add_test (tc_chain, segment_negative_rate);
1057   tcase_add_test (tc_chain, segment_negative_applied_rate);
1058   tcase_add_test (tc_chain, segment_stream_time_full);
1059
1060   return s;
1061 }
1062
1063 GST_CHECK_MAIN (gst_segment);