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