- Removed bufferpool code and move that to gstbuffer.c
[platform/upstream/gstreamer.git] / gst / gstclock.c
1 /* GStreamer
2  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3  *                    2000 Wim Taymans <wtay@chello.be>
4  *
5  * gstclock.c: Clock subsystem for maintaining time sync
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 #include <sys/time.h>
24
25 /* #define GST_DEBUG_ENABLED */
26 #include "gst_private.h"
27
28 #include "gstclock.h"
29 #include "gstlog.h"
30 #include "gstmemchunk.h"
31
32 #define CLASS(clock)  GST_CLOCK_CLASS (G_OBJECT_GET_CLASS (clock))
33
34 static GstMemChunk *_gst_clock_entries_chunk;
35
36 static void             gst_clock_class_init            (GstClockClass *klass);
37 static void             gst_clock_init                  (GstClock *clock);
38
39
40 static GstObjectClass *parent_class = NULL;
41 /* static guint gst_clock_signals[LAST_SIGNAL] = { 0 }; */
42
43 typedef struct _GstClockEntry GstClockEntry;
44
45 static void             gst_clock_free_entry            (GstClock *clock, GstClockEntry *entry);
46
47 typedef enum {
48   GST_ENTRY_OK,
49   GST_ENTRY_RESTART,
50 } GstEntryStatus;
51
52 struct _GstClockEntry {
53   GstClockTime           time;
54   GstEntryStatus         status;
55   GstClockCallback       func;
56   gpointer               user_data;
57 };
58
59 #define GST_CLOCK_ENTRY(entry)          ((GstClockEntry *)(entry))
60 #define GST_CLOCK_ENTRY_TIME(entry)     (((GstClockEntry *)(entry))->time)
61
62 static GstClockEntry*
63 gst_clock_entry_new (GstClockTime time,
64                      GstClockCallback func, gpointer user_data)
65 {
66   GstClockEntry *entry;
67
68   entry = gst_mem_chunk_alloc (_gst_clock_entries_chunk);
69
70   entry->time = time;
71   entry->func = func;
72   entry->user_data = user_data;
73
74   return entry;
75 }
76
77 /*
78 static gint
79 clock_compare_func (gconstpointer a,
80                     gconstpointer b)
81 {
82   GstClockEntry *entry1 = (GstClockEntry *)a;
83   GstClockEntry *entry2 = (GstClockEntry *)b;
84
85   return (entry1->time - entry2->time);
86 }
87 */
88
89 GType
90 gst_clock_get_type (void)
91 {
92   static GType clock_type = 0;
93
94   if (!clock_type) {
95     static const GTypeInfo clock_info = {
96       sizeof (GstClockClass),
97       NULL,
98       NULL,
99       (GClassInitFunc) gst_clock_class_init,
100       NULL,
101       NULL,
102       sizeof (GstClock),
103       4,
104       (GInstanceInitFunc) gst_clock_init,
105       NULL
106     };
107     clock_type = g_type_register_static (GST_TYPE_OBJECT, "GstClock", 
108                                          &clock_info,  G_TYPE_FLAG_ABSTRACT);
109   }
110   return clock_type;
111 }
112
113 static void
114 gst_clock_class_init (GstClockClass *klass)
115 {
116   GObjectClass *gobject_class;
117   GstObjectClass *gstobject_class;
118
119   gobject_class = (GObjectClass*) klass;
120   gstobject_class = (GstObjectClass*) klass;
121
122   parent_class = g_type_class_ref (GST_TYPE_OBJECT);
123
124   if (!g_thread_supported ())
125     g_thread_init (NULL);
126
127   _gst_clock_entries_chunk = gst_mem_chunk_new ("GstClockEntries",
128                      sizeof (GstClockEntry), sizeof (GstClockEntry) * 32,
129                      G_ALLOC_AND_FREE);
130 }
131
132 static void
133 gst_clock_init (GstClock *clock)
134 {
135   clock->speed = 1.0;
136   clock->active = FALSE;
137   clock->start_time = 0;
138   clock->last_time = 0;
139   clock->entries = NULL;
140   clock->async_supported = FALSE;
141
142   clock->active_mutex = g_mutex_new ();
143   clock->active_cond = g_cond_new ();
144 }
145
146 /**
147  * gst_clock_async_supported
148  * @clock: a #GstClock to query
149  *
150  * Checks if this clock can support asynchronous notification.
151  *
152  * Returns: TRUE if async notification is supported.
153  */
154 gboolean
155 gst_clock_async_supported (GstClock *clock)
156 {
157   g_return_val_if_fail (GST_IS_CLOCK (clock), FALSE);
158
159   return clock->async_supported;
160 }
161
162 /**
163  * gst_clock_set_speed
164  * @clock: a #GstClock to modify
165  * @speed: the speed to set on the clock
166  *
167  * Sets the speed on the given clock. 1.0 is the default 
168  * speed.
169  */
170 void
171 gst_clock_set_speed (GstClock *clock, gdouble speed)
172 {
173   g_return_if_fail (GST_IS_CLOCK (clock));
174
175   clock->speed = speed;
176 }
177
178 /**
179  * gst_clock_get_speed
180  * @clock: a #GstClock to query
181  *
182  * Gets the speed of the given clock.
183  *
184  * Returns: the speed of the clock.
185  */
186 gdouble
187 gst_clock_get_speed (GstClock *clock)
188 {
189   g_return_val_if_fail (GST_IS_CLOCK (clock), 0.0);
190
191   return clock->speed;
192 }
193
194
195 /**
196  * gst_clock_reset
197  * @clock: a #GstClock to reset
198  *
199  * Reset the clock to time 0.
200  */
201 void
202 gst_clock_reset (GstClock *clock)
203 {
204   GstClockTime time = 0LL;
205
206   g_return_if_fail (GST_IS_CLOCK (clock));
207
208   if (CLASS (clock)->get_internal_time) {
209     time = CLASS (clock)->get_internal_time (clock);
210   }
211
212   GST_LOCK (clock);
213   clock->active = FALSE;
214   clock->start_time = time;
215   clock->last_time = 0LL;
216   GST_UNLOCK (clock);
217 }
218
219 /**
220  * gst_clock_set_active
221  * @clock: a #GstClock to set state of
222  * @active: flag indicating if the clock should be activated (TRUE) or deactivated
223  *
224  * Activates or deactivates the clock based on the active parameter.
225  * As soon as the clock is activated, the time will start ticking.
226  */
227 void
228 gst_clock_set_active (GstClock *clock, gboolean active)
229 {
230   GstClockTime time = 0LL;
231
232   g_return_if_fail (GST_IS_CLOCK (clock));
233
234   clock->active = active;
235                 
236   if (CLASS (clock)->get_internal_time) {
237     time = CLASS (clock)->get_internal_time (clock);
238   }
239
240   GST_LOCK (clock);
241   if (active) {
242     clock->start_time = time - clock->last_time;
243     clock->accept_discont = TRUE;
244   }
245   else {
246     clock->last_time = time - clock->start_time;
247     clock->accept_discont = FALSE;
248   }
249   GST_UNLOCK (clock);
250
251   g_mutex_lock (clock->active_mutex);   
252   g_cond_broadcast (clock->active_cond);        
253   g_mutex_unlock (clock->active_mutex); 
254 }
255
256 /**
257  * gst_clock_is_active
258  * @clock: a #GstClock to query
259  *
260  * Checks if the given clock is active.
261  * 
262  * Returns: TRUE if the clock is active.
263  */
264 gboolean
265 gst_clock_is_active (GstClock *clock)
266 {
267   g_return_val_if_fail (GST_IS_CLOCK (clock), FALSE);
268
269   return clock->active;
270 }
271
272 /**
273  * gst_clock_handle_discont
274  * @clock: a #GstClock to notify of the discontinuity
275  * @time: The new time
276  *
277  * Notifies the clock of a discontinuity in time.
278  * 
279  * Returns: TRUE if the clock was updated. It is possible that
280  * the clock was not updated by this call because only the first
281  * discontinuitity in the pipeline is honoured.
282  */
283 gboolean
284 gst_clock_handle_discont (GstClock *clock, guint64 time)
285 {
286   GstClockTime itime = 0LL;
287   
288   GST_DEBUG (GST_CAT_CLOCK, "clock discont %llu %llu %d", time, clock->start_time, clock->accept_discont);
289
290   GST_LOCK (clock);
291   if (clock->accept_discont) {
292     if (CLASS (clock)->get_internal_time) {
293       itime = CLASS (clock)->get_internal_time (clock);
294     }
295   }
296   else {
297     GST_UNLOCK (clock);
298     GST_DEBUG (GST_CAT_CLOCK, "clock discont refused %llu %llu", time, clock->start_time);
299     return FALSE;
300   }
301
302   clock->start_time = itime - time;
303   clock->last_time = time;
304   clock->accept_discont = FALSE;
305   GST_UNLOCK (clock);
306
307   GST_DEBUG (GST_CAT_CLOCK, "new time %llu", gst_clock_get_time (clock));
308
309   g_mutex_lock (clock->active_mutex);   
310   g_cond_broadcast (clock->active_cond);        
311   g_mutex_unlock (clock->active_mutex); 
312
313   return TRUE;
314 }
315
316 /**
317  * gst_clock_get_time
318  * @clock: a #GstClock to query
319  *
320  * Gets the current time of the given clock. The time is always
321  * monotonically increasing.
322  * 
323  * Returns: the time of the clock.
324  */
325 GstClockTime
326 gst_clock_get_time (GstClock *clock)
327 {
328   GstClockTime ret = 0LL;
329
330   g_return_val_if_fail (GST_IS_CLOCK (clock), 0LL);
331
332   if (!clock->active) {
333     /* clock is not activen return previous time */
334     ret = clock->last_time;
335   }
336   else {
337     if (CLASS (clock)->get_internal_time) {
338       ret = CLASS (clock)->get_internal_time (clock) - clock->start_time;
339     }
340     /* make sure the time is increasing, else return last_time */
341     if ((gint64) ret < (gint64) clock->last_time) {
342       ret = clock->last_time;
343     }
344     else {
345       clock->last_time = ret;
346     }
347   }
348
349   return ret;
350 }
351
352 static GstClockID
353 gst_clock_wait_async_func (GstClock *clock, GstClockTime time,
354                            GstClockCallback func, gpointer user_data)
355 {
356   GstClockEntry *entry = NULL;
357   g_return_val_if_fail (GST_IS_CLOCK (clock), NULL);
358
359   if (!clock->active) {
360     GST_DEBUG (GST_CAT_CLOCK, "blocking on clock");
361     g_mutex_lock (clock->active_mutex); 
362     g_cond_wait (clock->active_cond, clock->active_mutex);      
363     g_mutex_unlock (clock->active_mutex);       
364   }
365
366   entry = gst_clock_entry_new (time, func, user_data);
367
368   return entry;
369 }
370
371 /**
372  * gst_clock_wait
373  * @clock: a #GstClock to wait on
374  * @time: The #GstClockTime to wait for
375  * @jitter: The jitter 
376  *
377  * Wait and block till the clock reaches the specified time.
378  * The jitter value contains the difference between the requested time and
379  * the actual time, negative values indicate that the requested time
380  * was allready passed when this call was made.
381  *
382  * Returns: the #GstClockReturn result of the operation.
383  */
384 GstClockReturn
385 gst_clock_wait (GstClock *clock, GstClockTime time, GstClockTimeDiff *jitter)
386 {
387   GstClockID id;
388   GstClockReturn res;
389   
390   g_return_val_if_fail (GST_IS_CLOCK (clock), GST_CLOCK_STOPPED);
391
392   id = gst_clock_wait_async_func (clock, time, NULL, NULL);
393   res = gst_clock_wait_id (clock, id, jitter);
394
395   return res;
396 }
397
398 /**
399  * gst_clock_wait_async
400  * @clock: a #GstClock to wait on
401  * @time: The #GstClockTime to wait for
402  * @func: The callback function 
403  * @user_data: User data passed in the calback
404  *
405  * Register a callback on the given clock that will be triggered 
406  * when the clock has reached the given time. A ClockID is returned
407  * that can be used to cancel the request.
408  *
409  * Returns: the clock id or NULL when async notification is not supported.
410  */
411 GstClockID
412 gst_clock_wait_async (GstClock *clock, GstClockTime time,
413                       GstClockCallback func, gpointer user_data)
414 {
415   g_return_val_if_fail (GST_IS_CLOCK (clock), NULL);
416
417   if (clock->async_supported) {
418     return gst_clock_wait_async_func (clock, time, func, user_data);
419   }
420   return NULL;
421 }
422
423 /**
424  * gst_clock_cancel_wait_async
425  * @clock: The clock to cancel the request on
426  * @id: The id to cancel
427  *
428  * Cancel an outstanding async notification request with the given ID.
429  */
430 void
431 gst_clock_cancel_wait_async (GstClock *clock, GstClockID id)
432 {
433   g_warning ("not supported");
434 }
435
436 /**
437  * gst_clock_notify_async
438  * @clock: The clock to wait on
439  * @interval: The interval between notifications
440  * @func: The callback function 
441  * @user_data: User data passed in the calback
442  *
443  * Register a callback on the given clock that will be periodically
444  * triggered with the specified interval. A ClockID is returned
445  * that can be used to cancel the request.
446  *
447  * Returns: the clock id or NULL when async notification is not supported.
448  */
449 GstClockID
450 gst_clock_notify_async (GstClock *clock, GstClockTime interval,
451                         GstClockCallback func, gpointer user_data) 
452 {
453   g_warning ("not supported");
454   return NULL;
455 }
456
457 /**
458  * gst_clock_remove_notify_async
459  * @clock: The clock to cancel the request on
460  * @id: The id to cancel
461  *
462  * Cancel an outstanding async notification request with the given ID.
463  */
464 void
465 gst_clock_remove_notify_async (GstClock *clock, GstClockID id)
466 {
467   g_warning ("not supported");
468 }
469
470 static void
471 gst_clock_unlock_func (GstClock *clock, GstClockTime time, GstClockID id, gpointer user_data)
472 {
473 }
474
475 /**
476  * gst_clock_wait_id
477  * @clock: The clock to wait on
478  * @id: The clock id to wait on
479  * @jitter: The jitter 
480  *
481  * Wait and block on the clockid obtained with gst_clock_wait_async.
482  * The jitter value is described in gst_clock_wait().
483  *
484  * Returns: result of the operation.
485  */
486 GstClockReturn
487 gst_clock_wait_id (GstClock *clock, GstClockID id, GstClockTimeDiff *jitter)
488 {
489   GstClockReturn res = GST_CLOCK_TIMEOUT;
490   GstClockEntry *entry = (GstClockEntry *) id;
491   GstClockTime current, target;
492   GstClockTimeDiff this_jitter;
493   
494   g_return_val_if_fail (GST_IS_CLOCK (clock), GST_CLOCK_ERROR);
495   g_return_val_if_fail (entry, GST_CLOCK_ERROR);
496
497   current = gst_clock_get_time (clock);
498
499   entry->func = gst_clock_unlock_func;
500   target = GST_CLOCK_ENTRY_TIME (entry) - current;
501
502   GST_DEBUG (GST_CAT_CLOCK, "real_target %llu,  target %llu, now %llu", 
503                   target, GST_CLOCK_ENTRY_TIME (entry), current); 
504   
505   if (((gint64)target) > 0) {
506     struct timeval tv;
507
508     GST_TIME_TO_TIMEVAL (target, tv);
509     select (0, NULL, NULL, NULL, &tv);
510
511     current = gst_clock_get_time (clock);
512     this_jitter = current - GST_CLOCK_ENTRY_TIME (entry);
513   }
514   else {
515     res = GST_CLOCK_EARLY;
516     this_jitter = target;
517   }
518
519   if (jitter)
520     *jitter = this_jitter;
521
522   gst_clock_free_entry (clock, entry);
523
524   return res;
525 }
526
527 /**
528  * gst_clock_get_next_id
529  * @clock: The clock to query
530  *
531  * Get the clockid of the next event.
532  *
533  * Returns: a clockid or NULL is no event is pending.
534  */
535 GstClockID
536 gst_clock_get_next_id (GstClock *clock)
537 {
538   GstClockEntry *entry = NULL;
539
540   GST_LOCK (clock);
541   if (clock->entries)
542     entry = GST_CLOCK_ENTRY (clock->entries->data);
543   GST_UNLOCK (clock);
544
545   return (GstClockID *) entry;
546 }
547
548 /**
549  * gst_clock_id_get_time
550  * @id: The clockid to query
551  *
552  * Get the time of the clock ID
553  *
554  * Returns: the time of the given clock id
555  */
556 GstClockTime
557 gst_clock_id_get_time (GstClockID id)
558 {
559   return GST_CLOCK_ENTRY_TIME (id);
560 }
561
562 static void
563 gst_clock_free_entry (GstClock *clock, GstClockEntry *entry)
564 {
565   gst_mem_chunk_free (_gst_clock_entries_chunk, entry);
566 }
567
568 /**
569  * gst_clock_unlock_id
570  * @clock: The clock that own the id
571  * @id: The clockid to unlock
572  *
573  * Unlock the ClockID.
574  */
575 void
576 gst_clock_unlock_id (GstClock *clock, GstClockID id)
577 {
578   GstClockEntry *entry = (GstClockEntry *) id;
579
580   if (entry->func)
581     entry->func (clock, gst_clock_get_time (clock), id, entry->user_data);
582
583   gst_clock_free_entry (clock, entry);
584 }
585
586 /**
587  * gst_clock_set_resolution
588  * @clock: The clock set the resolution on
589  * @resolution: The resolution to set
590  *
591  * Set the accuracy of the clock.
592  */
593 void
594 gst_clock_set_resolution (GstClock *clock, guint64 resolution)
595 {
596   g_return_if_fail (GST_IS_CLOCK (clock));
597
598   if (CLASS (clock)->set_resolution)
599     CLASS (clock)->set_resolution (clock, resolution);
600 }
601
602 /**
603  * gst_clock_get_resolution
604  * @clock: The clock get the resolution of
605  *
606  * Get the accuracy of the clock.
607  *
608  * Returns: the resolution of the clock in microseconds.
609  */
610 guint64
611 gst_clock_get_resolution (GstClock *clock)
612 {
613   g_return_val_if_fail (GST_IS_CLOCK (clock), 0LL);
614
615   if (CLASS (clock)->get_resolution)
616     return CLASS (clock)->get_resolution (clock);
617
618   return 1LL;
619 }
620