clock: use the new gst_clock_id_wait_async_full.
[platform/upstream/gstreamer.git] / gst / gstclock.c
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., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  */
23
24 /**
25  * SECTION:gstclock
26  * @short_description: Abstract class for global clocks
27  * @see_also: #GstSystemClock, #GstPipeline
28  *
29  * GStreamer uses a global clock to synchronize the plugins in a pipeline.
30  * Different clock implementations are possible by implementing this abstract
31  * base class or, more conveniently, by subclassing #GstSystemClock.
32  *
33  * The #GstClock returns a monotonically increasing time with the method
34  * gst_clock_get_time(). Its accuracy and base time depend on the specific
35  * clock implementation but time is always expressed 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.
38  * The time returned by a clock is called the absolute time.
39  *
40  * The pipeline uses the clock to calculate the running time. Usually all
41  * renderers synchronize to the global clock using the buffer timestamps, the
42  * newsegment events and the element's base time, see #GstPipeline.
43  *
44  * A clock implementation can support periodic and single shot clock
45  * notifications both synchronous and asynchronous.
46  *
47  * One first needs to create a #GstClockID for the periodic or single shot
48  * notification using gst_clock_new_single_shot_id() or
49  * gst_clock_new_periodic_id().
50  *
51  * To perform a blocking wait for the specific time of the #GstClockID use the
52  * gst_clock_id_wait(). To receive a callback when the specific time is reached
53  * in the clock use gst_clock_id_wait_async(). Both these calls can be
54  * interrupted with the gst_clock_id_unschedule() call. If the blocking wait is
55  * unscheduled a return value of #GST_CLOCK_UNSCHEDULED is returned.
56  *
57  * Periodic callbacks scheduled async will be repeatedly called automatically
58  * until it is unscheduled. To schedule a sync periodic callback,
59  * gst_clock_id_wait() should be called repeatedly.
60  *
61  * The async callbacks can happen from any thread, either provided by the core
62  * or from a streaming thread. The application should be prepared for this.
63  *
64  * A #GstClockID that has been unscheduled cannot be used again for any wait
65  * operation, a new #GstClockID should be created and the old unscheduled one
66  * should be destroyed with gst_clock_id_unref().
67  *
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 for
71  * the thread registering the entry last.
72  *
73  * None of the wait operations unref the #GstClockID, the owner is responsible
74  * for unreffing the ids itself. This holds for both periodic and single shot
75  * notifications. The reason being that the owner of the #GstClockID has to
76  * keep a handle to the #GstClockID to unblock the wait on FLUSHING events or
77  * state changes and if the entry would be unreffed automatically, the handle 
78  * might become invalid without any notification.
79  *
80  * These clock operations do not operate on the running time, so the callbacks
81  * will also occur when not in PLAYING state as if the clock just keeps on
82  * running. Some clocks however do not progress when the element that provided
83  * the clock is not PLAYING.
84  *
85  * When a clock has the #GST_CLOCK_FLAG_CAN_SET_MASTER flag set, it can be
86  * slaved to another #GstClock with the gst_clock_set_master(). The clock will
87  * then automatically be synchronized to this master clock by repeatedly
88  * sampling the master clock and the slave clock and recalibrating the slave
89  * clock with gst_clock_set_calibration(). This feature is mostly useful for
90  * plugins that have an internal clock but must operate with another clock
91  * selected by the #GstPipeline.  They can track the offset and rate difference
92  * of their internal clock relative to the master clock by using the
93  * gst_clock_get_calibration() function. 
94  *
95  * The master/slave synchronisation can be tuned with the #GstClock:timeout,
96  * #GstClock:window-size and #GstClock:window-threshold properties.
97  * The #GstClock:timeout property defines the interval to sample the master
98  * clock and run the calibration functions. #GstClock:window-size defines the
99  * number of samples to use when calibrating and #GstClock:window-threshold
100  * defines the minimum number of samples before the calibration is performed.
101  *
102  * Last reviewed on 2009-05-21 (0.10.24)
103  */
104
105
106 #include "gst_private.h"
107 #include <time.h>
108
109 #include "gstclock.h"
110 #include "gstinfo.h"
111 #include "gstutils.h"
112
113 #ifndef GST_DISABLE_TRACE
114 /* #define GST_WITH_ALLOC_TRACE */
115 #include "gsttrace.h"
116 static GstAllocTrace *_gst_clock_entry_trace;
117 #endif
118
119 /* #define DEBUGGING_ENABLED */
120
121 #define DEFAULT_STATS                   FALSE
122 #define DEFAULT_WINDOW_SIZE             32
123 #define DEFAULT_WINDOW_THRESHOLD        4
124 #define DEFAULT_TIMEOUT                 GST_SECOND / 10
125
126 enum
127 {
128   PROP_0,
129   PROP_STATS,
130   PROP_WINDOW_SIZE,
131   PROP_WINDOW_THRESHOLD,
132   PROP_TIMEOUT
133 };
134
135 struct _GstClockPrivate
136 {
137   gint pre_count;
138   gint post_count;
139 };
140
141 /* seqlocks */
142 #define read_seqbegin(clock)                                   \
143   g_atomic_int_get (&clock->ABI.priv->post_count);
144
145 static inline gboolean
146 read_seqretry (GstClock * clock, gint seq)
147 {
148   /* no retry if the seqnum did not change */
149   if (G_LIKELY (seq == g_atomic_int_get (&clock->ABI.priv->pre_count)))
150     return FALSE;
151
152   /* wait for the writer to finish and retry */
153   GST_OBJECT_LOCK (clock);
154   GST_OBJECT_UNLOCK (clock);
155   return TRUE;
156 }
157
158 #define write_seqlock(clock)                      \
159 G_STMT_START {                                    \
160   GST_OBJECT_LOCK (clock);                        \
161   g_atomic_int_inc (&clock->ABI.priv->pre_count);     \
162 } G_STMT_END;
163
164 #define write_sequnlock(clock)                    \
165 G_STMT_START {                                    \
166   g_atomic_int_inc (&clock->ABI.priv->post_count);    \
167   GST_OBJECT_UNLOCK (clock);                      \
168 } G_STMT_END;
169
170 static void gst_clock_dispose (GObject * object);
171 static void gst_clock_finalize (GObject * object);
172
173 static void gst_clock_set_property (GObject * object, guint prop_id,
174     const GValue * value, GParamSpec * pspec);
175 static void gst_clock_get_property (GObject * object, guint prop_id,
176     GValue * value, GParamSpec * pspec);
177 static void gst_clock_update_stats (GstClock * clock);
178
179
180 static GstObjectClass *parent_class = NULL;
181
182 /* static guint gst_clock_signals[LAST_SIGNAL] = { 0 }; */
183
184 static GstClockID
185 gst_clock_entry_new (GstClock * clock, GstClockTime time,
186     GstClockTime interval, GstClockEntryType type)
187 {
188   GstClockEntry *entry;
189
190   entry = g_slice_new (GstClockEntry);
191 #ifndef GST_DISABLE_TRACE
192   gst_alloc_trace_new (_gst_clock_entry_trace, entry);
193 #endif
194   GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
195       "created entry %p, time %" GST_TIME_FORMAT, entry, GST_TIME_ARGS (time));
196
197   entry->refcount = 1;
198   entry->clock = clock;
199   entry->type = type;
200   entry->time = time;
201   entry->interval = interval;
202   entry->status = GST_CLOCK_OK;
203   entry->func = NULL;
204   entry->user_data = NULL;
205   entry->destroy_data = NULL;
206
207   return (GstClockID) entry;
208 }
209
210 /**
211  * gst_clock_id_ref:
212  * @id: The #GstClockID to ref
213  *
214  * Increase the refcount of given @id.
215  *
216  * Returns: The same #GstClockID with increased refcount.
217  *
218  * MT safe.
219  */
220 GstClockID
221 gst_clock_id_ref (GstClockID id)
222 {
223   g_return_val_if_fail (id != NULL, NULL);
224
225   g_atomic_int_inc (&((GstClockEntry *) id)->refcount);
226
227   return id;
228 }
229
230 static void
231 _gst_clock_id_free (GstClockID id)
232 {
233   GstClockEntry *entry;
234   g_return_if_fail (id != NULL);
235
236   GST_CAT_DEBUG (GST_CAT_CLOCK, "freed entry %p", id);
237   entry = (GstClockEntry *) id;
238   if (entry->destroy_data)
239     entry->destroy_data (entry->user_data);
240
241 #ifndef GST_DISABLE_TRACE
242   gst_alloc_trace_free (_gst_clock_entry_trace, id);
243 #endif
244   g_slice_free (GstClockEntry, id);
245 }
246
247 /**
248  * gst_clock_id_unref:
249  * @id: The #GstClockID to unref
250  *
251  * Unref given @id. When the refcount reaches 0 the
252  * #GstClockID will be freed.
253  *
254  * MT safe.
255  */
256 void
257 gst_clock_id_unref (GstClockID id)
258 {
259   gint zero;
260
261   g_return_if_fail (id != NULL);
262
263   zero = g_atomic_int_dec_and_test (&((GstClockEntry *) id)->refcount);
264   /* if we ended up with the refcount at zero, free the id */
265   if (zero) {
266     _gst_clock_id_free (id);
267   }
268 }
269
270 /**
271  * gst_clock_new_single_shot_id
272  * @clock: The #GstClockID to get a single shot notification from
273  * @time: the requested time
274  *
275  * Get a #GstClockID from @clock to trigger a single shot
276  * notification at the requested time. The single shot id should be
277  * unreffed after usage.
278  *
279  * Returns: A #GstClockID that can be used to request the time notification.
280  *
281  * MT safe.
282  */
283 GstClockID
284 gst_clock_new_single_shot_id (GstClock * clock, GstClockTime time)
285 {
286   g_return_val_if_fail (GST_IS_CLOCK (clock), NULL);
287
288   return gst_clock_entry_new (clock,
289       time, GST_CLOCK_TIME_NONE, GST_CLOCK_ENTRY_SINGLE);
290 }
291
292 /**
293  * gst_clock_new_periodic_id
294  * @clock: The #GstClockID to get a periodic notification id from
295  * @start_time: the requested start time
296  * @interval: the requested interval
297  *
298  * Get an ID from @clock to trigger a periodic notification.
299  * The periodic notifications will start at time @start_time and
300  * will then be fired with the given @interval. @id should be unreffed
301  * after usage.
302  *
303  * Returns: A #GstClockID that can be used to request the time notification.
304  *
305  * MT safe.
306  */
307 GstClockID
308 gst_clock_new_periodic_id (GstClock * clock, GstClockTime start_time,
309     GstClockTime interval)
310 {
311   g_return_val_if_fail (GST_IS_CLOCK (clock), NULL);
312   g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (start_time), NULL);
313   g_return_val_if_fail (interval != 0, NULL);
314   g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (interval), NULL);
315
316   return gst_clock_entry_new (clock,
317       start_time, interval, GST_CLOCK_ENTRY_PERIODIC);
318 }
319
320 /**
321  * gst_clock_id_compare_func
322  * @id1: A #GstClockID
323  * @id2: A #GstClockID to compare with
324  *
325  * Compares the two #GstClockID instances. This function can be used
326  * as a GCompareFunc when sorting ids.
327  *
328  * Returns: negative value if a < b; zero if a = b; positive value if a > b
329  *
330  * MT safe.
331  */
332 gint
333 gst_clock_id_compare_func (gconstpointer id1, gconstpointer id2)
334 {
335   GstClockEntry *entry1, *entry2;
336
337   entry1 = (GstClockEntry *) id1;
338   entry2 = (GstClockEntry *) id2;
339
340   if (GST_CLOCK_ENTRY_TIME (entry1) > GST_CLOCK_ENTRY_TIME (entry2)) {
341     return 1;
342   }
343   if (GST_CLOCK_ENTRY_TIME (entry1) < GST_CLOCK_ENTRY_TIME (entry2)) {
344     return -1;
345   }
346   return 0;
347 }
348
349 /**
350  * gst_clock_id_get_time
351  * @id: The #GstClockID to query
352  *
353  * Get the time of the clock ID
354  *
355  * Returns: the time of the given clock id.
356  *
357  * MT safe.
358  */
359 GstClockTime
360 gst_clock_id_get_time (GstClockID id)
361 {
362   g_return_val_if_fail (id != NULL, GST_CLOCK_TIME_NONE);
363
364   return GST_CLOCK_ENTRY_TIME ((GstClockEntry *) id);
365 }
366
367 /**
368  * gst_clock_id_wait
369  * @id: The #GstClockID to wait on
370  * @jitter: A pointer that will contain the jitter, can be %NULL.
371  *
372  * Perform a blocking wait on @id. 
373  * @id should have been created with gst_clock_new_single_shot_id()
374  * or gst_clock_new_periodic_id() and should not have been unscheduled
375  * with a call to gst_clock_id_unschedule(). 
376  *
377  * If the @jitter argument is not %NULL and this function returns #GST_CLOCK_OK
378  * or #GST_CLOCK_EARLY, it will contain the difference
379  * against the clock and the time of @id when this method was
380  * called. 
381  * Positive values indicate how late @id was relative to the clock
382  * (in which case this function will return #GST_CLOCK_EARLY). 
383  * Negative values indicate how much time was spent waiting on the clock 
384  * before this function returned.
385  *
386  * Returns: the result of the blocking wait. #GST_CLOCK_EARLY will be returned
387  * if the current clock time is past the time of @id, #GST_CLOCK_OK if 
388  * @id was scheduled in time. #GST_CLOCK_UNSCHEDULED if @id was 
389  * unscheduled with gst_clock_id_unschedule().
390  *
391  * MT safe.
392  */
393 GstClockReturn
394 gst_clock_id_wait (GstClockID id, GstClockTimeDiff * jitter)
395 {
396   GstClockEntry *entry;
397   GstClock *clock;
398   GstClockReturn res;
399   GstClockTime requested;
400   GstClockClass *cclass;
401
402   g_return_val_if_fail (id != NULL, GST_CLOCK_ERROR);
403
404   entry = (GstClockEntry *) id;
405   requested = GST_CLOCK_ENTRY_TIME (entry);
406
407   clock = GST_CLOCK_ENTRY_CLOCK (entry);
408
409   /* can't sync on invalid times */
410   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (requested)))
411     goto invalid_time;
412
413   cclass = GST_CLOCK_GET_CLASS (clock);
414
415   GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "waiting on clock entry %p", id);
416
417   /* if we have a wait_jitter function, use that */
418   if (G_LIKELY (cclass->wait_jitter)) {
419     res = cclass->wait_jitter (clock, entry, jitter);
420   } else {
421     /* check if we have a simple _wait function otherwise. The function without
422      * the jitter arg is less optimal as we need to do an additional _get_time()
423      * which is not atomic with the _wait() and a typical _wait() function does
424      * yet another _get_time() anyway. */
425     if (G_UNLIKELY (cclass->wait == NULL))
426       goto not_supported;
427
428     if (jitter) {
429       GstClockTime now = gst_clock_get_time (clock);
430
431       /* jitter is the diff against the clock when this entry is scheduled. Negative
432        * values mean that the entry was in time, a positive value means that the
433        * entry was too late. */
434       *jitter = GST_CLOCK_DIFF (requested, now);
435     }
436     res = cclass->wait (clock, entry);
437   }
438
439   GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
440       "done waiting entry %p, res: %d", id, res);
441
442   if (entry->type == GST_CLOCK_ENTRY_PERIODIC)
443     entry->time = requested + entry->interval;
444
445   if (G_UNLIKELY (clock->stats))
446     gst_clock_update_stats (clock);
447
448   return res;
449
450   /* ERRORS */
451 invalid_time:
452   {
453     GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
454         "invalid time requested, returning _BADTIME");
455     return GST_CLOCK_BADTIME;
456   }
457 not_supported:
458   {
459     GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "clock wait is not supported");
460     return GST_CLOCK_UNSUPPORTED;
461   }
462 }
463
464 /**
465  * gst_clock_id_wait_async_full:
466  * @id: a #GstClockID to wait on
467  * @func: The callback function
468  * @user_data: User data passed in the callback
469  * @destroy_data: #GDestroyNotify for user_data
470  *
471  * Register a callback on the given #GstClockID @id with the given
472  * function and user_data. When passing a #GstClockID with an invalid
473  * time to this function, the callback will be called immediately
474  * with  a time set to GST_CLOCK_TIME_NONE. The callback will
475  * be called when the time of @id has been reached.
476  *
477  * The callback @func can be invoked from any thread, either provided by the
478  * core or from a streaming thread. The application should be prepared for this.
479  *
480  * Returns: the result of the non blocking wait.
481  *
482  * MT safe.
483  *
484  * Since: 0.10.30
485  */
486 GstClockReturn
487 gst_clock_id_wait_async_full (GstClockID id,
488     GstClockCallback func, gpointer user_data, GDestroyNotify destroy_data)
489 {
490   GstClockEntry *entry;
491   GstClock *clock;
492   GstClockReturn res;
493   GstClockClass *cclass;
494   GstClockTime requested;
495
496   g_return_val_if_fail (id != NULL, GST_CLOCK_ERROR);
497   g_return_val_if_fail (func != NULL, GST_CLOCK_ERROR);
498
499   entry = (GstClockEntry *) id;
500   requested = GST_CLOCK_ENTRY_TIME (entry);
501   clock = GST_CLOCK_ENTRY_CLOCK (entry);
502
503   /* can't sync on invalid times */
504   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (requested)))
505     goto invalid_time;
506
507   cclass = GST_CLOCK_GET_CLASS (clock);
508
509   if (G_UNLIKELY (cclass->wait_async == NULL))
510     goto not_supported;
511
512   entry->func = func;
513   entry->user_data = user_data;
514   entry->destroy_data = destroy_data;
515
516   res = cclass->wait_async (clock, entry);
517
518   return res;
519
520   /* ERRORS */
521 invalid_time:
522   {
523     (func) (clock, GST_CLOCK_TIME_NONE, id, user_data);
524     GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
525         "invalid time requested, returning _BADTIME");
526     return GST_CLOCK_BADTIME;
527   }
528 not_supported:
529   {
530     GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "clock wait is not supported");
531     return GST_CLOCK_UNSUPPORTED;
532   }
533 }
534
535 /**
536  * gst_clock_id_wait_async:
537  * @id: a #GstClockID to wait on
538  * @func: The callback function
539  * @user_data: User data passed in the callback
540  *
541  * Register a callback on the given #GstClockID @id with the given
542  * function and user_data. When passing a #GstClockID with an invalid
543  * time to this function, the callback will be called immediately
544  * with  a time set to GST_CLOCK_TIME_NONE. The callback will
545  * be called when the time of @id has been reached.
546  *
547  * The callback @func can be invoked from any thread, either provided by the
548  * core or from a streaming thread. The application should be prepared for this.
549  *
550  * Returns: the result of the non blocking wait.
551  *
552  * MT safe.
553  */
554 GstClockReturn
555 gst_clock_id_wait_async (GstClockID id,
556     GstClockCallback func, gpointer user_data)
557 {
558   return gst_clock_id_wait_async_full (id, func, user_data, NULL);
559 }
560
561 /**
562  * gst_clock_id_unschedule:
563  * @id: The id to unschedule
564  *
565  * Cancel an outstanding request with @id. This can either
566  * be an outstanding async notification or a pending sync notification.
567  * After this call, @id cannot be used anymore to receive sync or
568  * async notifications, you need to create a new #GstClockID.
569  *
570  * MT safe.
571  */
572 void
573 gst_clock_id_unschedule (GstClockID id)
574 {
575   GstClockEntry *entry;
576   GstClock *clock;
577   GstClockClass *cclass;
578
579   g_return_if_fail (id != NULL);
580
581   entry = (GstClockEntry *) id;
582   clock = entry->clock;
583
584   cclass = GST_CLOCK_GET_CLASS (clock);
585
586   if (G_LIKELY (cclass->unschedule))
587     cclass->unschedule (clock, entry);
588 }
589
590
591 /*
592  * GstClock abstract base class implementation
593  */
594 G_DEFINE_TYPE (GstClock, gst_clock, GST_TYPE_OBJECT);
595
596 static void
597 gst_clock_class_init (GstClockClass * klass)
598 {
599   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
600
601   parent_class = g_type_class_peek_parent (klass);
602
603 #ifndef GST_DISABLE_TRACE
604   _gst_clock_entry_trace =
605       gst_alloc_trace_register (GST_CLOCK_ENTRY_TRACE_NAME);
606 #endif
607
608   gobject_class->dispose = gst_clock_dispose;
609   gobject_class->finalize = gst_clock_finalize;
610   gobject_class->set_property = gst_clock_set_property;
611   gobject_class->get_property = gst_clock_get_property;
612
613   g_object_class_install_property (gobject_class, PROP_STATS,
614       g_param_spec_boolean ("stats", "Stats",
615           "Enable clock stats (unimplemented)", DEFAULT_STATS,
616           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
617   g_object_class_install_property (gobject_class, PROP_WINDOW_SIZE,
618       g_param_spec_int ("window-size", "Window size",
619           "The size of the window used to calculate rate and offset", 2, 1024,
620           DEFAULT_WINDOW_SIZE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
621   g_object_class_install_property (gobject_class, PROP_WINDOW_THRESHOLD,
622       g_param_spec_int ("window-threshold", "Window threshold",
623           "The threshold to start calculating rate and offset", 2, 1024,
624           DEFAULT_WINDOW_THRESHOLD,
625           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
626   g_object_class_install_property (gobject_class, PROP_TIMEOUT,
627       g_param_spec_uint64 ("timeout", "Timeout",
628           "The amount of time, in nanoseconds, to sample master and slave clocks",
629           0, G_MAXUINT64, DEFAULT_TIMEOUT,
630           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
631
632   g_type_class_add_private (klass, sizeof (GstClockPrivate));
633 }
634
635 static void
636 gst_clock_init (GstClock * clock)
637 {
638   clock->last_time = 0;
639   clock->entries = NULL;
640   clock->entries_changed = g_cond_new ();
641   clock->stats = FALSE;
642
643   clock->ABI.priv =
644       G_TYPE_INSTANCE_GET_PRIVATE (clock, GST_TYPE_CLOCK, GstClockPrivate);
645
646   clock->internal_calibration = 0;
647   clock->external_calibration = 0;
648   clock->rate_numerator = 1;
649   clock->rate_denominator = 1;
650
651   clock->slave_lock = g_mutex_new ();
652   clock->window_size = DEFAULT_WINDOW_SIZE;
653   clock->window_threshold = DEFAULT_WINDOW_THRESHOLD;
654   clock->filling = TRUE;
655   clock->time_index = 0;
656   clock->timeout = DEFAULT_TIMEOUT;
657   clock->times = g_new0 (GstClockTime, 4 * clock->window_size);
658 }
659
660 static void
661 gst_clock_dispose (GObject * object)
662 {
663   GstClock *clock = GST_CLOCK (object);
664   GstClock **master_p;
665
666   GST_OBJECT_LOCK (clock);
667   master_p = &clock->master;
668   gst_object_replace ((GstObject **) master_p, NULL);
669   GST_OBJECT_UNLOCK (clock);
670
671   G_OBJECT_CLASS (parent_class)->dispose (object);
672 }
673
674 static void
675 gst_clock_finalize (GObject * object)
676 {
677   GstClock *clock = GST_CLOCK (object);
678
679   GST_CLOCK_SLAVE_LOCK (clock);
680   if (clock->clockid) {
681     gst_clock_id_unschedule (clock->clockid);
682     gst_clock_id_unref (clock->clockid);
683     clock->clockid = NULL;
684   }
685   g_free (clock->times);
686   clock->times = NULL;
687   GST_CLOCK_SLAVE_UNLOCK (clock);
688
689   g_cond_free (clock->entries_changed);
690   g_mutex_free (clock->slave_lock);
691
692   G_OBJECT_CLASS (parent_class)->finalize (object);
693 }
694
695 /**
696  * gst_clock_set_resolution
697  * @clock: a #GstClock
698  * @resolution: The resolution to set
699  *
700  * Set the accuracy of the clock. Some clocks have the possibility to operate
701  * with different accuracy at the expense of more resource usage. There is
702  * normally no need to change the default resolution of a clock. The resolution
703  * of a clock can only be changed if the clock has the
704  * #GST_CLOCK_FLAG_CAN_SET_RESOLUTION flag set.
705  *
706  * Returns: the new resolution of the clock.
707  */
708 GstClockTime
709 gst_clock_set_resolution (GstClock * clock, GstClockTime resolution)
710 {
711   GstClockClass *cclass;
712
713   g_return_val_if_fail (GST_IS_CLOCK (clock), 0);
714   g_return_val_if_fail (resolution != 0, 0);
715
716   cclass = GST_CLOCK_GET_CLASS (clock);
717
718   if (cclass->change_resolution)
719     clock->resolution =
720         cclass->change_resolution (clock, clock->resolution, resolution);
721
722   return clock->resolution;
723 }
724
725 /**
726  * gst_clock_get_resolution
727  * @clock: a #GstClock
728  *
729  * Get the accuracy of the clock. The accuracy of the clock is the granularity
730  * of the values returned by gst_clock_get_time().
731  *
732  * Returns: the resolution of the clock in units of #GstClockTime.
733  *
734  * MT safe.
735  */
736 GstClockTime
737 gst_clock_get_resolution (GstClock * clock)
738 {
739   GstClockClass *cclass;
740
741   g_return_val_if_fail (GST_IS_CLOCK (clock), 0);
742
743   cclass = GST_CLOCK_GET_CLASS (clock);
744
745   if (cclass->get_resolution)
746     return cclass->get_resolution (clock);
747
748   return 1;
749 }
750
751 /**
752  * gst_clock_adjust_unlocked
753  * @clock: a #GstClock to use
754  * @internal: a clock time
755  *
756  * Converts the given @internal clock time to the external time, adjusting for the
757  * rate and reference time set with gst_clock_set_calibration() and making sure
758  * that the returned time is increasing. This function should be called with the
759  * clock's OBJECT_LOCK held and is mainly used by clock subclasses.
760  *
761  * This function is the reverse of gst_clock_unadjust_unlocked().
762  *
763  * Returns: the converted time of the clock.
764  */
765 GstClockTime
766 gst_clock_adjust_unlocked (GstClock * clock, GstClockTime internal)
767 {
768   GstClockTime ret, cinternal, cexternal, cnum, cdenom;
769
770   /* get calibration values for readability */
771   cinternal = clock->internal_calibration;
772   cexternal = clock->external_calibration;
773   cnum = clock->rate_numerator;
774   cdenom = clock->rate_denominator;
775
776   /* avoid divide by 0 */
777   if (G_UNLIKELY (cdenom == 0))
778     cnum = cdenom = 1;
779
780   /* The formula is (internal - cinternal) * cnum / cdenom + cexternal
781    *
782    * Since we do math on unsigned 64-bit ints we have to special case for
783    * internal < cinternal to get the sign right. this case is not very common,
784    * though.
785    */
786   if (G_LIKELY (internal >= cinternal)) {
787     ret = internal - cinternal;
788     ret = gst_util_uint64_scale (ret, cnum, cdenom);
789     ret += cexternal;
790   } else {
791     ret = cinternal - internal;
792     ret = gst_util_uint64_scale (ret, cnum, cdenom);
793     /* clamp to 0 */
794     if (G_LIKELY (cexternal > ret))
795       ret = cexternal - ret;
796     else
797       ret = 0;
798   }
799
800   /* make sure the time is increasing */
801   clock->last_time = MAX (ret, clock->last_time);
802
803   return clock->last_time;
804 }
805
806 /**
807  * gst_clock_unadjust_unlocked
808  * @clock: a #GstClock to use
809  * @external: an external clock time
810  *
811  * Converts the given @external clock time to the internal time of @clock,
812  * using the rate and reference time set with gst_clock_set_calibration().
813  * This function should be called with the clock's OBJECT_LOCK held and
814  * is mainly used by clock subclasses.
815  *
816  * This function is the reverse of gst_clock_adjust_unlocked().
817  *
818  * Returns: the internal time of the clock corresponding to @external.
819  *
820  * Since: 0.10.13
821  */
822 GstClockTime
823 gst_clock_unadjust_unlocked (GstClock * clock, GstClockTime external)
824 {
825   GstClockTime ret, cinternal, cexternal, cnum, cdenom;
826
827   /* get calibration values for readability */
828   cinternal = clock->internal_calibration;
829   cexternal = clock->external_calibration;
830   cnum = clock->rate_numerator;
831   cdenom = clock->rate_denominator;
832
833   /* avoid divide by 0 */
834   if (G_UNLIKELY (cnum == 0))
835     cnum = cdenom = 1;
836
837   /* The formula is (external - cexternal) * cdenom / cnum + cinternal */
838   if (G_LIKELY (external >= cexternal)) {
839     ret = external - cexternal;
840     ret = gst_util_uint64_scale (ret, cdenom, cnum);
841     ret += cinternal;
842   } else {
843     ret = cexternal - external;
844     ret = gst_util_uint64_scale (ret, cdenom, cnum);
845     if (G_LIKELY (cinternal > ret))
846       ret = cinternal - ret;
847     else
848       ret = 0;
849   }
850   return ret;
851 }
852
853 /**
854  * gst_clock_get_internal_time
855  * @clock: a #GstClock to query
856  *
857  * Gets the current internal time of the given clock. The time is returned
858  * unadjusted for the offset and the rate.
859  *
860  * Returns: the internal time of the clock. Or GST_CLOCK_TIME_NONE when
861  * given invalid input.
862  *
863  * MT safe.
864  */
865 GstClockTime
866 gst_clock_get_internal_time (GstClock * clock)
867 {
868   GstClockTime ret;
869   GstClockClass *cclass;
870
871   g_return_val_if_fail (GST_IS_CLOCK (clock), GST_CLOCK_TIME_NONE);
872
873   cclass = GST_CLOCK_GET_CLASS (clock);
874
875   if (G_UNLIKELY (cclass->get_internal_time == NULL))
876     goto not_supported;
877
878   ret = cclass->get_internal_time (clock);
879
880   GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "internal time %" GST_TIME_FORMAT,
881       GST_TIME_ARGS (ret));
882
883   return ret;
884
885   /* ERRORS */
886 not_supported:
887   {
888     GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
889         "internal time not supported, return 0");
890     return G_GINT64_CONSTANT (0);
891   }
892 }
893
894 /**
895  * gst_clock_get_time
896  * @clock: a #GstClock to query
897  *
898  * Gets the current time of the given clock. The time is always
899  * monotonically increasing and adjusted according to the current
900  * offset and rate.
901  *
902  * Returns: the time of the clock. Or GST_CLOCK_TIME_NONE when
903  * given invalid input.
904  *
905  * MT safe.
906  */
907 GstClockTime
908 gst_clock_get_time (GstClock * clock)
909 {
910   GstClockTime ret;
911   gint seq;
912
913   g_return_val_if_fail (GST_IS_CLOCK (clock), GST_CLOCK_TIME_NONE);
914
915   do {
916     /* reget the internal time when we retry to get the most current
917      * timevalue */
918     ret = gst_clock_get_internal_time (clock);
919
920     seq = read_seqbegin (clock);
921     /* this will scale for rate and offset */
922     ret = gst_clock_adjust_unlocked (clock, ret);
923   } while (read_seqretry (clock, seq));
924
925   GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "adjusted time %" GST_TIME_FORMAT,
926       GST_TIME_ARGS (ret));
927
928   return ret;
929 }
930
931 /**
932  * gst_clock_set_calibration
933  * @clock: a #GstClock to calibrate
934  * @internal: a reference internal time
935  * @external: a reference external time
936  * @rate_num: the numerator of the rate of the clock relative to its
937  *            internal time 
938  * @rate_denom: the denominator of the rate of the clock
939  *
940  * Adjusts the rate and time of @clock. A rate of 1/1 is the normal speed of
941  * the clock. Values bigger than 1/1 make the clock go faster.
942  *
943  * @internal and @external are calibration parameters that arrange that
944  * gst_clock_get_time() should have been @external at internal time @internal.
945  * This internal time should not be in the future; that is, it should be less
946  * than the value of gst_clock_get_internal_time() when this function is called.
947  *
948  * Subsequent calls to gst_clock_get_time() will return clock times computed as
949  * follows:
950  *
951  * <programlisting>
952  *   time = (internal_time - internal) * rate_num / rate_denom + external
953  * </programlisting>
954  *
955  * This formula is implemented in gst_clock_adjust_unlocked(). Of course, it
956  * tries to do the integer arithmetic as precisely as possible.
957  *
958  * Note that gst_clock_get_time() always returns increasing values so when you
959  * move the clock backwards, gst_clock_get_time() will report the previous value
960  * until the clock catches up.
961  *
962  * MT safe.
963  */
964 void
965 gst_clock_set_calibration (GstClock * clock, GstClockTime internal, GstClockTime
966     external, GstClockTime rate_num, GstClockTime rate_denom)
967 {
968   g_return_if_fail (GST_IS_CLOCK (clock));
969   g_return_if_fail (rate_num != GST_CLOCK_TIME_NONE);
970   g_return_if_fail (rate_denom > 0 && rate_denom != GST_CLOCK_TIME_NONE);
971
972   write_seqlock (clock);
973   GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
974       "internal %" GST_TIME_FORMAT " external %" GST_TIME_FORMAT " %"
975       G_GUINT64_FORMAT "/%" G_GUINT64_FORMAT " = %f", GST_TIME_ARGS (internal),
976       GST_TIME_ARGS (external), rate_num, rate_denom,
977       gst_guint64_to_gdouble (rate_num) / gst_guint64_to_gdouble (rate_denom));
978
979   clock->internal_calibration = internal;
980   clock->external_calibration = external;
981   clock->rate_numerator = rate_num;
982   clock->rate_denominator = rate_denom;
983   write_sequnlock (clock);
984 }
985
986 /**
987  * gst_clock_get_calibration
988  * @clock: a #GstClock 
989  * @internal: a location to store the internal time
990  * @external: a location to store the external time
991  * @rate_num: a location to store the rate numerator
992  * @rate_denom: a location to store the rate denominator
993  *
994  * Gets the internal rate and reference time of @clock. See
995  * gst_clock_set_calibration() for more information.
996  *
997  * @internal, @external, @rate_num, and @rate_denom can be left %NULL if the
998  * caller is not interested in the values.
999  *
1000  * MT safe.
1001  */
1002 void
1003 gst_clock_get_calibration (GstClock * clock, GstClockTime * internal,
1004     GstClockTime * external, GstClockTime * rate_num, GstClockTime * rate_denom)
1005 {
1006   gint seq;
1007
1008   g_return_if_fail (GST_IS_CLOCK (clock));
1009
1010   do {
1011     seq = read_seqbegin (clock);
1012     if (rate_num)
1013       *rate_num = clock->rate_numerator;
1014     if (rate_denom)
1015       *rate_denom = clock->rate_denominator;
1016     if (external)
1017       *external = clock->external_calibration;
1018     if (internal)
1019       *internal = clock->internal_calibration;
1020   } while (read_seqretry (clock, seq));
1021 }
1022
1023 /* will be called repeatedly to sample the master and slave clock
1024  * to recalibrate the clock  */
1025 static gboolean
1026 gst_clock_slave_callback (GstClock * master, GstClockTime time,
1027     GstClockID id, GstClock * clock)
1028 {
1029   GstClockTime stime, mtime;
1030   gdouble r_squared;
1031
1032   stime = gst_clock_get_internal_time (clock);
1033   mtime = gst_clock_get_time (master);
1034
1035   GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
1036       "master %" GST_TIME_FORMAT ", slave %" GST_TIME_FORMAT,
1037       GST_TIME_ARGS (mtime), GST_TIME_ARGS (stime));
1038
1039   gst_clock_add_observation (clock, stime, mtime, &r_squared);
1040
1041   /* FIXME, we can use the r_squared value to adjust the timeout
1042    * value of the clockid */
1043
1044   return TRUE;
1045 }
1046
1047 /**
1048  * gst_clock_set_master
1049  * @clock: a #GstClock 
1050  * @master: a master #GstClock 
1051  *
1052  * Set @master as the master clock for @clock. @clock will be automatically
1053  * calibrated so that gst_clock_get_time() reports the same time as the
1054  * master clock.  
1055  * 
1056  * A clock provider that slaves its clock to a master can get the current
1057  * calibration values with gst_clock_get_calibration().
1058  *
1059  * @master can be %NULL in which case @clock will not be slaved anymore. It will
1060  * however keep reporting its time adjusted with the last configured rate 
1061  * and time offsets.
1062  *
1063  * Returns: %TRUE if the clock is capable of being slaved to a master clock. 
1064  * Trying to set a master on a clock without the 
1065  * #GST_CLOCK_FLAG_CAN_SET_MASTER flag will make this function return %FALSE.
1066  *
1067  * MT safe.
1068  */
1069 gboolean
1070 gst_clock_set_master (GstClock * clock, GstClock * master)
1071 {
1072   GstClock **master_p;
1073
1074   g_return_val_if_fail (GST_IS_CLOCK (clock), FALSE);
1075   g_return_val_if_fail (master != clock, FALSE);
1076
1077   GST_OBJECT_LOCK (clock);
1078   /* we always allow setting the master to NULL */
1079   if (master && !GST_OBJECT_FLAG_IS_SET (clock, GST_CLOCK_FLAG_CAN_SET_MASTER))
1080     goto not_supported;
1081   GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
1082       "slaving %p to master clock %p", clock, master);
1083   GST_OBJECT_UNLOCK (clock);
1084
1085   GST_CLOCK_SLAVE_LOCK (clock);
1086   if (clock->clockid) {
1087     gst_clock_id_unschedule (clock->clockid);
1088     gst_clock_id_unref (clock->clockid);
1089     clock->clockid = NULL;
1090   }
1091   if (master) {
1092     clock->filling = TRUE;
1093     clock->time_index = 0;
1094     /* use the master periodic id to schedule sampling and
1095      * clock calibration. */
1096     clock->clockid = gst_clock_new_periodic_id (master,
1097         gst_clock_get_time (master), clock->timeout);
1098     gst_clock_id_wait_async_full (clock->clockid,
1099         (GstClockCallback) gst_clock_slave_callback,
1100         gst_object_ref (clock), (GDestroyNotify) gst_object_unref);
1101   }
1102   GST_CLOCK_SLAVE_UNLOCK (clock);
1103
1104   GST_OBJECT_LOCK (clock);
1105   master_p = &clock->master;
1106   gst_object_replace ((GstObject **) master_p, (GstObject *) master);
1107   GST_OBJECT_UNLOCK (clock);
1108
1109   return TRUE;
1110
1111   /* ERRORS */
1112 not_supported:
1113   {
1114     GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
1115         "cannot be slaved to a master clock");
1116     GST_OBJECT_UNLOCK (clock);
1117     return FALSE;
1118   }
1119 }
1120
1121 /**
1122  * gst_clock_get_master
1123  * @clock: a #GstClock 
1124  *
1125  * Get the master clock that @clock is slaved to or %NULL when the clock is
1126  * not slaved to any master clock.
1127  *
1128  * Returns: a master #GstClock or %NULL when this clock is not slaved to a
1129  * master clock. Unref after usage.
1130  *
1131  * MT safe.
1132  */
1133 GstClock *
1134 gst_clock_get_master (GstClock * clock)
1135 {
1136   GstClock *result = NULL;
1137
1138   g_return_val_if_fail (GST_IS_CLOCK (clock), NULL);
1139
1140   GST_OBJECT_LOCK (clock);
1141   if (clock->master)
1142     result = gst_object_ref (clock->master);
1143   GST_OBJECT_UNLOCK (clock);
1144
1145   return result;
1146 }
1147
1148 /* http://mathworld.wolfram.com/LeastSquaresFitting.html
1149  * with SLAVE_LOCK
1150  */
1151 static gboolean
1152 do_linear_regression (GstClock * clock, GstClockTime * m_num,
1153     GstClockTime * m_denom, GstClockTime * b, GstClockTime * xbase,
1154     gdouble * r_squared)
1155 {
1156   GstClockTime *newx, *newy;
1157   GstClockTime xmin, ymin, xbar, ybar, xbar4, ybar4;
1158   GstClockTimeDiff sxx, sxy, syy;
1159   GstClockTime *x, *y;
1160   gint i, j;
1161   guint n;
1162
1163   xbar = ybar = sxx = syy = sxy = 0;
1164
1165   x = clock->times;
1166   y = clock->times + 2;
1167   n = clock->filling ? clock->time_index : clock->window_size;
1168
1169 #ifdef DEBUGGING_ENABLED
1170   GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "doing regression on:");
1171   for (i = j = 0; i < n; i++, j += 4)
1172     GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
1173         "  %" G_GUINT64_FORMAT "  %" G_GUINT64_FORMAT, x[j], y[j]);
1174 #endif
1175
1176   xmin = ymin = G_MAXUINT64;
1177   for (i = j = 0; i < n; i++, j += 4) {
1178     xmin = MIN (xmin, x[j]);
1179     ymin = MIN (ymin, y[j]);
1180   }
1181
1182 #ifdef DEBUGGING_ENABLED
1183   GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "min x: %" G_GUINT64_FORMAT,
1184       xmin);
1185   GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "min y: %" G_GUINT64_FORMAT,
1186       ymin);
1187 #endif
1188
1189   newx = clock->times + 1;
1190   newy = clock->times + 3;
1191
1192   /* strip off unnecessary bits of precision */
1193   for (i = j = 0; i < n; i++, j += 4) {
1194     newx[j] = x[j] - xmin;
1195     newy[j] = y[j] - ymin;
1196   }
1197
1198 #ifdef DEBUGGING_ENABLED
1199   GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "reduced numbers:");
1200   for (i = j = 0; i < n; i++, j += 4)
1201     GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
1202         "  %" G_GUINT64_FORMAT "  %" G_GUINT64_FORMAT, newx[j], newy[j]);
1203 #endif
1204
1205   /* have to do this precisely otherwise the results are pretty much useless.
1206    * should guarantee that none of these accumulators can overflow */
1207
1208   /* quantities on the order of 1e10 -> 30 bits; window size a max of 2^10, so
1209      this addition could end up around 2^40 or so -- ample headroom */
1210   for (i = j = 0; i < n; i++, j += 4) {
1211     xbar += newx[j];
1212     ybar += newy[j];
1213   }
1214   xbar /= n;
1215   ybar /= n;
1216
1217 #ifdef DEBUGGING_ENABLED
1218   GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "  xbar  = %" G_GUINT64_FORMAT,
1219       xbar);
1220   GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "  ybar  = %" G_GUINT64_FORMAT,
1221       ybar);
1222 #endif
1223
1224   /* multiplying directly would give quantities on the order of 1e20 -> 60 bits;
1225      times the window size that's 70 which is too much. Instead we (1) subtract
1226      off the xbar*ybar in the loop instead of after, to avoid accumulation; (2)
1227      shift off 4 bits from each multiplicand, giving an expected ceiling of 52
1228      bits, which should be enough. Need to check the incoming range and domain
1229      to ensure this is an appropriate loss of precision though. */
1230   xbar4 = xbar >> 4;
1231   ybar4 = ybar >> 4;
1232   for (i = j = 0; i < n; i++, j += 4) {
1233     GstClockTime newx4, newy4;
1234
1235     newx4 = newx[j] >> 4;
1236     newy4 = newy[j] >> 4;
1237
1238     sxx += newx4 * newx4 - xbar4 * xbar4;
1239     syy += newy4 * newy4 - ybar4 * ybar4;
1240     sxy += newx4 * newy4 - xbar4 * ybar4;
1241   }
1242
1243   if (G_UNLIKELY (sxx == 0))
1244     goto invalid;
1245
1246   *m_num = sxy;
1247   *m_denom = sxx;
1248   *xbase = xmin;
1249   *b = (ybar + ymin) - gst_util_uint64_scale (xbar, *m_num, *m_denom);
1250   *r_squared = ((double) sxy * (double) sxy) / ((double) sxx * (double) syy);
1251
1252 #ifdef DEBUGGING_ENABLED
1253   GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "  m      = %g",
1254       ((double) *m_num) / *m_denom);
1255   GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "  b      = %" G_GUINT64_FORMAT,
1256       *b);
1257   GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "  xbase  = %" G_GUINT64_FORMAT,
1258       *xbase);
1259   GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "  r2     = %g", *r_squared);
1260 #endif
1261
1262   return TRUE;
1263
1264 invalid:
1265   {
1266     GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "sxx == 0, regression failed");
1267     return FALSE;
1268   }
1269 }
1270
1271 /**
1272  * gst_clock_add_observation
1273  * @clock: a #GstClock 
1274  * @slave: a time on the slave
1275  * @master: a time on the master
1276  * @r_squared: a pointer to hold the result
1277  *
1278  * The time @master of the master clock and the time @slave of the slave
1279  * clock are added to the list of observations. If enough observations
1280  * are available, a linear regression algorithm is run on the
1281  * observations and @clock is recalibrated.
1282  *
1283  * If this functions returns %TRUE, @r_squared will contain the 
1284  * correlation coefficient of the interpolation. A value of 1.0
1285  * means a perfect regression was performed. This value can
1286  * be used to control the sampling frequency of the master and slave
1287  * clocks.
1288  *
1289  * Returns: %TRUE if enough observations were added to run the 
1290  * regression algorithm.
1291  *
1292  * MT safe.
1293  */
1294 gboolean
1295 gst_clock_add_observation (GstClock * clock, GstClockTime slave,
1296     GstClockTime master, gdouble * r_squared)
1297 {
1298   GstClockTime m_num, m_denom, b, xbase;
1299
1300   g_return_val_if_fail (GST_IS_CLOCK (clock), FALSE);
1301   g_return_val_if_fail (r_squared != NULL, FALSE);
1302
1303   GST_CLOCK_SLAVE_LOCK (clock);
1304
1305   GST_CAT_LOG_OBJECT (GST_CAT_CLOCK, clock,
1306       "adding observation slave %" GST_TIME_FORMAT ", master %" GST_TIME_FORMAT,
1307       GST_TIME_ARGS (slave), GST_TIME_ARGS (master));
1308
1309   clock->times[(4 * clock->time_index)] = slave;
1310   clock->times[(4 * clock->time_index) + 2] = master;
1311
1312   clock->time_index++;
1313   if (G_UNLIKELY (clock->time_index == clock->window_size)) {
1314     clock->filling = FALSE;
1315     clock->time_index = 0;
1316   }
1317
1318   if (G_UNLIKELY (clock->filling
1319           && clock->time_index < clock->window_threshold))
1320     goto filling;
1321
1322   if (!do_linear_regression (clock, &m_num, &m_denom, &b, &xbase, r_squared))
1323     goto invalid;
1324
1325   GST_CLOCK_SLAVE_UNLOCK (clock);
1326
1327   GST_CAT_LOG_OBJECT (GST_CAT_CLOCK, clock,
1328       "adjusting clock to m=%" G_GUINT64_FORMAT "/%" G_GUINT64_FORMAT ", b=%"
1329       G_GUINT64_FORMAT " (rsquared=%g)", m_num, m_denom, b, *r_squared);
1330
1331   /* if we have a valid regression, adjust the clock */
1332   gst_clock_set_calibration (clock, xbase, b, m_num, m_denom);
1333
1334   return TRUE;
1335
1336 filling:
1337   {
1338     GST_CLOCK_SLAVE_UNLOCK (clock);
1339     return FALSE;
1340   }
1341 invalid:
1342   {
1343     /* no valid regression has been done, ignore the result then */
1344     GST_CLOCK_SLAVE_UNLOCK (clock);
1345     return TRUE;
1346   }
1347 }
1348
1349 static void
1350 gst_clock_update_stats (GstClock * clock)
1351 {
1352 }
1353
1354 static void
1355 gst_clock_set_property (GObject * object, guint prop_id,
1356     const GValue * value, GParamSpec * pspec)
1357 {
1358   GstClock *clock;
1359
1360   clock = GST_CLOCK (object);
1361
1362   switch (prop_id) {
1363     case PROP_STATS:
1364       GST_OBJECT_LOCK (clock);
1365       clock->stats = g_value_get_boolean (value);
1366       GST_OBJECT_UNLOCK (clock);
1367       g_object_notify (object, "stats");
1368       break;
1369     case PROP_WINDOW_SIZE:
1370       GST_CLOCK_SLAVE_LOCK (clock);
1371       clock->window_size = g_value_get_int (value);
1372       clock->window_threshold =
1373           MIN (clock->window_threshold, clock->window_size);
1374       clock->times =
1375           g_renew (GstClockTime, clock->times, 4 * clock->window_size);
1376       /* restart calibration */
1377       clock->filling = TRUE;
1378       clock->time_index = 0;
1379       GST_CLOCK_SLAVE_UNLOCK (clock);
1380       break;
1381     case PROP_WINDOW_THRESHOLD:
1382       GST_CLOCK_SLAVE_LOCK (clock);
1383       clock->window_threshold =
1384           MIN (g_value_get_int (value), clock->window_size);
1385       GST_CLOCK_SLAVE_UNLOCK (clock);
1386       break;
1387     case PROP_TIMEOUT:
1388       GST_CLOCK_SLAVE_LOCK (clock);
1389       clock->timeout = g_value_get_uint64 (value);
1390       GST_CLOCK_SLAVE_UNLOCK (clock);
1391       break;
1392     default:
1393       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1394       break;
1395   }
1396 }
1397
1398 static void
1399 gst_clock_get_property (GObject * object, guint prop_id,
1400     GValue * value, GParamSpec * pspec)
1401 {
1402   GstClock *clock;
1403
1404   clock = GST_CLOCK (object);
1405
1406   switch (prop_id) {
1407     case PROP_STATS:
1408       GST_OBJECT_LOCK (clock);
1409       g_value_set_boolean (value, clock->stats);
1410       GST_OBJECT_UNLOCK (clock);
1411       break;
1412     case PROP_WINDOW_SIZE:
1413       GST_CLOCK_SLAVE_LOCK (clock);
1414       g_value_set_int (value, clock->window_size);
1415       GST_CLOCK_SLAVE_UNLOCK (clock);
1416       break;
1417     case PROP_WINDOW_THRESHOLD:
1418       GST_CLOCK_SLAVE_LOCK (clock);
1419       g_value_set_int (value, clock->window_threshold);
1420       GST_CLOCK_SLAVE_UNLOCK (clock);
1421       break;
1422     case PROP_TIMEOUT:
1423       GST_CLOCK_SLAVE_LOCK (clock);
1424       g_value_set_uint64 (value, clock->timeout);
1425       GST_CLOCK_SLAVE_UNLOCK (clock);
1426       break;
1427     default:
1428       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1429       break;
1430   }
1431 }