mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-12-15 08:56:38 -05:00
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:
parent
5e8a3afe17
commit
0d0385b881
13 changed files with 328 additions and 241 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ typedef struct _SpaBuffer SpaBuffer;
|
|||
* @SPA_META_TYPE_POINTER: a generic pointer
|
||||
* @SPA_META_TYPE_VIDEO_CROP: video cropping region
|
||||
* @SPA_META_TYPE_RINGBUFFER: a ringbuffer
|
||||
* @SPA_META_TYPE_SHARED: buffer data and metadata memory can be shared
|
||||
*/
|
||||
typedef enum {
|
||||
SPA_META_TYPE_INVALID = 0,
|
||||
|
|
@ -43,6 +44,7 @@ typedef enum {
|
|||
SPA_META_TYPE_POINTER,
|
||||
SPA_META_TYPE_VIDEO_CROP,
|
||||
SPA_META_TYPE_RINGBUFFER,
|
||||
SPA_META_TYPE_SHARED,
|
||||
} SpaMetaType;
|
||||
|
||||
/**
|
||||
|
|
@ -119,6 +121,21 @@ typedef struct {
|
|||
SpaRingbuffer ringbuffer;
|
||||
} SpaMetaRingbuffer;
|
||||
|
||||
/**
|
||||
* SpaMetaShared:
|
||||
* @type:
|
||||
* @flags:
|
||||
* @fd:
|
||||
* @size:
|
||||
*/
|
||||
typedef struct {
|
||||
SpaDataType type;
|
||||
int flags;
|
||||
int fd;
|
||||
off_t offset;
|
||||
size_t size;
|
||||
} SpaMetaShared;
|
||||
|
||||
/**
|
||||
* SpaMeta:
|
||||
* @type: metadata type
|
||||
|
|
@ -131,26 +148,36 @@ typedef struct {
|
|||
size_t size;
|
||||
} SpaMeta;
|
||||
|
||||
/**
|
||||
* SpaChunk:
|
||||
* @offset: offset of valid data
|
||||
* @size: size of valid data
|
||||
* @stride: stride of data if applicable
|
||||
*/
|
||||
typedef struct {
|
||||
off_t offset;
|
||||
size_t size;
|
||||
ssize_t stride;
|
||||
} SpaChunk;
|
||||
|
||||
/**
|
||||
* SpaData:
|
||||
* @type: memory type
|
||||
* @flags: memory flags
|
||||
* @data: pointer to memory
|
||||
* @fd: file descriptor
|
||||
* @offset: start offset when mapping @fd
|
||||
* @maxsize: maximum size of the memory
|
||||
* @offset: offset in @data
|
||||
* @size: valid size of @data
|
||||
* @stride: stride of data if applicable
|
||||
* @data: pointer to memory
|
||||
* @chunk: pointer to chunk with valid offset
|
||||
*/
|
||||
typedef struct {
|
||||
SpaDataType type;
|
||||
int flags;
|
||||
void *data;
|
||||
int fd;
|
||||
size_t maxsize;
|
||||
off_t offset;
|
||||
size_t size;
|
||||
ssize_t stride;
|
||||
void *data;
|
||||
SpaChunk *chunk;
|
||||
} SpaData;
|
||||
|
||||
/**
|
||||
|
|
@ -169,6 +196,12 @@ struct _SpaBuffer {
|
|||
SpaData *datas;
|
||||
};
|
||||
|
||||
|
||||
typedef struct {
|
||||
unsigned int n_buffers;
|
||||
SpaBuffer **buffers;
|
||||
} SpaBufferArray;
|
||||
|
||||
static inline void *
|
||||
spa_buffer_find_meta (SpaBuffer *b, SpaMetaType type)
|
||||
{
|
||||
|
|
@ -189,6 +222,7 @@ spa_meta_type_get_size (SpaMetaType type)
|
|||
sizeof (SpaMetaPointer),
|
||||
sizeof (SpaMetaVideoCrop),
|
||||
sizeof (SpaMetaRingbuffer),
|
||||
sizeof (SpaMetaShared),
|
||||
};
|
||||
if (type <= 0 || type >= SPA_N_ELEMENTS (header_sizes))
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ struct meta_type_name {
|
|||
{ "SpaMetaPointer" },
|
||||
{ "SpaMetaVideoCrop" },
|
||||
{ "SpaMetaRingbuffer" },
|
||||
{ "SpaMetaShared" },
|
||||
{ "invalid" },
|
||||
};
|
||||
#define META_TYPE_NAME(t) meta_type_names[SPA_CLAMP(t,0,SPA_N_ELEMENTS(meta_type_names)-1)].name
|
||||
|
|
@ -172,6 +173,17 @@ spa_debug_buffer (const SpaBuffer *buffer)
|
|||
fprintf (stderr, " mask2: %zd\n", h->ringbuffer.mask2);
|
||||
break;
|
||||
}
|
||||
case SPA_META_TYPE_SHARED:
|
||||
{
|
||||
SpaMetaShared *h = m->data;
|
||||
fprintf (stderr, " SpaMetaShared:\n");
|
||||
fprintf (stderr, " type: %d\n", h->type);
|
||||
fprintf (stderr, " flags: %d\n", h->flags);
|
||||
fprintf (stderr, " fd: %d\n", h->fd);
|
||||
fprintf (stderr, " offset: %zd\n", h->offset);
|
||||
fprintf (stderr, " size: %zd\n", h->size);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
spa_debug_dump_mem (m->data, m->size);
|
||||
break;
|
||||
|
|
@ -184,10 +196,12 @@ spa_debug_buffer (const SpaBuffer *buffer)
|
|||
fprintf (stderr, " flags: %d\n", d->flags);
|
||||
fprintf (stderr, " data: %p\n", d->data);
|
||||
fprintf (stderr, " fd: %d\n", d->fd);
|
||||
fprintf (stderr, " maxsize: %zd\n", d->maxsize);
|
||||
fprintf (stderr, " offset: %zd\n", d->offset);
|
||||
fprintf (stderr, " size: %zd\n", d->size);
|
||||
fprintf (stderr, " stride: %zd\n", d->stride);
|
||||
fprintf (stderr, " maxsize: %zd\n", d->size);
|
||||
fprintf (stderr, " chunk: %p\n", d->chunk);
|
||||
fprintf (stderr, " offset: %zd\n", d->chunk->offset);
|
||||
fprintf (stderr, " size: %zd\n", d->chunk->size);
|
||||
fprintf (stderr, " stride: %zd\n", d->chunk->stride);
|
||||
}
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ spa_v4l2_clear_buffers (SpaV4l2Source *this)
|
|||
}
|
||||
if (b->allocated) {
|
||||
if (b->outbuf->datas[0].data)
|
||||
munmap (b->outbuf->datas[0].data, b->outbuf->datas[0].maxsize);
|
||||
munmap (b->outbuf->datas[0].data, b->outbuf->datas[0].size);
|
||||
if (b->outbuf->datas[0].fd != -1)
|
||||
close (b->outbuf->datas[0].fd);
|
||||
b->outbuf->datas[0].type = SPA_DATA_TYPE_INVALID;
|
||||
|
|
@ -876,7 +876,9 @@ mmap_read (SpaV4l2Source *this)
|
|||
}
|
||||
|
||||
d = b->outbuf->datas;
|
||||
d[0].size = buf.bytesused;
|
||||
d[0].chunk->offset = 0;
|
||||
d[0].chunk->size = buf.bytesused;
|
||||
d[0].chunk->stride = state->fmt.fmt.pix.bytesperline;
|
||||
|
||||
spa_list_insert (state->ready.prev, &b->list);
|
||||
|
||||
|
|
@ -970,7 +972,7 @@ spa_v4l2_use_buffers (SpaV4l2Source *this, SpaBuffer **buffers, uint32_t n_buffe
|
|||
spa_log_error (state->log, "v4l2: need mmaped memory");
|
||||
continue;
|
||||
}
|
||||
b->v4l2_buffer.m.userptr = (unsigned long) SPA_MEMBER (d[0].data, d[0].offset, void *);
|
||||
b->v4l2_buffer.m.userptr = (unsigned long) d[0].data;
|
||||
b->v4l2_buffer.length = d[0].size;
|
||||
break;
|
||||
case SPA_DATA_TYPE_DMABUF:
|
||||
|
|
@ -1047,8 +1049,9 @@ mmap_init (SpaV4l2Source *this,
|
|||
d = buffers[i]->datas;
|
||||
d[0].offset = 0;
|
||||
d[0].size = b->v4l2_buffer.length;
|
||||
d[0].maxsize = b->v4l2_buffer.length;
|
||||
d[0].stride = state->fmt.fmt.pix.bytesperline;
|
||||
d[0].chunk->offset = 0;
|
||||
d[0].chunk->size = b->v4l2_buffer.length;
|
||||
d[0].chunk->stride = state->fmt.fmt.pix.bytesperline;
|
||||
|
||||
if (state->export_buf) {
|
||||
struct v4l2_exportbuffer expbuf;
|
||||
|
|
|
|||
|
|
@ -658,7 +658,7 @@ spa_videotestsrc_node_port_use_buffers (SpaNode *node,
|
|||
continue;
|
||||
}
|
||||
b->ptr = SPA_MEMBER (d[0].data, d[0].offset, void);
|
||||
b->stride = d[0].stride;
|
||||
b->stride = d[0].chunk->stride;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue