#include "sched.h"
struct btr_pool {
+ char *name;
char *area_start;
char *area_end;
char *rhead;
void *context;
};
-struct btr_pool *btr_pool_new(size_t area_size)
+struct btr_pool *btr_pool_new(const char *name, size_t area_size)
{
- struct btr_pool *btrp = para_malloc(sizeof(*btrp));
+ struct btr_pool *btrp;
+ PARA_INFO_LOG("%s, %zu bytes\n", name, area_size);
+ btrp = para_malloc(sizeof(*btrp));
btrp->area_start = para_malloc(area_size);
btrp->area_end = btrp->area_start + area_size;
btrp->rhead = btrp->area_start;
btrp->whead = btrp->area_start;
+ btrp->name = para_strdup(name);
return btrp;
}
if (!btrp)
return;
free(btrp->area_start);
+ free(btrp->name);
free(btrp);
}
add_btrb_to_children(btrb, btrn, 0);
}
-void btr_add_output_pool(struct btr_pool *btrp, char *buf, size_t size,
- struct btr_node *btrn)
+void btr_add_output_pool(struct btr_pool *btrp, size_t size,
+ struct btr_node *btrn)
{
struct btr_buffer *btrb;
+ char *buf;
+ size_t avail;
assert(size != 0);
- if (list_empty(&btrn->children)) {
- btr_pool_deallocate(btrp, size);
+ if (list_empty(&btrn->children))
return;
- }
+ avail = btr_pool_get_buffer(btrp, &buf);
+ assert(avail >= size);
+ btr_pool_allocate(btrp, size);
btrb = new_btrb(buf, size);
btrb->pool = btrp;
add_btrb_to_children(btrb, btrn, 0);
}
+void btr_copy(const void *src, size_t n, struct btr_pool *btrp,
+ struct btr_node *btrn)
+{
+ char *buf;
+ size_t sz, copy;
+
+ if (n == 0)
+ return;
+ assert(n <= btr_pool_unused(btrp));
+ sz = btr_pool_get_buffer(btrp, &buf);
+ copy = PARA_MIN(sz, n);
+ memcpy(buf, src, copy);
+ btr_add_output_pool(btrp, copy, btrn);
+ if (copy == n)
+ return;
+ sz = btr_pool_get_buffer(btrp, &buf);
+ assert(sz >= n - copy);
+ memcpy(buf, src + copy, n - copy);
+ btr_add_output_pool(btrp, n - copy, btrn);
+}
+
static void btr_pushdown_br(struct btr_buffer_reference *br, struct btr_node *btrn)
{
add_btrb_to_children(br->btrb, btrn, br->consumed);
BTR_NT_LEAF,
};
-struct btr_pool *btr_pool_new(size_t area_size);
+struct btr_pool *btr_pool_new(const char *name, size_t area_size);
void btr_pool_free(struct btr_pool *btrp);
size_t btr_pool_get_buffer(struct btr_pool *btrp, char **result);
void btr_pool_allocate(struct btr_pool *btrp, size_t size);
-void btr_add_output_pool(struct btr_pool *btrp, char *buf, size_t size,
+void btr_add_output_pool(struct btr_pool *btrp, size_t size,
+ struct btr_node *btrn);
+size_t btr_pool_unused(struct btr_pool *btrp);
+void btr_copy(const void *src, size_t n, struct btr_pool *btrp,
struct btr_node *btrn);
struct btr_node *btr_new_node(const char *name, struct btr_node *parent,
int have_header;
/** Points to the first received group. */
struct fecdec_group *first_complete_group;
+ struct btr_pool *btrp;
};
/** Iterate over all fecdec groups. */
PARA_DEBUG_LOG("writing group %d (%d/%d decoded data bytes)\n",
fg->h.group_num, fg->h.group_bytes,
fg->h.data_slices_per_group * sb);
- need = fn->loaded + (fg->h.data_slices_per_group - i) * sb;
if (fn->btrn) {
- buf = para_malloc(need);
+ need = (fg->h.data_slices_per_group - i) * sb;
+ if (need > btr_pool_unused(pfd->btrp))
+ return -E_FECDEC_OVERRUN;
+ btr_pool_get_buffer(pfd->btrp, &buf);
p = buf;
} else {
+ need = fn->loaded + (fg->h.data_slices_per_group - i) * sb;
if (need > fn->bufsize) {
fn->bufsize = PARA_MAX(fn->bufsize * 2, need);
if (fn->bufsize > FECDEC_MAX_OUTBUF_SIZE)
break;
if (sb + written > fg->h.audio_header_size)
n = fg->h.audio_header_size - written;
- memcpy(p + written, fg->data[i], n);
+ if (fn->btrn)
+ btr_copy(fg->data[i], n, pfd->btrp, fn->btrn);
+ else
+ memcpy(p + written, fg->data[i], n);
fn->loaded += n;
written += n;
}
size_t n = sb;
if (n + written > fg->h.group_bytes)
n = fg->h.group_bytes - written;
- memcpy(p + written, fg->data[i], n);
+ if (fn->btrn)
+ btr_copy(fg->data[i], n, pfd->btrp, fn->btrn);
+ else
+ memcpy(p + written, fg->data[i], n);
fn->loaded += n;
written += n;
}
p += written;
- if (fn->btrn)
- btr_add_output(buf, p - buf, fn->btrn);
return 0;
}
ret = fec_new(k, n, &pfd->fec);
if (ret < 0)
return ret;
+ pfd->btrp = btr_pool_new("fecdec", 20 * k * h->slice_bytes);
/* decode and clear the first group */
ret = decode_group(pfd->first_complete_group, fn);
if (ret < 0)
ret = -E_RECV_EOF;
if (ret < 0)
goto err;
- btr_pool_allocate(phd->btrp, ret);
- btr_add_output_pool(phd->btrp, buf, ret, btrn);
+ btr_add_output_pool(phd->btrp, ret, btrn);
return;
}
ret = -E_HTTP_RECV_OVERRUN;
rn->private_data = phd = para_calloc(sizeof(struct private_http_recv_data));
phd->fd = fd;
phd->status = HTTP_CONNECTED;
- phd->btrp = btr_pool_new(320 * 1024);
+ phd->btrp = btr_pool_new("http_recv", 320 * 1024);
return 1;
}
packet_size = ret;
if (packet_size >= FEC_EOF_PACKET_LEN) {
if (!memcmp(buf, FEC_EOF_PACKET, FEC_EOF_PACKET_LEN)) {
- PARA_CRIT_LOG("%p: eof\n", rn);
+ PARA_INFO_LOG("received eof packet\n");
ret = -E_RECV_EOF;
goto err;
}
}
- btr_pool_allocate(purd->btrp, packet_size);
- btr_add_output_pool(purd->btrp, buf, packet_size, btrn);
+ btr_add_output_pool(purd->btrp, packet_size, btrn);
return;
err:
btr_remove_node(btrn);
}
PARA_CRIT_LOG("rn %p: receiving from %s:%d, fd=%d\n", rn, c->host_arg,
c->port_arg, purd->fd);
- purd->btrp = btr_pool_new(320 * 1024);
+ purd->btrp = btr_pool_new("udp_recv", 320 * 1024);
return purd->fd;
err:
free(rn->private_data);