gstclock.c 17.7 KB
Newer Older
1 2 3 4 5
/* GStreamer
 * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
 *                    2000 Wim Taymans <wtay@chello.be>
 *
 * gstclock.c: Clock subsystem for maintaining time sync
Wim Taymans's avatar
Wim Taymans committed
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

#include <sys/time.h>
24 25

#include "gst_private.h"
26

27
#include "gstclock.h"
28
#include "gstinfo.h"
29
#include "gstmemchunk.h"
Wim Taymans's avatar
Wim Taymans committed
30

Wim Taymans's avatar
Wim Taymans committed
31
#ifndef GST_DISABLE_TRACE
Wim Taymans's avatar
Wim Taymans committed
32
/* #define GST_WITH_ALLOC_TRACE */
Wim Taymans's avatar
Wim Taymans committed
33 34 35
#include "gsttrace.h"
static GstAllocTrace *_gst_clock_entry_trace;
#endif
Wim Taymans's avatar
Wim Taymans committed
36

37
#define DEFAULT_EVENT_DIFF	(GST_SECOND)
38 39
#define DEFAULT_MAX_DIFF	(2 * GST_SECOND)

40 41 42
enum {
  ARG_0,
  ARG_STATS,
43 44
  ARG_MAX_DIFF,
  ARG_EVENT_DIFF
45 46
};

Wim Taymans's avatar
Wim Taymans committed
47
static GstMemChunk   *_gst_clock_entries_chunk;
Wim Taymans's avatar
Wim Taymans committed
48

49 50 51
void			gst_clock_id_unlock		(GstClockID id);

  
52 53
static void		gst_clock_class_init		(GstClockClass *klass);
static void		gst_clock_init			(GstClock *clock);
Wim Taymans's avatar
Wim Taymans committed
54 55
static void 		gst_clock_dispose 		(GObject *object);

56 57 58 59 60
static void             gst_clock_set_property		(GObject *object, guint prop_id, 
							 const GValue *value, GParamSpec *pspec);
static void             gst_clock_get_property		(GObject *object, guint prop_id, 
							 GValue *value, GParamSpec * pspec);
static void		gst_clock_update_stats		(GstClock *clock);
61

62

63 64 65
static GstObjectClass *parent_class = NULL;
/* static guint gst_clock_signals[LAST_SIGNAL] = { 0 }; */

Wim Taymans's avatar
Wim Taymans committed
66
static GstClockID
67 68 69 70
gst_clock_entry_new (GstClock *clock, GstClockTime time, 
		     GstClockTime interval, GstClockEntryType type)
{
  GstClockEntry *entry;
71

72
  entry = gst_mem_chunk_alloc (_gst_clock_entries_chunk);
Wim Taymans's avatar
Wim Taymans committed
73
#ifndef GST_DISABLE_TRACE
Wim Taymans's avatar
Wim Taymans committed
74
  gst_alloc_trace_new (_gst_clock_entry_trace, entry);
Wim Taymans's avatar
Wim Taymans committed
75
#endif
76

77 78 79 80 81
  entry->clock = clock;
  entry->time = time;
  entry->interval = time;
  entry->type = type;
  entry->status = GST_CLOCK_ENTRY_OK;
82

83 84
  return (GstClockID) entry;
}
85

86 87 88 89 90 91 92 93 94 95 96 97 98
/**
 * gst_clock_new_single_shot_id
 * @clock: The clockid to get a single shot notification from
 * @time: the requested time
 *
 * Get an ID from the given clock to trigger a single shot 
 * notification at the requested time.
 *
 * Returns: An id that can be used to request the time notification.
 */
GstClockID
gst_clock_new_single_shot_id (GstClock *clock, GstClockTime time)
{
99 100
  g_return_val_if_fail (GST_IS_CLOCK (clock), NULL);

101 102 103 104 105 106 107
  return gst_clock_entry_new (clock, 
		  	      time, 
			      GST_CLOCK_TIME_NONE, 
			      GST_CLOCK_ENTRY_SINGLE);
}

