gstclock.c 16 KB
Newer Older
1 2 3
/* GStreamer
 * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
 *                    2000 Wim Taymans <wtay@chello.be>
4
 *                    2004 Wim Taymans <wim@fluendo.com>
5 6
 *
 * gstclock.c: Clock subsystem for maintaining time sync
Wim Taymans's avatar
Wim Taymans committed
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.
 */

24
#include <time.h>
25 26

#include "gst_private.h"
27

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

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

39
#define DEFAULT_EVENT_DIFF	(GST_SECOND)
40 41
#define DEFAULT_MAX_DIFF	(2 * GST_SECOND)

42 43
enum
{
44 45
  ARG_0,
  ARG_STATS,
46 47
  ARG_MAX_DIFF,
  ARG_EVENT_DIFF
48 49
};

50 51 52 53
static GstMemChunk *_gst_clock_entries_chunk;

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

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
static GstObjectClass *parent_class = NULL;
64

65 66
/* static guint gst_clock_signals[LAST_SIGNAL] = { 0 }; */

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

73
  entry = gst_mem_chunk_alloc (_gst_clock_entries_chunk);
Wim Taymans's avatar
Wim Taymans committed
74
#ifndef GST_DISABLE_TRACE
Wim Taymans's avatar
Wim Taymans committed
75
  gst_alloc_trace_new (_gst_clock_entry_trace, entry);
Wim Taymans's avatar
Wim Taymans committed
76
#endif
77 78
  GST_CAT_DEBUG (GST_CAT_CLOCK, "created entry %p, time %" GST_TIME_FORMAT,
      entry, GST_TIME_ARGS (time));
79

80
  gst_atomic_int_set (&entry->refcount, 1);
81 82
  entry->clock = clock;
  entry->time = time;
83
  entry->interval = interval;
84
  entry->type = type;
85
  entry->status = GST_CLOCK_BUSY;
86

87 88
  return (GstClockID) entry;
}
89

90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
/**
 * gst_clock_id_ref:
 * @id: The clockid to ref
 *
 * Increase the refcount of the given clockid.
 *
 * Returns: The same #GstClockID with increased refcount.
 *
 * MT safe.
 */
GstClockID
gst_clock_id_ref (GstClockID id)
{
  g_return_val_if_fail (id != NULL, NULL);

105
  g_atomic_int_inc (&((GstClockEntry *) id)->refcount);
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138

  return id;
}

static void
_gst_clock_id_free (GstClockID id)
{
  g_return_if_fail (id != NULL);

  GST_CAT_DEBUG (GST_CAT_CLOCK, "freed entry %p", id);

#ifndef GST_DISABLE_TRACE
  gst_alloc_trace_free (_gst_clock_entry_trace, id);
#endif
  gst_mem_chunk_free (_gst_clock_entries_chunk, id);
}

/**
 * gst_clock_id_unref:
 * @id: The clockid to unref
 *
 * Unref the given clockid. When the refcount reaches 0 the
 * #GstClockID will be freed.
 *
 * MT safe.
 */
void
gst_clock_id_unref (GstClockID id)
{
  gint zero;

  g_return_if_fail (id != NULL);

139
  zero = g_atomic_int_dec_and_test (&((GstClockEntry *) id)->refcount);
140 141 142 143 144 145
  /* if we ended up with the refcount at zero, free the id */
  if (zero) {
    _gst_clock_id_free (id);
  }
}

146 147 148 149 150 151
/**
 * 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 
152 153
 * notification at the requested time. The single shot id should be
 * unreffed after usage.
154 155
 *
 * Returns: An id that can be used to request the time notification.
156 157
 *
 * MT safe.
158 159
 */
GstClockID
160
gst_clock_new_single_shot_id (GstClock * clock, GstClockTime time)
161
{
162 163
  g_return_val_if_fail (GST_IS_CLOCK (clock), NULL);

164 165
  return gst_clock_entry_new (clock,
      time, GST_CLOCK_TIME_NONE, GST_CLOCK_ENTRY_SINGLE);
166 167 168
}

/**
Wim Taymans's avatar
Wim Taymans committed
169
 * gst_clock_new_periodic_id
170 171 172 173 174 175
 * @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
176 177
 * will then be fired with the given interval. The id should be unreffed
 * after usage.
178 179
 *
 * Returns: An id that can be used to request the time notification.
180 181
 *
 * MT safe.
182 183
 */
GstClockID
184 185
gst_clock_new_periodic_id (GstClock * clock, GstClockTime start_time,
    GstClockTime interval)
