• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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