/**
Wim Taymans's avatar
Wim Taymans committed
108
 * gst_clock_new_periodic_id
109 110 111 112 113 114 115 116 117 118 119 120 121 122
 * @clock: The clockid to get a periodic notification id from
 * @start_time: the requested start time
 * @interval: the requested interval
 *
 * Get an ID from the given clock to trigger a periodic notification.
 * The periodeic notifications will be start at time start_time and
 * will then be fired with the given interval.
 *
 * Returns: An id that can be used to request the time notification.
 */
GstClockID
gst_clock_new_periodic_id (GstClock *clock, GstClockTime start_time,
                           GstClockTime interval)
{
123
  g_return_val_if_fail (GST_IS_CLOCK (clock), NULL);
124
  g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (start_time), NULL);
125 126
  g_return_val_if_fail (interval != 0, NULL);

127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
  return gst_clock_entry_new (clock, 
		  	      start_time, 
			      interval, 
			      GST_CLOCK_ENTRY_PERIODIC);
}

/**
 * gst_clock_id_get_time
 * @id: The clockid to query
 *
 * Get the time of the clock ID
 *
 * Returns: the time of the given clock id
 */
GstClockTime
gst_clock_id_get_time (GstClockID id)
{
  g_return_val_if_fail (id != NULL, GST_CLOCK_TIME_NONE);

  return GST_CLOCK_ENTRY_TIME ((GstClockEntry *)id);
}


/**
 * gst_clock_id_wait
 * @id: The clockid to wait on
 * @jitter: A pointer that will contain the jitter
 *
 * Perform a blocking wait on the given ID. The jitter arg can be
 * NULL
 *
 * Returns: the result of the blocking wait.
 */
GstClockReturn
gst_clock_id_wait (GstClockID id, GstClockTimeDiff *jitter)
162 163
{
  GstClockEntry *entry;
164 165 166
  GstClock *clock;
  GstClockReturn res = GST_CLOCK_UNSUPPORTED;
  GstClockTime requested;
Wim Taymans's avatar
Wim Taymans committed
167
  GstClockClass *cclass;
168 169
  
  g_return_val_if_fail (id != NULL, GST_CLOCK_ERROR);
170

171 172
  entry = (GstClockEntry *) id;
  requested = GST_CLOCK_ENTRY_TIME (entry);
173

174
  if (! GST_CLOCK_TIME_IS_VALID (requested)) {
175
    GST_CAT_DEBUG (GST_CAT_CLOCK, "invalid time requested, returning _TIMEOUT");
176
    return GST_CLOCK_TIMEOUT;
177
  }
178

179
  clock = GST_CLOCK_ENTRY_CLOCK (entry);
Wim Taymans's avatar
Wim Taymans committed
180
  cclass = GST_CLOCK_GET_CLASS (clock);
181
  
Wim Taymans's avatar
Wim Taymans committed
182
  if (cclass->wait) {
183
    GstClockTime now;
184 185 186 187
    
    GST_LOCK (clock);
    clock->entries = g_list_prepend (clock->entries, entry);
    GST_UNLOCK (clock);
188

189
    GST_CAT_DEBUG (GST_CAT_CLOCK, "waiting on clock");
190
    do {
Wim Taymans's avatar
Wim Taymans committed
191
      res = cclass->wait (clock, entry);
192 193
    }
    while (res == GST_CLOCK_ENTRY_RESTART);
194
    GST_CAT_DEBUG (GST_CAT_CLOCK, "done waiting");
195

196 197 198 199
    GST_LOCK (clock);
    clock->entries = g_list_remove (clock->entries, entry);
    GST_UNLOCK (clock);

200 201 202 203 204 205 206 207 208 209 210 211 212 213
    if (jitter) {
      now = gst_clock_get_time (clock);
      *jitter = now - requested;
    }

    if (clock->stats) {
      gst_clock_update_stats (clock);
    }
  }

  return res;
}

/**
Wim Taymans's avatar
Wim Taymans committed
214 215
 * gst_clock_id_wait_async:
 * @id: a #GstClockID to wait on
216 217 218
 * @func: The callback function 
 * @user_data: User data passed in the calback
 *
Wim Taymans's avatar
Wim Taymans committed
219 220
 * Register a callback on the given clockid with the given
 * function and user_data.
221
 *
222
 * Returns: the result of the non blocking wait.
223 224 225 226 227 228 229 230
 */
