2 * Copyright (C) 2005 Jan Schmidt <thaytan@mad.scientist.com>
3 * 2009 Wim Taymans <wim.taymans@gmail.com>
5 * gstsegment.c: Unit test for segments
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.
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.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
23 #include <gst/check/gstcheck.h>
26 check_times (GstSegment * segment, guint64 position, guint64 stream_time,
31 st = gst_segment_to_stream_time (segment, segment->format, position);
32 rt = gst_segment_to_running_time (segment, segment->format, position);
34 fail_unless_equals_int64 (st, stream_time);
35 fail_unless_equals_int64 (rt, running_time);
38 /* mess with the segment structure in the bytes format */
39 GST_START_TEST (segment_seek_nosize)
43 guint64 cstart, cstop;
46 gst_segment_init (&segment, GST_FORMAT_BYTES);
48 /* configure segment to start 100 */
49 gst_segment_do_seek (&segment, 1.0,
52 GST_SEEK_TYPE_SET, 100, GST_SEEK_TYPE_NONE, -1, &update);
53 fail_unless (segment.start == 100);
54 fail_unless (segment.position == 100);
55 fail_unless (segment.stop == -1);
56 fail_unless (update == TRUE);
57 /* appended after current position 0 */
58 check_times (&segment, 100, 100, 0);
60 /* do some clipping on the open range */
61 /* completely outside */
62 res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 0, 50, &cstart, &cstop);
63 fail_unless (res == FALSE);
65 /* touching lower bound, still outside of the segment */
66 res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, 100, &cstart, &cstop);
67 fail_unless (res == FALSE);
69 /* partially inside */
70 res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, 150, &cstart, &cstop);
71 fail_unless (res == TRUE);
72 fail_unless (cstart == 100);
73 fail_unless (cstop == 150);
75 /* inside, touching lower bound */
76 res = gst_segment_clip (&segment, GST_FORMAT_BYTES,
77 100, 150, &cstart, &cstop);
78 fail_unless (res == TRUE);
79 fail_unless (cstart == 100);
80 fail_unless (cstop == 150);
82 /* special case, 0 duration and outside segment */
83 res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 90, 90, &cstart, &cstop);
84 fail_unless (res == FALSE);
86 /* special case, 0 duration and touching lower bound, i.e. inside segment */
87 res = gst_segment_clip (&segment, GST_FORMAT_BYTES,
88 100, 100, &cstart, &cstop);
89 fail_unless (res == TRUE);
90 fail_unless (cstart == 100);
91 fail_unless (cstop == 100);
93 /* special case, 0 duration and inside the segment */
94 res = gst_segment_clip (&segment, GST_FORMAT_BYTES,
95 120, 120, &cstart, &cstop);
96 fail_unless (res == TRUE);
97 fail_unless (cstart == 120);
98 fail_unless (cstop == 120);
100 /* completely inside */
101 res = gst_segment_clip (&segment, GST_FORMAT_BYTES,
102 150, 200, &cstart, &cstop);
103 fail_unless (res == TRUE);
104 fail_unless (cstart == 150);
105 fail_unless (cstop == 200);
108 res = gst_segment_clip (&segment, GST_FORMAT_BYTES, -1, 100, &cstart, &cstop);
109 fail_unless (res == FALSE);
111 /* start outside, we don't know the stop */
112 res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, -1, &cstart, &cstop);
113 fail_unless (res == TRUE);
114 fail_unless (cstart == 100);
115 fail_unless (cstop == -1);
117 /* start on lower bound */
118 res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 100, -1, &cstart, &cstop);
119 fail_unless (res == TRUE);
120 fail_unless (cstart == 100);
121 fail_unless (cstop == -1);
124 res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 150, -1, &cstart, &cstop);
125 fail_unless (res == TRUE);
126 fail_unless (cstart == 150);
127 fail_unless (cstop == -1);
129 /* move to 150, this is a running_time of 50 */
130 segment.position = 150;
131 check_times (&segment, 150, 150, 50);
133 /* add 100 to start, set stop to 300 */
134 gst_segment_do_seek (&segment, 1.0,
137 GST_SEEK_TYPE_SET, 100 + 100, GST_SEEK_TYPE_SET, 300, &update);
138 fail_unless (segment.start == 200);
139 fail_unless (segment.position == 200);
140 fail_unless (segment.stop == 300);
141 fail_unless (segment.base == 50);
142 fail_unless (update == TRUE);
143 check_times (&segment, 200, 200, 50);
144 check_times (&segment, 250, 250, 100);
147 /* add 100 to start (to 300), set stop to 200, this is not allowed.
148 * nothing should be updated in the segment. A g_warning is
150 ASSERT_CRITICAL (gst_segment_do_seek (&segment, 1.0,
153 GST_SEEK_TYPE_SET, 200 + 100, GST_SEEK_TYPE_SET, 200, &update));
154 fail_unless (segment.start == 200);
155 fail_unless (segment.position == 200);
156 fail_unless (segment.stop == 300);
157 fail_unless (segment.base == 50);
158 /* update didn't change */
159 fail_unless (update == FALSE);
160 check_times (&segment, 200, 200, 50);
161 check_times (&segment, 250, 250, 100);
164 /* seek relative to end, should not do anything since size is
166 gst_segment_do_seek (&segment, 1.0,
169 GST_SEEK_TYPE_END, -300, GST_SEEK_TYPE_END, -100, &update);
170 fail_unless (segment.start == 200);
171 fail_unless (segment.position == 200);
172 fail_unless (segment.stop == 300);
173 fail_unless (segment.base == 50);
174 fail_unless (update == FALSE);
175 check_times (&segment, 250, 250, 100);
177 /* completely outside */
178 res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 0, 50, &cstart, &cstop);
179 fail_unless (res == FALSE);
181 /* touching lower bound */
182 res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, 200, &cstart, &cstop);
183 fail_unless (res == FALSE);
185 /* partially inside */
186 res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, 250, &cstart, &cstop);
187 fail_unless (res == TRUE);
188 fail_unless (cstart == 200);
189 fail_unless (cstop == 250);
191 /* inside, touching lower bound */
192 res = gst_segment_clip (&segment, GST_FORMAT_BYTES,
193 200, 250, &cstart, &cstop);
194 fail_unless (res == TRUE);
195 fail_unless (cstart == 200);
196 fail_unless (cstop == 250);
198 /* completely inside */
199 res = gst_segment_clip (&segment, GST_FORMAT_BYTES,
200 250, 290, &cstart, &cstop);
201 fail_unless (res == TRUE);
202 fail_unless (cstart == 250);
203 fail_unless (cstop == 290);
205 /* partially inside */
206 res = gst_segment_clip (&segment, GST_FORMAT_BYTES,
207 250, 350, &cstart, &cstop);
208 fail_unless (res == TRUE);
209 fail_unless (cstart == 250);
210 fail_unless (cstop == 300);
213 res = gst_segment_clip (&segment, GST_FORMAT_BYTES, -1, 100, &cstart, &cstop);
214 fail_unless (res == FALSE);
217 res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, -1, &cstart, &cstop);
218 fail_unless (res == TRUE);
219 fail_unless (cstart == 200);
220 fail_unless (cstop == 300);
222 /* start on lower bound */
223 res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 200, -1, &cstart, &cstop);
224 fail_unless (res == TRUE);
225 fail_unless (cstart == 200);
226 fail_unless (cstop == 300);
229 res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 250, -1, &cstart, &cstop);
230 fail_unless (res == TRUE);
231 fail_unless (cstart == 250);
232 fail_unless (cstop == 300);
234 /* start outside on boundary */
235 res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 300, -1, &cstart, &cstop);
236 fail_unless (res == FALSE);
238 /* start completely outside */
239 res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 350, -1, &cstart, &cstop);
240 fail_unless (res == FALSE);
245 /* mess with the segment structure in the bytes format */
246 GST_START_TEST (segment_seek_size)
250 guint64 cstart, cstop;
253 gst_segment_init (&segment, GST_FORMAT_BYTES);
254 segment.duration = 200;
256 /* configure segment to start 100 */
257 gst_segment_do_seek (&segment, 1.0,
260 GST_SEEK_TYPE_SET, 100, GST_SEEK_TYPE_NONE, -1, &update);
261 fail_unless (segment.start == 100);
262 fail_unless (segment.position == 100);
263 fail_unless (segment.stop == -1);
264 fail_unless (update == TRUE);
265 check_times (&segment, 100, 100, 0);
267 /* do some clipping on the open range */
268 /* completely outside */
269 res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 0, 50, &cstart, &cstop);
270 fail_unless (res == FALSE);
272 /* touching lower bound */
273 res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, 100, &cstart, &cstop);
274 fail_unless (res == FALSE);
276 /* partially inside */
277 res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, 150, &cstart, &cstop);
278 fail_unless (res == TRUE);
279 fail_unless (cstart == 100);
280 fail_unless (cstop == 150);
282 /* inside, touching lower bound */
283 res = gst_segment_clip (&segment, GST_FORMAT_BYTES,
284 100, 150, &cstart, &cstop);
285 fail_unless (res == TRUE);
286 fail_unless (cstart == 100);
287 fail_unless (cstop == 150);
289 /* completely inside */
290 res = gst_segment_clip (&segment, GST_FORMAT_BYTES,
291 150, 200, &cstart, &cstop);
292 fail_unless (res == TRUE);
293 fail_unless (cstart == 150);
294 fail_unless (cstop == 200);
297 res = gst_segment_clip (&segment, GST_FORMAT_BYTES, -1, 100, &cstart, &cstop);
298 fail_unless (res == FALSE);
301 res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, -1, &cstart, &cstop);
302 fail_unless (res == TRUE);
303 fail_unless (cstart == 100);
304 fail_unless (cstop == -1);
306 /* start on lower bound */
307 res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 100, -1, &cstart, &cstop);
308 fail_unless (res == TRUE);
309 fail_unless (cstart == 100);
310 fail_unless (cstop == -1);
313 res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 150, -1, &cstart, &cstop);
314 fail_unless (res == TRUE);
315 fail_unless (cstart == 150);
316 fail_unless (cstop == -1);
318 /* add 100 to start, set stop to 300, stop clips to 200 */
319 gst_segment_do_seek (&segment, 1.0,
322 GST_SEEK_TYPE_SET, 100 + 100, GST_SEEK_TYPE_SET, 300, &update);
323 fail_unless (segment.start == 200);
324 fail_unless (segment.position == 200);
325 fail_unless (segment.stop == 200);
326 check_times (&segment, 200, 200, 0);
328 /* add 100 to start (to 300), set stop to 200, this clips start
330 gst_segment_do_seek (&segment, 1.0,
333 GST_SEEK_TYPE_SET, 200 + 100, GST_SEEK_TYPE_SET, 200, &update);
334 fail_unless (segment.start == 200);
335 fail_unless (segment.position == 200);
336 fail_unless (segment.stop == 200);
337 fail_unless (update == FALSE);
338 check_times (&segment, 200, 200, 0);
340 /* seek relative to end */
341 gst_segment_do_seek (&segment, 1.0,
344 GST_SEEK_TYPE_END, -100, GST_SEEK_TYPE_END, -20, &update);
345 fail_unless (segment.start == 100);
346 fail_unless (segment.position == 100);
347 fail_unless (segment.stop == 180);
348 fail_unless (update == TRUE);
349 check_times (&segment, 150, 150, 50);
351 /* completely outside */
352 res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 0, 50, &cstart, &cstop);
353 fail_unless (res == FALSE);
355 /* touching lower bound */
356 res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, 100, &cstart, &cstop);
357 fail_unless (res == FALSE);
359 /* partially inside */
360 res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, 150, &cstart, &cstop);
361 fail_unless (res == TRUE);
362 fail_unless (cstart == 100);
363 fail_unless (cstop == 150);
365 /* inside, touching lower bound */
366 res = gst_segment_clip (&segment, GST_FORMAT_BYTES,
367 100, 150, &cstart, &cstop);
368 fail_unless (res == TRUE);
369 fail_unless (cstart == 100);
370 fail_unless (cstop == 150);
372 /* completely inside */
373 res = gst_segment_clip (&segment, GST_FORMAT_BYTES,
374 150, 170, &cstart, &cstop);
375 fail_unless (res == TRUE);
376 fail_unless (cstart == 150);
377 fail_unless (cstop == 170);
379 /* partially inside */
380 res = gst_segment_clip (&segment, GST_FORMAT_BYTES,
381 150, 250, &cstart, &cstop);
382 fail_unless (res == TRUE);
383 fail_unless (cstart == 150);
384 fail_unless (cstop == 180);
387 res = gst_segment_clip (&segment, GST_FORMAT_BYTES, -1, 100, &cstart, &cstop);
388 fail_unless (res == FALSE);
391 res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, -1, &cstart, &cstop);
392 fail_unless (res == TRUE);
393 fail_unless (cstart == 100);
394 fail_unless (cstop == 180);
396 /* start on lower bound */
397 res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 100, -1, &cstart, &cstop);
398 fail_unless (res == TRUE);
399 fail_unless (cstart == 100);
400 fail_unless (cstop == 180);
403 res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 150, -1, &cstart, &cstop);
404 fail_unless (res == TRUE);
405 fail_unless (cstart == 150);
406 fail_unless (cstop == 180);
408 /* start outside on boundary */
409 res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 180, -1, &cstart, &cstop);
410 fail_unless (res == FALSE);
412 /* start completely outside */
413 res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 250, -1, &cstart, &cstop);
414 fail_unless (res == FALSE);
419 GST_START_TEST (segment_seek_reverse)
424 gst_segment_init (&segment, GST_FORMAT_BYTES);
425 segment.duration = 200;
427 /* configure segment to stop 100 */
428 gst_segment_do_seek (&segment, -1.0,
431 GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_SET, 100, &update);
432 fail_unless (segment.start == 0);
433 fail_unless (segment.stop == 100);
434 fail_unless (segment.time == 0);
435 fail_unless (segment.position == 100);
436 fail_unless (update == TRUE);
437 check_times (&segment, 100, 100, 0);
438 check_times (&segment, 50, 50, 50);
439 check_times (&segment, 0, 0, 100);
442 gst_segment_do_seek (&segment, -1.0,
445 GST_SEEK_TYPE_SET, 10, GST_SEEK_TYPE_SET, 100 - 20, &update);
446 fail_unless (segment.start == 10);
447 fail_unless (segment.stop == 80);
448 fail_unless (segment.time == 10);
449 fail_unless (segment.position == 80);
450 fail_unless (update == TRUE);
451 check_times (&segment, 80, 80, 0);
452 check_times (&segment, 40, 40, 40);
453 check_times (&segment, 10, 10, 70);
455 gst_segment_do_seek (&segment, -1.0,
458 GST_SEEK_TYPE_SET, 20, GST_SEEK_TYPE_NONE, 0, &update);
459 fail_unless (segment.start == 20);
460 fail_unless (segment.stop == 80);
461 fail_unless (segment.time == 20);
462 fail_unless (segment.position == 80);
463 fail_unless (update == FALSE);
464 check_times (&segment, 80, 80, 0);
465 check_times (&segment, 20, 20, 60);
470 /* mess with the segment structure in the bytes format */
471 GST_START_TEST (segment_seek_rate)
476 gst_segment_init (&segment, GST_FORMAT_BYTES);
478 /* configure segment to rate 2.0 */
479 gst_segment_do_seek (&segment, 2.0,
482 GST_SEEK_TYPE_NONE, -1, GST_SEEK_TYPE_NONE, -1, &update);
483 fail_unless (segment.format == GST_FORMAT_BYTES);
484 fail_unless (segment.start == 0);
485 fail_unless (segment.position == 0);
486 fail_unless (segment.stop == -1);
487 fail_unless (segment.rate == 2.0);
488 fail_unless (update == FALSE);
489 check_times (&segment, 50, 50, 25);
491 /* set a real stop position, this must happen in bytes */
492 gst_segment_do_seek (&segment, 3.0,
495 GST_SEEK_TYPE_NONE, -1, GST_SEEK_TYPE_SET, 100, &update);
496 fail_unless (segment.format == GST_FORMAT_BYTES);
497 fail_unless (segment.start == 0);
498 fail_unless (segment.stop == 100);
499 fail_unless (segment.rate == 3.0);
500 /* no seek should happen, we just updated the stop position in forward
502 fail_unless (update == FALSE);
503 check_times (&segment, 60, 60, 20);
505 /* set some duration, stop -1 END seeks will now work with the
506 * duration, if the formats match */
507 segment.duration = 200;
508 fail_unless (segment.duration == 200);
510 /* seek to end with 0 should set the stop to the duration */
511 gst_segment_do_seek (&segment, 2.0,
512 GST_FORMAT_BYTES, GST_SEEK_FLAG_NONE,
513 GST_SEEK_TYPE_NONE, -1, GST_SEEK_TYPE_END, 0, &update);
514 fail_unless (segment.stop == 200);
515 fail_unless (segment.duration == 200);
517 /* subtract 100 from the end */
518 gst_segment_do_seek (&segment, 2.0,
519 GST_FORMAT_BYTES, GST_SEEK_FLAG_NONE,
520 GST_SEEK_TYPE_NONE, -1, GST_SEEK_TYPE_END, -100, &update);
521 fail_unless (segment.stop == 100);
522 fail_unless (segment.duration == 200);
524 /* add 100 to the duration, this should be clamped to the duration */
525 gst_segment_do_seek (&segment, 2.0,
526 GST_FORMAT_BYTES, GST_SEEK_FLAG_NONE,
527 GST_SEEK_TYPE_NONE, -1, GST_SEEK_TYPE_END, 100, &update);
528 fail_unless (segment.stop == 200);
529 fail_unless (segment.duration == 200);
534 GST_START_TEST (segment_copy)
537 GstSegment segment = { 0.0, };
539 /* this is a boxed type copy function, we support copying NULL */
540 fail_unless (gst_segment_copy (NULL) == NULL);
542 gst_segment_init (&segment, GST_FORMAT_TIME);
545 segment.applied_rate = 1.0;
550 copy = gst_segment_copy (&segment);
551 fail_unless (copy != NULL);
552 /* we inited the struct on the stack to zeroes, so direct comparison should
553 * be ok here despite the padding field and regardless of implementation */
554 fail_unless (memcmp (copy, &segment, sizeof (GstSegment)) == 0);
555 gst_segment_free (copy);
560 /* mess with the segment structure in the bytes format */
561 GST_START_TEST (segment_seek_noupdate)
566 gst_segment_init (&segment, GST_FORMAT_TIME);
569 segment.position = 50;
573 /* doesn't change anything */
574 gst_segment_do_seek (&segment, 1.0,
577 GST_SEEK_TYPE_NONE, 0, GST_SEEK_TYPE_NONE, 0, &update);
578 fail_unless (update == FALSE);
579 fail_unless (segment.format == GST_FORMAT_TIME);
580 fail_unless (segment.start == 0);
581 fail_unless (segment.stop == 200);
582 fail_unless (segment.time == 0);
583 fail_unless (segment.position == 50);
584 fail_unless (segment.base == 50);
585 fail_unless (segment.offset == 50);
587 gst_segment_do_seek (&segment, 2.0,
590 GST_SEEK_TYPE_NONE, 0, GST_SEEK_TYPE_NONE, 0, &update);
591 fail_unless (update == FALSE);
592 fail_unless (segment.format == GST_FORMAT_TIME);
593 fail_unless (segment.start == 0);
594 fail_unless (segment.stop == 200);
595 fail_unless (segment.time == 0);
596 fail_unless (segment.position == 50);
597 fail_unless (segment.base == 50);
598 fail_unless_equals_int (segment.offset, 50);
600 gst_segment_do_seek (&segment, 1.0,
603 GST_SEEK_TYPE_NONE, 0, GST_SEEK_TYPE_NONE, 0, &update);
604 fail_unless (update == FALSE);
605 fail_unless (segment.format == GST_FORMAT_TIME);
606 fail_unless (segment.start == 0);
607 fail_unless (segment.stop == 200);
608 fail_unless (segment.time == 0);
609 fail_unless (segment.position == 50);
610 fail_unless (segment.base == 0);
611 fail_unless (segment.offset == 50);
618 gst_segment_suite (void)
620 Suite *s = suite_create ("GstSegment");
621 TCase *tc_chain = tcase_create ("segments");
623 tcase_set_timeout (tc_chain, 20);
625 suite_add_tcase (s, tc_chain);
626 tcase_add_test (tc_chain, segment_seek_nosize);
627 tcase_add_test (tc_chain, segment_seek_size);
628 tcase_add_test (tc_chain, segment_seek_reverse);
629 tcase_add_test (tc_chain, segment_seek_rate);
630 tcase_add_test (tc_chain, segment_copy);
631 tcase_add_test (tc_chain, segment_seek_noupdate);
636 GST_CHECK_MAIN (gst_segment);