bufferlist: fix a comment
[platform/upstream/gstreamer.git] / gst / gstsystemclock.c
1 /* GStreamer
2  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3  *                    2004 Wim Taymans <wim@fluendo.com>
4  *
5  * gstsystemclock.c: Default clock, uses the system clock
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 /**
24  * SECTION:gstsystemclock
25  * @short_description: Default clock that uses the current system time
26  * @see_also: #GstClock
27  *
28  * The GStreamer core provides a GstSystemClock based on the system time.
29  * Asynchronous callbacks are scheduled from an internal thread.
30  *
31  * Clock implementors are encouraged to subclass this systemclock as it
32  * implements the async notification.
33  *
34  * Subclasses can however override all of the important methods for sync and
35  * async notifications to implement their own callback methods or blocking
36  * wait operations.
37  *
38  * Last reviewed on 2006-03-08 (0.10.4)
39  */
40
41 #include "gst_private.h"
42 #include "gstinfo.h"
43 #include "gstsystemclock.h"
44 #include "gstpoll.h"
45
46 #include <errno.h>
47
48 /* Define this to get some extra debug about jitter from each clock_wait */
49 #undef WAIT_DEBUGGING
50
51 #define GST_TYPE_CLOCK_TYPE (gst_clock_type_get_type())
52
53 struct _GstSystemClockPrivate
54 {
55   GstClockType clock_type;
56   GstPoll *timer;
57   gint wakeup_count;            /* the number of entries with a pending wakeup */
58   gboolean async_wakeup;        /* if the wakeup was because of a async list change */
59 };
60
61 #define GST_SYSTEM_CLOCK_GET_PRIVATE(obj)  \
62    (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_SYSTEM_CLOCK, \
63         GstSystemClockPrivate))
64
65 enum
66 {
67   PROP_0,
68   PROP_CLOCK_TYPE,
69   /* FILL ME */
70 };
71
72 /* the one instance of the systemclock */
73 static GstClock *_the_system_clock = NULL;
74
75 static void gst_system_clock_class_init (GstSystemClockClass * klass);
76 static void gst_system_clock_init (GstSystemClock * clock);
77 static void gst_system_clock_dispose (GObject * object);
78 static void gst_system_clock_set_property (GObject * object, guint prop_id,
79     const GValue * value, GParamSpec * pspec);
80 static void gst_system_clock_get_property (GObject * object, guint prop_id,
81     GValue * value, GParamSpec * pspec);
82
83 static GstClockTime gst_system_clock_get_internal_time (GstClock * clock);
84 static guint64 gst_system_clock_get_resolution (GstClock * clock);
85 static GstClockReturn gst_system_clock_id_wait_jitter (GstClock * clock,
86     GstClockEntry * entry, GstClockTimeDiff * jitter);
87 static GstClockReturn gst_system_clock_id_wait_jitter_unlocked
88     (GstClock * clock, GstClockEntry * entry, GstClockTimeDiff * jitter,
89     gboolean restart);
90 static GstClockReturn gst_system_clock_id_wait_async (GstClock * clock,
91     GstClockEntry * entry);
92 static void gst_system_clock_id_unschedule (GstClock * clock,
93     GstClockEntry * entry);
94 static void gst_system_clock_async_thread (GstClock * clock);
95 static gboolean gst_system_clock_start_async (GstSystemClock * clock);
96 static void gst_system_clock_add_wakeup (GstSystemClock * sysclock);
97
98 static GStaticMutex _gst_sysclock_mutex = G_STATIC_MUTEX_INIT;
99
100 static GstClockClass *parent_class = NULL;
101
102 /* static guint gst_system_clock_signals[LAST_SIGNAL] = { 0 }; */
103
104 G_DEFINE_TYPE (GstSystemClock, gst_system_clock, GST_TYPE_CLOCK);
105
106 static GType
107 gst_clock_type_get_type (void)
108 {
109   static GType clock_type_type = 0;
110   static const GEnumValue clock_types[] = {
111     {GST_CLOCK_TYPE_REALTIME, "GST_CLOCK_TYPE_REALTIME", "realtime"},
112     {GST_CLOCK_TYPE_MONOTONIC, "GST_CLOCK_TYPE_MONOTONIC", "monotonic"},
113     {0, NULL, NULL},
114   };
115
116   if (G_UNLIKELY (!clock_type_type)) {
117     clock_type_type = g_enum_register_static ("GstClockType", clock_types);
118   }
119   return clock_type_type;
120 }
121
122 static void
123 gst_system_clock_class_init (GstSystemClockClass * klass)
124 {
125   GObjectClass *gobject_class;
126   GstClockClass *gstclock_class;
127
128   gobject_class = (GObjectClass *) klass;
129   gstclock_class = (GstClockClass *) klass;
130
131   parent_class = g_type_class_peek_parent (klass);
132
133   g_type_class_add_private (klass, sizeof (GstSystemClockPrivate));
134
135   gobject_class->dispose = gst_system_clock_dispose;
136   gobject_class->set_property = gst_system_clock_set_property;
137   gobject_class->get_property = gst_system_clock_get_property;
138
139   g_object_class_install_property (gobject_class, PROP_CLOCK_TYPE,
140       g_param_spec_enum ("clock-type", "Clock type",
141           "The type of underlying clock implementation used",
142           GST_TYPE_CLOCK_TYPE, GST_CLOCK_TYPE_REALTIME, G_PARAM_READWRITE));
143
144   gstclock_class->get_internal_time = gst_system_clock_get_internal_time;
145   gstclock_class->get_resolution = gst_system_clock_get_resolution;
146   gstclock_class->wait_jitter = gst_system_clock_id_wait_jitter;
147   gstclock_class->wait_async = gst_system_clock_id_wait_async;
148   gstclock_class->unschedule = gst_system_clock_id_unschedule;
149 }
150
151 static void
152 gst_system_clock_init (GstSystemClock * clock)
153 {
154   GST_OBJECT_FLAG_SET (clock,
155       GST_CLOCK_FLAG_CAN_DO_SINGLE_SYNC |
156       GST_CLOCK_FLAG_CAN_DO_SINGLE_ASYNC |
157       GST_CLOCK_FLAG_CAN_DO_PERIODIC_SYNC |
158       GST_CLOCK_FLAG_CAN_DO_PERIODIC_ASYNC);
159
160   clock->priv = GST_SYSTEM_CLOCK_GET_PRIVATE (clock);
161
162   clock->priv->clock_type = GST_CLOCK_TYPE_REALTIME;
163   clock->priv->timer = gst_poll_new_timer ();
164
165 #if 0
166   /* Uncomment this to start the async clock thread straight away */
167   GST_OBJECT_LOCK (clock);
168   gst_system_clock_start_async (clock);
169   GST_OBJECT_UNLOCK (clock);
170 #endif
171 }
172
173 static void
174 gst_system_clock_dispose (GObject * object)
175 {
176   GstClock *clock = (GstClock *) object;
177   GstSystemClock *sysclock = GST_SYSTEM_CLOCK_CAST (clock);
178   GList *entries;
179
180   /* else we have to stop the thread */
181   GST_OBJECT_LOCK (clock);
182   sysclock->stopping = TRUE;
183   /* unschedule all entries */
184   for (entries = clock->entries; entries; entries = g_list_next (entries)) {
185     GstClockEntry *entry = (GstClockEntry *) entries->data;
186
187     GST_CAT_DEBUG (GST_CAT_CLOCK, "unscheduling entry %p", entry);
188     entry->status = GST_CLOCK_UNSCHEDULED;
189   }
190   g_list_free (clock->entries);
191   clock->entries = NULL;
192   GST_CLOCK_BROADCAST (clock);
193   gst_system_clock_add_wakeup (sysclock);
194   GST_OBJECT_UNLOCK (clock);
195
196   if (sysclock->thread)
197     g_thread_join (sysclock->thread);
198   sysclock->thread = NULL;
199   GST_CAT_DEBUG (GST_CAT_CLOCK, "joined thread");
200
201   gst_poll_free (sysclock->priv->timer);
202
203   G_OBJECT_CLASS (parent_class)->dispose (object);
204
205   if (_the_system_clock == clock) {
206     _the_system_clock = NULL;
207     GST_CAT_DEBUG (GST_CAT_CLOCK, "disposed system clock");
208   }
209 }
210
211 static void
212 gst_system_clock_set_property (GObject * object, guint prop_id,
213     const GValue * value, GParamSpec * pspec)
214 {
215   GstSystemClock *sysclock = GST_SYSTEM_CLOCK (object);
216
217   switch (prop_id) {
218     case PROP_CLOCK_TYPE:
219       sysclock->priv->clock_type = g_value_get_enum (value);
220       GST_CAT_DEBUG (GST_CAT_CLOCK, "clock-type set to %d",
221           sysclock->priv->clock_type);
222       break;
223     default:
224       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
225       break;
226   }
227 }
228
229 static void
230 gst_system_clock_get_property (GObject * object, guint prop_id, GValue * value,
231     GParamSpec * pspec)
232 {
233   GstSystemClock *sysclock = GST_SYSTEM_CLOCK (object);
234
235   switch (prop_id) {
236     case PROP_CLOCK_TYPE:
237       g_value_set_enum (value, sysclock->priv->clock_type);
238       break;
239     default:
240       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
241       break;
242   }
243 }
244
245 /**
246  * gst_system_clock_obtain:
247  *
248  * Get a handle to the default system clock. The refcount of the
249  * clock will be increased so you need to unref the clock after
250  * usage.
251  *
252  * Returns: the default clock.
253  *
254  * MT safe.
255  */
256 GstClock *
257 gst_system_clock_obtain (void)
258 {
259   GstClock *clock;
260
261   g_static_mutex_lock (&_gst_sysclock_mutex);
262   clock = _the_system_clock;
263
264   if (clock == NULL) {
265     GST_CAT_DEBUG (GST_CAT_CLOCK, "creating new static system clock");
266     clock = g_object_new (GST_TYPE_SYSTEM_CLOCK,
267         "name", "GstSystemClock", NULL);
268
269     /* we created the global clock; take ownership so
270      * we can hand out instances later */
271     gst_object_ref_sink (clock);
272
273     _the_system_clock = clock;
274     g_static_mutex_unlock (&_gst_sysclock_mutex);
275   } else {
276     g_static_mutex_unlock (&_gst_sysclock_mutex);
277     GST_CAT_DEBUG (GST_CAT_CLOCK, "returning static system clock");
278   }
279
280   /* we ref it since we are a clock factory. */
281   gst_object_ref (clock);
282   return clock;
283 }
284
285 static void
286 gst_system_clock_remove_wakeup (GstSystemClock * sysclock)
287 {
288   g_return_if_fail (sysclock->priv->wakeup_count > 0);
289
290   sysclock->priv->wakeup_count--;
291   if (sysclock->priv->wakeup_count == 0) {
292     /* read the control socket byte when we removed the last wakeup count */
293     GST_CAT_DEBUG (GST_CAT_CLOCK, "reading control");
294     while (!gst_poll_read_control (sysclock->priv->timer)) {
295       g_warning ("gstsystemclock: read control failed, trying again\n");
296     }
297     GST_CLOCK_BROADCAST (sysclock);
298   }
299   GST_CAT_DEBUG (GST_CAT_CLOCK, "wakeup count %d",
300       sysclock->priv->wakeup_count);
301 }
302
303 static void
304 gst_system_clock_add_wakeup (GstSystemClock * sysclock)
305 {
306   /* only write the control socket for the first wakeup */
307   if (sysclock->priv->wakeup_count == 0) {
308     GST_CAT_DEBUG (GST_CAT_CLOCK, "writing control");
309     while (!gst_poll_write_control (sysclock->priv->timer)) {
310       g_warning
311           ("gstsystemclock: write control failed in wakeup_async, trying again : %d:%s\n",
312           errno, g_strerror (errno));
313     }
314   }
315   sysclock->priv->wakeup_count++;
316   GST_CAT_DEBUG (GST_CAT_CLOCK, "wakeup count %d",
317       sysclock->priv->wakeup_count);
318 }
319
320 static void
321 gst_system_clock_wait_wakeup (GstSystemClock * sysclock)
322 {
323   while (sysclock->priv->wakeup_count > 0) {
324     GST_CLOCK_WAIT (sysclock);
325   }
326 }
327
328 /* this thread reads the sorted clock entries from the queue.
329  *
330  * It waits on each of them and fires the callback when the timeout occurs.
331  *
332  * When an entry in the queue was canceled before we wait for it, it is
333  * simply skipped.
334  *
335  * When waiting for an entry, it can become canceled, in that case we don't
336  * call the callback but move to the next item in the queue.
337  *
338  * MT safe.
339  */
340 static void
341 gst_system_clock_async_thread (GstClock * clock)
342 {
343   GstSystemClock *sysclock = GST_SYSTEM_CLOCK_CAST (clock);
344
345   GST_CAT_DEBUG (GST_CAT_CLOCK, "enter system clock thread");
346   GST_OBJECT_LOCK (clock);
347   /* signal spinup */
348   GST_CLOCK_BROADCAST (clock);
349   /* now enter our (almost) infinite loop */
350   while (!sysclock->stopping) {
351     GstClockEntry *entry;
352     GstClockTime requested;
353     GstClockReturn res;
354
355     /* check if something to be done */
356     while (clock->entries == NULL) {
357       GST_CAT_DEBUG (GST_CAT_CLOCK, "no clock entries, waiting..");
358       /* wait for work to do */
359       GST_CLOCK_WAIT (clock);
360       GST_CAT_DEBUG (GST_CAT_CLOCK, "got signal");
361       /* clock was stopping, exit */
362       if (sysclock->stopping)
363         goto exit;
364     }
365
366     /* see if we have a pending wakeup because the order of the list
367      * changed. */
368     if (sysclock->priv->async_wakeup) {
369       GST_CAT_DEBUG (GST_CAT_CLOCK, "clear async wakeup");
370       gst_system_clock_remove_wakeup (sysclock);
371       sysclock->priv->async_wakeup = FALSE;
372     }
373
374     /* pick the next entry */
375     entry = clock->entries->data;
376     /* if it was unscheduled, just move on to the next entry */
377     if (entry->status == GST_CLOCK_UNSCHEDULED) {
378       GST_CAT_DEBUG (GST_CAT_CLOCK, "entry %p was unscheduled", entry);
379       goto next_entry;
380     }
381
382     requested = entry->time;
383
384     /* now wait for the entry, we already hold the lock */
385     res =
386         gst_system_clock_id_wait_jitter_unlocked (clock, (GstClockID) entry,
387         NULL, FALSE);
388
389     switch (res) {
390       case GST_CLOCK_UNSCHEDULED:
391         /* entry was unscheduled, move to the next */
392         GST_CAT_DEBUG (GST_CAT_CLOCK, "async entry %p unscheduled", entry);
393         goto next_entry;
394       case GST_CLOCK_OK:
395       case GST_CLOCK_EARLY:
396       {
397         /* entry timed out normally, fire the callback and move to the next
398          * entry */
399         GST_CAT_DEBUG (GST_CAT_CLOCK, "async entry %p timed out", entry);
400         if (entry->func) {
401           /* unlock before firing the callback */
402           GST_OBJECT_UNLOCK (clock);
403           entry->func (clock, entry->time, (GstClockID) entry,
404               entry->user_data);
405           GST_OBJECT_LOCK (clock);
406         }
407         if (entry->type == GST_CLOCK_ENTRY_PERIODIC) {
408           GST_CAT_DEBUG (GST_CAT_CLOCK, "updating periodic entry %p", entry);
409           /* adjust time now */
410           entry->time = requested + entry->interval;
411           /* and resort the list now */
412           clock->entries =
413               g_list_sort (clock->entries, gst_clock_id_compare_func);
414           /* and restart */
415           continue;
416         } else {
417           GST_CAT_DEBUG (GST_CAT_CLOCK, "moving to next entry");
418           goto next_entry;
419         }
420       }
421       case GST_CLOCK_BUSY:
422         /* somebody unlocked the entry but is was not canceled, This means that
423          * either a new entry was added in front of the queue or some other entry
424          * was canceled. Whatever it is, pick the head entry of the list and
425          * continue waiting. */
426         GST_CAT_DEBUG (GST_CAT_CLOCK, "async entry %p needs restart", entry);
427
428         /* we set the entry back to the OK state. This is needed so that the
429          * _unschedule() code can see if an entry is currently being waited
430          * on (when its state is BUSY). */
431         entry->status = GST_CLOCK_OK;
432         continue;
433       default:
434         GST_CAT_DEBUG (GST_CAT_CLOCK,
435             "strange result %d waiting for %p, skipping", res, entry);
436         g_warning ("%s: strange result %d waiting for %p, skipping",
437             GST_OBJECT_NAME (clock), res, entry);
438         goto next_entry;
439     }
440   next_entry:
441     /* we remove the current entry and unref it */
442     clock->entries = g_list_remove (clock->entries, entry);
443     gst_clock_id_unref ((GstClockID) entry);
444   }
445 exit:
446   /* signal exit */
447   GST_CLOCK_BROADCAST (clock);
448   GST_OBJECT_UNLOCK (clock);
449   GST_CAT_DEBUG (GST_CAT_CLOCK, "exit system clock thread");
450 }
451
452 #ifdef HAVE_POSIX_TIMERS
453 static inline clockid_t
454 clock_type_to_posix_id (GstClockType clock_type)
455 {
456 #ifdef HAVE_MONOTONIC_CLOCK
457   if (clock_type == GST_CLOCK_TYPE_MONOTONIC)
458     return CLOCK_MONOTONIC;
459   else
460 #endif
461     return CLOCK_REALTIME;
462 }
463 #endif
464
465 /* MT safe */
466 static GstClockTime
467 gst_system_clock_get_internal_time (GstClock * clock)
468 {
469 #ifdef HAVE_POSIX_TIMERS
470   GstSystemClock *sysclock = GST_SYSTEM_CLOCK_CAST (clock);
471   clockid_t ptype;
472   struct timespec ts;
473
474   ptype = clock_type_to_posix_id (sysclock->priv->clock_type);
475
476   if (G_UNLIKELY (clock_gettime (ptype, &ts)))
477     return GST_CLOCK_TIME_NONE;
478
479   return GST_TIMESPEC_TO_TIME (ts);
480 #else
481   GTimeVal timeval;
482
483   g_get_current_time (&timeval);
484
485   return GST_TIMEVAL_TO_TIME (timeval);
486 #endif
487 }
488
489 static guint64
490 gst_system_clock_get_resolution (GstClock * clock)
491 {
492 #ifdef HAVE_POSIX_TIMERS
493   GstSystemClock *sysclock = GST_SYSTEM_CLOCK_CAST (clock);
494   clockid_t ptype;
495   struct timespec ts;
496
497   ptype = clock_type_to_posix_id (sysclock->priv->clock_type);
498
499   if (G_UNLIKELY (clock_getres (ptype, &ts)))
500     return GST_CLOCK_TIME_NONE;
501
502   return GST_TIMESPEC_TO_TIME (ts);
503 #else
504   return 1 * GST_USECOND;
505 #endif
506 }
507
508 /* synchronously wait on the given GstClockEntry.
509  *
510  * We do this by blocking on the global clock GCond variable with
511  * the requested time as a timeout. This allows us to unblock the
512  * entry by signaling the GCond variable.
513  *
514  * Note that signaling the global GCond unlocks all waiting entries. So
515  * we need to check if an unlocked entry has changed when it unlocks.
516  *
517  * Entries that arrive too late are simply not waited on and a
518  * GST_CLOCK_EARLY result is returned.
519  *
520  * should be called with LOCK held.
521  *
522  * MT safe.
523  */
524 static GstClockReturn
525 gst_system_clock_id_wait_jitter_unlocked (GstClock * clock,
526     GstClockEntry * entry, GstClockTimeDiff * jitter, gboolean restart)
527 {
528   GstSystemClock *sysclock = GST_SYSTEM_CLOCK_CAST (clock);
529   GstClockTime entryt, real, now;
530   GstClockTimeDiff diff;
531
532   /* need to call the overridden method because we want to sync against the time
533    * of the clock, whatever the subclass uses as a clock. */
534   real = GST_CLOCK_GET_CLASS (clock)->get_internal_time (clock);
535   now = gst_clock_adjust_unlocked (clock, real);
536
537   /* get the time of the entry */
538   entryt = GST_CLOCK_ENTRY_TIME (entry);
539
540   if (jitter) {
541     *jitter = GST_CLOCK_DIFF (entryt, now);
542   }
543   /* the diff of the entry with the clock is the amount of time we have to
544    * wait */
545   diff = entryt - now;
546
547   GST_CAT_DEBUG (GST_CAT_CLOCK, "entry %p"
548       " time %" GST_TIME_FORMAT
549       " now %" GST_TIME_FORMAT
550       " real %" GST_TIME_FORMAT
551       " diff (time-now) %" G_GINT64_FORMAT,
552       entry,
553       GST_TIME_ARGS (entryt), GST_TIME_ARGS (now), GST_TIME_ARGS (real), diff);
554
555   if (diff > 0) {
556 #ifdef WAIT_DEBUGGING
557     GstClockTime final;
558 #endif
559
560     while (entry->status != GST_CLOCK_UNSCHEDULED) {
561       gint pollret;
562
563       /* mark the entry as busy */
564       entry->status = GST_CLOCK_BUSY;
565       GST_OBJECT_UNLOCK (clock);
566
567       /* now wait on the entry, it either times out or the fd is written. */
568       pollret = gst_poll_wait (sysclock->priv->timer, diff);
569
570       /* another thread can read the fd before we get the lock */
571       GST_OBJECT_LOCK (clock);
572       if (entry->status == GST_CLOCK_UNSCHEDULED) {
573         GST_CAT_DEBUG (GST_CAT_CLOCK, "entry %p unlocked", entry);
574         gst_system_clock_remove_wakeup (sysclock);
575       } else {
576         if (pollret != 0) {
577           /* some other id got unlocked */
578           if (!restart) {
579             /* this can happen if the entry got unlocked because of an async
580              * entry was added to the head of the async queue. */
581             GST_CAT_DEBUG (GST_CAT_CLOCK, "wakeup waiting for entry %p", entry);
582             break;
583           }
584
585           /* mark ourselves as EARLY, we release the lock and we could be
586            * unscheduled ourselves but we don't want the unscheduling thread
587            * to write on the control socket (it does that when an entry has a
588            * BUSY status). */
589           entry->status = GST_CLOCK_EARLY;
590
591           /* wait till all the entries got woken up */
592           gst_system_clock_wait_wakeup (sysclock);
593
594           /* we released the lock in the wait, recheck our status, we don't need
595            * to remove the wakeup count because we marked the entry as EARLY
596            * before releasing the object lock. */
597           if (entry->status == GST_CLOCK_UNSCHEDULED) {
598             GST_CAT_DEBUG (GST_CAT_CLOCK, "entry %p got unscheduled", entry);
599             break;
600           }
601
602           GST_CAT_DEBUG (GST_CAT_CLOCK, "entry %p needs to be restarted",
603               entry);
604         } else {
605           GST_CAT_DEBUG (GST_CAT_CLOCK, "entry %p unlocked after timeout",
606               entry);
607         }
608
609         /* reschedule if gst_poll_wait returned early or we have to reschedule after
610          * an unlock*/
611         real = GST_CLOCK_GET_CLASS (clock)->get_internal_time (clock);
612         now = gst_clock_adjust_unlocked (clock, real);
613         diff = entryt - now;
614
615         if (diff <= 0) {
616           /* timeout, this is fine, we can report success now */
617           entry->status = GST_CLOCK_OK;
618
619           GST_CAT_DEBUG (GST_CAT_CLOCK,
620               "entry %p finished, diff %" G_GINT64_FORMAT, entry, diff);
621
622 #ifdef WAIT_DEBUGGING
623           final = gst_system_clock_get_internal_time (clock);
624           GST_CAT_DEBUG (GST_CAT_CLOCK, "Waited for %" G_GINT64_FORMAT
625               " got %" G_GINT64_FORMAT " diff %" G_GINT64_FORMAT
626               " %g target-offset %" G_GINT64_FORMAT " %g", entryt, now,
627               now - entryt,
628               (double) (GstClockTimeDiff) (now - entryt) / GST_SECOND,
629               (final - target),
630               ((double) (GstClockTimeDiff) (final - target)) / GST_SECOND);
631 #endif
632           break;
633         } else {
634           GST_CAT_DEBUG (GST_CAT_CLOCK,
635               "entry %p restart, diff %" G_GINT64_FORMAT, entry, diff);
636         }
637       }
638     }
639   } else if (diff == 0) {
640     entry->status = GST_CLOCK_OK;
641   } else {
642     entry->status = GST_CLOCK_EARLY;
643   }
644   return entry->status;
645 }
646
647 static GstClockReturn
648 gst_system_clock_id_wait_jitter (GstClock * clock, GstClockEntry * entry,
649     GstClockTimeDiff * jitter)
650 {
651   GstClockReturn ret;
652
653   GST_OBJECT_LOCK (clock);
654   if (G_UNLIKELY (entry->status == GST_CLOCK_UNSCHEDULED))
655     goto was_unscheduled;
656
657   ret = gst_system_clock_id_wait_jitter_unlocked (clock, entry, jitter, TRUE);
658   GST_OBJECT_UNLOCK (clock);
659
660   return ret;
661
662   /* ERRORS */
663 was_unscheduled:
664   {
665     GST_OBJECT_UNLOCK (clock);
666     return GST_CLOCK_UNSCHEDULED;
667   }
668 }
669
670 /* Start the async clock thread. Must be called with the object lock
671  * held */
672 static gboolean
673 gst_system_clock_start_async (GstSystemClock * clock)
674 {
675   GError *error = NULL;
676
677   if (G_LIKELY (clock->thread != NULL))
678     return TRUE;                /* Thread already running. Nothing to do */
679
680   clock->thread = g_thread_create ((GThreadFunc) gst_system_clock_async_thread,
681       clock, TRUE, &error);
682   if (G_UNLIKELY (error))
683     goto no_thread;
684
685   /* wait for it to spin up */
686   GST_CLOCK_WAIT (clock);
687
688   return TRUE;
689
690   /* ERRORS */
691 no_thread:
692   {
693     g_warning ("could not create async clock thread: %s", error->message);
694     g_error_free (error);
695   }
696   return FALSE;
697 }
698
699 /* Add an entry to the list of pending async waits. The entry is inserted
700  * in sorted order. If we inserted the entry at the head of the list, we
701  * need to signal the thread as it might either be waiting on it or waiting
702  * for a new entry.
703  *
704  * MT safe.
705  */
706 static GstClockReturn
707 gst_system_clock_id_wait_async (GstClock * clock, GstClockEntry * entry)
708 {
709   GstSystemClock *sysclock;
710   GstClockEntry *head;
711
712   sysclock = GST_SYSTEM_CLOCK_CAST (clock);
713
714   GST_CAT_DEBUG (GST_CAT_CLOCK, "adding async entry %p", entry);
715
716   GST_OBJECT_LOCK (clock);
717   /* Start the clock async thread if needed */
718   if (G_UNLIKELY (!gst_system_clock_start_async (sysclock)))
719     goto thread_error;
720
721   if (G_UNLIKELY (entry->status == GST_CLOCK_UNSCHEDULED))
722     goto was_unscheduled;
723
724   if (clock->entries)
725     head = clock->entries->data;
726   else
727     head = NULL;
728
729   /* need to take a ref */
730   gst_clock_id_ref ((GstClockID) entry);
731   /* insert the entry in sorted order */
732   clock->entries = g_list_insert_sorted (clock->entries, entry,
733       gst_clock_id_compare_func);
734
735   /* only need to send the signal if the entry was added to the
736    * front, else the thread is just waiting for another entry and
737    * will get to this entry automatically. */
738   if (clock->entries->data == entry) {
739     GST_CAT_DEBUG (GST_CAT_CLOCK, "async entry added to head");
740     if (head == NULL) {
741       /* the list was empty before, signal the cond so that the async thread can
742        * start taking a look at the queue */
743       GST_CAT_DEBUG (GST_CAT_CLOCK, "first entry, sending signal");
744       GST_CLOCK_BROADCAST (clock);
745     } else {
746       if (head->status == GST_CLOCK_BUSY) {
747         /* the async thread was waiting for an entry, unlock the wait so that it
748          * looks at the new head entry instead, we only need to do this once */
749         if (!sysclock->priv->async_wakeup) {
750           GST_CAT_DEBUG (GST_CAT_CLOCK, "wakeup async thread");
751           sysclock->priv->async_wakeup = TRUE;
752           gst_system_clock_add_wakeup (sysclock);
753         }
754       }
755     }
756   }
757   GST_OBJECT_UNLOCK (clock);
758
759   return GST_CLOCK_OK;
760
761   /* ERRORS */
762 thread_error:
763   {
764     /* Could not start the async clock thread */
765     GST_OBJECT_UNLOCK (clock);
766     return GST_CLOCK_ERROR;
767   }
768 was_unscheduled:
769   {
770     GST_OBJECT_UNLOCK (clock);
771     return GST_CLOCK_UNSCHEDULED;
772   }
773 }
774
775 /* unschedule an entry. This will set the state of the entry to GST_CLOCK_UNSCHEDULED
776  * and will signal any thread waiting for entries to recheck their entry.
777  * We cannot really decide if the signal is needed or not because the entry
778  * could be waited on in async or sync mode.
779  *
780  * MT safe.
781  */
782 static void
783 gst_system_clock_id_unschedule (GstClock * clock, GstClockEntry * entry)
784 {
785   GstSystemClock *sysclock;
786
787   sysclock = GST_SYSTEM_CLOCK_CAST (clock);
788
789   GST_CAT_DEBUG (GST_CAT_CLOCK, "unscheduling entry %p", entry);
790
791   GST_OBJECT_LOCK (clock);
792   if (entry->status == GST_CLOCK_BUSY) {
793     /* the entry was being busy, wake up all entries so that they recheck their
794      * status. We cannot wake up just one entry because allocating such a
795      * datastructure for each entry would be too heavy and unlocking an entry
796      * is usually done when shutting down or some other exceptional case. */
797     GST_CAT_DEBUG (GST_CAT_CLOCK, "entry was BUSY, doing wakeup");
798     gst_system_clock_add_wakeup (sysclock);
799   }
800   /* when it leaves the poll, it'll detect the unscheduled */
801   entry->status = GST_CLOCK_UNSCHEDULED;
802   GST_OBJECT_UNLOCK (clock);
803 }