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_info_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 transferred 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 transferred 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 /**
1295 * default_clear_all:
1296 * @buf: the #GstAudioRingBuffer to clear
1297 *
1298 * Fill the ringbuffer with silence.
1299 */
1300 static void
default_clear_all(GstAudioRingBuffer * buf)1301 default_clear_all (GstAudioRingBuffer * buf)
1302 {
1303 gint i;
1304
1305 /* not fatal, we just are not negotiated yet */
1306 if (G_UNLIKELY (buf->spec.segtotal <= 0))
1307 return;
1308
1309 GST_DEBUG_OBJECT (buf, "clear all segments");
1310
1311 for (i = 0; i < buf->spec.segtotal; i++) {
1312 gst_audio_ring_buffer_clear (buf, i);
1313 }
1314 }
1315
1316 /**
1317 * gst_audio_ring_buffer_clear_all:
1318 * @buf: the #GstAudioRingBuffer to clear
1319 *
1320 * Clear all samples from the ringbuffer.
1321 *
1322 * MT safe.
1323 */
1324 void
gst_audio_ring_buffer_clear_all(GstAudioRingBuffer * buf)1325 gst_audio_ring_buffer_clear_all (GstAudioRingBuffer * buf)
1326 {
1327 GstAudioRingBufferClass *rclass;
1328
1329 g_return_if_fail (GST_IS_AUDIO_RING_BUFFER (buf));
1330
1331 rclass = GST_AUDIO_RING_BUFFER_GET_CLASS (buf);
1332
1333 if (G_LIKELY (rclass->clear_all))
1334 rclass->clear_all (buf);
1335 }
1336
1337
1338 static gboolean
wait_segment(GstAudioRingBuffer * buf)1339 wait_segment (GstAudioRingBuffer * buf)
1340 {
1341 gint segments;
1342 gboolean wait = TRUE;
1343
1344 /* buffer must be started now or we deadlock since nobody is reading */
1345 if (G_UNLIKELY (g_atomic_int_get (&buf->state) !=
1346 GST_AUDIO_RING_BUFFER_STATE_STARTED)) {
1347 /* see if we are allowed to start it */
1348 if (G_UNLIKELY (!g_atomic_int_get (&buf->may_start)))
1349 goto no_start;
1350
1351 GST_DEBUG_OBJECT (buf, "start!");
1352 segments = g_atomic_int_get (&buf->segdone);
1353 gst_audio_ring_buffer_start (buf);
1354
1355 /* After starting, the writer may have wrote segments already and then we
1356 * don't need to wait anymore */
1357 if (G_LIKELY (g_atomic_int_get (&buf->segdone) != segments))
1358 wait = FALSE;
1359 }
1360
1361 /* take lock first, then update our waiting flag */
1362 GST_OBJECT_LOCK (buf);
1363 if (G_UNLIKELY (buf->flushing))
1364 goto flushing;
1365
1366 if (G_UNLIKELY (g_atomic_int_get (&buf->state) !=
1367 GST_AUDIO_RING_BUFFER_STATE_STARTED))
1368 goto not_started;
1369
1370 if (G_LIKELY (wait)) {
1371 if (g_atomic_int_compare_and_exchange (&buf->waiting, 0, 1)) {
1372 GST_DEBUG_OBJECT (buf, "waiting..");
1373 GST_AUDIO_RING_BUFFER_WAIT (buf);
1374
1375 if (G_UNLIKELY (buf->flushing))
1376 goto flushing;
1377
1378 if (G_UNLIKELY (g_atomic_int_get (&buf->state) !=
1379 GST_AUDIO_RING_BUFFER_STATE_STARTED))
1380 goto not_started;
1381 }
1382 }
1383 GST_OBJECT_UNLOCK (buf);
1384
1385 return TRUE;
1386
1387 /* ERROR */
1388 not_started:
1389 {
1390 g_atomic_int_compare_and_exchange (&buf->waiting, 1, 0);
1391 GST_DEBUG_OBJECT (buf, "stopped processing");
1392 GST_OBJECT_UNLOCK (buf);
1393 return FALSE;
1394 }
1395 flushing:
1396 {
1397 g_atomic_int_compare_and_exchange (&buf->waiting, 1, 0);
1398 GST_DEBUG_OBJECT (buf, "flushing");
1399 GST_OBJECT_UNLOCK (buf);
1400 return FALSE;
1401 }
1402 no_start:
1403 {
1404 GST_DEBUG_OBJECT (buf, "not allowed to start");
1405 return FALSE;
1406 }
1407 }
1408
1409
1410
1411 #define REORDER_SAMPLE(d, s, l) \
1412 G_STMT_START { \
1413 gint i; \
1414 for (i = 0; i < channels; i++) { \
1415 memcpy (d + reorder_map[i] * bps, s + i * bps, bps); \
1416 } \
1417 } G_STMT_END
1418
1419 #define REORDER_SAMPLES(d, s, len) \
1420 G_STMT_START { \
1421 gint i, len_ = len / bpf; \
1422 guint8 *d_ = d, *s_ = s; \
1423 for (i = 0; i < len_; i++) { \
1424 REORDER_SAMPLE(d_, s_, bpf); \
1425 d_ += bpf; \
1426 s_ += bpf; \
1427 } \
1428 } G_STMT_END
1429
1430 #define FWD_SAMPLES(s,se,d,de,F) \
1431 G_STMT_START { \
1432 /* no rate conversion */ \
1433 guint towrite = MIN (se + bpf - s, de - d); \
1434 /* simple copy */ \
1435 if (!skip) \
1436 F (d, s, towrite); \
1437 in_samples -= towrite / bpf; \
1438 out_samples -= towrite / bpf; \
1439 s += towrite; \
1440 GST_DEBUG ("copy %u bytes", towrite); \
1441 } G_STMT_END
1442
1443 /* in_samples >= out_samples, rate > 1.0 */
1444 #define FWD_UP_SAMPLES(s,se,d,de,F) \
1445 G_STMT_START { \
1446 guint8 *sb = s, *db = d; \
1447 while (s <= se && d < de) { \
1448 if (!skip) \
1449 F (d, s, bpf); \
1450 s += bpf; \
1451 *accum += outr; \
1452 if ((*accum << 1) >= inr) { \
1453 *accum -= inr; \
1454 d += bpf; \
1455 } \
1456 } \
1457 in_samples -= (s - sb)/bpf; \
1458 out_samples -= (d - db)/bpf; \
1459 GST_DEBUG ("fwd_up end %d/%d",*accum,*toprocess); \
1460 } G_STMT_END
1461
1462 /* out_samples > in_samples, for rates smaller than 1.0 */
1463 #define FWD_DOWN_SAMPLES(s,se,d,de,F) \
1464 G_STMT_START { \
1465 guint8 *sb = s, *db = d; \
1466 while (s <= se && d < de) { \
1467 if (!skip) \
1468 F (d, s, bpf); \
1469 d += bpf; \
1470 *accum += inr; \
1471 if ((*accum << 1) >= outr) { \
1472 *accum -= outr; \
1473 s += bpf; \
1474 } \
1475 } \
1476 in_samples -= (s - sb)/bpf; \
1477 out_samples -= (d - db)/bpf; \
1478 GST_DEBUG ("fwd_down end %d/%d",*accum,*toprocess); \
1479 } G_STMT_END
1480
1481 #define REV_UP_SAMPLES(s,se,d,de,F) \
1482 G_STMT_START { \
1483 guint8 *sb = se, *db = d; \
1484 while (s <= se && d < de) { \
1485 if (!skip) \
1486 F (d, se, bpf); \
1487 se -= bpf; \
1488 *accum += outr; \
1489 while (d < de && (*accum << 1) >= inr) { \
1490 *accum -= inr; \
1491 d += bpf; \
1492 } \
1493 } \
1494 in_samples -= (sb - se)/bpf; \
1495 out_samples -= (d - db)/bpf; \
1496 GST_DEBUG ("rev_up end %d/%d",*accum,*toprocess); \
1497 } G_STMT_END
1498
1499 #define REV_DOWN_SAMPLES(s,se,d,de,F) \
1500 G_STMT_START { \
1501 guint8 *sb = se, *db = d; \
1502 while (s <= se && d < de) { \
1503 if (!skip) \
1504 F (d, se, bpf); \
1505 d += bpf; \
1506 *accum += inr; \
1507 while (s <= se && (*accum << 1) >= outr) { \
1508 *accum -= outr; \
1509 se -= bpf; \
1510 } \
1511 } \
1512 in_samples -= (sb - se)/bpf; \
1513 out_samples -= (d - db)/bpf; \
1514 GST_DEBUG ("rev_down end %d/%d",*accum,*toprocess); \
1515 } G_STMT_END
1516
1517 static guint
default_commit(GstAudioRingBuffer * buf,guint64 * sample,guint8 * data,gint in_samples,gint out_samples,gint * accum)1518 default_commit (GstAudioRingBuffer * buf, guint64 * sample,
1519 guint8 * data, gint in_samples, gint out_samples, gint * accum)
1520 {
1521 gint segdone;
1522 gint segsize, segtotal, channels, bps, bpf, sps;
1523 guint8 *dest, *data_end;
1524 gint writeseg, sampleoff;
1525 gint *toprocess;
1526 gint inr, outr;
1527 gboolean reverse;
1528 gboolean need_reorder;
1529
1530 g_return_val_if_fail (buf->memory != NULL, -1);
1531 g_return_val_if_fail (data != NULL, -1);
1532
1533 need_reorder = buf->need_reorder;
1534
1535 channels = buf->spec.info.channels;
1536 dest = buf->memory;
1537 segsize = buf->spec.segsize;
1538 segtotal = buf->spec.segtotal;
1539 bpf = buf->spec.info.bpf;
1540 bps = bpf / channels;
1541 sps = buf->samples_per_seg;
1542
1543 reverse = out_samples < 0;
1544 out_samples = ABS (out_samples);
1545
1546 if (in_samples >= out_samples)
1547 toprocess = &in_samples;
1548 else
1549 toprocess = &out_samples;
1550
1551 inr = in_samples - 1;
1552 outr = out_samples - 1;
1553
1554 /* data_end points to the last sample we have to write, not past it. This is
1555 * needed to properly handle reverse playback: it points to the last sample. */
1556 data_end = data + (bpf * inr);
1557
1558 /* figure out the segment and the offset inside the segment where
1559 * the first sample should be written. */
1560 writeseg = *sample / sps;
1561 sampleoff = (*sample % sps) * bpf;
1562
1563 GST_DEBUG_OBJECT (buf, "write %d : %d", in_samples, out_samples);
1564
1565 /* write out all samples */
1566 while (*toprocess > 0) {
1567 gint avail;
1568 guint8 *d, *d_end;
1569 gint ws;
1570 gboolean skip;
1571
1572 while (TRUE) {
1573 gint diff;
1574
1575 /* get the currently processed segment */
1576 segdone = g_atomic_int_get (&buf->segdone) - buf->segbase;
1577
1578 /* see how far away it is from the write segment */
1579 diff = writeseg - segdone;
1580
1581 GST_DEBUG_OBJECT (buf,
1582 "pointer at %d, write to %d-%d, diff %d, segtotal %d, segsize %d, base %d",
1583 segdone, writeseg, sampleoff, diff, segtotal, segsize, buf->segbase);
1584
1585 /* segment too far ahead, writer too slow, we need to drop, hopefully UNLIKELY */
1586 if (G_UNLIKELY (diff < 0)) {
1587 /* we need to drop one segment at a time, pretend we wrote a segment. */
1588 skip = TRUE;
1589 break;
1590 }
1591
1592 /* write segment is within writable range, we can break the loop and
1593 * start writing the data. */
1594 if (diff < segtotal) {
1595 skip = FALSE;
1596 break;
1597 }
1598
1599 /* else we need to wait for the segment to become writable. */
1600 if (!wait_segment (buf))
1601 goto not_started;
1602 }
1603
1604 /* we can write now */
1605 ws = writeseg % segtotal;
1606 avail = MIN (segsize - sampleoff, bpf * out_samples);
1607
1608 d = dest + (ws * segsize) + sampleoff;
1609 d_end = d + avail;
1610 *sample += avail / bpf;
1611
1612 GST_DEBUG_OBJECT (buf, "write @%p seg %d, sps %d, off %d, avail %d",
1613 dest + ws * segsize, ws, sps, sampleoff, avail);
1614
1615 if (need_reorder) {
1616 gint *reorder_map = buf->channel_reorder_map;
1617
1618 if (G_LIKELY (inr == outr && !reverse)) {
1619 /* no rate conversion, simply copy samples */
1620 FWD_SAMPLES (data, data_end, d, d_end, REORDER_SAMPLES);
1621 } else if (!reverse) {
1622 if (inr >= outr)
1623 /* forward speed up */
1624 FWD_UP_SAMPLES (data, data_end, d, d_end, REORDER_SAMPLE);
1625 else
1626 /* forward slow down */
1627 FWD_DOWN_SAMPLES (data, data_end, d, d_end, REORDER_SAMPLE);
1628 } else {
1629 if (inr >= outr)
1630 /* reverse speed up */
1631 REV_UP_SAMPLES (data, data_end, d, d_end, REORDER_SAMPLE);
1632 else
1633 /* reverse slow down */
1634 REV_DOWN_SAMPLES (data, data_end, d, d_end, REORDER_SAMPLE);
1635 }
1636 } else {
1637 if (G_LIKELY (inr == outr && !reverse)) {
1638 /* no rate conversion, simply copy samples */
1639 FWD_SAMPLES (data, data_end, d, d_end, memcpy);
1640 } else if (!reverse) {
1641 if (inr >= outr)
1642 /* forward speed up */
1643 FWD_UP_SAMPLES (data, data_end, d, d_end, memcpy);
1644 else
1645 /* forward slow down */
1646 FWD_DOWN_SAMPLES (data, data_end, d, d_end, memcpy);
1647 } else {
1648 if (inr >= outr)
1649 /* reverse speed up */
1650 REV_UP_SAMPLES (data, data_end, d, d_end, memcpy);
1651 else
1652 /* reverse slow down */
1653 REV_DOWN_SAMPLES (data, data_end, d, d_end, memcpy);
1654 }
1655 }
1656
1657 /* for the next iteration we write to the next segment at the beginning. */
1658 writeseg++;
1659 sampleoff = 0;
1660 }
1661 /* we consumed all samples here */
1662 data = data_end + bpf;
1663
1664 done:
1665 return inr - ((data_end - data) / bpf);
1666
1667 /* ERRORS */
1668 not_started:
1669 {
1670 GST_DEBUG_OBJECT (buf, "stopped processing");
1671 goto done;
1672 }
1673 }
1674
1675 /**
1676 * gst_audio_ring_buffer_commit:
1677 * @buf: the #GstAudioRingBuffer to commit
1678 * @sample: the sample position of the data
1679 * @data: (array length=in_samples): the data to commit
1680 * @in_samples: the number of samples in the data to commit
1681 * @out_samples: the number of samples to write to the ringbuffer
1682 * @accum: (inout): accumulator for rate conversion.
1683 *
1684 * Commit @in_samples samples pointed to by @data to the ringbuffer @buf.
1685 *
1686 * @in_samples and @out_samples define the rate conversion to perform on the
1687 * samples in @data. For negative rates, @out_samples must be negative and
1688 * @in_samples positive.
1689 *
1690 * When @out_samples is positive, the first sample will be written at position @sample
1691 * in the ringbuffer. When @out_samples is negative, the last sample will be written to
1692 * @sample in reverse order.
1693 *
1694 * @out_samples does not need to be a multiple of the segment size of the ringbuffer
1695 * although it is recommended for optimal performance.
1696 *
1697 * @accum will hold a temporary accumulator used in rate conversion and should be
1698 * set to 0 when this function is first called. In case the commit operation is
1699 * interrupted, one can resume the processing by passing the previously returned
1700 * @accum value back to this function.
1701 *
1702 * MT safe.
1703 *
1704 * Returns: The number of samples written to the ringbuffer or -1 on error. The
1705 * number of samples written can be less than @out_samples when @buf was interrupted
1706 * with a flush or stop.
1707 */
1708 guint
gst_audio_ring_buffer_commit(GstAudioRingBuffer * buf,guint64 * sample,guint8 * data,gint in_samples,gint out_samples,gint * accum)1709 gst_audio_ring_buffer_commit (GstAudioRingBuffer * buf, guint64 * sample,
1710 guint8 * data, gint in_samples, gint out_samples, gint * accum)
1711 {
1712 GstAudioRingBufferClass *rclass;
1713 guint res = -1;
1714
1715 g_return_val_if_fail (GST_IS_AUDIO_RING_BUFFER (buf), -1);
1716
1717 if (G_UNLIKELY (in_samples == 0 || out_samples == 0))
1718 return in_samples;
1719
1720 rclass = GST_AUDIO_RING_BUFFER_GET_CLASS (buf);
1721
1722 if (G_LIKELY (rclass->commit))
1723 res = rclass->commit (buf, sample, data, in_samples, out_samples, accum);
1724
1725 return res;
1726 }
1727
1728 /**
1729 * gst_audio_ring_buffer_read:
1730 * @buf: the #GstAudioRingBuffer to read from
1731 * @sample: the sample position of the data
1732 * @data: (array length=len): where the data should be read
1733 * @len: the number of samples in data to read
1734 * @timestamp: (out): where the timestamp is returned
1735 *
1736 * Read @len samples from the ringbuffer into the memory pointed
1737 * to by @data.
1738 * The first sample should be read from position @sample in
1739 * the ringbuffer.
1740 *
1741 * @len should not be a multiple of the segment size of the ringbuffer
1742 * although it is recommended.
1743 *
1744 * @timestamp will return the timestamp associated with the data returned.
1745 *
1746 * Returns: The number of samples read from the ringbuffer or -1 on
1747 * error.
1748 *
1749 * MT safe.
1750 */
1751 guint
gst_audio_ring_buffer_read(GstAudioRingBuffer * buf,guint64 sample,guint8 * data,guint len,GstClockTime * timestamp)1752 gst_audio_ring_buffer_read (GstAudioRingBuffer * buf, guint64 sample,
1753 guint8 * data, guint len, GstClockTime * timestamp)
1754 {
1755 gint segdone;
1756 gint segsize, segtotal, channels, bps, bpf, sps, readseg = 0;
1757 guint8 *dest;
1758 guint to_read;
1759 gboolean need_reorder;
1760
1761 g_return_val_if_fail (GST_IS_AUDIO_RING_BUFFER (buf), -1);
1762 g_return_val_if_fail (buf->memory != NULL, -1);
1763 g_return_val_if_fail (data != NULL, -1);
1764
1765 need_reorder = buf->need_reorder;
1766 dest = buf->memory;
1767 segsize = buf->spec.segsize;
1768 segtotal = buf->spec.segtotal;
1769 channels = buf->spec.info.channels;
1770 bpf = buf->spec.info.bpf;
1771 bps = bpf / channels;
1772 sps = buf->samples_per_seg;
1773
1774 to_read = len;
1775 /* read enough samples */
1776 while (to_read > 0) {
1777 gint sampleslen;
1778 gint sampleoff;
1779
1780 /* figure out the segment and the offset inside the segment where
1781 * the sample should be read from. */
1782 readseg = sample / sps;
1783 sampleoff = (sample % sps);
1784
1785 while (TRUE) {
1786 gint diff;
1787
1788 /* get the currently processed segment */
1789 segdone = g_atomic_int_get (&buf->segdone) - buf->segbase;
1790
1791 /* see how far away it is from the read segment, normally segdone (where
1792 * the hardware is writing) is bigger than readseg (where software is
1793 * reading) */
1794 diff = segdone - readseg;
1795
1796 GST_DEBUG_OBJECT
1797 (buf, "pointer at %d, sample %" G_GUINT64_FORMAT
1798 ", read from %d-%d, to_read %d, diff %d, segtotal %d, segsize %d",
1799 segdone, sample, readseg, sampleoff, to_read, diff, segtotal,
1800 segsize);
1801
1802 /* segment too far ahead, reader too slow */
1803 if (G_UNLIKELY (diff >= segtotal)) {
1804 /* pretend we read an empty segment. */
1805 sampleslen = MIN (sps, to_read);
1806 memcpy (data, buf->empty_seg, sampleslen * bpf);
1807 goto next;
1808 }
1809
1810 /* read segment is within readable range, we can break the loop and
1811 * start reading the data. */
1812 if (diff > 0)
1813 break;
1814
1815 /* else we need to wait for the segment to become readable. */
1816 if (!wait_segment (buf))
1817 goto not_started;
1818 }
1819
1820 /* we can read now */
1821 readseg = readseg % segtotal;
1822 sampleslen = MIN (sps - sampleoff, to_read);
1823
1824 GST_DEBUG_OBJECT (buf, "read @%p seg %d, off %d, sampleslen %d",
1825 dest + readseg * segsize, readseg, sampleoff, sampleslen);
1826
1827 if (need_reorder) {
1828 guint8 *ptr = dest + (readseg * segsize) + (sampleoff * bpf);
1829 gint i, j;
1830 gint *reorder_map = buf->channel_reorder_map;
1831
1832 /* Reorder from device order to GStreamer order */
1833 for (i = 0; i < sampleslen; i++) {
1834 for (j = 0; j < channels; j++) {
1835 memcpy (data + i * bpf + reorder_map[j] * bps, ptr + j * bps, bps);
1836 }
1837 ptr += bpf;
1838 }
1839 } else {
1840 memcpy (data, dest + (readseg * segsize) + (sampleoff * bpf),
1841 (sampleslen * bpf));
1842 }
1843
1844 next:
1845 to_read -= sampleslen;
1846 sample += sampleslen;
1847 data += sampleslen * bpf;
1848 }
1849
1850 if (buf->timestamps && timestamp) {
1851 *timestamp = buf->timestamps[readseg % segtotal];
1852 GST_DEBUG_OBJECT (buf, "Retrieved timestamp %" GST_TIME_FORMAT
1853 " @ %d", GST_TIME_ARGS (*timestamp), readseg % segtotal);
1854 }
1855
1856 return len - to_read;
1857
1858 /* ERRORS */
1859 not_started:
1860 {
1861 GST_DEBUG_OBJECT (buf, "stopped processing");
1862 return len - to_read;
1863 }
1864 }
1865
1866 /**
1867 * gst_audio_ring_buffer_prepare_read:
1868 * @buf: the #GstAudioRingBuffer to read from
1869 * @segment: (out): the segment to read
1870 * @readptr: (out) (array length=len):
1871 * the pointer to the memory where samples can be read
1872 * @len: (out): the number of bytes to read
1873 *
1874 * Returns a pointer to memory where the data from segment @segment
1875 * can be found. This function is mostly used by subclasses.
1876 *
1877 * Returns: FALSE if the buffer is not started.
1878 *
1879 * MT safe.
1880 */
1881 gboolean
gst_audio_ring_buffer_prepare_read(GstAudioRingBuffer * buf,gint * segment,guint8 ** readptr,gint * len)1882 gst_audio_ring_buffer_prepare_read (GstAudioRingBuffer * buf, gint * segment,
1883 guint8 ** readptr, gint * len)
1884 {
1885 guint8 *data;
1886 gint segdone;
1887
1888 g_return_val_if_fail (GST_IS_AUDIO_RING_BUFFER (buf), FALSE);
1889
1890 if (buf->callback == NULL) {
1891 /* push mode, fail when nothing is started */
1892 if (g_atomic_int_get (&buf->state) != GST_AUDIO_RING_BUFFER_STATE_STARTED)
1893 return FALSE;
1894 }
1895
1896 g_return_val_if_fail (buf->memory != NULL, FALSE);
1897 g_return_val_if_fail (segment != NULL, FALSE);
1898 g_return_val_if_fail (readptr != NULL, FALSE);
1899 g_return_val_if_fail (len != NULL, FALSE);
1900
1901 data = buf->memory;
1902
1903 /* get the position of the pointer */
1904 segdone = g_atomic_int_get (&buf->segdone);
1905
1906 *segment = segdone % buf->spec.segtotal;
1907 *len = buf->spec.segsize;
1908 *readptr = data + *segment * *len;
1909
1910 GST_LOG_OBJECT (buf, "prepare read from segment %d (real %d) @%p",
1911 *segment, segdone, *readptr);
1912
1913 /* callback to fill the memory with data, for pull based
1914 * scheduling. */
1915 if (buf->callback)
1916 buf->callback (buf, *readptr, *len, buf->cb_data);
1917
1918 return TRUE;
1919 }
1920
1921 /**
1922 * gst_audio_ring_buffer_advance:
1923 * @buf: the #GstAudioRingBuffer to advance
1924 * @advance: the number of segments written
1925 *
1926 * Subclasses should call this function to notify the fact that
1927 * @advance segments are now processed by the device.
1928 *
1929 * MT safe.
1930 */
1931 void
gst_audio_ring_buffer_advance(GstAudioRingBuffer * buf,guint advance)1932 gst_audio_ring_buffer_advance (GstAudioRingBuffer * buf, guint advance)
1933 {
1934 g_return_if_fail (GST_IS_AUDIO_RING_BUFFER (buf));
1935
1936 /* update counter */
1937 g_atomic_int_add (&buf->segdone, advance);
1938
1939 /* the lock is already taken when the waiting flag is set,
1940 * we grab the lock as well to make sure the waiter is actually
1941 * waiting for the signal */
1942 if (g_atomic_int_compare_and_exchange (&buf->waiting, 1, 0)) {
1943 GST_OBJECT_LOCK (buf);
1944 GST_DEBUG_OBJECT (buf, "signal waiter");
1945 GST_AUDIO_RING_BUFFER_SIGNAL (buf);
1946 GST_OBJECT_UNLOCK (buf);
1947 }
1948 }
1949
1950 /**
1951 * gst_audio_ring_buffer_clear:
1952 * @buf: the #GstAudioRingBuffer to clear
1953 * @segment: the segment to clear
1954 *
1955 * Clear the given segment of the buffer with silence samples.
1956 * This function is used by subclasses.
1957 *
1958 * MT safe.
1959 */
1960 void
gst_audio_ring_buffer_clear(GstAudioRingBuffer * buf,gint segment)1961 gst_audio_ring_buffer_clear (GstAudioRingBuffer * buf, gint segment)
1962 {
1963 guint8 *data;
1964
1965 g_return_if_fail (GST_IS_AUDIO_RING_BUFFER (buf));
1966
1967 /* no data means it's already cleared */
1968 if (G_UNLIKELY (buf->memory == NULL))
1969 return;
1970
1971 /* no empty_seg means it's not opened */
1972 if (G_UNLIKELY (buf->empty_seg == NULL))
1973 return;
1974
1975 segment %= buf->spec.segtotal;
1976
1977 data = buf->memory;
1978 data += segment * buf->spec.segsize;
1979
1980 GST_LOG_OBJECT (buf, "clear segment %d @%p", segment, data);
1981
1982 memcpy (data, buf->empty_seg, buf->spec.segsize);
1983 }
1984
1985 /**
1986 * gst_audio_ring_buffer_may_start:
1987 * @buf: the #GstAudioRingBuffer
1988 * @allowed: the new value
1989 *
1990 * Tell the ringbuffer that it is allowed to start playback when
1991 * the ringbuffer is filled with samples.
1992 *
1993 * MT safe.
1994 */
1995 void
gst_audio_ring_buffer_may_start(GstAudioRingBuffer * buf,gboolean allowed)1996 gst_audio_ring_buffer_may_start (GstAudioRingBuffer * buf, gboolean allowed)
1997 {
1998 g_return_if_fail (GST_IS_AUDIO_RING_BUFFER (buf));
1999
2000 GST_LOG_OBJECT (buf, "may start: %d", allowed);
2001 g_atomic_int_set (&buf->may_start, allowed);
2002 }
2003
2004 /* GST_AUDIO_CHANNEL_POSITION_NONE is used for position-less
2005 * mutually exclusive channels. In this case we should not attempt
2006 * to do any reordering.
2007 */
2008 static gboolean
position_less_channels(const GstAudioChannelPosition * pos,guint channels)2009 position_less_channels (const GstAudioChannelPosition * pos, guint channels)
2010 {
2011 guint i;
2012
2013 for (i = 0; i < channels; i++) {
2014 if (pos[i] != GST_AUDIO_CHANNEL_POSITION_NONE)
2015 return FALSE;
2016 }
2017
2018 return TRUE;
2019 }
2020
2021 /**
2022 * gst_audio_ring_buffer_set_channel_positions:
2023 * @buf: the #GstAudioRingBuffer
2024 * @position: (array): the device channel positions
2025 *
2026 * Tell the ringbuffer about the device's channel positions. This must
2027 * be called in when the ringbuffer is acquired.
2028 */
2029 void
gst_audio_ring_buffer_set_channel_positions(GstAudioRingBuffer * buf,const GstAudioChannelPosition * position)2030 gst_audio_ring_buffer_set_channel_positions (GstAudioRingBuffer * buf,
2031 const GstAudioChannelPosition * position)
2032 {
2033 const GstAudioChannelPosition *to;
2034 gint channels;
2035 gint i;
2036
2037 g_return_if_fail (GST_IS_AUDIO_RING_BUFFER (buf));
2038 g_return_if_fail (buf->acquired);
2039
2040 channels = buf->spec.info.channels;
2041 to = buf->spec.info.position;
2042
2043 buf->need_reorder = FALSE;
2044 if (memcmp (position, to, channels * sizeof (to[0])) == 0)
2045 return;
2046
2047 if (position_less_channels (position, channels)) {
2048 GST_LOG_OBJECT (buf, "position-less channels, no need to reorder");
2049 return;
2050 }
2051
2052 if (!gst_audio_get_channel_reorder_map (channels, position, to,
2053 buf->channel_reorder_map))
2054 g_return_if_reached ();
2055
2056 for (i = 0; i < channels; i++) {
2057 if (buf->channel_reorder_map[i] != i) {
2058 #ifndef GST_DISABLE_GST_DEBUG
2059 {
2060 gchar *tmp1, *tmp2;
2061
2062 tmp1 = gst_audio_channel_positions_to_string (position, channels);
2063 tmp2 = gst_audio_channel_positions_to_string (to, channels);
2064 GST_LOG_OBJECT (buf, "may have to reorder channels: %s -> %s", tmp1,
2065 tmp2);
2066 g_free (tmp1);
2067 g_free (tmp2);
2068 }
2069 #endif /* GST_DISABLE_GST_DEBUG */
2070
2071 buf->need_reorder = TRUE;
2072 break;
2073 }
2074 }
2075 }
2076
2077 /**
2078 * gst_ring_buffer_set_timestamp:
2079 * @buf: the #GstRingBuffer
2080 * @readseg: the current data segment
2081 * @timestamp: The new timestamp of the buffer.
2082 *
2083 * Set a new timestamp on the buffer.
2084 *
2085 * MT safe.
2086 */
2087 void
gst_audio_ring_buffer_set_timestamp(GstAudioRingBuffer * buf,gint readseg,GstClockTime timestamp)2088 gst_audio_ring_buffer_set_timestamp (GstAudioRingBuffer * buf, gint readseg,
2089 GstClockTime timestamp)
2090 {
2091 g_return_if_fail (GST_IS_AUDIO_RING_BUFFER (buf));
2092
2093 GST_DEBUG_OBJECT (buf, "Storing timestamp %" GST_TIME_FORMAT
2094 " @ %d", GST_TIME_ARGS (timestamp), readseg);
2095
2096 GST_OBJECT_LOCK (buf);
2097 if (G_UNLIKELY (!buf->acquired))
2098 goto not_acquired;
2099
2100 buf->timestamps[readseg] = timestamp;
2101
2102 done:
2103 GST_OBJECT_UNLOCK (buf);
2104 return;
2105
2106 not_acquired:
2107 {
2108 GST_DEBUG_OBJECT (buf, "we are not acquired");
2109 goto done;
2110 }
2111 }
2112