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