ringbuffer: remove old _full version
[platform/upstream/gstreamer.git] / 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., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /**
21  * SECTION:gstaudioringbuffer
22  * @short_description: Base class for audio ringbuffer implementations
23  * @see_also: #GstAudioBaseSink, #GstAudioSink
24  *
25  * <refsect2>
26  * <para>
27  * This object is the base class for audio ringbuffers used by the base
28  * audio source and sink classes.
29  * </para>
30  * <para>
31  * The ringbuffer abstracts a circular buffer of data. One reader and
32  * one writer can operate on the data from different threads in a lockfree
33  * manner. The base class is sufficiently flexible to be used as an
34  * abstraction for DMA based ringbuffers as well as a pure software
35  * implementations.
36  * </para>
37  * </refsect2>
38  *
39  * Last reviewed on 2006-02-02 (0.10.4)
40  */
41
42 #include <string.h>
43
44 #include "gstaudioringbuffer.h"
45
46 GST_DEBUG_CATEGORY_STATIC (gst_audio_ring_buffer_debug);
47 #define GST_CAT_DEFAULT gst_audio_ring_buffer_debug
48
49 static void gst_audio_ring_buffer_dispose (GObject * object);
50 static void gst_audio_ring_buffer_finalize (GObject * object);
51
52 static gboolean gst_audio_ring_buffer_pause_unlocked (GstAudioRingBuffer * buf);
53 static void default_clear_all (GstAudioRingBuffer * buf);
54 static guint default_commit (GstAudioRingBuffer * buf, guint64 * sample,
55     guchar * data, gint in_samples, gint out_samples, gint * accum);
56
57 /* ringbuffer abstract base class */
58 G_DEFINE_ABSTRACT_TYPE (GstAudioRingBuffer, gst_audio_ring_buffer,
59     GST_TYPE_OBJECT);
60
61 static void
62 gst_audio_ring_buffer_class_init (GstAudioRingBufferClass * klass)
63 {
64   GObjectClass *gobject_class;
65   GstAudioRingBufferClass *gstaudioringbuffer_class;
66
67   gobject_class = (GObjectClass *) klass;
68   gstaudioringbuffer_class = (GstAudioRingBufferClass *) klass;
69
70   GST_DEBUG_CATEGORY_INIT (gst_audio_ring_buffer_debug, "ringbuffer", 0,
71       "ringbuffer class");
72
73   gobject_class->dispose = gst_audio_ring_buffer_dispose;
74   gobject_class->finalize = gst_audio_ring_buffer_finalize;
75
76   gstaudioringbuffer_class->clear_all = GST_DEBUG_FUNCPTR (default_clear_all);
77   gstaudioringbuffer_class->commit = GST_DEBUG_FUNCPTR (default_commit);
78 }
79
80 static void
81 gst_audio_ring_buffer_init (GstAudioRingBuffer * ringbuffer)
82 {
83   ringbuffer->open = FALSE;
84   ringbuffer->acquired = FALSE;
85   ringbuffer->state = GST_AUDIO_RING_BUFFER_STATE_STOPPED;
86   ringbuffer->cond = g_cond_new ();
87   ringbuffer->waiting = 0;
88   ringbuffer->empty_seg = NULL;
89   ringbuffer->flushing = TRUE;
90 }
91
92 static void
93 gst_audio_ring_buffer_dispose (GObject * object)
94 {
95   GstAudioRingBuffer *ringbuffer = GST_AUDIO_RING_BUFFER (object);
96
97   gst_caps_replace (&ringbuffer->spec.caps, NULL);
98
99   G_OBJECT_CLASS (gst_audio_ring_buffer_parent_class)->dispose (G_OBJECT
100       (ringbuffer));
101 }
102
103 static void
104 gst_audio_ring_buffer_finalize (GObject * object)
105 {
106   GstAudioRingBuffer *ringbuffer = GST_AUDIO_RING_BUFFER (object);
107
108   g_cond_free (ringbuffer->cond);
109   g_free (ringbuffer->empty_seg);
110
111   G_OBJECT_CLASS (gst_audio_ring_buffer_parent_class)->finalize (G_OBJECT
112       (ringbuffer));
113 }
114
115 #ifndef GST_DISABLE_GST_DEBUG
116 static const gchar *format_type_names[] = {
117   "raw",
118   "mu law",
119   "a law",
120   "ima adpcm",
121   "mpeg",
122   "gsm",
123   "iec958",
124   "ac3",
125   "eac3",
126   "dts"
127 };
128 #endif
129
130 /**
131  * gst_audio_ring_buffer_debug_spec_caps:
132  * @spec: the spec to debug
133  *
134  * Print debug info about the parsed caps in @spec to the debug log.
135  */
136 void
137 gst_audio_ring_buffer_debug_spec_caps (GstAudioRingBufferSpec * spec)
138 {
139 #if 0
140   gint i, bytes;
141 #endif
142
143   GST_DEBUG ("spec caps: %p %" GST_PTR_FORMAT, spec->caps, spec->caps);
144   GST_DEBUG ("parsed caps: type:         %d, '%s'", spec->type,
145       format_type_names[spec->type]);
146 #if 0
147   GST_DEBUG ("parsed caps: width:        %d", spec->width);
148   GST_DEBUG ("parsed caps: sign:         %d", spec->sign);
149   GST_DEBUG ("parsed caps: bigend:       %d", spec->bigend);
150   GST_DEBUG ("parsed caps: rate:         %d", spec->rate);
151   GST_DEBUG ("parsed caps: channels:     %d", spec->channels);
152   GST_DEBUG ("parsed caps: sample bytes: %d", spec->bytes_per_sample);
153   bytes = (spec->width >> 3) * spec->channels;
154   for (i = 0; i < bytes; i++) {
155     GST_DEBUG ("silence byte %d: %02x", i, spec->silence_sample[i]);
156   }
157 #endif
158 }
159
160 /**
161  * gst_audio_ring_buffer_debug_spec_buff:
162  * @spec: the spec to debug
163  *
164  * Print debug info about the buffer sized in @spec to the debug log.
165  */
166 void
167 gst_audio_ring_buffer_debug_spec_buff (GstAudioRingBufferSpec * spec)
168 {
169   gint bpf = GST_AUDIO_INFO_BPF (&spec->info);
170
171   GST_DEBUG ("acquire ringbuffer: buffer time: %" G_GINT64_FORMAT " usec",
172       spec->buffer_time);
173   GST_DEBUG ("acquire ringbuffer: latency time: %" G_GINT64_FORMAT " usec",
174       spec->latency_time);
175   GST_DEBUG ("acquire ringbuffer: total segments: %d", spec->segtotal);
176   GST_DEBUG ("acquire ringbuffer: latency segments: %d", spec->seglatency);
177   GST_DEBUG ("acquire ringbuffer: segment size: %d bytes = %d samples",
178       spec->segsize, spec->segsize / bpf);
179   GST_DEBUG ("acquire ringbuffer: buffer size: %d bytes = %d samples",
180       spec->segsize * spec->segtotal, spec->segsize * spec->segtotal / bpf);
181 }
182
183 /**
184  * gst_audio_ring_buffer_parse_caps:
185  * @spec: a spec
186  * @caps: a #GstCaps
187  *
188  * Parse @caps into @spec.
189  *
190  * Returns: TRUE if the caps could be parsed.
191  */
192 gboolean
193 gst_audio_ring_buffer_parse_caps (GstAudioRingBufferSpec * spec, GstCaps * caps)
194 {
195   const gchar *mimetype;
196   GstStructure *structure;
197   gint i;
198   GstAudioInfo info;
199
200   structure = gst_caps_get_structure (caps, 0);
201   gst_audio_info_init (&info);
202
203   /* we have to differentiate between int and float formats */
204   mimetype = gst_structure_get_name (structure);
205
206   if (g_str_equal (mimetype, "audio/x-raw")) {
207     if (!gst_audio_info_from_caps (&info, caps))
208       goto parse_error;
209
210     spec->type = GST_BUFTYPE_RAW;
211   } else if (g_str_equal (mimetype, "audio/x-alaw")) {
212     /* extract the needed information from the cap */
213     if (!(gst_structure_get_int (structure, "rate", &info.rate) &&
214             gst_structure_get_int (structure, "channels", &info.channels)))
215       goto parse_error;
216
217     spec->type = GST_BUFTYPE_A_LAW;
218     info.bpf = info.channels;
219   } else if (g_str_equal (mimetype, "audio/x-mulaw")) {
220     /* extract the needed information from the cap */
221     if (!(gst_structure_get_int (structure, "rate", &info.rate) &&
222             gst_structure_get_int (structure, "channels", &info.channels)))
223       goto parse_error;
224
225     spec->type = GST_BUFTYPE_MU_LAW;
226     info.bpf = info.channels;
227   } else if (g_str_equal (mimetype, "audio/x-iec958")) {
228     /* extract the needed information from the cap */
229     if (!(gst_structure_get_int (structure, "rate", &info.rate)))
230       goto parse_error;
231
232     spec->type = GST_BUFTYPE_IEC958;
233     info.bpf = 4;
234   } else if (g_str_equal (mimetype, "audio/x-ac3")) {
235     /* extract the needed information from the cap */
236     if (!(gst_structure_get_int (structure, "rate", &info.rate)))
237       goto parse_error;
238
239     spec->type = GST_BUFTYPE_AC3;
240     info.bpf = 4;
241   } else if (g_str_equal (mimetype, "audio/x-eac3")) {
242     /* extract the needed information from the cap */
243     if (!(gst_structure_get_int (structure, "rate", &info.rate)))
244       goto parse_error;
245
246     spec->type = GST_BUFTYPE_EAC3;
247     info.bpf = 16;
248   } else if (g_str_equal (mimetype, "audio/x-dts")) {
249     /* extract the needed information from the cap */
250     if (!(gst_structure_get_int (structure, "rate", &info.rate)))
251       goto parse_error;
252
253     spec->type = GST_BUFTYPE_DTS;
254     info.bpf = 4;
255   } else if (g_str_equal (mimetype, "audio/mpeg") &&
256       gst_structure_get_int (structure, "mpegaudioversion", &i) &&
257       (i == 1 || i == 2)) {
258     /* Now we know this is MPEG-1 or MPEG-2 (non AAC) */
259     /* extract the needed information from the cap */
260     if (!(gst_structure_get_int (structure, "rate", &info.rate)))
261       goto parse_error;
262
263     spec->type = GST_BUFTYPE_MPEG;
264     info.bpf = 4;
265   } else {
266     goto parse_error;
267   }
268
269   gst_caps_replace (&spec->caps, caps);
270
271   g_return_val_if_fail (spec->latency_time != 0, FALSE);
272
273   /* calculate suggested segsize and segtotal. segsize should be one unit
274    * of 'latency_time' samples, scaling for the fact that latency_time is
275    * currently stored in microseconds (FIXME: in 0.11) */
276   spec->segsize = gst_util_uint64_scale (info.rate * info.bpf,
277       spec->latency_time, GST_SECOND / GST_USECOND);
278   /* Round to an integer number of samples */
279   spec->segsize -= spec->segsize % info.bpf;
280
281   spec->segtotal = spec->buffer_time / spec->latency_time;
282   /* leave the latency undefined now, implementations can change it but if it's
283    * not changed, we assume the same value as segtotal */
284   spec->seglatency = -1;
285
286   spec->info = info;
287
288   gst_audio_ring_buffer_debug_spec_caps (spec);
289   gst_audio_ring_buffer_debug_spec_buff (spec);
290
291   return TRUE;
292
293   /* ERRORS */
294 parse_error:
295   {
296     GST_DEBUG ("could not parse caps");
297     return FALSE;
298   }
299 }
300
301 /**
302  * gst_audio_ring_buffer_convert:
303  * @buf: the #GstAudioRingBuffer
304  * @src_fmt: the source format
305  * @src_val: the source value
306  * @dest_fmt: the destination format
307  * @dest_val: a location to store the converted value
308  *
309  * Convert @src_val in @src_fmt to the equivalent value in @dest_fmt. The result
310  * will be put in @dest_val.
311  *
312  * Returns: TRUE if the conversion succeeded.
313  *
314  * Since: 0.10.22.
315  */
316 gboolean
317 gst_audio_ring_buffer_convert (GstAudioRingBuffer * buf,
318     GstFormat src_fmt, gint64 src_val, GstFormat dest_fmt, gint64 * dest_val)
319 {
320   gboolean res;
321
322   GST_OBJECT_LOCK (buf);
323   res =
324       gst_audio_info_convert (&buf->spec.info, src_fmt, src_val, dest_fmt,
325       dest_val);
326   GST_OBJECT_UNLOCK (buf);
327
328   return res;
329 }
330
331 /**
332  * gst_audio_ring_buffer_set_callback:
333  * @buf: the #GstAudioRingBuffer to set the callback on
334  * @cb: the callback to set
335  * @user_data: user data passed to the callback
336  *
337  * Sets the given callback function on the buffer. This function
338  * will be called every time a segment has been written to a device.
339  *
340  * MT safe.
341  */
342 void
343 gst_audio_ring_buffer_set_callback (GstAudioRingBuffer * buf,
344     GstAudioRingBufferCallback cb, gpointer user_data)
345 {
346   g_return_if_fail (GST_IS_AUDIO_RING_BUFFER (buf));
347
348   GST_OBJECT_LOCK (buf);
349   buf->callback = cb;
350   buf->cb_data = user_data;
351   GST_OBJECT_UNLOCK (buf);
352 }
353
354
355 /**
356  * gst_audio_ring_buffer_open_device:
357  * @buf: the #GstAudioRingBuffer
358  *
359  * Open the audio device associated with the ring buffer. Does not perform any
360  * setup on the device. You must open the device before acquiring the ring
361  * buffer.
362  *
363  * Returns: TRUE if the device could be opened, FALSE on error.
364  *
365  * MT safe.
366  */
367 gboolean
368 gst_audio_ring_buffer_open_device (GstAudioRingBuffer * buf)
369 {
370   gboolean res = TRUE;
371   GstAudioRingBufferClass *rclass;
372
373   g_return_val_if_fail (GST_IS_AUDIO_RING_BUFFER (buf), FALSE);
374
375   GST_DEBUG_OBJECT (buf, "opening device");
376
377   GST_OBJECT_LOCK (buf);
378   if (G_UNLIKELY (buf->open))
379     goto was_opened;
380
381   buf->open = TRUE;
382
383   /* if this fails, something is wrong in this file */
384   g_assert (!buf->acquired);
385
386   rclass = GST_AUDIO_RING_BUFFER_GET_CLASS (buf);
387   if (G_LIKELY (rclass->open_device))
388     res = rclass->open_device (buf);
389
390   if (G_UNLIKELY (!res))
391     goto open_failed;
392
393   GST_DEBUG_OBJECT (buf, "opened device");
394
395 done:
396   GST_OBJECT_UNLOCK (buf);
397
398   return res;
399
400   /* ERRORS */
401 was_opened:
402   {
403     GST_DEBUG_OBJECT (buf, "Device for ring buffer already open");
404     g_warning ("Device for ring buffer %p already open, fix your code", buf);
405     res = TRUE;
406     goto done;
407   }
408 open_failed:
409   {
410     buf->open = FALSE;
411     GST_DEBUG_OBJECT (buf, "failed opening device");
412     goto done;
413   }
414 }
415
416 /**
417  * gst_audio_ring_buffer_close_device:
418  * @buf: the #GstAudioRingBuffer
419  *
420  * Close the audio device associated with the ring buffer. The ring buffer
421  * should already have been released via gst_audio_ring_buffer_release().
422  *
423  * Returns: TRUE if the device could be closed, FALSE on error.
424  *
425  * MT safe.
426  */
427 gboolean
428 gst_audio_ring_buffer_close_device (GstAudioRingBuffer * buf)
429 {
430   gboolean res = TRUE;
431   GstAudioRingBufferClass *rclass;
432
433   g_return_val_if_fail (GST_IS_AUDIO_RING_BUFFER (buf), FALSE);
434
435   GST_DEBUG_OBJECT (buf, "closing device");
436
437   GST_OBJECT_LOCK (buf);
438   if (G_UNLIKELY (!buf->open))
439     goto was_closed;
440
441   if (G_UNLIKELY (buf->acquired))
442     goto was_acquired;
443
444   buf->open = FALSE;
445
446   rclass = GST_AUDIO_RING_BUFFER_GET_CLASS (buf);
447   if (G_LIKELY (rclass->close_device))
448     res = rclass->close_device (buf);
449
450   if (G_UNLIKELY (!res))
451     goto close_error;
452
453   GST_DEBUG_OBJECT (buf, "closed device");
454
455 done:
456   GST_OBJECT_UNLOCK (buf);
457
458   return res;
459
460   /* ERRORS */
461 was_closed:
462   {
463     GST_DEBUG_OBJECT (buf, "Device for ring buffer already closed");
464     g_warning ("Device for ring buffer %p already closed, fix your code", buf);
465     res = TRUE;
466     goto done;
467   }
468 was_acquired:
469   {
470     GST_DEBUG_OBJECT (buf, "Resources for ring buffer still acquired");
471     g_critical ("Resources for ring buffer %p still acquired", buf);
472     res = FALSE;
473     goto done;
474   }
475 close_error:
476   {
477     buf->open = TRUE;
478     GST_DEBUG_OBJECT (buf, "error closing device");
479     goto done;
480   }
481 }
482
483 /**
484  * gst_audio_ring_buffer_device_is_open:
485  * @buf: the #GstAudioRingBuffer
486  *
487  * Checks the status of the device associated with the ring buffer.
488  *
489  * Returns: TRUE if the device was open, FALSE if it was closed.
490  *
491  * MT safe.
492  */
493 gboolean
494 gst_audio_ring_buffer_device_is_open (GstAudioRingBuffer * buf)
495 {
496   gboolean res = TRUE;
497
498   g_return_val_if_fail (GST_IS_AUDIO_RING_BUFFER (buf), FALSE);
499
500   GST_OBJECT_LOCK (buf);
501   res = buf->open;
502   GST_OBJECT_UNLOCK (buf);
503
504   return res;
505 }
506
507 /**
508  * gst_audio_ring_buffer_acquire:
509  * @buf: the #GstAudioRingBuffer to acquire
510  * @spec: the specs of the buffer
511  *
512  * Allocate the resources for the ringbuffer. This function fills
513  * in the data pointer of the ring buffer with a valid #GstBuffer
514  * to which samples can be written.
515  *
516  * Returns: TRUE if the device could be acquired, FALSE on error.
517  *
518  * MT safe.
519  */
520 gboolean
521 gst_audio_ring_buffer_acquire (GstAudioRingBuffer * buf,
522     GstAudioRingBufferSpec * spec)
523 {
524   gboolean res = FALSE;
525   GstAudioRingBufferClass *rclass;
526   gint segsize, bpf;
527
528   g_return_val_if_fail (GST_IS_AUDIO_RING_BUFFER (buf), FALSE);
529
530   GST_DEBUG_OBJECT (buf, "acquiring device %p", buf);
531
532   GST_OBJECT_LOCK (buf);
533   if (G_UNLIKELY (!buf->open))
534     goto not_opened;
535
536   if (G_UNLIKELY (buf->acquired))
537     goto was_acquired;
538
539   buf->acquired = TRUE;
540
541   rclass = GST_AUDIO_RING_BUFFER_GET_CLASS (buf);
542   if (G_LIKELY (rclass->acquire))
543     res = rclass->acquire (buf, spec);
544
545   if (G_UNLIKELY (!res))
546     goto acquire_failed;
547
548   if (G_UNLIKELY ((bpf = buf->spec.info.bpf) == 0))
549     goto invalid_bpf;
550
551   /* if the seglatency was overwritten with something else than -1, use it, else
552    * assume segtotal as the latency */
553   if (buf->spec.seglatency == -1)
554     buf->spec.seglatency = buf->spec.segtotal;
555
556   segsize = buf->spec.segsize;
557
558   buf->samples_per_seg = segsize / bpf;
559
560   /* create an empty segment */
561   g_free (buf->empty_seg);
562   buf->empty_seg = g_malloc (segsize);
563
564   if (buf->spec.type == GST_BUFTYPE_RAW) {
565     gst_audio_format_fill_silence (buf->spec.info.finfo, buf->empty_seg,
566         segsize);
567   } else {
568     /* FIXME, non-raw formats get 0 as the empty sample */
569     memset (buf->empty_seg, 0, segsize);
570   }
571   GST_DEBUG_OBJECT (buf, "acquired device");
572
573 done:
574   GST_OBJECT_UNLOCK (buf);
575
576   return res;
577
578   /* ERRORS */
579 not_opened:
580   {
581     GST_DEBUG_OBJECT (buf, "device not opened");
582     g_critical ("Device for %p not opened", buf);
583     res = FALSE;
584     goto done;
585   }
586 was_acquired:
587   {
588     res = TRUE;
589     GST_DEBUG_OBJECT (buf, "device was acquired");
590     goto done;
591   }
592 acquire_failed:
593   {
594     buf->acquired = FALSE;
595     GST_DEBUG_OBJECT (buf, "failed to acquire device");
596     goto done;
597   }
598 invalid_bpf:
599   {
600     g_warning
601         ("invalid bytes_per_frame from acquire ringbuffer %p, fix the element",
602         buf);
603     buf->acquired = FALSE;
604     res = FALSE;
605     goto done;
606   }
607 }
608
609 /**
610  * gst_audio_ring_buffer_release:
611  * @buf: the #GstAudioRingBuffer to release
612  *
613  * Free the resources of the ringbuffer.
614  *
615  * Returns: TRUE if the device could be released, FALSE on error.
616  *
617  * MT safe.
618  */
619 gboolean
620 gst_audio_ring_buffer_release (GstAudioRingBuffer * buf)
621 {
622   gboolean res = FALSE;
623   GstAudioRingBufferClass *rclass;
624
625   g_return_val_if_fail (GST_IS_AUDIO_RING_BUFFER (buf), FALSE);
626
627   GST_DEBUG_OBJECT (buf, "releasing device");
628
629   gst_audio_ring_buffer_stop (buf);
630
631   GST_OBJECT_LOCK (buf);
632   if (G_UNLIKELY (!buf->acquired))
633     goto was_released;
634
635   buf->acquired = FALSE;
636
637   /* if this fails, something is wrong in this file */
638   g_assert (buf->open == TRUE);
639
640   rclass = GST_AUDIO_RING_BUFFER_GET_CLASS (buf);
641   if (G_LIKELY (rclass->release))
642     res = rclass->release (buf);
643
644   /* signal any waiters */
645   GST_DEBUG_OBJECT (buf, "signal waiter");
646   GST_AUDIO_RING_BUFFER_SIGNAL (buf);
647
648   if (G_UNLIKELY (!res))
649     goto release_failed;
650
651   g_free (buf->empty_seg);
652   buf->empty_seg = NULL;
653   GST_DEBUG_OBJECT (buf, "released device");
654
655 done:
656   GST_OBJECT_UNLOCK (buf);
657
658   return res;
659
660   /* ERRORS */
661 was_released:
662   {
663     res = TRUE;
664     GST_DEBUG_OBJECT (buf, "device was released");
665     goto done;
666   }
667 release_failed:
668   {
669     buf->acquired = TRUE;
670     GST_DEBUG_OBJECT (buf, "failed to release device");
671     goto done;
672   }
673 }
674
675 /**
676  * gst_audio_ring_buffer_is_acquired:
677  * @buf: the #GstAudioRingBuffer to check
678  *
679  * Check if the ringbuffer is acquired and ready to use.
680  *
681  * Returns: TRUE if the ringbuffer is acquired, FALSE on error.
682  *
683  * MT safe.
684  */
685 gboolean
686 gst_audio_ring_buffer_is_acquired (GstAudioRingBuffer * buf)
687 {
688   gboolean res;
689
690   g_return_val_if_fail (GST_IS_AUDIO_RING_BUFFER (buf), FALSE);
691
692   GST_OBJECT_LOCK (buf);
693   res = buf->acquired;
694   GST_OBJECT_UNLOCK (buf);
695
696   return res;
697 }
698
699 /**
700  * gst_audio_ring_buffer_activate:
701  * @buf: the #GstAudioRingBuffer to activate
702  * @active: the new mode
703  *
704  * Activate @buf to start or stop pulling data.
705  *
706  * MT safe.
707  *
708  * Returns: TRUE if the device could be activated in the requested mode,
709  * FALSE on error.
710  *
711  * Since: 0.10.22.
712  */
713 gboolean
714 gst_audio_ring_buffer_activate (GstAudioRingBuffer * buf, gboolean active)
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, "activate device");
722
723   GST_OBJECT_LOCK (buf);
724   if (G_UNLIKELY (active && !buf->acquired))
725     goto not_acquired;
726
727   if (G_UNLIKELY (buf->active == active))
728     goto was_active;
729
730   rclass = GST_AUDIO_RING_BUFFER_GET_CLASS (buf);
731   /* if there is no activate function we assume it was started/released
732    * in the acquire method */
733   if (G_LIKELY (rclass->activate))
734     res = rclass->activate (buf, active);
735   else
736     res = TRUE;
737
738   if (G_UNLIKELY (!res))
739     goto activate_failed;
740
741   buf->active = active;
742
743 done:
744   GST_OBJECT_UNLOCK (buf);
745
746   return res;
747
748   /* ERRORS */
749 not_acquired:
750   {
751     GST_DEBUG_OBJECT (buf, "device not acquired");
752     g_critical ("Device for %p not acquired", buf);
753     res = FALSE;
754     goto done;
755   }
756 was_active:
757   {
758     res = TRUE;
759     GST_DEBUG_OBJECT (buf, "device was active in mode %d", active);
760     goto done;
761   }
762 activate_failed:
763   {
764     GST_DEBUG_OBJECT (buf, "failed to activate device");
765     goto done;
766   }
767 }
768
769 /**
770  * gst_audio_ring_buffer_is_active:
771  * @buf: the #GstAudioRingBuffer
772  *
773  * Check if @buf is activated.
774  *
775  * MT safe.
776  *
777  * Returns: TRUE if the device is active.
778  *
779  * Since: 0.10.22.
780  */
781 gboolean
782 gst_audio_ring_buffer_is_active (GstAudioRingBuffer * buf)
783 {
784   gboolean res;
785
786   g_return_val_if_fail (GST_IS_AUDIO_RING_BUFFER (buf), FALSE);
787
788   GST_OBJECT_LOCK (buf);
789   res = buf->active;
790   GST_OBJECT_UNLOCK (buf);
791
792   return res;
793 }
794
795
796 /**
797  * gst_audio_ring_buffer_set_flushing:
798  * @buf: the #GstAudioRingBuffer to flush
799  * @flushing: the new mode
800  *
801  * Set the ringbuffer to flushing mode or normal mode.
802  *
803  * MT safe.
804  */
805 void
806 gst_audio_ring_buffer_set_flushing (GstAudioRingBuffer * buf, gboolean flushing)
807 {
808   g_return_if_fail (GST_IS_AUDIO_RING_BUFFER (buf));
809
810   GST_OBJECT_LOCK (buf);
811   buf->flushing = flushing;
812
813   if (flushing) {
814     gst_audio_ring_buffer_pause_unlocked (buf);
815   } else {
816     gst_audio_ring_buffer_clear_all (buf);
817   }
818   GST_OBJECT_UNLOCK (buf);
819 }
820
821 /**
822  * gst_audio_ring_buffer_start:
823  * @buf: the #GstAudioRingBuffer to start
824  *
825  * Start processing samples from the ringbuffer.
826  *
827  * Returns: TRUE if the device could be started, FALSE on error.
828  *
829  * MT safe.
830  */
831 gboolean
832 gst_audio_ring_buffer_start (GstAudioRingBuffer * buf)
833 {
834   gboolean res = FALSE;
835   GstAudioRingBufferClass *rclass;
836   gboolean resume = FALSE;
837
838   g_return_val_if_fail (GST_IS_AUDIO_RING_BUFFER (buf), FALSE);
839
840   GST_DEBUG_OBJECT (buf, "starting ringbuffer");
841
842   GST_OBJECT_LOCK (buf);
843   if (G_UNLIKELY (buf->flushing))
844     goto flushing;
845
846   if (G_UNLIKELY (!buf->acquired))
847     goto not_acquired;
848
849   if (G_UNLIKELY (g_atomic_int_get (&buf->may_start) == FALSE))
850     goto may_not_start;
851
852   /* if stopped, set to started */
853   res = g_atomic_int_compare_and_exchange (&buf->state,
854       GST_AUDIO_RING_BUFFER_STATE_STOPPED, GST_AUDIO_RING_BUFFER_STATE_STARTED);
855
856   if (!res) {
857     GST_DEBUG_OBJECT (buf, "was not stopped, try paused");
858     /* was not stopped, try from paused */
859     res = g_atomic_int_compare_and_exchange (&buf->state,
860         GST_AUDIO_RING_BUFFER_STATE_PAUSED,
861         GST_AUDIO_RING_BUFFER_STATE_STARTED);
862     if (!res) {
863       /* was not paused either, must be started then */
864       res = TRUE;
865       GST_DEBUG_OBJECT (buf, "was not paused, must have been started");
866       goto done;
867     }
868     resume = TRUE;
869     GST_DEBUG_OBJECT (buf, "resuming");
870   }
871
872   rclass = GST_AUDIO_RING_BUFFER_GET_CLASS (buf);
873   if (resume) {
874     if (G_LIKELY (rclass->resume))
875       res = rclass->resume (buf);
876   } else {
877     if (G_LIKELY (rclass->start))
878       res = rclass->start (buf);
879   }
880
881   if (G_UNLIKELY (!res)) {
882     buf->state = GST_AUDIO_RING_BUFFER_STATE_PAUSED;
883     GST_DEBUG_OBJECT (buf, "failed to start");
884   } else {
885     GST_DEBUG_OBJECT (buf, "started");
886   }
887
888 done:
889   GST_OBJECT_UNLOCK (buf);
890
891   return res;
892
893 flushing:
894   {
895     GST_DEBUG_OBJECT (buf, "we are flushing");
896     GST_OBJECT_UNLOCK (buf);
897     return FALSE;
898   }
899 not_acquired:
900   {
901     GST_DEBUG_OBJECT (buf, "we are not acquired");
902     GST_OBJECT_UNLOCK (buf);
903     return FALSE;
904   }
905 may_not_start:
906   {
907     GST_DEBUG_OBJECT (buf, "we may not start");
908     GST_OBJECT_UNLOCK (buf);
909     return FALSE;
910   }
911 }
912
913 static gboolean
914 gst_audio_ring_buffer_pause_unlocked (GstAudioRingBuffer * buf)
915 {
916   gboolean res = FALSE;
917   GstAudioRingBufferClass *rclass;
918
919   GST_DEBUG_OBJECT (buf, "pausing ringbuffer");
920
921   /* if started, set to paused */
922   res = g_atomic_int_compare_and_exchange (&buf->state,
923       GST_AUDIO_RING_BUFFER_STATE_STARTED, GST_AUDIO_RING_BUFFER_STATE_PAUSED);
924
925   if (!res)
926     goto not_started;
927
928   /* signal any waiters */
929   GST_DEBUG_OBJECT (buf, "signal waiter");
930   GST_AUDIO_RING_BUFFER_SIGNAL (buf);
931
932   rclass = GST_AUDIO_RING_BUFFER_GET_CLASS (buf);
933   if (G_LIKELY (rclass->pause))
934     res = rclass->pause (buf);
935
936   if (G_UNLIKELY (!res)) {
937     buf->state = GST_AUDIO_RING_BUFFER_STATE_STARTED;
938     GST_DEBUG_OBJECT (buf, "failed to pause");
939   } else {
940     GST_DEBUG_OBJECT (buf, "paused");
941   }
942
943   return res;
944
945 not_started:
946   {
947     /* was not started */
948     GST_DEBUG_OBJECT (buf, "was not started");
949     return TRUE;
950   }
951 }
952
953 /**
954  * gst_audio_ring_buffer_pause:
955  * @buf: the #GstAudioRingBuffer to pause
956  *
957  * Pause processing samples from the ringbuffer.
958  *
959  * Returns: TRUE if the device could be paused, FALSE on error.
960  *
961  * MT safe.
962  */
963 gboolean
964 gst_audio_ring_buffer_pause (GstAudioRingBuffer * buf)
965 {
966   gboolean res = FALSE;
967
968   g_return_val_if_fail (GST_IS_AUDIO_RING_BUFFER (buf), FALSE);
969
970   GST_OBJECT_LOCK (buf);
971   if (G_UNLIKELY (buf->flushing))
972     goto flushing;
973
974   if (G_UNLIKELY (!buf->acquired))
975     goto not_acquired;
976
977   res = gst_audio_ring_buffer_pause_unlocked (buf);
978   GST_OBJECT_UNLOCK (buf);
979
980   return res;
981
982   /* ERRORS */
983 flushing:
984   {
985     GST_DEBUG_OBJECT (buf, "we are flushing");
986     GST_OBJECT_UNLOCK (buf);
987     return FALSE;
988   }
989 not_acquired:
990   {
991     GST_DEBUG_OBJECT (buf, "not acquired");
992     GST_OBJECT_UNLOCK (buf);
993     return FALSE;
994   }
995 }
996
997 /**
998  * gst_audio_ring_buffer_stop:
999  * @buf: the #GstAudioRingBuffer to stop
1000  *
1001  * Stop processing samples from the ringbuffer.
1002  *
1003  * Returns: TRUE if the device could be stopped, FALSE on error.
1004  *
1005  * MT safe.
1006  */
1007 gboolean
1008 gst_audio_ring_buffer_stop (GstAudioRingBuffer * buf)
1009 {
1010   gboolean res = FALSE;
1011   GstAudioRingBufferClass *rclass;
1012
1013   g_return_val_if_fail (GST_IS_AUDIO_RING_BUFFER (buf), FALSE);
1014
1015   GST_DEBUG_OBJECT (buf, "stopping");
1016
1017   GST_OBJECT_LOCK (buf);
1018
1019   /* if started, set to stopped */
1020   res = g_atomic_int_compare_and_exchange (&buf->state,
1021       GST_AUDIO_RING_BUFFER_STATE_STARTED, GST_AUDIO_RING_BUFFER_STATE_STOPPED);
1022
1023   if (!res) {
1024     GST_DEBUG_OBJECT (buf, "was not started, try paused");
1025     /* was not started, try from paused */
1026     res = g_atomic_int_compare_and_exchange (&buf->state,
1027         GST_AUDIO_RING_BUFFER_STATE_PAUSED,
1028         GST_AUDIO_RING_BUFFER_STATE_STOPPED);
1029     if (!res) {
1030       /* was not paused either, must have been stopped then */
1031       res = TRUE;
1032       GST_DEBUG_OBJECT (buf, "was not paused, must have been stopped");
1033       goto done;
1034     }
1035   }
1036
1037   /* signal any waiters */
1038   GST_DEBUG_OBJECT (buf, "signal waiter");
1039   GST_AUDIO_RING_BUFFER_SIGNAL (buf);
1040
1041   rclass = GST_AUDIO_RING_BUFFER_GET_CLASS (buf);
1042   if (G_LIKELY (rclass->stop))
1043     res = rclass->stop (buf);
1044
1045   if (G_UNLIKELY (!res)) {
1046     buf->state = GST_AUDIO_RING_BUFFER_STATE_STARTED;
1047     GST_DEBUG_OBJECT (buf, "failed to stop");
1048   } else {
1049     GST_DEBUG_OBJECT (buf, "stopped");
1050   }
1051 done:
1052   GST_OBJECT_UNLOCK (buf);
1053
1054   return res;
1055 }
1056
1057 /**
1058  * gst_audio_ring_buffer_delay:
1059  * @buf: the #GstAudioRingBuffer to query
1060  *
1061  * Get the number of samples queued in the audio device. This is
1062  * usually less than the segment size but can be bigger when the
1063  * implementation uses another internal buffer between the audio
1064  * device.
1065  *
1066  * For playback ringbuffers this is the amount of samples transfered from the
1067  * ringbuffer to the device but still not played.
1068  *
1069  * For capture ringbuffers this is the amount of samples in the device that are
1070  * not yet transfered to the ringbuffer.
1071  *
1072  * Returns: The number of samples queued in the audio device.
1073  *
1074  * MT safe.
1075  */
1076 guint
1077 gst_audio_ring_buffer_delay (GstAudioRingBuffer * buf)
1078 {
1079   GstAudioRingBufferClass *rclass;
1080   guint res;
1081
1082   g_return_val_if_fail (GST_IS_AUDIO_RING_BUFFER (buf), 0);
1083
1084   /* buffer must be acquired */
1085   if (G_UNLIKELY (!gst_audio_ring_buffer_is_acquired (buf)))
1086     goto not_acquired;
1087
1088   rclass = GST_AUDIO_RING_BUFFER_GET_CLASS (buf);
1089   if (G_LIKELY (rclass->delay))
1090     res = rclass->delay (buf);
1091   else
1092     res = 0;
1093
1094   return res;
1095
1096 not_acquired:
1097   {
1098     GST_DEBUG_OBJECT (buf, "not acquired");
1099     return 0;
1100   }
1101 }
1102
1103 /**
1104  * gst_audio_ring_buffer_samples_done:
1105  * @buf: the #GstAudioRingBuffer to query
1106  *
1107  * Get the number of samples that were processed by the ringbuffer
1108  * since it was last started. This does not include the number of samples not
1109  * yet processed (see gst_audio_ring_buffer_delay()).
1110  *
1111  * Returns: The number of samples processed by the ringbuffer.
1112  *
1113  * MT safe.
1114  */
1115 guint64
1116 gst_audio_ring_buffer_samples_done (GstAudioRingBuffer * buf)
1117 {
1118   gint segdone;
1119   guint64 samples;
1120
1121   g_return_val_if_fail (GST_IS_AUDIO_RING_BUFFER (buf), 0);
1122
1123   /* get the amount of segments we processed */
1124   segdone = g_atomic_int_get (&buf->segdone);
1125
1126   /* convert to samples */
1127   samples = ((guint64) segdone) * buf->samples_per_seg;
1128
1129   return samples;
1130 }
1131
1132 /**
1133  * gst_audio_ring_buffer_set_sample:
1134  * @buf: the #GstAudioRingBuffer to use
1135  * @sample: the sample number to set
1136  *
1137  * Make sure that the next sample written to the device is
1138  * accounted for as being the @sample sample written to the
1139  * device. This value will be used in reporting the current
1140  * sample position of the ringbuffer.
1141  *
1142  * This function will also clear the buffer with silence.
1143  *
1144  * MT safe.
1145  */
1146 void
1147 gst_audio_ring_buffer_set_sample (GstAudioRingBuffer * buf, guint64 sample)
1148 {
1149   g_return_if_fail (GST_IS_AUDIO_RING_BUFFER (buf));
1150
1151   if (sample == -1)
1152     sample = 0;
1153
1154   if (G_UNLIKELY (buf->samples_per_seg == 0))
1155     return;
1156
1157   /* FIXME, we assume the ringbuffer can restart at a random 
1158    * position, round down to the beginning and keep track of
1159    * offset when calculating the processed samples. */
1160   buf->segbase = buf->segdone - sample / buf->samples_per_seg;
1161
1162   gst_audio_ring_buffer_clear_all (buf);
1163
1164   GST_DEBUG_OBJECT (buf, "set sample to %" G_GUINT64_FORMAT ", segbase %d",
1165       sample, buf->segbase);
1166 }
1167
1168 static void
1169 default_clear_all (GstAudioRingBuffer * buf)
1170 {
1171   gint i;
1172
1173   /* not fatal, we just are not negotiated yet */
1174   if (G_UNLIKELY (buf->spec.segtotal <= 0))
1175     return;
1176
1177   GST_DEBUG_OBJECT (buf, "clear all segments");
1178
1179   for (i = 0; i < buf->spec.segtotal; i++) {
1180     gst_audio_ring_buffer_clear (buf, i);
1181   }
1182 }
1183
1184 /**
1185  * gst_audio_ring_buffer_clear_all:
1186  * @buf: the #GstAudioRingBuffer to clear
1187  *
1188  * Fill the ringbuffer with silence.
1189  *
1190  * MT safe.
1191  */
1192 void
1193 gst_audio_ring_buffer_clear_all (GstAudioRingBuffer * buf)
1194 {
1195   GstAudioRingBufferClass *rclass;
1196
1197   g_return_if_fail (GST_IS_AUDIO_RING_BUFFER (buf));
1198
1199   rclass = GST_AUDIO_RING_BUFFER_GET_CLASS (buf);
1200
1201   if (G_LIKELY (rclass->clear_all))
1202     rclass->clear_all (buf);
1203 }
1204
1205
1206 static gboolean
1207 wait_segment (GstAudioRingBuffer * buf)
1208 {
1209   gint segments;
1210   gboolean wait = TRUE;
1211
1212   /* buffer must be started now or we deadlock since nobody is reading */
1213   if (G_UNLIKELY (g_atomic_int_get (&buf->state) !=
1214           GST_AUDIO_RING_BUFFER_STATE_STARTED)) {
1215     /* see if we are allowed to start it */
1216     if (G_UNLIKELY (g_atomic_int_get (&buf->may_start) == FALSE))
1217       goto no_start;
1218
1219     GST_DEBUG_OBJECT (buf, "start!");
1220     segments = g_atomic_int_get (&buf->segdone);
1221     gst_audio_ring_buffer_start (buf);
1222
1223     /* After starting, the writer may have wrote segments already and then we
1224      * don't need to wait anymore */
1225     if (G_LIKELY (g_atomic_int_get (&buf->segdone) != segments))
1226       wait = FALSE;
1227   }
1228
1229   /* take lock first, then update our waiting flag */
1230   GST_OBJECT_LOCK (buf);
1231   if (G_UNLIKELY (buf->flushing))
1232     goto flushing;
1233
1234   if (G_UNLIKELY (g_atomic_int_get (&buf->state) !=
1235           GST_AUDIO_RING_BUFFER_STATE_STARTED))
1236     goto not_started;
1237
1238   if (G_LIKELY (wait)) {
1239     if (g_atomic_int_compare_and_exchange (&buf->waiting, 0, 1)) {
1240       GST_DEBUG_OBJECT (buf, "waiting..");
1241       GST_AUDIO_RING_BUFFER_WAIT (buf);
1242
1243       if (G_UNLIKELY (buf->flushing))
1244         goto flushing;
1245
1246       if (G_UNLIKELY (g_atomic_int_get (&buf->state) !=
1247               GST_AUDIO_RING_BUFFER_STATE_STARTED))
1248         goto not_started;
1249     }
1250   }
1251   GST_OBJECT_UNLOCK (buf);
1252
1253   return TRUE;
1254
1255   /* ERROR */
1256 not_started:
1257   {
1258     g_atomic_int_compare_and_exchange (&buf->waiting, 1, 0);
1259     GST_DEBUG_OBJECT (buf, "stopped processing");
1260     GST_OBJECT_UNLOCK (buf);
1261     return FALSE;
1262   }
1263 flushing:
1264   {
1265     g_atomic_int_compare_and_exchange (&buf->waiting, 1, 0);
1266     GST_DEBUG_OBJECT (buf, "flushing");
1267     GST_OBJECT_UNLOCK (buf);
1268     return FALSE;
1269   }
1270 no_start:
1271   {
1272     GST_DEBUG_OBJECT (buf, "not allowed to start");
1273     return FALSE;
1274   }
1275 }
1276
1277 #define FWD_SAMPLES(s,se,d,de)                  \
1278 G_STMT_START {                                  \
1279   /* no rate conversion */                      \
1280   guint towrite = MIN (se + bpf - s, de - d);   \
1281   /* simple copy */                             \
1282   if (!skip)                                    \
1283     memcpy (d, s, towrite);                     \
1284   in_samples -= towrite / bpf;                  \
1285   out_samples -= towrite / bpf;                 \
1286   s += towrite;                                 \
1287   GST_DEBUG ("copy %u bytes", towrite);         \
1288 } G_STMT_END
1289
1290 /* in_samples >= out_samples, rate > 1.0 */
1291 #define FWD_UP_SAMPLES(s,se,d,de)               \
1292 G_STMT_START {                                  \
1293   guint8 *sb = s, *db = d;                      \
1294   while (s <= se && d < de) {                   \
1295     if (!skip)                                  \
1296       memcpy (d, s, bpf);                       \
1297     s += bpf;                                   \
1298     *accum += outr;                             \
1299     if ((*accum << 1) >= inr) {                 \
1300       *accum -= inr;                            \
1301       d += bpf;                                 \
1302     }                                           \
1303   }                                             \
1304   in_samples -= (s - sb)/bpf;                   \
1305   out_samples -= (d - db)/bpf;                  \
1306   GST_DEBUG ("fwd_up end %d/%d",*accum,*toprocess);     \
1307 } G_STMT_END
1308
1309 /* out_samples > in_samples, for rates smaller than 1.0 */
1310 #define FWD_DOWN_SAMPLES(s,se,d,de)             \
1311 G_STMT_START {                                  \
1312   guint8 *sb = s, *db = d;                      \
1313   while (s <= se && d < de) {                   \
1314     if (!skip)                                  \
1315       memcpy (d, s, bpf);                       \
1316     d += bpf;                                   \
1317     *accum += inr;                              \
1318     if ((*accum << 1) >= outr) {                \
1319       *accum -= outr;                           \
1320       s += bpf;                                 \
1321     }                                           \
1322   }                                             \
1323   in_samples -= (s - sb)/bpf;                   \
1324   out_samples -= (d - db)/bpf;                  \
1325   GST_DEBUG ("fwd_down end %d/%d",*accum,*toprocess);   \
1326 } G_STMT_END
1327
1328 #define REV_UP_SAMPLES(s,se,d,de)               \
1329 G_STMT_START {                                  \
1330   guint8 *sb = se, *db = d;                     \
1331   while (s <= se && d < de) {                   \
1332     if (!skip)                                  \
1333       memcpy (d, se, bpf);                      \
1334     se -= bpf;                                  \
1335     *accum += outr;                             \
1336     while (d < de && (*accum << 1) >= inr) {    \
1337       *accum -= inr;                            \
1338       d += bpf;                                 \
1339     }                                           \
1340   }                                             \
1341   in_samples -= (sb - se)/bpf;                  \
1342   out_samples -= (d - db)/bpf;                  \
1343   GST_DEBUG ("rev_up end %d/%d",*accum,*toprocess);     \
1344 } G_STMT_END
1345
1346 #define REV_DOWN_SAMPLES(s,se,d,de)             \
1347 G_STMT_START {                                  \
1348   guint8 *sb = se, *db = d;                     \
1349   while (s <= se && d < de) {                   \
1350     if (!skip)                                  \
1351       memcpy (d, se, bpf);                      \
1352     d += bpf;                                   \
1353     *accum += inr;                              \
1354     while (s <= se && (*accum << 1) >= outr) {  \
1355       *accum -= outr;                           \
1356       se -= bpf;                                \
1357     }                                           \
1358   }                                             \
1359   in_samples -= (sb - se)/bpf;                  \
1360   out_samples -= (d - db)/bpf;                  \
1361   GST_DEBUG ("rev_down end %d/%d",*accum,*toprocess);   \
1362 } G_STMT_END
1363
1364 static guint
1365 default_commit (GstAudioRingBuffer * buf, guint64 * sample,
1366     guchar * data, gint in_samples, gint out_samples, gint * accum)
1367 {
1368   gint segdone;
1369   gint segsize, segtotal, bpf, sps;
1370   guint8 *dest, *data_end;
1371   gint writeseg, sampleoff;
1372   gint *toprocess;
1373   gint inr, outr;
1374   gboolean reverse;
1375
1376   g_return_val_if_fail (buf->memory != NULL, -1);
1377   g_return_val_if_fail (data != NULL, -1);
1378
1379   dest = buf->memory;
1380   segsize = buf->spec.segsize;
1381   segtotal = buf->spec.segtotal;
1382   bpf = buf->spec.info.bpf;
1383   sps = buf->samples_per_seg;
1384
1385   reverse = out_samples < 0;
1386   out_samples = ABS (out_samples);
1387
1388   if (in_samples >= out_samples)
1389     toprocess = &in_samples;
1390   else
1391     toprocess = &out_samples;
1392
1393   inr = in_samples - 1;
1394   outr = out_samples - 1;
1395
1396   /* data_end points to the last sample we have to write, not past it. This is
1397    * needed to properly handle reverse playback: it points to the last sample. */
1398   data_end = data + (bpf * inr);
1399
1400   /* figure out the segment and the offset inside the segment where
1401    * the first sample should be written. */
1402   writeseg = *sample / sps;
1403   sampleoff = (*sample % sps) * bpf;
1404
1405   /* write out all samples */
1406   while (*toprocess > 0) {
1407     gint avail;
1408     guint8 *d, *d_end;
1409     gint ws;
1410     gboolean skip;
1411
1412     while (TRUE) {
1413       gint diff;
1414
1415       /* get the currently processed segment */
1416       segdone = g_atomic_int_get (&buf->segdone) - buf->segbase;
1417
1418       /* see how far away it is from the write segment */
1419       diff = writeseg - segdone;
1420
1421       GST_DEBUG
1422           ("pointer at %d, write to %d-%d, diff %d, segtotal %d, segsize %d, base %d",
1423           segdone, writeseg, sampleoff, diff, segtotal, segsize, buf->segbase);
1424
1425       /* segment too far ahead, writer too slow, we need to drop, hopefully UNLIKELY */
1426       if (G_UNLIKELY (diff < 0)) {
1427         /* we need to drop one segment at a time, pretend we wrote a
1428          * segment. */
1429         skip = TRUE;
1430         break;
1431       }
1432
1433       /* write segment is within writable range, we can break the loop and
1434        * start writing the data. */
1435       if (diff < segtotal) {
1436         skip = FALSE;
1437         break;
1438       }
1439
1440       /* else we need to wait for the segment to become writable. */
1441       if (!wait_segment (buf))
1442         goto not_started;
1443     }
1444
1445     /* we can write now */
1446     ws = writeseg % segtotal;
1447     avail = MIN (segsize - sampleoff, bpf * out_samples);
1448
1449     d = dest + (ws * segsize) + sampleoff;
1450     d_end = d + avail;
1451     *sample += avail / bpf;
1452
1453     GST_DEBUG_OBJECT (buf, "write @%p seg %d, sps %d, off %d, avail %d",
1454         dest + ws * segsize, ws, sps, sampleoff, avail);
1455
1456     if (G_LIKELY (inr == outr && !reverse)) {
1457       /* no rate conversion, simply copy samples */
1458       FWD_SAMPLES (data, data_end, d, d_end);
1459     } else if (!reverse) {
1460       if (inr >= outr)
1461         /* forward speed up */
1462         FWD_UP_SAMPLES (data, data_end, d, d_end);
1463       else
1464         /* forward slow down */
1465         FWD_DOWN_SAMPLES (data, data_end, d, d_end);
1466     } else {
1467       if (inr >= outr)
1468         /* reverse speed up */
1469         REV_UP_SAMPLES (data, data_end, d, d_end);
1470       else
1471         /* reverse slow down */
1472         REV_DOWN_SAMPLES (data, data_end, d, d_end);
1473     }
1474
1475     /* for the next iteration we write to the next segment at the beginning. */
1476     writeseg++;
1477     sampleoff = 0;
1478   }
1479   /* we consumed all samples here */
1480   data = data_end + bpf;
1481
1482 done:
1483   return inr - ((data_end - data) / bpf);
1484
1485   /* ERRORS */
1486 not_started:
1487   {
1488     GST_DEBUG_OBJECT (buf, "stopped processing");
1489     goto done;
1490   }
1491 }
1492
1493 /**
1494  * gst_audio_ring_buffer_commit:
1495  * @buf: the #GstAudioRingBuffer to commit
1496  * @sample: the sample position of the data
1497  * @data: the data to commit
1498  * @in_samples: the number of samples in the data to commit
1499  * @out_samples: the number of samples to write to the ringbuffer
1500  * @accum: accumulator for rate conversion.
1501  *
1502  * Commit @in_samples samples pointed to by @data to the ringbuffer @buf.
1503  *
1504  * @in_samples and @out_samples define the rate conversion to perform on the
1505  * samples in @data. For negative rates, @out_samples must be negative and
1506  * @in_samples positive.
1507  *
1508  * When @out_samples is positive, the first sample will be written at position @sample
1509  * in the ringbuffer. When @out_samples is negative, the last sample will be written to
1510  * @sample in reverse order.
1511  *
1512  * @out_samples does not need to be a multiple of the segment size of the ringbuffer
1513  * although it is recommended for optimal performance.
1514  *
1515  * @accum will hold a temporary accumulator used in rate conversion and should be
1516  * set to 0 when this function is first called. In case the commit operation is
1517  * interrupted, one can resume the processing by passing the previously returned
1518  * @accum value back to this function.
1519  *
1520  * MT safe.
1521  *
1522  * Returns: The number of samples written to the ringbuffer or -1 on error. The
1523  * number of samples written can be less than @out_samples when @buf was interrupted
1524  * with a flush or stop.
1525  *
1526  * Since: 0.10.11.
1527  */
1528 guint
1529 gst_audio_ring_buffer_commit (GstAudioRingBuffer * buf, guint64 * sample,
1530     guchar * data, gint in_samples, gint out_samples, gint * accum)
1531 {
1532   GstAudioRingBufferClass *rclass;
1533   guint res = -1;
1534
1535   g_return_val_if_fail (GST_IS_AUDIO_RING_BUFFER (buf), -1);
1536
1537   if (G_UNLIKELY (in_samples == 0 || out_samples == 0))
1538     return in_samples;
1539
1540   rclass = GST_AUDIO_RING_BUFFER_GET_CLASS (buf);
1541
1542   if (G_LIKELY (rclass->commit))
1543     res = rclass->commit (buf, sample, data, in_samples, out_samples, accum);
1544
1545   return res;
1546 }
1547
1548 /**
1549  * gst_audio_ring_buffer_read:
1550  * @buf: the #GstAudioRingBuffer to read from
1551  * @sample: the sample position of the data
1552  * @data: where the data should be read
1553  * @len: the number of samples in data to read
1554  *
1555  * Read @len samples from the ringbuffer into the memory pointed 
1556  * to by @data.
1557  * The first sample should be read from position @sample in
1558  * the ringbuffer.
1559  *
1560  * @len should not be a multiple of the segment size of the ringbuffer
1561  * although it is recommended.
1562  *
1563  * Returns: The number of samples read from the ringbuffer or -1 on
1564  * error.
1565  *
1566  * MT safe.
1567  */
1568 guint
1569 gst_audio_ring_buffer_read (GstAudioRingBuffer * buf, guint64 sample,
1570     guchar * data, guint len)
1571 {
1572   gint segdone;
1573   gint segsize, segtotal, bpf, sps;
1574   guint8 *dest;
1575   guint to_read;
1576
1577   g_return_val_if_fail (GST_IS_AUDIO_RING_BUFFER (buf), -1);
1578   g_return_val_if_fail (buf->memory != NULL, -1);
1579   g_return_val_if_fail (data != NULL, -1);
1580
1581   dest = buf->memory;
1582   segsize = buf->spec.segsize;
1583   segtotal = buf->spec.segtotal;
1584   bpf = buf->spec.info.bpf;
1585   sps = buf->samples_per_seg;
1586
1587   to_read = len;
1588   /* read enough samples */
1589   while (to_read > 0) {
1590     gint sampleslen;
1591     gint readseg, sampleoff;
1592
1593     /* figure out the segment and the offset inside the segment where
1594      * the sample should be read from. */
1595     readseg = sample / sps;
1596     sampleoff = (sample % sps);
1597
1598     while (TRUE) {
1599       gint diff;
1600
1601       /* get the currently processed segment */
1602       segdone = g_atomic_int_get (&buf->segdone) - buf->segbase;
1603
1604       /* see how far away it is from the read segment, normally segdone (where
1605        * the hardware is writing) is bigger than readseg (where software is
1606        * reading) */
1607       diff = segdone - readseg;
1608
1609       GST_DEBUG
1610           ("pointer at %d, sample %" G_GUINT64_FORMAT
1611           ", read from %d-%d, to_read %d, diff %d, segtotal %d, segsize %d",
1612           segdone, sample, readseg, sampleoff, to_read, diff, segtotal,
1613           segsize);
1614
1615       /* segment too far ahead, reader too slow */
1616       if (G_UNLIKELY (diff >= segtotal)) {
1617         /* pretend we read an empty segment. */
1618         sampleslen = MIN (sps, to_read);
1619         memcpy (data, buf->empty_seg, sampleslen * bpf);
1620         goto next;
1621       }
1622
1623       /* read segment is within readable range, we can break the loop and
1624        * start reading the data. */
1625       if (diff > 0)
1626         break;
1627
1628       /* else we need to wait for the segment to become readable. */
1629       if (!wait_segment (buf))
1630         goto not_started;
1631     }
1632
1633     /* we can read now */
1634     readseg = readseg % segtotal;
1635     sampleslen = MIN (sps - sampleoff, to_read);
1636
1637     GST_DEBUG_OBJECT (buf, "read @%p seg %d, off %d, sampleslen %d",
1638         dest + readseg * segsize, readseg, sampleoff, sampleslen);
1639
1640     memcpy (data, dest + (readseg * segsize) + (sampleoff * bpf),
1641         (sampleslen * bpf));
1642
1643   next:
1644     to_read -= sampleslen;
1645     sample += sampleslen;
1646     data += sampleslen * bpf;
1647   }
1648
1649   return len - to_read;
1650
1651   /* ERRORS */
1652 not_started:
1653   {
1654     GST_DEBUG_OBJECT (buf, "stopped processing");
1655     return len - to_read;
1656   }
1657 }
1658
1659 /**
1660  * gst_audio_ring_buffer_prepare_read:
1661  * @buf: the #GstAudioRingBuffer to read from
1662  * @segment: the segment to read
1663  * @readptr: the pointer to the memory where samples can be read
1664  * @len: the number of bytes to read
1665  *
1666  * Returns a pointer to memory where the data from segment @segment
1667  * can be found. This function is mostly used by subclasses.
1668  *
1669  * Returns: FALSE if the buffer is not started.
1670  *
1671  * MT safe.
1672  */
1673 gboolean
1674 gst_audio_ring_buffer_prepare_read (GstAudioRingBuffer * buf, gint * segment,
1675     guint8 ** readptr, gint * len)
1676 {
1677   guint8 *data;
1678   gint segdone;
1679
1680   g_return_val_if_fail (GST_IS_AUDIO_RING_BUFFER (buf), FALSE);
1681
1682   if (buf->callback == NULL) {
1683     /* push mode, fail when nothing is started */
1684     if (g_atomic_int_get (&buf->state) != GST_AUDIO_RING_BUFFER_STATE_STARTED)
1685       return FALSE;
1686   }
1687
1688   g_return_val_if_fail (buf->memory != NULL, FALSE);
1689   g_return_val_if_fail (segment != NULL, FALSE);
1690   g_return_val_if_fail (readptr != NULL, FALSE);
1691   g_return_val_if_fail (len != NULL, FALSE);
1692
1693   data = buf->memory;
1694
1695   /* get the position of the pointer */
1696   segdone = g_atomic_int_get (&buf->segdone);
1697
1698   *segment = segdone % buf->spec.segtotal;
1699   *len = buf->spec.segsize;
1700   *readptr = data + *segment * *len;
1701
1702   GST_LOG ("prepare read from segment %d (real %d) @%p",
1703       *segment, segdone, *readptr);
1704
1705   /* callback to fill the memory with data, for pull based
1706    * scheduling. */
1707   if (buf->callback)
1708     buf->callback (buf, *readptr, *len, buf->cb_data);
1709
1710   return TRUE;
1711 }
1712
1713 /**
1714  * gst_audio_ring_buffer_advance:
1715  * @buf: the #GstAudioRingBuffer to advance
1716  * @advance: the number of segments written
1717  *
1718  * Subclasses should call this function to notify the fact that 
1719  * @advance segments are now processed by the device.
1720  *
1721  * MT safe.
1722  */
1723 void
1724 gst_audio_ring_buffer_advance (GstAudioRingBuffer * buf, guint advance)
1725 {
1726   g_return_if_fail (GST_IS_AUDIO_RING_BUFFER (buf));
1727
1728   /* update counter */
1729   g_atomic_int_add (&buf->segdone, advance);
1730
1731   /* the lock is already taken when the waiting flag is set,
1732    * we grab the lock as well to make sure the waiter is actually
1733    * waiting for the signal */
1734   if (g_atomic_int_compare_and_exchange (&buf->waiting, 1, 0)) {
1735     GST_OBJECT_LOCK (buf);
1736     GST_DEBUG_OBJECT (buf, "signal waiter");
1737     GST_AUDIO_RING_BUFFER_SIGNAL (buf);
1738     GST_OBJECT_UNLOCK (buf);
1739   }
1740 }
1741
1742 /**
1743  * gst_audio_ring_buffer_clear:
1744  * @buf: the #GstAudioRingBuffer to clear
1745  * @segment: the segment to clear
1746  *
1747  * Clear the given segment of the buffer with silence samples.
1748  * This function is used by subclasses.
1749  *
1750  * MT safe.
1751  */
1752 void
1753 gst_audio_ring_buffer_clear (GstAudioRingBuffer * buf, gint segment)
1754 {
1755   guint8 *data;
1756
1757   g_return_if_fail (GST_IS_AUDIO_RING_BUFFER (buf));
1758
1759   /* no data means it's already cleared */
1760   if (G_UNLIKELY (buf->memory == NULL))
1761     return;
1762
1763   /* no empty_seg means it's not opened */
1764   if (G_UNLIKELY (buf->empty_seg == NULL))
1765     return;
1766
1767   segment %= buf->spec.segtotal;
1768
1769   data = buf->memory;
1770   data += segment * buf->spec.segsize;
1771
1772   GST_LOG ("clear segment %d @%p", segment, data);
1773
1774   memcpy (data, buf->empty_seg, buf->spec.segsize);
1775 }
1776
1777 /**
1778  * gst_audio_ring_buffer_may_start:
1779  * @buf: the #GstAudioRingBuffer
1780  * @allowed: the new value
1781  *
1782  * Tell the ringbuffer that it is allowed to start playback when
1783  * the ringbuffer is filled with samples. 
1784  *
1785  * MT safe.
1786  *
1787  * Since: 0.10.6
1788  */
1789 void
1790 gst_audio_ring_buffer_may_start (GstAudioRingBuffer * buf, gboolean allowed)
1791 {
1792   g_return_if_fail (GST_IS_AUDIO_RING_BUFFER (buf));
1793
1794   GST_LOG_OBJECT (buf, "may start: %d", allowed);
1795   g_atomic_int_set (&buf->may_start, allowed);
1796 }