gstreamer_core/gst/gstclock.c
changeset 16 8e837d1bf446
parent 0 0e761a78d257
child 30 7e817e7e631c
equal deleted inserted replaced
15:4b0c6ed43234 16:8e837d1bf446
    26  * @short_description: Abstract class for global clocks
    26  * @short_description: Abstract class for global clocks
    27  * @see_also: #GstSystemClock, #GstPipeline
    27  * @see_also: #GstSystemClock, #GstPipeline
    28  *
    28  *
    29  * GStreamer uses a global clock to synchronize the plugins in a pipeline.
    29  * GStreamer uses a global clock to synchronize the plugins in a pipeline.
    30  * Different clock implementations are possible by implementing this abstract
    30  * Different clock implementations are possible by implementing this abstract
    31  * base class.
    31  * base class or, more conveniently, by subclassing #GstSystemClock.
    32  *
    32  *
    33  * The #GstClock returns a monotonically increasing time with the method
    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
    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
    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
    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.
    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.
    38  * The time returned by a clock is called the absolute time.
    39  *
    39  *
    40  * The pipeline uses the clock to calculate the stream time. Usually all
    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
    41  * renderers synchronize to the global clock using the buffer timestamps, the
    42  * newsegment events and the element's base time, see #GstPipeline.
    42  * newsegment events and the element's base time, see #GstPipeline.
    43  *
    43  *
    44  * A clock implementation can support periodic and single shot clock
    44  * A clock implementation can support periodic and single shot clock
    45  * notifications both synchronous and asynchronous.
    45  * notifications both synchronous and asynchronous.
    50  *
    50  *
    51  * To perform a blocking wait for the specific time of the #GstClockID use the
    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
    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
    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
    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.
    55  * unscheduled a return value of #GST_CLOCK_UNSCHEDULED is returned.
    56  *
    56  *
    57  * Periodic callbacks scheduled async will be repeadedly called automatically
    57  * Periodic callbacks scheduled async will be repeatedly called automatically
    58  * until it is unscheduled. To schedule a sync periodic callback,
    58  * until it is unscheduled. To schedule a sync periodic callback,
    59  * gst_clock_id_wait() should be called repeadedly.
    59  * gst_clock_id_wait() should be called repeatedly.
    60  *
    60  *
    61  * The async callbacks can happen from any thread, either provided by the core
    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.
    62  * or from a streaming thread. The application should be prepared for this.
    63  *
    63  *
    64  * A #GstClockID that has been unscheduled cannot be used again for any wait
    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
    65  * operation, a new #GstClockID should be created and the old unscheduled one
    66  * should be destroyed wirth gst_clock_id_unref().
    66  * should be destroyed with gst_clock_id_unref().
    67  *
    67  *
    68  * It is possible to perform a blocking wait on the same #GstClockID from
    68  * It is possible to perform a blocking wait on the same #GstClockID from
    69  * multiple threads. However, registering the same #GstClockID for multiple
    69  * multiple threads. However, registering the same #GstClockID for multiple
    70  * async notifications is not possible, the callback will only be called for
    70  * async notifications is not possible, the callback will only be called for
    71  * the thread registering the entry last.
    71  * the thread registering the entry last.
    75  * notifications. The reason being that the owner of the #GstClockID has to
    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
    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 
    77  * state changes and if the entry would be unreffed automatically, the handle 
    78  * might become invalid without any notification.
    78  * might become invalid without any notification.
    79  *
    79  *
    80  * These clock operations do not operate on the stream time, so the callbacks
    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
    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
    82  * running. Some clocks however do not progress when the element that provided
    83  * the clock is not PLAYING.
    83  * the clock is not PLAYING.
    84  *
    84  *
    85  * When a clock has the GST_CLOCK_FLAG_CAN_SET_MASTER flag set, it can be
    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
    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
    87  * then automatically be synchronized to this master clock by repeatedly
    88  * sampling the master clock and the slave clock and recalibrating the slave
    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
    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
    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
    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
    92  * of their internal clock relative to the master clock by using the
    93  * gst_clock_get_calibration() function. 
    93  * gst_clock_get_calibration() function. 
    94  *
    94  *
    95  * The master/slave synchronisation can be tuned with the "timeout", "window-size"
    95  * The master/slave synchronisation can be tuned with the #GstClock:timeout,
    96  * and "window-threshold" properties. The "timeout" property defines the interval
    96  * #GstClock:window-size and #GstClock:window-threshold properties.
    97  * to sample the master clock and run the calibration functions. 
    97  * The #GstClock:timeout property defines the interval to sample the master
    98  * "window-size" defines the number of samples to use when calibrating and
    98  * clock and run the calibration functions. #GstClock:window-size defines the
    99  * "window-threshold" defines the minimum number of samples before the 
    99  * number of samples to use when calibrating and #GstClock:window-threshold
   100  * calibration is performed.
   100  * defines the minimum number of samples before the calibration is performed.
   101  *
   101  *
   102  * Last reviewed on 2006-08-11 (0.10.10)
   102  * Last reviewed on 2009-05-21 (0.10.24)
   103  */
   103  */
   104 
   104 
   105 
   105 
   106 #include "gst_private.h"
   106 #include "gst_private.h"
   107 #include <time.h>
   107 #include <time.h>
   117 #endif
   117 #endif
   118 
   118 
   119 #ifdef __SYMBIAN32__
   119 #ifdef __SYMBIAN32__
   120 #include <glib_global.h>
   120 #include <glib_global.h>
   121 #endif
   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 */
   122 /* #define DEBUGGING_ENABLED */
   132 
   123 
   133 #define DEFAULT_STATS                   FALSE
   124 #define DEFAULT_STATS                   FALSE
   134 #define DEFAULT_WINDOW_SIZE             32
   125 #define DEFAULT_WINDOW_SIZE             32
   135 #define DEFAULT_WINDOW_THRESHOLD        4
   126 #define DEFAULT_WINDOW_THRESHOLD        4
   142   PROP_WINDOW_SIZE,
   133   PROP_WINDOW_SIZE,
   143   PROP_WINDOW_THRESHOLD,
   134   PROP_WINDOW_THRESHOLD,
   144   PROP_TIMEOUT
   135   PROP_TIMEOUT
   145 };
   136 };
   146 
   137 
       
   138 struct _GstClockPrivate
       
   139 {
       
   140   gint pre_count;
       
   141   gint post_count;
       
   142 };
       
   143 
       
   144 /* seqlocks */
       
   145 #define read_seqbegin(clock)                                   \
       
   146   g_atomic_int_get (&clock->ABI.priv->post_count);
       
   147 
       
   148 static inline gboolean
       
   149 read_seqretry (GstClock * clock, gint seq)
       
   150 {
       
   151   /* no retry if the seqnum did not change */
       
   152   if (G_LIKELY (seq == g_atomic_int_get (&clock->ABI.priv->pre_count)))
       
   153     return FALSE;
       
   154 
       
   155   /* wait for the writer to finish and retry */
       
   156   GST_OBJECT_LOCK (clock);
       
   157   GST_OBJECT_UNLOCK (clock);
       
   158   return TRUE;
       
   159 }
       
   160 
       
   161 #define write_seqlock(clock)                      \
       
   162 G_STMT_START {                                    \
       
   163   GST_OBJECT_LOCK (clock);                        \
       
   164   g_atomic_int_inc (&clock->ABI.priv->pre_count);     \
       
   165 } G_STMT_END;
       
   166 
       
   167 #define write_sequnlock(clock)                    \
       
   168 G_STMT_START {                                    \
       
   169   g_atomic_int_inc (&clock->ABI.priv->post_count);    \
       
   170   GST_OBJECT_UNLOCK (clock);                      \
       
   171 } G_STMT_END;
       
   172 
   147 static void gst_clock_class_init (GstClockClass * klass);
   173 static void gst_clock_class_init (GstClockClass * klass);
   148 static void gst_clock_init (GstClock * clock);
   174 static void gst_clock_init (GstClock * clock);
   149 static void gst_clock_dispose (GObject * object);
   175 static void gst_clock_dispose (GObject * object);
   150 static void gst_clock_finalize (GObject * object);
   176 static void gst_clock_finalize (GObject * object);
   151 
   177 
   164 gst_clock_entry_new (GstClock * clock, GstClockTime time,
   190 gst_clock_entry_new (GstClock * clock, GstClockTime time,
   165     GstClockTime interval, GstClockEntryType type)
   191     GstClockTime interval, GstClockEntryType type)
   166 {
   192 {
   167   GstClockEntry *entry;
   193   GstClockEntry *entry;
   168 
   194 
   169   entry = ALLOC_ENTRY ();
   195   entry = g_slice_new (GstClockEntry);
   170 #ifndef GST_DISABLE_TRACE
   196 #ifndef GST_DISABLE_TRACE
   171   gst_alloc_trace_new (_gst_clock_entry_trace, entry);
   197   gst_alloc_trace_new (_gst_clock_entry_trace, entry);
   172 #endif
   198 #endif
   173   GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
   199   GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
   174       "created entry %p, time %" GST_TIME_FORMAT, entry, GST_TIME_ARGS (time));
   200       "created entry %p, time %" GST_TIME_FORMAT, entry, GST_TIME_ARGS (time));
   175 
   201 
   176   gst_atomic_int_set (&entry->refcount, 1);
   202   entry->refcount = 1;
   177   entry->clock = clock;
   203   entry->clock = clock;
   178   entry->type = type;
   204   entry->type = type;
   179   entry->time = time;
   205   entry->time = time;
   180   entry->interval = interval;
   206   entry->interval = interval;
   181   entry->status = GST_CLOCK_BUSY;
   207   entry->status = GST_CLOCK_OK;
   182   entry->func = NULL;
   208   entry->func = NULL;
   183   entry->user_data = NULL;
   209   entry->user_data = NULL;
   184 
   210 
   185   return (GstClockID) entry;
   211   return (GstClockID) entry;
   186 }
   212 }
   217   GST_CAT_DEBUG (GST_CAT_CLOCK, "freed entry %p", id);
   243   GST_CAT_DEBUG (GST_CAT_CLOCK, "freed entry %p", id);
   218 
   244 
   219 #ifndef GST_DISABLE_TRACE
   245 #ifndef GST_DISABLE_TRACE
   220   gst_alloc_trace_free (_gst_clock_entry_trace, id);
   246   gst_alloc_trace_free (_gst_clock_entry_trace, id);
   221 #endif
   247 #endif
   222   FREE_ENTRY (id);
   248   g_slice_free (GstClockEntry, id);
   223 }
   249 }
   224 
   250 
   225 /**
   251 /**
   226  * gst_clock_id_unref:
   252  * gst_clock_id_unref:
   227  * @id: The #GstClockID to unref
   253  * @id: The #GstClockID to unref
   280  * @clock: The #GstClockID to get a periodic notification id from
   306  * @clock: The #GstClockID to get a periodic notification id from
   281  * @start_time: the requested start time
   307  * @start_time: the requested start time
   282  * @interval: the requested interval
   308  * @interval: the requested interval
   283  *
   309  *
   284  * Get an ID from @clock to trigger a periodic notification.
   310  * Get an ID from @clock to trigger a periodic notification.
   285  * The periodeic notifications will be start at time start_time and
   311  * The periodic notifications will start at time @start_time and
   286  * will then be fired with the given interval. @id should be unreffed
   312  * will then be fired with the given @interval. @id should be unreffed
   287  * after usage.
   313  * after usage.
   288  *
   314  *
   289  * Returns: A #GstClockID that can be used to request the time notification.
   315  * Returns: A #GstClockID that can be used to request the time notification.
   290  *
   316  *
   291  * MT safe.
   317  * MT safe.
   363 }
   389 }
   364 
   390 
   365 /**
   391 /**
   366  * gst_clock_id_wait
   392  * gst_clock_id_wait
   367  * @id: The #GstClockID to wait on
   393  * @id: The #GstClockID to wait on
   368  * @jitter: A pointer that will contain the jitter, can be NULL.
   394  * @jitter: A pointer that will contain the jitter, can be %NULL.
   369  *
   395  *
   370  * Perform a blocking wait on @id. 
   396  * Perform a blocking wait on @id. 
   371  * @id should have been created with gst_clock_new_single_shot_id()
   397  * @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
   398  * or gst_clock_new_periodic_id() and should not have been unscheduled
   373  * with a call to gst_clock_id_unschedule(). 
   399  * with a call to gst_clock_id_unschedule(). 
   374  *
   400  *
   375  * If the @jitter argument is not NULL and this function returns #GST_CLOCK_OK
   401  * If the @jitter argument is not %NULL and this function returns #GST_CLOCK_OK
   376  * or #GST_CLOCK_EARLY, it will contain the difference
   402  * or #GST_CLOCK_EARLY, it will contain the difference
   377  * against the clock and the time of @id when this method was
   403  * against the clock and the time of @id when this method was
   378  * called. 
   404  * called. 
   379  * Positive values indicate how late @id was relative to the clock
   405  * Positive values indicate how late @id was relative to the clock
   380  * (in which case this function will return #GST_CLOCK_EARLY). 
   406  * (in which case this function will return #GST_CLOCK_EARLY). 
   409   clock = GST_CLOCK_ENTRY_CLOCK (entry);
   435   clock = GST_CLOCK_ENTRY_CLOCK (entry);
   410 
   436 
   411   /* can't sync on invalid times */
   437   /* can't sync on invalid times */
   412   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (requested)))
   438   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (requested)))
   413     goto invalid_time;
   439     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 
   440 
   419   cclass = GST_CLOCK_GET_CLASS (clock);
   441   cclass = GST_CLOCK_GET_CLASS (clock);
   420 
   442 
   421   GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "waiting on clock entry %p", id);
   443   GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "waiting on clock entry %p", id);
   422 
   444 
   446       "done waiting entry %p, res: %d", id, res);
   468       "done waiting entry %p, res: %d", id, res);
   447 
   469 
   448   if (entry->type == GST_CLOCK_ENTRY_PERIODIC)
   470   if (entry->type == GST_CLOCK_ENTRY_PERIODIC)
   449     entry->time = requested + entry->interval;
   471     entry->time = requested + entry->interval;
   450 
   472 
   451   if (clock->stats)
   473   if (G_UNLIKELY (clock->stats))
   452     gst_clock_update_stats (clock);
   474     gst_clock_update_stats (clock);
   453 
   475 
   454   return res;
   476   return res;
   455 
   477 
   456   /* ERRORS */
   478   /* ERRORS */
   458   {
   480   {
   459     GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
   481     GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
   460         "invalid time requested, returning _BADTIME");
   482         "invalid time requested, returning _BADTIME");
   461     return GST_CLOCK_BADTIME;
   483     return GST_CLOCK_BADTIME;
   462   }
   484   }
   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:
   485 not_supported:
   470   {
   486   {
   471     GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "clock wait is not supported");
   487     GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "clock wait is not supported");
   472     return GST_CLOCK_UNSUPPORTED;
   488     return GST_CLOCK_UNSUPPORTED;
   473   }
   489   }
   475 
   491 
   476 /**
   492 /**
   477  * gst_clock_id_wait_async:
   493  * gst_clock_id_wait_async:
   478  * @id: a #GstClockID to wait on
   494  * @id: a #GstClockID to wait on
   479  * @func: The callback function
   495  * @func: The callback function
   480  * @user_data: User data passed in the calback
   496  * @user_data: User data passed in the callback
   481  *
   497  *
   482  * Register a callback on the given #GstClockID @id with the given
   498  * Register a callback on the given #GstClockID @id with the given
   483  * function and user_data. When passing a #GstClockID with an invalid
   499  * function and user_data. When passing a #GstClockID with an invalid
   484  * time to this function, the callback will be called immediatly
   500  * time to this function, the callback will be called immediately
   485  * with  a time set to GST_CLOCK_TIME_NONE. The callback will
   501  * with  a time set to GST_CLOCK_TIME_NONE. The callback will
   486  * be called when the time of @id has been reached.
   502  * be called when the time of @id has been reached.
       
   503  *
       
   504  * The callback @func can be invoked from any thread, either provided by the
       
   505  * core or from a streaming thread. The application should be prepared for this.
   487  *
   506  *
   488  * Returns: the result of the non blocking wait.
   507  * Returns: the result of the non blocking wait.
   489  *
   508  *
   490  * MT safe.
   509  * MT safe.
   491  */
   510  */
   511   clock = GST_CLOCK_ENTRY_CLOCK (entry);
   530   clock = GST_CLOCK_ENTRY_CLOCK (entry);
   512 
   531 
   513   /* can't sync on invalid times */
   532   /* can't sync on invalid times */
   514   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (requested)))
   533   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (requested)))
   515     goto invalid_time;
   534     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 
   535 
   521   cclass = GST_CLOCK_GET_CLASS (clock);
   536   cclass = GST_CLOCK_GET_CLASS (clock);
   522 
   537 
   523   if (G_UNLIKELY (cclass->wait_async == NULL))
   538   if (G_UNLIKELY (cclass->wait_async == NULL))
   524     goto not_supported;
   539     goto not_supported;
   536     (func) (clock, GST_CLOCK_TIME_NONE, id, user_data);
   551     (func) (clock, GST_CLOCK_TIME_NONE, id, user_data);
   537     GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
   552     GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
   538         "invalid time requested, returning _BADTIME");
   553         "invalid time requested, returning _BADTIME");
   539     return GST_CLOCK_BADTIME;
   554     return GST_CLOCK_BADTIME;
   540   }
   555   }
   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:
   556 not_supported:
   548   {
   557   {
   549     GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "clock wait is not supported");
   558     GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "clock wait is not supported");
   550     return GST_CLOCK_UNSUPPORTED;
   559     return GST_CLOCK_UNSUPPORTED;
   551   }
   560   }
   583   if (G_LIKELY (cclass->unschedule))
   592   if (G_LIKELY (cclass->unschedule))
   584     cclass->unschedule (clock, entry);
   593     cclass->unschedule (clock, entry);
   585 }
   594 }
   586 
   595 
   587 
   596 
   588 /**
   597 /*
   589  * GstClock abstract base class implementation
   598  * GstClock abstract base class implementation
   590  */
   599  */
   591 #ifdef __SYMBIAN32__
   600 G_DEFINE_TYPE (GstClock, gst_clock, GST_TYPE_OBJECT);
   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 
   601 
   620 static void
   602 static void
   621 gst_clock_class_init (GstClockClass * klass)
   603 gst_clock_class_init (GstClockClass * klass)
   622 {
   604 {
   623   GObjectClass *gobject_class;
   605   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
   624   GstObjectClass *gstobject_class;
       
   625 
       
   626   gobject_class = G_OBJECT_CLASS (klass);
       
   627   gstobject_class = GST_OBJECT_CLASS (klass);
       
   628 
   606 
   629   parent_class = g_type_class_peek_parent (klass);
   607   parent_class = g_type_class_peek_parent (klass);
   630 
       
   631   if (!g_thread_supported ())
       
   632     g_thread_init (NULL);
       
   633 
   608 
   634 #ifndef GST_DISABLE_TRACE
   609 #ifndef GST_DISABLE_TRACE
   635   _gst_clock_entry_trace =
   610   _gst_clock_entry_trace =
   636       gst_alloc_trace_register (GST_CLOCK_ENTRY_TRACE_NAME);
   611       gst_alloc_trace_register (GST_CLOCK_ENTRY_TRACE_NAME);
   637 #endif
   612 #endif
   642   gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_clock_get_property);
   617   gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_clock_get_property);
   643 
   618 
   644   g_object_class_install_property (gobject_class, PROP_STATS,
   619   g_object_class_install_property (gobject_class, PROP_STATS,
   645       g_param_spec_boolean ("stats", "Stats",
   620       g_param_spec_boolean ("stats", "Stats",
   646           "Enable clock stats (unimplemented)", DEFAULT_STATS,
   621           "Enable clock stats (unimplemented)", DEFAULT_STATS,
   647           G_PARAM_READWRITE));
   622           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   648   g_object_class_install_property (gobject_class, PROP_WINDOW_SIZE,
   623   g_object_class_install_property (gobject_class, PROP_WINDOW_SIZE,
   649       g_param_spec_int ("window-size", "Window size",
   624       g_param_spec_int ("window-size", "Window size",
   650           "The size of the window used to calculate rate and offset", 2, 1024,
   625           "The size of the window used to calculate rate and offset", 2, 1024,
   651           DEFAULT_WINDOW_SIZE, G_PARAM_READWRITE));
   626           DEFAULT_WINDOW_SIZE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   652   g_object_class_install_property (gobject_class, PROP_WINDOW_THRESHOLD,
   627   g_object_class_install_property (gobject_class, PROP_WINDOW_THRESHOLD,
   653       g_param_spec_int ("window-threshold", "Window threshold",
   628       g_param_spec_int ("window-threshold", "Window threshold",
   654           "The threshold to start calculating rate and offset", 2, 1024,
   629           "The threshold to start calculating rate and offset", 2, 1024,
   655           DEFAULT_WINDOW_THRESHOLD, G_PARAM_READWRITE));
   630           DEFAULT_WINDOW_THRESHOLD,
       
   631           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   656   g_object_class_install_property (gobject_class, PROP_TIMEOUT,
   632   g_object_class_install_property (gobject_class, PROP_TIMEOUT,
   657       g_param_spec_uint64 ("timeout", "Timeout",
   633       g_param_spec_uint64 ("timeout", "Timeout",
   658           "The amount of time, in nanoseconds, to sample master and slave clocks",
   634           "The amount of time, in nanoseconds, to sample master and slave clocks",
   659           0, G_MAXUINT64, DEFAULT_TIMEOUT, G_PARAM_READWRITE));
   635           0, G_MAXUINT64, DEFAULT_TIMEOUT,
       
   636           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
       
   637 
       
   638   g_type_class_add_private (klass, sizeof (GstClockPrivate));
   660 }
   639 }
   661 
   640 
   662 static void
   641 static void
   663 gst_clock_init (GstClock * clock)
   642 gst_clock_init (GstClock * clock)
   664 {
   643 {
   665   clock->last_time = 0;
   644   clock->last_time = 0;
   666   clock->entries = NULL;
   645   clock->entries = NULL;
   667   clock->entries_changed = g_cond_new ();
   646   clock->entries_changed = g_cond_new ();
   668   clock->stats = FALSE;
   647   clock->stats = FALSE;
       
   648 
       
   649   clock->ABI.priv =
       
   650       G_TYPE_INSTANCE_GET_PRIVATE (clock, GST_TYPE_CLOCK, GstClockPrivate);
   669 
   651 
   670   clock->internal_calibration = 0;
   652   clock->internal_calibration = 0;
   671   clock->external_calibration = 0;
   653   clock->external_calibration = 0;
   672   clock->rate_numerator = 1;
   654   clock->rate_numerator = 1;
   673   clock->rate_denominator = 1;
   655   clock->rate_denominator = 1;
   788  * Converts the given @internal clock time to the external time, adjusting for the
   770  * 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
   771  * 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
   772  * 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.
   773  * clock's OBJECT_LOCK held and is mainly used by clock subclasses.
   792  *
   774  *
   793  * This function is te reverse of gst_clock_unadjust_unlocked().
   775  * This function is the reverse of gst_clock_unadjust_unlocked().
   794  *
   776  *
   795  * Returns: the converted time of the clock.
   777  * Returns: the converted time of the clock.
   796  */
   778  */
   797 #ifdef __SYMBIAN32__
   779 #ifdef __SYMBIAN32__
   798 EXPORT_C
   780 EXPORT_C
   808   cexternal = clock->external_calibration;
   790   cexternal = clock->external_calibration;
   809   cnum = clock->rate_numerator;
   791   cnum = clock->rate_numerator;
   810   cdenom = clock->rate_denominator;
   792   cdenom = clock->rate_denominator;
   811 
   793 
   812   /* avoid divide by 0 */
   794   /* avoid divide by 0 */
   813   if (cdenom == 0)
   795   if (G_UNLIKELY (cdenom == 0))
   814     cnum = cdenom = 1;
   796     cnum = cdenom = 1;
   815 
   797 
   816   /* The formula is (internal - cinternal) * cnum / cdenom + cexternal
   798   /* The formula is (internal - cinternal) * cnum / cdenom + cexternal
   817    *
   799    *
   818    * Since we do math on unsigned 64-bit ints we have to special case for
   800    * 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,
   801    * internal < cinternal to get the sign right. this case is not very common,
   820    * though.
   802    * though.
   821    */
   803    */
   822   if (G_LIKELY (internal >= cinternal)) {
   804   if (G_LIKELY (internal >= cinternal)) {
   823     ret = gst_util_uint64_scale (internal - cinternal, cnum, cdenom);
   805     ret = internal - cinternal;
       
   806     ret = gst_util_uint64_scale (ret, cnum, cdenom);
   824     ret += cexternal;
   807     ret += cexternal;
   825   } else {
   808   } else {
   826     ret = gst_util_uint64_scale (cinternal - internal, cnum, cdenom);
   809     ret = cinternal - internal;
       
   810     ret = gst_util_uint64_scale (ret, cnum, cdenom);
   827     /* clamp to 0 */
   811     /* clamp to 0 */
   828     if (cexternal > ret)
   812     if (G_LIKELY (cexternal > ret))
   829       ret = cexternal - ret;
   813       ret = cexternal - ret;
   830     else
   814     else
   831       ret = 0;
   815       ret = 0;
   832   }
   816   }
   833 
   817 
   845  * Converts the given @external clock time to the internal time of @clock,
   829  * 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().
   830  * 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
   831  * This function should be called with the clock's OBJECT_LOCK held and
   848  * is mainly used by clock subclasses.
   832  * is mainly used by clock subclasses.
   849  *
   833  *
   850  * This function is te reverse of gst_clock_adjust_unlocked().
   834  * This function is the reverse of gst_clock_adjust_unlocked().
   851  *
   835  *
   852  * Returns: the internal time of the clock corresponding to @external.
   836  * Returns: the internal time of the clock corresponding to @external.
   853  *
   837  *
   854  * Since: 0.10.13
   838  * Since: 0.10.13
   855  */
   839  */
   867   cexternal = clock->external_calibration;
   851   cexternal = clock->external_calibration;
   868   cnum = clock->rate_numerator;
   852   cnum = clock->rate_numerator;
   869   cdenom = clock->rate_denominator;
   853   cdenom = clock->rate_denominator;
   870 
   854 
   871   /* avoid divide by 0 */
   855   /* avoid divide by 0 */
   872   if (cnum == 0)
   856   if (G_UNLIKELY (cnum == 0))
   873     cnum = cdenom = 1;
   857     cnum = cdenom = 1;
   874 
   858 
   875   /* The formula is (external - cexternal) * cdenom / cnum + cinternal */
   859   /* The formula is (external - cexternal) * cdenom / cnum + cinternal */
   876   if (external >= cexternal) {
   860   if (G_LIKELY (external >= cexternal)) {
   877     ret = gst_util_uint64_scale (external - cexternal, cdenom, cnum);
   861     ret = external - cexternal;
       
   862     ret = gst_util_uint64_scale (ret, cdenom, cnum);
   878     ret += cinternal;
   863     ret += cinternal;
   879   } else {
   864   } else {
   880     ret = gst_util_uint64_scale (cexternal - external, cdenom, cnum);
   865     ret = cexternal - external;
   881     if (cinternal > ret)
   866     ret = gst_util_uint64_scale (ret, cdenom, cnum);
       
   867     if (G_LIKELY (cinternal > ret))
   882       ret = cinternal - ret;
   868       ret = cinternal - ret;
   883     else
   869     else
   884       ret = 0;
   870       ret = 0;
   885   }
   871   }
   886   return ret;
   872   return ret;
   892  *
   878  *
   893  * Gets the current internal time of the given clock. The time is returned
   879  * Gets the current internal time of the given clock. The time is returned
   894  * unadjusted for the offset and the rate.
   880  * unadjusted for the offset and the rate.
   895  *
   881  *
   896  * Returns: the internal time of the clock. Or GST_CLOCK_TIME_NONE when
   882  * Returns: the internal time of the clock. Or GST_CLOCK_TIME_NONE when
   897  * giving wrong input.
   883  * given invalid input.
   898  *
   884  *
   899  * MT safe.
   885  * MT safe.
   900  */
   886  */
   901 #ifdef __SYMBIAN32__
   887 #ifdef __SYMBIAN32__
   902 EXPORT_C
   888 EXPORT_C
   938  * Gets the current time of the given clock. The time is always
   924  * Gets the current time of the given clock. The time is always
   939  * monotonically increasing and adjusted according to the current
   925  * monotonically increasing and adjusted according to the current
   940  * offset and rate.
   926  * offset and rate.
   941  *
   927  *
   942  * Returns: the time of the clock. Or GST_CLOCK_TIME_NONE when
   928  * Returns: the time of the clock. Or GST_CLOCK_TIME_NONE when
   943  * giving wrong input.
   929  * given invalid input.
   944  *
   930  *
   945  * MT safe.
   931  * MT safe.
   946  */
   932  */
   947 #ifdef __SYMBIAN32__
   933 #ifdef __SYMBIAN32__
   948 EXPORT_C
   934 EXPORT_C
   950 
   936 
   951 GstClockTime
   937 GstClockTime
   952 gst_clock_get_time (GstClock * clock)
   938 gst_clock_get_time (GstClock * clock)
   953 {
   939 {
   954   GstClockTime ret;
   940   GstClockTime ret;
       
   941   gint seq;
   955 
   942 
   956   g_return_val_if_fail (GST_IS_CLOCK (clock), GST_CLOCK_TIME_NONE);
   943   g_return_val_if_fail (GST_IS_CLOCK (clock), GST_CLOCK_TIME_NONE);
   957 
   944 
   958   ret = gst_clock_get_internal_time (clock);
   945   do {
   959 
   946     /* reget the internal time when we retry to get the most current
   960   GST_OBJECT_LOCK (clock);
   947      * timevalue */
   961   /* this will scale for rate and offset */
   948     ret = gst_clock_get_internal_time (clock);
   962   ret = gst_clock_adjust_unlocked (clock, ret);
   949 
   963   GST_OBJECT_UNLOCK (clock);
   950     seq = read_seqbegin (clock);
       
   951     /* this will scale for rate and offset */
       
   952     ret = gst_clock_adjust_unlocked (clock, ret);
       
   953   } while (read_seqretry (clock, seq));
   964 
   954 
   965   GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "adjusted time %" GST_TIME_FORMAT,
   955   GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "adjusted time %" GST_TIME_FORMAT,
   966       GST_TIME_ARGS (ret));
   956       GST_TIME_ARGS (ret));
   967 
   957 
   968   return ret;
   958   return ret;
   987  *
   977  *
   988  * Subsequent calls to gst_clock_get_time() will return clock times computed as
   978  * Subsequent calls to gst_clock_get_time() will return clock times computed as
   989  * follows:
   979  * follows:
   990  *
   980  *
   991  * <programlisting>
   981  * <programlisting>
   992  *   time = (internal_time - @internal) * @rate_num / @rate_denom + @external
   982  *   time = (internal_time - internal) * rate_num / rate_denom + external
   993  * </programlisting>
   983  * </programlisting>
   994  *
   984  *
   995  * This formula is implemented in gst_clock_adjust_unlocked(). Of course, it
   985  * This formula is implemented in gst_clock_adjust_unlocked(). Of course, it
   996  * tries to do the integer arithmetic as precisely as possible.
   986  * tries to do the integer arithmetic as precisely as possible.
   997  *
   987  *
  1008 void
   998 void
  1009 gst_clock_set_calibration (GstClock * clock, GstClockTime internal, GstClockTime
   999 gst_clock_set_calibration (GstClock * clock, GstClockTime internal, GstClockTime
  1010     external, GstClockTime rate_num, GstClockTime rate_denom)
  1000     external, GstClockTime rate_num, GstClockTime rate_denom)
  1011 {
  1001 {
  1012   g_return_if_fail (GST_IS_CLOCK (clock));
  1002   g_return_if_fail (GST_IS_CLOCK (clock));
  1013   g_return_if_fail (rate_num >= 0);
  1003   g_return_if_fail (rate_num != GST_CLOCK_TIME_NONE);
  1014   g_return_if_fail (rate_denom > 0);
  1004   g_return_if_fail (rate_denom > 0 && rate_denom != GST_CLOCK_TIME_NONE);
  1015   g_return_if_fail (internal <= gst_clock_get_internal_time (clock));
  1005 
  1016 
  1006   write_seqlock (clock);
  1017   GST_OBJECT_LOCK (clock);
       
  1018   GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
  1007   GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
  1019       "internal %" GST_TIME_FORMAT " external %" GST_TIME_FORMAT " %"
  1008       "internal %" GST_TIME_FORMAT " external %" GST_TIME_FORMAT " %"
  1020       G_GUINT64_FORMAT "/%" G_GUINT64_FORMAT " = %f", GST_TIME_ARGS (internal),
  1009       G_GUINT64_FORMAT "/%" G_GUINT64_FORMAT " = %f", GST_TIME_ARGS (internal),
  1021       GST_TIME_ARGS (external), rate_num, rate_denom,
  1010       GST_TIME_ARGS (external), rate_num, rate_denom,
  1022       gst_guint64_to_gdouble (rate_num / rate_denom));
  1011       gst_guint64_to_gdouble (rate_num) / gst_guint64_to_gdouble (rate_denom));
  1023 
  1012 
  1024   clock->internal_calibration = internal;
  1013   clock->internal_calibration = internal;
  1025   clock->external_calibration = external;
  1014   clock->external_calibration = external;
  1026   clock->rate_numerator = rate_num;
  1015   clock->rate_numerator = rate_num;
  1027   clock->rate_denominator = rate_denom;
  1016   clock->rate_denominator = rate_denom;
  1028   GST_OBJECT_UNLOCK (clock);
  1017   write_sequnlock (clock);
  1029 }
  1018 }
  1030 
  1019 
  1031 /**
  1020 /**
  1032  * gst_clock_get_calibration
  1021  * gst_clock_get_calibration
  1033  * @clock: a #GstClock 
  1022  * @clock: a #GstClock 
  1037  * @rate_denom: a location to store the rate denominator
  1026  * @rate_denom: a location to store the rate denominator
  1038  *
  1027  *
  1039  * Gets the internal rate and reference time of @clock. See
  1028  * Gets the internal rate and reference time of @clock. See
  1040  * gst_clock_set_calibration() for more information.
  1029  * gst_clock_set_calibration() for more information.
  1041  *
  1030  *
  1042  * @internal, @external, @rate_num, and @rate_denom can be left NULL if the
  1031  * @internal, @external, @rate_num, and @rate_denom can be left %NULL if the
  1043  * caller is not interested in the values.
  1032  * caller is not interested in the values.
  1044  *
  1033  *
  1045  * MT safe.
  1034  * MT safe.
  1046  */
  1035  */
  1047 #ifdef __SYMBIAN32__
  1036 #ifdef __SYMBIAN32__
  1050 
  1039 
  1051 void
  1040 void
  1052 gst_clock_get_calibration (GstClock * clock, GstClockTime * internal,
  1041 gst_clock_get_calibration (GstClock * clock, GstClockTime * internal,
  1053     GstClockTime * external, GstClockTime * rate_num, GstClockTime * rate_denom)
  1042     GstClockTime * external, GstClockTime * rate_num, GstClockTime * rate_denom)
  1054 {
  1043 {
       
  1044   gint seq;
       
  1045 
  1055   g_return_if_fail (GST_IS_CLOCK (clock));
  1046   g_return_if_fail (GST_IS_CLOCK (clock));
  1056 
  1047 
  1057   GST_OBJECT_LOCK (clock);
  1048   do {
  1058   if (rate_num)
  1049     seq = read_seqbegin (clock);
  1059     *rate_num = clock->rate_numerator;
  1050     if (rate_num)
  1060   if (rate_denom)
  1051       *rate_num = clock->rate_numerator;
  1061     *rate_denom = clock->rate_denominator;
  1052     if (rate_denom)
  1062   if (external)
  1053       *rate_denom = clock->rate_denominator;
  1063     *external = clock->external_calibration;
  1054     if (external)
  1064   if (internal)
  1055       *external = clock->external_calibration;
  1065     *internal = clock->internal_calibration;
  1056     if (internal)
  1066   GST_OBJECT_UNLOCK (clock);
  1057       *internal = clock->internal_calibration;
  1067 }
  1058   } while (read_seqretry (clock, seq));
  1068 
  1059 }
  1069 /* will be called repeadedly to sample the master and slave clock
  1060 
       
  1061 /* will be called repeatedly to sample the master and slave clock
  1070  * to recalibrate the clock  */
  1062  * to recalibrate the clock  */
  1071 static gboolean
  1063 static gboolean
  1072 gst_clock_slave_callback (GstClock * master, GstClockTime time,
  1064 gst_clock_slave_callback (GstClock * master, GstClockTime time,
  1073     GstClockID id, GstClock * clock)
  1065     GstClockID id, GstClock * clock)
  1074 {
  1066 {
  1100  * master clock.  
  1092  * master clock.  
  1101  * 
  1093  * 
  1102  * A clock provider that slaves its clock to a master can get the current
  1094  * A clock provider that slaves its clock to a master can get the current
  1103  * calibration values with gst_clock_get_calibration().
  1095  * calibration values with gst_clock_get_calibration().
  1104  *
  1096  *
  1105  * @master can be NULL in which case @clock will not be slaved anymore. It will
  1097  * @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 
  1098  * however keep reporting its time adjusted with the last configured rate 
  1107  * and time offsets.
  1099  * and time offsets.
  1108  *
  1100  *
  1109  * Returns: TRUE if the clock is capable of being slaved to a master clock. 
  1101  * 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 
  1102  * Trying to set a master on a clock without the 
  1111  * GST_CLOCK_FLAG_CAN_SET_MASTER flag will make this function return FALSE.
  1103  * #GST_CLOCK_FLAG_CAN_SET_MASTER flag will make this function return %FALSE.
  1112  *
  1104  *
  1113  * MT safe.
  1105  * MT safe.
  1114  */
  1106  */
  1115 #ifdef __SYMBIAN32__
  1107 #ifdef __SYMBIAN32__
  1116 EXPORT_C
  1108 EXPORT_C
  1167 
  1159 
  1168 /**
  1160 /**
  1169  * gst_clock_get_master
  1161  * gst_clock_get_master
  1170  * @clock: a #GstClock 
  1162  * @clock: a #GstClock 
  1171  *
  1163  *
  1172  * Get the master clock that @clock is slaved to or NULL when the clock is
  1164  * Get the master clock that @clock is slaved to or %NULL when the clock is
  1173  * not slaved to any master clock.
  1165  * not slaved to any master clock.
  1174  *
  1166  *
  1175  * Returns: a master #GstClock or NULL when this clock is not slaved to a master
  1167  * Returns: a master #GstClock or %NULL when this clock is not slaved to a
  1176  * clock. Unref after usage.
  1168  * master clock. Unref after usage.
  1177  *
  1169  *
  1178  * MT safe.
  1170  * MT safe.
  1179  */
  1171  */
  1180 #ifdef __SYMBIAN32__
  1172 #ifdef __SYMBIAN32__
  1181 EXPORT_C
  1173 EXPORT_C
  1330  * clock are added to the list of observations. If enough observations
  1322  * clock are added to the list of observations. If enough observations
  1331  * are available, a linear regression algorithm is run on the
  1323  * are available, a linear regression algorithm is run on the
  1332  * observations and @clock is recalibrated.
  1324  * observations and @clock is recalibrated.
  1333  *
  1325  *
  1334  * If this functions returns %TRUE, @r_squared will contain the 
  1326  * If this functions returns %TRUE, @r_squared will contain the 
  1335  * correlation coefficient of the interpollation. A value of 1.0
  1327  * correlation coefficient of the interpolation. A value of 1.0
  1336  * means a perfect regression was performed. This value can
  1328  * means a perfect regression was performed. This value can
  1337  * be used to control the sampling frequency of the master and slave
  1329  * be used to control the sampling frequency of the master and slave
  1338  * clocks.
  1330  * clocks.
  1339  *
  1331  *
  1340  * Returns: TRUE if enough observations were added to run the 
  1332  * Returns: %TRUE if enough observations were added to run the 
  1341  * regression algorithm.
  1333  * regression algorithm.
  1342  *
  1334  *
  1343  * MT safe.
  1335  * MT safe.
  1344  */
  1336  */
  1345 #ifdef __SYMBIAN32__
  1337 #ifdef __SYMBIAN32__
  1354 
  1346 
  1355   g_return_val_if_fail (GST_IS_CLOCK (clock), FALSE);
  1347   g_return_val_if_fail (GST_IS_CLOCK (clock), FALSE);
  1356   g_return_val_if_fail (r_squared != NULL, FALSE);
  1348   g_return_val_if_fail (r_squared != NULL, FALSE);
  1357 
  1349 
  1358   GST_CLOCK_SLAVE_LOCK (clock);
  1350   GST_CLOCK_SLAVE_LOCK (clock);
       
  1351 
       
  1352   GST_CAT_LOG_OBJECT (GST_CAT_CLOCK, clock,
       
  1353       "adding observation slave %" GST_TIME_FORMAT ", master %" GST_TIME_FORMAT,
       
  1354       GST_TIME_ARGS (slave), GST_TIME_ARGS (master));
  1359 
  1355 
  1360   clock->times[(4 * clock->time_index)] = slave;
  1356   clock->times[(4 * clock->time_index)] = slave;
  1361   clock->times[(4 * clock->time_index) + 2] = master;
  1357   clock->times[(4 * clock->time_index) + 2] = master;
  1362 
  1358 
  1363   clock->time_index++;
  1359   clock->time_index++;