Rework buffer memory layout

Move offset, size and stride to separate chunk structure that we
can keep in shared memory.
Add shared metadata type to hold the memory block holding the
metadata.
This commit is contained in:
Wim Taymans 2016-12-15 14:57:34 +01:00
parent 5e8a3afe17
commit 0d0385b881
13 changed files with 328 additions and 241 deletions

View file

@ -266,11 +266,18 @@ static void
connection_parse_use_buffers (PinosConnection *conn, PinosMessageUseBuffers *cmd)
{
void *p;
unsigned int i;
p = conn->in.data;
memcpy (cmd, p, sizeof (PinosMessageUseBuffers));
if (cmd->buffers)
cmd->buffers = SPA_MEMBER (p, SPA_PTR_TO_INT (cmd->buffers), PinosMessageMemRef);
cmd->buffers = SPA_MEMBER (p, SPA_PTR_TO_INT (cmd->buffers), PinosMessageBuffer);
for (i = 0; i < cmd->n_buffers; i++) {
if (cmd->buffers[i].buffer)
cmd->buffers[i].buffer = pinos_serialize_buffer_deserialize (conn->in.data,
SPA_PTR_TO_INT (cmd->buffers[i].buffer));
}
}
static void
@ -751,24 +758,32 @@ connection_add_use_buffers (PinosConnection *conn, uint32_t dest_id, PinosMessag
size_t len;
int i;
PinosMessageUseBuffers *d;
PinosMessageMemRef *mr;
PinosMessageBuffer *b;
void *p;
/* calculate length */
len = sizeof (PinosMessageUseBuffers);
len += ub->n_buffers * sizeof (PinosMessageMemRef);
len += ub->n_buffers * sizeof (PinosMessageBuffer);
for (i = 0; i < ub->n_buffers; i++)
len += pinos_serialize_buffer_get_size (ub->buffers[i].buffer);
d = connection_add_message (conn, dest_id, PINOS_MESSAGE_USE_BUFFERS, len);
memcpy (d, ub, sizeof (PinosMessageUseBuffers));
mr = SPA_MEMBER (d, sizeof (PinosMessageUseBuffers), void);
b = SPA_MEMBER (d, sizeof (PinosMessageUseBuffers), void);
p = SPA_MEMBER (b, ub->n_buffers * sizeof (PinosMessageBuffer), void);
if (d->n_buffers)
d->buffers = SPA_INT_TO_PTR (SPA_PTRDIFF (mr, d));
d->buffers = SPA_INT_TO_PTR (SPA_PTRDIFF (b, d));
else
d->buffers = 0;
for (i = 0; i < ub->n_buffers; i++)
memcpy (&mr[i], &ub->buffers[i], sizeof (PinosMessageMemRef));
for (i = 0; i < ub->n_buffers; i++) {
memcpy (&b[i], &ub->buffers[i], sizeof (PinosMessageBuffer));
len = pinos_serialize_buffer_serialize (p, b[i].buffer);
b[i].buffer = SPA_INT_TO_PTR (SPA_PTRDIFF (p, d));
p += len;
}
}
static void

View file

