1 /*
2 * Unit test for a deterministic clock for Gstreamer unit tests
3 *
4 * Copyright (C) 2008 Ole André Vadla Ravnås <ole.andre.ravnas@tandberg.com>
5 * Copyright (C) 2012 Sebastian Rasmussen <sebastian.rasmussen@axis.com>
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., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
21 */
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include <gst/check/gstcheck.h>
27 #include <gst/check/gsttestclock.h>
28
29 typedef struct
30 {
31 GstTestClock *test_clock;
32 GstClockID id;
33 GstClockTime reference;
34 } GtuClockWaitContext;
35
36 typedef struct
37 {
38 GstClockID clock_id;
39 GstClockTimeDiff jitter;
40 } SyncClockWaitContext;
41
42 #define assert_pending_id(pending_id, id, type, time) \
43 G_STMT_START { \
44 GstClockEntry *entry = GST_CLOCK_ENTRY (pending_id); \
45 g_assert (entry == (id)); \
46 g_assert (GST_CLOCK_ENTRY_TYPE (entry) == (type)); \
47 g_assert_cmpuint (GST_CLOCK_ENTRY_TIME (entry), ==, (time)); \
48 } G_STMT_END
49
50 #define assert_processed_id(processed_id, id, type, time) \
51 G_STMT_START { \
52 GstClockEntry *entry = GST_CLOCK_ENTRY (processed_id); \
53 g_assert (entry == (id)); \
54 g_assert (GST_CLOCK_ENTRY_TYPE (entry) == (type)); \
55 g_assert_cmpuint (GST_CLOCK_ENTRY_STATUS (entry), ==, (time)); \
56 } G_STMT_END
57
58 static gpointer test_wait_pending_single_shot_id_sync_worker (gpointer data);
59 static gpointer test_wait_pending_single_shot_id_async_worker (gpointer data);
60 static gpointer test_wait_pending_periodic_id_waiter_thread (gpointer data);
61 static gboolean test_async_wait_cb (GstClock * clock, GstClockTime time,
62 GstClockID id, gpointer user_data);
63
64 static GtuClockWaitContext *gst_test_util_wait_for_clock_id_begin (GstTestClock
65 * clock, GstClockID id, GstClockTimeDiff * jitter);
66 static GstClockReturn gst_test_util_wait_for_clock_id_end (GtuClockWaitContext *
67 wait_ctx);
68 static gboolean
69 gst_test_util_clock_wait_context_has_completed (GtuClockWaitContext * wait_ctx);
70
71 static gpointer
test_wait_pending_single_shot_id_sync_worker(gpointer data)72 test_wait_pending_single_shot_id_sync_worker (gpointer data)
73 {
74 SyncClockWaitContext *ctx = data;
75
76 gst_clock_id_wait (ctx->clock_id, &ctx->jitter);
77
78 return NULL;
79 }
80
81 static gpointer
test_wait_pending_single_shot_id_async_worker(gpointer data)82 test_wait_pending_single_shot_id_async_worker (gpointer data)
83 {
84 GstClockID clock_id = data;
85
86 g_usleep (G_USEC_PER_SEC / 10);
87 gst_clock_id_wait_async (clock_id, test_async_wait_cb, NULL, NULL);
88
89 return NULL;
90 }
91
92 static gpointer
test_wait_pending_periodic_id_waiter_thread(gpointer data)93 test_wait_pending_periodic_id_waiter_thread (gpointer data)
94 {
95 GstClockID clock_id = data;
96 gst_clock_id_wait (clock_id, NULL);
97 return NULL;
98 }
99
100 static gboolean
test_async_wait_cb(GstClock * clock,GstClockTime time,GstClockID id,gpointer user_data)101 test_async_wait_cb (GstClock * clock,
102 GstClockTime time, GstClockID id, gpointer user_data)
103 {
104
105 gboolean *wait_complete = user_data;
106
107 if (wait_complete != NULL)
108 *wait_complete = TRUE;
109
110 return TRUE;
111 }
112
113 static GtuClockWaitContext *
gst_test_util_wait_for_clock_id_begin(GstTestClock * test_clock,GstClockID id,GstClockTimeDiff * jitter)114 gst_test_util_wait_for_clock_id_begin (GstTestClock * test_clock, GstClockID id,
115 GstClockTimeDiff * jitter)
116 {
117 GtuClockWaitContext *wait_ctx;
118
119 wait_ctx = g_slice_new (GtuClockWaitContext);
120 wait_ctx->test_clock = gst_object_ref (test_clock);
121 wait_ctx->reference = gst_clock_get_time (GST_CLOCK (wait_ctx->test_clock));
122 wait_ctx->id = gst_clock_id_ref (id);
123
124 if (jitter) {
125 GstClockEntry *entry = GST_CLOCK_ENTRY (wait_ctx->id);
126 GstClockTime requested = GST_CLOCK_ENTRY_TIME (entry);
127 GstClockTime reference = wait_ctx->reference;
128
129 *jitter = GST_CLOCK_DIFF (requested, reference);
130 }
131
132 if (!gst_test_clock_has_id (wait_ctx->test_clock, wait_ctx->id)) {
133 GstClockClass *klass = GST_CLOCK_GET_CLASS (wait_ctx->test_clock);
134 GstClock *clock = GST_CLOCK (wait_ctx->test_clock);
135 g_assert (klass->wait_async (clock, wait_ctx->id) == GST_CLOCK_OK);
136 }
137
138 g_assert (gst_test_clock_has_id (wait_ctx->test_clock, wait_ctx->id));
139 g_assert_cmpint (gst_test_clock_peek_id_count (wait_ctx->test_clock), >, 0);
140
141 return wait_ctx;
142 }
143
144 static GstClockReturn
gst_test_util_wait_for_clock_id_end(GtuClockWaitContext * wait_ctx)145 gst_test_util_wait_for_clock_id_end (GtuClockWaitContext * wait_ctx)
146 {
147 GstClockReturn status = GST_CLOCK_ERROR;
148 GstClockEntry *entry = GST_CLOCK_ENTRY (wait_ctx->id);
149
150 if (G_UNLIKELY (GST_CLOCK_ENTRY_STATUS (entry) == GST_CLOCK_UNSCHEDULED)) {
151 status = GST_CLOCK_UNSCHEDULED;
152 } else {
153 GstClockTime requested = GST_CLOCK_ENTRY_TIME (entry);
154 GstClockTimeDiff diff;
155
156 g_assert (gst_test_clock_has_id (wait_ctx->test_clock, wait_ctx->id));
157
158 diff = GST_CLOCK_DIFF (requested, wait_ctx->reference);
159
160 if (diff > 0) {
161 status = GST_CLOCK_EARLY;
162 } else {
163 status = GST_CLOCK_OK;
164 }
165
166 g_atomic_int_set (&GST_CLOCK_ENTRY_STATUS (entry), status);
167 }
168
169 if (GST_CLOCK_ENTRY_TYPE (entry) == GST_CLOCK_ENTRY_SINGLE) {
170 GstClockClass *klass = GST_CLOCK_GET_CLASS (wait_ctx->test_clock);
171 GstClock *clock = GST_CLOCK (wait_ctx->test_clock);
172
173 klass->unschedule (clock, wait_ctx->id);
174 g_assert (!gst_test_clock_has_id (wait_ctx->test_clock, wait_ctx->id));
175 } else {
176 GST_CLOCK_ENTRY_TIME (entry) += GST_CLOCK_ENTRY_INTERVAL (entry);
177 g_assert (gst_test_clock_has_id (wait_ctx->test_clock, wait_ctx->id));
178 }
179
180 gst_clock_id_unref (wait_ctx->id);
181 gst_object_unref (wait_ctx->test_clock);
182 g_slice_free (GtuClockWaitContext, wait_ctx);
183
184 return status;
185 }
186
187 static gboolean
gst_test_util_clock_wait_context_has_completed(GtuClockWaitContext * wait_ctx)188 gst_test_util_clock_wait_context_has_completed (GtuClockWaitContext * wait_ctx)
189 {
190 GstClock *clock = GST_CLOCK (wait_ctx->test_clock);
191 GstClockEntry *entry = GST_CLOCK_ENTRY (wait_ctx->id);
192 GstClockTime requested = GST_CLOCK_ENTRY_TIME (entry);
193 GstClockTime now = gst_clock_get_time (clock);
194
195 return requested < now;
196 }
197
GST_START_TEST(test_object_flags)198 GST_START_TEST (test_object_flags)
199 {
200 GstClock *clock = gst_test_clock_new ();
201 g_assert (GST_OBJECT_FLAG_IS_SET (clock, GST_CLOCK_FLAG_CAN_DO_SINGLE_SYNC));
202 g_assert (GST_OBJECT_FLAG_IS_SET (clock, GST_CLOCK_FLAG_CAN_DO_SINGLE_ASYNC));
203 g_assert (GST_OBJECT_FLAG_IS_SET (clock,
204 GST_CLOCK_FLAG_CAN_DO_PERIODIC_SYNC));
205 g_assert (GST_OBJECT_FLAG_IS_SET (clock,
206 GST_CLOCK_FLAG_CAN_DO_PERIODIC_ASYNC));
207 gst_object_unref (clock);
208 }
209
210 GST_END_TEST;
211
GST_START_TEST(test_resolution_query)212 GST_START_TEST (test_resolution_query)
213 {
214 GstClock *clock = gst_test_clock_new ();
215 g_assert_cmpuint (gst_clock_get_resolution (clock), ==, 1);
216 gst_object_unref (clock);
217 }
218
219 GST_END_TEST;
220
GST_START_TEST(test_start_time)221 GST_START_TEST (test_start_time)
222 {
223 GstClock *clock;
224 guint64 start_time;
225
226 clock = gst_test_clock_new ();
227 g_assert_cmpuint (gst_clock_get_time (clock), ==, 0);
228 g_object_get (clock, "start-time", &start_time, NULL);
229 g_assert_cmpuint (start_time, ==, 0);
230 gst_object_unref (clock);
231
232 clock = gst_test_clock_new_with_start_time (GST_SECOND);
233 g_assert_cmpuint (gst_clock_get_time (clock), ==, GST_SECOND);
234 g_object_get (clock, "start-time", &start_time, NULL);
235 g_assert_cmpuint (start_time, ==, GST_SECOND);
236 gst_object_unref (clock);
237 }
238
239 GST_END_TEST;
240
GST_START_TEST(test_set_time)241 GST_START_TEST (test_set_time)
242 {
243 GstClock *clock = gst_test_clock_new_with_start_time (GST_SECOND);
244 gst_test_clock_set_time (GST_TEST_CLOCK (clock), GST_SECOND);
245 g_assert_cmpuint (gst_clock_get_time (clock), ==, GST_SECOND);
246 gst_test_clock_set_time (GST_TEST_CLOCK (clock), GST_SECOND + 1);
247 g_assert_cmpuint (gst_clock_get_time (clock), ==, GST_SECOND + 1);
248 gst_object_unref (clock);
249 }
250
251 GST_END_TEST;
252
GST_START_TEST(test_advance_time)253 GST_START_TEST (test_advance_time)
254 {
255 GstClock *clock = gst_test_clock_new_with_start_time (GST_SECOND);
256 gst_test_clock_advance_time (GST_TEST_CLOCK (clock), 0);
257 g_assert_cmpuint (gst_clock_get_time (clock), ==, GST_SECOND);
258 gst_test_clock_advance_time (GST_TEST_CLOCK (clock), 42 * GST_MSECOND);
259 g_assert_cmpuint (gst_clock_get_time (clock), ==,
260 GST_SECOND + (42 * GST_MSECOND));
261 gst_object_unref (clock);
262 }
263
264 GST_END_TEST;
265
GST_START_TEST(test_wait_synchronous_no_timeout)266 GST_START_TEST (test_wait_synchronous_no_timeout)
267 {
268 GstClock *clock;
269 GstTestClock *test_clock;
270 GstClockID clock_id;
271 GThread *worker_thread;
272 GstClockID pending_id;
273 GstClockID processed_id;
274 SyncClockWaitContext context;
275
276 clock = gst_test_clock_new_with_start_time (GST_SECOND);
277 test_clock = GST_TEST_CLOCK (clock);
278
279 clock_id = gst_clock_new_single_shot_id (clock, GST_SECOND - 1);
280 context.clock_id = gst_clock_id_ref (clock_id);
281 context.jitter = 0;
282 worker_thread =
283 g_thread_new ("worker_thread",
284 test_wait_pending_single_shot_id_sync_worker, &context);
285 gst_test_clock_wait_for_next_pending_id (test_clock, &pending_id);
286 assert_pending_id (pending_id, clock_id, GST_CLOCK_ENTRY_SINGLE,
287 GST_SECOND - 1);
288 gst_clock_id_unref (pending_id);
289 processed_id = gst_test_clock_process_next_clock_id (test_clock);
290 assert_processed_id (processed_id, clock_id, GST_CLOCK_ENTRY_SINGLE,
291 GST_CLOCK_EARLY);
292 gst_clock_id_unref (processed_id);
293 g_thread_join (worker_thread);
294 g_assert_cmpuint (context.jitter, ==, 1);
295 gst_clock_id_unref (context.clock_id);
296 gst_clock_id_unref (clock_id);
297
298 clock_id = gst_clock_new_single_shot_id (clock, GST_SECOND);
299 context.clock_id = gst_clock_id_ref (clock_id);
300 context.jitter = 0;
301 worker_thread =
302 g_thread_new ("worker_thread",
303 test_wait_pending_single_shot_id_sync_worker, &context);
304 gst_test_clock_wait_for_next_pending_id (test_clock, &pending_id);
305 assert_pending_id (pending_id, clock_id, GST_CLOCK_ENTRY_SINGLE, GST_SECOND);
306 gst_clock_id_unref (pending_id);
307 processed_id = gst_test_clock_process_next_clock_id (test_clock);
308 assert_processed_id (processed_id, clock_id, GST_CLOCK_ENTRY_SINGLE,
309 GST_CLOCK_OK);
310 gst_clock_id_unref (processed_id);
311 g_thread_join (worker_thread);
312 g_assert_cmpuint (context.jitter, ==, 0);
313 gst_clock_id_unref (context.clock_id);
314 gst_clock_id_unref (clock_id);
315
316 clock_id = gst_clock_new_single_shot_id (clock, GST_SECOND + 1);
317 context.clock_id = gst_clock_id_ref (clock_id);
318 context.jitter = 0;
319 worker_thread =
320 g_thread_new ("worker_thread",
321 test_wait_pending_single_shot_id_sync_worker, &context);
322 gst_test_clock_wait_for_next_pending_id (test_clock, &pending_id);
323 assert_pending_id (pending_id, clock_id, GST_CLOCK_ENTRY_SINGLE,
324 GST_SECOND + 1);
325 gst_clock_id_unref (pending_id);
326 processed_id = gst_test_clock_process_next_clock_id (test_clock);
327 g_assert (processed_id == NULL);
328 gst_test_clock_advance_time (test_clock, 1);
329 processed_id = gst_test_clock_process_next_clock_id (test_clock);
330 assert_processed_id (processed_id, clock_id, GST_CLOCK_ENTRY_SINGLE,
331 GST_CLOCK_OK);
332 gst_clock_id_unref (processed_id);
333 g_thread_join (worker_thread);
334 g_assert_cmpuint (context.jitter, ==, -1);
335 gst_clock_id_unref (context.clock_id);
336 gst_clock_id_unref (clock_id);
337
338 gst_object_unref (clock);
339 }
340
341 GST_END_TEST;
342
GST_START_TEST(test_wait_pending_single_shot_id)343 GST_START_TEST (test_wait_pending_single_shot_id)
344 {
345 GstClock *clock;
346 GstTestClock *test_clock;
347 GstClockID clock_id;
348 GstClockID processed_id;
349 GThread *worker_thread;
350 GstClockID pending_id;
351
352 clock = gst_test_clock_new_with_start_time (GST_SECOND);
353 test_clock = GST_TEST_CLOCK (clock);
354
355 clock_id = gst_clock_new_single_shot_id (clock, GST_SECOND);
356 gst_clock_id_wait_async (clock_id, test_async_wait_cb, NULL, NULL);
357 gst_test_clock_wait_for_next_pending_id (test_clock, &pending_id);
358 assert_pending_id (pending_id, clock_id, GST_CLOCK_ENTRY_SINGLE, GST_SECOND);
359 gst_clock_id_unref (pending_id);
360 processed_id = gst_test_clock_process_next_clock_id (test_clock);
361 assert_processed_id (processed_id, clock_id, GST_CLOCK_ENTRY_SINGLE,
362 GST_CLOCK_OK);
363 gst_clock_id_unref (processed_id);
364 gst_clock_id_unref (clock_id);
365
366 clock_id = gst_clock_new_single_shot_id (clock, 2 * GST_SECOND);
367 worker_thread =
368 g_thread_new ("worker_thread",
369 test_wait_pending_single_shot_id_async_worker, clock_id);
370 gst_test_clock_wait_for_next_pending_id (test_clock, &pending_id);
371 assert_pending_id (pending_id, clock_id, GST_CLOCK_ENTRY_SINGLE,
372 2 * GST_SECOND);
373 gst_clock_id_unref (pending_id);
374 g_thread_join (worker_thread);
375 gst_clock_id_unref (clock_id);
376
377 clock_id = gst_clock_new_single_shot_id (clock, 3 * GST_SECOND);
378 worker_thread =
379 g_thread_new ("worker_thread",
380 test_wait_pending_single_shot_id_async_worker, clock_id);
381 gst_test_clock_wait_for_next_pending_id (test_clock, NULL);
382 g_thread_join (worker_thread);
383 gst_clock_id_unref (clock_id);
384
385 gst_object_unref (clock);
386 }
387
388 GST_END_TEST;
389
GST_START_TEST(test_wait_pending_periodic_id)390 GST_START_TEST (test_wait_pending_periodic_id)
391 {
392 GstClock *clock;
393 GstTestClock *test_clock;
394 GstClockID clock_id;
395 GstClockID processed_id;
396
397 clock = gst_test_clock_new_with_start_time (GST_SECOND);
398 test_clock = GST_TEST_CLOCK (clock);
399 clock_id = gst_clock_new_periodic_id (clock, GST_SECOND, GST_MSECOND);
400
401 {
402 GThread *waiter_thread;
403
404 waiter_thread =
405 g_thread_new ("waiter_thread",
406 test_wait_pending_periodic_id_waiter_thread, clock_id);
407
408 gst_test_clock_wait_for_next_pending_id (test_clock, NULL);
409 gst_test_clock_set_time (test_clock, GST_SECOND);
410 processed_id = gst_test_clock_process_next_clock_id (test_clock);
411 assert_processed_id (processed_id, clock_id, GST_CLOCK_ENTRY_PERIODIC,
412 GST_CLOCK_OK);
413 gst_clock_id_unref (processed_id);
414
415 g_thread_join (waiter_thread);
416 }
417
418 {
419 guint i;
420 GThread *waiter_thread;
421
422 for (i = 0; i < 3; i++) {
423 g_assert (!gst_test_clock_peek_next_pending_id (test_clock, NULL));
424 g_usleep (G_USEC_PER_SEC / 10 / 10);
425 }
426
427 waiter_thread =
428 g_thread_new ("waiter_thread",
429 test_wait_pending_periodic_id_waiter_thread, clock_id);
430
431 gst_test_clock_wait_for_next_pending_id (test_clock, NULL);
432 gst_clock_id_unschedule (clock_id);
433
434 g_thread_join (waiter_thread);
435 }
436
437 gst_clock_id_unref (clock_id);
438 gst_object_unref (clock);
439 }
440
441 GST_END_TEST;
442
GST_START_TEST(test_single_shot_sync_past)443 GST_START_TEST (test_single_shot_sync_past)
444 {
445 GstClock *clock;
446 GstTestClock *test_clock;
447 GstClockID clock_id;
448 GstClockTimeDiff jitter;
449 GtuClockWaitContext *wait_ctx;
450
451 clock = gst_test_clock_new_with_start_time (GST_SECOND);
452 test_clock = GST_TEST_CLOCK (clock);
453
454 clock_id = gst_clock_new_single_shot_id (clock, GST_SECOND - 1);
455 wait_ctx =
456 gst_test_util_wait_for_clock_id_begin (test_clock, clock_id, &jitter);
457 g_assert (gst_test_util_wait_for_clock_id_end (wait_ctx) == GST_CLOCK_EARLY);
458 g_assert_cmpint (jitter, ==, 1);
459 gst_clock_id_unref (clock_id);
460
461 gst_object_unref (clock);
462 }
463
464 GST_END_TEST;
465
GST_START_TEST(test_single_shot_sync_present)466 GST_START_TEST (test_single_shot_sync_present)
467 {
468 GstClock *clock;
469 GstTestClock *test_clock;
470 GstClockID clock_id;
471 GstClockTimeDiff jitter;
472 GtuClockWaitContext *wait_ctx;
473
474 clock = gst_test_clock_new_with_start_time (GST_SECOND);
475 test_clock = GST_TEST_CLOCK (clock);
476
477 clock_id = gst_clock_new_single_shot_id (clock, GST_SECOND);
478 wait_ctx =
479 gst_test_util_wait_for_clock_id_begin (test_clock, clock_id, &jitter);
480 g_assert (gst_test_util_wait_for_clock_id_end (wait_ctx) == GST_CLOCK_OK);
481 g_assert_cmpint (jitter, ==, 0);
482 gst_clock_id_unref (clock_id);
483
484 gst_object_unref (clock);
485 }
486
487 GST_END_TEST;
488
GST_START_TEST(test_single_shot_sync_future)489 GST_START_TEST (test_single_shot_sync_future)
490 {
491 GstClock *clock;
492 GstTestClock *test_clock;
493 GstClockID clock_id;
494 GstClockTimeDiff jitter;
495 GtuClockWaitContext *wait_ctx;
496
497 clock = gst_test_clock_new_with_start_time (GST_SECOND);
498 test_clock = GST_TEST_CLOCK (clock);
499
500 clock_id = gst_clock_new_single_shot_id (clock, 2 * GST_SECOND);
501 wait_ctx =
502 gst_test_util_wait_for_clock_id_begin (test_clock, clock_id, &jitter);
503 gst_test_clock_advance_time (test_clock, GST_SECOND);
504 g_assert (gst_test_util_wait_for_clock_id_end (wait_ctx) == GST_CLOCK_OK);
505 g_assert_cmpint (jitter, ==, -GST_SECOND);
506 gst_clock_id_unref (clock_id);
507
508 gst_object_unref (clock);
509 }
510
511 GST_END_TEST;
512
GST_START_TEST(test_single_shot_sync_unschedule)513 GST_START_TEST (test_single_shot_sync_unschedule)
514 {
515 GstClock *clock;
516 GstTestClock *test_clock;
517 GstClockID clock_id;
518 GtuClockWaitContext *wait_ctx;
519 gboolean wait_complete = FALSE;
520
521 clock = gst_test_clock_new_with_start_time (GST_SECOND);
522 test_clock = GST_TEST_CLOCK (clock);
523
524 clock_id = gst_clock_new_single_shot_id (clock, GST_SECOND);
525 gst_clock_id_unschedule (clock_id);
526 /* any wait should timeout immediately */
527 g_assert (gst_clock_id_wait_async (clock_id, test_async_wait_cb,
528 &wait_complete, NULL) == GST_CLOCK_UNSCHEDULED);
529 g_assert (gst_clock_id_wait (clock_id, NULL) == GST_CLOCK_UNSCHEDULED);
530 gst_clock_id_unref (clock_id);
531
532 clock_id = gst_clock_new_single_shot_id (clock, 2 * GST_SECOND);
533 wait_ctx = gst_test_util_wait_for_clock_id_begin (test_clock, clock_id, NULL);
534 gst_clock_id_unschedule (clock_id);
535 g_assert (gst_test_util_wait_for_clock_id_end (wait_ctx)
536 == GST_CLOCK_UNSCHEDULED);
537 gst_clock_id_unref (clock_id);
538
539 gst_object_unref (clock);
540 }
541
542 GST_END_TEST;
543
GST_START_TEST(test_single_shot_sync_ordering)544 GST_START_TEST (test_single_shot_sync_ordering)
545 {
546 GstClock *clock;
547 GstTestClock *test_clock;
548 GstClockID clock_id_a, clock_id_b;
549 GtuClockWaitContext *wait_ctx_a, *wait_ctx_b;
550
551 clock = gst_test_clock_new_with_start_time (GST_SECOND);
552 test_clock = GST_TEST_CLOCK (clock);
553
554 clock_id_a = gst_clock_new_single_shot_id (clock, 3 * GST_SECOND);
555 wait_ctx_a =
556 gst_test_util_wait_for_clock_id_begin (test_clock, clock_id_a, NULL);
557
558 gst_test_clock_advance_time (test_clock, GST_SECOND);
559
560 clock_id_b = gst_clock_new_single_shot_id (clock, 2 * GST_SECOND);
561 wait_ctx_b =
562 gst_test_util_wait_for_clock_id_begin (test_clock, clock_id_b, NULL);
563
564 gst_test_clock_advance_time (test_clock, GST_SECOND);
565
566 g_assert (gst_test_util_wait_for_clock_id_end (wait_ctx_b) == GST_CLOCK_OK);
567 g_assert (gst_test_util_wait_for_clock_id_end (wait_ctx_a) == GST_CLOCK_OK);
568
569 gst_clock_id_unref (clock_id_b);
570 gst_clock_id_unref (clock_id_a);
571
572 gst_object_unref (clock);
573 }
574
575 GST_END_TEST;
576
GST_START_TEST(test_single_shot_sync_ordering_parallel)577 GST_START_TEST (test_single_shot_sync_ordering_parallel)
578 {
579 GstClock *clock;
580 GstTestClock *test_clock;
581 GstClockID clock_id_a, clock_id_b;
582 GtuClockWaitContext *wait_ctx_a, *wait_ctx_b;
583
584 clock = gst_test_clock_new_with_start_time (GST_SECOND);
585 test_clock = GST_TEST_CLOCK (clock);
586
587 clock_id_a = gst_clock_new_single_shot_id (clock, 3 * GST_SECOND);
588 clock_id_b = gst_clock_new_single_shot_id (clock, 2 * GST_SECOND);
589 wait_ctx_a = gst_test_util_wait_for_clock_id_begin (test_clock, clock_id_a,
590 NULL);
591 wait_ctx_b = gst_test_util_wait_for_clock_id_begin (test_clock, clock_id_b,
592 NULL);
593
594 g_assert_cmpuint (gst_test_clock_get_next_entry_time (test_clock), ==,
595 2 * GST_SECOND);
596 gst_test_clock_advance_time (test_clock, GST_SECOND);
597 g_assert (gst_test_util_wait_for_clock_id_end (wait_ctx_b) == GST_CLOCK_OK);
598
599 g_assert_cmpuint (gst_test_clock_get_next_entry_time (test_clock), ==,
600 3 * GST_SECOND);
601 gst_test_clock_advance_time (test_clock, GST_SECOND);
602 g_assert (gst_test_util_wait_for_clock_id_end (wait_ctx_a) == GST_CLOCK_OK);
603
604 gst_clock_id_unref (clock_id_b);
605 gst_clock_id_unref (clock_id_a);
606
607 gst_object_unref (clock);
608 }
609
610 GST_END_TEST;
611
GST_START_TEST(test_single_shot_sync_simultaneous_no_timeout)612 GST_START_TEST (test_single_shot_sync_simultaneous_no_timeout)
613 {
614 GstClock *clock;
615 GstTestClock *test_clock;
616 GstClockID clock_id_a;
617 GstClockID clock_id_b;
618 SyncClockWaitContext context_a;
619 SyncClockWaitContext context_b;
620 GThread *worker_thread_a;
621 GThread *worker_thread_b;
622 GstClockID processed_id;
623 GstClockID pending_id;
624
625 clock = gst_test_clock_new_with_start_time (GST_SECOND);
626 test_clock = GST_TEST_CLOCK (clock);
627
628 clock_id_a = gst_clock_new_single_shot_id (clock, 5 * GST_SECOND);
629 clock_id_b = gst_clock_new_single_shot_id (clock, 6 * GST_SECOND);
630
631 context_a.clock_id = gst_clock_id_ref (clock_id_a);
632 context_a.jitter = 0;
633 context_b.clock_id = gst_clock_id_ref (clock_id_b);
634 context_b.jitter = 0;
635
636 gst_test_clock_wait_for_multiple_pending_ids (test_clock, 0, NULL);
637
638 worker_thread_b =
639 g_thread_new ("worker_thread_b",
640 test_wait_pending_single_shot_id_sync_worker, &context_b);
641
642 gst_test_clock_wait_for_multiple_pending_ids (test_clock, 1, NULL);
643 gst_test_clock_wait_for_next_pending_id (test_clock, &pending_id);
644 assert_pending_id (pending_id, clock_id_b, GST_CLOCK_ENTRY_SINGLE,
645 6 * GST_SECOND);
646 gst_clock_id_unref (pending_id);
647
648 worker_thread_a =
649 g_thread_new ("worker_thread_a",
650 test_wait_pending_single_shot_id_sync_worker, &context_a);
651
652 gst_test_clock_wait_for_multiple_pending_ids (test_clock, 2, NULL);
653 gst_test_clock_wait_for_next_pending_id (test_clock, &pending_id);
654 assert_pending_id (pending_id, clock_id_a, GST_CLOCK_ENTRY_SINGLE,
655 5 * GST_SECOND);
656 gst_clock_id_unref (pending_id);
657
658 g_assert_cmpuint (gst_test_clock_get_next_entry_time (test_clock), ==,
659 5 * GST_SECOND);
660 gst_test_clock_advance_time (test_clock, 5 * GST_SECOND);
661 processed_id = gst_test_clock_process_next_clock_id (test_clock);
662 assert_processed_id (processed_id, clock_id_a, GST_CLOCK_ENTRY_SINGLE,
663 GST_CLOCK_OK);
664 gst_clock_id_unref (processed_id);
665
666 gst_test_clock_wait_for_multiple_pending_ids (test_clock, 1, NULL);
667 gst_test_clock_wait_for_next_pending_id (test_clock, &pending_id);
668 assert_pending_id (pending_id, clock_id_b, GST_CLOCK_ENTRY_SINGLE,
669 6 * GST_SECOND);
670 gst_clock_id_unref (pending_id);
671
672 g_assert_cmpuint (gst_test_clock_get_next_entry_time (test_clock), ==,
673 6 * GST_SECOND);
674 gst_test_clock_advance_time (test_clock, 6 * GST_SECOND);
675 processed_id = gst_test_clock_process_next_clock_id (test_clock);
676 assert_processed_id (processed_id, clock_id_b, GST_CLOCK_ENTRY_SINGLE,
677 GST_CLOCK_OK);
678 gst_clock_id_unref (processed_id);
679
680 gst_test_clock_wait_for_multiple_pending_ids (test_clock, 0, NULL);
681
682 g_thread_join (worker_thread_a);
683 g_thread_join (worker_thread_b);
684
685 g_assert_cmpuint (context_a.jitter, ==, -4 * GST_SECOND);
686 g_assert_cmpuint (context_b.jitter, ==, -5 * GST_SECOND);
687
688 gst_clock_id_unref (context_a.clock_id);
689 gst_clock_id_unref (context_b.clock_id);
690
691 gst_clock_id_unref (clock_id_a);
692 gst_clock_id_unref (clock_id_b);
693
694 gst_object_unref (clock);
695 }
696
697 GST_END_TEST;
698
GST_START_TEST(test_processing_multiple_ids)699 GST_START_TEST (test_processing_multiple_ids)
700 {
701 GstClock *clock;
702 GstTestClock *test_clock;
703 GstClockID clock_id_a;
704 GstClockID clock_id_b;
705 SyncClockWaitContext context_a;
706 SyncClockWaitContext context_b;
707 GThread *worker_thread_a;
708 GThread *worker_thread_b;
709 GList *pending_list = NULL;
710
711 clock = gst_test_clock_new_with_start_time (GST_SECOND);
712 test_clock = GST_TEST_CLOCK (clock);
713
714 /* register a wait for 5 seconds */
715 clock_id_a = gst_clock_new_single_shot_id (clock, 5 * GST_SECOND);
716 context_a.clock_id = gst_clock_id_ref (clock_id_a);
717 context_a.jitter = 0;
718 worker_thread_a =
719 g_thread_new ("worker_thread_a",
720 test_wait_pending_single_shot_id_sync_worker, &context_a);
721
722 /* register another wait for 6 seconds */
723 clock_id_b = gst_clock_new_single_shot_id (clock, 6 * GST_SECOND);
724 context_b.clock_id = gst_clock_id_ref (clock_id_b);
725 context_b.jitter = 0;
726 worker_thread_b =
727 g_thread_new ("worker_thread_b",
728 test_wait_pending_single_shot_id_sync_worker, &context_b);
729
730 /* wait for two waits */
731 gst_test_clock_wait_for_multiple_pending_ids (test_clock, 2, &pending_list);
732
733 /* assert they are correct */
734 assert_pending_id (pending_list->data, clock_id_a, GST_CLOCK_ENTRY_SINGLE,
735 5 * GST_SECOND);
736 assert_pending_id (pending_list->next->data, clock_id_b,
737 GST_CLOCK_ENTRY_SINGLE, 6 * GST_SECOND);
738
739 /* verify we are waiting for 6 seconds as the latest time */
740 fail_unless_equals_int64 (6 * GST_SECOND,
741 gst_test_clock_id_list_get_latest_time (pending_list));
742
743 /* process both ID's at the same time */
744 gst_test_clock_process_id_list (test_clock, pending_list);
745 g_list_free_full (pending_list, (GDestroyNotify) gst_clock_id_unref);
746
747 g_thread_join (worker_thread_a);
748 g_thread_join (worker_thread_b);
749
750 fail_unless_equals_int64 (-4 * GST_SECOND, context_a.jitter);
751 fail_unless_equals_int64 (-5 * GST_SECOND, context_b.jitter);
752
753 gst_clock_id_unref (context_a.clock_id);
754 gst_clock_id_unref (context_b.clock_id);
755
756 gst_clock_id_unref (clock_id_a);
757 gst_clock_id_unref (clock_id_b);
758
759 gst_object_unref (clock);
760 }
761
762 GST_END_TEST;
763
GST_START_TEST(test_single_shot_async_past)764 GST_START_TEST (test_single_shot_async_past)
765 {
766 GstClock *clock;
767 GstClockID clock_id;
768 GstClockID processed_id;
769 gboolean wait_complete = FALSE;
770
771 clock = gst_test_clock_new_with_start_time (GST_SECOND);
772 clock_id = gst_clock_new_single_shot_id (clock, GST_SECOND - 1);
773 g_assert (gst_clock_id_wait_async (clock_id, test_async_wait_cb,
774 &wait_complete, NULL) == GST_CLOCK_OK);
775 g_assert (!wait_complete);
776 processed_id = gst_test_clock_process_next_clock_id (GST_TEST_CLOCK (clock));
777 g_assert (wait_complete);
778 assert_processed_id (processed_id, clock_id, GST_CLOCK_ENTRY_SINGLE,
779 GST_CLOCK_EARLY);
780 gst_clock_id_unref (processed_id);
781 gst_clock_id_unref (clock_id);
782 gst_object_unref (clock);
783 }
784
785 GST_END_TEST;
786
GST_START_TEST(test_single_shot_async_present)787 GST_START_TEST (test_single_shot_async_present)
788 {
789 GstClock *clock;
790 GstClockID clock_id;
791 GstClockID processed_id;
792 gboolean wait_complete = FALSE;
793
794 clock = gst_test_clock_new_with_start_time (GST_SECOND);
795 clock_id = gst_clock_new_single_shot_id (clock, GST_SECOND);
796 g_assert (gst_clock_id_wait_async (clock_id, test_async_wait_cb,
797 &wait_complete, NULL) == GST_CLOCK_OK);
798 g_assert (!wait_complete);
799 processed_id = gst_test_clock_process_next_clock_id (GST_TEST_CLOCK (clock));
800 g_assert (wait_complete);
801 assert_processed_id (processed_id, clock_id, GST_CLOCK_ENTRY_SINGLE,
802 GST_CLOCK_OK);
803 gst_clock_id_unref (processed_id);
804 gst_clock_id_unref (clock_id);
805 gst_object_unref (clock);
806 }
807
808 GST_END_TEST;
809
GST_START_TEST(test_single_shot_async_future)810 GST_START_TEST (test_single_shot_async_future)
811 {
812 GstClock *clock;
813 GstClockID clock_id;
814 GstClockID processed_id;
815 gboolean wait_complete = FALSE;
816
817 clock = gst_test_clock_new_with_start_time (GST_SECOND);
818 clock_id = gst_clock_new_single_shot_id (clock, 2 * GST_SECOND);
819 g_assert (gst_clock_id_wait_async (clock_id, test_async_wait_cb,
820 &wait_complete, NULL) == GST_CLOCK_OK);
821 processed_id = gst_test_clock_process_next_clock_id (GST_TEST_CLOCK (clock));
822 g_assert (processed_id == NULL);
823 g_assert (!wait_complete);
824 g_assert (GST_CLOCK_ENTRY_STATUS (GST_CLOCK_ENTRY (clock_id))
825 == GST_CLOCK_OK);
826
827 gst_test_clock_advance_time (GST_TEST_CLOCK (clock), GST_SECOND - 1);
828 processed_id = gst_test_clock_process_next_clock_id (GST_TEST_CLOCK (clock));
829 g_assert (processed_id == NULL);
830 g_assert (!wait_complete);
831 g_assert (GST_CLOCK_ENTRY_STATUS (GST_CLOCK_ENTRY (clock_id))
832 == GST_CLOCK_OK);
833
834 gst_test_clock_advance_time (GST_TEST_CLOCK (clock), 1);
835 processed_id = gst_test_clock_process_next_clock_id (GST_TEST_CLOCK (clock));
836 g_assert (wait_complete);
837 assert_processed_id (processed_id, clock_id, GST_CLOCK_ENTRY_SINGLE,
838 GST_CLOCK_OK);
839 gst_clock_id_unref (processed_id);
840 g_assert (GST_CLOCK_ENTRY_STATUS (GST_CLOCK_ENTRY (clock_id))
841 == GST_CLOCK_OK);
842
843 gst_clock_id_unref (clock_id);
844 gst_object_unref (clock);
845 }
846
847 GST_END_TEST;
848
GST_START_TEST(test_single_shot_async_unschedule)849 GST_START_TEST (test_single_shot_async_unschedule)
850 {
851 GstClock *clock;
852 GstClockID clock_id;
853 gboolean wait_complete = FALSE;
854
855 clock = gst_test_clock_new_with_start_time (GST_SECOND);
856
857 clock_id = gst_clock_new_single_shot_id (clock, 3 * GST_SECOND);
858 g_assert (gst_clock_id_wait_async (clock_id, test_async_wait_cb,
859 &wait_complete, NULL) == GST_CLOCK_OK);
860
861 gst_clock_id_unschedule (clock_id);
862
863 gst_test_clock_advance_time (GST_TEST_CLOCK (clock), 2 * GST_SECOND);
864 g_assert (gst_test_clock_process_next_clock_id (GST_TEST_CLOCK (clock))
865 == NULL);
866 g_assert (!wait_complete);
867
868 gst_clock_id_unref (clock_id);
869 gst_object_unref (clock);
870 }
871
872 GST_END_TEST;
873
GST_START_TEST(test_periodic_sync)874 GST_START_TEST (test_periodic_sync)
875 {
876 GstClock *clock;
877 GstTestClock *test_clock;
878 GstClockID clock_id;
879 guint i;
880 const GstClockTime interval = 4 * GST_MSECOND;
881
882 clock = gst_test_clock_new ();
883 test_clock = GST_TEST_CLOCK (clock);
884
885 clock_id = gst_clock_new_periodic_id (clock, GST_SECOND, interval);
886
887 for (i = 0; i < 3; i++) {
888 GtuClockWaitContext *wait_ctx;
889 GstClockID pending_id;
890 guint j;
891
892 wait_ctx =
893 gst_test_util_wait_for_clock_id_begin (test_clock, clock_id, NULL);
894
895 gst_test_clock_wait_for_next_pending_id (test_clock, &pending_id);
896 assert_pending_id (pending_id, clock_id, GST_CLOCK_ENTRY_PERIODIC,
897 GST_SECOND + (i * interval));
898 gst_clock_id_unref (pending_id);
899
900 for (j = 0; j < 10; j++) {
901 g_usleep (G_USEC_PER_SEC / 10 / 10);
902 g_assert (!gst_test_util_clock_wait_context_has_completed (wait_ctx));
903 }
904
905 if (i == 0)
906 gst_test_clock_advance_time (test_clock, GST_SECOND);
907 else
908 gst_test_clock_advance_time (test_clock, interval);
909
910 gst_test_util_wait_for_clock_id_end (wait_ctx);
911 }
912
913 gst_clock_id_unref (clock_id);
914 gst_object_unref (clock);
915 }
916
917 GST_END_TEST;
918
GST_START_TEST(test_periodic_async)919 GST_START_TEST (test_periodic_async)
920 {
921 GstClock *clock;
922 GstClockID clock_id;
923 GstClockID processed_id;
924 gboolean wait_complete = FALSE;
925 const GstClockTime interval = 4 * GST_MSECOND;
926
927 clock = gst_test_clock_new ();
928 clock_id = gst_clock_new_periodic_id (clock, gst_clock_get_time (clock),
929 interval);
930 g_assert (gst_clock_id_wait_async (clock_id, test_async_wait_cb,
931 &wait_complete, NULL) == GST_CLOCK_OK);
932
933 processed_id = gst_test_clock_process_next_clock_id (GST_TEST_CLOCK (clock));
934 assert_processed_id (processed_id, clock_id, GST_CLOCK_ENTRY_PERIODIC,
935 GST_CLOCK_OK);
936 gst_clock_id_unref (processed_id);
937
938 g_assert (wait_complete);
939 wait_complete = FALSE;
940
941 gst_test_clock_advance_time (GST_TEST_CLOCK (clock), interval - 1);
942 processed_id = gst_test_clock_process_next_clock_id (GST_TEST_CLOCK (clock));
943 g_assert (processed_id == NULL);
944 g_assert (!wait_complete);
945
946 gst_test_clock_advance_time (GST_TEST_CLOCK (clock), 1);
947 processed_id = gst_test_clock_process_next_clock_id (GST_TEST_CLOCK (clock));
948 assert_processed_id (processed_id, clock_id, GST_CLOCK_ENTRY_PERIODIC,
949 GST_CLOCK_OK);
950 gst_clock_id_unref (processed_id);
951 g_assert (wait_complete);
952 wait_complete = FALSE;
953
954 gst_test_clock_advance_time (GST_TEST_CLOCK (clock), interval - 1);
955 processed_id = gst_test_clock_process_next_clock_id (GST_TEST_CLOCK (clock));
956 g_assert (processed_id == NULL);
957 g_assert (!wait_complete);
958
959 gst_test_clock_advance_time (GST_TEST_CLOCK (clock), 1);
960 processed_id = gst_test_clock_process_next_clock_id (GST_TEST_CLOCK (clock));
961 assert_processed_id (processed_id, clock_id, GST_CLOCK_ENTRY_PERIODIC,
962 GST_CLOCK_OK);
963 gst_clock_id_unref (processed_id);
964 g_assert (wait_complete);
965 wait_complete = FALSE;
966
967 gst_clock_id_unref (clock_id);
968 gst_object_unref (clock);
969 }
970
971 GST_END_TEST;
972
GST_START_TEST(test_periodic_uniqueness)973 GST_START_TEST (test_periodic_uniqueness)
974 {
975 GstClock *clock;
976 GstTestClock *test_clock;
977 GstClockID clock_id;
978 guint i;
979 const GstClockTime interval = 4 * GST_MSECOND;
980
981 clock = gst_test_clock_new ();
982 test_clock = GST_TEST_CLOCK (clock);
983
984 clock_id = gst_clock_new_periodic_id (clock, 0, interval);
985
986 for (i = 0; i < 3; i++) {
987 GtuClockWaitContext *wait_ctx;
988 guint j;
989
990 wait_ctx =
991 gst_test_util_wait_for_clock_id_begin (test_clock, clock_id, NULL);
992
993 for (j = 0; j < 10; j++) {
994 g_usleep (G_USEC_PER_SEC / 10 / 10);
995 g_assert_cmpuint (gst_test_clock_peek_id_count (test_clock), ==, 1);
996 }
997
998 gst_test_clock_advance_time (test_clock, interval);
999 gst_test_util_wait_for_clock_id_end (wait_ctx);
1000 }
1001
1002 gst_clock_id_unref (clock_id);
1003 gst_object_unref (clock);
1004 }
1005
1006 GST_END_TEST;
1007
GST_START_TEST(test_crank)1008 GST_START_TEST (test_crank)
1009 {
1010 GstClock *clock;
1011 GstTestClock *test_clock;
1012 GstClockID clock_id;
1013 SyncClockWaitContext context;
1014 GThread *worker_thread;
1015
1016 clock = gst_test_clock_new_with_start_time (GST_SECOND);
1017 test_clock = GST_TEST_CLOCK (clock);
1018
1019 /* register a wait for 5 seconds */
1020 clock_id = gst_clock_new_single_shot_id (clock, 5 * GST_SECOND);
1021 context.clock_id = gst_clock_id_ref (clock_id);
1022 context.jitter = 0;
1023 worker_thread =
1024 g_thread_new ("worker_thread_a",
1025 test_wait_pending_single_shot_id_sync_worker, &context);
1026
1027 /* crank */
1028 gst_test_clock_crank (test_clock);
1029
1030 /* the clock should have advanced and the wait released */
1031 g_thread_join (worker_thread);
1032
1033 /* 4 seconds was spent waiting for the clock */
1034 fail_unless_equals_int64 (-4 * GST_SECOND, context.jitter);
1035
1036 /* and the clock is now at 5 seconds */
1037 fail_unless_equals_int64 (5 * GST_SECOND, gst_clock_get_time (clock));
1038
1039 gst_clock_id_unref (context.clock_id);
1040 gst_clock_id_unref (clock_id);
1041 gst_object_unref (clock);
1042 }
1043
1044 GST_END_TEST;
1045
1046 static Suite *
gst_test_clock_suite(void)1047 gst_test_clock_suite (void)
1048 {
1049 Suite *s = suite_create ("GstTestClock");
1050 TCase *tc_chain = tcase_create ("testclock");
1051
1052 suite_add_tcase (s, tc_chain);
1053
1054 tcase_add_test (tc_chain, test_object_flags);
1055 tcase_add_test (tc_chain, test_resolution_query);
1056 tcase_add_test (tc_chain, test_start_time);
1057 tcase_add_test (tc_chain, test_set_time);
1058 tcase_add_test (tc_chain, test_advance_time);
1059 tcase_add_test (tc_chain, test_wait_synchronous_no_timeout);
1060 tcase_add_test (tc_chain, test_wait_pending_single_shot_id);
1061 tcase_add_test (tc_chain, test_wait_pending_periodic_id);
1062 tcase_add_test (tc_chain, test_single_shot_sync_simultaneous_no_timeout);
1063 tcase_add_test (tc_chain, test_processing_multiple_ids);
1064 tcase_add_test (tc_chain, test_single_shot_sync_past);
1065 tcase_add_test (tc_chain, test_single_shot_sync_present);
1066 tcase_add_test (tc_chain, test_single_shot_sync_future);
1067 tcase_add_test (tc_chain, test_single_shot_sync_unschedule);
1068 tcase_add_test (tc_chain, test_single_shot_sync_ordering);
1069 tcase_add_test (tc_chain, test_single_shot_sync_ordering_parallel);
1070 tcase_add_test (tc_chain, test_single_shot_async_past);
1071 tcase_add_test (tc_chain, test_single_shot_async_present);
1072 tcase_add_test (tc_chain, test_single_shot_async_future);
1073 tcase_add_test (tc_chain, test_single_shot_async_unschedule);
1074 tcase_add_test (tc_chain, test_periodic_sync);
1075 tcase_add_test (tc_chain, test_periodic_async);
1076 tcase_add_test (tc_chain, test_periodic_uniqueness);
1077 tcase_add_test (tc_chain, test_crank);
1078
1079 return s;
1080 }
1081
1082 GST_CHECK_MAIN (gst_test_clock);
1083