186
{
187
  g_return_val_if_fail (GST_IS_CLOCK (clock), NULL);
188
  g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (start_time), NULL);
189 190
  g_return_val_if_fail (interval != 0, NULL);

191 192
  return gst_clock_entry_new (clock,
      start_time, interval, GST_CLOCK_ENTRY_PERIODIC);
193 194
}

195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224
/**
 * gst_clock_id_compare_func
 * @id1: A clockid
 * @id2: A clockid to compare with
 *
 * Compares the two GstClockID instances. This function can be used
 * as a GCompareFunc when sorting ids.
 *
 * Returns: negative value if a < b; zero if a = b; positive value if a > b
 *
 * MT safe.
 */
gint
gst_clock_id_compare_func (gconstpointer id1, gconstpointer id2)
{
  GstClockEntry *entry1, *entry2;

  entry1 = (GstClockEntry *) id1;
  entry2 = (GstClockEntry *) id2;

  if (GST_CLOCK_ENTRY_TIME (entry1) > GST_CLOCK_ENTRY_TIME (entry2)) {
    return 1;
  }
  if (GST_CLOCK_ENTRY_TIME (entry1) < GST_CLOCK_ENTRY_TIME (entry2)) {
    return -1;
  }

  return entry1 - entry2;
}

225 226 227 228 229 230
/**
 * gst_clock_id_get_time
 * @id: The clockid to query
 *
 * Get the time of the clock ID
 *
231 232 233
 * Returns: the time of the given clock id.
 *
 * MT safe.
234 235 236 237 238 239
 */
GstClockTime
gst_clock_id_get_time (GstClockID id)
{
  g_return_val_if_fail (id != NULL, GST_CLOCK_TIME_NONE);

240
  return GST_CLOCK_ENTRY_TIME ((GstClockEntry *) id);
241 242 243 244 245 246 247 248 249
}


/**
 * 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
250
 * NULL.
251 252
 *
 * Returns: the result of the blocking wait.
253 254
 *
 * MT safe.
255 256
 */
GstClockReturn
257
gst_clock_id_wait (GstClockID id, GstClockTimeDiff * jitter)
258 259
{
  GstClockEntry *entry;
260
  GstClock *clock;
261
  GstClockReturn res;
262
  GstClockTime requested;
Wim Taymans's avatar
Wim Taymans committed
263
  GstClockClass *cclass;
264

265
  g_return_val_if_fail (id != NULL, GST_CLOCK_ERROR);
266

267 268
  entry = (GstClockEntry *) id;
  requested = GST_CLOCK_ENTRY_TIME (entry);
269

270 271 272 273 274
  if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (requested)))
    goto invalid_time;

  if (G_UNLIKELY (entry->status == GST_CLOCK_UNSCHEDULED))
    goto unscheduled;
275

276
  clock = GST_CLOCK_ENTRY_CLOCK (entry);
Wim Taymans's avatar
Wim Taymans committed
277
  cclass = GST_CLOCK_GET_CLASS (clock);
278

279
  if (G_LIKELY (cclass->wait)) {
280

281 282 283
    GST_CAT_DEBUG (GST_CAT_CLOCK, "waiting on clock entry %p", id);
    res = cclass->wait (clock, entry);
    GST_CAT_DEBUG (GST_CAT_CLOCK, "done waiting entry %p", id);
284

285
    if (jitter) {
286 287
      GstClockTime now = gst_clock_get_time (clock);

288 289
      *jitter = now - requested;
    }
290 291 292
    if (entry->type == GST_CLOCK_ENTRY_PERIODIC) {
      entry->time += entry->interval;
    }
293 294 295 296

    if (clock->stats) {
      gst_clock_update_stats (clock);
    }
297 298
  } else {
    res = GST_CLOCK_UNSUPPORTED;
299 300
  }
  return res;
301 302 303 304 305 306 307 308 309 310 311 312

  /* ERRORS */
invalid_time:
  {
    GST_CAT_DEBUG (GST_CAT_CLOCK, "invalid time requested, returning _BADTIME");
    return GST_CLOCK_BADTIME;
  }
unscheduled:
  {
    GST_CAT_DEBUG (GST_CAT_CLOCK, "entry was unscheduled return _UNSCHEDULED");
    return GST_CLOCK_UNSCHEDULED;
  }
313 314 315
}