@ -286,10 +286,11 @@ typedef struct {
} PinosMessageAddMem;
typedef struct {
SpaBuffer *buffer;
uint32_t mem_id;
off_t offset;
size_t size;
} PinosMessageMemRef;
} PinosMessageBuffer;
/* PINOS_MESSAGE_USE_BUFFERS */
typedef struct {
@ -297,7 +298,7 @@ typedef struct {
SpaDirection direction;
uint32_t port_id;
unsigned int n_buffers;
PinosMessageMemRef *buffers;
PinosMessageBuffer *buffers;
} PinosMessageUseBuffers;
PinosConnection * pinos_connection_new (int fd);

View file

@ -30,7 +30,7 @@ pinos_serialize_buffer_get_size (const SpaBuffer *buffer)
size = sizeof (SpaBuffer);
for (i = 0; i < buffer->n_metas; i++)
size += sizeof (SpaMeta) + buffer->metas[i].size;
size += sizeof (SpaMeta);
for (i = 0; i < buffer->n_datas; i++)
size += sizeof (SpaData);
return size;
@ -57,12 +57,8 @@ pinos_serialize_buffer_serialize (void *dest, const SpaBuffer *buffer)
tb->metas = SPA_INT_TO_PTR (SPA_PTRDIFF (mp, tb));
tb->datas = SPA_INT_TO_PTR (SPA_PTRDIFF (dp, tb));
for (i = 0; i < tb->n_metas; i++) {
for (i = 0; i < tb->n_metas; i++)
memcpy (&mp[i], &buffer->metas[i], sizeof (SpaMeta));
memcpy (p, mp[i].data, mp[i].size);
mp[i].data = SPA_INT_TO_PTR (SPA_PTRDIFF (p, tb));
p += mp[i].size;
}
for (i = 0; i < tb->n_datas; i++)
memcpy (&dp[i], &buffer->datas[i], sizeof (SpaData));
@ -78,17 +74,21 @@ pinos_serialize_buffer_deserialize (void *src, off_t offset)
b = SPA_MEMBER (src, offset, SpaBuffer);
if (b->metas)
b->metas = SPA_MEMBER (b, SPA_PTR_TO_INT (b->metas), SpaMeta);
for (i = 0; i < b->n_metas; i++) {
SpaMeta *m = &b->metas[i];
if (m->data)
m->data = SPA_MEMBER (b, SPA_PTR_TO_INT (m->data), void);
}
if (b->datas)
b->datas = SPA_MEMBER (b, SPA_PTR_TO_INT (b->datas), SpaData);
return b;
}
SpaBuffer *
pinos_serialize_buffer_copy_into (void *dest, const SpaBuffer *buffer)
{
if (buffer == NULL)
return NULL;
pinos_serialize_buffer_serialize (dest, buffer);
return pinos_serialize_buffer_deserialize (dest, 0);
}
size_t
pinos_serialize_format_get_size (const SpaFormat *format)

View file

