1 /* GStreamer
2 * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3 * 2000 Wim Taymans <wtay@chello.be>
4 * 2004 Wim Taymans <wim@fluendo.com>
5 *
6 * gstclock.c: Clock subsystem for maintaining time sync
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
17 *
18 * You should have received a copy of the GNU Library General Public
19 * License along with this library; if not, write to the
20 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
22 */
23
24 /**
25 * SECTION:gstclock
26 * @title: GstClock
27 * @short_description: Abstract class for global clocks
28 * @see_also: #GstSystemClock, #GstPipeline
29 *
30 * GStreamer uses a global clock to synchronize the plugins in a pipeline.
31 * Different clock implementations are possible by implementing this abstract
32 * base class or, more conveniently, by subclassing #GstSystemClock.
33 *
34 * The #GstClock returns a monotonically increasing time with the method
35 * gst_clock_get_time(). Its accuracy and base time depend on the specific
36 * clock implementation but time is always expressed in nanoseconds. Since the
37 * baseline of the clock is undefined, the clock time returned is not
38 * meaningful in itself, what matters are the deltas between two clock times.
39 * The time returned by a clock is called the absolute time.
40 *
41 * The pipeline uses the clock to calculate the running time. Usually all
42 * renderers synchronize to the global clock using the buffer timestamps, the
43 * newsegment events and the element's base time, see #GstPipeline.
44 *
45 * A clock implementation can support periodic and single shot clock
46 * notifications both synchronous and asynchronous.
47 *
48 * One first needs to create a #GstClockID for the periodic or single shot
49 * notification using gst_clock_new_single_shot_id() or
50 * gst_clock_new_periodic_id().
51 *
52 * To perform a blocking wait for the specific time of the #GstClockID use the
53 * gst_clock_id_wait(). To receive a callback when the specific time is reached
54 * in the clock use gst_clock_id_wait_async(). Both these calls can be
55 * interrupted with the gst_clock_id_unschedule() call. If the blocking wait is
56 * unscheduled a return value of #GST_CLOCK_UNSCHEDULED is returned.
57 *
58 * Periodic callbacks scheduled async will be repeatedly called automatically
59 * until it is unscheduled. To schedule a sync periodic callback,
60 * gst_clock_id_wait() should be called repeatedly.
61 *
62 * The async callbacks can happen from any thread, either provided by the core
63 * or from a streaming thread. The application should be prepared for this.
64 *
65 * A #GstClockID that has been unscheduled cannot be used again for any wait
66 * operation, a new #GstClockID should be created and the old unscheduled one
67 * should be destroyed with gst_clock_id_unref().
68 *
69 * It is possible to perform a blocking wait on the same #GstClockID from
70 * multiple threads. However, registering the same #GstClockID for multiple
71 * async notifications is not possible, the callback will only be called for
72 * the thread registering the entry last.
73 *
74 * None of the wait operations unref the #GstClockID, the owner is responsible
75 * for unreffing the ids itself. This holds for both periodic and single shot
76 * notifications. The reason being that the owner of the #GstClockID has to
77 * keep a handle to the #GstClockID to unblock the wait on FLUSHING events or
78 * state changes and if the entry would be unreffed automatically, the handle
79 * might become invalid without any notification.
80 *
81 * These clock operations do not operate on the running time, so the callbacks
82 * will also occur when not in PLAYING state as if the clock just keeps on
83 * running. Some clocks however do not progress when the element that provided
84 * the clock is not PLAYING.
85 *
86 * When a clock has the #GST_CLOCK_FLAG_CAN_SET_MASTER flag set, it can be
87 * slaved to another #GstClock with the gst_clock_set_master(). The clock will
88 * then automatically be synchronized to this master clock by repeatedly
89 * sampling the master clock and the slave clock and recalibrating the slave
90 * clock with gst_clock_set_calibration(). This feature is mostly useful for
91 * plugins that have an internal clock but must operate with another clock
92 * selected by the #GstPipeline. They can track the offset and rate difference
93 * of their internal clock relative to the master clock by using the
94 * gst_clock_get_calibration() function.
95 *
96 * The master/slave synchronisation can be tuned with the #GstClock:timeout,
97 * #GstClock:window-size and #GstClock:window-threshold properties.
98 * The #GstClock:timeout property defines the interval to sample the master
99 * clock and run the calibration functions. #GstClock:window-size defines the
100 * number of samples to use when calibrating and #GstClock:window-threshold
101 * defines the minimum number of samples before the calibration is performed.
102 */
103
104 #include "gst_private.h"
105 #include <time.h>
106
107 #include "gstclock.h"
108 #include "gstinfo.h"
109 #include "gstutils.h"
110 #include "glib-compat-private.h"
111
112 /* #define DEBUGGING_ENABLED */
113
114 #define DEFAULT_WINDOW_SIZE 32
115 #define DEFAULT_WINDOW_THRESHOLD 4
116 #define DEFAULT_TIMEOUT GST_SECOND / 10
117
118 enum
119 {
120 PROP_0,
121 PROP_WINDOW_SIZE,
122 PROP_WINDOW_THRESHOLD,
123 PROP_TIMEOUT
124 };
125
126 enum
127 {
128 SIGNAL_SYNCED,
129 SIGNAL_LAST
130 };
131
132 #define GST_CLOCK_SLAVE_LOCK(clock) g_mutex_lock (&GST_CLOCK_CAST (clock)->priv->slave_lock)
133 #define GST_CLOCK_SLAVE_UNLOCK(clock) g_mutex_unlock (&GST_CLOCK_CAST (clock)->priv->slave_lock)
134
135 struct _GstClockPrivate
136 {
137 GMutex slave_lock; /* order: SLAVE_LOCK, OBJECT_LOCK */
138
139 GCond sync_cond;
140
141 /* with LOCK */
142 GstClockTime internal_calibration;
143 GstClockTime external_calibration;
144 GstClockTime rate_numerator;
145 GstClockTime rate_denominator;
146 GstClockTime last_time;
147
148 /* with LOCK */
149 GstClockTime resolution;
150
151 /* for master/slave clocks */
152 GstClock *master;
153
154 /* with SLAVE_LOCK */
155 gboolean filling;
156 gint window_size;
157 gint window_threshold;
158 gint time_index;
159 GstClockTime timeout;
160 GstClockTime *times;
161 GstClockTime *times_temp;
162 GstClockID clockid;
163
164 gint pre_count;
165 gint post_count;
166
167 gboolean synced;
168 };
169
170 typedef struct
171 {
172 GstClockEntry entry;
173 GWeakRef clock;
174 } GstClockEntryImpl;
175
176 #define GST_CLOCK_ENTRY_CLOCK_WEAK_REF(entry) (&((GstClockEntryImpl *)(entry))->clock)
177
178 /* seqlocks */
179 #define read_seqbegin(clock) \
180 g_atomic_int_get (&clock->priv->post_count);
181
182 static inline gboolean
read_seqretry(GstClock * clock,gint seq)183 read_seqretry (GstClock * clock, gint seq)
184 {
185 /* no retry if the seqnum did not change */
186 if (G_LIKELY (seq == g_atomic_int_get (&clock->priv->pre_count)))
187 return FALSE;
188
189 /* wait for the writer to finish and retry */
190 GST_OBJECT_LOCK (clock);
191 GST_OBJECT_UNLOCK (clock);
192 return TRUE;
193 }
194
195 #define write_seqlock(clock) \
196 G_STMT_START { \
197 GST_OBJECT_LOCK (clock); \
198 g_atomic_int_inc (&clock->priv->pre_count); \
199 } G_STMT_END;
200
201 #define write_sequnlock(clock) \
202 G_STMT_START { \
203 g_atomic_int_inc (&clock->priv->post_count); \
204 GST_OBJECT_UNLOCK (clock); \
205 } G_STMT_END;
206
207 #ifndef GST_DISABLE_GST_DEBUG
208 static const gchar *
gst_clock_return_get_name(GstClockReturn ret)209 gst_clock_return_get_name (GstClockReturn ret)
210 {
211 switch (ret) {
212 case GST_CLOCK_OK:
213 return "ok";
214 case GST_CLOCK_EARLY:
215 return "early";
216 case GST_CLOCK_UNSCHEDULED:
217 return "unscheduled";
218 case GST_CLOCK_BUSY:
219 return "busy";
220 case GST_CLOCK_BADTIME:
221 return "bad-time";
222 case GST_CLOCK_ERROR:
223 return "error";
224 case GST_CLOCK_UNSUPPORTED:
225 return "unsupported";
226 case GST_CLOCK_DONE:
227 return "done";
228 default:
229 break;
230 }
231
232 return "unknown";
233 }
234 #endif /* GST_DISABLE_GST_DEBUG */
235
236 static void gst_clock_dispose (GObject * object);
237 static void gst_clock_finalize (GObject * object);
238
239 static void gst_clock_set_property (GObject * object, guint prop_id,
240 const GValue * value, GParamSpec * pspec);
241 static void gst_clock_get_property (GObject * object, guint prop_id,
242 GValue * value, GParamSpec * pspec);
243
244 static guint gst_clock_signals[SIGNAL_LAST] = { 0 };
245
246 static GstClockID
gst_clock_entry_new(GstClock * clock,GstClockTime time,GstClockTime interval,GstClockEntryType type)247 gst_clock_entry_new (GstClock * clock, GstClockTime time,
248 GstClockTime interval, GstClockEntryType type)
249 {
250 GstClockEntry *entry;
251
252 entry = (GstClockEntry *) g_slice_new (GstClockEntryImpl);
253
254 /* FIXME: add tracer hook for struct allocations such as clock entries */
255
256 GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
257 "created entry %p, time %" GST_TIME_FORMAT, entry, GST_TIME_ARGS (time));
258
259 entry->refcount = 1;
260 #ifndef GST_REMOVE_DEPRECATED
261 #ifndef GST_DISABLE_DEPRECATED
262 entry->clock = clock;
263 #else
264 entry->_clock = clock;
265 #endif
266 #endif
267 g_weak_ref_init (GST_CLOCK_ENTRY_CLOCK_WEAK_REF (entry), clock);
268 entry->type = type;
269 entry->time = time;
270 entry->interval = interval;
271 entry->status = GST_CLOCK_OK;
272 entry->func = NULL;
273 entry->user_data = NULL;
274 entry->destroy_data = NULL;
275 entry->unscheduled = FALSE;
276 entry->woken_up = FALSE;
277
278 return (GstClockID) entry;
279 }
280
281 /* WARNING : Does not modify the refcount
282 * WARNING : Do not use if a pending clock operation is happening on that entry */
283 static gboolean
gst_clock_entry_reinit(GstClock * clock,GstClockEntry * entry,GstClockTime time,GstClockTime interval,GstClockEntryType type)284 gst_clock_entry_reinit (GstClock * clock, GstClockEntry * entry,
285 GstClockTime time, GstClockTime interval, GstClockEntryType type)
286 {
287 g_return_val_if_fail (entry->status != GST_CLOCK_BUSY, FALSE);
288 g_return_val_if_fail (gst_clock_id_uses_clock ((GstClockID) entry, clock),
289 FALSE);
290
291 entry->type = type;
292 entry->time = time;
293 entry->interval = interval;
294 entry->status = GST_CLOCK_OK;
295 entry->unscheduled = FALSE;
296 entry->woken_up = FALSE;
297
298 return TRUE;
299 }
300
301 /**
302 * gst_clock_single_shot_id_reinit:
303 * @clock: a #GstClock
304 * @id: a #GstClockID
305 * @time: The requested time.
306 *
307 * Reinitializes the provided single shot @id to the provided time. Does not
308 * modify the reference count.
309 *
310 * Returns: %TRUE if the GstClockID could be reinitialized to the provided
311 * @time, else %FALSE.
312 */
313 gboolean
gst_clock_single_shot_id_reinit(GstClock * clock,GstClockID id,GstClockTime time)314 gst_clock_single_shot_id_reinit (GstClock * clock, GstClockID id,
315 GstClockTime time)
316 {
317 return gst_clock_entry_reinit (clock, (GstClockEntry *) id, time,
318 GST_CLOCK_TIME_NONE, GST_CLOCK_ENTRY_SINGLE);
319 }
320
321 /**
322 * gst_clock_periodic_id_reinit:
323 * @clock: a #GstClock
324 * @id: a #GstClockID
325 * @start_time: the requested start time
326 * @interval: the requested interval
327 *
328 * Reinitializes the provided periodic @id to the provided start time and
329 * interval. Does not modify the reference count.
330 *
331 * Returns: %TRUE if the GstClockID could be reinitialized to the provided
332 * @time, else %FALSE.
333 */
334 gboolean
gst_clock_periodic_id_reinit(GstClock * clock,GstClockID id,GstClockTime start_time,GstClockTime interval)335 gst_clock_periodic_id_reinit (GstClock * clock, GstClockID id,
336 GstClockTime start_time, GstClockTime interval)
337 {
338 return gst_clock_entry_reinit (clock, (GstClockEntry *) id, start_time,
339 interval, GST_CLOCK_ENTRY_PERIODIC);
340 }
341
342 /**
343 * gst_clock_id_ref:
344 * @id: The #GstClockID to ref
345 *
346 * Increase the refcount of given @id.
347 *
348 * Returns: (transfer full): The same #GstClockID with increased refcount.
349 *
350 * MT safe.
351 */
352 GstClockID
gst_clock_id_ref(GstClockID id)353 gst_clock_id_ref (GstClockID id)
354 {
355 g_return_val_if_fail (id != NULL, NULL);
356
357 g_atomic_int_inc (&((GstClockEntry *) id)->refcount);
358
359 return id;
360 }
361
362 static void
_gst_clock_id_free(GstClockID id)363 _gst_clock_id_free (GstClockID id)
364 {
365 GstClockEntry *entry;
366 g_return_if_fail (id != NULL);
367
368 GST_CAT_DEBUG (GST_CAT_CLOCK, "freed entry %p", id);
369 entry = (GstClockEntry *) id;
370 if (entry->destroy_data)
371 entry->destroy_data (entry->user_data);
372
373 g_weak_ref_clear (GST_CLOCK_ENTRY_CLOCK_WEAK_REF (entry));
374
375 /* FIXME: add tracer hook for struct allocations such as clock entries */
376
377 g_slice_free (GstClockEntryImpl, (GstClockEntryImpl *) id);
378 }
379
380 /**
381 * gst_clock_id_unref:
382 * @id: (transfer full): The #GstClockID to unref
383 *
384 * Unref given @id. When the refcount reaches 0 the
385 * #GstClockID will be freed.
386 *
387 * MT safe.
388 */
389 void
gst_clock_id_unref(GstClockID id)390 gst_clock_id_unref (GstClockID id)
391 {
392 gint zero;
393
394 g_return_if_fail (id != NULL);
395
396 zero = g_atomic_int_dec_and_test (&((GstClockEntry *) id)->refcount);
397 /* if we ended up with the refcount at zero, free the id */
398 if (zero) {
399 _gst_clock_id_free (id);
400 }
401 }
402
403 /**
404 * gst_clock_new_single_shot_id:
405 * @clock: The #GstClockID to get a single shot notification from
406 * @time: the requested time
407 *
408 * Get a #GstClockID from @clock to trigger a single shot
409 * notification at the requested time. The single shot id should be
410 * unreffed after usage.
411 *
412 * Free-function: gst_clock_id_unref
413 *
414 * Returns: (transfer full): a #GstClockID that can be used to request the
415 * time notification.
416 *
417 * MT safe.
418 */
419 GstClockID
gst_clock_new_single_shot_id(GstClock * clock,GstClockTime time)420 gst_clock_new_single_shot_id (GstClock * clock, GstClockTime time)
421 {
422 g_return_val_if_fail (GST_IS_CLOCK (clock), NULL);
423
424 return gst_clock_entry_new (clock,
425 time, GST_CLOCK_TIME_NONE, GST_CLOCK_ENTRY_SINGLE);
426 }
427
428 /**
429 * gst_clock_new_periodic_id:
430 * @clock: The #GstClockID to get a periodic notification id from
431 * @start_time: the requested start time
432 * @interval: the requested interval
433 *
434 * Get an ID from @clock to trigger a periodic notification.
435 * The periodic notifications will start at time @start_time and
436 * will then be fired with the given @interval. @id should be unreffed
437 * after usage.
438 *
439 * Free-function: gst_clock_id_unref
440 *
441 * Returns: (transfer full): a #GstClockID that can be used to request the
442 * time notification.
443 *
444 * MT safe.
445 */
446 GstClockID
gst_clock_new_periodic_id(GstClock * clock,GstClockTime start_time,GstClockTime interval)447 gst_clock_new_periodic_id (GstClock * clock, GstClockTime start_time,
448 GstClockTime interval)
449 {
450 g_return_val_if_fail (GST_IS_CLOCK (clock), NULL);
451 g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (start_time), NULL);
452 g_return_val_if_fail (interval != 0, NULL);
453 g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (interval), NULL);
454
455 return gst_clock_entry_new (clock,
456 start_time, interval, GST_CLOCK_ENTRY_PERIODIC);
457 }
458
459 /**
460 * gst_clock_id_compare_func:
461 * @id1: A #GstClockID
462 * @id2: A #GstClockID to compare with
463 *
464 * Compares the two #GstClockID instances. This function can be used
465 * as a GCompareFunc when sorting ids.
466 *
467 * Returns: negative value if a < b; zero if a = b; positive value if a > b
468 *
469 * MT safe.
470 */
471 gint
gst_clock_id_compare_func(gconstpointer id1,gconstpointer id2)472 gst_clock_id_compare_func (gconstpointer id1, gconstpointer id2)
473 {
474 GstClockEntry *entry1, *entry2;
475
476 entry1 = (GstClockEntry *) id1;
477 entry2 = (GstClockEntry *) id2;
478
479 if (GST_CLOCK_ENTRY_TIME (entry1) > GST_CLOCK_ENTRY_TIME (entry2)) {
480 return 1;
481 }
482 if (GST_CLOCK_ENTRY_TIME (entry1) < GST_CLOCK_ENTRY_TIME (entry2)) {
483 return -1;
484 }
485 return 0;
486 }
487
488 /**
489 * gst_clock_id_get_time:
490 * @id: The #GstClockID to query
491 *
492 * Get the time of the clock ID
493 *
494 * Returns: the time of the given clock id.
495 *
496 * MT safe.
497 */
498 GstClockTime
gst_clock_id_get_time(GstClockID id)499 gst_clock_id_get_time (GstClockID id)
500 {
501 g_return_val_if_fail (id != NULL, GST_CLOCK_TIME_NONE);
502
503 return GST_CLOCK_ENTRY_TIME ((GstClockEntry *) id);
504 }
505
506 /**
507 * gst_clock_id_wait:
508 * @id: The #GstClockID to wait on
509 * @jitter: (out) (allow-none): a pointer that will contain the jitter,
510 * can be %NULL.
511 *
512 * Perform a blocking wait on @id.
513 * @id should have been created with gst_clock_new_single_shot_id()
514 * or gst_clock_new_periodic_id() and should not have been unscheduled
515 * with a call to gst_clock_id_unschedule().
516 *
517 * If the @jitter argument is not %NULL and this function returns #GST_CLOCK_OK
518 * or #GST_CLOCK_EARLY, it will contain the difference
519 * against the clock and the time of @id when this method was
520 * called.
521 * Positive values indicate how late @id was relative to the clock
522 * (in which case this function will return #GST_CLOCK_EARLY).
523 * Negative values indicate how much time was spent waiting on the clock
524 * before this function returned.
525 *
526 * Returns: the result of the blocking wait. #GST_CLOCK_EARLY will be returned
527 * if the current clock time is past the time of @id, #GST_CLOCK_OK if
528 * @id was scheduled in time. #GST_CLOCK_UNSCHEDULED if @id was
529 * unscheduled with gst_clock_id_unschedule().
530 *
531 * MT safe.
532 */
533 GstClockReturn
gst_clock_id_wait(GstClockID id,GstClockTimeDiff * jitter)534 gst_clock_id_wait (GstClockID id, GstClockTimeDiff * jitter)
535 {
536 GstClockEntry *entry;
537 GstClock *clock;
538 GstClockReturn res;
539 GstClockTime requested;
540 GstClockClass *cclass;
541
542 g_return_val_if_fail (id != NULL, GST_CLOCK_ERROR);
543
544 entry = (GstClockEntry *) id;
545 requested = GST_CLOCK_ENTRY_TIME (entry);
546
547 clock = g_weak_ref_get (GST_CLOCK_ENTRY_CLOCK_WEAK_REF (entry));
548 if (G_UNLIKELY (clock == NULL))
549 goto invalid_entry;
550
551 /* can't sync on invalid times */
552 if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (requested)))
553 goto invalid_time;
554
555 cclass = GST_CLOCK_GET_CLASS (clock);
556
557 GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "waiting on clock entry %p", id);
558
559 /* if we have a wait_jitter function, use that */
560 if (G_UNLIKELY (cclass->wait == NULL))
561 goto not_supported;
562
563 res = cclass->wait (clock, entry, jitter);
564
565 GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
566 "done waiting entry %p, res: %d (%s)", id, res,
567 gst_clock_return_get_name (res));
568
569 if (entry->type == GST_CLOCK_ENTRY_PERIODIC)
570 entry->time = requested + entry->interval;
571
572 gst_object_unref (clock);
573 return res;
574
575 /* ERRORS */
576 invalid_time:
577 {
578 GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
579 "invalid time requested, returning _BADTIME");
580 gst_object_unref (clock);
581 return GST_CLOCK_BADTIME;
582 }
583 not_supported:
584 {
585 GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "clock wait is not supported");
586 gst_object_unref (clock);
587 return GST_CLOCK_UNSUPPORTED;
588 }
589 invalid_entry:
590 {
591 GST_CAT_DEBUG (GST_CAT_CLOCK, "clock entry %p lost its clock", id);
592 return GST_CLOCK_ERROR;
593 }
594 }
595
596 /**
597 * gst_clock_id_wait_async:
598 * @id: a #GstClockID to wait on
599 * @func: The callback function
600 * @user_data: User data passed in the callback
601 * @destroy_data: #GDestroyNotify for user_data
602 *
603 * Register a callback on the given #GstClockID @id with the given
604 * function and user_data. When passing a #GstClockID with an invalid
605 * time to this function, the callback will be called immediately
606 * with a time set to GST_CLOCK_TIME_NONE. The callback will
607 * be called when the time of @id has been reached.
608 *
609 * The callback @func can be invoked from any thread, either provided by the
610 * core or from a streaming thread. The application should be prepared for this.
611 *
612 * Returns: the result of the non blocking wait.
613 *
614 * MT safe.
615 */
616 GstClockReturn
gst_clock_id_wait_async(GstClockID id,GstClockCallback func,gpointer user_data,GDestroyNotify destroy_data)617 gst_clock_id_wait_async (GstClockID id,
618 GstClockCallback func, gpointer user_data, GDestroyNotify destroy_data)
619 {
620 GstClockEntry *entry;
621 GstClock *clock;
622 GstClockReturn res;
623 GstClockClass *cclass;
624 GstClockTime requested;
625
626 g_return_val_if_fail (id != NULL, GST_CLOCK_ERROR);
627 g_return_val_if_fail (func != NULL, GST_CLOCK_ERROR);
628
629 entry = (GstClockEntry *) id;
630 requested = GST_CLOCK_ENTRY_TIME (entry);
631 clock = g_weak_ref_get (GST_CLOCK_ENTRY_CLOCK_WEAK_REF (entry));
632 if (G_UNLIKELY (clock == NULL))
633 goto invalid_entry;
634
635 /* can't sync on invalid times */
636 if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (requested)))
637 goto invalid_time;
638
639 cclass = GST_CLOCK_GET_CLASS (clock);
640
641 if (G_UNLIKELY (cclass->wait_async == NULL))
642 goto not_supported;
643
644 entry->func = func;
645 entry->user_data = user_data;
646 entry->destroy_data = destroy_data;
647
648 res = cclass->wait_async (clock, entry);
649
650 gst_object_unref (clock);
651 return res;
652
653 /* ERRORS */
654 invalid_time:
655 {
656 (func) (clock, GST_CLOCK_TIME_NONE, id, user_data);
657 GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
658 "invalid time requested, returning _BADTIME");
659 gst_object_unref (clock);
660 return GST_CLOCK_BADTIME;
661 }
662 not_supported:
663 {
664 GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "clock wait is not supported");
665 gst_object_unref (clock);
666 return GST_CLOCK_UNSUPPORTED;
667 }
668 invalid_entry:
669 {
670 GST_CAT_DEBUG (GST_CAT_CLOCK, "clock entry %p lost its clock", id);
671 return GST_CLOCK_ERROR;
672 }
673 }
674
675 /**
676 * gst_clock_id_unschedule:
677 * @id: The id to unschedule
678 *
679 * Cancel an outstanding request with @id. This can either
680 * be an outstanding async notification or a pending sync notification.
681 * After this call, @id cannot be used anymore to receive sync or
682 * async notifications, you need to create a new #GstClockID.
683 *
684 * MT safe.
685 */
686 void
gst_clock_id_unschedule(GstClockID id)687 gst_clock_id_unschedule (GstClockID id)
688 {
689 GstClockEntry *entry;
690 GstClock *clock;
691 GstClockClass *cclass;
692
693 g_return_if_fail (id != NULL);
694
695 entry = (GstClockEntry *) id;
696 clock = g_weak_ref_get (GST_CLOCK_ENTRY_CLOCK_WEAK_REF (entry));
697 if (G_UNLIKELY (clock == NULL))
698 goto invalid_entry;
699
700 cclass = GST_CLOCK_GET_CLASS (clock);
701
702 if (G_LIKELY (cclass->unschedule))
703 cclass->unschedule (clock, entry);
704
705 gst_object_unref (clock);
706 return;
707
708 invalid_entry:
709 {
710 GST_CAT_DEBUG (GST_CAT_CLOCK, "clock entry %p lost its clock", id);
711 return;
712 }
713 }
714
715
716 /*
717 * GstClock abstract base class implementation
718 */
719 #define gst_clock_parent_class parent_class
720 G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GstClock, gst_clock, GST_TYPE_OBJECT);
721
722 static void
gst_clock_class_init(GstClockClass * klass)723 gst_clock_class_init (GstClockClass * klass)
724 {
725 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
726
727 gobject_class->dispose = gst_clock_dispose;
728 gobject_class->finalize = gst_clock_finalize;
729 gobject_class->set_property = gst_clock_set_property;
730 gobject_class->get_property = gst_clock_get_property;
731
732 g_object_class_install_property (gobject_class, PROP_WINDOW_SIZE,
733 g_param_spec_int ("window-size", "Window size",
734 "The size of the window used to calculate rate and offset", 2, 1024,
735 DEFAULT_WINDOW_SIZE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
736 g_object_class_install_property (gobject_class, PROP_WINDOW_THRESHOLD,
737 g_param_spec_int ("window-threshold", "Window threshold",
738 "The threshold to start calculating rate and offset", 2, 1024,
739 DEFAULT_WINDOW_THRESHOLD,
740 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
741 g_object_class_install_property (gobject_class, PROP_TIMEOUT,
742 g_param_spec_uint64 ("timeout", "Timeout",
743 "The amount of time, in nanoseconds, to sample master and slave clocks",
744 0, G_MAXUINT64, DEFAULT_TIMEOUT,
745 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
746
747 /**
748 * GstClock::synced:
749 * @clock: the clock
750 * @synced: if the clock is synced now
751 *
752 * Signaled on clocks with GST_CLOCK_FLAG_NEEDS_STARTUP_SYNC set once
753 * the clock is synchronized, or when it completely lost synchronization.
754 * This signal will not be emitted on clocks without the flag.
755 *
756 * This signal will be emitted from an arbitrary thread, most likely not
757 * the application's main thread.
758 *
759 * Since: 1.6
760 */
761 gst_clock_signals[SIGNAL_SYNCED] =
762 g_signal_new ("synced", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
763 0, NULL, NULL,
764 g_cclosure_marshal_generic, G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
765 }
766
767 static void
gst_clock_init(GstClock * clock)768 gst_clock_init (GstClock * clock)
769 {
770 GstClockPrivate *priv;
771
772 clock->priv = priv = gst_clock_get_instance_private (clock);
773
774 priv->last_time = 0;
775
776 priv->internal_calibration = 0;
777 priv->external_calibration = 0;
778 priv->rate_numerator = 1;
779 priv->rate_denominator = 1;
780
781 g_mutex_init (&priv->slave_lock);
782 g_cond_init (&priv->sync_cond);
783 priv->window_size = DEFAULT_WINDOW_SIZE;
784 priv->window_threshold = DEFAULT_WINDOW_THRESHOLD;
785 priv->filling = TRUE;
786 priv->time_index = 0;
787 priv->timeout = DEFAULT_TIMEOUT;
788 priv->times = g_new0 (GstClockTime, 4 * priv->window_size);
789 priv->times_temp = priv->times + 2 * priv->window_size;
790 }
791
792 static void
gst_clock_dispose(GObject * object)793 gst_clock_dispose (GObject * object)
794 {
795 GstClock *clock = GST_CLOCK (object);
796 GstClock **master_p;
797
798 GST_OBJECT_LOCK (clock);
799 master_p = &clock->priv->master;
800 gst_object_replace ((GstObject **) master_p, NULL);
801 GST_OBJECT_UNLOCK (clock);
802
803 G_OBJECT_CLASS (parent_class)->dispose (object);
804 }
805
806 static void
gst_clock_finalize(GObject * object)807 gst_clock_finalize (GObject * object)
808 {
809 GstClock *clock = GST_CLOCK (object);
810
811 GST_CLOCK_SLAVE_LOCK (clock);
812 if (clock->priv->clockid) {
813 gst_clock_id_unschedule (clock->priv->clockid);
814 gst_clock_id_unref (clock->priv->clockid);
815 clock->priv->clockid = NULL;
816 }
817 g_free (clock->priv->times);
818 clock->priv->times = NULL;
819 clock->priv->times_temp = NULL;
820 GST_CLOCK_SLAVE_UNLOCK (clock);
821
822 g_mutex_clear (&clock->priv->slave_lock);
823 g_cond_clear (&clock->priv->sync_cond);
824
825 G_OBJECT_CLASS (parent_class)->finalize (object);
826 }
827
828 /**
829 * gst_clock_set_resolution:
830 * @clock: a #GstClock
831 * @resolution: The resolution to set
832 *
833 * Set the accuracy of the clock. Some clocks have the possibility to operate
834 * with different accuracy at the expense of more resource usage. There is
835 * normally no need to change the default resolution of a clock. The resolution
836 * of a clock can only be changed if the clock has the
837 * #GST_CLOCK_FLAG_CAN_SET_RESOLUTION flag set.
838 *
839 * Returns: the new resolution of the clock.
840 */
841 GstClockTime
gst_clock_set_resolution(GstClock * clock,GstClockTime resolution)842 gst_clock_set_resolution (GstClock * clock, GstClockTime resolution)
843 {
844 GstClockPrivate *priv;
845 GstClockClass *cclass;
846
847 g_return_val_if_fail (GST_IS_CLOCK (clock), 0);
848 g_return_val_if_fail (resolution != 0, 0);
849
850 cclass = GST_CLOCK_GET_CLASS (clock);
851 priv = clock->priv;
852
853 if (cclass->change_resolution)
854 priv->resolution =
855 cclass->change_resolution (clock, priv->resolution, resolution);
856
857 return priv->resolution;
858 }
859
860 /**
861 * gst_clock_get_resolution:
862 * @clock: a #GstClock
863 *
864 * Get the accuracy of the clock. The accuracy of the clock is the granularity
865 * of the values returned by gst_clock_get_time().
866 *
867 * Returns: the resolution of the clock in units of #GstClockTime.
868 *
869 * MT safe.
870 */
871 GstClockTime
gst_clock_get_resolution(GstClock * clock)872 gst_clock_get_resolution (GstClock * clock)
873 {
874 GstClockClass *cclass;
875
876 g_return_val_if_fail (GST_IS_CLOCK (clock), 0);
877
878 cclass = GST_CLOCK_GET_CLASS (clock);
879
880 if (cclass->get_resolution)
881 return cclass->get_resolution (clock);
882
883 return 1;
884 }
885
886 /* FIXME 2.0: Remove clock parameter below */
887 /**
888 * gst_clock_adjust_with_calibration:
889 * @clock: (allow-none): a #GstClock to use
890 * @internal_target: a clock time
891 * @cinternal: a reference internal time
892 * @cexternal: a reference external time
893 * @cnum: the numerator of the rate of the clock relative to its
894 * internal time
895 * @cdenom: the denominator of the rate of the clock
896 *
897 * Converts the given @internal_target clock time to the external time,
898 * using the passed calibration parameters. This function performs the
899 * same calculation as gst_clock_adjust_unlocked() when called using the
900 * current calibration parameters, but doesn't ensure a monotonically
901 * increasing result as gst_clock_adjust_unlocked() does.
902 *
903 * Note: The @clock parameter is unused and can be NULL
904 *
905 * Returns: the converted time of the clock.
906 *
907 * Since: 1.6
908 */
909 GstClockTime
gst_clock_adjust_with_calibration(GstClock * clock,GstClockTime internal_target,GstClockTime cinternal,GstClockTime cexternal,GstClockTime cnum,GstClockTime cdenom)910 gst_clock_adjust_with_calibration (GstClock * clock,
911 GstClockTime internal_target, GstClockTime cinternal,
912 GstClockTime cexternal, GstClockTime cnum, GstClockTime cdenom)
913 {
914 GstClockTime ret;
915
916 /* avoid divide by 0 */
917 if (G_UNLIKELY (cdenom == 0))
918 cnum = cdenom = 1;
919
920 /* The formula is (internal - cinternal) * cnum / cdenom + cexternal
921 *
922 * Since we do math on unsigned 64-bit ints we have to special case for
923 * internal < cinternal to get the sign right. this case is not very common,
924 * though.
925 */
926 if (G_LIKELY (internal_target >= cinternal)) {
927 ret = internal_target - cinternal;
928 ret = gst_util_uint64_scale (ret, cnum, cdenom);
929 ret += cexternal;
930 } else {
931 ret = cinternal - internal_target;
932 ret = gst_util_uint64_scale (ret, cnum, cdenom);
933 /* clamp to 0 */
934 if (G_LIKELY (cexternal > ret))
935 ret = cexternal - ret;
936 else
937 ret = 0;
938 }
939
940 return ret;
941 }
942
943 /**
944 * gst_clock_adjust_unlocked:
945 * @clock: a #GstClock to use
946 * @internal: a clock time
947 *
948 * Converts the given @internal clock time to the external time, adjusting for the
949 * rate and reference time set with gst_clock_set_calibration() and making sure
950 * that the returned time is increasing. This function should be called with the
951 * clock's OBJECT_LOCK held and is mainly used by clock subclasses.
952 *
953 * This function is the reverse of gst_clock_unadjust_unlocked().
954 *
955 * Returns: the converted time of the clock.
956 */
957 GstClockTime
gst_clock_adjust_unlocked(GstClock * clock,GstClockTime internal)958 gst_clock_adjust_unlocked (GstClock * clock, GstClockTime internal)
959 {
960 GstClockTime ret, cinternal, cexternal, cnum, cdenom;
961 GstClockPrivate *priv = clock->priv;
962
963 /* get calibration values for readability */
964 cinternal = priv->internal_calibration;
965 cexternal = priv->external_calibration;
966 cnum = priv->rate_numerator;
967 cdenom = priv->rate_denominator;
968
969 ret =
970 gst_clock_adjust_with_calibration (clock, internal, cinternal, cexternal,
971 cnum, cdenom);
972
973 /* make sure the time is increasing */
974 priv->last_time = MAX (ret, priv->last_time);
975
976 return priv->last_time;
977 }
978
979 /* FIXME 2.0: Remove clock parameter below */
980 /**
981 * gst_clock_unadjust_with_calibration:
982 * @clock: (allow-none): a #GstClock to use
983 * @external_target: a clock time
984 * @cinternal: a reference internal time
985 * @cexternal: a reference external time
986 * @cnum: the numerator of the rate of the clock relative to its
987 * internal time
988 * @cdenom: the denominator of the rate of the clock
989 *
990 * Converts the given @external_target clock time to the internal time,
991 * using the passed calibration parameters. This function performs the
992 * same calculation as gst_clock_unadjust_unlocked() when called using the
993 * current calibration parameters.
994 *
995 * Note: The @clock parameter is unused and can be NULL
996 *
997 * Returns: the converted time of the clock.
998 *
999 * Since: 1.8
1000 */
1001 GstClockTime
gst_clock_unadjust_with_calibration(GstClock * clock,GstClockTime external_target,GstClockTime cinternal,GstClockTime cexternal,GstClockTime cnum,GstClockTime cdenom)1002 gst_clock_unadjust_with_calibration (GstClock * clock,
1003 GstClockTime external_target, GstClockTime cinternal,
1004 GstClockTime cexternal, GstClockTime cnum, GstClockTime cdenom)
1005 {
1006 GstClockTime ret;
1007
1008 /* avoid divide by 0 */
1009 if (G_UNLIKELY (cnum == 0))
1010 cnum = cdenom = 1;
1011
1012 /* The formula is (external - cexternal) * cdenom / cnum + cinternal */
1013 if (G_LIKELY (external_target >= cexternal)) {
1014 ret = external_target - cexternal;
1015 ret = gst_util_uint64_scale (ret, cdenom, cnum);
1016 ret += cinternal;
1017 } else {
1018 ret = cexternal - external_target;
1019 ret = gst_util_uint64_scale (ret, cdenom, cnum);
1020 if (G_LIKELY (cinternal > ret))
1021 ret = cinternal - ret;
1022 else
1023 ret = 0;
1024 }
1025
1026 return ret;
1027 }
1028
1029 /**
1030 * gst_clock_unadjust_unlocked:
1031 * @clock: a #GstClock to use
1032 * @external: an external clock time
1033 *
1034 * Converts the given @external clock time to the internal time of @clock,
1035 * using the rate and reference time set with gst_clock_set_calibration().
1036 * This function should be called with the clock's OBJECT_LOCK held and
1037 * is mainly used by clock subclasses.
1038 *
1039 * This function is the reverse of gst_clock_adjust_unlocked().
1040 *
1041 * Returns: the internal time of the clock corresponding to @external.
1042 */
1043 GstClockTime
gst_clock_unadjust_unlocked(GstClock * clock,GstClockTime external)1044 gst_clock_unadjust_unlocked (GstClock * clock, GstClockTime external)
1045 {
1046 GstClockTime cinternal, cexternal, cnum, cdenom;
1047 GstClockPrivate *priv = clock->priv;
1048
1049 /* get calibration values for readability */
1050 cinternal = priv->internal_calibration;
1051 cexternal = priv->external_calibration;
1052 cnum = priv->rate_numerator;
1053 cdenom = priv->rate_denominator;
1054
1055 return gst_clock_unadjust_with_calibration (clock, external, cinternal,
1056 cexternal, cnum, cdenom);
1057 }
1058
1059 /**
1060 * gst_clock_get_internal_time:
1061 * @clock: a #GstClock to query
1062 *
1063 * Gets the current internal time of the given clock. The time is returned
1064 * unadjusted for the offset and the rate.
1065 *
1066 * Returns: the internal time of the clock. Or GST_CLOCK_TIME_NONE when
1067 * given invalid input.
1068 *
1069 * MT safe.
1070 */
1071 GstClockTime
gst_clock_get_internal_time(GstClock * clock)1072 gst_clock_get_internal_time (GstClock * clock)
1073 {
1074 GstClockTime ret;
1075 GstClockClass *cclass;
1076
1077 g_return_val_if_fail (GST_IS_CLOCK (clock), GST_CLOCK_TIME_NONE);
1078
1079 if (G_UNLIKELY (GST_OBJECT_FLAG_IS_SET (clock,
1080 GST_CLOCK_FLAG_NEEDS_STARTUP_SYNC) && !clock->priv->synced))
1081 GST_CAT_WARNING_OBJECT (GST_CAT_CLOCK, clock,
1082 "clock is not synchronized yet");
1083
1084 cclass = GST_CLOCK_GET_CLASS (clock);
1085
1086 if (G_UNLIKELY (cclass->get_internal_time == NULL))
1087 goto not_supported;
1088
1089 ret = cclass->get_internal_time (clock);
1090
1091 GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "internal time %" GST_TIME_FORMAT,
1092 GST_TIME_ARGS (ret));
1093
1094 return ret;
1095
1096 /* ERRORS */
1097 not_supported:
1098 {
1099 GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
1100 "internal time not supported, return 0");
1101 return G_GINT64_CONSTANT (0);
1102 }
1103 }
1104
1105 /**
1106 * gst_clock_get_time:
1107 * @clock: a #GstClock to query
1108 *
1109 * Gets the current time of the given clock. The time is always
1110 * monotonically increasing and adjusted according to the current
1111 * offset and rate.
1112 *
1113 * Returns: the time of the clock. Or GST_CLOCK_TIME_NONE when
1114 * given invalid input.
1115 *
1116 * MT safe.
1117 */
1118 GstClockTime
gst_clock_get_time(GstClock * clock)1119 gst_clock_get_time (GstClock * clock)
1120 {
1121 GstClockTime ret;
1122 gint seq;
1123
1124 g_return_val_if_fail (GST_IS_CLOCK (clock), GST_CLOCK_TIME_NONE);
1125
1126 do {
1127 /* reget the internal time when we retry to get the most current
1128 * timevalue */
1129 ret = gst_clock_get_internal_time (clock);
1130
1131 seq = read_seqbegin (clock);
1132 /* this will scale for rate and offset */
1133 ret = gst_clock_adjust_unlocked (clock, ret);
1134 } while (read_seqretry (clock, seq));
1135
1136 GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "adjusted time %" GST_TIME_FORMAT,
1137 GST_TIME_ARGS (ret));
1138
1139 return ret;
1140 }
1141
1142 /**
1143 * gst_clock_set_calibration:
1144 * @clock: a #GstClock to calibrate
1145 * @internal: a reference internal time
1146 * @external: a reference external time
1147 * @rate_num: the numerator of the rate of the clock relative to its
1148 * internal time
1149 * @rate_denom: the denominator of the rate of the clock
1150 *
1151 * Adjusts the rate and time of @clock. A rate of 1/1 is the normal speed of
1152 * the clock. Values bigger than 1/1 make the clock go faster.
1153 *
1154 * @internal and @external are calibration parameters that arrange that
1155 * gst_clock_get_time() should have been @external at internal time @internal.
1156 * This internal time should not be in the future; that is, it should be less
1157 * than the value of gst_clock_get_internal_time() when this function is called.
1158 *
1159 * Subsequent calls to gst_clock_get_time() will return clock times computed as
1160 * follows:
1161 *
1162 * |[
1163 * time = (internal_time - internal) * rate_num / rate_denom + external
1164 * ]|
1165 *
1166 * This formula is implemented in gst_clock_adjust_unlocked(). Of course, it
1167 * tries to do the integer arithmetic as precisely as possible.
1168 *
1169 * Note that gst_clock_get_time() always returns increasing values so when you
1170 * move the clock backwards, gst_clock_get_time() will report the previous value
1171 * until the clock catches up.
1172 *
1173 * MT safe.
1174 */
1175 void
gst_clock_set_calibration(GstClock * clock,GstClockTime internal,GstClockTime external,GstClockTime rate_num,GstClockTime rate_denom)1176 gst_clock_set_calibration (GstClock * clock, GstClockTime internal, GstClockTime
1177 external, GstClockTime rate_num, GstClockTime rate_denom)
1178 {
1179 GstClockPrivate *priv;
1180
1181 g_return_if_fail (GST_IS_CLOCK (clock));
1182 g_return_if_fail (rate_num != GST_CLOCK_TIME_NONE);
1183 g_return_if_fail (rate_denom > 0 && rate_denom != GST_CLOCK_TIME_NONE);
1184
1185 priv = clock->priv;
1186
1187 write_seqlock (clock);
1188 GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
1189 "internal %" GST_TIME_FORMAT " external %" GST_TIME_FORMAT " %"
1190 G_GUINT64_FORMAT "/%" G_GUINT64_FORMAT " = %f", GST_TIME_ARGS (internal),
1191 GST_TIME_ARGS (external), rate_num, rate_denom,
1192 gst_guint64_to_gdouble (rate_num) / gst_guint64_to_gdouble (rate_denom));
1193
1194 priv->internal_calibration = internal;
1195 priv->external_calibration = external;
1196 priv->rate_numerator = rate_num;
1197 priv->rate_denominator = rate_denom;
1198 write_sequnlock (clock);
1199 }
1200
1201 /**
1202 * gst_clock_get_calibration:
1203 * @clock: a #GstClock
1204 * @internal: (out) (allow-none): a location to store the internal time
1205 * @external: (out) (allow-none): a location to store the external time
1206 * @rate_num: (out) (allow-none): a location to store the rate numerator
1207 * @rate_denom: (out) (allow-none): a location to store the rate denominator
1208 *
1209 * Gets the internal rate and reference time of @clock. See
1210 * gst_clock_set_calibration() for more information.
1211 *
1212 * @internal, @external, @rate_num, and @rate_denom can be left %NULL if the
1213 * caller is not interested in the values.
1214 *
1215 * MT safe.
1216 */
1217 void
gst_clock_get_calibration(GstClock * clock,GstClockTime * internal,GstClockTime * external,GstClockTime * rate_num,GstClockTime * rate_denom)1218 gst_clock_get_calibration (GstClock * clock, GstClockTime * internal,
1219 GstClockTime * external, GstClockTime * rate_num, GstClockTime * rate_denom)
1220 {
1221 gint seq;
1222 GstClockPrivate *priv;
1223
1224 g_return_if_fail (GST_IS_CLOCK (clock));
1225
1226 priv = clock->priv;
1227
1228 do {
1229 seq = read_seqbegin (clock);
1230 if (rate_num)
1231 *rate_num = priv->rate_numerator;
1232 if (rate_denom)
1233 *rate_denom = priv->rate_denominator;
1234 if (external)
1235 *external = priv->external_calibration;
1236 if (internal)
1237 *internal = priv->internal_calibration;
1238 } while (read_seqretry (clock, seq));
1239 }
1240
1241 /* will be called repeatedly to sample the master and slave clock
1242 * to recalibrate the clock */
1243 static gboolean
gst_clock_slave_callback(GstClock * master,GstClockTime time,GstClockID id,GstClock * clock)1244 gst_clock_slave_callback (GstClock * master, GstClockTime time,
1245 GstClockID id, GstClock * clock)
1246 {
1247 GstClockTime stime, mtime;
1248 gdouble r_squared;
1249
1250 if (!gst_clock_is_synced (clock)) {
1251 GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
1252 "Slave clock is not synced yet");
1253 return TRUE;
1254 }
1255
1256 stime = gst_clock_get_internal_time (clock);
1257 mtime = gst_clock_get_time (master);
1258
1259 GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
1260 "master %" GST_TIME_FORMAT ", slave %" GST_TIME_FORMAT,
1261 GST_TIME_ARGS (mtime), GST_TIME_ARGS (stime));
1262
1263 gst_clock_add_observation (clock, stime, mtime, &r_squared);
1264
1265 /* FIXME, we can use the r_squared value to adjust the timeout
1266 * value of the clockid */
1267
1268 return TRUE;
1269 }
1270
1271 /**
1272 * gst_clock_set_master:
1273 * @clock: a #GstClock
1274 * @master: (allow-none): a master #GstClock
1275 *
1276 * Set @master as the master clock for @clock. @clock will be automatically
1277 * calibrated so that gst_clock_get_time() reports the same time as the
1278 * master clock.
1279 *
1280 * A clock provider that slaves its clock to a master can get the current
1281 * calibration values with gst_clock_get_calibration().
1282 *
1283 * @master can be %NULL in which case @clock will not be slaved anymore. It will
1284 * however keep reporting its time adjusted with the last configured rate
1285 * and time offsets.
1286 *
1287 * Returns: %TRUE if the clock is capable of being slaved to a master clock.
1288 * Trying to set a master on a clock without the
1289 * #GST_CLOCK_FLAG_CAN_SET_MASTER flag will make this function return %FALSE.
1290 *
1291 * MT safe.
1292 */
1293 gboolean
gst_clock_set_master(GstClock * clock,GstClock * master)1294 gst_clock_set_master (GstClock * clock, GstClock * master)
1295 {
1296 GstClock **master_p;
1297 GstClockPrivate *priv;
1298
1299 g_return_val_if_fail (GST_IS_CLOCK (clock), FALSE);
1300 g_return_val_if_fail (master != clock, FALSE);
1301
1302 GST_OBJECT_LOCK (clock);
1303 /* we always allow setting the master to NULL */
1304 if (master && !GST_OBJECT_FLAG_IS_SET (clock, GST_CLOCK_FLAG_CAN_SET_MASTER))
1305 goto not_supported;
1306 if (master && !gst_clock_is_synced (master))
1307 goto master_not_synced;
1308
1309 GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
1310 "slaving %p to master clock %p", clock, master);
1311 GST_OBJECT_UNLOCK (clock);
1312
1313 priv = clock->priv;
1314
1315 GST_CLOCK_SLAVE_LOCK (clock);
1316 if (priv->clockid) {
1317 gst_clock_id_unschedule (priv->clockid);
1318 gst_clock_id_unref (priv->clockid);
1319 priv->clockid = NULL;
1320 }
1321 if (master) {
1322 priv->filling = TRUE;
1323 priv->time_index = 0;
1324 /* use the master periodic id to schedule sampling and
1325 * clock calibration. */
1326 priv->clockid = gst_clock_new_periodic_id (master,
1327 gst_clock_get_time (master), priv->timeout);
1328 gst_clock_id_wait_async (priv->clockid,
1329 (GstClockCallback) gst_clock_slave_callback,
1330 gst_object_ref (clock), (GDestroyNotify) gst_object_unref);
1331 }
1332 GST_CLOCK_SLAVE_UNLOCK (clock);
1333
1334 GST_OBJECT_LOCK (clock);
1335 master_p = &priv->master;
1336 gst_object_replace ((GstObject **) master_p, (GstObject *) master);
1337 GST_OBJECT_UNLOCK (clock);
1338
1339 return TRUE;
1340
1341 /* ERRORS */
1342 not_supported:
1343 {
1344 GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
1345 "cannot be slaved to a master clock");
1346 GST_OBJECT_UNLOCK (clock);
1347 return FALSE;
1348 }
1349
1350 master_not_synced:
1351 {
1352 GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, master,
1353 "master clock is not synced yet");
1354 GST_OBJECT_UNLOCK (clock);
1355 return FALSE;
1356 }
1357 }
1358
1359 /**
1360 * gst_clock_get_master:
1361 * @clock: a #GstClock
1362 *
1363 * Get the master clock that @clock is slaved to or %NULL when the clock is
1364 * not slaved to any master clock.
1365 *
1366 * Returns: (transfer full) (nullable): a master #GstClock or %NULL
1367 * when this clock is not slaved to a master clock. Unref after
1368 * usage.
1369 *
1370 * MT safe.
1371 */
1372 GstClock *
gst_clock_get_master(GstClock * clock)1373 gst_clock_get_master (GstClock * clock)
1374 {
1375 GstClock *result = NULL;
1376 GstClockPrivate *priv;
1377
1378 g_return_val_if_fail (GST_IS_CLOCK (clock), NULL);
1379
1380 priv = clock->priv;
1381
1382 GST_OBJECT_LOCK (clock);
1383 if (priv->master)
1384 result = gst_object_ref (priv->master);
1385 GST_OBJECT_UNLOCK (clock);
1386
1387 return result;
1388 }
1389
1390 /**
1391 * gst_clock_id_get_clock:
1392 * @id: a #GstClockID
1393 *
1394 * This function returns the underlying clock.
1395 *
1396 * Returns: (transfer full) (nullable): a #GstClock or %NULL when the
1397 * underlying clock has been freed. Unref after usage.
1398 *
1399 * MT safe.
1400 *
1401 * Since: 1.16
1402 */
1403 GstClock *
gst_clock_id_get_clock(GstClockID id)1404 gst_clock_id_get_clock (GstClockID id)
1405 {
1406 GstClockEntry *entry;
1407
1408 g_return_val_if_fail (id != NULL, NULL);
1409
1410 entry = (GstClockEntry *) id;
1411 return g_weak_ref_get (GST_CLOCK_ENTRY_CLOCK_WEAK_REF (entry));
1412 }
1413
1414 /**
1415 * gst_clock_id_uses_clock:
1416 * @id: a #GstClockID to check
1417 * @clock: a #GstClock to compare against
1418 *
1419 * This function returns whether @id uses @clock as the underlying clock.
1420 * @clock can be NULL, in which case the return value indicates whether
1421 * the underlying clock has been freed. If this is the case, the @id is
1422 * no longer usable and should be freed.
1423 *
1424 * Returns: whether the clock @id uses the same underlying #GstClock @clock.
1425 *
1426 * MT safe.
1427 *
1428 * Since: 1.16
1429 */
1430 gboolean
gst_clock_id_uses_clock(GstClockID id,GstClock * clock)1431 gst_clock_id_uses_clock (GstClockID id, GstClock * clock)
1432 {
1433 GstClockEntry *entry;
1434 GstClock *entry_clock;
1435 gboolean ret = FALSE;
1436
1437 g_return_val_if_fail (id != NULL, FALSE);
1438 g_return_val_if_fail (clock != NULL, FALSE);
1439
1440 entry = (GstClockEntry *) id;
1441 entry_clock = g_weak_ref_get (GST_CLOCK_ENTRY_CLOCK_WEAK_REF (entry));
1442 if (entry_clock == clock)
1443 ret = TRUE;
1444
1445 if (G_LIKELY (entry_clock != NULL))
1446 gst_object_unref (entry_clock);
1447
1448 return ret;
1449 }
1450
1451
1452 /**
1453 * gst_clock_add_observation:
1454 * @clock: a #GstClock
1455 * @slave: a time on the slave
1456 * @master: a time on the master
1457 * @r_squared: (out): a pointer to hold the result
1458 *
1459 * The time @master of the master clock and the time @slave of the slave
1460 * clock are added to the list of observations. If enough observations
1461 * are available, a linear regression algorithm is run on the
1462 * observations and @clock is recalibrated.
1463 *
1464 * If this functions returns %TRUE, @r_squared will contain the
1465 * correlation coefficient of the interpolation. A value of 1.0
1466 * means a perfect regression was performed. This value can
1467 * be used to control the sampling frequency of the master and slave
1468 * clocks.
1469 *
1470 * Returns: %TRUE if enough observations were added to run the
1471 * regression algorithm.
1472 *
1473 * MT safe.
1474 */
1475 gboolean
gst_clock_add_observation(GstClock * clock,GstClockTime slave,GstClockTime master,gdouble * r_squared)1476 gst_clock_add_observation (GstClock * clock, GstClockTime slave,
1477 GstClockTime master, gdouble * r_squared)
1478 {
1479 GstClockTime m_num, m_denom, b, xbase;
1480
1481 if (!gst_clock_add_observation_unapplied (clock, slave, master, r_squared,
1482 &xbase, &b, &m_num, &m_denom))
1483 return FALSE;
1484
1485 /* if we have a valid regression, adjust the clock */
1486 gst_clock_set_calibration (clock, xbase, b, m_num, m_denom);
1487
1488 return TRUE;
1489 }
1490
1491 /**
1492 * gst_clock_add_observation_unapplied:
1493 * @clock: a #GstClock
1494 * @slave: a time on the slave
1495 * @master: a time on the master
1496 * @r_squared: (out): a pointer to hold the result
1497 * @internal: (out) (allow-none): a location to store the internal time
1498 * @external: (out) (allow-none): a location to store the external time
1499 * @rate_num: (out) (allow-none): a location to store the rate numerator
1500 * @rate_denom: (out) (allow-none): a location to store the rate denominator
1501 *
1502 * Add a clock observation to the internal slaving algorithm the same as
1503 * gst_clock_add_observation(), and return the result of the master clock
1504 * estimation, without updating the internal calibration.
1505 *
1506 * The caller can then take the results and call gst_clock_set_calibration()
1507 * with the values, or some modified version of them.
1508 *
1509 * Since: 1.6
1510 */
1511 gboolean
gst_clock_add_observation_unapplied(GstClock * clock,GstClockTime slave,GstClockTime master,gdouble * r_squared,GstClockTime * internal,GstClockTime * external,GstClockTime * rate_num,GstClockTime * rate_denom)1512 gst_clock_add_observation_unapplied (GstClock * clock, GstClockTime slave,
1513 GstClockTime master, gdouble * r_squared,
1514 GstClockTime * internal, GstClockTime * external,
1515 GstClockTime * rate_num, GstClockTime * rate_denom)
1516 {
1517 GstClockTime m_num, m_denom, b, xbase;
1518 GstClockPrivate *priv;
1519 guint n;
1520
1521 g_return_val_if_fail (GST_IS_CLOCK (clock), FALSE);
1522 g_return_val_if_fail (r_squared != NULL, FALSE);
1523
1524 priv = clock->priv;
1525
1526 GST_CLOCK_SLAVE_LOCK (clock);
1527
1528 GST_CAT_LOG_OBJECT (GST_CAT_CLOCK, clock,
1529 "adding observation slave %" GST_TIME_FORMAT ", master %" GST_TIME_FORMAT,
1530 GST_TIME_ARGS (slave), GST_TIME_ARGS (master));
1531
1532 priv->times[(2 * priv->time_index)] = slave;
1533 priv->times[(2 * priv->time_index) + 1] = master;
1534
1535 priv->time_index++;
1536 if (G_UNLIKELY (priv->time_index == priv->window_size)) {
1537 priv->filling = FALSE;
1538 priv->time_index = 0;
1539 }
1540
1541 if (G_UNLIKELY (priv->filling && priv->time_index < priv->window_threshold))
1542 goto filling;
1543
1544 n = priv->filling ? priv->time_index : priv->window_size;
1545 if (!gst_calculate_linear_regression (priv->times, priv->times_temp, n,
1546 &m_num, &m_denom, &b, &xbase, r_squared))
1547 goto invalid;
1548
1549 GST_CLOCK_SLAVE_UNLOCK (clock);
1550
1551 GST_CAT_LOG_OBJECT (GST_CAT_CLOCK, clock,
1552 "adjusting clock to m=%" G_GUINT64_FORMAT "/%" G_GUINT64_FORMAT ", b=%"
1553 G_GUINT64_FORMAT " (rsquared=%g)", m_num, m_denom, b, *r_squared);
1554
1555 if (internal)
1556 *internal = xbase;
1557 if (external)
1558 *external = b;
1559 if (rate_num)
1560 *rate_num = m_num;
1561 if (rate_denom)
1562 *rate_denom = m_denom;
1563
1564 return TRUE;
1565
1566 filling:
1567 {
1568 GST_CLOCK_SLAVE_UNLOCK (clock);
1569 return FALSE;
1570 }
1571 invalid:
1572 {
1573 /* no valid regression has been done, ignore the result then */
1574 GST_CLOCK_SLAVE_UNLOCK (clock);
1575 return FALSE;
1576 }
1577 }
1578
1579 /**
1580 * gst_clock_set_timeout:
1581 * @clock: a #GstClock
1582 * @timeout: a timeout
1583 *
1584 * Set the amount of time, in nanoseconds, to sample master and slave
1585 * clocks
1586 */
1587 void
gst_clock_set_timeout(GstClock * clock,GstClockTime timeout)1588 gst_clock_set_timeout (GstClock * clock, GstClockTime timeout)
1589 {
1590 g_return_if_fail (GST_IS_CLOCK (clock));
1591
1592 GST_CLOCK_SLAVE_LOCK (clock);
1593 clock->priv->timeout = timeout;
1594 GST_CLOCK_SLAVE_UNLOCK (clock);
1595 }
1596
1597 /**
1598 * gst_clock_get_timeout:
1599 * @clock: a #GstClock
1600 *
1601 * Get the amount of time that master and slave clocks are sampled.
1602 *
1603 * Returns: the interval between samples.
1604 */
1605 GstClockTime
gst_clock_get_timeout(GstClock * clock)1606 gst_clock_get_timeout (GstClock * clock)
1607 {
1608 GstClockTime result;
1609
1610 g_return_val_if_fail (GST_IS_CLOCK (clock), GST_CLOCK_TIME_NONE);
1611
1612 GST_CLOCK_SLAVE_LOCK (clock);
1613 result = clock->priv->timeout;
1614 GST_CLOCK_SLAVE_UNLOCK (clock);
1615
1616 return result;
1617 }
1618
1619 static void
gst_clock_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)1620 gst_clock_set_property (GObject * object, guint prop_id,
1621 const GValue * value, GParamSpec * pspec)
1622 {
1623 GstClock *clock;
1624 GstClockPrivate *priv;
1625
1626 clock = GST_CLOCK (object);
1627 priv = clock->priv;
1628
1629 switch (prop_id) {
1630 case PROP_WINDOW_SIZE:
1631 GST_CLOCK_SLAVE_LOCK (clock);
1632 priv->window_size = g_value_get_int (value);
1633 priv->window_threshold = MIN (priv->window_threshold, priv->window_size);
1634 priv->times = g_renew (GstClockTime, priv->times, 4 * priv->window_size);
1635 priv->times_temp = priv->times + 2 * priv->window_size;
1636 /* restart calibration */
1637 priv->filling = TRUE;
1638 priv->time_index = 0;
1639 GST_CLOCK_SLAVE_UNLOCK (clock);
1640 break;
1641 case PROP_WINDOW_THRESHOLD:
1642 GST_CLOCK_SLAVE_LOCK (clock);
1643 priv->window_threshold = MIN (g_value_get_int (value), priv->window_size);
1644 GST_CLOCK_SLAVE_UNLOCK (clock);
1645 break;
1646 case PROP_TIMEOUT:
1647 gst_clock_set_timeout (clock, g_value_get_uint64 (value));
1648 break;
1649 default:
1650 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1651 break;
1652 }
1653 }
1654
1655 static void
gst_clock_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)1656 gst_clock_get_property (GObject * object, guint prop_id,
1657 GValue * value, GParamSpec * pspec)
1658 {
1659 GstClock *clock;
1660 GstClockPrivate *priv;
1661
1662 clock = GST_CLOCK (object);
1663 priv = clock->priv;
1664
1665 switch (prop_id) {
1666 case PROP_WINDOW_SIZE:
1667 GST_CLOCK_SLAVE_LOCK (clock);
1668 g_value_set_int (value, priv->window_size);
1669 GST_CLOCK_SLAVE_UNLOCK (clock);
1670 break;
1671 case PROP_WINDOW_THRESHOLD:
1672 GST_CLOCK_SLAVE_LOCK (clock);
1673 g_value_set_int (value, priv->window_threshold);
1674 GST_CLOCK_SLAVE_UNLOCK (clock);
1675 break;
1676 case PROP_TIMEOUT:
1677 g_value_set_uint64 (value, gst_clock_get_timeout (clock));
1678 break;
1679 default:
1680 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1681 break;
1682 }
1683 }
1684
1685
1686 /**
1687 * gst_clock_wait_for_sync:
1688 * @clock: a GstClock
1689 * @timeout: timeout for waiting or %GST_CLOCK_TIME_NONE
1690 *
1691 * Waits until @clock is synced for reporting the current time. If @timeout
1692 * is %GST_CLOCK_TIME_NONE it will wait forever, otherwise it will time out
1693 * after @timeout nanoseconds.
1694 *
1695 * For asynchronous waiting, the GstClock::synced signal can be used.
1696 *
1697 * This returns immediately with TRUE if GST_CLOCK_FLAG_NEEDS_STARTUP_SYNC
1698 * is not set on the clock, or if the clock is already synced.
1699 *
1700 * Returns: %TRUE if waiting was successful, or %FALSE on timeout
1701 *
1702 * Since: 1.6
1703 */
1704 gboolean
gst_clock_wait_for_sync(GstClock * clock,GstClockTime timeout)1705 gst_clock_wait_for_sync (GstClock * clock, GstClockTime timeout)
1706 {
1707 gboolean timed_out = FALSE;
1708
1709 g_return_val_if_fail (GST_IS_CLOCK (clock), FALSE);
1710
1711 GST_OBJECT_LOCK (clock);
1712 if (!GST_OBJECT_FLAG_IS_SET (clock, GST_CLOCK_FLAG_NEEDS_STARTUP_SYNC)
1713 || clock->priv->synced) {
1714 GST_OBJECT_UNLOCK (clock);
1715 return TRUE;
1716 }
1717
1718 if (timeout != GST_CLOCK_TIME_NONE) {
1719 gint64 end_time = g_get_monotonic_time () + gst_util_uint64_scale (timeout,
1720 G_TIME_SPAN_SECOND, GST_SECOND);
1721
1722 while (!clock->priv->synced && !timed_out) {
1723 timed_out =
1724 !g_cond_wait_until (&clock->priv->sync_cond,
1725 GST_OBJECT_GET_LOCK (clock), end_time);
1726 }
1727 } else {
1728 timed_out = FALSE;
1729 while (!clock->priv->synced) {
1730 g_cond_wait (&clock->priv->sync_cond, GST_OBJECT_GET_LOCK (clock));
1731 }
1732 }
1733 GST_OBJECT_UNLOCK (clock);
1734
1735 return !timed_out;
1736 }
1737
1738 /**
1739 * gst_clock_is_synced:
1740 * @clock: a GstClock
1741 *
1742 * Checks if the clock is currently synced.
1743 *
1744 * This returns if GST_CLOCK_FLAG_NEEDS_STARTUP_SYNC is not set on the clock.
1745 *
1746 * Returns: %TRUE if the clock is currently synced
1747 *
1748 * Since: 1.6
1749 */
1750 gboolean
gst_clock_is_synced(GstClock * clock)1751 gst_clock_is_synced (GstClock * clock)
1752 {
1753 g_return_val_if_fail (GST_IS_CLOCK (clock), TRUE);
1754
1755 return !GST_OBJECT_FLAG_IS_SET (clock, GST_CLOCK_FLAG_NEEDS_STARTUP_SYNC)
1756 || clock->priv->synced;
1757 }
1758
1759 /**
1760 * gst_clock_set_synced:
1761 * @clock: a GstClock
1762 * @synced: if the clock is synced
1763 *
1764 * Sets @clock to synced and emits the GstClock::synced signal, and wakes up any
1765 * thread waiting in gst_clock_wait_for_sync().
1766 *
1767 * This function must only be called if GST_CLOCK_FLAG_NEEDS_STARTUP_SYNC
1768 * is set on the clock, and is intended to be called by subclasses only.
1769 *
1770 * Since: 1.6
1771 */
1772 void
gst_clock_set_synced(GstClock * clock,gboolean synced)1773 gst_clock_set_synced (GstClock * clock, gboolean synced)
1774 {
1775 g_return_if_fail (GST_IS_CLOCK (clock));
1776 g_return_if_fail (GST_OBJECT_FLAG_IS_SET (clock,
1777 GST_CLOCK_FLAG_NEEDS_STARTUP_SYNC));
1778
1779 GST_OBJECT_LOCK (clock);
1780 if (clock->priv->synced != ! !synced) {
1781 clock->priv->synced = ! !synced;
1782 g_cond_signal (&clock->priv->sync_cond);
1783 GST_OBJECT_UNLOCK (clock);
1784 g_signal_emit (clock, gst_clock_signals[SIGNAL_SYNCED], 0, ! !synced);
1785 } else {
1786 GST_OBJECT_UNLOCK (clock);
1787 }
1788 }
1789