GstClockReturn
gst_clock_id_wait_async (GstClockID id,
		         GstClockCallback func, gpointer user_data)
{
  GstClockEntry *entry;
  GstClock *clock;
  GstClockReturn res = GST_CLOCK_UNSUPPORTED;
Wim Taymans's avatar
Wim Taymans committed
231
  GstClockClass *cclass;
232 233
  
  g_return_val_if_fail (id != NULL, GST_CLOCK_ERROR);
234
  g_return_val_if_fail (func != NULL, GST_CLOCK_ERROR);
235 236 237 238

  entry = (GstClockEntry *) id;
  clock = entry->clock;

239
  if (! GST_CLOCK_TIME_IS_VALID (GST_CLOCK_ENTRY_TIME (entry))) {
240 241 242 243
    (func) (clock, GST_CLOCK_TIME_NONE, id, user_data);
    return GST_CLOCK_TIMEOUT;
  }

Wim Taymans's avatar
Wim Taymans committed
244 245 246 247 248 249 250
  cclass = GST_CLOCK_GET_CLASS (clock);

  if (cclass->wait_async) {
    entry->func = func;
    entry->user_data = user_data;

    res = cclass->wait_async (clock, entry);
251 252 253 254 255
  }

  return res;
}

256 257 258 259 260 261 262 263
static void
gst_clock_reschedule_func (GstClockEntry *entry)
{
  entry->status = GST_CLOCK_ENTRY_OK;
  
  gst_clock_id_unlock ((GstClockID)entry);
}

264
/**
Wim Taymans's avatar
Wim Taymans committed
265 266
 * gst_clock_id_unschedule:
 * @id: The id to unschedule
267 268 269 270 271 272 273 274
 *
 * Cancel an outstanding async notification request with the given ID.
 */
void
gst_clock_id_unschedule (GstClockID id)
{
  GstClockEntry *entry;
  GstClock *clock;
Wim Taymans's avatar
Wim Taymans committed
275
  GstClockClass *cclass;
276 277 278 279 280
  
  g_return_if_fail (id != NULL);

  entry = (GstClockEntry *) id;
  clock = entry->clock;
281

Wim Taymans's avatar
Wim Taymans committed
282 283 284 285
  cclass = GST_CLOCK_GET_CLASS (clock);

  if (cclass->unschedule)
    cclass->unschedule (clock, entry);
286 287
}

288
/**
Wim Taymans's avatar
Wim Taymans committed
289
 * gst_clock_id_free:
290 291 292 293 294 295
 * @id: The clockid to free
 *
 * Free the resources held by the given id
 */
void
gst_clock_id_free (GstClockID id)
296
{
297 298
  g_return_if_fail (id != NULL);

Wim Taymans's avatar
Wim Taymans committed
299
#ifndef GST_DISABLE_TRACE
Wim Taymans's avatar
Wim Taymans committed
300
  gst_alloc_trace_free (_gst_clock_entry_trace, id);
Wim Taymans's avatar
Wim Taymans committed
301
#endif
302 303
  gst_mem_chunk_free (_gst_clock_entries_chunk, id);
}
304

305
/**
Wim Taymans's avatar
Wim Taymans committed
306
 * gst_clock_id_unlock:
307 308 309 310 311 312 313 314 315
 * @id: The clockid to unlock
 *
 * Unlock the givan ClockID.
 */
void
gst_clock_id_unlock (GstClockID id)
{
  GstClockEntry *entry;
  GstClock *clock;
Wim Taymans's avatar
Wim Taymans committed
316
  GstClockClass *cclass;
317 318 319 320 321 322
  
  g_return_if_fail (id != NULL);

  entry = (GstClockEntry *) id;
  clock = entry->clock;

Wim Taymans's avatar
Wim Taymans committed
323 324 325 326
  cclass = GST_CLOCK_GET_CLASS (clock);

  if (cclass->unlock)
    cclass->unlock (clock, entry);
327 328
}

