8040baf339215b0d8ead84c69926527c6a7b79cc
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 */
23 #include <sys/time.h>
25 //#define GST_DEBUG_ENABLED
26 #include "gst_private.h"
28 #include "gstelement.h"
29 #include "gstclock.h"
32 static GstClock *the_system_clock = NULL;
34 /**
35 * gst_clock_new:
36 * @name: the name of the new clock
37 *
38 * create a new clock element
39 *
40 * Returns: the new clock element
41 */
42 GstClock*
43 gst_clock_new (gchar *name)
44 {
45 GstClock *clock = (GstClock *) g_malloc(sizeof(GstClock));
47 clock->name = g_strdup (name);
48 clock->sinkobjects = NULL;
49 clock->sinkmutex = g_mutex_new ();
50 clock->lock = g_mutex_new ();
51 g_mutex_lock (clock->sinkmutex);
53 clock->num = 0;
54 clock->num_locked = 0;
55 clock->locking = FALSE;
57 return clock;
58 }
60 GstClock*
61 gst_clock_get_system(void)
62 {
63 if (the_system_clock == NULL) {
64 the_system_clock = gst_clock_new ("system_clock");
65 gst_clock_reset (the_system_clock);
66 }
67 return the_system_clock;
68 }
70 void
71 gst_clock_register (GstClock *clock, GstObject *obj)
72 {
73 if ((GST_ELEMENT(obj))->numsrcpads == 0) {
74 GST_DEBUG (0,"gst_clock: setting registered sink object 0x%p\n", obj);
75 clock->sinkobjects = g_list_append (clock->sinkobjects, obj);
76 clock->num++;
77 }
78 }
80 void
81 gst_clock_set (GstClock *clock, GstClockTime time)
82 {
83 struct timeval tfnow;
84 GstClockTime now;
86 gettimeofday (&tfnow, (struct timezone *)NULL);
87 now = tfnow.tv_sec*1000000LL+tfnow.tv_usec;
88 g_mutex_lock (clock->lock);
89 clock->start_time = now - time;
90 g_mutex_unlock (clock->lock);
91 GST_DEBUG (0,"gst_clock: setting clock to %llu %llu %llu\n", time, now, clock->start_time);
92 }
94 GstClockTimeDiff
95 gst_clock_current_diff (GstClock *clock, GstClockTime time)
96 {
97 struct timeval tfnow;
98 GstClockTime now;
100 gettimeofday (&tfnow, (struct timezone *)NULL);
101 g_mutex_lock (clock->lock);
102 now = ((guint64)tfnow.tv_sec*1000000LL+tfnow.tv_usec) - (guint64)clock->start_time;
103 g_mutex_unlock (clock->lock);
105 return GST_CLOCK_DIFF (time, now);
106 }
108 void
109 gst_clock_reset (GstClock *clock)
110 {
111 struct timeval tfnow;
113 gettimeofday (&tfnow, (struct timezone *)NULL);
114 g_mutex_lock (clock->lock);
115 clock->start_time = ((guint64)tfnow.tv_sec)*1000000LL+tfnow.tv_usec;
116 clock->current_time = clock->start_time;
117 clock->adjust = 0LL;
118 GST_DEBUG (0,"gst_clock: setting start clock %llu\n", clock->start_time);
119 g_mutex_unlock (clock->lock);
120 }
122 void
123 gst_clock_wait (GstClock *clock, GstClockTime time, GstObject *obj)
124 {
125 struct timeval tfnow;
126 GstClockTime now;
127 GstClockTimeDiff diff;
130 gettimeofday (&tfnow, (struct timezone *)NULL);
131 g_mutex_lock (clock->lock);
132 now = tfnow.tv_sec*1000000LL+tfnow.tv_usec - clock->start_time;
134 diff = GST_CLOCK_DIFF (time, now);
135 // if we are not behind wait a bit
136 GST_DEBUG (0,"gst_clock: %s waiting for time %08llu %08llu %08lld\n", GST_OBJECT_NAME (obj), time, now, diff);
138 g_mutex_unlock (clock->lock);
139 if (diff > 10000 ) {
140 tfnow.tv_usec = (diff % 1000000);
141 tfnow.tv_sec = diff / 1000000;
142 // FIXME, this piece of code does not work with egcs optimisations on, had to use the following line
143 if (!tfnow.tv_sec) {
144 select(0, NULL, NULL, NULL, &tfnow);
145 }
146 else GST_DEBUG (0,"gst_clock: %s waiting %u %llu %llu %llu seconds\n", GST_OBJECT_NAME (obj),
147 (int)tfnow.tv_sec, now, diff, time);
148 }
149 GST_DEBUG (0,"gst_clock: %s waiting for time %08llu %08llu %08lld done \n", GST_OBJECT_NAME (obj), time, now, diff);
150 }