/**
Wim Taymans's avatar
Wim Taymans committed
316 317
 * gst_clock_id_wait_async:
 * @id: a #GstClockID to wait on
318 319 320
 * @func: The callback function 
 * @user_data: User data passed in the calback
 *
Wim Taymans's avatar
Wim Taymans committed
321
 * Register a callback on the given clockid with the given
322 323 324 325
 * function and user_data. When passing an id with an invalid
 * time to this function, the callback will be called immediatly
 * with  a time set to GST_CLOCK_TIME_NONE. The callback will
 * be called when the time of the id has been reached.
326
 *
327
 * Returns: the result of the non blocking wait.
328 329
 *
 * MT safe.
330 331 332
 */
GstClockReturn
gst_clock_id_wait_async (GstClockID id,
333
    GstClockCallback func, gpointer user_data)
334 335 336
{
  GstClockEntry *entry;
  GstClock *clock;
337
  GstClockReturn res;
Wim Taymans's avatar
Wim Taymans committed
338
  GstClockClass *cclass;
339
  GstClockTime requested;
340

341
  g_return_val_if_fail (id != NULL, GST_CLOCK_ERROR);
342
  g_return_val_if_fail (func != NULL, GST_CLOCK_ERROR);
343 344

  entry = (GstClockEntry *) id;
345 346
  requested = GST_CLOCK_ENTRY_TIME (entry);
  clock = GST_CLOCK_ENTRY_CLOCK (entry);
347

348 349 350 351 352
  if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (requested)))
    goto invalid_time;

  if (G_UNLIKELY (entry->status == GST_CLOCK_UNSCHEDULED))
    goto unscheduled;
353

Wim Taymans's avatar
Wim Taymans committed
354 355 356 357 358 359 360
  cclass = GST_CLOCK_GET_CLASS (clock);

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

    res = cclass->wait_async (clock, entry);
361 362
  } else {
    res = GST_CLOCK_UNSUPPORTED;
363 364 365
  }
  return res;

366 367 368 369 370 371 372 373 374 375 376 377
  /* ERRORS */
invalid_time:
  {
    (func) (clock, GST_CLOCK_TIME_NONE, id, user_data);
    GST_CAT_DEBUG (GST_CAT_CLOCK, "invalid time requested, returning _BADTIME");
    return GST_CLOCK_BADTIME;
  }
unscheduled:
  {
    GST_CAT_DEBUG (GST_CAT_CLOCK, "entry was unscheduled return _UNSCHEDULED");
    return GST_CLOCK_UNSCHEDULED;
  }
378 379
}

380
/**
Wim Taymans's avatar
Wim Taymans committed
381 382
 * gst_clock_id_unschedule:
 * @id: The id to unschedule
383
 *
384 385 386 387 388 389
 * Cancel an outstanding request with the given ID. This can either
 * be an outstanding async notification or a pending sync notification.
 * After this call, the @id cannot be used anymore to receive sync or
 * async notifications, you need to create a new GstClockID.
 *
 * MT safe.
390 391 392 393 394 395
 */
void
gst_clock_id_unschedule (GstClockID id)
{
  GstClockEntry *entry;
  GstClock *clock;
Wim Taymans's avatar
Wim Taymans committed
396
  GstClockClass *cclass;
397

398 399 400 401
  g_return_if_fail (id != NULL);

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

Wim Taymans's avatar
Wim Taymans committed
403 404 405 406
  cclass = GST_CLOCK_GET_CLASS (clock);

  if (cclass->unschedule)
    cclass->unschedule (clock, entry);
407 408
}

409 410 411 412

/**
 * GstClock abstract base class implementation
 */
413 414
GType
gst_clock_get_type (void)
Wim Taymans's avatar
Wim Taymans committed
415
{
416 417 418 419
  static GType clock_type = 0;

  if (!clock_type) {
    static const GTypeInfo clock_info = {
420
      sizeof (GstClockClass),
421 422 423 424 425
      NULL,
      NULL,
      (GClassInitFunc) gst_clock_class_init,
      NULL,
      NULL,
426
      sizeof (GstClock),
427
      0,
428 429 430
      (GInstanceInitFunc) gst_clock_init,
      NULL
    };
431

432
    clock_type = g_type_register_static (GST_TYPE_OBJECT, "GstClock",
433
        &clock_info, G_TYPE_FLAG_ABSTRACT);
434 435 436
  }
  return clock_type;
}
437

