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