summaryrefslogtreecommitdiffstats
path: root/bufferq.c
diff options
context:
space:
mode:
Diffstat (limited to 'bufferq.c')
-rw-r--r--bufferq.c88
1 files changed, 72 insertions, 16 deletions
diff --git a/bufferq.c b/bufferq.c
index c4c3ec3..5261f35 100644
--- a/bufferq.c
+++ b/bufferq.c
@@ -4,6 +4,8 @@
#include "macro.h"
#include "bufferq.h"
+#define SA_BUFFERQ_CONCAT_DATA(x) ((void*) (uint8_t*) (x) + ALIGN(sizeof(sa_bufferq_item_t)))
+
int sa_bufferq_init(sa_bufferq_t *q, unsigned nchannels, size_t sample_size) {
sa_assert(q);
sa_assert(sample_size > 0);
@@ -42,19 +44,53 @@ void sa_bufferq_done(sa_bufferq_t *q) {
sa_free(q->last);
}
-static sa_bufferq_item_t* bufferq_item_new(size_t size) {
+static sa_bufferq_item_t* bufferq_item_new(const void *d, size_t size, int copy) {
sa_bufferq_item_t *i;
sa_assert(size > 0);
+
+ if (!copy) {
+ if (!(i = sa_new(sa_bufferq_item_t, 1)))
+ return i;
+ i->type = SA_BUFFERQ_ITEM_STATIC;
+ i->data = (void*) d;
+ } else {
+ if (!(i = sa_malloc(ALIGN(sizeof(sa_bufferq_item_t)) + size)))
+ return i;
+ i->type = SA_BUFFERQ_ITEM_CONCATENATED;
+ i->data = SA_BUFFERQ_CONCAT_DATA(i);
+ memcpy(i->data, d, size);
+ }
+
+ i->size = size;
+ SA_LLIST_ITEM_INIT(sa_bufferq_item_t, bufferq, i);
+
+ return i;
+}
+
+static sa_bufferq_item_t* bufferq_item_make_writable(sa_bufferq_item_t *i) {
+ void *d;
+ sa_assert(i);
- if (!(i = sa_malloc(ALIGN(sizeof(sa_bufferq_item_t)) + size)))
+ if (i->type == SA_BUFFERQ_ITEM_CONCATENATED || i->type == SA_BUFFERQ_ITEM_DYNAMIC)
return i;
- SA_LLIST_ITEM_INIT(sa_bufferq_item_t, bufferq, i);
+ if (!(d = sa_memdup(i->data, i->size)))
+ return NULL;
+ i->data = d;
+ i->type = SA_BUFFERQ_ITEM_DYNAMIC;
return i;
}
-int sa_bufferq_push(sa_bufferq_t *q, unsigned channel, const void *data, size_t nbytes, int64_t offset, sa_seek_t whence) {
+static void bufferq_item_free(sa_bufferq_item_t *i) {
+ sa_assert(i);
+
+ if (i->type == SA_BUFFERQ_ITEM_DYNAMIC)
+ sa_free(i->data);
+ sa_free(i);
+}
+
+int sa_bufferq_push(sa_bufferq_t *q, unsigned channel, const void *data, size_t nbytes, int64_t offset, sa_seek_t whence, int copy) {
int64_t idx;
sa_bufferq_item_t *i, *j;
@@ -103,13 +139,11 @@ int sa_bufferq_push(sa_bufferq_t *q, unsigned channel, const void *data, size_t
if (l > i->idx - idx)
l = i->idx - idx;
-
- if (!(j = bufferq_item_new(l)))
- return SA_ERROR_OOM;
- memcpy(SA_BUFFERQ_ITEM_DATA(j), data, l);
+ if (!(j = bufferq_item_new(data, l, copy)))
+ return SA_ERROR_OOM;
+
j->idx = idx;
- j->size = l;
SA_LLIST_INSERT_BEFORE(sa_bufferq_item_t, bufferq, q->items[channel], i, j);
@@ -127,7 +161,10 @@ int sa_bufferq_push(sa_bufferq_t *q, unsigned channel, const void *data, size_t
if (l > i->idx + i->size - idx)
l = i->idx + i->size - idx;
- memcpy((uint8_t*) SA_BUFFERQ_ITEM_DATA(i) + (idx - i->idx), data, l);
+ if (!(i = bufferq_item_make_writable(i)))
+ return SA_ERROR_OOM;
+
+ memcpy((uint8_t*) i->data + (idx - i->idx), data, l);
idx += l;
data += l;
@@ -138,12 +175,10 @@ int sa_bufferq_push(sa_bufferq_t *q, unsigned channel, const void *data, size_t
if (nbytes > 0) {
sa_assert(!i);
- if (!(j = bufferq_item_new(nbytes)))
+ if (!(j = bufferq_item_new(data, nbytes, copy)))
return SA_ERROR_OOM;
- memcpy(SA_BUFFERQ_ITEM_DATA(j), data, nbytes);
j->idx = idx;
- j->size = nbytes;
if (q->last[channel])
SA_LLIST_INSERT_AFTER(sa_bufferq_item_t, bufferq, q->items[channel], q->last[channel], j);
@@ -186,7 +221,7 @@ int sa_bufferq_get(sa_bufferq_t *q, void *i[], size_t *bytes) {
} else {
int64_t l;
- i[u] = (uint8_t*) SA_BUFFERQ_ITEM_DATA(q->items[u]) + q->read_index - q->items[u]->idx;
+ i[u] = (uint8_t*) q->items[u]->data + q->read_index - q->items[u]->idx;
l = q->items[u]->size - (q->read_index - q->items[u]->idx);
@@ -213,7 +248,6 @@ int sa_bufferq_drop(sa_bufferq_t *q, int64_t bytes) {
q->read_index += bytes;
for (u = 0; u < q->nchannels; u++) {
-
sa_bufferq_item_t *i;
i = q->items[u];
@@ -223,7 +257,7 @@ int sa_bufferq_drop(sa_bufferq_t *q, int64_t bytes) {
SA_LLIST_REMOVE(sa_bufferq_item_t, bufferq, q->items[u], i);
- sa_free(i);
+ bufferq_item_free(i);
i = n;
}
@@ -233,3 +267,25 @@ int sa_bufferq_drop(sa_bufferq_t *q, int64_t bytes) {
return SA_SUCCESS;
}
+
+int sa_bufferq_realloc(sa_bufferq_t *q) {
+ unsigned u;
+ sa_assert(q);
+
+ for (u = 0; u < q->nchannels; u++) {
+ sa_bufferq_item_t *i;
+
+ i = q->items[u];
+
+ while (i) {
+
+ if (!bufferq_item_make_writable(i))
+ return SA_ERROR_OOM;
+
+ i = i->bufferq_next;
+ }
+
+ }
+
+ return SA_SUCCESS;
+}