dc38ee6d16565b4883ff185ee4968a2ce463cecd
[platform/upstream/gstreamer.git] / subprojects / gst-plugins-base / gst-libs / gst / audio / gstaudioringbuffer.c
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
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
80 gst_audio_ring_buffer_init (GstAudioRingBuffer * ringbuffer)
81 {
82   ringbuffer->open = FALSE;
83   ringbuffer->acquired = FALSE;
84   g_atomic_int_set (&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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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     g_atomic_int_set (&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 G_GNUC_INTERNAL
1040     void __gst_audio_ring_buffer_set_errored (GstAudioRingBuffer * buf);
1041
1042 /* __gst_audio_ring_buffer_set_errored:
1043  * @buf: the #GstAudioRingBuffer that has encountered an error
1044  *
1045  * Mark the ringbuffer as errored after it has started.
1046  *
1047  * MT safe.
1048
1049  * Since: 1.24 (internal in 1.22)
1050  */
1051 void
1052 __gst_audio_ring_buffer_set_errored (GstAudioRingBuffer * buf)
1053 {
1054   gboolean res;
1055
1056   /* If started set to errored */
1057   res = g_atomic_int_compare_and_exchange (&buf->state,
1058       GST_AUDIO_RING_BUFFER_STATE_STARTED, GST_AUDIO_RING_BUFFER_STATE_ERROR);
1059   if (!res) {
1060     GST_DEBUG_OBJECT (buf, "ringbuffer was not started, checking paused");
1061     res = g_atomic_int_compare_and_exchange (&buf->state,
1062         GST_AUDIO_RING_BUFFER_STATE_PAUSED, GST_AUDIO_RING_BUFFER_STATE_ERROR);
1063   }
1064   if (res) {
1065     GST_DEBUG_OBJECT (buf, "ringbuffer is errored");
1066   } else {
1067     GST_DEBUG_OBJECT (buf,
1068         "Could not mark ringbuffer as errored. It must have been stopped or already errored (was state %d)",
1069         g_atomic_int_get (&buf->state));
1070   }
1071 }
1072
1073 static gboolean
1074 gst_audio_ring_buffer_pause_unlocked (GstAudioRingBuffer * buf)
1075 {
1076   gboolean res = FALSE;
1077   GstAudioRingBufferClass *rclass;
1078
1079   GST_DEBUG_OBJECT (buf, "pausing ringbuffer");
1080
1081   /* if started, set to paused */
1082   res = g_atomic_int_compare_and_exchange (&buf->state,
1083       GST_AUDIO_RING_BUFFER_STATE_STARTED, GST_AUDIO_RING_BUFFER_STATE_PAUSED);
1084
1085   if (!res)
1086     goto not_started;
1087
1088   /* signal any waiters */
1089   GST_DEBUG_OBJECT (buf, "signal waiter");
1090   GST_AUDIO_RING_BUFFER_SIGNAL (buf);
1091
1092   rclass = GST_AUDIO_RING_BUFFER_GET_CLASS (buf);
1093   if (G_LIKELY (rclass->pause))
1094     res = rclass->pause (buf);
1095
1096   if (G_UNLIKELY (!res)) {
1097     /* Restore started state */
1098     g_atomic_int_set (&buf->state, GST_AUDIO_RING_BUFFER_STATE_STARTED);
1099     GST_DEBUG_OBJECT (buf, "failed to pause");
1100   } else {
1101     GST_DEBUG_OBJECT (buf, "paused");
1102   }
1103
1104   return res;
1105
1106 not_started:
1107   {
1108     /* was not started */
1109     GST_DEBUG_OBJECT (buf, "was not started (state %d)", buf->state);
1110     return TRUE;
1111   }
1112 }
1113
1114 /**
1115  * gst_audio_ring_buffer_pause:
1116  * @buf: the #GstAudioRingBuffer to pause
1117  *
1118  * Pause processing samples from the ringbuffer.
1119  *
1120  * Returns: TRUE if the device could be paused, FALSE on error.
1121  *
1122  * MT safe.
1123  */
1124 gboolean
1125 gst_audio_ring_buffer_pause (GstAudioRingBuffer * buf)
1126 {
1127   gboolean res = FALSE;
1128
1129   g_return_val_if_fail (GST_IS_AUDIO_RING_BUFFER (buf), FALSE);
1130
1131   GST_OBJECT_LOCK (buf);
1132   if (G_UNLIKELY (buf->flushing))
1133     goto flushing;
1134
1135   if (G_UNLIKELY (!buf->acquired))
1136     goto not_acquired;
1137
1138   res = gst_audio_ring_buffer_pause_unlocked (buf);
1139   GST_OBJECT_UNLOCK (buf);
1140
1141   return res;
1142
1143   /* ERRORS */
1144 flushing:
1145   {
1146     GST_DEBUG_OBJECT (buf, "we are flushing");
1147     GST_OBJECT_UNLOCK (buf);
1148     return FALSE;
1149   }
1150 not_acquired:
1151   {
1152     GST_DEBUG_OBJECT (buf, "not acquired");
1153     GST_OBJECT_UNLOCK (buf);
1154     return FALSE;
1155   }
1156 }
1157
1158 /**
1159  * gst_audio_ring_buffer_stop:
1160  * @buf: the #GstAudioRingBuffer to stop
1161  *
1162  * Stop processing samples from the ringbuffer.
1163  *
1164  * Returns: TRUE if the device could be stopped, FALSE on error.
1165  *
1166  * MT safe.
1167  */
1168 gboolean
1169 gst_audio_ring_buffer_stop (GstAudioRingBuffer * buf)
1170 {
1171   gboolean res = FALSE;
1172   GstAudioRingBufferClass *rclass;
1173
1174   g_return_val_if_fail (GST_IS_AUDIO_RING_BUFFER (buf), FALSE);
1175
1176   GST_DEBUG_OBJECT (buf, "stopping");
1177
1178   GST_OBJECT_LOCK (buf);
1179
1180   /* if started, set to stopped */
1181   res = g_atomic_int_compare_and_exchange (&buf->state,
1182       GST_AUDIO_RING_BUFFER_STATE_STARTED, GST_AUDIO_RING_BUFFER_STATE_STOPPED);
1183
1184   if (!res) {
1185     GST_DEBUG_OBJECT (buf, "was not started, try paused");
1186     /* was not started, try from paused */
1187     res = g_atomic_int_compare_and_exchange (&buf->state,
1188         GST_AUDIO_RING_BUFFER_STATE_PAUSED,
1189         GST_AUDIO_RING_BUFFER_STATE_STOPPED);
1190     if (!res) {
1191       GST_DEBUG_OBJECT (buf, "was not paused, try errored");
1192       res = g_atomic_int_compare_and_exchange (&buf->state,
1193           GST_AUDIO_RING_BUFFER_STATE_ERROR,
1194           GST_AUDIO_RING_BUFFER_STATE_STOPPED);
1195     }
1196     if (!res) {
1197       /* was not paused or stopped either, must have been stopped then */
1198       res = TRUE;
1199       GST_DEBUG_OBJECT (buf,
1200           "was not paused or errored, must have been stopped");
1201       goto done;
1202     }
1203   }
1204
1205   /* signal any waiters */
1206   GST_DEBUG_OBJECT (buf, "signal waiter");
1207   GST_AUDIO_RING_BUFFER_SIGNAL (buf);
1208
1209   rclass = GST_AUDIO_RING_BUFFER_GET_CLASS (buf);
1210   if (G_LIKELY (rclass->stop))
1211     res = rclass->stop (buf);
1212
1213   if (G_UNLIKELY (!res)) {
1214     g_atomic_int_set (&buf->state, GST_AUDIO_RING_BUFFER_STATE_STARTED);
1215     GST_DEBUG_OBJECT (buf, "failed to stop");
1216   } else {
1217     GST_DEBUG_OBJECT (buf, "stopped");
1218   }
1219 done:
1220   GST_OBJECT_UNLOCK (buf);
1221
1222   return res;
1223 }
1224
1225 /**
1226  * gst_audio_ring_buffer_delay:
1227  * @buf: the #GstAudioRingBuffer to query
1228  *
1229  * Get the number of samples queued in the audio device. This is
1230  * usually less than the segment size but can be bigger when the
1231  * implementation uses another internal buffer between the audio
1232  * device.
1233  *
1234  * For playback ringbuffers this is the amount of samples transferred from the
1235  * ringbuffer to the device but still not played.
1236  *
1237  * For capture ringbuffers this is the amount of samples in the device that are
1238  * not yet transferred to the ringbuffer.
1239  *
1240  * Returns: The number of samples queued in the audio device.
1241  *
1242  * MT safe.
1243  */
1244 guint
1245 gst_audio_ring_buffer_delay (GstAudioRingBuffer * buf)
1246 {
1247   GstAudioRingBufferClass *rclass;
1248   guint res;
1249
1250   g_return_val_if_fail (GST_IS_AUDIO_RING_BUFFER (buf), 0);
1251
1252   /* buffer must be acquired */
1253   if (G_UNLIKELY (!gst_audio_ring_buffer_is_acquired (buf)))
1254     goto not_acquired;
1255
1256   rclass = GST_AUDIO_RING_BUFFER_GET_CLASS (buf);
1257   if (G_LIKELY (rclass->delay))
1258     res = rclass->delay (buf);
1259   else
1260     res = 0;
1261
1262   return res;
1263
1264 not_acquired:
1265   {
1266     GST_DEBUG_OBJECT (buf, "not acquired");
1267     return 0;
1268   }
1269 }
1270
1271 /**
1272  * gst_audio_ring_buffer_samples_done:
1273  * @buf: the #GstAudioRingBuffer to query
1274  *
1275  * Get the number of samples that were processed by the ringbuffer
1276  * since it was last started. This does not include the number of samples not
1277  * yet processed (see gst_audio_ring_buffer_delay()).
1278  *
1279  * Returns: The number of samples processed by the ringbuffer.
1280  *
1281  * MT safe.
1282  */
1283 guint64
1284 gst_audio_ring_buffer_samples_done (GstAudioRingBuffer * buf)
1285 {
1286   gint segdone;
1287   guint64 samples;
1288
1289   g_return_val_if_fail (GST_IS_AUDIO_RING_BUFFER (buf), 0);
1290
1291   /* get the amount of segments we processed */
1292   segdone = g_atomic_int_get (&buf->segdone);
1293
1294   /* convert to samples */
1295   samples = ((guint64) segdone) * buf->samples_per_seg;
1296
1297   return samples;
1298 }
1299
1300 /**
1301  * gst_audio_ring_buffer_set_sample:
1302  * @buf: the #GstAudioRingBuffer to use
1303  * @sample: the sample number to set
1304  *
1305  * Make sure that the next sample written to the device is
1306  * accounted for as being the @sample sample written to the
1307  * device. This value will be used in reporting the current
1308  * sample position of the ringbuffer.
1309  *
1310  * This function will also clear the buffer with silence.
1311  *
1312  * MT safe.
1313  */
1314 void
1315 gst_audio_ring_buffer_set_sample (GstAudioRingBuffer * buf, guint64 sample)
1316 {
1317   g_return_if_fail (GST_IS_AUDIO_RING_BUFFER (buf));
1318
1319   if (sample == -1)
1320     sample = 0;
1321
1322   if (G_UNLIKELY (buf->samples_per_seg == 0))
1323     return;
1324
1325   /* FIXME, we assume the ringbuffer can restart at a random
1326    * position, round down to the beginning and keep track of
1327    * offset when calculating the processed samples. */
1328   buf->segbase = buf->segdone - sample / buf->samples_per_seg;
1329
1330   gst_audio_ring_buffer_clear_all (buf);
1331
1332   GST_DEBUG_OBJECT (buf, "set sample to %" G_GUINT64_FORMAT ", segbase %d",
1333       sample, buf->segbase);
1334 }
1335
1336 /**
1337  * default_clear_all:
1338  * @buf: the #GstAudioRingBuffer to clear
1339  *
1340  * Fill the ringbuffer with silence.
1341  */
1342 static void
1343 default_clear_all (GstAudioRingBuffer * buf)
1344 {
1345   gint i;
1346
1347   /* not fatal, we just are not negotiated yet */
1348   if (G_UNLIKELY (buf->spec.segtotal <= 0))
1349     return;
1350
1351   GST_DEBUG_OBJECT (buf, "clear all segments");
1352
1353   for (i = 0; i < buf->spec.segtotal; i++) {
1354     gst_audio_ring_buffer_clear (buf, i);
1355   }
1356 }
1357
1358 /**
1359  * gst_audio_ring_buffer_clear_all:
1360  * @buf: the #GstAudioRingBuffer to clear
1361  *
1362  * Clear all samples from the ringbuffer.
1363  *
1364  * MT safe.
1365  */
1366 void
1367 gst_audio_ring_buffer_clear_all (GstAudioRingBuffer * buf)
1368 {
1369   GstAudioRingBufferClass *rclass;
1370
1371   g_return_if_fail (GST_IS_AUDIO_RING_BUFFER (buf));
1372
1373   rclass = GST_AUDIO_RING_BUFFER_GET_CLASS (buf);
1374
1375   if (G_LIKELY (rclass->clear_all))
1376     rclass->clear_all (buf);
1377 }
1378
1379
1380 static gboolean
1381 wait_segment (GstAudioRingBuffer * buf)
1382 {
1383   gint segments;
1384   gboolean wait = TRUE;
1385
1386   /* buffer must be started now or we deadlock since nobody is reading */
1387   if (G_UNLIKELY (g_atomic_int_get (&buf->state) !=
1388           GST_AUDIO_RING_BUFFER_STATE_STARTED)) {
1389     /* see if we are allowed to start it */
1390     if (G_UNLIKELY (!g_atomic_int_get (&buf->may_start)))
1391       goto no_start;
1392
1393     GST_DEBUG_OBJECT (buf, "start!");
1394     segments = g_atomic_int_get (&buf->segdone);
1395     gst_audio_ring_buffer_start (buf);
1396
1397     /* After starting, the writer may have wrote segments already and then we
1398      * don't need to wait anymore */
1399     if (G_LIKELY (g_atomic_int_get (&buf->segdone) != segments))
1400       wait = FALSE;
1401   }
1402
1403   /* take lock first, then update our waiting flag */
1404   GST_OBJECT_LOCK (buf);
1405   if (G_UNLIKELY (buf->flushing))
1406     goto flushing;
1407
1408   if (G_UNLIKELY (g_atomic_int_get (&buf->state) !=
1409           GST_AUDIO_RING_BUFFER_STATE_STARTED))
1410     goto not_started;
1411
1412   if (G_LIKELY (wait)) {
1413     if (g_atomic_int_compare_and_exchange (&buf->waiting, 0, 1)) {
1414       GST_DEBUG_OBJECT (buf, "waiting..");
1415       GST_AUDIO_RING_BUFFER_WAIT (buf);
1416
1417       if (G_UNLIKELY (buf->flushing))
1418         goto flushing;
1419
1420       if (G_UNLIKELY (g_atomic_int_get (&buf->state) !=
1421               GST_AUDIO_RING_BUFFER_STATE_STARTED))
1422         goto not_started;
1423     }
1424   }
1425   GST_OBJECT_UNLOCK (buf);
1426
1427   return TRUE;
1428
1429   /* ERROR */
1430 not_started:
1431   {
1432     g_atomic_int_compare_and_exchange (&buf->waiting, 1, 0);
1433     GST_DEBUG_OBJECT (buf, "stopped processing");
1434     GST_OBJECT_UNLOCK (buf);
1435     return FALSE;
1436   }
1437 flushing:
1438   {
1439     g_atomic_int_compare_and_exchange (&buf->waiting, 1, 0);
1440     GST_DEBUG_OBJECT (buf, "flushing");
1441     GST_OBJECT_UNLOCK (buf);
1442     return FALSE;
1443   }
1444 no_start:
1445   {
1446     GST_DEBUG_OBJECT (buf, "not allowed to start");
1447     return FALSE;
1448   }
1449 }
1450
1451
1452
1453 #define REORDER_SAMPLE(d, s, l)                 \
1454 G_STMT_START {                                  \
1455   gint i;                                       \
1456   for (i = 0; i < channels; i++) {              \
1457     memcpy (d + reorder_map[i] * bps, s + i * bps, bps); \
1458   }                                             \
1459 } G_STMT_END
1460
1461 #define REORDER_SAMPLES(d, s, len)              \
1462 G_STMT_START {                                  \
1463   gint i, len_ = len / bpf;                     \
1464   guint8 *d_ = d, *s_ = s;                      \
1465   for (i = 0; i < len_; i++) {                  \
1466     REORDER_SAMPLE(d_, s_, bpf);                \
1467     d_ += bpf;                                  \
1468     s_ += bpf;                                  \
1469   }                                             \
1470 } G_STMT_END
1471
1472 #define FWD_SAMPLES(s,se,d,de,F)                \
1473 G_STMT_START {                                  \
1474   /* no rate conversion */                      \
1475   guint towrite = MIN (se + bpf - s, de - d);   \
1476   /* simple copy */                             \
1477   if (!skip)                                    \
1478     F (d, s, towrite);                          \
1479   in_samples -= towrite / bpf;                  \
1480   out_samples -= towrite / bpf;                 \
1481   s += towrite;                                 \
1482   GST_DEBUG ("copy %u bytes", towrite);         \
1483 } G_STMT_END
1484
1485 /* in_samples >= out_samples, rate > 1.0 */
1486 #define FWD_UP_SAMPLES(s,se,d,de,F)             \
1487 G_STMT_START {                                  \
1488   guint8 *sb = s, *db = d;                      \
1489   while (s <= se && d < de) {                   \
1490     if (!skip)                                  \
1491       F (d, s, bpf);                            \
1492     s += bpf;                                   \
1493     *accum += outr;                             \
1494     if ((*accum << 1) >= inr) {                 \
1495       *accum -= inr;                            \
1496       d += bpf;                                 \
1497     }                                           \
1498   }                                             \
1499   in_samples -= (s - sb)/bpf;                   \
1500   out_samples -= (d - db)/bpf;                  \
1501   GST_DEBUG ("fwd_up end %d/%d",*accum,*toprocess);     \
1502 } G_STMT_END
1503
1504 /* out_samples > in_samples, for rates smaller than 1.0 */
1505 #define FWD_DOWN_SAMPLES(s,se,d,de,F)           \
1506 G_STMT_START {                                  \
1507   guint8 *sb = s, *db = d;                      \
1508   while (s <= se && d < de) {                   \
1509     if (!skip)                                  \
1510       F (d, s, bpf);                            \
1511     d += bpf;                                   \
1512     *accum += inr;                              \
1513     if ((*accum << 1) >= outr) {                \
1514       *accum -= outr;                           \
1515       s += bpf;                                 \
1516     }                                           \
1517   }                                             \
1518   in_samples -= (s - sb)/bpf;                   \
1519   out_samples -= (d - db)/bpf;                  \
1520   GST_DEBUG ("fwd_down end %d/%d",*accum,*toprocess);   \
1521 } G_STMT_END
1522
1523 #define REV_UP_SAMPLES(s,se,d,de,F)             \
1524 G_STMT_START {                                  \
1525   guint8 *sb = se, *db = d;                     \
1526   while (s <= se && d < de) {                   \
1527     if (!skip)                                  \
1528       F (d, se, bpf);                           \
1529     se -= bpf;                                  \
1530     *accum += outr;                             \
1531     while (d < de && (*accum << 1) >= inr) {    \
1532       *accum -= inr;                            \
1533       d += bpf;                                 \
1534     }                                           \
1535   }                                             \
1536   in_samples -= (sb - se)/bpf;                  \
1537   out_samples -= (d - db)/bpf;                  \
1538   GST_DEBUG ("rev_up end %d/%d",*accum,*toprocess);     \
1539 } G_STMT_END
1540
1541 #define REV_DOWN_SAMPLES(s,se,d,de,F)           \
1542 G_STMT_START {                                  \
1543   guint8 *sb = se, *db = d;                     \
1544   while (s <= se && d < de) {                   \
1545     if (!skip)                                  \
1546       F (d, se, bpf);                           \
1547     d += bpf;                                   \
1548     *accum += inr;                              \
1549     while (s <= se && (*accum << 1) >= outr) {  \
1550       *accum -= outr;                           \
1551       se -= bpf;                                \
1552     }                                           \
1553   }                                             \
1554   in_samples -= (sb - se)/bpf;                  \
1555   out_samples -= (d - db)/bpf;                  \
1556   GST_DEBUG ("rev_down end %d/%d",*accum,*toprocess);   \
1557 } G_STMT_END
1558
1559 static guint
1560 default_commit (GstAudioRingBuffer * buf, guint64 * sample,
1561     guint8 * data, gint in_samples, gint out_samples, gint * accum)
1562 {
1563   gint segdone;
1564   gint segsize, segtotal, channels, bps, bpf, sps;
1565   guint8 *dest, *data_end;
1566   gint writeseg, sampleoff;
1567   gint *toprocess;
1568   gint inr, outr;
1569   gboolean reverse;
1570   gboolean need_reorder;
1571
1572   g_return_val_if_fail (buf->memory != NULL, -1);
1573   g_return_val_if_fail (data != NULL, -1);
1574
1575   need_reorder = buf->need_reorder;
1576
1577   channels = buf->spec.info.channels;
1578   dest = buf->memory;
1579   segsize = buf->spec.segsize;
1580   segtotal = buf->spec.segtotal;
1581   bpf = buf->spec.info.bpf;
1582   bps = bpf / channels;
1583   sps = buf->samples_per_seg;
1584
1585   reverse = out_samples < 0;
1586   out_samples = ABS (out_samples);
1587
1588   if (in_samples >= out_samples)
1589     toprocess = &in_samples;
1590   else
1591     toprocess = &out_samples;
1592
1593   inr = in_samples - 1;
1594   outr = out_samples - 1;
1595
1596   /* data_end points to the last sample we have to write, not past it. This is
1597    * needed to properly handle reverse playback: it points to the last sample. */
1598   data_end = data + (bpf * inr);
1599
1600   /* figure out the segment and the offset inside the segment where
1601    * the first sample should be written. */
1602   writeseg = *sample / sps;
1603   sampleoff = (*sample % sps) * bpf;
1604
1605   GST_DEBUG_OBJECT (buf, "write %d : %d", in_samples, out_samples);
1606
1607   /* write out all samples */
1608   while (*toprocess > 0) {
1609     gint avail;
1610     guint8 *d, *d_end;
1611     gint ws;
1612     gboolean skip;
1613
1614     while (TRUE) {
1615       gint diff;
1616
1617       /* get the currently processed segment */
1618       segdone = g_atomic_int_get (&buf->segdone) - buf->segbase;
1619
1620       /* see how far away it is from the write segment */
1621       diff = writeseg - segdone;
1622
1623       GST_DEBUG_OBJECT (buf,
1624           "pointer at %d, write to %d-%d, diff %d, segtotal %d, segsize %d, base %d",
1625           segdone, writeseg, sampleoff, diff, segtotal, segsize, buf->segbase);
1626
1627       /* segment too far ahead, writer too slow, we need to drop, hopefully UNLIKELY */
1628       if (G_UNLIKELY (diff < 0)) {
1629         /* we need to drop one segment at a time, pretend we wrote a segment. */
1630         skip = TRUE;
1631         break;
1632       }
1633
1634       /* write segment is within writable range, we can break the loop and
1635        * start writing the data. */
1636       if (diff < segtotal) {
1637         skip = FALSE;
1638         break;
1639       }
1640
1641       /* else we need to wait for the segment to become writable. */
1642       if (!wait_segment (buf))
1643         goto not_started;
1644     }
1645
1646     /* we can write now */
1647     ws = writeseg % segtotal;
1648     avail = MIN (segsize - sampleoff, bpf * out_samples);
1649
1650     d = dest + (ws * segsize) + sampleoff;
1651     d_end = d + avail;
1652     *sample += avail / bpf;
1653
1654     GST_DEBUG_OBJECT (buf, "write @%p seg %d, sps %d, off %d, avail %d",
1655         dest + ws * segsize, ws, sps, sampleoff, avail);
1656
1657     if (need_reorder) {
1658       gint *reorder_map = buf->channel_reorder_map;
1659
1660       if (G_LIKELY (inr == outr && !reverse)) {
1661         /* no rate conversion, simply copy samples */
1662         FWD_SAMPLES (data, data_end, d, d_end, REORDER_SAMPLES);
1663       } else if (!reverse) {
1664         if (inr >= outr)
1665           /* forward speed up */
1666           FWD_UP_SAMPLES (data, data_end, d, d_end, REORDER_SAMPLE);
1667         else
1668           /* forward slow down */
1669           FWD_DOWN_SAMPLES (data, data_end, d, d_end, REORDER_SAMPLE);
1670       } else {
1671         if (inr >= outr)
1672           /* reverse speed up */
1673           REV_UP_SAMPLES (data, data_end, d, d_end, REORDER_SAMPLE);
1674         else
1675           /* reverse slow down */
1676           REV_DOWN_SAMPLES (data, data_end, d, d_end, REORDER_SAMPLE);
1677       }
1678     } else {
1679       if (G_LIKELY (inr == outr && !reverse)) {
1680         /* no rate conversion, simply copy samples */
1681         FWD_SAMPLES (data, data_end, d, d_end, memcpy);
1682       } else if (!reverse) {
1683         if (inr >= outr)
1684           /* forward speed up */
1685           FWD_UP_SAMPLES (data, data_end, d, d_end, memcpy);
1686         else
1687           /* forward slow down */
1688           FWD_DOWN_SAMPLES (data, data_end, d, d_end, memcpy);
1689       } else {
1690         if (inr >= outr)
1691           /* reverse speed up */
1692           REV_UP_SAMPLES (data, data_end, d, d_end, memcpy);
1693         else
1694           /* reverse slow down */
1695           REV_DOWN_SAMPLES (data, data_end, d, d_end, memcpy);
1696       }
1697     }
1698
1699     /* for the next iteration we write to the next segment at the beginning. */
1700     writeseg++;
1701     sampleoff = 0;
1702   }
1703   /* we consumed all samples here */
1704   data = data_end + bpf;
1705
1706 done:
1707   return inr - ((data_end - data) / bpf);
1708
1709   /* ERRORS */
1710 not_started:
1711   {
1712     GST_DEBUG_OBJECT (buf, "stopped processing");
1713     goto done;
1714   }
1715 }
1716
1717 /**
1718  * gst_audio_ring_buffer_commit:
1719  * @buf: the #GstAudioRingBuffer to commit
1720  * @sample: (inout): the sample position of the data
1721  * @data: (array length=in_samples): the data to commit
1722  * @in_samples: the number of samples in the data to commit
1723  * @out_samples: the number of samples to write to the ringbuffer
1724  * @accum: (inout): accumulator for rate conversion.
1725  *
1726  * Commit @in_samples samples pointed to by @data to the ringbuffer @buf.
1727  *
1728  * @in_samples and @out_samples define the rate conversion to perform on the
1729  * samples in @data. For negative rates, @out_samples must be negative and
1730  * @in_samples positive.
1731  *
1732  * When @out_samples is positive, the first sample will be written at position @sample
1733  * in the ringbuffer. When @out_samples is negative, the last sample will be written to
1734  * @sample in reverse order.
1735  *
1736  * @out_samples does not need to be a multiple of the segment size of the ringbuffer
1737  * although it is recommended for optimal performance.
1738  *
1739  * @accum will hold a temporary accumulator used in rate conversion and should be
1740  * set to 0 when this function is first called. In case the commit operation is
1741  * interrupted, one can resume the processing by passing the previously returned
1742  * @accum value back to this function.
1743  *
1744  * MT safe.
1745  *
1746  * Returns: The number of samples written to the ringbuffer or -1 on error. The
1747  * number of samples written can be less than @out_samples when @buf was interrupted
1748  * with a flush or stop.
1749  */
1750 guint
1751 gst_audio_ring_buffer_commit (GstAudioRingBuffer * buf, guint64 * sample,
1752     guint8 * data, gint in_samples, gint out_samples, gint * accum)
1753 {
1754   GstAudioRingBufferClass *rclass;
1755   guint res = -1;
1756
1757   g_return_val_if_fail (GST_IS_AUDIO_RING_BUFFER (buf), -1);
1758
1759   if (G_UNLIKELY (in_samples == 0 || out_samples == 0))
1760     return in_samples;
1761
1762   rclass = GST_AUDIO_RING_BUFFER_GET_CLASS (buf);
1763
1764   if (G_LIKELY (rclass->commit))
1765     res = rclass->commit (buf, sample, data, in_samples, out_samples, accum);
1766
1767   return res;
1768 }
1769
1770 /**
1771  * gst_audio_ring_buffer_read:
1772  * @buf: the #GstAudioRingBuffer to read from
1773  * @sample: the sample position of the data
1774  * @data: (array length=len): where the data should be read
1775  * @len: the number of samples in data to read
1776  * @timestamp: (out): where the timestamp is returned
1777  *
1778  * Read @len samples from the ringbuffer into the memory pointed
1779  * to by @data.
1780  * The first sample should be read from position @sample in
1781  * the ringbuffer.
1782  *
1783  * @len should not be a multiple of the segment size of the ringbuffer
1784  * although it is recommended.
1785  *
1786  * @timestamp will return the timestamp associated with the data returned.
1787  *
1788  * Returns: The number of samples read from the ringbuffer or -1 on
1789  * error.
1790  *
1791  * MT safe.
1792  */
1793 guint
1794 gst_audio_ring_buffer_read (GstAudioRingBuffer * buf, guint64 sample,
1795     guint8 * data, guint len, GstClockTime * timestamp)
1796 {
1797   gint segdone;
1798   gint segsize, segtotal, channels, bps, bpf, sps, readseg = 0;
1799   guint8 *dest;
1800   guint to_read;
1801   gboolean need_reorder;
1802
1803   g_return_val_if_fail (GST_IS_AUDIO_RING_BUFFER (buf), -1);
1804   g_return_val_if_fail (buf->memory != NULL, -1);
1805   g_return_val_if_fail (data != NULL, -1);
1806
1807   need_reorder = buf->need_reorder;
1808   dest = buf->memory;
1809   segsize = buf->spec.segsize;
1810   segtotal = buf->spec.segtotal;
1811   channels = buf->spec.info.channels;
1812   bpf = buf->spec.info.bpf;
1813   bps = bpf / channels;
1814   sps = buf->samples_per_seg;
1815
1816   to_read = len;
1817   /* read enough samples */
1818   while (to_read > 0) {
1819     gint sampleslen;
1820     gint sampleoff;
1821
1822     /* figure out the segment and the offset inside the segment where
1823      * the sample should be read from. */
1824     readseg = sample / sps;
1825     sampleoff = (sample % sps);
1826
1827     while (TRUE) {
1828       gint diff;
1829
1830       /* get the currently processed segment */
1831       segdone = g_atomic_int_get (&buf->segdone) - buf->segbase;
1832
1833       /* see how far away it is from the read segment, normally segdone (where
1834        * the hardware is writing) is bigger than readseg (where software is
1835        * reading) */
1836       diff = segdone - readseg;
1837
1838       GST_DEBUG_OBJECT
1839           (buf, "pointer at %d, sample %" G_GUINT64_FORMAT
1840           ", read from %d-%d, to_read %d, diff %d, segtotal %d, segsize %d",
1841           segdone, sample, readseg, sampleoff, to_read, diff, segtotal,
1842           segsize);
1843
1844       /* segment too far ahead, reader too slow */
1845       if (G_UNLIKELY (diff >= segtotal)) {
1846         /* pretend we read an empty segment. */
1847         sampleslen = MIN (sps, to_read);
1848         memcpy (data, buf->empty_seg, sampleslen * bpf);
1849         goto next;
1850       }
1851
1852       /* read segment is within readable range, we can break the loop and
1853        * start reading the data. */
1854       if (diff > 0)
1855         break;
1856
1857       /* else we need to wait for the segment to become readable. */
1858       if (!wait_segment (buf))
1859         goto not_started;
1860     }
1861
1862     /* we can read now */
1863     readseg = readseg % segtotal;
1864     sampleslen = MIN (sps - sampleoff, to_read);
1865
1866     GST_DEBUG_OBJECT (buf, "read @%p seg %d, off %d, sampleslen %d",
1867         dest + readseg * segsize, readseg, sampleoff, sampleslen);
1868
1869     if (need_reorder) {
1870       guint8 *ptr = dest + (readseg * segsize) + (sampleoff * bpf);
1871       gint i, j;
1872       gint *reorder_map = buf->channel_reorder_map;
1873
1874       /* Reorder from device order to GStreamer order */
1875       for (i = 0; i < sampleslen; i++) {
1876         for (j = 0; j < channels; j++) {
1877           memcpy (data + i * bpf + reorder_map[j] * bps, ptr + j * bps, bps);
1878         }
1879         ptr += bpf;
1880       }
1881     } else {
1882       memcpy (data, dest + (readseg * segsize) + (sampleoff * bpf),
1883           (sampleslen * bpf));
1884     }
1885
1886   next:
1887     to_read -= sampleslen;
1888     sample += sampleslen;
1889     data += sampleslen * bpf;
1890   }
1891
1892   if (buf->timestamps && timestamp) {
1893     *timestamp = buf->timestamps[readseg % segtotal];
1894     GST_DEBUG_OBJECT (buf, "Retrieved timestamp %" GST_TIME_FORMAT
1895         " @ %d", GST_TIME_ARGS (*timestamp), readseg % segtotal);
1896   }
1897
1898   return len - to_read;
1899
1900   /* ERRORS */
1901 not_started:
1902   {
1903     GST_DEBUG_OBJECT (buf, "stopped processing");
1904     return len - to_read;
1905   }
1906 }
1907
1908 /**
1909  * gst_audio_ring_buffer_prepare_read:
1910  * @buf: the #GstAudioRingBuffer to read from
1911  * @segment: (out): the segment to read
1912  * @readptr: (out) (array length=len):
1913  *     the pointer to the memory where samples can be read
1914  * @len: (out): the number of bytes to read
1915  *
1916  * Returns a pointer to memory where the data from segment @segment
1917  * can be found. This function is mostly used by subclasses.
1918  *
1919  * Returns: FALSE if the buffer is not started.
1920  *
1921  * MT safe.
1922  */
1923 gboolean
1924 gst_audio_ring_buffer_prepare_read (GstAudioRingBuffer * buf, gint * segment,
1925     guint8 ** readptr, gint * len)
1926 {
1927   guint8 *data;
1928   gint segdone;
1929
1930   g_return_val_if_fail (GST_IS_AUDIO_RING_BUFFER (buf), FALSE);
1931
1932   if (buf->callback == NULL) {
1933     /* push mode, fail when nothing is started */
1934     if (g_atomic_int_get (&buf->state) != GST_AUDIO_RING_BUFFER_STATE_STARTED)
1935       return FALSE;
1936   }
1937
1938   g_return_val_if_fail (buf->memory != NULL, FALSE);
1939   g_return_val_if_fail (segment != NULL, FALSE);
1940   g_return_val_if_fail (readptr != NULL, FALSE);
1941   g_return_val_if_fail (len != NULL, FALSE);
1942
1943   data = buf->memory;
1944
1945   /* get the position of the pointer */
1946   segdone = g_atomic_int_get (&buf->segdone);
1947
1948   *segment = segdone % buf->spec.segtotal;
1949   *len = buf->spec.segsize;
1950   *readptr = data + *segment * *len;
1951
1952   GST_LOG_OBJECT (buf, "prepare read from segment %d (real %d) @%p",
1953       *segment, segdone, *readptr);
1954
1955   /* callback to fill the memory with data, for pull based
1956    * scheduling. */
1957   if (buf->callback)
1958     buf->callback (buf, *readptr, *len, buf->cb_data);
1959
1960   return TRUE;
1961 }
1962
1963 /**
1964  * gst_audio_ring_buffer_advance:
1965  * @buf: the #GstAudioRingBuffer to advance
1966  * @advance: the number of segments written
1967  *
1968  * Subclasses should call this function to notify the fact that
1969  * @advance segments are now processed by the device.
1970  *
1971  * MT safe.
1972  */
1973 void
1974 gst_audio_ring_buffer_advance (GstAudioRingBuffer * buf, guint advance)
1975 {
1976   g_return_if_fail (GST_IS_AUDIO_RING_BUFFER (buf));
1977
1978   /* update counter */
1979   g_atomic_int_add (&buf->segdone, advance);
1980
1981   /* the lock is already taken when the waiting flag is set,
1982    * we grab the lock as well to make sure the waiter is actually
1983    * waiting for the signal */
1984   if (g_atomic_int_compare_and_exchange (&buf->waiting, 1, 0)) {
1985     GST_OBJECT_LOCK (buf);
1986     GST_DEBUG_OBJECT (buf, "signal waiter");
1987     GST_AUDIO_RING_BUFFER_SIGNAL (buf);
1988     GST_OBJECT_UNLOCK (buf);
1989   }
1990 }
1991
1992 /**
1993  * gst_audio_ring_buffer_clear:
1994  * @buf: the #GstAudioRingBuffer to clear
1995  * @segment: the segment to clear
1996  *
1997  * Clear the given segment of the buffer with silence samples.
1998  * This function is used by subclasses.
1999  *
2000  * MT safe.
2001  */
2002 void
2003 gst_audio_ring_buffer_clear (GstAudioRingBuffer * buf, gint segment)
2004 {
2005   guint8 *data;
2006
2007   g_return_if_fail (GST_IS_AUDIO_RING_BUFFER (buf));
2008
2009   /* no data means it's already cleared */
2010   if (G_UNLIKELY (buf->memory == NULL))
2011     return;
2012
2013   /* no empty_seg means it's not opened */
2014   if (G_UNLIKELY (buf->empty_seg == NULL))
2015     return;
2016
2017   segment %= buf->spec.segtotal;
2018
2019   data = buf->memory;
2020   data += segment * buf->spec.segsize;
2021
2022   GST_LOG_OBJECT (buf, "clear segment %d @%p", segment, data);
2023
2024   memcpy (data, buf->empty_seg, buf->spec.segsize);
2025 }
2026
2027 /**
2028  * gst_audio_ring_buffer_may_start:
2029  * @buf: the #GstAudioRingBuffer
2030  * @allowed: the new value
2031  *
2032  * Tell the ringbuffer that it is allowed to start playback when
2033  * the ringbuffer is filled with samples.
2034  *
2035  * MT safe.
2036  */
2037 void
2038 gst_audio_ring_buffer_may_start (GstAudioRingBuffer * buf, gboolean allowed)
2039 {
2040   g_return_if_fail (GST_IS_AUDIO_RING_BUFFER (buf));
2041
2042   GST_LOG_OBJECT (buf, "may start: %d", allowed);
2043   g_atomic_int_set (&buf->may_start, allowed);
2044 }
2045
2046 /* GST_AUDIO_CHANNEL_POSITION_NONE is used for position-less
2047  * mutually exclusive channels. In this case we should not attempt
2048  * to do any reordering.
2049  */
2050 static gboolean
2051 position_less_channels (const GstAudioChannelPosition * pos, guint channels)
2052 {
2053   guint i;
2054
2055   for (i = 0; i < channels; i++) {
2056     if (pos[i] != GST_AUDIO_CHANNEL_POSITION_NONE)
2057       return FALSE;
2058   }
2059
2060   return TRUE;
2061 }
2062
2063 /**
2064  * gst_audio_ring_buffer_set_channel_positions:
2065  * @buf: the #GstAudioRingBuffer
2066  * @position: (array): the device channel positions
2067  *
2068  * Tell the ringbuffer about the device's channel positions. This must
2069  * be called in when the ringbuffer is acquired.
2070  */
2071 void
2072 gst_audio_ring_buffer_set_channel_positions (GstAudioRingBuffer * buf,
2073     const GstAudioChannelPosition * position)
2074 {
2075   const GstAudioChannelPosition *to;
2076   gint channels;
2077   gint i;
2078
2079   g_return_if_fail (GST_IS_AUDIO_RING_BUFFER (buf));
2080   g_return_if_fail (buf->acquired);
2081
2082   channels = buf->spec.info.channels;
2083   to = buf->spec.info.position;
2084
2085   buf->need_reorder = FALSE;
2086   if (memcmp (position, to, channels * sizeof (to[0])) == 0)
2087     return;
2088
2089   if (channels == 1) {
2090     GST_LOG_OBJECT (buf, "single channel, no need to reorder");
2091     return;
2092   }
2093
2094   if (position_less_channels (position, channels)) {
2095     GST_LOG_OBJECT (buf, "position-less channels, no need to reorder");
2096     return;
2097   }
2098
2099   if (!gst_audio_get_channel_reorder_map (channels, position, to,
2100           buf->channel_reorder_map))
2101     g_return_if_reached ();
2102
2103   for (i = 0; i < channels; i++) {
2104     if (buf->channel_reorder_map[i] != i) {
2105 #ifndef GST_DISABLE_GST_DEBUG
2106       {
2107         gchar *tmp1, *tmp2;
2108
2109         tmp1 = gst_audio_channel_positions_to_string (position, channels);
2110         tmp2 = gst_audio_channel_positions_to_string (to, channels);
2111         GST_LOG_OBJECT (buf, "may have to reorder channels: %s -> %s", tmp1,
2112             tmp2);
2113         g_free (tmp1);
2114         g_free (tmp2);
2115       }
2116 #endif /* GST_DISABLE_GST_DEBUG */
2117
2118       buf->need_reorder = TRUE;
2119       break;
2120     }
2121   }
2122 }
2123
2124 /**
2125  * gst_ring_buffer_set_timestamp:
2126  * @buf: the #GstRingBuffer
2127  * @readseg: the current data segment
2128  * @timestamp: The new timestamp of the buffer.
2129  *
2130  * Set a new timestamp on the buffer.
2131  *
2132  * MT safe.
2133  */
2134 void
2135 gst_audio_ring_buffer_set_timestamp (GstAudioRingBuffer * buf, gint readseg,
2136     GstClockTime timestamp)
2137 {
2138   g_return_if_fail (GST_IS_AUDIO_RING_BUFFER (buf));
2139
2140   GST_DEBUG_OBJECT (buf, "Storing timestamp %" GST_TIME_FORMAT
2141       " @ %d", GST_TIME_ARGS (timestamp), readseg);
2142
2143   GST_OBJECT_LOCK (buf);
2144   if (G_UNLIKELY (!buf->acquired))
2145     goto not_acquired;
2146
2147   buf->timestamps[readseg] = timestamp;
2148
2149 done:
2150   GST_OBJECT_UNLOCK (buf);
2151   return;
2152
2153 not_acquired:
2154   {
2155     GST_DEBUG_OBJECT (buf, "we are not acquired");
2156     goto done;
2157   }
2158 }