438
static void
439
gst_clock_class_init (GstClockClass * klass)
440 441 442
{
  GObjectClass *gobject_class;
  GstObjectClass *gstobject_class;
443

444 445
  gobject_class = (GObjectClass *) klass;
  gstobject_class = (GstObjectClass *) klass;
446

447
  parent_class = g_type_class_ref (GST_TYPE_OBJECT);
448

Wim Taymans's avatar
Wim Taymans committed
449 450 451
  if (!g_thread_supported ())
    g_thread_init (NULL);

452
  _gst_clock_entries_chunk = gst_mem_chunk_new ("GstClockEntries",
453
      sizeof (GstClockEntry), sizeof (GstClockEntry) * 32, G_ALLOC_AND_FREE);
454

Wim Taymans's avatar
Wim Taymans committed
455
#ifndef GST_DISABLE_TRACE
456 457
  _gst_clock_entry_trace =
      gst_alloc_trace_register (GST_CLOCK_ENTRY_TRACE_NAME);
Wim Taymans's avatar
Wim Taymans committed
458
#endif
459

Wim Taymans's avatar
Wim Taymans committed
460
  gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_clock_finalize);
461 462 463 464
  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,
465
      g_param_spec_boolean ("stats", "Stats", "Enable clock stats",
466
          FALSE, G_PARAM_READWRITE));
Wim Taymans's avatar
Wim Taymans committed
467 468
}

469
static void
470
gst_clock_init (GstClock * clock)
Wim Taymans's avatar
Wim Taymans committed
471
{
472
  clock->adjust = 0;
473 474
  clock->last_time = 0;
  clock->entries = NULL;
475
  clock->entries_changed = g_cond_new ();
476 477
  clock->flags = 0;
  clock->stats = FALSE;
Wim Taymans's avatar
Wim Taymans committed
478 479
}

Wim Taymans's avatar
Wim Taymans committed
480
static void
Wim Taymans's avatar
Wim Taymans committed
481
gst_clock_finalize (GObject * object)
Wim Taymans's avatar
Wim Taymans committed
482 483 484
{
  GstClock *clock = GST_CLOCK (object);

485
  g_cond_free (clock->entries_changed);
Wim Taymans's avatar
Wim Taymans committed
486

Wim Taymans's avatar
Wim Taymans committed
487
  G_OBJECT_CLASS (parent_class)->finalize (object);
Wim Taymans's avatar
Wim Taymans committed
488 489
}

Wim Taymans's avatar
Wim Taymans committed
490
/**
491 492 493
 * gst_clock_set_resolution
 * @clock: The clock set the resolution on
 * @resolution: The resolution to set
Wim Taymans's avatar
Wim Taymans committed
494
 *
495 496 497
 * Set the accuracy of the clock.
 *
 * Returns: the new resolution of the clock.
Wim Taymans's avatar
Wim Taymans committed
498
 */
499
guint64
500
gst_clock_set_resolution (GstClock * clock, guint64 resolution)
Wim Taymans's avatar
Wim Taymans committed
501
{
Wim Taymans's avatar
Wim Taymans committed
502 503
  GstClockClass *cclass;

Wim Taymans's avatar
Wim Taymans committed
504 505
  g_return_val_if_fail (GST_IS_CLOCK (clock), G_GINT64_CONSTANT (0));
  g_return_val_if_fail (resolution != 0, G_GINT64_CONSTANT (0));
506

Wim Taymans's avatar
Wim Taymans committed
507 508 509
  cclass = GST_CLOCK_GET_CLASS (clock);

  if (cclass->change_resolution)
510
    clock->resolution =
511
        cclass->change_resolution (clock, clock->resolution, resolution);
512

513 514
  return clock->resolution;
}
515

516 517 518 519 520 521 522
/**
 * 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.
523 524
 *
 * MT safe.
525 526
 */
guint64
527
gst_clock_get_resolution (GstClock * clock)
528
{
Wim Taymans's avatar
Wim Taymans committed
529 530
  GstClockClass *cclass;

Wim Taymans's avatar
Wim Taymans committed
531
  g_return_val_if_fail (GST_IS_CLOCK (clock), G_GINT64_CONSTANT (0));
532

Wim Taymans's avatar
Wim Taymans committed
533 534 535 536
  cclass = GST_CLOCK_GET_CLASS (clock);

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

Wim Taymans's avatar
Wim Taymans committed
538
  return G_GINT64_CONSTANT (1);
Wim Taymans's avatar
Wim Taymans committed
539 540
}

Wim Taymans's avatar
Wim Taymans committed
541
/**
542 543 544
 * gst_clock_adjust_unlocked
 * @clock: a #GstClock to use
 * @internal: a clock time
Wim Taymans's avatar
Wim Taymans committed
545
 *
546 547 548
 * Converts the given @internal clock time to the real time, adjusting
 * and making sure that the returned time is increasing.
 * This function should be called with the clock lock held.
Wim Taymans's avatar
Wim Taymans committed
549
 *
550
 * Returns: the converted time of the clock.
551
 *
552
 * MT safe.
553
 */
