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);
537 gst_structure_fixate_field_nearest_int (s, "width", 16);
540 if (gst_structure_has_field (s, "depth")) {
541 gst_structure_get_int (s, "width", &width);
542 /* round width to nearest multiple of 8 for the depth */
543 depth = GST_ROUND_UP_8 (width);
544 gst_structure_fixate_field_nearest_int (s, "depth", depth);
546 if (gst_structure_has_field (s, "signed"))
547 gst_structure_fixate_field_boolean (s, "signed", TRUE);
548 if (gst_structure_has_field (s, "endianness"))
549 gst_structure_fixate_field_nearest_int (s, "endianness", G_BYTE_ORDER);
553 gst_base_audio_src_setcaps (GstBaseSrc * bsrc, GstCaps * caps)
555 GstBaseAudioSrc *src = GST_BASE_AUDIO_SRC (bsrc);
556 GstRingBufferSpec *spec;
558 spec = &src->ringbuffer->spec;
560 spec->buffer_time = src->buffer_time;
561 spec->latency_time = src->latency_time;
563 GST_OBJECT_LOCK (src);
564 if (!gst_ring_buffer_parse_caps (spec, caps))
566 GST_OBJECT_UNLOCK (src);
570 /* calculate suggested segsize and segtotal */
572 spec->rate * spec->bytes_per_sample * spec->latency_time / GST_MSECOND;
573 spec->segtotal = spec->buffer_time / spec->latency_time;
575 GST_OBJECT_UNLOCK (src);
577 GST_DEBUG ("release old ringbuffer");
579 gst_ring_buffer_release (src->ringbuffer);
581 gst_ring_buffer_debug_spec_buff (spec);
583 GST_DEBUG ("acquire new ringbuffer");
585 if (!gst_ring_buffer_acquire (src->ringbuffer, spec))
588 /* calculate actual latency and buffer times */
590 spec->segsize * GST_MSECOND / (spec->rate * spec->bytes_per_sample);
592 spec->segtotal * spec->segsize * GST_MSECOND / (spec->rate *
593 spec->bytes_per_sample);
595 gst_ring_buffer_debug_spec_buff (spec);
597 g_object_notify (G_OBJECT (src), "actual-buffer-time");
598 g_object_notify (G_OBJECT (src), "actual-latency-time");
605 GST_DEBUG ("could not parse caps");
610 GST_DEBUG ("could not acquire ringbuffer");
616 gst_base_audio_src_get_times (GstBaseSrc * bsrc, GstBuffer * buffer,
617 GstClockTime * start, GstClockTime * end)
619 /* no need to sync to a clock here, we schedule the samples based
620 * on our own clock for the moment. */
621 *start = GST_CLOCK_TIME_NONE;
622 *end = GST_CLOCK_TIME_NONE;
626 gst_base_audio_src_query (GstBaseSrc * bsrc, GstQuery * query)
628 GstBaseAudioSrc *src = GST_BASE_AUDIO_SRC (bsrc);
629 gboolean res = FALSE;
631 switch (GST_QUERY_TYPE (query)) {
632 case GST_QUERY_LATENCY:
634 GstClockTime min_latency, max_latency;
635 GstRingBufferSpec *spec;
637 GST_OBJECT_LOCK (src);
638 if (G_UNLIKELY (src->ringbuffer == NULL
639 || src->ringbuffer->spec.rate == 0)) {
640 GST_OBJECT_UNLOCK (src);
644 spec = &src->ringbuffer->spec;
646 /* we have at least 1 segment of latency */
648 gst_util_uint64_scale_int (spec->segsize, GST_SECOND,
649 spec->rate * spec->bytes_per_sample);
650 /* we cannot delay more than the buffersize else we lose data */
652 gst_util_uint64_scale_int (spec->segtotal * spec->segsize, GST_SECOND,
653 spec->rate * spec->bytes_per_sample);
654 GST_OBJECT_UNLOCK (src);
656 GST_DEBUG_OBJECT (src,
657 "report latency min %" GST_TIME_FORMAT " max %" GST_TIME_FORMAT,
658 GST_TIME_ARGS (min_latency), GST_TIME_ARGS (max_latency));
660 /* we are always live, the min latency is 1 segment and the max latency is
661 * the complete buffer of segments. */
662 gst_query_set_latency (query, TRUE, min_latency, max_latency);
668 res = GST_BASE_SRC_CLASS (parent_class)->query (bsrc, query);
676 gst_base_audio_src_event (GstBaseSrc * bsrc, GstEvent * event)
678 GstBaseAudioSrc *src = GST_BASE_AUDIO_SRC (bsrc);
683 switch (GST_EVENT_TYPE (event)) {
684 case GST_EVENT_FLUSH_START:
685 GST_DEBUG_OBJECT (bsrc, "flush-start");
686 gst_ring_buffer_pause (src->ringbuffer);
687 gst_ring_buffer_clear_all (src->ringbuffer);
689 case GST_EVENT_FLUSH_STOP:
690 GST_DEBUG_OBJECT (bsrc, "flush-stop");
691 /* always resync on sample after a flush */
692 src->next_sample = -1;
693 gst_ring_buffer_clear_all (src->ringbuffer);
696 GST_DEBUG_OBJECT (bsrc, "refuse to seek");
700 GST_DEBUG_OBJECT (bsrc, "dropping event %p", event);
706 /* get the next offset in the ringbuffer for reading samples.
707 * If the next sample is too far away, this function will position itself to the
708 * next most recent sample, creating discontinuity */
710 gst_base_audio_src_get_offset (GstBaseAudioSrc * src)
713 gint readseg, segdone, segtotal, sps;
716 /* assume we can append to the previous sample */
717 sample = src->next_sample;
719 sps = src->ringbuffer->samples_per_seg;
720 segtotal = src->ringbuffer->spec.segtotal;
722 /* get the currently processed segment */
723 segdone = g_atomic_int_get (&src->ringbuffer->segdone)
724 - src->ringbuffer->segbase;
727 GST_DEBUG_OBJECT (src, "at segment %d and sample %" G_GUINT64_FORMAT,
729 /* figure out the segment and the offset inside the segment where
730 * the sample should be read from. */
731 readseg = sample / sps;
733 /* see how far away it is from the read segment, normally segdone (where new
734 * data is written in the ringbuffer) is bigger than readseg (where we are
736 diff = segdone - readseg;
737 if (diff >= segtotal) {
738 GST_DEBUG_OBJECT (src, "dropped, align to segment %d", segdone);
739 /* sample would be dropped, position to next playable position */
740 sample = ((guint64) (segdone)) * sps;
743 /* no previous sample, go to the current position */
744 GST_DEBUG_OBJECT (src, "first sample, align to current %d", segdone);
745 sample = ((guint64) (segdone)) * sps;
749 GST_DEBUG_OBJECT (src,
750 "reading from %d, we are at %d, sample %" G_GUINT64_FORMAT, readseg,
757 gst_base_audio_src_create (GstBaseSrc * bsrc, guint64 offset, guint length,
760 GstBaseAudioSrc *src = GST_BASE_AUDIO_SRC (bsrc);
763 guint samples, total_samples;
766 GstRingBuffer *ringbuffer;
767 GstRingBufferSpec *spec;
769 GstClockTime timestamp, duration;
772 ringbuffer = src->ringbuffer;
773 spec = &ringbuffer->spec;
775 if (G_UNLIKELY (!gst_ring_buffer_is_acquired (ringbuffer)))
778 bps = spec->bytes_per_sample;
780 if ((length == 0 && bsrc->blocksize == 0) || length == -1)
781 /* no length given, use the default segment size */
782 length = spec->segsize;
784 /* make sure we round down to an integral number of samples */
785 length -= length % bps;
787 /* figure out the offset in the ringbuffer */
788 if (G_UNLIKELY (offset != -1)) {
789 sample = offset / bps;
790 /* if a specific offset was given it must be the next sequential
791 * offset we expect or we fail for now. */
792 if (src->next_sample != -1 && sample != src->next_sample)
795 /* calculate the sequentially next sample we need to read. This can jump and
796 * create a DISCONT. */
797 sample = gst_base_audio_src_get_offset (src);
800 GST_DEBUG_OBJECT (src, "reading from sample %" G_GUINT64_FORMAT, sample);
802 /* get the number of samples to read */
803 total_samples = samples = length / bps;
805 /* FIXME, using a bufferpool would be nice here */
806 buf = gst_buffer_new_and_alloc (length);
807 data = GST_BUFFER_DATA (buf);
810 read = gst_ring_buffer_read (ringbuffer, sample, data, samples);
811 GST_DEBUG_OBJECT (src, "read %u of %u", read, samples);
812 /* if we read all, we're done */
816 /* else something interrupted us and we wait for playing again. */
817 GST_DEBUG_OBJECT (src, "wait playing");
818 if (gst_base_src_wait_playing (bsrc) != GST_FLOW_OK)
821 GST_DEBUG_OBJECT (src, "continue playing");
823 /* read next samples */
829 /* mark discontinuity if needed */
830 if (G_UNLIKELY (sample != src->next_sample) && src->next_sample != -1) {
831 GST_WARNING_OBJECT (src,
832 "create DISCONT of %" G_GUINT64_FORMAT " samples at sample %"
833 G_GUINT64_FORMAT, sample - src->next_sample, sample);
834 GST_ELEMENT_WARNING (src, CORE, CLOCK,
835 (_("Can't record audio fast enough")),
836 ("Dropped %" G_GUINT64_FORMAT " samples. This is most likely because "
837 "downstream can't keep up and is consuming samples too slowly.",
838 sample - src->next_sample));
839 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
842 src->next_sample = sample + samples;
844 /* get the normal timestamp to get the duration. */
845 timestamp = gst_util_uint64_scale_int (sample, GST_SECOND, spec->rate);
846 duration = gst_util_uint64_scale_int (src->next_sample, GST_SECOND,
847 spec->rate) - timestamp;
849 GST_OBJECT_LOCK (src);
850 if (!(clock = GST_ELEMENT_CLOCK (src)))
853 if (clock != src->clock) {
854 /* we are slaved, check how to handle this */
855 switch (src->priv->slave_method) {
856 case GST_BASE_AUDIO_SRC_SLAVE_RESAMPLE:
857 /* not implemented, use skew algorithm. This algorithm should
858 * work on the readout pointer and produces more or less samples based
859 * on the clock drift */
860 case GST_BASE_AUDIO_SRC_SLAVE_SKEW:
862 GstClockTime running_time;
863 GstClockTime base_time;
864 GstClockTime current_time;
865 guint64 running_time_sample;
866 gint running_time_segment;
867 gint last_read_segment;
870 gint segments_written;
871 gint last_written_segment;
873 /* get the amount of segments written from the device by now */
874 segments_written = g_atomic_int_get (&ringbuffer->segdone);
876 /* subtract the base to segments_written to get the number of the
877 last written segment in the ringbuffer (one segment written = segment 0) */
878 last_written_segment = segments_written - ringbuffer->segbase - 1;
880 /* samples per segment */
881 sps = ringbuffer->samples_per_seg;
883 /* get the current time */
884 current_time = gst_clock_get_time (clock);
886 /* get the basetime */
887 base_time = GST_ELEMENT_CAST (src)->base_time;
889 /* get the running_time */
890 running_time = current_time - base_time;
892 /* the running_time converted to a sample (relative to the ringbuffer) */
893 running_time_sample =
894 gst_util_uint64_scale_int (running_time, spec->rate, GST_SECOND);
896 /* the segmentnr corrensponding to running_time, round down */
897 running_time_segment = running_time_sample / sps;
899 /* the segment currently read from the ringbuffer */
900 last_read_segment = sample / sps;
902 /* the skew we have between running_time and the ringbuffertime (last written to) */
903 segment_skew = running_time_segment - last_written_segment;
905 GST_DEBUG_OBJECT (bsrc,
906 "\n running_time = %"
910 "\n running_time_segment = %d"
911 "\n last_written_segment = %d"
912 "\n segment_skew (running time segment - last_written_segment) = %d"
913 "\n last_read_segment = %d",
914 GST_TIME_ARGS (running_time), GST_TIME_ARGS (timestamp),
915 running_time_segment, last_written_segment, segment_skew,
918 /* Resync the ringbuffer if:
920 * 1. We are more than the length of the ringbuffer behind.
921 * The length of the ringbuffer then gets to dictate
922 * the threshold for what is concidered "too late"
924 * 2. If this is our first buffer.
925 * We know that we should catch up to running_time
926 * the first time we are ran.
928 if ((segment_skew >= ringbuffer->spec.segtotal) ||
929 (last_read_segment == 0)) {
930 gint new_read_segment;
934 /* the difference between running_time and the last written segment */
935 segment_diff = running_time_segment - last_written_segment;
937 /* advance the ringbuffer */
938 gst_ring_buffer_advance (ringbuffer, segment_diff);
940 /* we move the new read segment to the last known written segment */
942 g_atomic_int_get (&ringbuffer->segdone) - ringbuffer->segbase;
944 /* we calculate the new sample value */
945 new_sample = ((guint64) new_read_segment) * sps;
947 /* and get the relative time to this -> our new timestamp */
949 gst_util_uint64_scale_int (new_sample, GST_SECOND, spec->rate);
951 /* we update the next sample accordingly */
952 src->next_sample = new_sample + samples;
954 GST_DEBUG_OBJECT (bsrc,
955 "Timeshifted the ringbuffer with %d segments: "
956 "Updating the timestamp to %" GST_TIME_FORMAT ", "
957 "and src->next_sample to %" G_GUINT64_FORMAT, segment_diff,
958 GST_TIME_ARGS (timestamp), src->next_sample);
962 case GST_BASE_AUDIO_SRC_SLAVE_RETIMESTAMP:
964 GstClockTime base_time, latency;
966 /* We are slaved to another clock, take running time of the pipeline clock and
967 * timestamp against it. Somebody else in the pipeline should figure out the
968 * clock drift. We keep the duration we calculated above. */
969 timestamp = gst_clock_get_time (clock);
970 base_time = GST_ELEMENT_CAST (src)->base_time;
972 if (GST_CLOCK_DIFF (timestamp, base_time) < 0)
973 timestamp -= base_time;
977 /* subtract latency */
979 gst_util_uint64_scale_int (total_samples, GST_SECOND, spec->rate);
980 if (timestamp > latency)
981 timestamp -= latency;
985 case GST_BASE_AUDIO_SRC_SLAVE_NONE:
989 GstClockTime base_time;
991 /* to get the timestamp against the clock we also need to add our offset */
992 timestamp = gst_audio_clock_adjust (clock, timestamp);
994 /* we are not slaved, subtract base_time */
995 base_time = GST_ELEMENT_CAST (src)->base_time;
997 if (GST_CLOCK_DIFF (timestamp, base_time) < 0) {
998 timestamp -= base_time;
1000 "buffer timestamp %" GST_TIME_FORMAT " (base_time %" GST_TIME_FORMAT
1001 ")", GST_TIME_ARGS (timestamp), GST_TIME_ARGS (base_time));
1003 GST_LOG_OBJECT (src,
1004 "buffer timestamp 0, ts %" GST_TIME_FORMAT " <= base_time %"
1005 GST_TIME_FORMAT, GST_TIME_ARGS (timestamp),
1006 GST_TIME_ARGS (base_time));
1012 GST_OBJECT_UNLOCK (src);
1014 GST_BUFFER_TIMESTAMP (buf) = timestamp;
1015 GST_BUFFER_DURATION (buf) = duration;
1016 GST_BUFFER_OFFSET (buf) = sample;
1017 GST_BUFFER_OFFSET_END (buf) = sample + samples;
1026 GST_DEBUG_OBJECT (src, "ringbuffer in wrong state");
1027 return GST_FLOW_WRONG_STATE;
1031 GST_ELEMENT_ERROR (src, RESOURCE, SEEK,
1032 (NULL), ("resource can only be operated on sequentially but offset %"
1033 G_GUINT64_FORMAT " was given", offset));
1034 return GST_FLOW_ERROR;
1038 gst_buffer_unref (buf);
1039 GST_DEBUG_OBJECT (src, "ringbuffer stopped");
1040 return GST_FLOW_WRONG_STATE;
1045 * gst_base_audio_src_create_ringbuffer:
1046 * @src: a #GstBaseAudioSrc.
1048 * Create and return the #GstRingBuffer for @src. This function will call the
1049 * ::create_ringbuffer vmethod and will set @src as the parent of the returned
1050 * buffer (see gst_object_set_parent()).
1052 * Returns: The new ringbuffer of @src.
1055 gst_base_audio_src_create_ringbuffer (GstBaseAudioSrc * src)
1057 GstBaseAudioSrcClass *bclass;
1058 GstRingBuffer *buffer = NULL;
1060 bclass = GST_BASE_AUDIO_SRC_GET_CLASS (src);
1061 if (bclass->create_ringbuffer)
1062 buffer = bclass->create_ringbuffer (src);
1064 if (G_LIKELY (buffer))
1065 gst_object_set_parent (GST_OBJECT_CAST (buffer), GST_OBJECT_CAST (src));
1070 static GstStateChangeReturn
1071 gst_base_audio_src_change_state (GstElement * element,
1072 GstStateChange transition)
1074 GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
1075 GstBaseAudioSrc *src = GST_BASE_AUDIO_SRC (element);
1077 switch (transition) {
1078 case GST_STATE_CHANGE_NULL_TO_READY:
1079 GST_DEBUG_OBJECT (src, "NULL->READY");
1080 GST_OBJECT_LOCK (src);
1081 if (src->ringbuffer == NULL) {
1082 gst_audio_clock_reset (GST_AUDIO_CLOCK (src->clock), 0);
1083 src->ringbuffer = gst_base_audio_src_create_ringbuffer (src);
1085 GST_OBJECT_UNLOCK (src);
1086 if (!gst_ring_buffer_open_device (src->ringbuffer))
1089 case GST_STATE_CHANGE_READY_TO_PAUSED:
1090 GST_DEBUG_OBJECT (src, "READY->PAUSED");
1091 src->next_sample = -1;
1092 gst_ring_buffer_set_flushing (src->ringbuffer, FALSE);
1093 gst_ring_buffer_may_start (src->ringbuffer, FALSE);
1094 /* Only post clock-provide messages if this is the clock that
1095 * we've created. If the subclass has overriden it the subclass
1096 * should post this messages whenever necessary */
1097 if (src->clock && GST_IS_AUDIO_CLOCK (src->clock) &&
1098 GST_AUDIO_CLOCK_CAST (src->clock)->func ==
1099 (GstAudioClockGetTimeFunc) gst_base_audio_src_get_time)
1100 gst_element_post_message (element,
1101 gst_message_new_clock_provide (GST_OBJECT_CAST (element),
1104 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
1105 GST_DEBUG_OBJECT (src, "PAUSED->PLAYING");
1106 gst_ring_buffer_may_start (src->ringbuffer, TRUE);
1108 case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
1109 GST_DEBUG_OBJECT (src, "PLAYING->PAUSED");
1110 gst_ring_buffer_may_start (src->ringbuffer, FALSE);
1111 gst_ring_buffer_pause (src->ringbuffer);
1113 case GST_STATE_CHANGE_PAUSED_TO_READY:
1114 GST_DEBUG_OBJECT (src, "PAUSED->READY");
1115 /* Only post clock-lost messages if this is the clock that
1116 * we've created. If the subclass has overriden it the subclass
1117 * should post this messages whenever necessary */
1118 if (src->clock && GST_IS_AUDIO_CLOCK (src->clock) &&
1119 GST_AUDIO_CLOCK_CAST (src->clock)->func ==
1120 (GstAudioClockGetTimeFunc) gst_base_audio_src_get_time)
1121 gst_element_post_message (element,
1122 gst_message_new_clock_lost (GST_OBJECT_CAST (element), src->clock));
1123 gst_ring_buffer_set_flushing (src->ringbuffer, TRUE);
1129 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1131 switch (transition) {
1132 case GST_STATE_CHANGE_PAUSED_TO_READY:
1133 GST_DEBUG_OBJECT (src, "PAUSED->READY");
1134 gst_ring_buffer_release (src->ringbuffer);
1136 case GST_STATE_CHANGE_READY_TO_NULL:
1137 GST_DEBUG_OBJECT (src, "READY->NULL");
1138 gst_ring_buffer_close_device (src->ringbuffer);
1139 GST_OBJECT_LOCK (src);
1140 gst_object_unparent (GST_OBJECT_CAST (src->ringbuffer));
1141 src->ringbuffer = NULL;
1142 GST_OBJECT_UNLOCK (src);
1153 /* subclass must post a meaningfull error message */
1154 GST_DEBUG_OBJECT (src, "open failed");
1155 return GST_STATE_CHANGE_FAILURE;