1 /* GStreamer
2 * Copyright (C) 2005 Wim Taymans <wim@fluendo.com>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19
20 /**
21 * SECTION:gstaudioringbuffer
22 * @title: GstAudioRingBuffer
23 * @short_description: Base class for audio ringbuffer implementations
24 * @see_also: #GstAudioBaseSink, #GstAudioSink
25 *
26 * This object is the base class for audio ringbuffers used by the base
27 * audio source and sink classes.
28 *
29 * The ringbuffer abstracts a circular buffer of data. One reader and
30 * one writer can operate on the data from different threads in a lockfree
31 * manner. The base class is sufficiently flexible to be used as an
32 * abstraction for DMA based ringbuffers as well as a pure software
33 * implementations.
34 *
35 */
36 #ifdef HAVE_CONFIG_H
37 #include "config.h"
38 #endif
39
40 #include <string.h>
41
42 #include <gst/audio/audio.h>
43 #include "gstaudioringbuffer.h"
44
45 GST_DEBUG_CATEGORY_STATIC (gst_audio_ring_buffer_debug);
46 #define GST_CAT_DEFAULT gst_audio_ring_buffer_debug
47
48 static void gst_audio_ring_buffer_dispose (GObject * object);
49 static void gst_audio_ring_buffer_finalize (GObject * object);
50
51 static gboolean gst_audio_ring_buffer_pause_unlocked (GstAudioRingBuffer * buf);
52 static void default_clear_all (GstAudioRingBuffer * buf);
53 static guint default_commit (GstAudioRingBuffer * buf, guint64 * sample,
54 guint8 * data, gint in_samples, gint out_samples, gint * accum);
55
56 /* ringbuffer abstract base class */
57 G_DEFINE_ABSTRACT_TYPE (GstAudioRingBuffer, gst_audio_ring_buffer,
58 GST_TYPE_OBJECT);
59
60 static void
gst_audio_ring_buffer_class_init(GstAudioRingBufferClass * klass)61 gst_audio_ring_buffer_class_init (GstAudioRingBufferClass * klass)
62 {
63 GObjectClass *gobject_class;
64 GstAudioRingBufferClass *gstaudioringbuffer_class;
65
66 gobject_class = (GObjectClass *) klass;
67 gstaudioringbuffer_class = (GstAudioRingBufferClass *) klass;
68
69 GST_DEBUG_CATEGORY_INIT (gst_audio_ring_buffer_debug, "ringbuffer", 0,
70 "ringbuffer class");
71
72 gobject_class->dispose = gst_audio_ring_buffer_dispose;
73 gobject_class->finalize = gst_audio_ring_buffer_finalize;
74
75 gstaudioringbuffer_class->clear_all = GST_DEBUG_FUNCPTR (default_clear_all);
76 gstaudioringbuffer_class->commit = GST_DEBUG_FUNCPTR (default_commit);
77 }
78
79 static void
gst_audio_ring_buffer_init(GstAudioRingBuffer * ringbuffer)80 gst_audio_ring_buffer_init (GstAudioRingBuffer * ringbuffer)
81 {
82 ringbuffer->open = FALSE;
83 ringbuffer->acquired = FALSE;
84 ringbuffer->state = GST_AUDIO_RING_BUFFER_STATE_STOPPED;
85 g_cond_init (&ringbuffer->cond);
86 ringbuffer->waiting = 0;
87 ringbuffer->empty_seg = NULL;
88 ringbuffer->flushing = TRUE;
89 ringbuffer->segbase = 0;
90 ringbuffer->segdone = 0;
91 }
92
93 static void
gst_audio_ring_buffer_dispose(GObject * object)94 gst_audio_ring_buffer_dispose (GObject * object)
95 {
96 GstAudioRingBuffer *ringbuffer = GST_AUDIO_RING_BUFFER (object);
97
98 gst_caps_replace (&ringbuffer->spec.caps, NULL);
99
100 G_OBJECT_CLASS (gst_audio_ring_buffer_parent_class)->dispose (G_OBJECT
101 (ringbuffer));
102 }
103
104 static void
gst_audio_ring_buffer_finalize(GObject * object)105 gst_audio_ring_buffer_finalize (GObject * object)
106 {
107 GstAudioRingBuffer *ringbuffer = GST_AUDIO_RING_BUFFER (object);
108
109 g_cond_clear (&ringbuffer->cond);
110 g_free (ringbuffer->empty_seg);
111
112 if (ringbuffer->cb_data_notify != NULL)
113 ringbuffer->cb_data_notify (ringbuffer->cb_data);
114
115 G_OBJECT_CLASS (gst_audio_ring_buffer_parent_class)->finalize (G_OBJECT
116 (ringbuffer));
117 }
118
119 #ifndef GST_DISABLE_GST_DEBUG
120 static const gchar *format_type_names[] = {
121 "raw",
122 "mu law",
123 "a law",
124 "ima adpcm",
125 "mpeg",
126 "gsm",
127 "iec958",
128 "ac3",
129 "eac3",
130 "dts",
131 "aac mpeg2",
132 "aac mpeg4",
133 "aac mpeg2 raw",
134 "aac mpeg4 raw",
135 "flac"
136 };
137 #endif
138
139 /**
140 * gst_audio_ring_buffer_debug_spec_caps:
141 * @spec: the spec to debug
142 *
143 * Print debug info about the parsed caps in @spec to the debug log.
144 */
145 void
gst_audio_ring_buffer_debug_spec_caps(GstAudioRingBufferSpec * spec)146 gst_audio_ring_buffer_debug_spec_caps (GstAudioRingBufferSpec * spec)
147 {
148 #if 0
149 gint i, bytes;
150 #endif
151
152 GST_DEBUG ("spec caps: %p %" GST_PTR_FORMAT, spec->caps, spec->caps);
153 GST_DEBUG ("parsed caps: type: %d, '%s'", spec->type,
154 format_type_names[spec->type]);
155 #if 0
156 GST_DEBUG ("parsed caps: width: %d", spec->width);
157 GST_DEBUG ("parsed caps: sign: %d", spec->sign);
158 GST_DEBUG ("parsed caps: bigend: %d", spec->bigend);
159 GST_DEBUG ("parsed caps: rate: %d", spec->rate);
160 GST_DEBUG ("parsed caps: channels: %d", spec->channels);
161 GST_DEBUG ("parsed caps: sample bytes: %d", spec->bytes_per_sample);
162 bytes = (spec->width >> 3) * spec->channels;
163 for (i = 0; i < bytes; i++) {
164 GST_DEBUG ("silence byte %d: %02x", i, spec->silence_sample[i]);
165 }
166 #endif
167 }
168
169 /**
170 * gst_audio_ring_buffer_debug_spec_buff:
171 * @spec: the spec to debug
172 *
173 * Print debug info about the buffer sized in @spec to the debug log.
174 */
175 void
gst_audio_ring_buffer_debug_spec_buff(GstAudioRingBufferSpec * spec)176 gst_audio_ring_buffer_debug_spec_buff (GstAudioRingBufferSpec * spec)
177 {
178 gint bpf = GST_AUDIO_INFO_BPF (&spec->info);
179
180 GST_DEBUG ("acquire ringbuffer: buffer time: %" G_GINT64_FORMAT " usec",
181 spec->buffer_time);
182 GST_DEBUG ("acquire ringbuffer: latency time: %" G_GINT64_FORMAT " usec",
183 spec->latency_time);
184 GST_DEBUG ("acquire ringbuffer: total segments: %d", spec->segtotal);
185 GST_DEBUG ("acquire ringbuffer: latency segments: %d", spec->seglatency);
186 GST_DEBUG ("acquire ringbuffer: segment size: %d bytes = %d samples",
187 spec->segsize, (bpf != 0) ? (spec->segsize / bpf) : -1);
188 GST_DEBUG ("acquire ringbuffer: buffer size: %d bytes = %d samples",
189 spec->segsize * spec->segtotal,
190 (bpf != 0) ? (spec->segsize * spec->segtotal / bpf) : -1);
191 }
192
193 /**
194 * gst_audio_ring_buffer_parse_caps:
195 * @spec: a spec
196 * @caps: a #GstCaps
197 *
198 * Parse @caps into @spec.
199 *
200 * Returns: TRUE if the caps could be parsed.
201 */
202 gboolean
gst_audio_ring_buffer_parse_caps(GstAudioRingBufferSpec * spec,GstCaps * caps)203 gst_audio_ring_buffer_parse_caps (GstAudioRingBufferSpec * spec, GstCaps * caps)
204 {
205 const gchar *mimetype;
206 GstStructure *structure;
207 gint i;
208 GstAudioInfo info;
209
210 structure = gst_caps_get_structure (caps, 0);
211 gst_audio_info_init (&info);
212
213 /* we have to differentiate between int and float formats */
214 mimetype = gst_structure_get_name (structure);
215
216 if (g_str_equal (mimetype, "audio/x-raw")) {
217 if (!gst_audio_info_from_caps (&info, caps))
218 goto parse_error;
219
220 spec->type = GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW;
221 } else if (g_str_equal (mimetype, "audio/x-alaw")) {
222 /* extract the needed information from the cap */
223 if (!(gst_structure_get_int (structure, "rate", &info.rate) &&
224 gst_structure_get_int (structure, "channels", &info.channels)))
225 goto parse_error;
226
227 if (!(gst_audio_channel_positions_from_mask (info.channels, 0,
228 info.position)))
229 goto parse_error;
230
231 spec->type = GST_AUDIO_RING_BUFFER_FORMAT_TYPE_A_LAW;
232 info.bpf = info.channels;
233 } else if (g_str_equal (mimetype, "audio/x-mulaw")) {
234 /* extract the needed information from the cap */
235 if (!(gst_structure_get_int (structure, "rate", &info.rate) &&
236 gst_structure_get_int (structure, "channels", &info.channels)))
237 goto parse_error;
238
239 if (!(gst_audio_channel_positions_from_mask (info.channels, 0,
240 info.position)))
241 goto parse_error;
242
243 spec->type = GST_AUDIO_RING_BUFFER_FORMAT_TYPE_MU_LAW;
244 info.bpf = info.channels;
245 } else if (g_str_equal (mimetype, "audio/x-iec958")) {
246 /* extract the needed information from the cap */
247 if (!(gst_structure_get_int (structure, "rate", &info.rate)))
248 goto parse_error;
249
250 spec->type = GST_AUDIO_RING_BUFFER_FORMAT_TYPE_IEC958;
251 info.bpf = 4;
252 } else if (g_str_equal (mimetype, "audio/x-ac3")) {
253 /* extract the needed information from the cap */
254 if (!(gst_structure_get_int (structure, "rate", &info.rate)))
255 goto parse_error;
256
257 gst_structure_get_int (structure, "channels", &info.channels);
258 spec->type = GST_AUDIO_RING_BUFFER_FORMAT_TYPE_AC3;
259 info.bpf = 4;
260 } else if (g_str_equal (mimetype, "audio/x-eac3")) {
261 /* extract the needed information from the cap */
262 if (!(gst_structure_get_int (structure, "rate", &info.rate)))
263 goto parse_error;
264
265 gst_structure_get_int (structure, "channels", &info.channels);
266 spec->type = GST_AUDIO_RING_BUFFER_FORMAT_TYPE_EAC3;
267 info.bpf = 16;
268 } else if (g_str_equal (mimetype, "audio/x-dts")) {
269 /* extract the needed information from the cap */
270 if (!(gst_structure_get_int (structure, "rate", &info.rate)))
271 goto parse_error;
272
273 gst_structure_get_int (structure, "channels", &info.channels);
274 spec->type = GST_AUDIO_RING_BUFFER_FORMAT_TYPE_DTS;
275 info.bpf = 4;
276 } else if (g_str_equal (mimetype, "audio/mpeg") &&
277 gst_structure_get_int (structure, "mpegaudioversion", &i) &&
278 (i == 1 || i == 2 || i == 3)) {
279 /* Now we know this is MPEG-1, MPEG-2 or MPEG-2.5 (non AAC) */
280 /* extract the needed information from the cap */
281 if (!(gst_structure_get_int (structure, "rate", &info.rate)))
282 goto parse_error;
283
284 gst_structure_get_int (structure, "channels", &info.channels);
285 spec->type = GST_AUDIO_RING_BUFFER_FORMAT_TYPE_MPEG;
286 info.bpf = 1;
287 } else if (g_str_equal (mimetype, "audio/mpeg") &&
288 gst_structure_get_int (structure, "mpegversion", &i) &&
289 (i == 2 || i == 4) &&
290 (!g_strcmp0 (gst_structure_get_string (structure, "stream-format"),
291 "adts")
292 || !g_strcmp0 (gst_structure_get_string (structure, "stream-format"),
293 "raw"))) {
294 /* MPEG-2 AAC or MPEG-4 AAC */
295 if (!(gst_structure_get_int (structure, "rate", &info.rate)))
296 goto parse_error;
297
298 gst_structure_get_int (structure, "channels", &info.channels);
299 if (!g_strcmp0 (gst_structure_get_string (structure, "stream-format"),
300 "adts"))
301 spec->type = (i == 2) ? GST_AUDIO_RING_BUFFER_FORMAT_TYPE_MPEG2_AAC :
302 GST_AUDIO_RING_BUFFER_FORMAT_TYPE_MPEG4_AAC;
303 else
304 spec->type = (i == 2) ?
305 GST_AUDIO_RING_BUFFER_FORMAT_TYPE_MPEG2_AAC_RAW :
306 GST_AUDIO_RING_BUFFER_FORMAT_TYPE_MPEG4_AAC_RAW;
307 info.bpf = 1;
308 } else if (g_str_equal (mimetype, "audio/x-flac")) {
309 /* extract the needed information from the cap */
310 if (!(gst_structure_get_int (structure, "rate", &info.rate)))
311 goto parse_error;
312
313 gst_structure_get_int (structure, "channels", &info.channels);
314 spec->type = GST_AUDIO_RING_BUFFER_FORMAT_TYPE_FLAC;
315 info.bpf = 1;
316 } else {
317 goto parse_error;
318 }
319
320 gst_caps_replace (&spec->caps, caps);
321
322 g_return_val_if_fail (spec->latency_time != 0, FALSE);
323
324 /* calculate suggested segsize and segtotal. segsize should be one unit
325 * of 'latency_time' samples, scaling for the fact that latency_time is
326 * currently stored in microseconds (FIXME: in 0.11) */
327 spec->segsize = gst_util_uint64_scale (info.rate * info.bpf,
328 spec->latency_time, GST_SECOND / GST_USECOND);
329 /* Round to an integer number of samples */
330 spec->segsize -= spec->segsize % info.bpf;
331
332 spec->segtotal = spec->buffer_time / spec->latency_time;
333 /* leave the latency undefined now, implementations can change it but if it's
334 * not changed, we assume the same value as segtotal */
335 spec->seglatency = -1;
336
337 spec->info = info;
338
339 gst_audio_ring_buffer_debug_spec_caps (spec);
340 gst_audio_ring_buffer_debug_spec_buff (spec);
341
342 return TRUE;
343
344 /* ERRORS */
345 parse_error:
346 {
347 GST_DEBUG ("could not parse caps");
348 return FALSE;
349 }
350 }
351
352 /**
353 * gst_audio_ring_buffer_convert:
354 * @buf: the #GstAudioRingBuffer
355 * @src_fmt: the source format
356 * @src_val: the source value
357 * @dest_fmt: the destination format
358 * @dest_val: (out): a location to store the converted value
359 *
360 * Convert @src_val in @src_fmt to the equivalent value in @dest_fmt. The result
361 * will be put in @dest_val.
362 *
363 * Returns: TRUE if the conversion succeeded.
364 */
365 gboolean
gst_audio_ring_buffer_convert(GstAudioRingBuffer * buf,GstFormat src_fmt,gint64 src_val,GstFormat dest_fmt,gint64 * dest_val)366 gst_audio_ring_buffer_convert (GstAudioRingBuffer * buf,
367 GstFormat src_fmt, gint64 src_val, GstFormat dest_fmt, gint64 * dest_val)
368 {
369 gboolean res;
370
371 GST_OBJECT_LOCK (buf);
372 res =
373 gst_audio_info_convert (&buf->spec.info, src_fmt, src_val, dest_fmt,
374 dest_val);
375 GST_OBJECT_UNLOCK (buf);
376
377 return res;
378 }
379
380 /**
381 * gst_audio_ring_buffer_set_callback: (skip)
382 * @buf: the #GstAudioRingBuffer to set the callback on
383 * @cb: (allow-none): the callback to set
384 * @user_data: user data passed to the callback
385 *
386 * Sets the given callback function on the buffer. This function
387 * will be called every time a segment has been written to a device.
388 *
389 * MT safe.
390 */
391 void
gst_audio_ring_buffer_set_callback(GstAudioRingBuffer * buf,GstAudioRingBufferCallback cb,gpointer user_data)392 gst_audio_ring_buffer_set_callback (GstAudioRingBuffer * buf,
393 GstAudioRingBufferCallback cb, gpointer user_data)
394 {
395 gst_audio_ring_buffer_set_callback_full (buf, cb, user_data, NULL);
396 }
397
398 /**
399 * gst_audio_ring_buffer_set_callback_full: (rename-to gst_audio_ring_buffer_set_callback)
400 * @buf: the #GstAudioRingBuffer to set the callback on
401 * @cb: (allow-none): the callback to set
402 * @user_data: user data passed to the callback
403 * @notify: function to be called when @user_data is no longer needed
404 *
405 * Sets the given callback function on the buffer. This function
406 * will be called every time a segment has been written to a device.
407 *
408 * MT safe.
409 *
410 * Since: 1.12
411 */
412 void
gst_audio_ring_buffer_set_callback_full(GstAudioRingBuffer * buf,GstAudioRingBufferCallback cb,gpointer user_data,GDestroyNotify notify)413 gst_audio_ring_buffer_set_callback_full (GstAudioRingBuffer * buf,
414 GstAudioRingBufferCallback cb, gpointer user_data, GDestroyNotify notify)
415 {
416 gpointer old_data = NULL;
417 GDestroyNotify old_notify;
418
419 g_return_if_fail (GST_IS_AUDIO_RING_BUFFER (buf));
420
421 GST_OBJECT_LOCK (buf);
422 old_notify = buf->cb_data_notify;
423 old_data = buf->cb_data;
424
425 buf->callback = cb;
426 buf->cb_data = user_data;
427 buf->cb_data_notify = notify;
428 GST_OBJECT_UNLOCK (buf);
429
430 if (old_notify) {
431 old_notify (old_data);
432 }
433 }
434
435
436 /**
437 * gst_audio_ring_buffer_open_device:
438 * @buf: the #GstAudioRingBuffer
439 *
440 * Open the audio device associated with the ring buffer. Does not perform any
441 * setup on the device. You must open the device before acquiring the ring
442 * buffer.
443 *
444 * Returns: TRUE if the device could be opened, FALSE on error.
445 *
446 * MT safe.
447 */
448 gboolean
gst_audio_ring_buffer_open_device(GstAudioRingBuffer * buf)449 gst_audio_ring_buffer_open_device (GstAudioRingBuffer * buf)
450 {
451 gboolean res = TRUE;
452 GstAudioRingBufferClass *rclass;
453
454 g_return_val_if_fail (GST_IS_AUDIO_RING_BUFFER (buf), FALSE);
455
456 GST_DEBUG_OBJECT (buf, "opening device");
457
458 GST_OBJECT_LOCK (buf);
459 if (G_UNLIKELY (buf->open))
460 goto was_opened;
461
462 buf->open = TRUE;
463
464 /* if this fails, something is wrong in this file */
465 g_assert (!buf->acquired);
466
467 rclass = GST_AUDIO_RING_BUFFER_GET_CLASS (buf);
468 if (G_LIKELY (rclass->open_device))
469 res = rclass->open_device (buf);
470
471 if (G_UNLIKELY (!res))
472 goto open_failed;
473
474 GST_DEBUG_OBJECT (buf, "opened device");
475
476 done:
477 GST_OBJECT_UNLOCK (buf);
478
479 return res;
480
481 /* ERRORS */
482 was_opened:
483 {
484 GST_DEBUG_OBJECT (buf, "Device for ring buffer already open");
485 g_warning ("Device for ring buffer %p already open, fix your code", buf);
486 res = TRUE;
487 goto done;
488 }
489 open_failed:
490 {
491 buf->open = FALSE;
492 GST_DEBUG_OBJECT (buf, "failed opening device");
493 goto done;
494 }
495 }
496
497 /**
498 * gst_audio_ring_buffer_close_device:
499 * @buf: the #GstAudioRingBuffer
500 *
501 * Close the audio device associated with the ring buffer. The ring buffer
502 * should already have been released via gst_audio_ring_buffer_release().
503 *
504 * Returns: TRUE if the device could be closed, FALSE on error.
505 *
506 * MT safe.
507 */
508 gboolean
gst_audio_ring_buffer_close_device(GstAudioRingBuffer * buf)509 gst_audio_ring_buffer_close_device (GstAudioRingBuffer * buf)
510 {
511 gboolean res = TRUE;
512 GstAudioRingBufferClass *rclass;
513
514 g_return_val_if_fail (GST_IS_AUDIO_RING_BUFFER (buf), FALSE);
515
516 GST_DEBUG_OBJECT (buf, "closing device");
517
518 GST_OBJECT_LOCK (buf);
519 if (G_UNLIKELY (!buf->open))
520 goto was_closed;
521
522 if (G_UNLIKELY (buf->acquired))
523 goto was_acquired;
524
525 buf->open = FALSE;
526
527 rclass = GST_AUDIO_RING_BUFFER_GET_CLASS (buf);
528 if (G_LIKELY (rclass->close_device))
529 res = rclass->close_device (buf);
530
531 if (G_UNLIKELY (!res))
532 goto close_error;
533
534 GST_DEBUG_OBJECT (buf, "closed device");
535
536 done:
537 GST_OBJECT_UNLOCK (buf);
538
539 return res;
540
541 /* ERRORS */
542 was_closed:
543 {
544 GST_DEBUG_OBJECT (buf, "Device for ring buffer already closed");
545 g_warning ("Device for ring buffer %p already closed, fix your code", buf);
546 res = TRUE;
547 goto done;
548 }
549 was_acquired:
550 {
551 GST_DEBUG_OBJECT (buf, "Resources for ring buffer still acquired");
552 g_critical ("Resources for ring buffer %p still acquired", buf);
553 res = FALSE;
554 goto done;
555 }
556 close_error:
557 {
558 buf->open = TRUE;
559 GST_DEBUG_OBJECT (buf, "error closing device");
560 goto done;
561 }
562 }
563
564 /**
565 * gst_audio_ring_buffer_device_is_open:
566 * @buf: the #GstAudioRingBuffer
567 *
568 * Checks the status of the device associated with the ring buffer.
569 *
570 * Returns: TRUE if the device was open, FALSE if it was closed.
571 *
572 * MT safe.
573 */
574 gboolean
gst_audio_ring_buffer_device_is_open(GstAudioRingBuffer * buf)575 gst_audio_ring_buffer_device_is_open (GstAudioRingBuffer * buf)
576 {
577 gboolean res = TRUE;
578
579 g_return_val_if_fail (GST_IS_AUDIO_RING_BUFFER (buf), FALSE);
580
581 GST_OBJECT_LOCK (buf);
582 res = buf->open;
583 GST_OBJECT_UNLOCK (buf);
584
585 return res;
586 }
587
588 /**
589 * gst_audio_ring_buffer_acquire:
590 * @buf: the #GstAudioRingBuffer to acquire
591 * @spec: the specs of the buffer
592 *
593 * Allocate the resources for the ringbuffer. This function fills
594 * in the data pointer of the ring buffer with a valid #GstBuffer
595 * to which samples can be written.
596 *
597 * Returns: TRUE if the device could be acquired, FALSE on error.
598 *
599 * MT safe.
600 */
601 gboolean
gst_audio_ring_buffer_acquire(GstAudioRingBuffer * buf,GstAudioRingBufferSpec * spec)602 gst_audio_ring_buffer_acquire (GstAudioRingBuffer * buf,
603 GstAudioRingBufferSpec * spec)
604 {
605 gboolean res = FALSE;
606 GstAudioRingBufferClass *rclass;
607 gint segsize, bpf, i;
608
609 g_return_val_if_fail (GST_IS_AUDIO_RING_BUFFER (buf), FALSE);
610
611 GST_DEBUG_OBJECT (buf, "acquiring device %p", buf);
612
613 GST_OBJECT_LOCK (buf);
614 if (G_UNLIKELY (!buf->open))
615 goto not_opened;
616
617 if (G_UNLIKELY (buf->acquired))
618 goto was_acquired;
619
620 buf->acquired = TRUE;
621 buf->need_reorder = FALSE;
622
623 rclass = GST_AUDIO_RING_BUFFER_GET_CLASS (buf);
624 if (G_LIKELY (rclass->acquire))
625 res = rclass->acquire (buf, spec);
626
627 /* Only reorder for raw audio */
628 buf->need_reorder = (buf->need_reorder
629 && buf->spec.type == GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW);
630
631 if (G_UNLIKELY (!res))
632 goto acquire_failed;
633
634 GST_INFO_OBJECT (buf, "Allocating an array for %d timestamps",
635 spec->segtotal);
636 buf->timestamps = g_slice_alloc0 (sizeof (GstClockTime) * spec->segtotal);
637 /* initialize array with invalid timestamps */
638 for (i = 0; i < spec->segtotal; i++) {
639 buf->timestamps[i] = GST_CLOCK_TIME_NONE;
640 }
641
642 if (G_UNLIKELY ((bpf = buf->spec.info.bpf) == 0))
643 goto invalid_bpf;
644
645 /* if the seglatency was overwritten with something else than -1, use it, else
646 * assume segtotal as the latency */
647 if (buf->spec.seglatency == -1)
648 buf->spec.seglatency = buf->spec.segtotal;
649
650 segsize = buf->spec.segsize;
651
652 buf->samples_per_seg = segsize / bpf;
653
654 /* create an empty segment */
655 g_free (buf->empty_seg);
656 buf->empty_seg = g_malloc (segsize);
657
658 if (buf->spec.type == GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW) {
659 gst_audio_format_fill_silence (buf->spec.info.finfo, buf->empty_seg,
660 segsize);
661 } else {
662 /* FIXME, non-raw formats get 0 as the empty sample */
663 memset (buf->empty_seg, 0, segsize);
664 }
665 GST_DEBUG_OBJECT (buf, "acquired device");
666
667 done:
668 GST_OBJECT_UNLOCK (buf);
669
670 return res;
671
672 /* ERRORS */
673 not_opened:
674 {
675 GST_DEBUG_OBJECT (buf, "device not opened");
676 g_critical ("Device for %p not opened", buf);
677 res = FALSE;
678 goto done;
679 }
680 was_acquired:
681 {
682 res = TRUE;
683 GST_DEBUG_OBJECT (buf, "device was acquired");
684 goto done;
685 }
686 acquire_failed:
687 {
688 buf->acquired = FALSE;
689 GST_DEBUG_OBJECT (buf, "failed to acquire device");
690 goto done;
691 }
692 invalid_bpf:
693 {
694 g_warning
695 ("invalid bytes_per_frame from acquire ringbuffer %p, fix the element",
696 buf);
697 buf->acquired = FALSE;
698 res = FALSE;
699 goto done;
700 }
701 }
702
703 /**
704 * gst_audio_ring_buffer_release:
705 * @buf: the #GstAudioRingBuffer to release
706 *
707 * Free the resources of the ringbuffer.
708 *
709 * Returns: TRUE if the device could be released, FALSE on error.
710 *
711 * MT safe.
712 */
713 gboolean
gst_audio_ring_buffer_release(GstAudioRingBuffer * buf)714 gst_audio_ring_buffer_release (GstAudioRingBuffer * buf)
715 {
716 gboolean res = FALSE;
717 GstAudioRingBufferClass *rclass;
718
719 g_return_val_if_fail (GST_IS_AUDIO_RING_BUFFER (buf), FALSE);
720
721 GST_DEBUG_OBJECT (buf, "releasing device");
722
723 gst_audio_ring_buffer_stop (buf);
724
725 GST_OBJECT_LOCK (buf);
726
727 if (G_LIKELY (buf->timestamps)) {
728 GST_INFO_OBJECT (buf, "Freeing timestamp buffer, %d entries",
729 buf->spec.segtotal);
730 g_slice_free1 (sizeof (GstClockTime) * buf->spec.segtotal, buf->timestamps);
731 buf->timestamps = NULL;
732 }
733
734 if (G_UNLIKELY (!buf->acquired))
735 goto was_released;
736
737 buf->acquired = FALSE;
738
739 /* if this fails, something is wrong in this file */
740 g_assert (buf->open);
741
742 rclass = GST_AUDIO_RING_BUFFER_GET_CLASS (buf);
743 if (G_LIKELY (rclass->release))
744 res = rclass->release (buf);
745
746 /* signal any waiters */
747 GST_DEBUG_OBJECT (buf, "signal waiter");
748 GST_AUDIO_RING_BUFFER_SIGNAL (buf);
749
750 if (G_UNLIKELY (!res))
751 goto release_failed;
752
753 g_atomic_int_set (&buf->segdone, 0);
754 buf->segbase = 0;
755 g_free (buf->empty_seg);
756 buf->empty_seg = NULL;
757 gst_caps_replace (&buf->spec.caps, NULL);
758 gst_audio_info_init (&buf->spec.info);
759 GST_DEBUG_OBJECT (buf, "released device");
760
761 done:
762 GST_OBJECT_UNLOCK (buf);
763
764 return res;
765
766 /* ERRORS */
767 was_released:
768 {
769 res = TRUE;
770 GST_DEBUG_OBJECT (buf, "device was released");
771 goto done;
772 }
773 release_failed:
774 {
775 buf->acquired = TRUE;
776 GST_DEBUG_OBJECT (buf, "failed to release device");
777 goto done;
778 }
779 }
780
781 /**
782 * gst_audio_ring_buffer_is_acquired:
783 * @buf: the #GstAudioRingBuffer to check
784 *
785 * Check if the ringbuffer is acquired and ready to use.
786 *
787 * Returns: TRUE if the ringbuffer is acquired, FALSE on error.
788 *
789 * MT safe.
790 */
791 gboolean
gst_audio_ring_buffer_is_acquired(GstAudioRingBuffer * buf)792 gst_audio_ring_buffer_is_acquired (GstAudioRingBuffer * buf)
793 {
794 gboolean res;
795
796 g_return_val_if_fail (GST_IS_AUDIO_RING_BUFFER (buf), FALSE);
797
798 GST_OBJECT_LOCK (buf);
799 res = buf->acquired;
800 GST_OBJECT_UNLOCK (buf);
801
802 return res;
803 }
804
805 /**
806 * gst_audio_ring_buffer_activate:
807 * @buf: the #GstAudioRingBuffer to activate
808 * @active: the new mode
809 *
810 * Activate @buf to start or stop pulling data.
811 *
812 * MT safe.
813 *
814 * Returns: TRUE if the device could be activated in the requested mode,
815 * FALSE on error.
816 */
817 gboolean
gst_audio_ring_buffer_activate(GstAudioRingBuffer * buf,gboolean active)818 gst_audio_ring_buffer_activate (GstAudioRingBuffer * buf, gboolean active)
819 {
820 gboolean res = FALSE;
821 GstAudioRingBufferClass *rclass;
822
823 g_return_val_if_fail (GST_IS_AUDIO_RING_BUFFER (buf), FALSE);
824
825 GST_DEBUG_OBJECT (buf, "activate device");
826
827 GST_OBJECT_LOCK (buf);
828 if (G_UNLIKELY (active && !buf->acquired))
829 goto not_acquired;
830
831 if (G_UNLIKELY (buf->active == active))
832 goto was_active;
833
834 rclass = GST_AUDIO_RING_BUFFER_GET_CLASS (buf);
835 /* if there is no activate function we assume it was started/released
836 * in the acquire method */
837 if (G_LIKELY (rclass->activate))
838 res = rclass->activate (buf, active);
839 else
840 res = TRUE;
841
842 if (G_UNLIKELY (!res))
843 goto activate_failed;
844
845 buf->active = active;
846
847 done:
848 GST_OBJECT_UNLOCK (buf);
849
850 return res;
851
852 /* ERRORS */
853 not_acquired:
854 {
855 GST_DEBUG_OBJECT (buf, "device not acquired");
856 g_critical ("Device for %p not acquired", buf);
857 res = FALSE;
858 goto done;
859 }
860 was_active:
861 {
862 res = TRUE;
863 GST_DEBUG_OBJECT (buf, "device was active in mode %d", active);
864 goto done;
865 }
866 activate_failed:
867 {
868 GST_DEBUG_OBJECT (buf, "failed to activate device");
869 goto done;
870 }
871 }
872
873 /**
874 * gst_audio_ring_buffer_is_active:
875 * @buf: the #GstAudioRingBuffer
876 *
877 * Check if @buf is activated.
878 *
879 * MT safe.
880 *
881 * Returns: TRUE if the device is active.
882 */
883 gboolean
gst_audio_ring_buffer_is_active(GstAudioRingBuffer * buf)884 gst_audio_ring_buffer_is_active (GstAudioRingBuffer * buf)
885 {
886 gboolean res;
887
888 g_return_val_if_fail (GST_IS_AUDIO_RING_BUFFER (buf), FALSE);
889
890 GST_OBJECT_LOCK (buf);
891 res = buf->active;
892 GST_OBJECT_UNLOCK (buf);
893
894 return res;
895 }
896
897
898 /**
899 * gst_audio_ring_buffer_set_flushing:
900 * @buf: the #GstAudioRingBuffer to flush
901 * @flushing: the new mode
902 *
903 * Set the ringbuffer to flushing mode or normal mode.
904 *
905 * MT safe.
906 */
907 void
gst_audio_ring_buffer_set_flushing(GstAudioRingBuffer * buf,gboolean flushing)908 gst_audio_ring_buffer_set_flushing (GstAudioRingBuffer * buf, gboolean flushing)
909 {
910 g_return_if_fail (GST_IS_AUDIO_RING_BUFFER (buf));
911
912 GST_OBJECT_LOCK (buf);
913 buf->flushing = flushing;
914
915 if (flushing) {
916 gst_audio_ring_buffer_pause_unlocked (buf);
917 } else {
918 gst_audio_ring_buffer_clear_all (buf);
919 }
920 GST_OBJECT_UNLOCK (buf);
921 }
922
923 /**
924 * gst_audio_ring_buffer_is_flushing:
925 * @buf: the #GstAudioRingBuffer
926 *
927 * Check if @buf is flushing.
928 *
929 * MT safe.
930 *
931 * Returns: TRUE if the device is flushing.
932 */
933 gboolean
gst_audio_ring_buffer_is_flushing(GstAudioRingBuffer * buf)934 gst_audio_ring_buffer_is_flushing (GstAudioRingBuffer * buf)
935 {
936 gboolean res;
937
938 g_return_val_if_fail (GST_IS_AUDIO_RING_BUFFER (buf), TRUE);
939
940 GST_OBJECT_LOCK (buf);
941 res = buf->flushing;
942 GST_OBJECT_UNLOCK (buf);
943
944 return res;
945 }
946
947 /**
948 * gst_audio_ring_buffer_start:
949 * @buf: the #GstAudioRingBuffer to start
950 *
951 * Start processing samples from the ringbuffer.
952 *
953 * Returns: TRUE if the device could be started, FALSE on error.
954 *
955 * MT safe.
956 */
957 gboolean
gst_audio_ring_buffer_start(GstAudioRingBuffer * buf)958 gst_audio_ring_buffer_start (GstAudioRingBuffer * buf)
959 {
960 gboolean res = FALSE;
961 GstAudioRingBufferClass *rclass;
962 gboolean resume = FALSE;
963
964 g_return_val_if_fail (GST_IS_AUDIO_RING_BUFFER (buf), FALSE);
965
966 GST_DEBUG_OBJECT (buf, "starting ringbuffer");
967
968 GST_OBJECT_LOCK (buf);
969 if (G_UNLIKELY (buf->flushing))
970 goto flushing;
971
972 if (G_UNLIKELY (!buf->acquired))
973 goto not_acquired;
974
975 if (G_UNLIKELY (!g_atomic_int_get (&buf->may_start)))
976 goto may_not_start;
977
978 /* if stopped, set to started */
979 res = g_atomic_int_compare_and_exchange (&buf->state,
980 GST_AUDIO_RING_BUFFER_STATE_STOPPED, GST_AUDIO_RING_BUFFER_STATE_STARTED);
981
982 if (!res) {
983 GST_DEBUG_OBJECT (buf, "was not stopped, try paused");
984 /* was not stopped, try from paused */
985 res = g_atomic_int_compare_and_exchange (&buf->state,
986 GST_AUDIO_RING_BUFFER_STATE_PAUSED,
987 GST_AUDIO_RING_BUFFER_STATE_STARTED);
988 if (!res) {
989 /* was not paused either, must be started then */
990 res = TRUE;
991 GST_DEBUG_OBJECT (buf, "was not paused, must have been started");
992 goto done;
993 }
994 resume = TRUE;
995 GST_DEBUG_OBJECT (buf, "resuming");
996 }
997
998 rclass = GST_AUDIO_RING_BUFFER_GET_CLASS (buf);
999 if (resume) {
1000 if (G_LIKELY (rclass->resume))
1001 res = rclass->resume (buf);
1002 } else {
1003 if (G_LIKELY (rclass->start))
1004 res = rclass->start (buf);
1005 }
1006
1007 if (G_UNLIKELY (!res)) {
1008 buf->state = GST_AUDIO_RING_BUFFER_STATE_PAUSED;
1009 GST_DEBUG_OBJECT (buf, "failed to start");
1010 } else {
1011 GST_DEBUG_OBJECT (buf, "started");
1012 }
1013
1014 done:
1015 GST_OBJECT_UNLOCK (buf);
1016
1017 return res;
1018
1019 flushing:
1020 {
1021 GST_DEBUG_OBJECT (buf, "we are flushing");
1022 GST_OBJECT_UNLOCK (buf);
1023 return FALSE;
1024 }
1025 not_acquired:
1026 {
1027 GST_DEBUG_OBJECT (buf, "we are not acquired");
1028 GST_OBJECT_UNLOCK (buf);
1029 return FALSE;
1030 }
1031 may_not_start:
1032 {
1033 GST_DEBUG_OBJECT (buf, "we may not start");
1034 GST_OBJECT_UNLOCK (buf);
1035 return FALSE;
1036 }
1037 }
1038
1039 static gboolean
gst_audio_ring_buffer_pause_unlocked(GstAudioRingBuffer * buf)1040 gst_audio_ring_buffer_pause_unlocked (GstAudioRingBuffer * buf)
1041 {
1042 gboolean res = FALSE;
1043 GstAudioRingBufferClass *rclass;
1044
1045 GST_DEBUG_OBJECT (buf, "pausing ringbuffer");
1046
1047 /* if started, set to paused */
1048 res = g_atomic_int_compare_and_exchange (&buf->state,
1049 GST_AUDIO_RING_BUFFER_STATE_STARTED, GST_AUDIO_RING_BUFFER_STATE_PAUSED);
1050
1051 if (!res)
1052 goto not_started;
1053
1054 /* signal any waiters */
1055 GST_DEBUG_OBJECT (buf, "signal waiter");
1056 GST_AUDIO_RING_BUFFER_SIGNAL (buf);
1057
1058 rclass = GST_AUDIO_RING_BUFFER_GET_CLASS (buf);
1059 if (G_LIKELY (rclass->pause))
1060 res = rclass->pause (buf);
1061
1062 if (G_UNLIKELY (!res)) {
1063 buf->state = GST_AUDIO_RING_BUFFER_STATE_STARTED;
1064 GST_DEBUG_OBJECT (buf, "failed to pause");
1065 } else {
1066 GST_DEBUG_OBJECT (buf, "paused");
1067 }
1068
1069 return res;
1070
1071 not_started:
1072 {
1073 /* was not started */
1074 GST_DEBUG_OBJECT (buf, "was not started");
1075 return TRUE;
1076 }
1077 }
1078
1079 /**
1080 * gst_audio_ring_buffer_pause:
1081 * @buf: the #GstAudioRingBuffer to pause
1082 *
1083 * Pause processing samples from the ringbuffer.
1084 *
1085 * Returns: TRUE if the device could be paused, FALSE on error.
1086 *
1087 * MT safe.
1088 */
1089 gboolean
gst_audio_ring_buffer_pause(GstAudioRingBuffer * buf)1090 gst_audio_ring_buffer_pause (GstAudioRingBuffer * buf)
1091 {
1092 gboolean res = FALSE;
1093
1094 g_return_val_if_fail (GST_IS_AUDIO_RING_BUFFER (buf), FALSE);
1095
1096 GST_OBJECT_LOCK (buf);
1097 if (G_UNLIKELY (buf->flushing))
1098 goto flushing;
1099
1100 if (G_UNLIKELY (!buf->acquired))
1101 goto not_acquired;
1102
1103 res = gst_audio_ring_buffer_pause_unlocked (buf);
1104 GST_OBJECT_UNLOCK (buf);
1105
1106 return res;
1107
1108 /* ERRORS */
1109 flushing:
1110 {
1111 GST_DEBUG_OBJECT (buf, "we are flushing");
1112 GST_OBJECT_UNLOCK (buf);
1113 return FALSE;
1114 }
1115 not_acquired:
1116 {
1117 GST_DEBUG_OBJECT (buf, "not acquired");
1118 GST_OBJECT_UNLOCK (buf);
1119 return FALSE;
1120 }
1121 }
1122
1123 /**
1124 * gst_audio_ring_buffer_stop:
1125 * @buf: the #GstAudioRingBuffer to stop
1126 *
1127 * Stop processing samples from the ringbuffer.
1128 *
1129 * Returns: TRUE if the device could be stopped, FALSE on error.
1130 *
1131 * MT safe.
1132 */
1133 gboolean
gst_audio_ring_buffer_stop(GstAudioRingBuffer * buf)1134 gst_audio_ring_buffer_stop (GstAudioRingBuffer * buf)
1135 {
1136 gboolean res = FALSE;
1137 GstAudioRingBufferClass *rclass;
1138
1139 g_return_val_if_fail (GST_IS_AUDIO_RING_BUFFER (buf), FALSE);
1140
1141 GST_DEBUG_OBJECT (buf, "stopping");
1142
1143 GST_OBJECT_LOCK (buf);
1144
1145 /* if started, set to stopped */
1146 res = g_atomic_int_compare_and_exchange (&buf->state,
1147 GST_AUDIO_RING_BUFFER_STATE_STARTED, GST_AUDIO_RING_BUFFER_STATE_STOPPED);
1148
1149 if (!res) {
1150 GST_DEBUG_OBJECT (buf, "was not started, try paused");
1151 /* was not started, try from paused */
1152 res = g_atomic_int_compare_and_exchange (&buf->state,
1153 GST_AUDIO_RING_BUFFER_STATE_PAUSED,
1154 GST_AUDIO_RING_BUFFER_STATE_STOPPED);
1155 if (!res) {
1156 /* was not paused either, must have been stopped then */
1157 res = TRUE;
1158 GST_DEBUG_OBJECT (buf, "was not paused, must have been stopped");
1159 goto done;
1160 }
1161 }
1162
1163 /* signal any waiters */
1164 GST_DEBUG_OBJECT (buf, "signal waiter");
1165 GST_AUDIO_RING_BUFFER_SIGNAL (buf);
1166
1167 rclass = GST_AUDIO_RING_BUFFER_GET_CLASS (buf);
1168 if (G_LIKELY (rclass->stop))
1169 res = rclass->stop (buf);
1170
1171 if (G_UNLIKELY (!res)) {
1172 buf->state = GST_AUDIO_RING_BUFFER_STATE_STARTED;
1173 GST_DEBUG_OBJECT (buf, "failed to stop");
1174 } else {
1175 GST_DEBUG_OBJECT (buf, "stopped");
1176 }
1177 done:
1178 GST_OBJECT_UNLOCK (buf);
1179
1180 return res;
1181 }
1182
1183 /**
1184 * gst_audio_ring_buffer_delay:
1185 * @buf: the #GstAudioRingBuffer to query
1186 *
1187 * Get the number of samples queued in the audio device. This is
1188 * usually less than the segment size but can be bigger when the
1189 * implementation uses another internal buffer between the audio
1190 * device.
1191 *
1192 * For playback ringbuffers this is the amount of samples transfered from the
1193 * ringbuffer to the device but still not played.
1194 *
1195 * For capture ringbuffers this is the amount of samples in the device that are
1196 * not yet transfered to the ringbuffer.
1197 *
1198 * Returns: The number of samples queued in the audio device.
1199 *
1200 * MT safe.
1201 */
1202 guint
gst_audio_ring_buffer_delay(GstAudioRingBuffer * buf)1203 gst_audio_ring_buffer_delay (GstAudioRingBuffer * buf)
1204 {
1205 GstAudioRingBufferClass *rclass;
1206 guint res;
1207
1208 g_return_val_if_fail (GST_IS_AUDIO_RING_BUFFER (buf), 0);
1209
1210 /* buffer must be acquired */
1211 if (G_UNLIKELY (!gst_audio_ring_buffer_is_acquired (buf)))
1212 goto not_acquired;
1213
1214 rclass = GST_AUDIO_RING_BUFFER_GET_CLASS (buf);
1215 if (G_LIKELY (rclass->delay))
1216 res = rclass->delay (buf);
1217 else
1218 res = 0;
1219
1220 return res;
1221
1222 not_acquired:
1223 {
1224 GST_DEBUG_OBJECT (buf, "not acquired");
1225 return 0;
1226 }
1227 }
1228
1229 /**
1230 * gst_audio_ring_buffer_samples_done:
1231 * @buf: the #GstAudioRingBuffer to query
1232 *
1233 * Get the number of samples that were processed by the ringbuffer
1234 * since it was last started. This does not include the number of samples not
1235 * yet processed (see gst_audio_ring_buffer_delay()).
1236 *
1237 * Returns: The number of samples processed by the ringbuffer.
1238 *
1239 * MT safe.
1240 */
1241 guint64
gst_audio_ring_buffer_samples_done(GstAudioRingBuffer * buf)1242 gst_audio_ring_buffer_samples_done (GstAudioRingBuffer * buf)
1243 {
1244 gint segdone;
1245 guint64 samples;
1246
1247 g_return_val_if_fail (GST_IS_AUDIO_RING_BUFFER (buf), 0);
1248
1249 /* get the amount of segments we processed */
1250 segdone = g_atomic_int_get (&buf->segdone);
1251
1252 /* convert to samples */
1253 samples = ((guint64) segdone) * buf->samples_per_seg;
1254
1255 return samples;
1256 }
1257
1258 /**
1259 * gst_audio_ring_buffer_set_sample:
1260 * @buf: the #GstAudioRingBuffer to use
1261 * @sample: the sample number to set
1262 *
1263 * Make sure that the next sample written to the device is
1264 * accounted for as being the @sample sample written to the
1265 * device. This value will be used in reporting the current
1266 * sample position of the ringbuffer.
1267 *
1268 * This function will also clear the buffer with silence.
1269 *
1270 * MT safe.
1271 */
1272 void
gst_audio_ring_buffer_set_sample(GstAudioRingBuffer * buf,guint64 sample)1273 gst_audio_ring_buffer_set_sample (GstAudioRingBuffer * buf, guint64 sample)
1274 {
1275 g_return_if_fail (GST_IS_AUDIO_RING_BUFFER (buf));
1276
1277 if (sample == -1)
1278 sample = 0;
1279
1280 if (G_UNLIKELY (buf->samples_per_seg == 0))
1281 return;
1282
1283 /* FIXME, we assume the ringbuffer can restart at a random
1284 * position, round down to the beginning and keep track of
1285 * offset when calculating the processed samples. */
1286 buf->segbase = buf->segdone - sample / buf->samples_per_seg;
1287
1288 gst_audio_ring_buffer_clear_all (buf);
1289
1290 GST_DEBUG_OBJECT (buf, "set sample to %" G_GUINT64_FORMAT ", segbase %d",
1291 sample, buf->segbase);
1292 }
1293
1294 static void
default_clear_all(GstAudioRingBuffer * buf)1295 default_clear_all (GstAudioRingBuffer * buf)
1296 {
1297 gint i;
1298
1299 /* not fatal, we just are not negotiated yet */
1300 if (G_UNLIKELY (buf->spec.segtotal <= 0))
1301 return;
1302
1303 GST_DEBUG_OBJECT (buf, "clear all segments");
1304
1305 for (i = 0; i < buf->spec.segtotal; i++) {
1306 gst_audio_ring_buffer_clear (buf, i);
1307 }
1308 }
1309
1310 /**
1311 * gst_audio_ring_buffer_clear_all:
1312 * @buf: the #GstAudioRingBuffer to clear
1313 *
1314 * Fill the ringbuffer with silence.
1315 *
1316 * MT safe.
1317 */
1318 void
gst_audio_ring_buffer_clear_all(GstAudioRingBuffer * buf)1319 gst_audio_ring_buffer_clear_all (GstAudioRingBuffer * buf)
1320 {
1321 GstAudioRingBufferClass *rclass;
1322
1323 g_return_if_fail (GST_IS_AUDIO_RING_BUFFER (buf));
1324
1325 rclass = GST_AUDIO_RING_BUFFER_GET_CLASS (buf);
1326
1327 if (G_LIKELY (rclass->clear_all))
1328 rclass->clear_all (buf);
1329 }
1330
1331
1332 static gboolean
wait_segment(GstAudioRingBuffer * buf)1333 wait_segment (GstAudioRingBuffer * buf)
1334 {
1335 gint segments;
1336 gboolean wait = TRUE;
1337
1338 /* buffer must be started now or we deadlock since nobody is reading */
1339 if (G_UNLIKELY (g_atomic_int_get (&buf->state) !=
1340 GST_AUDIO_RING_BUFFER_STATE_STARTED)) {
1341 /* see if we are allowed to start it */
1342 if (G_UNLIKELY (!g_atomic_int_get (&buf->may_start)))
1343 goto no_start;
1344
1345 GST_DEBUG_OBJECT (buf, "start!");
1346 segments = g_atomic_int_get (&buf->segdone);
1347 gst_audio_ring_buffer_start (buf);
1348
1349 /* After starting, the writer may have wrote segments already and then we
1350 * don't need to wait anymore */
1351 if (G_LIKELY (g_atomic_int_get (&buf->segdone) != segments))
1352 wait = FALSE;
1353 }
1354
1355 /* take lock first, then update our waiting flag */
1356 GST_OBJECT_LOCK (buf);
1357 if (G_UNLIKELY (buf->flushing))
1358 goto flushing;
1359
1360 if (G_UNLIKELY (g_atomic_int_get (&buf->state) !=
1361 GST_AUDIO_RING_BUFFER_STATE_STARTED))
1362 goto not_started;
1363
1364 if (G_LIKELY (wait)) {
1365 if (g_atomic_int_compare_and_exchange (&buf->waiting, 0, 1)) {
1366 GST_DEBUG_OBJECT (buf, "waiting..");
1367 GST_AUDIO_RING_BUFFER_WAIT (buf);
1368
1369 if (G_UNLIKELY (buf->flushing))
1370 goto flushing;
1371
1372 if (G_UNLIKELY (g_atomic_int_get (&buf->state) !=
1373 GST_AUDIO_RING_BUFFER_STATE_STARTED))
1374 goto not_started;
1375 }
1376 }
1377 GST_OBJECT_UNLOCK (buf);
1378
1379 return TRUE;
1380
1381 /* ERROR */
1382 not_started:
1383 {
1384 g_atomic_int_compare_and_exchange (&buf->waiting, 1, 0);
1385 GST_DEBUG_OBJECT (buf, "stopped processing");
1386 GST_OBJECT_UNLOCK (buf);
1387 return FALSE;
1388 }
1389 flushing:
1390 {
1391 g_atomic_int_compare_and_exchange (&buf->waiting, 1, 0);
1392 GST_DEBUG_OBJECT (buf, "flushing");
1393 GST_OBJECT_UNLOCK (buf);
1394 return FALSE;
1395 }
1396 no_start:
1397 {
1398 GST_DEBUG_OBJECT (buf, "not allowed to start");
1399 return FALSE;
1400 }
1401 }
1402
1403
1404
1405 #define REORDER_SAMPLE(d, s, l) \
1406 G_STMT_START { \
1407 gint i; \
1408 for (i = 0; i < channels; i++) { \
1409 memcpy (d + reorder_map[i] * bps, s + i * bps, bps); \
1410 } \
1411 } G_STMT_END
1412
1413 #define REORDER_SAMPLES(d, s, len) \
1414 G_STMT_START { \
1415 gint i, len_ = len / bpf; \
1416 guint8 *d_ = d, *s_ = s; \
1417 for (i = 0; i < len_; i++) { \
1418 REORDER_SAMPLE(d_, s_, bpf); \
1419 d_ += bpf; \
1420 s_ += bpf; \
1421 } \
1422 } G_STMT_END
1423
1424 #define FWD_SAMPLES(s,se,d,de,F) \
1425 G_STMT_START { \
1426 /* no rate conversion */ \
1427 guint towrite = MIN (se + bpf - s, de - d); \
1428 /* simple copy */ \
1429 if (!skip) \
1430 F (d, s, towrite); \
1431 in_samples -= towrite / bpf; \
1432 out_samples -= towrite / bpf; \
1433 s += towrite; \
1434 GST_DEBUG ("copy %u bytes", towrite); \
1435 } G_STMT_END
1436
1437 /* in_samples >= out_samples, rate > 1.0 */
1438 #define FWD_UP_SAMPLES(s,se,d,de,F) \
1439 G_STMT_START { \
1440 guint8 *sb = s, *db = d; \
1441 while (s <= se && d < de) { \
1442 if (!skip) \
1443 F (d, s, bpf); \
1444 s += bpf; \
1445 *accum += outr; \
1446 if ((*accum << 1) >= inr) { \
1447 *accum -= inr; \
1448 d += bpf; \
1449 } \
1450 } \
1451 in_samples -= (s - sb)/bpf; \
1452 out_samples -= (d - db)/bpf; \
1453 GST_DEBUG ("fwd_up end %d/%d",*accum,*toprocess); \
1454 } G_STMT_END
1455
1456 /* out_samples > in_samples, for rates smaller than 1.0 */
1457 #define FWD_DOWN_SAMPLES(s,se,d,de,F) \
1458 G_STMT_START { \
1459 guint8 *sb = s, *db = d; \
1460 while (s <= se && d < de) { \
1461 if (!skip) \
1462 F (d, s, bpf); \
1463 d += bpf; \
1464 *accum += inr; \
1465 if ((*accum << 1) >= outr) { \
1466 *accum -= outr; \
1467 s += bpf; \
1468 } \
1469 } \
1470 in_samples -= (s - sb)/bpf; \
1471 out_samples -= (d - db)/bpf; \
1472 GST_DEBUG ("fwd_down end %d/%d",*accum,*toprocess); \
1473 } G_STMT_END
1474
1475 #define REV_UP_SAMPLES(s,se,d,de,F) \
1476 G_STMT_START { \
1477 guint8 *sb = se, *db = d; \
1478 while (s <= se && d < de) { \
1479 if (!skip) \
1480 F (d, se, bpf); \
1481 se -= bpf; \
1482 *accum += outr; \
1483 while (d < de && (*accum << 1) >= inr) { \
1484 *accum -= inr; \
1485 d += bpf; \
1486 } \
1487 } \
1488 in_samples -= (sb - se)/bpf; \
1489 out_samples -= (d - db)/bpf; \
1490 GST_DEBUG ("rev_up end %d/%d",*accum,*toprocess); \
1491 } G_STMT_END
1492
1493 #define REV_DOWN_SAMPLES(s,se,d,de,F) \
1494 G_STMT_START { \
1495 guint8 *sb = se, *db = d; \
1496 while (s <= se && d < de) { \
1497 if (!skip) \
1498 F (d, se, bpf); \
1499 d += bpf; \
1500 *accum += inr; \
1501 while (s <= se && (*accum << 1) >= outr) { \
1502 *accum -= outr; \
1503 se -= bpf; \
1504 } \
1505 } \
1506 in_samples -= (sb - se)/bpf; \
1507 out_samples -= (d - db)/bpf; \
1508 GST_DEBUG ("rev_down end %d/%d",*accum,*toprocess); \
1509 } G_STMT_END
1510
1511 static guint
default_commit(GstAudioRingBuffer * buf,guint64 * sample,guint8 * data,gint in_samples,gint out_samples,gint * accum)1512 default_commit (GstAudioRingBuffer * buf, guint64 * sample,
1513 guint8 * data, gint in_samples, gint out_samples, gint * accum)
1514 {
1515 gint segdone;
1516 gint segsize, segtotal, channels, bps, bpf, sps;
1517 guint8 *dest, *data_end;
1518 gint writeseg, sampleoff;
1519 gint *toprocess;
1520 gint inr, outr;
1521 gboolean reverse;
1522 gboolean need_reorder;
1523
1524 g_return_val_if_fail (buf->memory != NULL, -1);
1525 g_return_val_if_fail (data != NULL, -1);
1526
1527 need_reorder = buf->need_reorder;
1528
1529 channels = buf->spec.info.channels;
1530 dest = buf->memory;
1531 segsize = buf->spec.segsize;
1532 segtotal = buf->spec.segtotal;
1533 bpf = buf->spec.info.bpf;
1534 bps = bpf / channels;
1535 sps = buf->samples_per_seg;
1536
1537 reverse = out_samples < 0;
1538 out_samples = ABS (out_samples);
1539
1540 if (in_samples >= out_samples)
1541 toprocess = &in_samples;
1542 else
1543 toprocess = &out_samples;
1544
1545 inr = in_samples - 1;
1546 outr = out_samples - 1;
1547
1548 /* data_end points to the last sample we have to write, not past it. This is
1549 * needed to properly handle reverse playback: it points to the last sample. */
1550 data_end = data + (bpf * inr);
1551
1552 /* figure out the segment and the offset inside the segment where
1553 * the first sample should be written. */
1554 writeseg = *sample / sps;
1555 sampleoff = (*sample % sps) * bpf;
1556
1557 GST_DEBUG_OBJECT (buf, "write %d : %d", in_samples, out_samples);
1558
1559 /* write out all samples */
1560 while (*toprocess > 0) {
1561 gint avail;
1562 guint8 *d, *d_end;
1563 gint ws;
1564 gboolean skip;
1565
1566 while (TRUE) {
1567 gint diff;
1568
1569 /* get the currently processed segment */
1570 segdone = g_atomic_int_get (&buf->segdone) - buf->segbase;
1571
1572 /* see how far away it is from the write segment */
1573 diff = writeseg - segdone;
1574
1575 GST_DEBUG_OBJECT (buf,
1576 "pointer at %d, write to %d-%d, diff %d, segtotal %d, segsize %d, base %d",
1577 segdone, writeseg, sampleoff, diff, segtotal, segsize, buf->segbase);
1578
1579 /* segment too far ahead, writer too slow, we need to drop, hopefully UNLIKELY */
1580 if (G_UNLIKELY (diff < 0)) {
1581 /* we need to drop one segment at a time, pretend we wrote a segment. */
1582 skip = TRUE;
1583 break;
1584 }
1585
1586 /* write segment is within writable range, we can break the loop and
1587 * start writing the data. */
1588 if (diff < segtotal) {
1589 skip = FALSE;
1590 break;
1591 }
1592
1593 /* else we need to wait for the segment to become writable. */
1594 if (!wait_segment (buf))
1595 goto not_started;
1596 }
1597
1598 /* we can write now */
1599 ws = writeseg % segtotal;
1600 avail = MIN (segsize - sampleoff, bpf * out_samples);
1601
1602 d = dest + (ws * segsize) + sampleoff;
1603 d_end = d + avail;
1604 *sample += avail / bpf;
1605
1606 GST_DEBUG_OBJECT (buf, "write @%p seg %d, sps %d, off %d, avail %d",
1607 dest + ws * segsize, ws, sps, sampleoff, avail);
1608
1609 if (need_reorder) {
1610 gint *reorder_map = buf->channel_reorder_map;
1611
1612 if (G_LIKELY (inr == outr && !reverse)) {
1613 /* no rate conversion, simply copy samples */
1614 FWD_SAMPLES (data, data_end, d, d_end, REORDER_SAMPLES);
1615 } else if (!reverse) {
1616 if (inr >= outr)
1617 /* forward speed up */
1618 FWD_UP_SAMPLES (data, data_end, d, d_end, REORDER_SAMPLE);
1619 else
1620 /* forward slow down */
1621 FWD_DOWN_SAMPLES (data, data_end, d, d_end, REORDER_SAMPLE);
1622 } else {
1623 if (inr >= outr)
1624 /* reverse speed up */
1625 REV_UP_SAMPLES (data, data_end, d, d_end, REORDER_SAMPLE);
1626 else
1627 /* reverse slow down */
1628 REV_DOWN_SAMPLES (data, data_end, d, d_end, REORDER_SAMPLE);
1629 }
1630 } else {
1631 if (G_LIKELY (inr == outr && !reverse)) {
1632 /* no rate conversion, simply copy samples */
1633 FWD_SAMPLES (data, data_end, d, d_end, memcpy);
1634 } else if (!reverse) {
1635 if (inr >= outr)
1636 /* forward speed up */
1637 FWD_UP_SAMPLES (data, data_end, d, d_end, memcpy);
1638 else
1639 /* forward slow down */
1640 FWD_DOWN_SAMPLES (data, data_end, d, d_end, memcpy);
1641 } else {
1642 if (inr >= outr)
1643 /* reverse speed up */
1644 REV_UP_SAMPLES (data, data_end, d, d_end, memcpy);
1645 else
1646 /* reverse slow down */
1647 REV_DOWN_SAMPLES (data, data_end, d, d_end, memcpy);
1648 }
1649 }
1650
1651 /* for the next iteration we write to the next segment at the beginning. */
1652 writeseg++;
1653 sampleoff = 0;
1654 }
1655 /* we consumed all samples here */
1656 data = data_end + bpf;
1657
1658 done:
1659 return inr - ((data_end - data) / bpf);
1660
1661 /* ERRORS */
1662 not_started:
1663 {
1664 GST_DEBUG_OBJECT (buf, "stopped processing");
1665 goto done;
1666 }
1667 }
1668
1669 /**
1670 * gst_audio_ring_buffer_commit:
1671 * @buf: the #GstAudioRingBuffer to commit
1672 * @sample: the sample position of the data
1673 * @data: (array length=in_samples): the data to commit
1674 * @in_samples: the number of samples in the data to commit
1675 * @out_samples: the number of samples to write to the ringbuffer
1676 * @accum: (inout): accumulator for rate conversion.
1677 *
1678 * Commit @in_samples samples pointed to by @data to the ringbuffer @buf.
1679 *
1680 * @in_samples and @out_samples define the rate conversion to perform on the
1681 * samples in @data. For negative rates, @out_samples must be negative and
1682 * @in_samples positive.
1683 *
1684 * When @out_samples is positive, the first sample will be written at position @sample
1685 * in the ringbuffer. When @out_samples is negative, the last sample will be written to
1686 * @sample in reverse order.
1687 *
1688 * @out_samples does not need to be a multiple of the segment size of the ringbuffer
1689 * although it is recommended for optimal performance.
1690 *
1691 * @accum will hold a temporary accumulator used in rate conversion and should be
1692 * set to 0 when this function is first called. In case the commit operation is
1693 * interrupted, one can resume the processing by passing the previously returned
1694 * @accum value back to this function.
1695 *
1696 * MT safe.
1697 *
1698 * Returns: The number of samples written to the ringbuffer or -1 on error. The
1699 * number of samples written can be less than @out_samples when @buf was interrupted
1700 * with a flush or stop.
1701 */
1702 guint
gst_audio_ring_buffer_commit(GstAudioRingBuffer * buf,guint64 * sample,guint8 * data,gint in_samples,gint out_samples,gint * accum)1703 gst_audio_ring_buffer_commit (GstAudioRingBuffer * buf, guint64 * sample,
1704 guint8 * data, gint in_samples, gint out_samples, gint * accum)
1705 {
1706 GstAudioRingBufferClass *rclass;
1707 guint res = -1;
1708
1709 g_return_val_if_fail (GST_IS_AUDIO_RING_BUFFER (buf), -1);
1710
1711 if (G_UNLIKELY (in_samples == 0 || out_samples == 0))
1712 return in_samples;
1713
1714 rclass = GST_AUDIO_RING_BUFFER_GET_CLASS (buf);
1715
1716 if (G_LIKELY (rclass->commit))
1717 res = rclass->commit (buf, sample, data, in_samples, out_samples, accum);
1718
1719 return res;
1720 }
1721
1722 /**
1723 * gst_audio_ring_buffer_read:
1724 * @buf: the #GstAudioRingBuffer to read from
1725 * @sample: the sample position of the data
1726 * @data: (array length=len): where the data should be read
1727 * @len: the number of samples in data to read
1728 * @timestamp: (out): where the timestamp is returned
1729 *
1730 * Read @len samples from the ringbuffer into the memory pointed
1731 * to by @data.
1732 * The first sample should be read from position @sample in
1733 * the ringbuffer.
1734 *
1735 * @len should not be a multiple of the segment size of the ringbuffer
1736 * although it is recommended.
1737 *
1738 * @timestamp will return the timestamp associated with the data returned.
1739 *
1740 * Returns: The number of samples read from the ringbuffer or -1 on
1741 * error.
1742 *
1743 * MT safe.
1744 */
1745 guint
gst_audio_ring_buffer_read(GstAudioRingBuffer * buf,guint64 sample,guint8 * data,guint len,GstClockTime * timestamp)1746 gst_audio_ring_buffer_read (GstAudioRingBuffer * buf, guint64 sample,
1747 guint8 * data, guint len, GstClockTime * timestamp)
1748 {
1749 gint segdone;
1750 gint segsize, segtotal, channels, bps, bpf, sps, readseg = 0;
1751 guint8 *dest;
1752 guint to_read;
1753 gboolean need_reorder;
1754
1755 g_return_val_if_fail (GST_IS_AUDIO_RING_BUFFER (buf), -1);
1756 g_return_val_if_fail (buf->memory != NULL, -1);
1757 g_return_val_if_fail (data != NULL, -1);
1758
1759 need_reorder = buf->need_reorder;
1760 dest = buf->memory;
1761 segsize = buf->spec.segsize;
1762 segtotal = buf->spec.segtotal;
1763 channels = buf->spec.info.channels;
1764 bpf = buf->spec.info.bpf;
1765 bps = bpf / channels;
1766 sps = buf->samples_per_seg;
1767
1768 to_read = len;
1769 /* read enough samples */
1770 while (to_read > 0) {
1771 gint sampleslen;
1772 gint sampleoff;
1773
1774 /* figure out the segment and the offset inside the segment where
1775 * the sample should be read from. */
1776 readseg = sample / sps;
1777 sampleoff = (sample % sps);
1778
1779 while (TRUE) {
1780 gint diff;
1781
1782 /* get the currently processed segment */
1783 segdone = g_atomic_int_get (&buf->segdone) - buf->segbase;
1784
1785 /* see how far away it is from the read segment, normally segdone (where
1786 * the hardware is writing) is bigger than readseg (where software is
1787 * reading) */
1788 diff = segdone - readseg;
1789
1790 GST_DEBUG_OBJECT
1791 (buf, "pointer at %d, sample %" G_GUINT64_FORMAT
1792 ", read from %d-%d, to_read %d, diff %d, segtotal %d, segsize %d",
1793 segdone, sample, readseg, sampleoff, to_read, diff, segtotal,
1794 segsize);
1795
1796 /* segment too far ahead, reader too slow */
1797 if (G_UNLIKELY (diff >= segtotal)) {
1798 /* pretend we read an empty segment. */
1799 sampleslen = MIN (sps, to_read);
1800 memcpy (data, buf->empty_seg, sampleslen * bpf);
1801 goto next;
1802 }
1803
1804 /* read segment is within readable range, we can break the loop and
1805 * start reading the data. */
1806 if (diff > 0)
1807 break;
1808
1809 /* else we need to wait for the segment to become readable. */
1810 if (!wait_segment (buf))
1811 goto not_started;
1812 }
1813
1814 /* we can read now */
1815 readseg = readseg % segtotal;
1816 sampleslen = MIN (sps - sampleoff, to_read);
1817
1818 GST_DEBUG_OBJECT (buf, "read @%p seg %d, off %d, sampleslen %d",
1819 dest + readseg * segsize, readseg, sampleoff, sampleslen);
1820
1821 if (need_reorder) {
1822 guint8 *ptr = dest + (readseg * segsize) + (sampleoff * bpf);
1823 gint i, j;
1824 gint *reorder_map = buf->channel_reorder_map;
1825
1826 /* Reorder from device order to GStreamer order */
1827 for (i = 0; i < sampleslen; i++) {
1828 for (j = 0; j < channels; j++) {
1829 memcpy (data + i * bpf + reorder_map[j] * bps, ptr + j * bps, bps);
1830 }
1831 ptr += bpf;
1832 }
1833 } else {
1834 memcpy (data, dest + (readseg * segsize) + (sampleoff * bpf),
1835 (sampleslen * bpf));
1836 }
1837
1838 next:
1839 to_read -= sampleslen;
1840 sample += sampleslen;
1841 data += sampleslen * bpf;
1842 }
1843
1844 if (buf->timestamps && timestamp) {
1845 *timestamp = buf->timestamps[readseg % segtotal];
1846 GST_DEBUG_OBJECT (buf, "Retrieved timestamp %" GST_TIME_FORMAT
1847 " @ %d", GST_TIME_ARGS (*timestamp), readseg % segtotal);
1848 }
1849
1850 return len - to_read;
1851
1852 /* ERRORS */
1853 not_started:
1854 {
1855 GST_DEBUG_OBJECT (buf, "stopped processing");
1856 return len - to_read;
1857 }
1858 }
1859
1860 /**
1861 * gst_audio_ring_buffer_prepare_read:
1862 * @buf: the #GstAudioRingBuffer to read from
1863 * @segment: (out): the segment to read
1864 * @readptr: (out) (array length=len):
1865 * the pointer to the memory where samples can be read
1866 * @len: (out): the number of bytes to read
1867 *
1868 * Returns a pointer to memory where the data from segment @segment
1869 * can be found. This function is mostly used by subclasses.
1870 *
1871 * Returns: FALSE if the buffer is not started.
1872 *
1873 * MT safe.
1874 */
1875 gboolean
gst_audio_ring_buffer_prepare_read(GstAudioRingBuffer * buf,gint * segment,guint8 ** readptr,gint * len)1876 gst_audio_ring_buffer_prepare_read (GstAudioRingBuffer * buf, gint * segment,
1877 guint8 ** readptr, gint * len)
1878 {
1879 guint8 *data;
1880 gint segdone;
1881
1882 g_return_val_if_fail (GST_IS_AUDIO_RING_BUFFER (buf), FALSE);
1883
1884 if (buf->callback == NULL) {
1885 /* push mode, fail when nothing is started */
1886 if (g_atomic_int_get (&buf->state) != GST_AUDIO_RING_BUFFER_STATE_STARTED)
1887 return FALSE;
1888 }
1889
1890 g_return_val_if_fail (buf->memory != NULL, FALSE);
1891 g_return_val_if_fail (segment != NULL, FALSE);
1892 g_return_val_if_fail (readptr != NULL, FALSE);
1893 g_return_val_if_fail (len != NULL, FALSE);
1894
1895 data = buf->memory;
1896
1897 /* get the position of the pointer */
1898 segdone = g_atomic_int_get (&buf->segdone);
1899
1900 *segment = segdone % buf->spec.segtotal;
1901 *len = buf->spec.segsize;
1902 *readptr = data + *segment * *len;
1903
1904 GST_LOG_OBJECT (buf, "prepare read from segment %d (real %d) @%p",
1905 *segment, segdone, *readptr);
1906
1907 /* callback to fill the memory with data, for pull based
1908 * scheduling. */
1909 if (buf->callback)
1910 buf->callback (buf, *readptr, *len, buf->cb_data);
1911
1912 return TRUE;
1913 }
1914
1915 /**
1916 * gst_audio_ring_buffer_advance:
1917 * @buf: the #GstAudioRingBuffer to advance
1918 * @advance: the number of segments written
1919 *
1920 * Subclasses should call this function to notify the fact that
1921 * @advance segments are now processed by the device.
1922 *
1923 * MT safe.
1924 */
1925 void
gst_audio_ring_buffer_advance(GstAudioRingBuffer * buf,guint advance)1926 gst_audio_ring_buffer_advance (GstAudioRingBuffer * buf, guint advance)
1927 {
1928 g_return_if_fail (GST_IS_AUDIO_RING_BUFFER (buf));
1929
1930 /* update counter */
1931 g_atomic_int_add (&buf->segdone, advance);
1932
1933 /* the lock is already taken when the waiting flag is set,
1934 * we grab the lock as well to make sure the waiter is actually
1935 * waiting for the signal */
1936 if (g_atomic_int_compare_and_exchange (&buf->waiting, 1, 0)) {
1937 GST_OBJECT_LOCK (buf);
1938 GST_DEBUG_OBJECT (buf, "signal waiter");
1939 GST_AUDIO_RING_BUFFER_SIGNAL (buf);
1940 GST_OBJECT_UNLOCK (buf);
1941 }
1942 }
1943
1944 /**
1945 * gst_audio_ring_buffer_clear:
1946 * @buf: the #GstAudioRingBuffer to clear
1947 * @segment: the segment to clear
1948 *
1949 * Clear the given segment of the buffer with silence samples.
1950 * This function is used by subclasses.
1951 *
1952 * MT safe.
1953 */
1954 void
gst_audio_ring_buffer_clear(GstAudioRingBuffer * buf,gint segment)1955 gst_audio_ring_buffer_clear (GstAudioRingBuffer * buf, gint segment)
1956 {
1957 guint8 *data;
1958
1959 g_return_if_fail (GST_IS_AUDIO_RING_BUFFER (buf));
1960
1961 /* no data means it's already cleared */
1962 if (G_UNLIKELY (buf->memory == NULL))
1963 return;
1964
1965 /* no empty_seg means it's not opened */
1966 if (G_UNLIKELY (buf->empty_seg == NULL))
1967 return;
1968
1969 segment %= buf->spec.segtotal;
1970
1971 data = buf->memory;
1972 data += segment * buf->spec.segsize;
1973
1974 GST_LOG_OBJECT (buf, "clear segment %d @%p", segment, data);
1975
1976 memcpy (data, buf->empty_seg, buf->spec.segsize);
1977 }
1978
1979 /**
1980 * gst_audio_ring_buffer_may_start:
1981 * @buf: the #GstAudioRingBuffer
1982 * @allowed: the new value
1983 *
1984 * Tell the ringbuffer that it is allowed to start playback when
1985 * the ringbuffer is filled with samples.
1986 *
1987 * MT safe.
1988 */
1989 void
gst_audio_ring_buffer_may_start(GstAudioRingBuffer * buf,gboolean allowed)1990 gst_audio_ring_buffer_may_start (GstAudioRingBuffer * buf, gboolean allowed)
1991 {
1992 g_return_if_fail (GST_IS_AUDIO_RING_BUFFER (buf));
1993
1994 GST_LOG_OBJECT (buf, "may start: %d", allowed);
1995 g_atomic_int_set (&buf->may_start, allowed);
1996 }
1997
1998 /* GST_AUDIO_CHANNEL_POSITION_NONE is used for position-less
1999 * mutually exclusive channels. In this case we should not attempt
2000 * to do any reordering.
2001 */
2002 static gboolean
position_less_channels(const GstAudioChannelPosition * pos,guint channels)2003 position_less_channels (const GstAudioChannelPosition * pos, guint channels)
2004 {
2005 guint i;
2006
2007 for (i = 0; i < channels; i++) {
2008 if (pos[i] != GST_AUDIO_CHANNEL_POSITION_NONE)
2009 return FALSE;
2010 }
2011
2012 return TRUE;
2013 }
2014
2015 /**
2016 * gst_audio_ring_buffer_set_channel_positions:
2017 * @buf: the #GstAudioRingBuffer
2018 * @position: (array): the device channel positions
2019 *
2020 * Tell the ringbuffer about the device's channel positions. This must
2021 * be called in when the ringbuffer is acquired.
2022 */
2023 void
gst_audio_ring_buffer_set_channel_positions(GstAudioRingBuffer * buf,const GstAudioChannelPosition * position)2024 gst_audio_ring_buffer_set_channel_positions (GstAudioRingBuffer * buf,
2025 const GstAudioChannelPosition * position)
2026 {
2027 const GstAudioChannelPosition *to;
2028 gint channels;
2029 gint i;
2030
2031 g_return_if_fail (GST_IS_AUDIO_RING_BUFFER (buf));
2032 g_return_if_fail (buf->acquired);
2033
2034 channels = buf->spec.info.channels;
2035 to = buf->spec.info.position;
2036
2037 buf->need_reorder = FALSE;
2038 if (memcmp (position, to, channels * sizeof (to[0])) == 0)
2039 return;
2040
2041 if (position_less_channels (position, channels)) {
2042 GST_LOG_OBJECT (buf, "position-less channels, no need to reorder");
2043 return;
2044 }
2045
2046 if (!gst_audio_get_channel_reorder_map (channels, position, to,
2047 buf->channel_reorder_map))
2048 g_return_if_reached ();
2049
2050 for (i = 0; i < channels; i++) {
2051 if (buf->channel_reorder_map[i] != i) {
2052 #ifndef GST_DISABLE_GST_DEBUG
2053 {
2054 gchar *tmp1, *tmp2;
2055
2056 tmp1 = gst_audio_channel_positions_to_string (position, channels);
2057 tmp2 = gst_audio_channel_positions_to_string (to, channels);
2058 GST_LOG_OBJECT (buf, "may have to reorder channels: %s -> %s", tmp1,
2059 tmp2);
2060 g_free (tmp1);
2061 g_free (tmp2);
2062 }
2063 #endif /* GST_DISABLE_GST_DEBUG */
2064
2065 buf->need_reorder = TRUE;
2066 break;
2067 }
2068 }
2069 }
2070
2071 /**
2072 * gst_ring_buffer_set_timestamp:
2073 * @buf: the #GstRingBuffer
2074 * @readseg: the current data segment
2075 * @timestamp: The new timestamp of the buffer.
2076 *
2077 * Set a new timestamp on the buffer.
2078 *
2079 * MT safe.
2080 */
2081 void
gst_audio_ring_buffer_set_timestamp(GstAudioRingBuffer * buf,gint readseg,GstClockTime timestamp)2082 gst_audio_ring_buffer_set_timestamp (GstAudioRingBuffer * buf, gint readseg,
2083 GstClockTime timestamp)
2084 {
2085 g_return_if_fail (GST_IS_AUDIO_RING_BUFFER (buf));
2086
2087 GST_DEBUG_OBJECT (buf, "Storing timestamp %" GST_TIME_FORMAT
2088 " @ %d", GST_TIME_ARGS (timestamp), readseg);
2089
2090 GST_OBJECT_LOCK (buf);
2091 if (G_UNLIKELY (!buf->acquired))
2092 goto not_acquired;
2093
2094 buf->timestamps[readseg] = timestamp;
2095
2096 done:
2097 GST_OBJECT_UNLOCK (buf);
2098 return;
2099
2100 not_acquired:
2101 {
2102 GST_DEBUG_OBJECT (buf, "we are not acquired");
2103 goto done;
2104 }
2105 }
2106