Merging gst-omx
[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   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     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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 }