2 * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3 * 2000 Wim Taymans <wtay@chello.be>
5 * audioclock.c: Clock for use by audio plugins
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.
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.
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.
24 * SECTION:gstaudioclock
25 * @short_description: Helper object for implementing audio clocks
26 * @see_also: #GstBaseAudioSink, #GstSystemClock
28 * #GstAudioClock makes it easy for elements to implement a #GstClock, they
29 * simply need to provide a function that returns the current clock time.
31 * This object is internally used to implement the clock in #GstBaseAudioSink.
33 * Last reviewed on 2006-09-27 (0.10.12)
40 #include "gstaudioclock.h"
42 GST_DEBUG_CATEGORY_STATIC (gst_audio_clock_debug);
43 #define GST_CAT_DEFAULT gst_audio_clock_debug
45 static void gst_audio_clock_class_init (GstAudioClockClass * klass);
46 static void gst_audio_clock_init (GstAudioClock * clock);
48 static void gst_audio_clock_dispose (GObject * object);
50 static GstClockTime gst_audio_clock_get_internal_time (GstClock * clock);
52 static GstSystemClockClass *parent_class = NULL;
54 /* static guint gst_audio_clock_signals[LAST_SIGNAL] = { 0 }; */
57 gst_audio_clock_get_type (void)
59 static volatile gsize clock_type = 0;
60 static const GTypeInfo clock_info = {
61 sizeof (GstAudioClockClass),
64 (GClassInitFunc) gst_audio_clock_class_init,
67 sizeof (GstAudioClock),
69 (GInstanceInitFunc) gst_audio_clock_init,
73 if (g_once_init_enter (&clock_type)) {
74 GType tmp = g_type_register_static (GST_TYPE_SYSTEM_CLOCK, "GstAudioClock",
76 g_once_init_leave (&clock_type, tmp);
79 return (GType) clock_type;
83 gst_audio_clock_class_init (GstAudioClockClass * klass)
85 GstClockClass *gstclock_class;
86 GObjectClass *gobject_class;
88 gobject_class = (GObjectClass *) klass;
89 gstclock_class = (GstClockClass *) klass;
91 parent_class = g_type_class_peek_parent (klass);
93 gobject_class->dispose = gst_audio_clock_dispose;
94 gstclock_class->get_internal_time = gst_audio_clock_get_internal_time;
96 GST_DEBUG_CATEGORY_INIT (gst_audio_clock_debug, "audioclock", 0,
101 gst_audio_clock_init (GstAudioClock * clock)
103 GST_DEBUG_OBJECT (clock, "init");
104 clock->last_time = 0;
105 clock->abidata.ABI.time_offset = 0;
106 GST_OBJECT_FLAG_SET (clock, GST_CLOCK_FLAG_CAN_SET_MASTER);
110 gst_audio_clock_dispose (GObject * object)
112 GstAudioClock *clock = GST_AUDIO_CLOCK (object);
114 if (clock->abidata.ABI.destroy_notify && clock->user_data)
115 clock->abidata.ABI.destroy_notify (clock->user_data);
116 clock->abidata.ABI.destroy_notify = NULL;
117 clock->user_data = NULL;
119 G_OBJECT_CLASS (parent_class)->dispose (object);
123 * gst_audio_clock_new:
124 * @name: the name of the clock
126 * @user_data: user data
128 * Create a new #GstAudioClock instance. Whenever the clock time should be
129 * calculated it will call @func with @user_data. When @func returns
130 * #GST_CLOCK_TIME_NONE, the clock will return the last reported time.
132 * Returns: a new #GstAudioClock casted to a #GstClock.
135 gst_audio_clock_new (const gchar * name, GstAudioClockGetTimeFunc func,
138 GstAudioClock *aclock =
139 GST_AUDIO_CLOCK (g_object_new (GST_TYPE_AUDIO_CLOCK, "name", name, NULL));
142 aclock->user_data = user_data;
144 return (GstClock *) aclock;
148 * gst_audio_clock_new_full:
149 * @name: the name of the clock
151 * @user_data: user data
152 * @destroy_notify: #GDestroyNotify for @user_data
154 * Create a new #GstAudioClock instance. Whenever the clock time should be
155 * calculated it will call @func with @user_data. When @func returns
156 * #GST_CLOCK_TIME_NONE, the clock will return the last reported time.
158 * Returns: a new #GstAudioClock casted to a #GstClock.
163 gst_audio_clock_new_full (const gchar * name, GstAudioClockGetTimeFunc func,
164 gpointer user_data, GDestroyNotify destroy_notify)
166 GstAudioClock *aclock =
167 GST_AUDIO_CLOCK (g_object_new (GST_TYPE_AUDIO_CLOCK, "name", name, NULL));
170 aclock->user_data = user_data;
171 aclock->abidata.ABI.destroy_notify = destroy_notify;
173 return (GstClock *) aclock;
177 * gst_audio_clock_reset:
178 * @clock: a #GstAudioClock
179 * @time: a #GstClockTime
181 * Inform @clock that future calls to #GstAudioClockGetTimeFunc will return values
182 * starting from @time. The clock will update an internal offset to make sure that
183 * future calls to internal_time will return an increasing result as required by
184 * the #GstClock object.
187 gst_audio_clock_reset (GstAudioClock * clock, GstClockTime time)
189 GstClockTimeDiff time_offset;
191 if (clock->last_time >= time)
192 time_offset = clock->last_time - time;
194 time_offset = -(time - clock->last_time);
196 clock->abidata.ABI.time_offset = time_offset;
198 GST_DEBUG_OBJECT (clock,
199 "reset clock to %" GST_TIME_FORMAT ", last %" GST_TIME_FORMAT ", offset %"
200 GST_TIME_FORMAT, GST_TIME_ARGS (time), GST_TIME_ARGS (clock->last_time),
201 GST_TIME_ARGS (time_offset));
205 gst_audio_clock_func_invalid (GstClock * clock, gpointer user_data)
207 return GST_CLOCK_TIME_NONE;
211 gst_audio_clock_get_internal_time (GstClock * clock)
213 GstAudioClock *aclock;
216 aclock = GST_AUDIO_CLOCK_CAST (clock);
218 result = aclock->func (clock, aclock->user_data);
219 if (result == GST_CLOCK_TIME_NONE) {
220 result = aclock->last_time;
222 result += aclock->abidata.ABI.time_offset;
223 /* clock must be increasing */
224 if (aclock->last_time < result)
225 aclock->last_time = result;
227 result = aclock->last_time;
230 GST_DEBUG_OBJECT (clock,
231 "result %" GST_TIME_FORMAT ", last_time %" GST_TIME_FORMAT,
232 GST_TIME_ARGS (result), GST_TIME_ARGS (aclock->last_time));
238 * gst_audio_clock_get_time:
239 * @clock: a #GstAudioClock
241 * Report the time as returned by the #GstAudioClockGetTimeFunc without applying
244 * Returns: the time as reported by the time function of the audio clock
249 gst_audio_clock_get_time (GstClock * clock)
251 GstAudioClock *aclock;
254 aclock = GST_AUDIO_CLOCK_CAST (clock);
256 result = aclock->func (clock, aclock->user_data);
257 if (result == GST_CLOCK_TIME_NONE) {
258 GST_DEBUG_OBJECT (clock, "no time, reuse last");
259 result = aclock->last_time - aclock->abidata.ABI.time_offset;
262 GST_DEBUG_OBJECT (clock,
263 "result %" GST_TIME_FORMAT ", last_time %" GST_TIME_FORMAT,
264 GST_TIME_ARGS (result), GST_TIME_ARGS (aclock->last_time));
270 * gst_audio_clock_adjust:
271 * @clock: a #GstAudioClock
272 * @time: a #GstClockTime
274 * Adjust @time with the internal offset of the audio clock.
276 * Returns: @time adjusted with the internal offset.
281 gst_audio_clock_adjust (GstClock * clock, GstClockTime time)
283 GstAudioClock *aclock;
286 aclock = GST_AUDIO_CLOCK_CAST (clock);
288 result = time + aclock->abidata.ABI.time_offset;
294 * gst_audio_clock_invalidate:
295 * @clock: a #GstAudioClock
297 * Invalidate the clock function. Call this function when the provided
298 * #GstAudioClockGetTimeFunc cannot be called anymore, for example, when the
299 * user_data becomes invalid.
301 * After calling this function, @clock will return the last returned time for
302 * the rest of its lifetime.
307 gst_audio_clock_invalidate (GstClock * clock)
309 GstAudioClock *aclock;
311 aclock = GST_AUDIO_CLOCK_CAST (clock);
313 aclock->func = gst_audio_clock_func_invalid;