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