source: trunk/third/gstreamer/gst/gstsystemclock.c @ 21005

Revision 21005, 6.4 KB checked in by ghudson, 20 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r21004, which included commits to RCS files with non-trunk default branches.
Line 
1/* GStreamer
2 * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3 *                    2000 Wim Taymans <wim.taymans@chello.be>
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#include <time.h>
24
25#include "gst_private.h"
26#include "gstinfo.h"
27
28#include "gstsystemclock.h"
29
30static GstClock *_the_system_clock = NULL;
31
32static void gst_system_clock_class_init (GstSystemClockClass * klass);
33static void gst_system_clock_init (GstSystemClock * clock);
34static void gst_system_clock_dispose (GObject * object);
35
36static GstClockTime gst_system_clock_get_internal_time (GstClock * clock);
37static guint64 gst_system_clock_get_resolution (GstClock * clock);
38static GstClockEntryStatus gst_system_clock_wait (GstClock * clock,
39    GstClockEntry * entry);
40static void gst_system_clock_unlock (GstClock * clock, GstClockEntry * entry);
41
42static GStaticMutex _gst_sysclock_mutex = G_STATIC_MUTEX_INIT;
43
44static GstClockClass *parent_class = NULL;
45
46/* static guint gst_system_clock_signals[LAST_SIGNAL] = { 0 }; */
47
48GType
49gst_system_clock_get_type (void)
50{
51  static GType clock_type = 0;
52
53  if (!clock_type) {
54    static const GTypeInfo clock_info = {
55      sizeof (GstSystemClockClass),
56      NULL,
57      NULL,
58      (GClassInitFunc) gst_system_clock_class_init,
59      NULL,
60      NULL,
61      sizeof (GstSystemClock),
62      0,
63      (GInstanceInitFunc) gst_system_clock_init,
64      NULL
65    };
66
67    clock_type = g_type_register_static (GST_TYPE_CLOCK, "GstSystemClock",
68        &clock_info, 0);
69  }
70  return clock_type;
71}
72
73static void
74gst_system_clock_class_init (GstSystemClockClass * klass)
75{
76  GObjectClass *gobject_class;
77  GstObjectClass *gstobject_class;
78  GstClockClass *gstclock_class;
79
80  gobject_class = (GObjectClass *) klass;
81  gstobject_class = (GstObjectClass *) klass;
82  gstclock_class = (GstClockClass *) klass;
83
84  parent_class = g_type_class_ref (GST_TYPE_CLOCK);
85
86  gobject_class->dispose = gst_system_clock_dispose;
87
88  gstclock_class->get_internal_time = gst_system_clock_get_internal_time;
89  gstclock_class->get_resolution = gst_system_clock_get_resolution;
90  gstclock_class->wait = gst_system_clock_wait;
91  gstclock_class->unlock = gst_system_clock_unlock;
92}
93
94static void
95gst_system_clock_init (GstSystemClock * clock)
96{
97  clock->mutex = g_mutex_new ();
98  clock->cond = g_cond_new ();
99}
100
101static void
102gst_system_clock_dispose (GObject * object)
103{
104  GstClock *clock = (GstClock *) object;
105  GstSystemClock *sysclock = (GstSystemClock *) object;
106
107  /* there are subclasses of GstSystemClock running around... */
108  if (_the_system_clock == clock) {
109    g_warning ("disposing systemclock!");
110
111    /* no parent dispose here, this is bad enough already */
112  } else {
113    G_OBJECT_CLASS (parent_class)->dispose (object);
114
115    /* FIXME: Notifying before freeing? */
116    g_cond_free (sysclock->cond);
117    g_mutex_free (sysclock->mutex);
118  }
119}
120
121/**
122 * gst_system_clock_obtain
123 *
124 * Get a handle to the default system clock.
125 *
126 * Returns: the default clock.
127 */
128GstClock *
129gst_system_clock_obtain (void)
130{
131  GstClock *clock = _the_system_clock;
132
133  if (clock == NULL) {
134    g_static_mutex_lock (&_gst_sysclock_mutex);
135    if (_the_system_clock != NULL) {
136      clock = _the_system_clock;
137      g_static_mutex_unlock (&_gst_sysclock_mutex);
138      GST_CAT_DEBUG (GST_CAT_CLOCK, "returning static system clock");
139      goto have_clock;
140    }
141
142    GST_CAT_DEBUG (GST_CAT_CLOCK, "creating new static system clock");
143    /* FIXME: the only way to clean this up is to have a gst_exit()
144     * function; until then, the program will always end with the sysclock
145     * at refcount 1 */
146    clock = GST_CLOCK (g_object_new (GST_TYPE_SYSTEM_CLOCK, NULL));
147
148    gst_object_set_name (GST_OBJECT (clock), "GstSystemClock");
149
150    /* we created the global clock; take ownership so
151     * we can hand out instances later */
152    gst_object_ref (GST_OBJECT (clock));
153    gst_object_sink (GST_OBJECT (clock));
154
155    _the_system_clock = clock;
156    g_static_mutex_unlock (&_gst_sysclock_mutex);
157  } else {
158    GST_CAT_DEBUG (GST_CAT_CLOCK, "returning static system clock");
159  }
160
161have_clock:
162  /* we ref it since we are a clock factory. */
163  gst_object_ref (GST_OBJECT (clock));
164  return clock;
165}
166
167static GstClockTime
168gst_system_clock_get_internal_time (GstClock * clock)
169{
170  GTimeVal timeval;
171
172  g_get_current_time (&timeval);
173
174  return GST_TIMEVAL_TO_TIME (timeval);
175}
176
177static guint64
178gst_system_clock_get_resolution (GstClock * clock)
179{
180  return 1 * GST_USECOND;
181}
182
183static GstClockEntryStatus
184gst_system_clock_wait (GstClock * clock, GstClockEntry * entry)
185{
186  GstClockEntryStatus res;
187  GstClockTime current, target;
188  gint64 diff;
189  GstSystemClock *sysclock = GST_SYSTEM_CLOCK (clock);
190
191  current = gst_clock_get_time (clock);
192  diff = GST_CLOCK_ENTRY_TIME (entry) - current;
193
194  if (diff + clock->max_diff < 0) {
195    GST_WARNING_OBJECT (clock, "clock is way behind: %" G_GINT64_FORMAT
196        "s (max allowed is %" G_GINT64_FORMAT "s", -diff, clock->max_diff);
197    return GST_CLOCK_ENTRY_EARLY;
198  }
199
200  target = gst_system_clock_get_internal_time (clock) + diff;
201
202  GST_CAT_DEBUG (GST_CAT_CLOCK, "real_target %" G_GUINT64_FORMAT
203      " target %" G_GUINT64_FORMAT
204      " now %" G_GUINT64_FORMAT, target, GST_CLOCK_ENTRY_TIME (entry), current);
205
206  if (((gint64) target) > 0) {
207    GTimeVal tv;
208
209    GST_TIME_TO_TIMEVAL (target, tv);
210    g_mutex_lock (sysclock->mutex);
211    g_cond_timed_wait (sysclock->cond, sysclock->mutex, &tv);
212    g_mutex_unlock (sysclock->mutex);
213    res = entry->status;
214  } else {
215    res = GST_CLOCK_ENTRY_EARLY;
216  }
217  return res;
218}
219
220static void
221gst_system_clock_unlock (GstClock * clock, GstClockEntry * entry)
222{
223  GstSystemClock *sysclock = GST_SYSTEM_CLOCK (clock);
224
225  g_mutex_lock (sysclock->mutex);
226  g_cond_broadcast (sysclock->cond);
227  g_mutex_unlock (sysclock->mutex);
228}
Note: See TracBrowser for help on using the repository browser.