329 330 331 332

/**
 * GstClock abstract base class implementation
 */
333 334
GType
gst_clock_get_type (void)
Wim Taymans's avatar
Wim Taymans committed
335
{
336 337 338 339
  static GType clock_type = 0;

  if (!clock_type) {
    static const GTypeInfo clock_info = {
340
      sizeof (GstClockClass),
341 342 343 344 345
      NULL,
      NULL,
      (GClassInitFunc) gst_clock_class_init,
      NULL,
      NULL,
346
      sizeof (GstClock),
347 348 349 350 351
      4,
      (GInstanceInitFunc) gst_clock_init,
      NULL
    };
    clock_type = g_type_register_static (GST_TYPE_OBJECT, "GstClock", 
352
		    			 &clock_info,  G_TYPE_FLAG_ABSTRACT);
353 354 355
  }
  return clock_type;
}
356

357 358 359 360 361
static void
gst_clock_class_init (GstClockClass *klass)
{
  GObjectClass *gobject_class;
  GstObjectClass *gstobject_class;
362

363 364
  gobject_class = (GObjectClass*) klass;
  gstobject_class = (GstObjectClass*) klass;
365

366
  parent_class = g_type_class_ref (GST_TYPE_OBJECT);
367

Wim Taymans's avatar
Wim Taymans committed
368 369 370
  if (!g_thread_supported ())
    g_thread_init (NULL);

371
  _gst_clock_entries_chunk = gst_mem_chunk_new ("GstClockEntries",
372 373
                     sizeof (GstClockEntry), sizeof (GstClockEntry) * 32,
                     G_ALLOC_AND_FREE);
374

Wim Taymans's avatar
Wim Taymans committed
375
#ifndef GST_DISABLE_TRACE
Wim Taymans's avatar
Wim Taymans committed
376
  _gst_clock_entry_trace = gst_alloc_trace_register (GST_CLOCK_ENTRY_TRACE_NAME);
Wim Taymans's avatar
Wim Taymans committed
377
#endif
378

Wim Taymans's avatar
Wim Taymans committed
379
  gobject_class->dispose      = GST_DEBUG_FUNCPTR (gst_clock_dispose);
380 381 382 383 384 385
  gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_clock_set_property);
  gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_clock_get_property);

  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_STATS,
    g_param_spec_boolean ("stats", "Stats", "Enable clock stats",
                          FALSE, G_PARAM_READWRITE));
386 387 388
  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MAX_DIFF,
    g_param_spec_int64 ("max-diff", "Max diff", "The maximum amount of time to wait in nanoseconds",
                        0, G_MAXINT64, DEFAULT_MAX_DIFF, G_PARAM_READWRITE));
389
  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_EVENT_DIFF,
390 391
    g_param_spec_uint64 ("event-diff", "event diff", 
	"The amount of time that may elapse until 2 events are treated as happening at different times",
392
                        0, G_MAXUINT64, DEFAULT_EVENT_DIFF, G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
Wim Taymans's avatar
Wim Taymans committed
393 394
}

395 396
static void
gst_clock_init (GstClock *clock)
Wim Taymans's avatar
Wim Taymans committed
397
{
398 399
  clock->max_diff = DEFAULT_MAX_DIFF;

400
  clock->speed = 1.0;
401
  clock->active = TRUE;
402
  clock->start_time = 0;
403 404
  clock->last_time = 0;
  clock->entries = NULL;
405 406
  clock->flags = 0;
  clock->stats = FALSE;
407 408 409

  clock->active_mutex = g_mutex_new ();
  clock->active_cond = g_cond_new ();
Wim Taymans's avatar
Wim Taymans committed
410 411
}

Wim Taymans's avatar
Wim Taymans committed
412 413 414 415 416 417 418 419 420 421 422
static void
gst_clock_dispose (GObject *object)
{
  GstClock *clock = GST_CLOCK (object);

  g_mutex_free (clock->active_mutex);
  g_cond_free (clock->active_cond);

  G_OBJECT_CLASS (parent_class)->dispose (object);
}

