move last template doc snippets to source code and delete them
[platform/upstream/gstreamer.git] / gst-libs / gst / audio / gstringbuffer.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:gstringbuffer
22  * @short_description: Base class for audio ringbuffer implementations
23  * @see_also: gstbaseaudiosink
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 "gstringbuffer.h"
45
46 GST_DEBUG_CATEGORY_STATIC (gst_ring_buffer_debug);
47 #define GST_CAT_DEFAULT gst_ring_buffer_debug
48
49 static void gst_ring_buffer_class_init (GstRingBufferClass * klass);
50 static void gst_ring_buffer_init (GstRingBuffer * ringbuffer);
51 static void gst_ring_buffer_dispose (GObject * object);
52 static void gst_ring_buffer_finalize (GObject * object);
53
54 static gboolean gst_ring_buffer_pause_unlocked (GstRingBuffer * buf);
55
56 static GstObjectClass *parent_class = NULL;
57
58 /* ringbuffer abstract base class */
59 GType
60 gst_ring_buffer_get_type (void)
61 {
62   static GType ringbuffer_type = 0;
63
64   if (G_UNLIKELY (!ringbuffer_type)) {
65     static const GTypeInfo ringbuffer_info = {
66       sizeof (GstRingBufferClass),
67       NULL,
68       NULL,
69       (GClassInitFunc) gst_ring_buffer_class_init,
70       NULL,
71       NULL,
72       sizeof (GstRingBuffer),
73       0,
74       (GInstanceInitFunc) gst_ring_buffer_init,
75       NULL
76     };
77
78     ringbuffer_type = g_type_register_static (GST_TYPE_OBJECT, "GstRingBuffer",
79         &ringbuffer_info, G_TYPE_FLAG_ABSTRACT);
80
81     GST_DEBUG_CATEGORY_INIT (gst_ring_buffer_debug, "ringbuffer", 0,
82         "ringbuffer class");
83   }
84   return ringbuffer_type;
85 }
86
87 static void
88 gst_ring_buffer_class_init (GstRingBufferClass * klass)
89 {
90   GObjectClass *gobject_class;
91   GstObjectClass *gstobject_class;
92
93   gobject_class = (GObjectClass *) klass;
94   gstobject_class = (GstObjectClass *) klass;
95
96   parent_class = g_type_class_peek_parent (klass);
97
98   gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_ring_buffer_dispose);
99   gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_ring_buffer_finalize);
100 }
101
102 static void
103 gst_ring_buffer_init (GstRingBuffer * ringbuffer)
104 {
105   ringbuffer->open = FALSE;
106   ringbuffer->acquired = FALSE;
107   ringbuffer->state = GST_RING_BUFFER_STATE_STOPPED;
108   ringbuffer->cond = g_cond_new ();
109   ringbuffer->waiting = 0;
110   ringbuffer->empty_seg = NULL;
111   ringbuffer->abidata.ABI.flushing = TRUE;
112 }
113
114 static void
115 gst_ring_buffer_dispose (GObject * object)
116 {
117   GstRingBuffer *ringbuffer = GST_RING_BUFFER (object);
118
119   G_OBJECT_CLASS (parent_class)->dispose (G_OBJECT (ringbuffer));
120 }
121
122 static void
123 gst_ring_buffer_finalize (GObject * object)
124 {
125   GstRingBuffer *ringbuffer = GST_RING_BUFFER (object);
126
127   g_cond_free (ringbuffer->cond);
128   g_free (ringbuffer->empty_seg);
129
130   G_OBJECT_CLASS (parent_class)->finalize (G_OBJECT (ringbuffer));
131 }
132
133 static const int linear_formats[4 * 2 * 2] = {
134   GST_S8,
135   GST_S8,
136   GST_U8,
137   GST_U8,
138   GST_S16_LE,
139   GST_S16_BE,
140   GST_U16_LE,
141   GST_U16_BE,
142   GST_S24_LE,
143   GST_S24_BE,
144   GST_U24_LE,
145   GST_U24_BE,
146   GST_S32_LE,
147   GST_S32_BE,
148   GST_U32_LE,
149   GST_U32_BE
150 };
151
152 static const int linear24_formats[3 * 2 * 2] = {
153   GST_S24_3LE,
154   GST_S24_3BE,
155   GST_U24_3LE,
156   GST_U24_3BE,
157   GST_S20_3LE,
158   GST_S20_3BE,
159   GST_U20_3LE,
160   GST_U20_3BE,
161   GST_S18_3LE,
162   GST_S18_3BE,
163   GST_U18_3LE,
164   GST_U18_3BE,
165 };
166
167 static GstBufferFormat
168 build_linear_format (int depth, int width, int unsignd, int big_endian)
169 {
170   const gint *formats;
171
172   if (width == 24) {
173     switch (depth) {
174       case 24:
175         formats = &linear24_formats[0];
176         break;
177       case 20:
178         formats = &linear24_formats[4];
179         break;
180       case 18:
181         formats = &linear24_formats[8];
182         break;
183       default:
184         return GST_UNKNOWN;
185     }
186   } else {
187     switch (depth) {
188       case 8:
189         formats = &linear_formats[0];
190         break;
191       case 16:
192         formats = &linear_formats[4];
193         break;
194       case 24:
195         formats = &linear_formats[8];
196         break;
197       case 32:
198         formats = &linear_formats[12];
199         break;
200       default:
201         return GST_UNKNOWN;
202     }
203   }
204   if (unsignd)
205     formats += 2;
206   if (big_endian)
207     formats += 1;
208   return (GstBufferFormat) * formats;
209 }
210
211 /**
212  * gst_ring_buffer_debug_spec_caps:
213  * @spec: the spec to debug
214  *
215  * Print debug info about the parsed caps in @spec to the debug log.
216  */
217 void
218 gst_ring_buffer_debug_spec_caps (GstRingBufferSpec * spec)
219 {
220   GST_DEBUG ("spec caps: %p %" GST_PTR_FORMAT, spec->caps, spec->caps);
221   GST_DEBUG ("parsed caps: type:         %d", spec->type);
222   GST_DEBUG ("parsed caps: format:       %d", spec->format);
223   GST_DEBUG ("parsed caps: width:        %d", spec->width);
224   GST_DEBUG ("parsed caps: depth:        %d", spec->depth);
225   GST_DEBUG ("parsed caps: sign:         %d", spec->sign);
226   GST_DEBUG ("parsed caps: bigend:       %d", spec->bigend);
227   GST_DEBUG ("parsed caps: rate:         %d", spec->rate);
228   GST_DEBUG ("parsed caps: channels:     %d", spec->channels);
229   GST_DEBUG ("parsed caps: sample bytes: %d", spec->bytes_per_sample);
230 }
231
232 /**
233  * gst_ring_buffer_debug_spec_buff:
234  * @spec: the spec to debug
235  *
236  * Print debug info about the buffer sized in @spec to the debug log.
237  */
238 void
239 gst_ring_buffer_debug_spec_buff (GstRingBufferSpec * spec)
240 {
241   GST_DEBUG ("acquire ringbuffer: buffer time: %" G_GINT64_FORMAT " usec",
242       spec->buffer_time);
243   GST_DEBUG ("acquire ringbuffer: latency time: %" G_GINT64_FORMAT " usec",
244       spec->latency_time);
245   GST_DEBUG ("acquire ringbuffer: total segments: %d", spec->segtotal);
246   GST_DEBUG ("acquire ringbuffer: segment size: %d bytes = %d samples",
247       spec->segsize, spec->segsize / spec->bytes_per_sample);
248   GST_DEBUG ("acquire ringbuffer: buffer size: %d bytes = %d samples",
249       spec->segsize * spec->segtotal,
250       spec->segsize * spec->segtotal / spec->bytes_per_sample);
251 }
252
253 /**
254  * gst_ring_buffer_parse_caps:
255  * @spec: a spec
256  * @caps: a #GstCaps
257  *
258  * Parse @caps into @spec.
259  *
260  * Returns: TRUE if the caps could be parsed.
261  */
262 gboolean
263 gst_ring_buffer_parse_caps (GstRingBufferSpec * spec, GstCaps * caps)
264 {
265   const gchar *mimetype;
266   GstStructure *structure;
267
268   structure = gst_caps_get_structure (caps, 0);
269
270   /* we have to differentiate between int and float formats */
271   mimetype = gst_structure_get_name (structure);
272
273   if (!strncmp (mimetype, "audio/x-raw-int", 15)) {
274     gint endianness;
275
276     spec->type = GST_BUFTYPE_LINEAR;
277
278     /* extract the needed information from the cap */
279     if (!(gst_structure_get_int (structure, "width", &spec->width) &&
280             gst_structure_get_int (structure, "depth", &spec->depth) &&
281             gst_structure_get_boolean (structure, "signed", &spec->sign)))
282       goto parse_error;
283
284     /* extract endianness if needed */
285     if (spec->width > 8) {
286       if (!gst_structure_get_int (structure, "endianness", &endianness))
287         goto parse_error;
288     } else {
289       endianness = G_BYTE_ORDER;
290     }
291
292     spec->bigend = endianness == G_LITTLE_ENDIAN ? FALSE : TRUE;
293
294     spec->format =
295         build_linear_format (spec->depth, spec->width, spec->sign ? 0 : 1,
296         spec->bigend ? 1 : 0);
297   } else if (!strncmp (mimetype, "audio/x-raw-float", 17)) {
298
299     spec->type = GST_BUFTYPE_FLOAT;
300
301     /* get layout */
302     if (!gst_structure_get_int (structure, "width", &spec->width))
303       goto parse_error;
304
305     /* match layout to format wrt to endianness */
306     switch (spec->width) {
307       case 32:
308         spec->format =
309             G_BYTE_ORDER == G_LITTLE_ENDIAN ? GST_FLOAT32_LE : GST_FLOAT32_BE;
310         break;
311       case 64:
312         spec->format =
313             G_BYTE_ORDER == G_LITTLE_ENDIAN ? GST_FLOAT64_LE : GST_FLOAT64_BE;
314         break;
315       default:
316         goto parse_error;
317     }
318   } else if (!strncmp (mimetype, "audio/x-alaw", 12)) {
319     spec->type = GST_BUFTYPE_A_LAW;
320     spec->format = GST_A_LAW;
321     spec->width = 8;
322     spec->depth = 8;
323   } else if (!strncmp (mimetype, "audio/x-mulaw", 13)) {
324     spec->type = GST_BUFTYPE_MU_LAW;
325     spec->format = GST_MU_LAW;
326     spec->width = 8;
327     spec->depth = 8;
328   } else {
329     goto parse_error;
330   }
331
332   /* get rate and channels */
333   if (!(gst_structure_get_int (structure, "rate", &spec->rate) &&
334           gst_structure_get_int (structure, "channels", &spec->channels)))
335     goto parse_error;
336
337   spec->bytes_per_sample = (spec->width >> 3) * spec->channels;
338
339   gst_caps_replace (&spec->caps, caps);
340
341   g_return_val_if_fail (spec->latency_time != 0, FALSE);
342
343   /* calculate suggested segsize and segtotal. segsize should be one unit
344    * of 'latency_time' samples, scaling for the fact that latency_time is
345    * currently stored in microseconds (FIXME: in 0.11) */
346   spec->segsize = gst_util_uint64_scale (spec->rate * spec->bytes_per_sample,
347       spec->latency_time, GST_SECOND / GST_USECOND);
348   /* Round to an integer number of samples */
349   spec->segsize -= spec->segsize % spec->bytes_per_sample;
350
351   spec->segtotal = spec->buffer_time / spec->latency_time;
352
353   gst_ring_buffer_debug_spec_caps (spec);
354   gst_ring_buffer_debug_spec_buff (spec);
355
356   return TRUE;
357
358   /* ERRORS */
359 parse_error:
360   {
361     GST_DEBUG ("could not parse caps");
362     return FALSE;
363   }
364 }
365
366 /**
367  * gst_ring_buffer_set_callback:
368  * @buf: the #GstRingBuffer to set the callback on
369  * @cb: the callback to set
370  * @user_data: user data passed to the callback
371  *
372  * Sets the given callback function on the buffer. This function
373  * will be called every time a segment has been written to a device.
374  *
375  * MT safe.
376  */
377 void
378 gst_ring_buffer_set_callback (GstRingBuffer * buf, GstRingBufferCallback cb,
379     gpointer user_data)
380 {
381   g_return_if_fail (GST_IS_RING_BUFFER (buf));
382
383   GST_OBJECT_LOCK (buf);
384   buf->callback = cb;
385   buf->cb_data = user_data;
386   GST_OBJECT_UNLOCK (buf);
387 }
388
389
390 /**
391  * gst_ring_buffer_open_device:
392  * @buf: the #GstRingBuffer
393  *
394  * Open the audio device associated with the ring buffer. Does not perform any
395  * setup on the device. You must open the device before acquiring the ring
396  * buffer.
397  *
398  * Returns: TRUE if the device could be opened, FALSE on error.
399  *
400  * MT safe.
401  */
402 gboolean
403 gst_ring_buffer_open_device (GstRingBuffer * buf)
404 {
405   gboolean res = TRUE;
406   GstRingBufferClass *rclass;
407
408   g_return_val_if_fail (GST_IS_RING_BUFFER (buf), FALSE);
409
410   GST_DEBUG_OBJECT (buf, "opening device");
411
412   GST_OBJECT_LOCK (buf);
413   if (G_UNLIKELY (buf->open))
414     goto was_opened;
415
416   buf->open = TRUE;
417
418   /* if this fails, something is wrong in this file */
419   g_assert (!buf->acquired);
420
421   rclass = GST_RING_BUFFER_GET_CLASS (buf);
422   if (G_LIKELY (rclass->open_device))
423     res = rclass->open_device (buf);
424
425   if (G_UNLIKELY (!res))
426     goto open_failed;
427
428   GST_DEBUG_OBJECT (buf, "opened device");
429
430 done:
431   GST_OBJECT_UNLOCK (buf);
432
433   return res;
434
435   /* ERRORS */
436 was_opened:
437   {
438     GST_DEBUG_OBJECT (buf, "Device for ring buffer already open");
439     g_warning ("Device for ring buffer %p already open, fix your code", buf);
440     res = TRUE;
441     goto done;
442   }
443 open_failed:
444   {
445     buf->open = FALSE;
446     GST_DEBUG_OBJECT (buf, "failed opening device");
447     goto done;
448   }
449 }
450
451 /**
452  * gst_ring_buffer_close_device:
453  * @buf: the #GstRingBuffer
454  *
455  * Close the audio device associated with the ring buffer. The ring buffer
456  * should already have been released via gst_ring_buffer_release().
457  *
458  * Returns: TRUE if the device could be closed, FALSE on error.
459  *
460  * MT safe.
461  */
462 gboolean
463 gst_ring_buffer_close_device (GstRingBuffer * buf)
464 {
465   gboolean res = TRUE;
466   GstRingBufferClass *rclass;
467
468   g_return_val_if_fail (GST_IS_RING_BUFFER (buf), FALSE);
469
470   GST_DEBUG_OBJECT (buf, "closing device");
471
472   GST_OBJECT_LOCK (buf);
473   if (G_UNLIKELY (!buf->open))
474     goto was_closed;
475
476   if (G_UNLIKELY (buf->acquired))
477     goto was_acquired;
478
479   buf->open = FALSE;
480
481   rclass = GST_RING_BUFFER_GET_CLASS (buf);
482   if (G_LIKELY (rclass->close_device))
483     res = rclass->close_device (buf);
484
485   if (G_UNLIKELY (!res))
486     goto close_error;
487
488   GST_DEBUG_OBJECT (buf, "closed device");
489
490 done:
491   GST_OBJECT_UNLOCK (buf);
492
493   return res;
494
495   /* ERRORS */
496 was_closed:
497   {
498     GST_DEBUG_OBJECT (buf, "Device for ring buffer already closed");
499     g_warning ("Device for ring buffer %p already closed, fix your code", buf);
500     res = TRUE;
501     goto done;
502   }
503 was_acquired:
504   {
505     GST_DEBUG_OBJECT (buf, "Resources for ring buffer still acquired");
506     g_critical ("Resources for ring buffer %p still acquired", buf);
507     res = FALSE;
508     goto done;
509   }
510 close_error:
511   {
512     buf->open = TRUE;
513     GST_DEBUG_OBJECT (buf, "error closing device");
514     goto done;
515   }
516 }
517
518 /**
519  * gst_ring_buffer_device_is_open:
520  * @buf: the #GstRingBuffer
521  *
522  * Checks the status of the device associated with the ring buffer.
523  *
524  * Returns: TRUE if the device was open, FALSE if it was closed.
525  *
526  * MT safe.
527  */
528 gboolean
529 gst_ring_buffer_device_is_open (GstRingBuffer * buf)
530 {
531   gboolean res = TRUE;
532
533   g_return_val_if_fail (GST_IS_RING_BUFFER (buf), FALSE);
534
535   GST_OBJECT_LOCK (buf);
536   res = buf->open;
537   GST_OBJECT_UNLOCK (buf);
538
539   return res;
540 }
541
542
543 /**
544  * gst_ring_buffer_acquire:
545  * @buf: the #GstRingBuffer to acquire
546  * @spec: the specs of the buffer
547  *
548  * Allocate the resources for the ringbuffer. This function fills
549  * in the data pointer of the ring buffer with a valid #GstBuffer
550  * to which samples can be written.
551  *
552  * Returns: TRUE if the device could be acquired, FALSE on error.
553  *
554  * MT safe.
555  */
556 gboolean
557 gst_ring_buffer_acquire (GstRingBuffer * buf, GstRingBufferSpec * spec)
558 {
559   gboolean res = FALSE;
560   GstRingBufferClass *rclass;
561   gint i, j;
562   gint segsize, bps;
563
564   g_return_val_if_fail (GST_IS_RING_BUFFER (buf), FALSE);
565
566   GST_DEBUG_OBJECT (buf, "acquiring device");
567
568   GST_OBJECT_LOCK (buf);
569   if (G_UNLIKELY (!buf->open))
570     goto not_opened;
571
572   if (G_UNLIKELY (buf->acquired))
573     goto was_acquired;
574
575   buf->acquired = TRUE;
576
577   rclass = GST_RING_BUFFER_GET_CLASS (buf);
578   if (G_LIKELY (rclass->acquire))
579     res = rclass->acquire (buf, spec);
580
581   if (G_UNLIKELY (!res))
582     goto acquire_failed;
583
584   if (G_UNLIKELY ((bps = buf->spec.bytes_per_sample) == 0))
585     goto invalid_bps;
586
587   segsize = buf->spec.segsize;
588
589   buf->samples_per_seg = segsize / bps;
590
591   /* create an empty segment */
592   g_free (buf->empty_seg);
593   buf->empty_seg = g_malloc (segsize);
594   for (i = 0, j = 0; i < segsize; i++) {
595     buf->empty_seg[i] = buf->spec.silence_sample[j];
596     j = (j + 1) % bps;
597   }
598   GST_DEBUG_OBJECT (buf, "acquired device");
599
600 done:
601   GST_OBJECT_UNLOCK (buf);
602
603   return res;
604
605   /* ERRORS */
606 not_opened:
607   {
608     GST_DEBUG_OBJECT (buf, "device not opened");
609     g_critical ("Device for %p not opened", buf);
610     res = FALSE;
611     goto done;
612   }
613 was_acquired:
614   {
615     res = TRUE;
616     GST_DEBUG_OBJECT (buf, "device was acquired");
617     goto done;
618   }
619 acquire_failed:
620   {
621     buf->acquired = FALSE;
622     GST_DEBUG_OBJECT (buf, "failed to acquire device");
623     goto done;
624   }
625 invalid_bps:
626   {
627     g_warning
628         ("invalid bytes_per_sample from acquire ringbuffer, fix the element");
629     buf->acquired = FALSE;
630     res = FALSE;
631     goto done;
632   }
633 }
634
635 /**
636  * gst_ring_buffer_release:
637  * @buf: the #GstRingBuffer to release
638  *
639  * Free the resources of the ringbuffer.
640  *
641  * Returns: TRUE if the device could be released, FALSE on error.
642  *
643  * MT safe.
644  */
645 gboolean
646 gst_ring_buffer_release (GstRingBuffer * buf)
647 {
648   gboolean res = FALSE;
649   GstRingBufferClass *rclass;
650
651   g_return_val_if_fail (GST_IS_RING_BUFFER (buf), FALSE);
652
653   GST_DEBUG_OBJECT (buf, "releasing device");
654
655   gst_ring_buffer_stop (buf);
656
657   GST_OBJECT_LOCK (buf);
658   if (G_UNLIKELY (!buf->acquired))
659     goto was_released;
660
661   buf->acquired = FALSE;
662
663   /* if this fails, something is wrong in this file */
664   g_assert (buf->open == TRUE);
665
666   rclass = GST_RING_BUFFER_GET_CLASS (buf);
667   if (G_LIKELY (rclass->release))
668     res = rclass->release (buf);
669
670   /* signal any waiters */
671   GST_DEBUG_OBJECT (buf, "signal waiter");
672   GST_RING_BUFFER_SIGNAL (buf);
673
674   if (G_UNLIKELY (!res))
675     goto release_failed;
676
677   g_free (buf->empty_seg);
678   buf->empty_seg = NULL;
679   GST_DEBUG_OBJECT (buf, "released device");
680
681 done:
682   GST_OBJECT_UNLOCK (buf);
683
684   return res;
685
686   /* ERRORS */
687 was_released:
688   {
689     res = TRUE;
690     GST_DEBUG_OBJECT (buf, "device was released");
691     goto done;
692   }
693 release_failed:
694   {
695     buf->acquired = TRUE;
696     GST_DEBUG_OBJECT (buf, "failed to release device");
697     goto done;
698   }
699 }
700
701 /**
702  * gst_ring_buffer_is_acquired:
703  * @buf: the #GstRingBuffer to check
704  *
705  * Check if the ringbuffer is acquired and ready to use.
706  *
707  * Returns: TRUE if the ringbuffer is acquired, FALSE on error.
708  *
709  * MT safe.
710  */
711 gboolean
712 gst_ring_buffer_is_acquired (GstRingBuffer * buf)
713 {
714   gboolean res;
715
716   g_return_val_if_fail (GST_IS_RING_BUFFER (buf), FALSE);
717
718   GST_OBJECT_LOCK (buf);
719   res = buf->acquired;
720   GST_OBJECT_UNLOCK (buf);
721
722   return res;
723 }
724
725 /**
726  * gst_ring_buffer_set_flushing:
727  * @buf: the #GstRingBuffer to flush
728  *
729  * Set the ringbuffer to flushing mode or normal mode.
730  *
731  * MT safe.
732  */
733 void
734 gst_ring_buffer_set_flushing (GstRingBuffer * buf, gboolean flushing)
735 {
736   g_return_if_fail (GST_IS_RING_BUFFER (buf));
737
738   GST_OBJECT_LOCK (buf);
739   buf->abidata.ABI.flushing = flushing;
740
741   gst_ring_buffer_clear_all (buf);
742   if (flushing) {
743     gst_ring_buffer_pause_unlocked (buf);
744   }
745   GST_OBJECT_UNLOCK (buf);
746 }
747
748 /**
749  * gst_ring_buffer_start:
750  * @buf: the #GstRingBuffer to start
751  *
752  * Start processing samples from the ringbuffer.
753  *
754  * Returns: TRUE if the device could be started, FALSE on error.
755  *
756  * MT safe.
757  */
758 gboolean
759 gst_ring_buffer_start (GstRingBuffer * buf)
760 {
761   gboolean res = FALSE;
762   GstRingBufferClass *rclass;
763   gboolean resume = FALSE;
764
765   g_return_val_if_fail (GST_IS_RING_BUFFER (buf), FALSE);
766
767   GST_DEBUG_OBJECT (buf, "starting ringbuffer");
768
769   GST_OBJECT_LOCK (buf);
770   if (G_UNLIKELY (buf->abidata.ABI.flushing))
771     goto flushing;
772
773   /* if stopped, set to started */
774   res = g_atomic_int_compare_and_exchange (&buf->state,
775       GST_RING_BUFFER_STATE_STOPPED, GST_RING_BUFFER_STATE_STARTED);
776
777   if (!res) {
778     /* was not stopped, try from paused */
779     res = g_atomic_int_compare_and_exchange (&buf->state,
780         GST_RING_BUFFER_STATE_PAUSED, GST_RING_BUFFER_STATE_STARTED);
781     if (!res) {
782       /* was not paused either, must be started then */
783       res = TRUE;
784       GST_DEBUG_OBJECT (buf, "was started");
785       goto done;
786     }
787     resume = TRUE;
788     GST_DEBUG_OBJECT (buf, "resuming");
789   }
790
791   rclass = GST_RING_BUFFER_GET_CLASS (buf);
792   if (resume) {
793     if (G_LIKELY (rclass->resume))
794       res = rclass->resume (buf);
795   } else {
796     if (G_LIKELY (rclass->start))
797       res = rclass->start (buf);
798   }
799
800   if (G_UNLIKELY (!res)) {
801     buf->state = GST_RING_BUFFER_STATE_PAUSED;
802     GST_DEBUG_OBJECT (buf, "failed to start");
803   } else {
804     GST_DEBUG_OBJECT (buf, "started");
805   }
806
807 done:
808   GST_OBJECT_UNLOCK (buf);
809
810   return res;
811
812 flushing:
813   {
814     GST_OBJECT_UNLOCK (buf);
815     return FALSE;
816   }
817 }
818
819 static gboolean
820 gst_ring_buffer_pause_unlocked (GstRingBuffer * buf)
821 {
822   gboolean res = FALSE;
823   GstRingBufferClass *rclass;
824
825   GST_DEBUG_OBJECT (buf, "pausing ringbuffer");
826
827   /* if started, set to paused */
828   res = g_atomic_int_compare_and_exchange (&buf->state,
829       GST_RING_BUFFER_STATE_STARTED, GST_RING_BUFFER_STATE_PAUSED);
830
831   if (!res)
832     goto not_started;
833
834   /* signal any waiters */
835   GST_DEBUG_OBJECT (buf, "signal waiter");
836   GST_RING_BUFFER_SIGNAL (buf);
837
838   rclass = GST_RING_BUFFER_GET_CLASS (buf);
839   if (G_LIKELY (rclass->pause))
840     res = rclass->pause (buf);
841
842   if (G_UNLIKELY (!res)) {
843     buf->state = GST_RING_BUFFER_STATE_STARTED;
844     GST_DEBUG_OBJECT (buf, "failed to pause");
845   } else {
846     GST_DEBUG_OBJECT (buf, "paused");
847   }
848
849   return res;
850
851 not_started:
852   {
853     /* was not started */
854     GST_DEBUG_OBJECT (buf, "was not started");
855     return TRUE;
856   }
857 }
858
859 /**
860  * gst_ring_buffer_pause:
861  * @buf: the #GstRingBuffer to pause
862  *
863  * Pause processing samples from the ringbuffer.
864  *
865  * Returns: TRUE if the device could be paused, FALSE on error.
866  *
867  * MT safe.
868  */
869 gboolean
870 gst_ring_buffer_pause (GstRingBuffer * buf)
871 {
872   gboolean res = FALSE;
873
874   g_return_val_if_fail (GST_IS_RING_BUFFER (buf), FALSE);
875
876   GST_OBJECT_LOCK (buf);
877   if (G_UNLIKELY (buf->abidata.ABI.flushing))
878     goto flushing;
879
880   res = gst_ring_buffer_pause_unlocked (buf);
881   GST_OBJECT_UNLOCK (buf);
882
883   return res;
884
885 flushing:
886   {
887     GST_OBJECT_UNLOCK (buf);
888     return FALSE;
889   }
890 }
891
892 /**
893  * gst_ring_buffer_stop:
894  * @buf: the #GstRingBuffer to stop
895  *
896  * Stop processing samples from the ringbuffer.
897  *
898  * Returns: TRUE if the device could be stopped, FALSE on error.
899  *
900  * MT safe.
901  */
902 gboolean
903 gst_ring_buffer_stop (GstRingBuffer * buf)
904 {
905   gboolean res = FALSE;
906   GstRingBufferClass *rclass;
907
908   g_return_val_if_fail (GST_IS_RING_BUFFER (buf), FALSE);
909
910   GST_DEBUG_OBJECT (buf, "stopping");
911
912   GST_OBJECT_LOCK (buf);
913
914   /* if started, set to stopped */
915   res = g_atomic_int_compare_and_exchange (&buf->state,
916       GST_RING_BUFFER_STATE_STARTED, GST_RING_BUFFER_STATE_STOPPED);
917
918   if (!res) {
919     /* was not started, must be stopped then */
920     GST_DEBUG_OBJECT (buf, "was not started");
921     res = TRUE;
922     goto done;
923   }
924
925   /* signal any waiters */
926   GST_DEBUG_OBJECT (buf, "signal waiter");
927   GST_RING_BUFFER_SIGNAL (buf);
928
929   rclass = GST_RING_BUFFER_GET_CLASS (buf);
930   if (G_LIKELY (rclass->stop))
931     res = rclass->stop (buf);
932
933   if (G_UNLIKELY (!res)) {
934     buf->state = GST_RING_BUFFER_STATE_STARTED;
935     GST_DEBUG_OBJECT (buf, "failed to stop");
936   } else {
937     GST_DEBUG_OBJECT (buf, "stopped");
938   }
939 done:
940   GST_OBJECT_UNLOCK (buf);
941
942   return res;
943 }
944
945 /**
946  * gst_ring_buffer_delay:
947  * @buf: the #GstRingBuffer to query
948  *
949  * Get the number of samples queued in the audio device. This is
950  * usually less than the segment size but can be bigger when the
951  * implementation uses another internal buffer between the audio
952  * device.
953  *
954  * Returns: The number of samples queued in the audio device.
955  *
956  * MT safe.
957  */
958 guint
959 gst_ring_buffer_delay (GstRingBuffer * buf)
960 {
961   GstRingBufferClass *rclass;
962   guint res;
963
964   g_return_val_if_fail (GST_IS_RING_BUFFER (buf), 0);
965
966   res = 0;
967
968   /* buffer must be acquired */
969   if (G_UNLIKELY (!gst_ring_buffer_is_acquired (buf)))
970     goto done;
971
972   rclass = GST_RING_BUFFER_GET_CLASS (buf);
973   if (G_LIKELY (rclass->delay))
974     res = rclass->delay (buf);
975
976 done:
977   return res;
978 }
979
980 /**
981  * gst_ring_buffer_samples_done:
982  * @buf: the #GstRingBuffer to query
983  *
984  * Get the number of samples that were processed by the ringbuffer
985  * since it was last started.
986  *
987  * Returns: The number of samples processed by the ringbuffer.
988  *
989  * MT safe.
990  */
991 guint64
992 gst_ring_buffer_samples_done (GstRingBuffer * buf)
993 {
994   gint segdone;
995   guint64 raw, samples;
996   guint delay;
997
998   g_return_val_if_fail (GST_IS_RING_BUFFER (buf), 0);
999
1000   /* get the amount of segments we processed */
1001   segdone = g_atomic_int_get (&buf->segdone);
1002
1003   /* and the number of samples not yet processed */
1004   delay = gst_ring_buffer_delay (buf);
1005
1006   raw = samples = ((guint64) segdone) * buf->samples_per_seg;
1007
1008   if (G_LIKELY (samples >= delay))
1009     samples -= delay;
1010   else
1011     samples = 0;
1012
1013   GST_DEBUG_OBJECT (buf, "processed samples: raw %llu, delay %u, real %llu",
1014       raw, delay, samples);
1015
1016   return samples;
1017 }
1018
1019 /**
1020  * gst_ring_buffer_set_sample:
1021  * @buf: the #GstRingBuffer to use
1022  * @sample: the sample number to set
1023  *
1024  * Make sure that the next sample written to the device is
1025  * accounted for as being the @sample sample written to the
1026  * device. This value will be used in reporting the current
1027  * sample position of the ringbuffer.
1028  *
1029  * This function will also clear the buffer with silence.
1030  *
1031  * MT safe.
1032  */
1033 void
1034 gst_ring_buffer_set_sample (GstRingBuffer * buf, guint64 sample)
1035 {
1036   g_return_if_fail (GST_IS_RING_BUFFER (buf));
1037
1038   if (sample == -1)
1039     sample = 0;
1040
1041   if (G_UNLIKELY (buf->samples_per_seg == 0))
1042     return;
1043
1044   /* FIXME, we assume the ringbuffer can restart at a random 
1045    * position, round down to the beginning and keep track of
1046    * offset when calculating the processed samples. */
1047   buf->segbase = buf->segdone - sample / buf->samples_per_seg;
1048
1049   gst_ring_buffer_clear_all (buf);
1050
1051   GST_DEBUG_OBJECT (buf, "set sample to %llu, segbase %d", sample,
1052       buf->segbase);
1053 }
1054
1055 /**
1056  * gst_ring_buffer_clear_all:
1057  * @buf: the #GstRingBuffer to clear
1058  *
1059  * Fill the ringbuffer with silence.
1060  *
1061  * MT safe.
1062  */
1063 void
1064 gst_ring_buffer_clear_all (GstRingBuffer * buf)
1065 {
1066   gint i;
1067
1068   g_return_if_fail (GST_IS_RING_BUFFER (buf));
1069
1070   /* not fatal, we just are not negotiated yet */
1071   if (G_UNLIKELY (buf->spec.segtotal <= 0))
1072     return;
1073
1074   GST_DEBUG_OBJECT (buf, "clear all segments");
1075
1076   for (i = 0; i < buf->spec.segtotal; i++) {
1077     gst_ring_buffer_clear (buf, i);
1078   }
1079 }
1080
1081
1082 static gboolean
1083 wait_segment (GstRingBuffer * buf)
1084 {
1085   /* buffer must be started now or we deadlock since nobody is reading */
1086   if (G_UNLIKELY (g_atomic_int_get (&buf->state) !=
1087           GST_RING_BUFFER_STATE_STARTED)) {
1088     /* see if we are allowed to start it */
1089     if (G_UNLIKELY (g_atomic_int_get (&buf->abidata.ABI.may_start) == FALSE))
1090       goto no_start;
1091
1092     GST_DEBUG_OBJECT (buf, "start!");
1093     gst_ring_buffer_start (buf);
1094   }
1095
1096   /* take lock first, then update our waiting flag */
1097   GST_OBJECT_LOCK (buf);
1098   if (G_UNLIKELY (buf->abidata.ABI.flushing))
1099     goto flushing;
1100
1101   if (G_UNLIKELY (g_atomic_int_get (&buf->state) !=
1102           GST_RING_BUFFER_STATE_STARTED))
1103     goto not_started;
1104
1105   if (g_atomic_int_compare_and_exchange (&buf->waiting, 0, 1)) {
1106     GST_DEBUG_OBJECT (buf, "waiting..");
1107     GST_RING_BUFFER_WAIT (buf);
1108
1109     if (G_UNLIKELY (buf->abidata.ABI.flushing))
1110       goto flushing;
1111
1112     if (G_UNLIKELY (g_atomic_int_get (&buf->state) !=
1113             GST_RING_BUFFER_STATE_STARTED))
1114       goto not_started;
1115   }
1116   GST_OBJECT_UNLOCK (buf);
1117
1118   return TRUE;
1119
1120   /* ERROR */
1121 not_started:
1122   {
1123     g_atomic_int_compare_and_exchange (&buf->waiting, 1, 0);
1124     GST_DEBUG_OBJECT (buf, "stopped processing");
1125     GST_OBJECT_UNLOCK (buf);
1126     return FALSE;
1127   }
1128 flushing:
1129   {
1130     g_atomic_int_compare_and_exchange (&buf->waiting, 1, 0);
1131     GST_DEBUG_OBJECT (buf, "flushing");
1132     GST_OBJECT_UNLOCK (buf);
1133     return FALSE;
1134   }
1135 no_start:
1136   {
1137     GST_DEBUG_OBJECT (buf, "not allowed to start");
1138     return FALSE;
1139   }
1140 }
1141
1142 /**
1143  * gst_ring_buffer_commit:
1144  * @buf: the #GstRingBuffer to commit
1145  * @sample: the sample position of the data
1146  * @data: the data to commit
1147  * @len: the number of samples in the data to commit
1148  *
1149  * Commit @len samples pointed to by @data to the ringbuffer
1150  * @buf. The first sample should be written at position @sample in
1151  * the ringbuffer.
1152  *
1153  * @len does not need to be a multiple of the segment size of the ringbuffer
1154  * although it is recommended for optimal performance.
1155  *
1156  * Returns: The number of samples written to the ringbuffer or -1 on
1157  * error.
1158  *
1159  * MT safe.
1160  */
1161 guint
1162 gst_ring_buffer_commit (GstRingBuffer * buf, guint64 sample, guchar * data,
1163     guint len)
1164 {
1165   gint segdone;
1166   gint segsize, segtotal, bps, sps;
1167   guint8 *dest;
1168   guint to_write;
1169
1170   g_return_val_if_fail (GST_IS_RING_BUFFER (buf), -1);
1171   g_return_val_if_fail (buf->data != NULL, -1);
1172   g_return_val_if_fail (data != NULL, -1);
1173
1174   dest = GST_BUFFER_DATA (buf->data);
1175   segsize = buf->spec.segsize;
1176   segtotal = buf->spec.segtotal;
1177   bps = buf->spec.bytes_per_sample;
1178   sps = buf->samples_per_seg;
1179
1180   to_write = len;
1181   /* write out all samples */
1182   while (to_write > 0) {
1183     gint sampleslen;
1184     gint writeseg, sampleoff;
1185
1186     /* figure out the segment and the offset inside the segment where
1187      * the sample should be written. */
1188     writeseg = sample / sps;
1189     sampleoff = (sample % sps);
1190
1191     while (TRUE) {
1192       gint diff;
1193
1194       /* get the currently processed segment */
1195       segdone = g_atomic_int_get (&buf->segdone) - buf->segbase;
1196
1197       /* see how far away it is from the write segment */
1198       diff = writeseg - segdone;
1199
1200       GST_DEBUG
1201           ("pointer at %d, sample %llu, write to %d-%d, to_write %d, diff %d, segtotal %d, segsize %d",
1202           segdone, sample, writeseg, sampleoff, to_write, diff, segtotal, sps);
1203
1204       /* segment too far ahead, we need to drop, hopefully UNLIKELY */
1205       if (G_UNLIKELY (diff < 0)) {
1206         /* we need to drop one segment at a time, pretend we wrote a
1207          * segment. */
1208         sampleslen = MIN (sps, to_write);
1209         goto next;
1210       }
1211
1212       /* write segment is within writable range, we can break the loop and
1213        * start writing the data. */
1214       if (diff < segtotal)
1215         break;
1216
1217       /* else we need to wait for the segment to become writable. */
1218       if (!wait_segment (buf))
1219         goto not_started;
1220     }
1221
1222     /* we can write now */
1223     writeseg = writeseg % segtotal;
1224     sampleslen = MIN (sps - sampleoff, to_write);
1225
1226     GST_DEBUG_OBJECT (buf, "write @%p seg %d, off %d, sampleslen %d",
1227         dest + writeseg * segsize, writeseg, sampleoff, sampleslen);
1228
1229     memcpy (dest + (writeseg * segsize) + (sampleoff * bps), data,
1230         (sampleslen * bps));
1231
1232   next:
1233     to_write -= sampleslen;
1234     sample += sampleslen;
1235     data += sampleslen * bps;
1236   }
1237
1238   return len - to_write;
1239
1240   /* ERRORS */
1241 not_started:
1242   {
1243     GST_DEBUG_OBJECT (buf, "stopped processing");
1244     return len - to_write;
1245   }
1246 }
1247
1248 /**
1249  * gst_ring_buffer_read:
1250  * @buf: the #GstRingBuffer to read from
1251  * @sample: the sample position of the data
1252  * @data: where the data should be read
1253  * @len: the number of samples in data to read
1254  *
1255  * Read @len samples from the ringbuffer into the memory pointed 
1256  * to by @data.
1257  * The first sample should be read from position @sample in
1258  * the ringbuffer.
1259  *
1260  * @len should not be a multiple of the segment size of the ringbuffer
1261  * although it is recommended.
1262  *
1263  * Returns: The number of samples read from the ringbuffer or -1 on
1264  * error.
1265  *
1266  * MT safe.
1267  */
1268 guint
1269 gst_ring_buffer_read (GstRingBuffer * buf, guint64 sample, guchar * data,
1270     guint len)
1271 {
1272   gint segdone;
1273   gint segsize, segtotal, bps, sps;
1274   guint8 *dest;
1275
1276   g_return_val_if_fail (GST_IS_RING_BUFFER (buf), -1);
1277   g_return_val_if_fail (buf->data != NULL, -1);
1278   g_return_val_if_fail (data != NULL, -1);
1279
1280   dest = GST_BUFFER_DATA (buf->data);
1281   segsize = buf->spec.segsize;
1282   segtotal = buf->spec.segtotal;
1283   bps = buf->spec.bytes_per_sample;
1284   sps = buf->samples_per_seg;
1285
1286   /* read enough samples */
1287   while (len > 0) {
1288     gint sampleslen;
1289     gint readseg, sampleoff;
1290
1291     /* figure out the segment and the offset inside the segment where
1292      * the sample should be written. */
1293     readseg = sample / sps;
1294     sampleoff = (sample % sps);
1295
1296     while (TRUE) {
1297       gint diff;
1298
1299       /* get the currently processed segment */
1300       segdone = g_atomic_int_get (&buf->segdone) - buf->segbase;
1301
1302       /* see how far away it is from the read segment */
1303       diff = segdone - readseg;
1304
1305       GST_DEBUG
1306           ("pointer at %d, sample %llu, read from %d-%d, len %d, diff %d, segtotal %d, segsize %d",
1307           segdone, sample, readseg, sampleoff, len, diff, segtotal, segsize);
1308
1309       /* segment too far ahead, we need to drop */
1310       if (diff < 0) {
1311         /* we need to drop one segment at a time, pretend we read an
1312          * empty segment. */
1313         sampleslen = MIN (sps, len);
1314         memcpy (data, buf->empty_seg, sampleslen * bps);
1315         goto next;
1316       }
1317
1318       /* read segment is within readable range, we can break the loop and
1319        * start reading the data. */
1320       if (diff > 0 && diff < segtotal)
1321         break;
1322
1323       /* flush if diff has grown bigger than ringbuffer */
1324       if (diff >= segtotal) {
1325         gst_ring_buffer_clear_all (buf);
1326         buf->segdone = readseg;
1327       }
1328
1329       /* else we need to wait for the segment to become readable. */
1330       if (!wait_segment (buf))
1331         goto not_started;
1332     }
1333
1334     /* we can read now */
1335     readseg = readseg % segtotal;
1336     sampleslen = MIN (sps - sampleoff, len);
1337
1338     GST_DEBUG_OBJECT (buf, "read @%p seg %d, off %d, len %d",
1339         dest + readseg * segsize, readseg, sampleoff, sampleslen);
1340
1341     memcpy (data, dest + (readseg * segsize) + (sampleoff * bps),
1342         (sampleslen * bps));
1343
1344   next:
1345     len -= sampleslen;
1346     sample += sampleslen;
1347     data += sampleslen * bps;
1348   }
1349
1350   return len;
1351
1352   /* ERRORS */
1353 not_started:
1354   {
1355     GST_DEBUG_OBJECT (buf, "stopped processing");
1356     return -1;
1357   }
1358 }
1359
1360 /**
1361  * gst_ring_buffer_prepare_read:
1362  * @buf: the #GstRingBuffer to read from
1363  * @segment: the segment to read
1364  * @readptr: the pointer to the memory where samples can be read
1365  * @len: the number of bytes to read
1366  *
1367  * Returns a pointer to memory where the data from segment @segment
1368  * can be found. This function is mostly used by subclasses.
1369  *
1370  * Returns: FALSE if the buffer is not started.
1371  *
1372  * MT safe.
1373  */
1374 gboolean
1375 gst_ring_buffer_prepare_read (GstRingBuffer * buf, gint * segment,
1376     guint8 ** readptr, gint * len)
1377 {
1378   guint8 *data;
1379   gint segdone;
1380
1381   g_return_val_if_fail (GST_IS_RING_BUFFER (buf), FALSE);
1382
1383   /* buffer must be started */
1384   if (g_atomic_int_get (&buf->state) != GST_RING_BUFFER_STATE_STARTED)
1385     return FALSE;
1386
1387   g_return_val_if_fail (buf->data != NULL, FALSE);
1388   g_return_val_if_fail (segment != NULL, FALSE);
1389   g_return_val_if_fail (readptr != NULL, FALSE);
1390   g_return_val_if_fail (len != NULL, FALSE);
1391
1392   data = GST_BUFFER_DATA (buf->data);
1393
1394   /* get the position of the pointer */
1395   segdone = g_atomic_int_get (&buf->segdone);
1396
1397   *segment = segdone % buf->spec.segtotal;
1398   *len = buf->spec.segsize;
1399   *readptr = data + *segment * *len;
1400
1401   /* callback to fill the memory with data, for pull based
1402    * scheduling. */
1403   if (buf->callback)
1404     buf->callback (buf, *readptr, *len, buf->cb_data);
1405
1406   GST_LOG ("prepare read from segment %d (real %d) @%p",
1407       *segment, segdone, *readptr);
1408
1409   return TRUE;
1410 }
1411
1412 /**
1413  * gst_ring_buffer_advance:
1414  * @buf: the #GstRingBuffer to advance
1415  * @advance: the number of segments written
1416  *
1417  * Subclasses should call this function to notify the fact that 
1418  * @advance segments are now processed by the device.
1419  *
1420  * MT safe.
1421  */
1422 void
1423 gst_ring_buffer_advance (GstRingBuffer * buf, guint advance)
1424 {
1425   g_return_if_fail (GST_IS_RING_BUFFER (buf));
1426
1427   /* update counter */
1428   g_atomic_int_add (&buf->segdone, advance);
1429
1430   /* the lock is already taken when the waiting flag is set,
1431    * we grab the lock as well to make sure the waiter is actually
1432    * waiting for the signal */
1433   if (g_atomic_int_compare_and_exchange (&buf->waiting, 1, 0)) {
1434     GST_OBJECT_LOCK (buf);
1435     GST_DEBUG_OBJECT (buf, "signal waiter");
1436     GST_RING_BUFFER_SIGNAL (buf);
1437     GST_OBJECT_UNLOCK (buf);
1438   }
1439 }
1440
1441 /**
1442  * gst_ring_buffer_clear:
1443  * @buf: the #GstRingBuffer to clear
1444  * @segment: the segment to clear
1445  *
1446  * Clear the given segment of the buffer with silence samples.
1447  * This function is used by subclasses.
1448  *
1449  * MT safe.
1450  */
1451 void
1452 gst_ring_buffer_clear (GstRingBuffer * buf, gint segment)
1453 {
1454   guint8 *data;
1455
1456   g_return_if_fail (GST_IS_RING_BUFFER (buf));
1457
1458   /* no data means it's already cleared */
1459   if (G_UNLIKELY (buf->data == NULL))
1460     return;
1461
1462   /* no empty_seg means it's not opened */
1463   if (G_UNLIKELY (buf->empty_seg == NULL))
1464     return;
1465
1466   segment %= buf->spec.segtotal;
1467
1468   data = GST_BUFFER_DATA (buf->data);
1469   data += segment * buf->spec.segsize;
1470
1471   GST_LOG ("clear segment %d @%p", segment, data);
1472
1473   memcpy (data, buf->empty_seg, buf->spec.segsize);
1474 }
1475
1476 /**
1477  * gst_ring_buffer_may_start:
1478  * @buf: the #GstRingBuffer
1479  * @allowed: the new value
1480  *
1481  * Tell the ringbuffer that it is allowed to start playback when
1482  * the ringbuffer is filled with samples. 
1483  *
1484  * Since: 0.10.6
1485  *
1486  * MT safe.
1487  */
1488 void
1489 gst_ring_buffer_may_start (GstRingBuffer * buf, gboolean allowed)
1490 {
1491   g_return_if_fail (GST_IS_RING_BUFFER (buf));
1492
1493   GST_LOG_OBJECT (buf, "may start: %d", allowed);
1494   gst_atomic_int_set (&buf->abidata.ABI.may_start, allowed);
1495 }