@ -32,6 +32,7 @@ extern "C" {
size_t pinos_serialize_buffer_get_size (const SpaBuffer *buffer);
size_t pinos_serialize_buffer_serialize (void *dest, const SpaBuffer *buffer);
SpaBuffer * pinos_serialize_buffer_deserialize (void *src, off_t offset);
SpaBuffer * pinos_serialize_buffer_copy_into (void *dest, const SpaBuffer *buffer);
size_t pinos_serialize_format_get_size (const SpaFormat *format);
size_t pinos_serialize_format_serialize (void *dest, const SpaFormat *format);

View file

@ -44,6 +44,7 @@ typedef struct {
int fd;
uint32_t flags;
void *ptr;
off_t offset;
size_t size;
} MemId;
@ -453,20 +454,13 @@ on_rtsocket_condition (SpaSource *source,
read (impl->rtfd, &cmd, 1);
if (cmd & PINOS_TRANSPORT_CMD_HAVE_DATA) {
BufferId *bid;
for (i = 0; i < impl->trans->area->n_inputs; i++) {
SpaPortInput *input = &impl->trans->inputs[i];
if (input->buffer_id == SPA_ID_INVALID)
continue;
if ((bid = find_buffer (stream, input->buffer_id))) {
for (i = 0; i < bid->buf->n_datas; i++) {
bid->buf->datas[i].size = bid->datas[i].size;
}
pinos_signal_emit (&stream->new_buffer, stream, bid->id);
}
pinos_signal_emit (&stream->new_buffer, stream, input->buffer_id);
input->buffer_id = SPA_ID_INVALID;
}
send_need_input (stream);
@ -652,15 +646,18 @@ stream_dispatch_func (void *object,
m = find_mem (stream, p->mem_id);
if (m) {
pinos_log_debug ("update mem %u, fd %d, flags %d, size %zd", p->mem_id, p->memfd, p->flags, p->size);
pinos_log_debug ("update mem %u, fd %d, flags %d, off %zd, size %zd",
p->mem_id, p->memfd, p->flags, p->offset, p->size);
} else {
m = pinos_array_add (&impl->mem_ids, sizeof (MemId));
pinos_log_debug ("add mem %u, fd %d, flags %d, size %zd", p->mem_id, p->memfd, p->flags, p->size);
pinos_log_debug ("add mem %u, fd %d, flags %d, off %zd, size %zd",
p->mem_id, p->memfd, p->flags, p->offset, p->size);
}
m->id = p->mem_id;
m->fd = p->memfd;
m->flags = p->flags;
m->ptr = NULL;
m->offset = p->offset;
m->size = p->size;
break;
}
@ -675,6 +672,8 @@ stream_dispatch_func (void *object,
clear_buffers (stream);
for (i = 0; i < p->n_buffers; i++) {
off_t offset = 0;
MemId *mid = find_mem (stream, p->buffers[i].mem_id);
if (mid == NULL) {
pinos_log_warn ("unknown memory id %u", mid->id);
@ -682,41 +681,28 @@ stream_dispatch_func (void *object,
}
if (mid->ptr == NULL) {
mid->ptr = mmap (NULL, mid->size, PROT_READ | PROT_WRITE, MAP_SHARED, mid->fd, 0);
//mid->ptr = mmap (NULL, mid->size, PROT_READ | PROT_WRITE, MAP_SHARED, mid->fd, mid->offset);
mid->ptr = mmap (NULL, mid->size + mid->offset, PROT_READ | PROT_WRITE, MAP_SHARED, mid->fd, 0);
if (mid->ptr == MAP_FAILED) {
mid->ptr = NULL;
pinos_log_warn ("Failed to mmap memory %zd %p: %s", mid->size, mid, strerror (errno));
continue;
}
mid->ptr = SPA_MEMBER (mid->ptr, mid->offset, void);
}
len = pinos_array_get_len (&impl->buffer_ids, BufferId);
bid = pinos_array_add (&impl->buffer_ids, sizeof (BufferId));
b = p->buffers[i].buffer;
bid->buf_ptr = SPA_MEMBER (mid->ptr, p->buffers[i].offset, void);
{
size_t size;
unsigned int i;
SpaMeta *m;
b = bid->buf_ptr;
size = sizeof (SpaBuffer);
m = SPA_MEMBER (b, SPA_PTR_TO_INT (b->metas), SpaMeta);
for (i = 0; i < b->n_metas; i++)
size += sizeof (SpaMeta) + m[i].size;
for (i = 0; i < b->n_datas; i++)
size += sizeof (SpaData);
size = pinos_serialize_buffer_get_size (p->buffers[i].buffer);
b = bid->buf = malloc (size);
memcpy (b, bid->buf_ptr, size);
if (b->metas)
b->metas = SPA_MEMBER (b, SPA_PTR_TO_INT (b->metas), SpaMeta);
if (b->datas) {
bid->datas = SPA_MEMBER (bid->buf_ptr, SPA_PTR_TO_INT (b->datas), SpaData);
b->datas = SPA_MEMBER (b, SPA_PTR_TO_INT (b->datas), SpaData);
}
pinos_serialize_buffer_copy_into (b, p->buffers[i].buffer);
}
bid->id = b->id;
if (bid->id != len) {
@ -727,13 +713,15 @@ stream_dispatch_func (void *object,
for (j = 0; j < b->n_metas; j++) {
SpaMeta *m = &b->metas[j];
if (m->data)
m->data = SPA_MEMBER (bid->buf_ptr, SPA_PTR_TO_INT (m->data), void);
m->data = SPA_MEMBER (bid->buf_ptr, offset, void);
offset += m->size;
}
for (j = 0; j < b->n_datas; j++) {
SpaData *d = &b->datas[j];
d->chunk = SPA_MEMBER (bid->buf_ptr, offset + sizeof (SpaChunk) * j, SpaChunk);
switch (d->type) {
case SPA_DATA_TYPE_ID:
{
@ -757,6 +745,8 @@ stream_dispatch_func (void *object,
}
}
spa_debug_buffer (b);
pinos_signal_emit (&stream->add_buffer, stream, bid->id);
}
@ -1096,9 +1086,6 @@ pinos_stream_send_buffer (PinosStream *stream,
uint8_t cmd = PINOS_TRANSPORT_CMD_HAVE_DATA;
bid->used = true;
for (i = 0; i < bid->buf->n_datas; i++) {
bid->datas[i].size = bid->buf->datas[i].size;
}
impl->trans->outputs[0].buffer_id = id;
impl->trans->outputs[0].status = SPA_RESULT_OK;
write (impl->rtfd, &cmd, 1);

View file

@ -403,13 +403,13 @@ on_add_buffer (PinosListener *listener,
case SPA_DATA_TYPE_DMABUF:
{
gmem = gst_fd_allocator_alloc (pinossink->allocator, dup (d->fd),
d->maxsize, GST_FD_MEMORY_FLAG_NONE);
gst_memory_resize (gmem, d->offset, d->size);
d->size, GST_FD_MEMORY_FLAG_NONE);
gst_memory_resize (gmem, d->chunk->offset, d->chunk->size);
break;
}
case SPA_DATA_TYPE_MEMPTR:
gmem = gst_memory_new_wrapped (0, d->data, d->maxsize, d->offset,
d->size, NULL, NULL);
gmem = gst_memory_new_wrapped (0, d->data, d->size, d->chunk->offset,
d->chunk->size, NULL, NULL);
break;
default:
break;
@ -644,8 +644,8 @@ gst_pinos_sink_render (GstBaseSink * bsink, GstBuffer * buffer)
for (i = 0; i < data->buf->n_datas; i++) {
SpaData *d = &data->buf->datas[i];
GstMemory *mem = gst_buffer_peek_memory (buffer, i);
d->offset = mem->offset;
d->size = mem->size;
d->chunk->offset = mem->offset;
d->chunk->size = mem->size;
}
gst_buffer_ref (buffer);

View file

@ -417,13 +417,13 @@ on_add_buffer (PinosListener *listener,
case SPA_DATA_TYPE_DMABUF:
{
gmem = gst_fd_allocator_alloc (pinossrc->fd_allocator, dup (d->fd),
d->maxsize, GST_FD_MEMORY_FLAG_NONE);
gst_memory_resize (gmem, d->offset, d->size);
d->size, GST_FD_MEMORY_FLAG_NONE);
gst_memory_resize (gmem, d->chunk->offset, d->chunk->size);
break;
}
case SPA_DATA_TYPE_MEMPTR:
gmem = gst_memory_new_wrapped (0, d->data, d->maxsize, d->offset,
d->size, NULL, NULL);
gmem = gst_memory_new_wrapped (0, d->data, d->size, d->chunk->offset,
d->chunk->size, NULL, NULL);
default:
break;
}
@ -488,8 +488,8 @@ on_new_buffer (PinosListener *listener,
for (i = 0; i < data->buf->n_datas; i++) {
SpaData *d = &data->buf->datas[i];
GstMemory *mem = gst_buffer_peek_memory (buf, i);
mem->offset = d->offset;
mem->size = d->size;
mem->offset = d->chunk->offset;
mem->size = d->chunk->size;
}
g_queue_push_tail (&pinossrc->queue, buf);

View file

@ -66,7 +66,6 @@ struct _ProxyBuffer {
off_t offset;
size_t size;
bool outstanding;
ProxyBuffer *next;
};
typedef struct {
@ -610,9 +609,9 @@ spa_proxy_node_port_use_buffers (SpaNode *node,
unsigned int i, j;
PinosMessageAddMem am;
PinosMessageUseBuffers ub;
size_t size, n_mem;
PinosMessageMemRef *memref;
void *p;
size_t n_mem;
PinosMessageBuffer *mb;
SpaMetaShared *msh;
if (node == NULL)
return SPA_RESULT_INVALID_ARGUMENTS;
@ -630,19 +629,44 @@ spa_proxy_node_port_use_buffers (SpaNode *node,
clear_buffers (this, port);
/* find size to store buffers */
size = 0;
if (n_buffers > 0) {
mb = alloca (n_buffers * sizeof (PinosMessageBuffer));
} else {
mb = NULL;
}
n_mem = 0;
for (i = 0; i < n_buffers; i++) {
ProxyBuffer *b = &port->buffers[i];
msh = spa_buffer_find_meta (buffers[i], SPA_META_TYPE_SHARED);
if (msh == NULL) {
spa_log_error (this->log, "missing shared metadata on buffer %d", i);
return SPA_RESULT_ERROR;
}
b->outbuf = buffers[i];
memcpy (&b->buffer, buffers[i], sizeof (SpaBuffer));
b->buffer.datas = b->datas;
b->buffer.metas = b->metas;
b->size = SPA_ROUND_UP_N (pinos_serialize_buffer_get_size (buffers[i]), 64);
b->offset = size;
am.direction = direction;
am.port_id = port_id;
am.mem_id = n_mem++;
am.type = SPA_DATA_TYPE_MEMFD;
am.memfd = msh->fd;
am.flags = msh->flags;
am.offset = msh->offset;
am.size = msh->size;
pinos_resource_send_message (this->resource,
PINOS_MESSAGE_ADD_MEM,
&am,
false);
mb[i].buffer = &b->buffer;
mb[i].mem_id = am.mem_id;
mb[i].offset = 0;
mb[i].size = am.size;
for (j = 0; j < buffers[i]->n_metas; j++) {
memcpy (&b->buffer.metas[j], &buffers[i]->metas[j], sizeof (SpaMeta));
@ -663,7 +687,7 @@ spa_proxy_node_port_use_buffers (SpaNode *node,
am.memfd = d->fd;
am.flags = d->flags;
am.offset = d->offset;
am.size = d->maxsize;
am.size = d->size;
pinos_resource_send_message (this->resource,
PINOS_MESSAGE_ADD_MEM,
&am,
@ -683,78 +707,20 @@ spa_proxy_node_port_use_buffers (SpaNode *node,
break;
}
}
size += b->size;
}
if (n_buffers > 0) {
/* make mem for the buffers */
port->buffer_mem_id = n_mem++;
if (pinos_memblock_alloc (PINOS_MEMBLOCK_FLAG_WITH_FD |
PINOS_MEMBLOCK_FLAG_MAP_READWRITE |
PINOS_MEMBLOCK_FLAG_SEAL,
size,
&port->buffer_mem) < 0) {
spa_log_error (this->log, "Failed to allocate buffer memory");
return SPA_RESULT_ERROR;
}
p = port->buffer_mem.ptr;
for (i = 0; i < n_buffers; i++) {
ProxyBuffer *b = &port->buffers[i];
SpaBuffer *sb;
SpaMeta *sbm;
SpaData *sbd;
pinos_serialize_buffer_serialize (p, &b->buffer);
sb = p;
b->buffer.datas = SPA_MEMBER (sb, SPA_PTR_TO_INT (sb->datas), SpaData);
sbm = SPA_MEMBER (sb, SPA_PTR_TO_INT (sb->metas), SpaMeta);
sbd = SPA_MEMBER (sb, SPA_PTR_TO_INT (sb->datas), SpaData);
for (j = 0; j < b->buffer.n_metas; j++)
b->metas[j].data = SPA_MEMBER (sb, SPA_PTR_TO_INT (sbm[j].data), void);
for (j = 0; j < b->buffer.n_datas; j++) {
if (b->datas[j].type == SPA_DATA_TYPE_MEMPTR)
b->datas[j].data = SPA_MEMBER (sb, SPA_PTR_TO_INT (sbd[j].data), void);
}
p += b->size;
}
am.direction = direction;
am.port_id = port_id;
am.mem_id = port->buffer_mem_id;
am.type = SPA_DATA_TYPE_MEMFD;
am.memfd = port->buffer_mem.fd;
am.flags = 0;
am.offset = 0;
am.size = size;
pinos_resource_send_message (this->resource,
PINOS_MESSAGE_ADD_MEM,
&am,
false);
memref = alloca (n_buffers * sizeof (PinosMessageMemRef));
for (i = 0; i < n_buffers; i++) {
memref[i].mem_id = port->buffer_mem_id;
memref[i].offset = port->buffers[i].offset;
memref[i].size = port->buffers[i].size;
}
} else {
memref = NULL;
}
port->n_buffers = n_buffers;
ub.seq = this->seq++;
ub.direction = direction;
ub.port_id = port_id;
ub.n_buffers = n_buffers;
ub.buffers = memref;
ub.buffers = mb;
pinos_resource_send_message (this->resource,
PINOS_MESSAGE_USE_BUFFERS,
&ub,
true);
return SPA_RESULT_RETURN_ASYNC (ub.seq);
}
@ -789,6 +755,7 @@ spa_proxy_node_port_alloc_buffers (SpaNode *node,
static void
copy_meta_in (SpaProxy *this, SpaProxyPort *port, uint32_t buffer_id)
{
#if 0
ProxyBuffer *b = &port->buffers[buffer_id];
unsigned int i;
@ -804,11 +771,13 @@ copy_meta_in (SpaProxy *this, SpaProxyPort *port, uint32_t buffer_id)
memcpy (b->outbuf->datas[i].data, b->datas[i].data, b->buffer.datas[i].size);
}
}
#endif
}
static void
copy_meta_out (SpaProxy *this, SpaProxyPort *port, uint32_t buffer_id)
{
#if 0
ProxyBuffer *b = &port->buffers[buffer_id];
unsigned int i;
@ -824,6 +793,7 @@ copy_meta_out (SpaProxy *this, SpaProxyPort *port, uint32_t buffer_id)
memcpy (b->datas[i].data, b->outbuf->datas[i].data, b->outbuf->datas[i].size);
}
}
#endif
}
static SpaResult

View file

@ -201,6 +201,145 @@ find_meta_enable (const SpaPortInfo *info, SpaMetaType type)
return NULL;
}
static SpaBuffer **
alloc_buffers (PinosLink *this,
unsigned int n_buffers,
unsigned int n_params,
SpaAllocParam **params,
unsigned int n_datas,
size_t *data_sizes,
ssize_t *data_strides,
PinosMemblock *mem)
{
SpaBuffer **buffers, *bp;
unsigned int i;
size_t skel_size, data_size, meta_size;
SpaChunk *cdp;
void *ddp;
unsigned int n_metas;
SpaMeta *metas;
n_metas = data_size = meta_size = 0;
/* each buffer */
skel_size = sizeof (SpaBuffer);
metas = alloca (sizeof (SpaMeta) * n_params + 1);
/* add shared metadata */
metas[n_metas].type = SPA_META_TYPE_SHARED;
metas[n_metas].size = spa_meta_type_get_size (SPA_META_TYPE_SHARED);
meta_size += metas[n_metas].size;
n_metas++;
skel_size += sizeof (SpaMeta);
/* collect metadata */
for (i = 0; i < n_params; i++) {
SpaAllocParam *ap = params[i];
if (ap->type == SPA_ALLOC_PARAM_TYPE_META_ENABLE) {
SpaAllocParamMetaEnable *pme = (SpaAllocParamMetaEnable *) ap;
metas[n_metas].type = pme->type;
metas[n_metas].size = spa_meta_type_get_size (pme->type);
meta_size += metas[n_metas].size;
n_metas++;
skel_size += sizeof (SpaMeta);
}
}
data_size += meta_size;
/* data */
for (i = 0; i < n_datas; i++) {
data_size += sizeof (SpaChunk);
data_size += data_sizes[i];
skel_size += sizeof (SpaData);
}
buffers = calloc (n_buffers, skel_size + sizeof (SpaBuffer *));
/* pointer to buffer structures */
bp = SPA_MEMBER (buffers, n_buffers * sizeof (SpaBuffer *), SpaBuffer);
pinos_memblock_alloc (PINOS_MEMBLOCK_FLAG_WITH_FD |
PINOS_MEMBLOCK_FLAG_MAP_READWRITE |
PINOS_MEMBLOCK_FLAG_SEAL,
n_buffers * data_size,
mem);
for (i = 0; i < n_buffers; i++) {
int j;
SpaBuffer *b;
void *p;
buffers[i] = b = SPA_MEMBER (bp, skel_size * i, SpaBuffer);
p = SPA_MEMBER (mem->ptr, data_size * i, void);
b->id = i;
b->n_metas = n_metas;
b->metas = SPA_MEMBER (b, sizeof (SpaBuffer), SpaMeta);
for (j = 0; j < n_metas; j++) {
SpaMeta *m = &b->metas[j];
m->type = metas[j].type;
m->data = p;
m->size = metas[j].size;
switch (m->type) {
case SPA_META_TYPE_SHARED:
{
SpaMetaShared *msh = p;
msh->type = SPA_DATA_TYPE_MEMFD;
msh->flags = 0;
msh->fd = mem->fd;
msh->offset = data_size * i;
msh->size = data_size;
break;
}
case SPA_META_TYPE_RINGBUFFER:
{
SpaMetaRingbuffer *rb = p;
spa_ringbuffer_init (&rb->ringbuffer, data_sizes[0]);
break;
}
default:
break;
}
p += m->size;
}
/* pointer to data structure */
b->n_datas = n_datas;
b->datas = SPA_MEMBER (b->metas, n_metas * sizeof (SpaMeta), SpaData);
cdp = p;
ddp = SPA_MEMBER (cdp, sizeof (SpaChunk) * n_datas, void);
for (j = 0; j < n_datas; j++) {
SpaData *d = &b->datas[j];
d->chunk = &cdp[j];
if (data_sizes[j] > 0) {
d->type = SPA_DATA_TYPE_MEMFD;
d->flags = 0;
d->fd = mem->fd;
d->offset = 0;
d->size = mem->size;
d->data = mem->ptr;
d->chunk->offset = SPA_PTRDIFF (ddp, d->data);
d->chunk->size = data_sizes[j];
d->chunk->stride = data_strides[j];
ddp += data_sizes[j];
} else {
d->type = SPA_DATA_TYPE_INVALID;
d->data = NULL;
}
}
}
return buffers;
}
static SpaResult
do_allocation (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state)
{
@ -317,98 +456,21 @@ do_allocation (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state)
impl->allocated = false;
pinos_log_debug ("reusing %d output buffers %p", impl->n_buffers, impl->buffers);
} else {
unsigned int i, j;
size_t hdr_size, buf_size, arr_size;
void *p;
unsigned int n_metas, n_datas;
size_t data_sizes[1];
ssize_t data_strides[1];
n_metas = 0;
n_datas = 1;
hdr_size = sizeof (SpaBuffer);
hdr_size += n_datas * sizeof (SpaData);
for (i = 0; i < oinfo->n_params; i++) {
SpaAllocParam *ap = oinfo->params[i];
if (ap->type == SPA_ALLOC_PARAM_TYPE_META_ENABLE) {
SpaAllocParamMetaEnable *pme = (SpaAllocParamMetaEnable *) ap;
hdr_size += spa_meta_type_get_size (pme->type);
n_metas++;
}
}
hdr_size += n_metas * sizeof (SpaMeta);
buf_size = SPA_ROUND_UP_N (hdr_size + (minsize * blocks), 64);
data_sizes[0] = minsize;
data_strides[0] = stride;
impl->n_buffers = max_buffers;
pinos_memblock_alloc (PINOS_MEMBLOCK_FLAG_WITH_FD |
PINOS_MEMBLOCK_FLAG_MAP_READWRITE |
PINOS_MEMBLOCK_FLAG_SEAL,
impl->n_buffers * (sizeof (SpaBuffer*) + buf_size),
&impl->buffer_mem);
arr_size = impl->n_buffers * sizeof (SpaBuffer*);
impl->buffers = p = impl->buffer_mem.ptr;
p = SPA_MEMBER (p, arr_size, void);
for (i = 0; i < impl->n_buffers; i++) {
SpaBuffer *b;
SpaData *d;
void *pd;
unsigned int mi;
b = impl->buffers[i] = SPA_MEMBER (p, buf_size * i, SpaBuffer);
b->id = i;
b->n_metas = n_metas;
b->metas = SPA_MEMBER (b, sizeof (SpaBuffer), SpaMeta);
b->n_datas = n_datas;
b->datas = SPA_MEMBER (b->metas, sizeof (SpaMeta) * n_metas, SpaData);
pd = SPA_MEMBER (b->datas, sizeof (SpaData) * n_datas, void);
for (j = 0, mi = 0; j < oinfo->n_params; j++) {
SpaAllocParam *ap = oinfo->params[j];
if (ap->type == SPA_ALLOC_PARAM_TYPE_META_ENABLE) {
SpaAllocParamMetaEnable *pme = (SpaAllocParamMetaEnable *) ap;
b->metas[mi].type = pme->type;
b->metas[mi].data = pd;
b->metas[mi].size = spa_meta_type_get_size (pme->type);
switch (pme->type) {
case SPA_META_TYPE_RINGBUFFER:
{
SpaMetaRingbuffer *rb = pd;
spa_ringbuffer_init (&rb->ringbuffer, minsize);
break;
}
default:
break;
}
pd = SPA_MEMBER (pd, b->metas[mi].size, void);
mi++;
}
}
d = &b->datas[0];
if (minsize > 0) {
d->type = SPA_DATA_TYPE_MEMFD;
d->flags = 0;
d->data = impl->buffer_mem.ptr;
d->fd = impl->buffer_mem.fd;
d->maxsize = impl->buffer_mem.size;
d->offset = arr_size + hdr_size + (buf_size * i);
d->size = minsize;
d->stride = stride;
} else {
d->type = SPA_DATA_TYPE_INVALID;
d->data = NULL;
}
}
pinos_log_debug ("allocated %d buffers %p %zd", impl->n_buffers, impl->buffers, minsize);
impl->allocated = true;
impl->buffers = alloc_buffers (this,
impl->n_buffers,
oinfo->n_params,
oinfo->params,
1,
data_sizes,
data_strides,
&impl->buffer_mem);
}
if (out_flags & SPA_PORT_INFO_FLAG_CAN_ALLOC_BUFFERS) {