Wim Taymans's avatar
Wim Taymans committed
423 424
/**
 * gst_clock_set_speed
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
425 426
 * @clock: a #GstClock to modify
 * @speed: the speed to set on the clock
Wim Taymans's avatar
Wim Taymans committed
427
 *
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
428
 * Sets the speed on the given clock. 1.0 is the default 
Wim Taymans's avatar
Wim Taymans committed
429
 * speed.
430 431
 *
 * Returns: the new speed of the clock.
Wim Taymans's avatar
Wim Taymans committed
432
 */
433
gdouble
Wim Taymans's avatar
Wim Taymans committed
434 435
gst_clock_set_speed (GstClock *clock, gdouble speed)
{
436 437
  g_return_val_if_fail (GST_IS_CLOCK (clock), 0.0);

438
  GST_WARNING_OBJECT (clock, "called deprecated function");
439
  return clock->speed;
Wim Taymans's avatar
Wim Taymans committed
440 441 442 443
}

/**
 * gst_clock_get_speed
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
444
 * @clock: a #GstClock to query
Wim Taymans's avatar
Wim Taymans committed
445
 *
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
446
 * Gets the speed of the given clock.
Wim Taymans's avatar
Wim Taymans committed
447 448 449 450 451 452 453 454
 *
 * Returns: the speed of the clock.
 */
gdouble
gst_clock_get_speed (GstClock *clock)
{
  g_return_val_if_fail (GST_IS_CLOCK (clock), 0.0);

455
  GST_WARNING_OBJECT (clock, "called deprecated function");
Wim Taymans's avatar
Wim Taymans committed
456 457 458 459
  return clock->speed;
}

/**
460 461 462
 * gst_clock_set_resolution
 * @clock: The clock set the resolution on
 * @resolution: The resolution to set
Wim Taymans's avatar
Wim Taymans committed
463
 *
464 465 466
 * Set the accuracy of the clock.
 *
 * Returns: the new resolution of the clock.
Wim Taymans's avatar
Wim Taymans committed
467
 */
468 469
guint64
gst_clock_set_resolution (GstClock *clock, guint64 resolution)
Wim Taymans's avatar
Wim Taymans committed
470
{
Wim Taymans's avatar
Wim Taymans committed
471 472
  GstClockClass *cclass;

Wim Taymans's avatar
Wim Taymans committed
473 474
  g_return_val_if_fail (GST_IS_CLOCK (clock), G_GINT64_CONSTANT (0));
  g_return_val_if_fail (resolution != 0, G_GINT64_CONSTANT (0));
475

Wim Taymans's avatar
Wim Taymans committed
476 477 478 479
  cclass = GST_CLOCK_GET_CLASS (clock);

  if (cclass->change_resolution)
    clock->resolution = cclass->change_resolution (clock, clock->resolution, resolution);
480

481 482
  return clock->resolution;
}
483

484 485 486 487 488 489 490 491 492 493 494
/**
 * gst_clock_get_resolution
 * @clock: The clock get the resolution of
 *
 * Get the accuracy of the clock.
 *
 * Returns: the resolution of the clock in microseconds.
 */
guint64
gst_clock_get_resolution (GstClock *clock)
{
Wim Taymans's avatar
Wim Taymans committed
495 496
  GstClockClass *cclass;

Wim Taymans's avatar
Wim Taymans committed
497
  g_return_val_if_fail (GST_IS_CLOCK (clock), G_GINT64_CONSTANT (0));
498

Wim Taymans's avatar
Wim Taymans committed
499 500 501 502
  cclass = GST_CLOCK_GET_CLASS (clock);

  if (cclass->get_resolution)
    return cclass->get_resolution (clock);
503

Wim Taymans's avatar
Wim Taymans committed
504
  return G_GINT64_CONSTANT (1);
Wim Taymans's avatar
Wim Taymans committed
505 506
}

