summaryrefslogtreecommitdiffstats
path: root/media/libcubeb/src/cubeb_ring_array.h
diff options
context:
space:
mode:
Diffstat (limited to 'media/libcubeb/src/cubeb_ring_array.h')
-rw-r--r--media/libcubeb/src/cubeb_ring_array.h159
1 files changed, 159 insertions, 0 deletions
diff --git a/media/libcubeb/src/cubeb_ring_array.h b/media/libcubeb/src/cubeb_ring_array.h
new file mode 100644
index 000000000..51b3b321a
--- /dev/null
+++ b/media/libcubeb/src/cubeb_ring_array.h
@@ -0,0 +1,159 @@
+/*
+ * Copyright © 2016 Mozilla Foundation
+ *
+ * This program is made available under an ISC-style license. See the
+ * accompanying file LICENSE for details.
+ */
+
+#ifndef CUBEB_RING_ARRAY_H
+#define CUBEB_RING_ARRAY_H
+
+#include "cubeb_utils.h"
+
+/** Ring array of pointers is used to hold buffers. In case that
+ asynchronous producer/consumer callbacks do not arrive in a
+ repeated order the ring array stores the buffers and fetch
+ them in the correct order. */
+
+typedef struct {
+ AudioBuffer * buffer_array; /**< Array that hold pointers of the allocated space for the buffers. */
+ unsigned int tail; /**< Index of the last element (first to deliver). */
+ unsigned int count; /**< Number of elements in the array. */
+ unsigned int capacity; /**< Total length of the array. */
+} ring_array;
+
+static int
+single_audiobuffer_init(AudioBuffer * buffer,
+ uint32_t bytesPerFrame,
+ uint32_t channelsPerFrame,
+ uint32_t frames)
+{
+ assert(buffer);
+ assert(bytesPerFrame > 0 && channelsPerFrame && frames > 0);
+
+ size_t size = bytesPerFrame * frames;
+ buffer->mData = operator new(size);
+ if (buffer->mData == NULL) {
+ return CUBEB_ERROR;
+ }
+ PodZero(static_cast<char*>(buffer->mData), size);
+
+ buffer->mNumberChannels = channelsPerFrame;
+ buffer->mDataByteSize = size;
+
+ return CUBEB_OK;
+}
+
+/** Initialize the ring array.
+ @param ra The ring_array pointer of allocated structure.
+ @retval 0 on success. */
+int
+ring_array_init(ring_array * ra,
+ uint32_t capacity,
+ uint32_t bytesPerFrame,
+ uint32_t channelsPerFrame,
+ uint32_t framesPerBuffer)
+{
+ assert(ra);
+ if (capacity == 0 || bytesPerFrame == 0 ||
+ channelsPerFrame == 0 || framesPerBuffer == 0) {
+ return CUBEB_ERROR_INVALID_PARAMETER;
+ }
+ ra->capacity = capacity;
+ ra->tail = 0;
+ ra->count = 0;
+
+ ra->buffer_array = new AudioBuffer[ra->capacity];
+ PodZero(ra->buffer_array, ra->capacity);
+ if (ra->buffer_array == NULL) {
+ return CUBEB_ERROR;
+ }
+
+ for (unsigned int i = 0; i < ra->capacity; ++i) {
+ if (single_audiobuffer_init(&ra->buffer_array[i],
+ bytesPerFrame,
+ channelsPerFrame,
+ framesPerBuffer) != CUBEB_OK) {
+ return CUBEB_ERROR;
+ }
+ }
+
+ return CUBEB_OK;
+}
+
+/** Destroy the ring array.
+ @param ra The ring_array pointer.*/
+void
+ring_array_destroy(ring_array * ra)
+{
+ assert(ra);
+ if (ra->buffer_array == NULL){
+ return;
+ }
+ for (unsigned int i = 0; i < ra->capacity; ++i) {
+ if (ra->buffer_array[i].mData) {
+ operator delete(ra->buffer_array[i].mData);
+ }
+ }
+ delete [] ra->buffer_array;
+}
+
+/** Get the allocated buffer to be stored with fresh data.
+ @param ra The ring_array pointer.
+ @retval Pointer of the allocated space to be stored with fresh data or NULL if full. */
+AudioBuffer *
+ring_array_get_free_buffer(ring_array * ra)
+{
+ assert(ra && ra->buffer_array);
+ assert(ra->buffer_array[0].mData != NULL);
+ if (ra->count == ra->capacity) {
+ return NULL;
+ }
+
+ assert(ra->count == 0 || (ra->tail + ra->count) % ra->capacity != ra->tail);
+ AudioBuffer * ret = &ra->buffer_array[(ra->tail + ra->count) % ra->capacity];
+
+ ++ra->count;
+ assert(ra->count <= ra->capacity);
+
+ return ret;
+}
+
+/** Get the next available buffer with data.
+ @param ra The ring_array pointer.
+ @retval Pointer of the next in order data buffer or NULL if empty. */
+AudioBuffer *
+ring_array_get_data_buffer(ring_array * ra)
+{
+ assert(ra && ra->buffer_array);
+ assert(ra->buffer_array[0].mData != NULL);
+
+ if (ra->count == 0) {
+ return NULL;
+ }
+ AudioBuffer * ret = &ra->buffer_array[ra->tail];
+
+ ra->tail = (ra->tail + 1) % ra->capacity;
+ assert(ra->tail < ra->capacity);
+
+ assert(ra->count > 0);
+ --ra->count;
+
+ return ret;
+}
+
+/** When array is empty get the first allocated buffer in the array.
+ @param ra The ring_array pointer.
+ @retval If arrays is empty, pointer of the allocated space else NULL. */
+AudioBuffer *
+ring_array_get_dummy_buffer(ring_array * ra)
+{
+ assert(ra && ra->buffer_array);
+ assert(ra->capacity > 0);
+ if (ra->count > 0) {
+ return NULL;
+ }
+ return &ra->buffer_array[0];
+}
+
+#endif //CUBEB_RING_ARRAY_H