2 * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3 * 2005 Wim Taymans <wim@fluendo.com>
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:gstbaseaudiosrc
25 * @short_description: Base class for audio sources
26 * @see_also: #GstAudioSrc, #GstRingBuffer.
28 * This is the base class for audio sources. Subclasses need to implement the
29 * ::create_ringbuffer vmethod. This base class will then take care of
30 * reading samples from the ringbuffer, synchronisation and flushing.
32 * Last reviewed on 2006-09-27 (0.10.12)
41 #include "gstbaseaudiosrc.h"
43 #include "gst/gst-i18n-plugin.h"
45 GST_DEBUG_CATEGORY_STATIC (gst_base_audio_src_debug);
46 #define GST_CAT_DEFAULT gst_base_audio_src_debug
49 gst_base_audio_src_slave_method_get_type (void)
51 static volatile gsize slave_method_type = 0;
52 /* FIXME 0.11: nick should be "retimestamp" not "re-timestamp" */
53 static const GEnumValue slave_method[] = {
54 {GST_BASE_AUDIO_SRC_SLAVE_RESAMPLE,
55 "GST_BASE_AUDIO_SRC_SLAVE_RESAMPLE", "resample"},
56 {GST_BASE_AUDIO_SRC_SLAVE_RETIMESTAMP,
57 "GST_BASE_AUDIO_SRC_SLAVE_RETIMESTAMP", "re-timestamp"},
58 {GST_BASE_AUDIO_SRC_SLAVE_SKEW, "GST_BASE_AUDIO_SRC_SLAVE_SKEW", "skew"},
59 {GST_BASE_AUDIO_SRC_SLAVE_NONE, "GST_BASE_AUDIO_SRC_SLAVE_NONE", "none"},
63 if (g_once_init_enter (&slave_method_type)) {
65 g_enum_register_static ("GstBaseAudioSrcSlaveMethod", slave_method);
66 g_once_init_leave (&slave_method_type, tmp);
68 return (GType) slave_method_type;
71 #define GST_BASE_AUDIO_SRC_GET_PRIVATE(obj) \
72 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_BASE_AUDIO_SRC, GstBaseAudioSrcPrivate))
74 struct _GstBaseAudioSrcPrivate
76 gboolean provide_clock;
78 /* the clock slaving algorithm in use */
79 GstBaseAudioSrcSlaveMethod slave_method;
82 /* BaseAudioSrc signals and args */
89 #define DEFAULT_BUFFER_TIME ((200 * GST_MSECOND) / GST_USECOND)
90 #define DEFAULT_LATENCY_TIME ((10 * GST_MSECOND) / GST_USECOND)
91 #define DEFAULT_ACTUAL_BUFFER_TIME -1
92 #define DEFAULT_ACTUAL_LATENCY_TIME -1
93 #define DEFAULT_PROVIDE_CLOCK TRUE
94 #define DEFAULT_SLAVE_METHOD GST_BASE_AUDIO_SRC_SLAVE_SKEW
101 PROP_ACTUAL_BUFFER_TIME,
102 PROP_ACTUAL_LATENCY_TIME,
109 _do_init (GType type)
111 GST_DEBUG_CATEGORY_INIT (gst_base_audio_src_debug, "baseaudiosrc", 0,
112 "baseaudiosrc element");
115 GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE,
117 bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
118 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
119 #endif /* ENABLE_NLS */
122 GST_BOILERPLATE_FULL (GstBaseAudioSrc, gst_base_audio_src, GstPushSrc,
123 GST_TYPE_PUSH_SRC, _do_init);
125 static void gst_base_audio_src_set_property (GObject * object, guint prop_id,
126 const GValue * value, GParamSpec * pspec);
127 static void gst_base_audio_src_get_property (GObject * object, guint prop_id,
128 GValue * value, GParamSpec * pspec);
129 static void gst_base_audio_src_dispose (GObject * object);
131 static GstStateChangeReturn gst_base_audio_src_change_state (GstElement *
132 element, GstStateChange transition);
134 static GstClock *gst_base_audio_src_provide_clock (GstElement * elem);
135 static GstClockTime gst_base_audio_src_get_time (GstClock * clock,
136 GstBaseAudioSrc * src);
138 static GstFlowReturn gst_base_audio_src_create (GstBaseSrc * bsrc,
139 guint64 offset, guint length, GstBuffer ** buf);
140 static gboolean gst_base_audio_src_check_get_range (GstBaseSrc * bsrc);
142 static gboolean gst_base_audio_src_event (GstBaseSrc * bsrc, GstEvent * event);
143 static void gst_base_audio_src_get_times (GstBaseSrc * bsrc,
144 GstBuffer * buffer, GstClockTime * start, GstClockTime * end);
145 static gboolean gst_base_audio_src_setcaps (GstBaseSrc * bsrc, GstCaps * caps);
146 static gboolean gst_base_audio_src_query (GstBaseSrc * bsrc, GstQuery * query);
147 static void gst_base_audio_src_fixate (GstBaseSrc * bsrc, GstCaps * caps);
149 /* static guint gst_base_audio_src_signals[LAST_SIGNAL] = { 0 }; */
152 gst_base_audio_src_base_init (gpointer g_class)
157 gst_base_audio_src_class_init (GstBaseAudioSrcClass * klass)
159 GObjectClass *gobject_class;
160 GstElementClass *gstelement_class;
161 GstBaseSrcClass *gstbasesrc_class;
163 gobject_class = (GObjectClass *) klass;
164 gstelement_class = (GstElementClass *) klass;
165 gstbasesrc_class = (GstBaseSrcClass *) klass;
167 g_type_class_add_private (klass, sizeof (GstBaseAudioSrcPrivate));
169 gobject_class->set_property = gst_base_audio_src_set_property;
170 gobject_class->get_property = gst_base_audio_src_get_property;
171 gobject_class->dispose = gst_base_audio_src_dispose;
173 g_object_class_install_property (gobject_class, PROP_BUFFER_TIME,
174 g_param_spec_int64 ("buffer-time", "Buffer Time",
175 "Size of audio buffer in microseconds", 1,
176 G_MAXINT64, DEFAULT_BUFFER_TIME,
177 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
179 g_object_class_install_property (gobject_class, PROP_LATENCY_TIME,
180 g_param_spec_int64 ("latency-time", "Latency Time",
181 "Audio latency in microseconds", 1,
182 G_MAXINT64, DEFAULT_LATENCY_TIME,
183 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
186 * GstBaseAudioSrc:actual-buffer-time:
188 * Actual configured size of audio buffer in microseconds.
192 g_object_class_install_property (gobject_class, PROP_ACTUAL_BUFFER_TIME,
193 g_param_spec_int64 ("actual-buffer-time", "Actual Buffer Time",
194 "Actual configured size of audio buffer in microseconds",
195 DEFAULT_ACTUAL_BUFFER_TIME, G_MAXINT64, DEFAULT_ACTUAL_BUFFER_TIME,
196 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
199 * GstBaseAudioSrc:actual-latency-time:
201 * Actual configured audio latency in microseconds.
205 g_object_class_install_property (gobject_class, PROP_ACTUAL_LATENCY_TIME,
206 g_param_spec_int64 ("actual-latency-time", "Actual Latency Time",
207 "Actual configured audio latency in microseconds",
208 DEFAULT_ACTUAL_LATENCY_TIME, G_MAXINT64, DEFAULT_ACTUAL_LATENCY_TIME,
209 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
211 g_object_class_install_property (gobject_class, PROP_PROVIDE_CLOCK,
212 g_param_spec_boolean ("provide-clock", "Provide Clock",
213 "Provide a clock to be used as the global pipeline clock",
214 DEFAULT_PROVIDE_CLOCK, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
216 g_object_class_install_property (gobject_class, PROP_SLAVE_METHOD,
217 g_param_spec_enum ("slave-method", "Slave Method",
218 "Algorithm to use to match the rate of the masterclock",
219 GST_TYPE_BASE_AUDIO_SRC_SLAVE_METHOD, DEFAULT_SLAVE_METHOD,
220 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
222 gstelement_class->change_state =
223 GST_DEBUG_FUNCPTR (gst_base_audio_src_change_state);
224 gstelement_class->provide_clock =
225 GST_DEBUG_FUNCPTR (gst_base_audio_src_provide_clock);
227 gstbasesrc_class->set_caps = GST_DEBUG_FUNCPTR (gst_base_audio_src_setcaps);
228 gstbasesrc_class->event = GST_DEBUG_FUNCPTR (gst_base_audio_src_event);
229 gstbasesrc_class->query = GST_DEBUG_FUNCPTR (gst_base_audio_src_query);
230 gstbasesrc_class->get_times =
231 GST_DEBUG_FUNCPTR (gst_base_audio_src_get_times);
232 gstbasesrc_class->create = GST_DEBUG_FUNCPTR (gst_base_audio_src_create);
233 gstbasesrc_class->check_get_range =
234 GST_DEBUG_FUNCPTR (gst_base_audio_src_check_get_range);
235 gstbasesrc_class->fixate = GST_DEBUG_FUNCPTR (gst_base_audio_src_fixate);
237 /* ref class from a thread-safe context to work around missing bit of
238 * thread-safety in GObject */
239 g_type_class_ref (GST_TYPE_AUDIO_CLOCK);
240 g_type_class_ref (GST_TYPE_RING_BUFFER);
244 gst_base_audio_src_init (GstBaseAudioSrc * baseaudiosrc,
245 GstBaseAudioSrcClass * g_class)
247 baseaudiosrc->priv = GST_BASE_AUDIO_SRC_GET_PRIVATE (baseaudiosrc);
249 baseaudiosrc->buffer_time = DEFAULT_BUFFER_TIME;
250 baseaudiosrc->latency_time = DEFAULT_LATENCY_TIME;
251 baseaudiosrc->priv->provide_clock = DEFAULT_PROVIDE_CLOCK;
252 baseaudiosrc->priv->slave_method = DEFAULT_SLAVE_METHOD;
253 /* reset blocksize we use latency time to calculate a more useful
254 * value based on negotiated format. */
255 GST_BASE_SRC (baseaudiosrc)->blocksize = 0;
257 baseaudiosrc->clock = gst_audio_clock_new ("GstAudioSrcClock",
258 (GstAudioClockGetTimeFunc) gst_base_audio_src_get_time, baseaudiosrc);
260 /* we are always a live source */
261 gst_base_src_set_live (GST_BASE_SRC (baseaudiosrc), TRUE);
262 /* we operate in time */
263 gst_base_src_set_format (GST_BASE_SRC (baseaudiosrc), GST_FORMAT_TIME);
267 gst_base_audio_src_dispose (GObject * object)
269 GstBaseAudioSrc *src;
271 src = GST_BASE_AUDIO_SRC (object);
273 GST_OBJECT_LOCK (src);
275 gst_audio_clock_invalidate (src->clock);
276 gst_object_unref (src->clock);
280 if (src->ringbuffer) {
281 gst_object_unparent (GST_OBJECT_CAST (src->ringbuffer));
282 src->ringbuffer = NULL;
284 GST_OBJECT_UNLOCK (src);
286 G_OBJECT_CLASS (parent_class)->dispose (object);
290 gst_base_audio_src_provide_clock (GstElement * elem)
292 GstBaseAudioSrc *src;
295 src = GST_BASE_AUDIO_SRC (elem);
297 /* we have no ringbuffer (must be NULL state) */
298 if (src->ringbuffer == NULL)
301 if (!gst_ring_buffer_is_acquired (src->ringbuffer))
304 GST_OBJECT_LOCK (src);
305 if (!src->priv->provide_clock)
308 clock = GST_CLOCK_CAST (gst_object_ref (src->clock));
309 GST_OBJECT_UNLOCK (src);
316 GST_DEBUG_OBJECT (src, "ringbuffer not acquired");
321 GST_DEBUG_OBJECT (src, "clock provide disabled");
322 GST_OBJECT_UNLOCK (src);
328 gst_base_audio_src_get_time (GstClock * clock, GstBaseAudioSrc * src)
330 guint64 raw, samples;
334 if (G_UNLIKELY (src->ringbuffer == NULL || src->ringbuffer->spec.rate == 0))
335 return GST_CLOCK_TIME_NONE;
337 raw = samples = gst_ring_buffer_samples_done (src->ringbuffer);
339 /* the number of samples not yet processed, this is still queued in the
340 * device (not yet read for capture). */
341 delay = gst_ring_buffer_delay (src->ringbuffer);
345 result = gst_util_uint64_scale_int (samples, GST_SECOND,
346 src->ringbuffer->spec.rate);
348 GST_DEBUG_OBJECT (src,
349 "processed samples: raw %" G_GUINT64_FORMAT ", delay %u, real %"
350 G_GUINT64_FORMAT ", time %" GST_TIME_FORMAT, raw, delay, samples,
351 GST_TIME_ARGS (result));
357 gst_base_audio_src_check_get_range (GstBaseSrc * bsrc)
359 /* we allow limited pull base operation of which the details
360 * will eventually exposed in an as of yet non-existing query.
361 * Basically pulling can be done on any number of bytes as long
362 * as the offset is -1 or sequentially increasing. */
367 * gst_base_audio_src_set_provide_clock:
368 * @src: a #GstBaseAudioSrc
369 * @provide: new state
371 * Controls whether @src will provide a clock or not. If @provide is %TRUE,
372 * gst_element_provide_clock() will return a clock that reflects the datarate
373 * of @src. If @provide is %FALSE, gst_element_provide_clock() will return NULL.
378 gst_base_audio_src_set_provide_clock (GstBaseAudioSrc * src, gboolean provide)
380 g_return_if_fail (GST_IS_BASE_AUDIO_SRC (src));
382 GST_OBJECT_LOCK (src);
383 src->priv->provide_clock = provide;
384 GST_OBJECT_UNLOCK (src);
388 * gst_base_audio_src_get_provide_clock:
389 * @src: a #GstBaseAudioSrc
391 * Queries whether @src will provide a clock or not. See also
392 * gst_base_audio_src_set_provide_clock.
394 * Returns: %TRUE if @src will provide a clock.
399 gst_base_audio_src_get_provide_clock (GstBaseAudioSrc * src)
403 g_return_val_if_fail (GST_IS_BASE_AUDIO_SRC (src), FALSE);
405 GST_OBJECT_LOCK (src);
406 result = src->priv->provide_clock;
407 GST_OBJECT_UNLOCK (src);
413 * gst_base_audio_src_set_slave_method:
414 * @src: a #GstBaseAudioSrc
415 * @method: the new slave method
417 * Controls how clock slaving will be performed in @src.
422 gst_base_audio_src_set_slave_method (GstBaseAudioSrc * src,
423 GstBaseAudioSrcSlaveMethod method)
425 g_return_if_fail (GST_IS_BASE_AUDIO_SRC (src));
427 GST_OBJECT_LOCK (src);
428 src->priv->slave_method = method;
429 GST_OBJECT_UNLOCK (src);
433 * gst_base_audio_src_get_slave_method:
434 * @src: a #GstBaseAudioSrc
436 * Get the current slave method used by @src.
438 * Returns: The current slave method used by @src.
442 GstBaseAudioSrcSlaveMethod
443 gst_base_audio_src_get_slave_method (GstBaseAudioSrc * src)
445 GstBaseAudioSrcSlaveMethod result;
447 g_return_val_if_fail (GST_IS_BASE_AUDIO_SRC (src), -1);
449 GST_OBJECT_LOCK (src);
450 result = src->priv->slave_method;
451 GST_OBJECT_UNLOCK (src);
457 gst_base_audio_src_set_property (GObject * object, guint prop_id,
458 const GValue * value, GParamSpec * pspec)
460 GstBaseAudioSrc *src;
462 src = GST_BASE_AUDIO_SRC (object);
465 case PROP_BUFFER_TIME:
466 src->buffer_time = g_value_get_int64 (value);
468 case PROP_LATENCY_TIME:
469 src->latency_time = g_value_get_int64 (value);
471 case PROP_PROVIDE_CLOCK:
472 gst_base_audio_src_set_provide_clock (src, g_value_get_boolean (value));
474 case PROP_SLAVE_METHOD:
475 gst_base_audio_src_set_slave_method (src, g_value_get_enum (value));
478 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
484 gst_base_audio_src_get_property (GObject * object, guint prop_id,
485 GValue * value, GParamSpec * pspec)
487 GstBaseAudioSrc *src;
489 src = GST_BASE_AUDIO_SRC (object);
492 case PROP_BUFFER_TIME:
493 g_value_set_int64 (value, src->buffer_time);
495 case PROP_LATENCY_TIME:
496 g_value_set_int64 (value, src->latency_time);
498 case PROP_ACTUAL_BUFFER_TIME:
499 GST_OBJECT_LOCK (src);
500 if (src->ringbuffer && src->ringbuffer->acquired)
501 g_value_set_int64 (value, src->ringbuffer->spec.buffer_time);
503 g_value_set_int64 (value, DEFAULT_ACTUAL_BUFFER_TIME);
504 GST_OBJECT_UNLOCK (src);
506 case PROP_ACTUAL_LATENCY_TIME:
507 GST_OBJECT_LOCK (src);
508 if (src->ringbuffer && src->ringbuffer->acquired)
509 g_value_set_int64 (value, src->ringbuffer->spec.latency_time);
511 g_value_set_int64 (value, DEFAULT_ACTUAL_LATENCY_TIME);
512 GST_OBJECT_UNLOCK (src);
514 case PROP_PROVIDE_CLOCK:
515 g_value_set_boolean (value, gst_base_audio_src_get_provide_clock (src));
517 case PROP_SLAVE_METHOD:
518 g_value_set_enum (value, gst_base_audio_src_get_slave_method (src));
521 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
527 gst_base_audio_src_fixate (GstBaseSrc * bsrc, GstCaps * caps)
532 s = gst_caps_get_structure (caps, 0);
534 /* fields for all formats */
535 gst_structure_fixate_field_nearest_int (s, "rate", 44100);
536 gst_structure_fixate_field_nearest_int (s, "channels", 2);
538 /* fields for int and/or float, but maybe not others like alaw/mulaw */
539 if (gst_structure_has_field (s, "width")) {
540 gst_structure_fixate_field_nearest_int (s, "width", 16);
542 if (gst_structure_has_field (s, "depth")) {
543 gst_structure_get_int (s, "width", &width);
544 /* round width to nearest multiple of 8 for the depth */
545 depth = GST_ROUND_UP_8 (width);
546 gst_structure_fixate_field_nearest_int (s, "depth", depth);
549 if (gst_structure_has_field (s, "signed"))
550 gst_structure_fixate_field_boolean (s, "signed", TRUE);
551 if (gst_structure_has_field (s, "endianness"))
552 gst_structure_fixate_field_nearest_int (s, "endianness", G_BYTE_ORDER);
556 gst_base_audio_src_setcaps (GstBaseSrc * bsrc, GstCaps * caps)
558 GstBaseAudioSrc *src = GST_BASE_AUDIO_SRC (bsrc);
559 GstRingBufferSpec *spec;
561 spec = &src->ringbuffer->spec;
563 spec->buffer_time = src->buffer_time;
564 spec->latency_time = src->latency_time;
566 GST_OBJECT_LOCK (src);
567 if (!gst_ring_buffer_parse_caps (spec, caps)) {
568 GST_OBJECT_UNLOCK (src);
572 /* calculate suggested segsize and segtotal */
574 spec->rate * spec->bytes_per_sample * spec->latency_time / GST_MSECOND;
575 spec->segtotal = spec->buffer_time / spec->latency_time;
577 GST_OBJECT_UNLOCK (src);
579 GST_DEBUG ("release old ringbuffer");
581 gst_ring_buffer_release (src->ringbuffer);
583 gst_ring_buffer_debug_spec_buff (spec);
585 GST_DEBUG ("acquire new ringbuffer");
587 if (!gst_ring_buffer_acquire (src->ringbuffer, spec))
590 /* calculate actual latency and buffer times */
592 spec->segsize * GST_MSECOND / (spec->rate * spec->bytes_per_sample);
594 spec->segtotal * spec->segsize * GST_MSECOND / (spec->rate *
595 spec->bytes_per_sample);
597 gst_ring_buffer_debug_spec_buff (spec);
599 g_object_notify (G_OBJECT (src), "actual-buffer-time");
600 g_object_notify (G_OBJECT (src), "actual-latency-time");
607 GST_DEBUG ("could not parse caps");
612 GST_DEBUG ("could not acquire ringbuffer");
618 gst_base_audio_src_get_times (GstBaseSrc * bsrc, GstBuffer * buffer,
619 GstClockTime * start, GstClockTime * end)
621 /* no need to sync to a clock here, we schedule the samples based
622 * on our own clock for the moment. */
623 *start = GST_CLOCK_TIME_NONE;
624 *end = GST_CLOCK_TIME_NONE;
628 gst_base_audio_src_query (GstBaseSrc * bsrc, GstQuery * query)
630 GstBaseAudioSrc *src = GST_BASE_AUDIO_SRC (bsrc);
631 gboolean res = FALSE;
633 switch (GST_QUERY_TYPE (query)) {
634 case GST_QUERY_LATENCY:
636 GstClockTime min_latency, max_latency;
637 GstRingBufferSpec *spec;
639 GST_OBJECT_LOCK (src);
640 if (G_UNLIKELY (src->ringbuffer == NULL
641 || src->ringbuffer->spec.rate == 0)) {
642 GST_OBJECT_UNLOCK (src);
646 spec = &src->ringbuffer->spec;
648 /* we have at least 1 segment of latency */
650 gst_util_uint64_scale_int (spec->segsize, GST_SECOND,
651 spec->rate * spec->bytes_per_sample);
652 /* we cannot delay more than the buffersize else we lose data */
654 gst_util_uint64_scale_int (spec->segtotal * spec->segsize, GST_SECOND,
655 spec->rate * spec->bytes_per_sample);
656 GST_OBJECT_UNLOCK (src);
658 GST_DEBUG_OBJECT (src,
659 "report latency min %" GST_TIME_FORMAT " max %" GST_TIME_FORMAT,
660 GST_TIME_ARGS (min_latency), GST_TIME_ARGS (max_latency));
662 /* we are always live, the min latency is 1 segment and the max latency is
663 * the complete buffer of segments. */
664 gst_query_set_latency (query, TRUE, min_latency, max_latency);
670 res = GST_BASE_SRC_CLASS (parent_class)->query (bsrc, query);
678 gst_base_audio_src_event (GstBaseSrc * bsrc, GstEvent * event)
680 GstBaseAudioSrc *src = GST_BASE_AUDIO_SRC (bsrc);
685 switch (GST_EVENT_TYPE (event)) {
686 case GST_EVENT_FLUSH_START:
687 GST_DEBUG_OBJECT (bsrc, "flush-start");
688 gst_ring_buffer_pause (src->ringbuffer);
689 gst_ring_buffer_clear_all (src->ringbuffer);
691 case GST_EVENT_FLUSH_STOP:
692 GST_DEBUG_OBJECT (bsrc, "flush-stop");
693 /* always resync on sample after a flush */
694 src->next_sample = -1;
695 gst_ring_buffer_clear_all (src->ringbuffer);
698 GST_DEBUG_OBJECT (bsrc, "refuse to seek");
702 GST_DEBUG_OBJECT (bsrc, "dropping event %p", event);
708 /* get the next offset in the ringbuffer for reading samples.
709 * If the next sample is too far away, this function will position itself to the
710 * next most recent sample, creating discontinuity */
712 gst_base_audio_src_get_offset (GstBaseAudioSrc * src)
715 gint readseg, segdone, segtotal, sps;
718 /* assume we can append to the previous sample */
719 sample = src->next_sample;
721 sps = src->ringbuffer->samples_per_seg;
722 segtotal = src->ringbuffer->spec.segtotal;
724 /* get the currently processed segment */
725 segdone = g_atomic_int_get (&src->ringbuffer->segdone)
726 - src->ringbuffer->segbase;
729 GST_DEBUG_OBJECT (src, "at segment %d and sample %" G_GUINT64_FORMAT,
731 /* figure out the segment and the offset inside the segment where
732 * the sample should be read from. */
733 readseg = sample / sps;
735 /* see how far away it is from the read segment, normally segdone (where new
736 * data is written in the ringbuffer) is bigger than readseg (where we are
738 diff = segdone - readseg;
739 if (diff >= segtotal) {
740 GST_DEBUG_OBJECT (src, "dropped, align to segment %d", segdone);
741 /* sample would be dropped, position to next playable position */
742 sample = ((guint64) (segdone)) * sps;
745 /* no previous sample, go to the current position */
746 GST_DEBUG_OBJECT (src, "first sample, align to current %d", segdone);
747 sample = ((guint64) (segdone)) * sps;
751 GST_DEBUG_OBJECT (src,
752 "reading from %d, we are at %d, sample %" G_GUINT64_FORMAT, readseg,
759 gst_base_audio_src_create (GstBaseSrc * bsrc, guint64 offset, guint length,
762 GstBaseAudioSrc *src = GST_BASE_AUDIO_SRC (bsrc);
765 guint samples, total_samples;
768 GstRingBuffer *ringbuffer;
769 GstRingBufferSpec *spec;
771 GstClockTime timestamp, duration;
774 ringbuffer = src->ringbuffer;
775 spec = &ringbuffer->spec;
777 if (G_UNLIKELY (!gst_ring_buffer_is_acquired (ringbuffer)))
780 bps = spec->bytes_per_sample;
782 if ((length == 0 && bsrc->blocksize == 0) || length == -1)
783 /* no length given, use the default segment size */
784 length = spec->segsize;
786 /* make sure we round down to an integral number of samples */
787 length -= length % bps;
789 /* figure out the offset in the ringbuffer */
790 if (G_UNLIKELY (offset != -1)) {
791 sample = offset / bps;
792 /* if a specific offset was given it must be the next sequential
793 * offset we expect or we fail for now. */
794 if (src->next_sample != -1 && sample != src->next_sample)
797 /* calculate the sequentially next sample we need to read. This can jump and
798 * create a DISCONT. */
799 sample = gst_base_audio_src_get_offset (src);
802 GST_DEBUG_OBJECT (src, "reading from sample %" G_GUINT64_FORMAT, sample);
804 /* get the number of samples to read */
805 total_samples = samples = length / bps;
807 /* FIXME, using a bufferpool would be nice here */
808 buf = gst_buffer_new_and_alloc (length);
809 data = GST_BUFFER_DATA (buf);
812 read = gst_ring_buffer_read (ringbuffer, sample, data, samples);
813 GST_DEBUG_OBJECT (src, "read %u of %u", read, samples);
814 /* if we read all, we're done */
818 /* else something interrupted us and we wait for playing again. */
819 GST_DEBUG_OBJECT (src, "wait playing");
820 if (gst_base_src_wait_playing (bsrc) != GST_FLOW_OK)
823 GST_DEBUG_OBJECT (src, "continue playing");
825 /* read next samples */
831 /* mark discontinuity if needed */
832 if (G_UNLIKELY (sample != src->next_sample) && src->next_sample != -1) {
833 GST_WARNING_OBJECT (src,
834 "create DISCONT of %" G_GUINT64_FORMAT " samples at sample %"
835 G_GUINT64_FORMAT, sample - src->next_sample, sample);
836 GST_ELEMENT_WARNING (src, CORE, CLOCK,
837 (_("Can't record audio fast enough")),
838 ("Dropped %" G_GUINT64_FORMAT " samples. This is most likely because "
839 "downstream can't keep up and is consuming samples too slowly.",
840 sample - src->next_sample));
841 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
844 src->next_sample = sample + samples;
846 /* get the normal timestamp to get the duration. */
847 timestamp = gst_util_uint64_scale_int (sample, GST_SECOND, spec->rate);
848 duration = gst_util_uint64_scale_int (src->next_sample, GST_SECOND,
849 spec->rate) - timestamp;
851 GST_OBJECT_LOCK (src);
852 if (!(clock = GST_ELEMENT_CLOCK (src)))
855 if (clock != src->clock) {
856 /* we are slaved, check how to handle this */
857 switch (src->priv->slave_method) {
858 case GST_BASE_AUDIO_SRC_SLAVE_RESAMPLE:
859 /* not implemented, use skew algorithm. This algorithm should
860 * work on the readout pointer and produces more or less samples based
861 * on the clock drift */
862 case GST_BASE_AUDIO_SRC_SLAVE_SKEW:
864 GstClockTime running_time;
865 GstClockTime base_time;
866 GstClockTime current_time;
867 guint64 running_time_sample;
868 gint running_time_segment;
869 gint last_read_segment;
872 gint segments_written;
873 gint last_written_segment;
875 /* get the amount of segments written from the device by now */
876 segments_written = g_atomic_int_get (&ringbuffer->segdone);
878 /* subtract the base to segments_written to get the number of the
879 last written segment in the ringbuffer (one segment written = segment 0) */
880 last_written_segment = segments_written - ringbuffer->segbase - 1;
882 /* samples per segment */
883 sps = ringbuffer->samples_per_seg;
885 /* get the current time */
886 current_time = gst_clock_get_time (clock);
888 /* get the basetime */
889 base_time = GST_ELEMENT_CAST (src)->base_time;
891 /* get the running_time */
892 running_time = current_time - base_time;
894 /* the running_time converted to a sample (relative to the ringbuffer) */
895 running_time_sample =
896 gst_util_uint64_scale_int (running_time, spec->rate, GST_SECOND);
898 /* the segmentnr corresponding to running_time, round down */
899 running_time_segment = running_time_sample / sps;
901 /* the segment currently read from the ringbuffer */
902 last_read_segment = sample / sps;
904 /* the skew we have between running_time and the ringbuffertime (last written to) */
905 segment_skew = running_time_segment - last_written_segment;
907 GST_DEBUG_OBJECT (bsrc,
908 "\n running_time = %"
912 "\n running_time_segment = %d"
913 "\n last_written_segment = %d"
914 "\n segment_skew (running time segment - last_written_segment) = %d"
915 "\n last_read_segment = %d",
916 GST_TIME_ARGS (running_time), GST_TIME_ARGS (timestamp),
917 running_time_segment, last_written_segment, segment_skew,
920 /* Resync the ringbuffer if:
922 * 1. We are more than the length of the ringbuffer behind.
923 * The length of the ringbuffer then gets to dictate
924 * the threshold for what is considered "too late"
926 * 2. If this is our first buffer.
927 * We know that we should catch up to running_time
928 * the first time we are ran.
930 if ((segment_skew >= ringbuffer->spec.segtotal) ||
931 (last_read_segment == 0)) {
932 gint new_read_segment;
936 /* the difference between running_time and the last written segment */
937 segment_diff = running_time_segment - last_written_segment;
939 /* advance the ringbuffer */
940 gst_ring_buffer_advance (ringbuffer, segment_diff);
942 /* we move the new read segment to the last known written segment */
944 g_atomic_int_get (&ringbuffer->segdone) - ringbuffer->segbase;
946 /* we calculate the new sample value */
947 new_sample = ((guint64) new_read_segment) * sps;
949 /* and get the relative time to this -> our new timestamp */
951 gst_util_uint64_scale_int (new_sample, GST_SECOND, spec->rate);
953 /* we update the next sample accordingly */
954 src->next_sample = new_sample + samples;
956 GST_DEBUG_OBJECT (bsrc,
957 "Timeshifted the ringbuffer with %d segments: "
958 "Updating the timestamp to %" GST_TIME_FORMAT ", "
959 "and src->next_sample to %" G_GUINT64_FORMAT, segment_diff,
960 GST_TIME_ARGS (timestamp), src->next_sample);
964 case GST_BASE_AUDIO_SRC_SLAVE_RETIMESTAMP:
966 GstClockTime base_time, latency;
968 /* We are slaved to another clock, take running time of the pipeline clock and
969 * timestamp against it. Somebody else in the pipeline should figure out the
970 * clock drift. We keep the duration we calculated above. */
971 timestamp = gst_clock_get_time (clock);
972 base_time = GST_ELEMENT_CAST (src)->base_time;
974 if (GST_CLOCK_DIFF (timestamp, base_time) < 0)
975 timestamp -= base_time;
979 /* subtract latency */
981 gst_util_uint64_scale_int (total_samples, GST_SECOND, spec->rate);
982 if (timestamp > latency)
983 timestamp -= latency;
987 case GST_BASE_AUDIO_SRC_SLAVE_NONE:
991 GstClockTime base_time;
993 /* to get the timestamp against the clock we also need to add our offset */
994 timestamp = gst_audio_clock_adjust (clock, timestamp);
996 /* we are not slaved, subtract base_time */
997 base_time = GST_ELEMENT_CAST (src)->base_time;
999 if (GST_CLOCK_DIFF (timestamp, base_time) < 0) {
1000 timestamp -= base_time;
1001 GST_LOG_OBJECT (src,
1002 "buffer timestamp %" GST_TIME_FORMAT " (base_time %" GST_TIME_FORMAT
1003 ")", GST_TIME_ARGS (timestamp), GST_TIME_ARGS (base_time));
1005 GST_LOG_OBJECT (src,
1006 "buffer timestamp 0, ts %" GST_TIME_FORMAT " <= base_time %"
1007 GST_TIME_FORMAT, GST_TIME_ARGS (timestamp),
1008 GST_TIME_ARGS (base_time));
1014 GST_OBJECT_UNLOCK (src);
1016 GST_BUFFER_TIMESTAMP (buf) = timestamp;
1017 GST_BUFFER_DURATION (buf) = duration;
1018 GST_BUFFER_OFFSET (buf) = sample;
1019 GST_BUFFER_OFFSET_END (buf) = sample + samples;
1028 GST_DEBUG_OBJECT (src, "ringbuffer in wrong state");
1029 return GST_FLOW_WRONG_STATE;
1033 GST_ELEMENT_ERROR (src, RESOURCE, SEEK,
1034 (NULL), ("resource can only be operated on sequentially but offset %"
1035 G_GUINT64_FORMAT " was given", offset));
1036 return GST_FLOW_ERROR;
1040 gst_buffer_unref (buf);
1041 GST_DEBUG_OBJECT (src, "ringbuffer stopped");
1042 return GST_FLOW_WRONG_STATE;
1047 * gst_base_audio_src_create_ringbuffer:
1048 * @src: a #GstBaseAudioSrc.
1050 * Create and return the #GstRingBuffer for @src. This function will call the
1051 * ::create_ringbuffer vmethod and will set @src as the parent of the returned
1052 * buffer (see gst_object_set_parent()).
1054 * Returns: The new ringbuffer of @src.
1057 gst_base_audio_src_create_ringbuffer (GstBaseAudioSrc * src)
1059 GstBaseAudioSrcClass *bclass;
1060 GstRingBuffer *buffer = NULL;
1062 bclass = GST_BASE_AUDIO_SRC_GET_CLASS (src);
1063 if (bclass->create_ringbuffer)
1064 buffer = bclass->create_ringbuffer (src);
1066 if (G_LIKELY (buffer))
1067 gst_object_set_parent (GST_OBJECT_CAST (buffer), GST_OBJECT_CAST (src));
1072 static GstStateChangeReturn
1073 gst_base_audio_src_change_state (GstElement * element,
1074 GstStateChange transition)
1076 GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
1077 GstBaseAudioSrc *src = GST_BASE_AUDIO_SRC (element);
1079 switch (transition) {
1080 case GST_STATE_CHANGE_NULL_TO_READY:
1081 GST_DEBUG_OBJECT (src, "NULL->READY");
1082 GST_OBJECT_LOCK (src);
1083 if (src->ringbuffer == NULL) {
1084 gst_audio_clock_reset (GST_AUDIO_CLOCK (src->clock), 0);
1085 src->ringbuffer = gst_base_audio_src_create_ringbuffer (src);
1087 GST_OBJECT_UNLOCK (src);
1088 if (!gst_ring_buffer_open_device (src->ringbuffer))
1091 case GST_STATE_CHANGE_READY_TO_PAUSED:
1092 GST_DEBUG_OBJECT (src, "READY->PAUSED");
1093 src->next_sample = -1;
1094 gst_ring_buffer_set_flushing (src->ringbuffer, FALSE);
1095 gst_ring_buffer_may_start (src->ringbuffer, FALSE);
1096 /* Only post clock-provide messages if this is the clock that
1097 * we've created. If the subclass has overriden it the subclass
1098 * should post this messages whenever necessary */
1099 if (src->clock && GST_IS_AUDIO_CLOCK (src->clock) &&
1100 GST_AUDIO_CLOCK_CAST (src->clock)->func ==
1101 (GstAudioClockGetTimeFunc) gst_base_audio_src_get_time)
1102 gst_element_post_message (element,
1103 gst_message_new_clock_provide (GST_OBJECT_CAST (element),
1106 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
1107 GST_DEBUG_OBJECT (src, "PAUSED->PLAYING");
1108 gst_ring_buffer_may_start (src->ringbuffer, TRUE);
1110 case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
1111 GST_DEBUG_OBJECT (src, "PLAYING->PAUSED");
1112 gst_ring_buffer_may_start (src->ringbuffer, FALSE);
1113 gst_ring_buffer_pause (src->ringbuffer);
1115 case GST_STATE_CHANGE_PAUSED_TO_READY:
1116 GST_DEBUG_OBJECT (src, "PAUSED->READY");
1117 /* Only post clock-lost messages if this is the clock that
1118 * we've created. If the subclass has overriden it the subclass
1119 * should post this messages whenever necessary */
1120 if (src->clock && GST_IS_AUDIO_CLOCK (src->clock) &&
1121 GST_AUDIO_CLOCK_CAST (src->clock)->func ==
1122 (GstAudioClockGetTimeFunc) gst_base_audio_src_get_time)
1123 gst_element_post_message (element,
1124 gst_message_new_clock_lost (GST_OBJECT_CAST (element), src->clock));
1125 gst_ring_buffer_set_flushing (src->ringbuffer, TRUE);
1131 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1133 switch (transition) {
1134 case GST_STATE_CHANGE_PAUSED_TO_READY:
1135 GST_DEBUG_OBJECT (src, "PAUSED->READY");
1136 gst_ring_buffer_release (src->ringbuffer);
1138 case GST_STATE_CHANGE_READY_TO_NULL:
1139 GST_DEBUG_OBJECT (src, "READY->NULL");
1140 gst_ring_buffer_close_device (src->ringbuffer);
1141 GST_OBJECT_LOCK (src);
1142 gst_object_unparent (GST_OBJECT_CAST (src->ringbuffer));
1143 src->ringbuffer = NULL;
1144 GST_OBJECT_UNLOCK (src);
1155 /* subclass must post a meaningful error message */
1156 GST_DEBUG_OBJECT (src, "open failed");
1157 return GST_STATE_CHANGE_FAILURE;