Wim Taymans's avatar
Wim Taymans committed
507
/**
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
508 509 510
 * gst_clock_set_active
 * @clock: a #GstClock to set state of
 * @active: flag indicating if the clock should be activated (TRUE) or deactivated
Wim Taymans's avatar
Wim Taymans committed
511
 *
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
512
 * Activates or deactivates the clock based on the active parameter.
Wim Taymans's avatar
Wim Taymans committed
513 514
 * As soon as the clock is activated, the time will start ticking.
 */
515
void
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
516
gst_clock_set_active (GstClock *clock, gboolean active)
Wim Taymans's avatar
Wim Taymans committed
517
{
518
  g_return_if_fail (GST_IS_CLOCK (clock));
519 520
  
  GST_ERROR_OBJECT (clock, "called deprecated function that does nothing now.");
521

522
  return;
523 524
}

Wim Taymans's avatar
Wim Taymans committed
525 526
/**
 * gst_clock_is_active
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
527
 * @clock: a #GstClock to query
Wim Taymans's avatar
Wim Taymans committed
528 529 530 531 532
 *
 * Checks if the given clock is active.
 * 
 * Returns: TRUE if the clock is active.
 */
533 534
gboolean
gst_clock_is_active (GstClock *clock)
535
{
536
  g_return_val_if_fail (GST_IS_CLOCK (clock), FALSE);
537

538 539 540
  GST_WARNING_OBJECT (clock, "called deprecated function.");

  return TRUE;
Wim Taymans's avatar
Wim Taymans committed
541 542
}

543 544 545 546 547 548 549 550 551
/**
 * gst_clock_reset
 * @clock: a #GstClock to reset
 *
 * Reset the clock to time 0.
 */
void
gst_clock_reset (GstClock *clock)
{
Wim Taymans's avatar
Wim Taymans committed
552
  GstClockTime time = G_GINT64_CONSTANT (0);
Wim Taymans's avatar
Wim Taymans committed
553
  GstClockClass *cclass;
554 555 556

  g_return_if_fail (GST_IS_CLOCK (clock));

557 558
  GST_ERROR_OBJECT (clock, "called deprecated function.");

Wim Taymans's avatar
Wim Taymans committed
559 560 561 562
  cclass = GST_CLOCK_GET_CLASS (clock);
	        
  if (cclass->get_internal_time) {
    time = cclass->get_internal_time (clock);
563 564 565
  }

  GST_LOCK (clock);
566
  //clock->active = FALSE;
567
  clock->start_time = time;
Wim Taymans's avatar
Wim Taymans committed
568
  clock->last_time = G_GINT64_CONSTANT (0);
569
  g_list_foreach (clock->entries, (GFunc) gst_clock_reschedule_func, NULL);
570 571 572
  GST_UNLOCK (clock);
}

Wim Taymans's avatar
Wim Taymans committed
573 574 575 576 577 578
/**
 * gst_clock_handle_discont
 * @clock: a #GstClock to notify of the discontinuity
 * @time: The new time
 *
 * Notifies the clock of a discontinuity in time.
579
 *
Wim Taymans's avatar
Wim Taymans committed
580 581 582 583
 * Returns: TRUE if the clock was updated. It is possible that
 * the clock was not updated by this call because only the first
 * discontinuitity in the pipeline is honoured.
 */
584 585 586
gboolean
gst_clock_handle_discont (GstClock *clock, guint64 time)
{
587
  GST_ERROR_OBJECT (clock, "called deprecated function.");
588

589
  return FALSE;
590 591
}

Wim Taymans's avatar
Wim Taymans committed
592 593
/**
 * gst_clock_get_time
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
594
 * @clock: a #GstClock to query
Wim Taymans's avatar
Wim Taymans committed
595
 *
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
596
 * Gets the current time of the given clock. The time is always
Wim Taymans's avatar
Wim Taymans committed
597
 * monotonically increasing.
598
 *
Wim Taymans's avatar
Wim Taymans committed
599 600
 * Returns: the time of the clock.
 */
