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