554 555
GstClockTime
gst_clock_adjust_unlocked (GstClock * clock, GstClockTime internal)
556
{
557
  GstClockTime ret;
558

559 560 561 562 563 564
  ret = internal + clock->adjust;
  /* make sure the time is increasing, else return last_time */
  if ((gint64) ret < (gint64) clock->last_time) {
    ret = clock->last_time;
  } else {
    clock->last_time = ret;
565
  }
566
  return ret;
567 568
}

Wim Taymans's avatar
Wim Taymans committed
569 570
/**
 * gst_clock_get_time
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
571
 * @clock: a #GstClock to query
Wim Taymans's avatar
Wim Taymans committed
572
 *
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
573
 * Gets the current time of the given clock. The time is always
Wim Taymans's avatar
Wim Taymans committed
574
 * monotonically increasing.
575
 *
576 577 578 579
 * Returns: the time of the clock. Or GST_CLOCK_TIME_NONE when
 * giving wrong input.
 *
 * MT safe.
Wim Taymans's avatar
Wim Taymans committed
580
 */
581
GstClockTime
582
gst_clock_get_time (GstClock * clock)
583
{
584
  GstClockTime ret;
585
  GstClockClass *cclass;
586

587
  g_return_val_if_fail (GST_IS_CLOCK (clock), GST_CLOCK_TIME_NONE);
588

589
  cclass = GST_CLOCK_GET_CLASS (clock);
Wim Taymans's avatar
Wim Taymans committed
590

591
  if (cclass->get_internal_time) {
592
    ret = cclass->get_internal_time (clock);
593
  } else {
594
    ret = G_GINT64_CONSTANT (0);
595
  }
596 597
  GST_CAT_DEBUG (GST_CAT_CLOCK, "internal time %" GST_TIME_FORMAT,
      GST_TIME_ARGS (ret));
598

599 600 601
  GST_LOCK (clock);
  ret = gst_clock_adjust_unlocked (clock, ret);
  GST_UNLOCK (clock);
602

603 604
  GST_CAT_DEBUG (GST_CAT_CLOCK, "adjusted time %" GST_TIME_FORMAT,
      GST_TIME_ARGS (ret));
605

606
  return ret;
607 608
}

Wim Taymans's avatar
Wim Taymans committed
609
/**
610 611 612
 * gst_clock_set_time_adjust
 * @clock: a #GstClock to adjust
 * @adjust: the adjust value
Wim Taymans's avatar
Wim Taymans committed
613
 *
614 615 616 617 618
 * Adjusts the current time of the clock with the adjust value.
 * A positive value moves the clock forwards and a backwards value
 * moves it backwards. Note that _get_time() always returns 
 * increasing values so when you move the clock backwards, _get_time()
 * will report the previous value until the clock catches up.
Wim Taymans's avatar
Wim Taymans committed
619
 *
620
 * MT safe.
Wim Taymans's avatar
Wim Taymans committed
621
 */
622 623
void
gst_clock_set_time_adjust (GstClock * clock, GstClockTime adjust)
624
{
625
  g_return_if_fail (GST_IS_CLOCK (clock));
626

627
  GST_LOCK (clock);
628
  clock->adjust = adjust;
629 630 631 632
  GST_UNLOCK (clock);
}

static void
633
gst_clock_update_stats (GstClock * clock)
634
{
635 636
}

637
static void
638 639
gst_clock_set_property (GObject * object, guint prop_id,
    const GValue * value, GParamSpec * pspec)
640
{
641
  GstClock *clock;
642

643 644 645 646 647
  clock = GST_CLOCK (object);

  switch (prop_id) {
    case ARG_STATS:
      clock->stats = g_value_get_boolean (value);
648
      g_object_notify (object, "stats");
649 650 651 652
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
653
  }
Wim Taymans's avatar
Wim Taymans committed
654
}
655

656
static void
657 658
gst_clock_get_property (GObject * object, guint prop_id,
    GValue * value, GParamSpec * pspec)
659
{
660
  GstClock *clock;
661

662 663 664 665 666 667 668 669 670
  clock = GST_CLOCK (object);

  switch (prop_id) {
    case ARG_STATS:
      g_value_set_boolean (value, clock->stats);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
671
  }
672
}