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 (st == stream_time);
35 fail_unless (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 (update == TRUE);
142 check_times (&segment, 200, 200, 50);
145 /* add 100 to start (to 300), set stop to 200, this is not allowed.
146 * nothing should be updated in the segment. A g_warning is
148 ASSERT_CRITICAL (gst_segment_do_seek (&segment, 1.0,
151 GST_SEEK_TYPE_SET, 200 + 100, GST_SEEK_TYPE_SET, 200, &update));
152 fail_unless (segment.start == 200);
153 fail_unless (segment.position == 200);
154 fail_unless (segment.stop == 300);
155 /* update didn't change */
156 fail_unless (update == FALSE);
157 check_times (&segment, 250, 250, 100);
160 /* seek relative to end, should not do anything since size is
162 gst_segment_do_seek (&segment, 1.0,
165 GST_SEEK_TYPE_END, -300, GST_SEEK_TYPE_END, -100, &update);
166 fail_unless (segment.start == 200);
167 fail_unless (segment.position == 200);
168 fail_unless (segment.stop == 300);
169 fail_unless (update == FALSE);
170 check_times (&segment, 250, 250, 100);
172 /* completely outside */
173 res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 0, 50, &cstart, &cstop);
174 fail_unless (res == FALSE);
176 /* touching lower bound */
177 res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, 200, &cstart, &cstop);
178 fail_unless (res == FALSE);
180 /* partially inside */
181 res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, 250, &cstart, &cstop);
182 fail_unless (res == TRUE);
183 fail_unless (cstart == 200);
184 fail_unless (cstop == 250);
186 /* inside, touching lower bound */
187 res = gst_segment_clip (&segment, GST_FORMAT_BYTES,
188 200, 250, &cstart, &cstop);
189 fail_unless (res == TRUE);
190 fail_unless (cstart == 200);
191 fail_unless (cstop == 250);
193 /* completely inside */
194 res = gst_segment_clip (&segment, GST_FORMAT_BYTES,
195 250, 290, &cstart, &cstop);
196 fail_unless (res == TRUE);
197 fail_unless (cstart == 250);
198 fail_unless (cstop == 290);
200 /* partially inside */
201 res = gst_segment_clip (&segment, GST_FORMAT_BYTES,
202 250, 350, &cstart, &cstop);
203 fail_unless (res == TRUE);
204 fail_unless (cstart == 250);
205 fail_unless (cstop == 300);
208 res = gst_segment_clip (&segment, GST_FORMAT_BYTES, -1, 100, &cstart, &cstop);
209 fail_unless (res == FALSE);
212 res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, -1, &cstart, &cstop);
213 fail_unless (res == TRUE);
214 fail_unless (cstart == 200);
215 fail_unless (cstop == 300);
217 /* start on lower bound */
218 res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 200, -1, &cstart, &cstop);
219 fail_unless (res == TRUE);
220 fail_unless (cstart == 200);
221 fail_unless (cstop == 300);
224 res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 250, -1, &cstart, &cstop);
225 fail_unless (res == TRUE);
226 fail_unless (cstart == 250);
227 fail_unless (cstop == 300);
229 /* start outside on boundary */
230 res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 300, -1, &cstart, &cstop);
231 fail_unless (res == FALSE);
233 /* start completely outside */
234 res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 350, -1, &cstart, &cstop);
235 fail_unless (res == FALSE);
240 /* mess with the segment structure in the bytes format */
241 GST_START_TEST (segment_seek_size)
245 guint64 cstart, cstop;
248 gst_segment_init (&segment, GST_FORMAT_BYTES);
249 segment.duration = 200;
251 /* configure segment to start 100 */
252 gst_segment_do_seek (&segment, 1.0,
255 GST_SEEK_TYPE_SET, 100, GST_SEEK_TYPE_NONE, -1, &update);
256 fail_unless (segment.start == 100);
257 fail_unless (segment.position == 100);
258 fail_unless (segment.stop == -1);
259 fail_unless (update == TRUE);
260 check_times (&segment, 100, 100, 0);
262 /* do some clipping on the open range */
263 /* completely outside */
264 res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 0, 50, &cstart, &cstop);
265 fail_unless (res == FALSE);
267 /* touching lower bound */
268 res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, 100, &cstart, &cstop);
269 fail_unless (res == FALSE);
271 /* partially inside */
272 res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, 150, &cstart, &cstop);
273 fail_unless (res == TRUE);
274 fail_unless (cstart == 100);
275 fail_unless (cstop == 150);
277 /* inside, touching lower bound */
278 res = gst_segment_clip (&segment, GST_FORMAT_BYTES,
279 100, 150, &cstart, &cstop);
280 fail_unless (res == TRUE);
281 fail_unless (cstart == 100);
282 fail_unless (cstop == 150);
284 /* completely inside */
285 res = gst_segment_clip (&segment, GST_FORMAT_BYTES,
286 150, 200, &cstart, &cstop);
287 fail_unless (res == TRUE);
288 fail_unless (cstart == 150);
289 fail_unless (cstop == 200);
292 res = gst_segment_clip (&segment, GST_FORMAT_BYTES, -1, 100, &cstart, &cstop);
293 fail_unless (res == FALSE);
296 res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, -1, &cstart, &cstop);
297 fail_unless (res == TRUE);
298 fail_unless (cstart == 100);
299 fail_unless (cstop == -1);
301 /* start on lower bound */
302 res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 100, -1, &cstart, &cstop);
303 fail_unless (res == TRUE);
304 fail_unless (cstart == 100);
305 fail_unless (cstop == -1);
308 res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 150, -1, &cstart, &cstop);
309 fail_unless (res == TRUE);
310 fail_unless (cstart == 150);
311 fail_unless (cstop == -1);
313 /* add 100 to start, set stop to 300, stop clips to 200 */
314 gst_segment_do_seek (&segment, 1.0,
317 GST_SEEK_TYPE_SET, 100 + 100, GST_SEEK_TYPE_SET, 300, &update);
318 fail_unless (segment.start == 200);
319 fail_unless (segment.position == 200);
320 fail_unless (segment.stop == 200);
321 check_times (&segment, 200, 200, 0);
323 /* add 100 to start (to 300), set stop to 200, this clips start
325 gst_segment_do_seek (&segment, 1.0,
328 GST_SEEK_TYPE_SET, 200 + 100, GST_SEEK_TYPE_SET, 200, &update);
329 fail_unless (segment.start == 200);
330 fail_unless (segment.position == 200);
331 fail_unless (segment.stop == 200);
332 fail_unless (update == FALSE);
333 check_times (&segment, 200, 200, 0);
335 /* seek relative to end */
336 gst_segment_do_seek (&segment, 1.0,
339 GST_SEEK_TYPE_END, -100, GST_SEEK_TYPE_END, -20, &update);
340 fail_unless (segment.start == 100);
341 fail_unless (segment.position == 100);
342 fail_unless (segment.stop == 180);
343 fail_unless (update == TRUE);
344 check_times (&segment, 150, 150, 50);
346 /* completely outside */
347 res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 0, 50, &cstart, &cstop);
348 fail_unless (res == FALSE);
350 /* touching lower bound */
351 res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, 100, &cstart, &cstop);
352 fail_unless (res == FALSE);
354 /* partially inside */
355 res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, 150, &cstart, &cstop);
356 fail_unless (res == TRUE);
357 fail_unless (cstart == 100);
358 fail_unless (cstop == 150);
360 /* inside, touching lower bound */
361 res = gst_segment_clip (&segment, GST_FORMAT_BYTES,
362 100, 150, &cstart, &cstop);
363 fail_unless (res == TRUE);
364 fail_unless (cstart == 100);
365 fail_unless (cstop == 150);
367 /* completely inside */
368 res = gst_segment_clip (&segment, GST_FORMAT_BYTES,
369 150, 170, &cstart, &cstop);
370 fail_unless (res == TRUE);
371 fail_unless (cstart == 150);
372 fail_unless (cstop == 170);
374 /* partially inside */
375 res = gst_segment_clip (&segment, GST_FORMAT_BYTES,
376 150, 250, &cstart, &cstop);
377 fail_unless (res == TRUE);
378 fail_unless (cstart == 150);
379 fail_unless (cstop == 180);
382 res = gst_segment_clip (&segment, GST_FORMAT_BYTES, -1, 100, &cstart, &cstop);
383 fail_unless (res == FALSE);
386 res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, -1, &cstart, &cstop);
387 fail_unless (res == TRUE);
388 fail_unless (cstart == 100);
389 fail_unless (cstop == 180);
391 /* start on lower bound */
392 res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 100, -1, &cstart, &cstop);
393 fail_unless (res == TRUE);
394 fail_unless (cstart == 100);
395 fail_unless (cstop == 180);
398 res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 150, -1, &cstart, &cstop);
399 fail_unless (res == TRUE);
400 fail_unless (cstart == 150);
401 fail_unless (cstop == 180);
403 /* start outside on boundary */
404 res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 180, -1, &cstart, &cstop);
405 fail_unless (res == FALSE);
407 /* start completely outside */
408 res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 250, -1, &cstart, &cstop);
409 fail_unless (res == FALSE);
414 GST_START_TEST (segment_seek_reverse)
419 gst_segment_init (&segment, GST_FORMAT_BYTES);
420 segment.duration = 200;
422 /* configure segment to stop 100 */
423 gst_segment_do_seek (&segment, -1.0,
426 GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_SET, 100, &update);
427 fail_unless (segment.start == 0);
428 fail_unless (segment.stop == 100);
429 fail_unless (segment.time == 0);
430 fail_unless (segment.position == 100);
431 fail_unless (update == TRUE);
432 check_times (&segment, 100, 100, 0);
433 check_times (&segment, 50, 50, 50);
434 check_times (&segment, 0, 0, 100);
437 gst_segment_do_seek (&segment, -1.0,
440 GST_SEEK_TYPE_SET, 10, GST_SEEK_TYPE_SET, 100 - 20, &update);
441 fail_unless (segment.start == 10);
442 fail_unless (segment.stop == 80);
443 fail_unless (segment.time == 10);
444 fail_unless (segment.position == 80);
445 fail_unless (update == TRUE);
446 check_times (&segment, 80, 80, 0);
447 check_times (&segment, 40, 40, 40);
448 check_times (&segment, 10, 10, 70);
450 gst_segment_do_seek (&segment, -1.0,
453 GST_SEEK_TYPE_SET, 20, GST_SEEK_TYPE_NONE, 0, &update);
454 fail_unless (segment.start == 20);
455 fail_unless (segment.stop == 80);
456 fail_unless (segment.time == 20);
457 fail_unless (segment.position == 80);
458 fail_unless (update == FALSE);
459 check_times (&segment, 80, 80, 0);
460 check_times (&segment, 20, 20, 60);
465 /* mess with the segment structure in the bytes format */
466 GST_START_TEST (segment_seek_rate)
471 gst_segment_init (&segment, GST_FORMAT_BYTES);
473 /* configure segment to rate 2.0 */
474 gst_segment_do_seek (&segment, 2.0,
477 GST_SEEK_TYPE_NONE, -1, GST_SEEK_TYPE_NONE, -1, &update);
478 fail_unless (segment.format == GST_FORMAT_BYTES);
479 fail_unless (segment.start == 0);
480 fail_unless (segment.stop == -1);
481 fail_unless (segment.rate == 2.0);
482 fail_unless (update == FALSE);
484 /* set a real stop position, this must happen in bytes */
485 gst_segment_do_seek (&segment, 3.0,
488 GST_SEEK_TYPE_NONE, -1, GST_SEEK_TYPE_SET, 100, &update);
489 fail_unless (segment.format == GST_FORMAT_BYTES);
490 fail_unless (segment.start == 0);
491 fail_unless (segment.stop == 100);
492 fail_unless (segment.rate == 3.0);
493 /* no seek should happen, we just updated the stop position in forward
495 fail_unless (update == FALSE);
497 /* set some duration, stop -1 END seeks will now work with the
498 * duration, if the formats match */
499 segment.duration = 200;
500 fail_unless (segment.duration == 200);
502 /* seek to end with 0 should set the stop to the duration */
503 gst_segment_do_seek (&segment, 2.0,
504 GST_FORMAT_BYTES, GST_SEEK_FLAG_NONE,
505 GST_SEEK_TYPE_NONE, -1, GST_SEEK_TYPE_END, 0, &update);
506 fail_unless (segment.stop == 200);
507 fail_unless (segment.duration == 200);
509 /* subtract 100 from the end */
510 gst_segment_do_seek (&segment, 2.0,
511 GST_FORMAT_BYTES, GST_SEEK_FLAG_NONE,
512 GST_SEEK_TYPE_NONE, -1, GST_SEEK_TYPE_END, -100, &update);
513 fail_unless (segment.stop == 100);
514 fail_unless (segment.duration == 200);
516 /* add 100 to the duration, this should be clamped to the duration */
517 gst_segment_do_seek (&segment, 2.0,
518 GST_FORMAT_BYTES, GST_SEEK_FLAG_NONE,
519 GST_SEEK_TYPE_NONE, -1, GST_SEEK_TYPE_END, 100, &update);
520 fail_unless (segment.stop == 200);
521 fail_unless (segment.duration == 200);
526 GST_START_TEST (segment_copy)
529 GstSegment segment = { 0.0, };
531 /* this is a boxed type copy function, we support copying NULL */
532 fail_unless (gst_segment_copy (NULL) == NULL);
534 gst_segment_init (&segment, GST_FORMAT_TIME);
537 segment.applied_rate = 1.0;
542 copy = gst_segment_copy (&segment);
543 fail_unless (copy != NULL);
544 /* we inited the struct on the stack to zeroes, so direct comparison should
545 * be ok here despite the padding field and regardless of implementation */
546 fail_unless (memcmp (copy, &segment, sizeof (GstSegment)) == 0);
547 gst_segment_free (copy);
553 gst_segment_suite (void)
555 Suite *s = suite_create ("GstSegment");
556 TCase *tc_chain = tcase_create ("segments");
558 tcase_set_timeout (tc_chain, 20);
560 suite_add_tcase (s, tc_chain);
561 tcase_add_test (tc_chain, segment_seek_nosize);
562 tcase_add_test (tc_chain, segment_seek_size);
563 tcase_add_test (tc_chain, segment_seek_reverse);
564 tcase_add_test (tc_chain, segment_seek_rate);
565 tcase_add_test (tc_chain, segment_copy);
570 GST_CHECK_MAIN (gst_segment);