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