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>
6 * gstclock.c: Clock subsystem for maintaining time sync
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.
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.
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., 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, USA.
26 * @short_description: Abstract class for global clocks
27 * @see_also: #GstSystemClock
29 * GStreamer uses a global clock to synchronize the plugins in a pipeline.
30 * Different clock implementations are possible by implementing this abstract
33 * The #GstClock returns a monotonically increasing time with the method
34 * gst_clock_get_time(). Its accuracy and base time depends on the specific
35 * clock implementation but time is always expessed in nanoseconds. Since the
36 * baseline of the clock is undefined, the clock time returned is not
37 * meaningful in itself, what matters are the deltas between two clock times.
39 * The pipeline uses the clock to calculate the stream time. Usually all
40 * renderers synchronize to the global clock using the buffer timestamps, the
41 * newsegment events and the element's base time.
43 * The time of the clock in itself is not very useful for an application.
45 * A clock implementation can support periodic and single shot clock
46 * notifications both synchronous and asynchronous.
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().
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.
58 * Periodic callbacks scheduled async will be repeadedly called automatically
59 * until it is unscheduled. To schedule an async periodic callback,
60 * gst_clock_id_wait() should be called repeadedly.
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.
65 * A #GstClockID that has been unscheduled cannot be used again for any wait
68 * It is possible to perform a blocking wait on the same #GstClockID from
69 * multiple threads. However, registering the same #GstClockID for multiple
70 * async notifications is not possible, the callback will only be called once.
72 * None of the wait operations unref the #GstClockID, the owner is responsible
73 * for unreffing the ids itself. This holds for both periodic and single shot
74 * notifications. The reason being that the owner of the #GstClockID has to
75 * keep a handle to the #GstClockID to unblock the wait on FLUSHING events or
76 * state changes and if we unref it automatically, the handle might be invalid.
78 * These clock operations do not operate on the stream time, so the callbacks
79 * will also occur when not in PLAYING state as if the clock just keeps on
80 * running. Some clocks however do not progress when the element that provided
81 * the clock is not PLAYING.
83 * When a clock has the GST_CLOCK_FLAG_CAN_SET_MASTER flag set, it can be
84 * slaved to another #GstClock with the gst_clock_set_master(). The clock will
85 * then automatically be synchronized to this master clock by repeadedly
86 * sampling the master clock and the slave clock and recalibrating the slave
87 * clock with gst_clock_set_calibration(). This feature is mostly usefull for
88 * plugins that have an internal clock but must operate with another clock
89 * selected by the #GstPipeline. They can track the offset and rate difference
90 * of their internal clock relative to the master clock by using the
91 * gst_clock_get_calibration() function.
93 * Last reviewed on 2005-10-28 (0.9.4)
98 #include "gst_private.h"
100 #include "gstclock.h"
102 #include "gstutils.h"
104 #ifndef GST_DISABLE_TRACE
105 /* #define GST_WITH_ALLOC_TRACE */
106 #include "gsttrace.h"
107 static GstAllocTrace *_gst_clock_entry_trace;
110 /* #define DEBUGGING_ENABLED */
112 #define DEFAULT_STATS FALSE
113 #define DEFAULT_WINDOW_SIZE 32
114 #define DEFAULT_WINDOW_THRESHOLD 4
115 #define DEFAULT_TIMEOUT GST_SECOND / 10
122 PROP_WINDOW_THRESHOLD,
126 static void gst_clock_class_init (GstClockClass * klass);
127 static void gst_clock_init (GstClock * clock);
128 static void gst_clock_finalize (GObject * object);
130 static void gst_clock_set_property (GObject * object, guint prop_id,
131 const GValue * value, GParamSpec * pspec);
132 static void gst_clock_get_property (GObject * object, guint prop_id,
133 GValue * value, GParamSpec * pspec);
134 static void gst_clock_update_stats (GstClock * clock);
137 static GstObjectClass *parent_class = NULL;
139 /* static guint gst_clock_signals[LAST_SIGNAL] = { 0 }; */
142 gst_clock_entry_new (GstClock * clock, GstClockTime time,
143 GstClockTime interval, GstClockEntryType type)
145 GstClockEntry *entry;
147 entry = g_malloc0 (sizeof (GstClockEntry));
148 #ifndef GST_DISABLE_TRACE
149 gst_alloc_trace_new (_gst_clock_entry_trace, entry);
151 GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
152 "created entry %p, time %" GST_TIME_FORMAT, entry, GST_TIME_ARGS (time));
154 gst_atomic_int_set (&entry->refcount, 1);
155 entry->clock = clock;
157 entry->interval = interval;
159 entry->status = GST_CLOCK_BUSY;
161 return (GstClockID) entry;
166 * @id: The clockid to ref
168 * Increase the refcount of the given clockid.
170 * Returns: The same #GstClockID with increased refcount.
175 gst_clock_id_ref (GstClockID id)
177 g_return_val_if_fail (id != NULL, NULL);
179 g_atomic_int_inc (&((GstClockEntry *) id)->refcount);
185 _gst_clock_id_free (GstClockID id)
187 g_return_if_fail (id != NULL);
189 GST_CAT_DEBUG (GST_CAT_CLOCK, "freed entry %p", id);
191 #ifndef GST_DISABLE_TRACE
192 gst_alloc_trace_free (_gst_clock_entry_trace, id);
198 * gst_clock_id_unref:
199 * @id: The clockid to unref
201 * Unref the given clockid. When the refcount reaches 0 the
202 * #GstClockID will be freed.
207 gst_clock_id_unref (GstClockID id)
211 g_return_if_fail (id != NULL);
213 zero = g_atomic_int_dec_and_test (&((GstClockEntry *) id)->refcount);
214 /* if we ended up with the refcount at zero, free the id */
216 _gst_clock_id_free (id);
221 * gst_clock_new_single_shot_id
222 * @clock: The clockid to get a single shot notification from
223 * @time: the requested time
225 * Get an ID from the given clock to trigger a single shot
226 * notification at the requested time. The single shot id should be
227 * unreffed after usage.
229 * Returns: An id that can be used to request the time notification.
234 gst_clock_new_single_shot_id (GstClock * clock, GstClockTime time)
236 g_return_val_if_fail (GST_IS_CLOCK (clock), NULL);
238 return gst_clock_entry_new (clock,
239 time, GST_CLOCK_TIME_NONE, GST_CLOCK_ENTRY_SINGLE);
243 * gst_clock_new_periodic_id
244 * @clock: The clockid to get a periodic notification id from
245 * @start_time: the requested start time
246 * @interval: the requested interval
248 * Get an ID from the given clock to trigger a periodic notification.
249 * The periodeic notifications will be start at time start_time and
250 * will then be fired with the given interval. The id should be unreffed
253 * Returns: An id that can be used to request the time notification.
258 gst_clock_new_periodic_id (GstClock * clock, GstClockTime start_time,
259 GstClockTime interval)
261 g_return_val_if_fail (GST_IS_CLOCK (clock), NULL);
262 g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (start_time), NULL);
263 g_return_val_if_fail (interval != 0, NULL);
265 return gst_clock_entry_new (clock,
266 start_time, interval, GST_CLOCK_ENTRY_PERIODIC);
270 * gst_clock_id_compare_func
272 * @id2: A clockid to compare with
274 * Compares the two GstClockID instances. This function can be used
275 * as a GCompareFunc when sorting ids.
277 * Returns: negative value if a < b; zero if a = b; positive value if a > b
282 gst_clock_id_compare_func (gconstpointer id1, gconstpointer id2)
284 GstClockEntry *entry1, *entry2;
286 entry1 = (GstClockEntry *) id1;
287 entry2 = (GstClockEntry *) id2;
289 if (GST_CLOCK_ENTRY_TIME (entry1) > GST_CLOCK_ENTRY_TIME (entry2)) {
292 if (GST_CLOCK_ENTRY_TIME (entry1) < GST_CLOCK_ENTRY_TIME (entry2)) {
296 return entry1 - entry2;
300 * gst_clock_id_get_time
301 * @id: The clockid to query
303 * Get the time of the clock ID
305 * Returns: the time of the given clock id.
310 gst_clock_id_get_time (GstClockID id)
312 g_return_val_if_fail (id != NULL, GST_CLOCK_TIME_NONE);
314 return GST_CLOCK_ENTRY_TIME ((GstClockEntry *) id);
320 * @id: The clockid to wait on
321 * @jitter: A pointer that will contain the jitter
323 * Perform a blocking wait on the given ID. The jitter arg can be
326 * Returns: the result of the blocking wait.
331 gst_clock_id_wait (GstClockID id, GstClockTimeDiff * jitter)
333 GstClockEntry *entry;
336 GstClockTime requested;
337 GstClockClass *cclass;
339 g_return_val_if_fail (id != NULL, GST_CLOCK_ERROR);
341 entry = (GstClockEntry *) id;
342 requested = GST_CLOCK_ENTRY_TIME (entry);
344 clock = GST_CLOCK_ENTRY_CLOCK (entry);
346 if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (requested)))
349 if (G_UNLIKELY (entry->status == GST_CLOCK_UNSCHEDULED))
352 cclass = GST_CLOCK_GET_CLASS (clock);
354 if (G_LIKELY (cclass->wait)) {
356 GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "waiting on clock entry %p",
358 res = cclass->wait (clock, entry);
359 GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
360 "done waiting entry %p, res: %d", id, res);
363 GstClockTime now = gst_clock_get_time (clock);
365 *jitter = now - requested;
367 if (entry->type == GST_CLOCK_ENTRY_PERIODIC) {
368 entry->time += entry->interval;
372 gst_clock_update_stats (clock);
375 res = GST_CLOCK_UNSUPPORTED;
382 GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
383 "invalid time requested, returning _BADTIME");
384 return GST_CLOCK_BADTIME;
388 GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
389 "entry was unscheduled return _UNSCHEDULED");
390 return GST_CLOCK_UNSCHEDULED;
395 * gst_clock_id_wait_async:
396 * @id: a #GstClockID to wait on
397 * @func: The callback function
398 * @user_data: User data passed in the calback
400 * Register a callback on the given clockid with the given
401 * function and user_data. When passing an id with an invalid
402 * time to this function, the callback will be called immediatly
403 * with a time set to GST_CLOCK_TIME_NONE. The callback will
404 * be called when the time of the id has been reached.
406 * Returns: the result of the non blocking wait.
411 gst_clock_id_wait_async (GstClockID id,
412 GstClockCallback func, gpointer user_data)
414 GstClockEntry *entry;
417 GstClockClass *cclass;
418 GstClockTime requested;
420 g_return_val_if_fail (id != NULL, GST_CLOCK_ERROR);
421 g_return_val_if_fail (func != NULL, GST_CLOCK_ERROR);
423 entry = (GstClockEntry *) id;
424 requested = GST_CLOCK_ENTRY_TIME (entry);
425 clock = GST_CLOCK_ENTRY_CLOCK (entry);
427 if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (requested)))
430 if (G_UNLIKELY (entry->status == GST_CLOCK_UNSCHEDULED))
433 cclass = GST_CLOCK_GET_CLASS (clock);
435 if (cclass->wait_async) {
437 entry->user_data = user_data;
439 res = cclass->wait_async (clock, entry);
441 res = GST_CLOCK_UNSUPPORTED;
448 (func) (clock, GST_CLOCK_TIME_NONE, id, user_data);
449 GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
450 "invalid time requested, returning _BADTIME");
451 return GST_CLOCK_BADTIME;
455 GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
456 "entry was unscheduled return _UNSCHEDULED");
457 return GST_CLOCK_UNSCHEDULED;
462 * gst_clock_id_unschedule:
463 * @id: The id to unschedule
465 * Cancel an outstanding request with the given ID. This can either
466 * be an outstanding async notification or a pending sync notification.
467 * After this call, the @id cannot be used anymore to receive sync or
468 * async notifications, you need to create a new GstClockID.
473 gst_clock_id_unschedule (GstClockID id)
475 GstClockEntry *entry;
477 GstClockClass *cclass;
479 g_return_if_fail (id != NULL);
481 entry = (GstClockEntry *) id;
482 clock = entry->clock;
484 cclass = GST_CLOCK_GET_CLASS (clock);
486 if (cclass->unschedule)
487 cclass->unschedule (clock, entry);
492 * GstClock abstract base class implementation
495 gst_clock_get_type (void)
497 static GType clock_type = 0;
500 static const GTypeInfo clock_info = {
501 sizeof (GstClockClass),
504 (GClassInitFunc) gst_clock_class_init,
509 (GInstanceInitFunc) gst_clock_init,
513 clock_type = g_type_register_static (GST_TYPE_OBJECT, "GstClock",
514 &clock_info, G_TYPE_FLAG_ABSTRACT);
520 gst_clock_class_init (GstClockClass * klass)
522 GObjectClass *gobject_class;
523 GstObjectClass *gstobject_class;
525 gobject_class = (GObjectClass *) klass;
526 gstobject_class = (GstObjectClass *) klass;
528 parent_class = g_type_class_ref (GST_TYPE_OBJECT);
530 if (!g_thread_supported ())
531 g_thread_init (NULL);
533 #ifndef GST_DISABLE_TRACE
534 _gst_clock_entry_trace =
535 gst_alloc_trace_register (GST_CLOCK_ENTRY_TRACE_NAME);
538 gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_clock_finalize);
539 gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_clock_set_property);
540 gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_clock_get_property);
542 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_STATS,
543 g_param_spec_boolean ("stats", "Stats", "Enable clock stats",
544 DEFAULT_STATS, G_PARAM_READWRITE));
545 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_WINDOW_SIZE,
546 g_param_spec_int ("window-size", "Window size",
547 "The size of the window used to calculate rate and offset", 2, 1024,
548 DEFAULT_WINDOW_SIZE, G_PARAM_READWRITE));
549 g_object_class_install_property (G_OBJECT_CLASS (klass),
550 PROP_WINDOW_THRESHOLD, g_param_spec_int ("window-threshold",
552 "The threshold to start calculating rate and offset", 2, 1024,
553 DEFAULT_WINDOW_THRESHOLD, G_PARAM_READWRITE));
554 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_TIMEOUT,
555 g_param_spec_uint64 ("timeout", "Timeout",
556 "The amount of time, in nanoseconds, to sample master and slave clocks",
557 0, G_MAXUINT64, DEFAULT_TIMEOUT, G_PARAM_READWRITE));
561 gst_clock_init (GstClock * clock)
563 clock->last_time = 0;
564 clock->entries = NULL;
565 clock->entries_changed = g_cond_new ();
566 clock->stats = FALSE;
568 clock->internal_calibration = 0;
569 clock->external_calibration = 0;
570 clock->rate_numerator = 1;
571 clock->rate_denominator = 1;
573 clock->slave_lock = g_mutex_new ();
574 clock->filling = TRUE;
575 clock->window_size = DEFAULT_WINDOW_SIZE;
576 clock->window_threshold = DEFAULT_WINDOW_THRESHOLD;
577 clock->time_index = 0;
578 clock->timeout = DEFAULT_TIMEOUT;
579 clock->times = g_new0 (GstClockTime, 4 * clock->window_size);
583 gst_clock_finalize (GObject * object)
585 GstClock *clock = GST_CLOCK (object);
587 GST_CLOCK_SLAVE_LOCK (clock);
588 if (clock->clockid) {
589 gst_clock_id_unschedule (clock->clockid);
590 gst_clock_id_unref (clock->clockid);
591 clock->clockid = NULL;
593 g_free (clock->times);
595 GST_CLOCK_SLAVE_UNLOCK (clock);
597 g_cond_free (clock->entries_changed);
598 g_mutex_free (clock->slave_lock);
600 G_OBJECT_CLASS (parent_class)->finalize (object);
604 * gst_clock_set_resolution
605 * @clock: a #GstClock
606 * @resolution: The resolution to set
608 * Set the accuracy of the clock.
610 * Returns: the new resolution of the clock.
613 gst_clock_set_resolution (GstClock * clock, GstClockTime resolution)
615 GstClockClass *cclass;
617 g_return_val_if_fail (GST_IS_CLOCK (clock), 0);
618 g_return_val_if_fail (resolution != 0, 0);
620 cclass = GST_CLOCK_GET_CLASS (clock);
622 if (cclass->change_resolution)
624 cclass->change_resolution (clock, clock->resolution, resolution);
626 return clock->resolution;
630 * gst_clock_get_resolution
631 * @clock: a #GstClock
633 * Get the accuracy of the clock.
635 * Returns: the resolution of the clock in units of #GstClockTime.
640 gst_clock_get_resolution (GstClock * clock)
642 GstClockClass *cclass;
644 g_return_val_if_fail (GST_IS_CLOCK (clock), 0);
646 cclass = GST_CLOCK_GET_CLASS (clock);
648 if (cclass->get_resolution)
649 return cclass->get_resolution (clock);
655 * gst_clock_adjust_unlocked
656 * @clock: a #GstClock to use
657 * @internal: a clock time
659 * Converts the given @internal clock time to the real time, adjusting for the
660 * rate and reference time set with gst_clock_set_calibration() and making sure
661 * that the returned time is increasing. This function should be called with the
662 * clock's OBJECT_LOCK held and is mainly used by clock subclasses.
664 * Returns: the converted time of the clock.
669 gst_clock_adjust_unlocked (GstClock * clock, GstClockTime internal)
673 ret = gst_util_uint64_scale (internal - clock->internal_calibration,
674 clock->rate_numerator, clock->rate_denominator);
675 ret += clock->external_calibration;
677 /* make sure the time is increasing */
678 clock->last_time = MAX (ret, clock->last_time);
680 return clock->last_time;
684 * gst_clock_get_internal_time
685 * @clock: a #GstClock to query
687 * Gets the current internal time of the given clock. The time is returned
688 * unadjusted for the offset and the rate.
690 * Returns: the internal time of the clock. Or GST_CLOCK_TIME_NONE when
691 * giving wrong input.
696 gst_clock_get_internal_time (GstClock * clock)
699 GstClockClass *cclass;
701 g_return_val_if_fail (GST_IS_CLOCK (clock), GST_CLOCK_TIME_NONE);
703 cclass = GST_CLOCK_GET_CLASS (clock);
705 if (cclass->get_internal_time) {
706 ret = cclass->get_internal_time (clock);
708 ret = G_GINT64_CONSTANT (0);
710 GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "internal time %" GST_TIME_FORMAT,
711 GST_TIME_ARGS (ret));
718 * @clock: a #GstClock to query
720 * Gets the current time of the given clock. The time is always
721 * monotonically increasing and adjusted according to the current
724 * Returns: the time of the clock. Or GST_CLOCK_TIME_NONE when
725 * giving wrong input.
730 gst_clock_get_time (GstClock * clock)
734 g_return_val_if_fail (GST_IS_CLOCK (clock), GST_CLOCK_TIME_NONE);
736 ret = gst_clock_get_internal_time (clock);
738 GST_OBJECT_LOCK (clock);
739 /* this will scale for rate and offset */
740 ret = gst_clock_adjust_unlocked (clock, ret);
741 GST_OBJECT_UNLOCK (clock);
743 GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "adjusted time %" GST_TIME_FORMAT,
744 GST_TIME_ARGS (ret));
750 * gst_clock_set_calibration
751 * @clock: a #GstClock to calibrate
752 * @internal: a reference internal time
753 * @external: a reference external time
754 * @rate_num: the numerator of the rate of the clock relative to its
756 * @rate_denom: the denominator of the rate of the clock
758 * Adjusts the rate and time of @clock. A rate of 1/1 is the normal speed of
759 * the clock. Values bigger than 1/1 make the clock go faster.
761 * @internal and @external are calibration parameters that arrange that
762 * gst_clock_get_time() should have been @external at internal time @internal.
763 * This internal time should not be in the future; that is, it should be less
764 * than the value of gst_clock_get_internal_time() when this function is called.
766 * Subsequent calls to gst_clock_get_time() will return clock times computed as
770 * time = (internal_time - @internal) * @rate_num / @rate_denom + @external
773 * This formula is implemented in gst_clock_adjust_unlocked(). Of course, it
774 * tries to do the integer arithmetic as precisely as possible.
776 * Note that gst_clock_get_time() always returns increasing values so when you
777 * move the clock backwards, gst_clock_get_time() will report the previous value
778 * until the clock catches up.
783 gst_clock_set_calibration (GstClock * clock, GstClockTime internal, GstClockTime
784 external, GstClockTime rate_num, GstClockTime rate_denom)
786 g_return_if_fail (GST_IS_CLOCK (clock));
787 g_return_if_fail (rate_num > 0);
788 g_return_if_fail (rate_denom > 0);
789 g_return_if_fail (internal <= gst_clock_get_internal_time (clock));
791 GST_OBJECT_LOCK (clock);
792 clock->internal_calibration = internal;
793 clock->external_calibration = external;
794 clock->rate_numerator = rate_num;
795 clock->rate_denominator = rate_denom;
796 GST_OBJECT_UNLOCK (clock);
800 * gst_clock_get_calibration
801 * @clock: a #GstClock
802 * @internal: a location to store the internal time
803 * @external: a location to store the external time
804 * @rate_num: a location to store the rate numerator
805 * @rate_denom: a location to store the rate denominator
807 * Gets the internal rate and reference time of @clock. See
808 * gst_clock_set_calibration() for more information.
810 * @internal, @external, @rate_num, and @rate_denom can be left NULL if the
811 * caller is not interested in the values.
816 gst_clock_get_calibration (GstClock * clock, GstClockTime * internal,
817 GstClockTime * external, GstClockTime * rate_num, GstClockTime * rate_denom)
819 g_return_if_fail (GST_IS_CLOCK (clock));
821 GST_OBJECT_LOCK (clock);
823 *rate_num = clock->rate_numerator;
825 *rate_denom = clock->rate_denominator;
827 *external = clock->external_calibration;
829 *internal = clock->internal_calibration;
830 GST_OBJECT_UNLOCK (clock);
833 /* will be called repeadedly to sample the master and slave clock
834 * to recalibrate the clock */
836 gst_clock_slave_callback (GstClock * master, GstClockTime time,
837 GstClockID id, GstClock * clock)
839 GstClockTime stime, mtime;
842 stime = gst_clock_get_internal_time (clock);
843 mtime = gst_clock_get_time (master);
845 GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
846 "master %" GST_TIME_FORMAT ", slave %" GST_TIME_FORMAT,
847 GST_TIME_ARGS (mtime), GST_TIME_ARGS (stime));
849 gst_clock_add_observation (clock, stime, mtime, &r_squared);
851 /* FIXME, we can use the r_squared value to adjust the timeout
852 * value of the clockid */
858 * gst_clock_set_master
859 * @clock: a #GstClock
860 * @master: a master #GstClock
862 * Set @master as the master clock for @clock. @clock will be automatically
863 * calibrated so that gst_clock_get_time() reports the same time as the
866 * A clock provider that slaves its clock to a master can get the current
867 * calibration values with gst_clock_get_calibration().
869 * Returns: TRUE if the clock is capable of being slaved to a master clock.
874 gst_clock_set_master (GstClock * clock, GstClock * master)
876 g_return_val_if_fail (GST_IS_CLOCK (clock), FALSE);
878 GST_OBJECT_LOCK (clock);
879 /* we always allow setting the master to NULL */
880 if (master && !GST_OBJECT_FLAG_IS_SET (clock, GST_CLOCK_FLAG_CAN_SET_MASTER))
883 GST_DEBUG_OBJECT (clock, "slaving to master clock %p", master);
884 gst_object_replace ((GstObject **) & clock->master, (GstObject *) master);
885 GST_OBJECT_UNLOCK (clock);
887 GST_CLOCK_SLAVE_LOCK (clock);
888 if (clock->clockid) {
889 gst_clock_id_unschedule (clock->clockid);
890 gst_clock_id_unref (clock->clockid);
891 clock->clockid = NULL;
894 clock->filling = TRUE;
895 clock->time_index = 0;
896 /* use the master periodic id to schedule sampling and
897 * clock calibration. */
898 clock->clockid = gst_clock_new_periodic_id (master,
899 gst_clock_get_time (master), clock->timeout);
900 gst_clock_id_wait_async (clock->clockid,
901 (GstClockCallback) gst_clock_slave_callback, clock);
903 GST_CLOCK_SLAVE_UNLOCK (clock);
909 GST_DEBUG_OBJECT (clock, "cannot be slaved to a master clock");
910 GST_OBJECT_UNLOCK (clock);
916 * gst_clock_get_master
917 * @clock: a #GstClock
919 * Get the master clock that @clock is slaved to or NULL when the clock is
920 * not slaved to any master clock.
922 * Returns: a master #GstClock or NULL when this clock is not slaved to a master
923 * clock. Unref after usage.
928 gst_clock_get_master (GstClock * clock)
930 GstClock *result = NULL;
932 g_return_val_if_fail (GST_IS_CLOCK (clock), NULL);
934 GST_OBJECT_LOCK (clock);
936 result = gst_object_ref (clock->master);
937 GST_OBJECT_UNLOCK (clock);
942 /* http://mathworld.wolfram.com/LeastSquaresFitting.html
946 do_linear_regression (GstClock * clock, GstClockTime * m_num,
947 GstClockTime * m_denom, GstClockTime * b, GstClockTime * xbase,
950 GstClockTime *newx, *newy;
951 GstClockTime xmin, ymin, xbar, ybar, xbar4, ybar4;
952 GstClockTimeDiff sxx, sxy, syy;
957 xbar = ybar = sxx = syy = sxy = 0;
960 y = clock->times + 2;
961 n = clock->filling ? clock->time_index : clock->window_size;
963 #ifdef DEBUGGING_ENABLED
964 GST_DEBUG ("doing regression on:");
965 for (i = j = 0; i < n; i++, j += 4)
966 GST_DEBUG (" %" G_GUINT64_FORMAT " %" G_GUINT64_FORMAT, x[j], y[j]);
969 xmin = ymin = G_MAXUINT64;
970 for (i = j = 0; i < n; i++, j += 4) {
971 xmin = MIN (xmin, x[j]);
972 ymin = MIN (ymin, y[j]);
975 #ifdef DEBUGGING_ENABLED
976 GST_DEBUG ("min x: %" G_GUINT64_FORMAT, xmin);
977 GST_DEBUG ("min y: %" G_GUINT64_FORMAT, ymin);
980 newx = clock->times + 1;
981 newy = clock->times + 3;
983 /* strip off unnecessary bits of precision */
984 for (i = j = 0; i < n; i++, j += 4) {
985 newx[j] = x[j] - xmin;
986 newy[j] = y[j] - ymin;
989 #ifdef DEBUGGING_ENABLED
990 GST_DEBUG ("reduced numbers:");
991 for (i = j = 0; i < n; i++, j += 4)
992 GST_DEBUG (" %" G_GUINT64_FORMAT " %" G_GUINT64_FORMAT, newx[j], newy[j]);
995 /* have to do this precisely otherwise the results are pretty much useless.
996 * should guarantee that none of these accumulators can overflow */
998 /* quantities on the order of 1e10 -> 30 bits; window size a max of 2^10, so
999 this addition could end up around 2^40 or so -- ample headroom */
1000 for (i = j = 0; i < n; i++, j += 4) {
1007 #ifdef DEBUGGING_ENABLED
1008 GST_DEBUG (" xbar = %" G_GUINT64_FORMAT, xbar);
1009 GST_DEBUG (" ybar = %" G_GUINT64_FORMAT, ybar);
1012 /* multiplying directly would give quantities on the order of 1e20 -> 60 bits;
1013 times the window size that's 70 which is too much. Instead we (1) subtract
1014 off the xbar*ybar in the loop instead of after, to avoid accumulation; (2)
1015 shift off 4 bits from each multiplicand, giving an expected ceiling of 52
1016 bits, which should be enough. Need to check the incoming range and domain
1017 to ensure this is an appropriate loss of precision though. */
1020 for (i = j = 0; i < n; i++, j += 4) {
1021 GstClockTime newx4, newy4;
1023 newx4 = newx[j] >> 4;
1024 newy4 = newy[j] >> 4;
1026 sxx += newx4 * newx4 - xbar4 * xbar4;
1027 syy += newy4 * newy4 - ybar4 * ybar4;
1028 sxy += newx4 * newy4 - xbar4 * ybar4;
1037 *b = (ybar + ymin) - gst_util_uint64_scale (xbar, *m_num, *m_denom);
1038 *r_squared = ((double) sxy * (double) sxy) / ((double) sxx * (double) syy);
1040 #ifdef DEBUGGING_ENABLED
1041 GST_DEBUG (" m = %g", ((double) *m_num) / *m_denom);
1042 GST_DEBUG (" b = %" G_GUINT64_FORMAT, *b);
1043 GST_DEBUG (" xbase = %" G_GUINT64_FORMAT, *xbase);
1044 GST_DEBUG (" r2 = %g", *r_squared);
1056 * gst_clock_add_observation
1057 * @clock: a #GstClock
1058 * @slave: a time on the slave
1059 * @master: a time on the master
1060 * @r_squared: a pointer to hold the result
1062 * The time @master of the master clock and the time @slave of the slave
1063 * clock are added to the list of observations. If enough observations
1064 * are available, a linear regression algorithm is run on the
1065 * observations and @clock is recalibrated.
1067 * Returns: TRUE if enough observations were added to run the
1068 * regression algorithm.
1073 gst_clock_add_observation (GstClock * clock, GstClockTime slave,
1074 GstClockTime master, gdouble * r_squared)
1076 GstClockTime m_num, m_denom, b, xbase;
1078 g_return_val_if_fail (GST_IS_CLOCK (clock), FALSE);
1079 g_return_val_if_fail (r_squared != NULL, FALSE);
1081 GST_CLOCK_SLAVE_LOCK (clock);
1083 clock->times[(4 * clock->time_index)] = slave;
1084 clock->times[(4 * clock->time_index) + 2] = master;
1086 clock->time_index++;
1087 if (clock->time_index == clock->window_size) {
1088 clock->filling = FALSE;
1089 clock->time_index = 0;
1092 if (clock->filling && clock->time_index < clock->window_threshold)
1095 if (!do_linear_regression (clock, &m_num, &m_denom, &b, &xbase, r_squared))
1098 GST_CLOCK_SLAVE_UNLOCK (clock);
1100 GST_CAT_LOG_OBJECT (GST_CAT_CLOCK, clock,
1101 "adjusting clock to m=%" G_GUINT64_FORMAT "/%" G_GUINT64_FORMAT ", b=%"
1102 G_GUINT64_FORMAT " (rsquared=%g)", m_num, m_denom, b, *r_squared);
1104 /* if we have a valid regression, adjust the clock */
1105 gst_clock_set_calibration (clock, xbase, b, m_num, m_denom);
1111 GST_CLOCK_SLAVE_UNLOCK (clock);
1116 /* no valid regression has been done, ignore the result then */
1117 GST_CLOCK_SLAVE_UNLOCK (clock);
1123 gst_clock_update_stats (GstClock * clock)
1128 gst_clock_set_property (GObject * object, guint prop_id,
1129 const GValue * value, GParamSpec * pspec)
1133 clock = GST_CLOCK (object);
1137 GST_OBJECT_LOCK (clock);
1138 clock->stats = g_value_get_boolean (value);
1139 GST_OBJECT_UNLOCK (clock);
1140 g_object_notify (object, "stats");
1142 case PROP_WINDOW_SIZE:
1143 GST_CLOCK_SLAVE_LOCK (clock);
1144 clock->window_size = g_value_get_int (value);
1145 clock->window_threshold =
1146 MIN (clock->window_threshold, clock->window_size);
1148 g_renew (GstClockTime, clock->times, 4 * clock->window_size);
1149 GST_CLOCK_SLAVE_UNLOCK (clock);
1151 case PROP_WINDOW_THRESHOLD:
1152 GST_CLOCK_SLAVE_LOCK (clock);
1153 clock->window_threshold =
1154 MIN (g_value_get_int (value), clock->window_size);
1155 GST_CLOCK_SLAVE_UNLOCK (clock);
1158 GST_CLOCK_SLAVE_LOCK (clock);
1159 clock->timeout = g_value_get_uint64 (value);
1160 GST_CLOCK_SLAVE_UNLOCK (clock);
1163 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1169 gst_clock_get_property (GObject * object, guint prop_id,
1170 GValue * value, GParamSpec * pspec)
1174 clock = GST_CLOCK (object);
1178 GST_OBJECT_LOCK (clock);
1179 g_value_set_boolean (value, clock->stats);
1180 GST_OBJECT_UNLOCK (clock);
1182 case PROP_WINDOW_SIZE:
1183 GST_CLOCK_SLAVE_LOCK (clock);
1184 g_value_set_int (value, clock->window_size);
1185 GST_CLOCK_SLAVE_UNLOCK (clock);
1187 case PROP_WINDOW_THRESHOLD:
1188 GST_CLOCK_SLAVE_LOCK (clock);
1189 g_value_set_int (value, clock->window_threshold);
1190 GST_CLOCK_SLAVE_UNLOCK (clock);
1193 GST_CLOCK_SLAVE_LOCK (clock);
1194 g_value_set_uint64 (value, clock->timeout);
1195 GST_CLOCK_SLAVE_UNLOCK (clock);
1198 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);