601 602 603
GstClockTime
gst_clock_get_time (GstClock *clock)
{
Wim Taymans's avatar
Wim Taymans committed
604
  GstClockTime ret = G_GINT64_CONSTANT (0);
605

Wim Taymans's avatar
Wim Taymans committed
606
  g_return_val_if_fail (GST_IS_CLOCK (clock), G_GINT64_CONSTANT (0));
607

Wim Taymans's avatar
Wim Taymans committed
608 609 610 611 612 613
    GstClockClass *cclass;

    cclass = GST_CLOCK_GET_CLASS (clock);

    if (cclass->get_internal_time) {
      ret = cclass->get_internal_time (clock) - clock->start_time;
614 615
    }
    /* make sure the time is increasing, else return last_time */
616
    if ((gint64) ret < (gint64) clock->last_time) {
617 618 619 620 621
      ret = clock->last_time;
    }
    else {
      clock->last_time = ret;
    }
622

623
  return ret;
624 625
}

626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657
/**
 * gst_clock_get_event_time:
 * @clock: clock to query
 * 
 * Gets the "event time" of a given clock. An event on the clock happens
 * whenever this function is called. This ensures that multiple events that
 * happen shortly after each other are treated as if they happened at the same
 * time. GStreamer uses to keep state changes of multiple elements in sync.
 *
 * Returns: the time of the event
 */
GstClockTime
gst_clock_get_event_time (GstClock *clock)
{
  GstClockTime time;
  
  g_return_val_if_fail (GST_IS_CLOCK (clock), GST_CLOCK_TIME_NONE);
  
  time = gst_clock_get_time (clock);

  if (clock->last_event + clock->max_event_diff >= time) {
    GST_LOG_OBJECT (clock, "reporting last event time %"G_GUINT64_FORMAT, 
	clock->last_event);
  } else {
    GST_LOG_OBJECT (clock, "reporting new event time %"G_GUINT64_FORMAT, 
	clock->last_event);
    clock->last_event = time;
  }
  
  return clock->last_event;
}

Wim Taymans's avatar
Wim Taymans committed
658 659 660 661 662 663 664 665
/**
 * gst_clock_get_next_id
 * @clock: The clock to query
 *
 * Get the clockid of the next event.
 *
 * Returns: a clockid or NULL is no event is pending.
 */
666 667 668 669 670
GstClockID
gst_clock_get_next_id (GstClock *clock)
{
  GstClockEntry *entry = NULL;

671 672
  g_return_val_if_fail (GST_IS_CLOCK (clock), NULL);

673 674 675 676 677 678 679 680 681
  GST_LOCK (clock);
  if (clock->entries)
    entry = GST_CLOCK_ENTRY (clock->entries->data);
  GST_UNLOCK (clock);

  return (GstClockID *) entry;
}

static void
682
gst_clock_update_stats (GstClock *clock)
683
{
684 685
}

686 687 688
static void
gst_clock_set_property (GObject *object, guint prop_id,
     		        const GValue *value, GParamSpec *pspec)
689
{
690 691 692 693 694 695 696
  GstClock *clock;
	     
  clock = GST_CLOCK (object);

  switch (prop_id) {
    case ARG_STATS:
      clock->stats = g_value_get_boolean (value);
697
      g_object_notify (object, "stats");
698
      break;
699 700
    case ARG_MAX_DIFF:
      clock->max_diff = g_value_get_int64 (value);
701 702 703 704
      g_object_notify (object, "max-diff");
      break;
    case ARG_EVENT_DIFF:
      clock->max_event_diff = g_value_get_uint64 (value);
705
      g_object_notify (object, "event-diff");
706
      break;
707 708 709 710
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
   }
Wim Taymans's avatar
Wim Taymans committed
711
}
712

713 714 715
static void
gst_clock_get_property (GObject *object, guint prop_id, 
			GValue *value, GParamSpec * pspec)
716
{
717 718 719 720 721 722 723 724
  GstClock *clock;
	     
  clock = GST_CLOCK (object);

  switch (prop_id) {
    case ARG_STATS:
      g_value_set_boolean (value, clock->stats);
      break;
725 726 727
    case ARG_MAX_DIFF:
      g_value_set_int64 (value, clock->max_diff);
      break;
728 729 730
    case ARG_EVENT_DIFF:
      g_value_set_uint64 (value, clock->max_event_diff);
      break;
731 732 733 734
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
   }
735
}