diff --git a/pinos/client/connection.c b/pinos/client/connection.c index 877591ff3..7b53cf933 100644 --- a/pinos/client/connection.c +++ b/pinos/client/connection.c @@ -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 diff --git a/pinos/client/connection.h b/pinos/client/connection.h index 96d34b7df..4ea926d57 100644 --- a/pinos/client/connection.h +++ b/pinos/client/connection.h @@ -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); diff --git a/pinos/client/serialize.c b/pinos/client/serialize.c index 0b8f949e7..214162242 100644 --- a/pinos/client/serialize.c +++ b/pinos/client/serialize.c @@ -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) diff --git a/pinos/client/serialize.h b/pinos/client/serialize.h index 7f8a3035a..568ce879d 100644 --- a/pinos/client/serialize.h +++ b/pinos/client/serialize.h @@ -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); diff --git a/pinos/client/stream.c b/pinos/client/stream.c index 41f53935f..01df9e020 100644 --- a/pinos/client/stream.c +++ b/pinos/client/stream.c @@ -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); diff --git a/pinos/gst/gstpinossink.c b/pinos/gst/gstpinossink.c index 5233a97b8..c858ef813 100644 --- a/pinos/gst/gstpinossink.c +++ b/pinos/gst/gstpinossink.c @@ -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); diff --git a/pinos/gst/gstpinossrc.c b/pinos/gst/gstpinossrc.c index 0c0154122..635a8d665 100644 --- a/pinos/gst/gstpinossrc.c +++ b/pinos/gst/gstpinossrc.c @@ -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); diff --git a/pinos/server/client-node.c b/pinos/server/client-node.c index 2816d7a63..3dd0ccae5 100644 --- a/pinos/server/client-node.c +++ b/pinos/server/client-node.c @@ -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 diff --git a/pinos/server/link.c b/pinos/server/link.c index 2f23f56fe..2b316b1e0 100644 --- a/pinos/server/link.c +++ b/pinos/server/link.c @@ -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) { diff --git a/spa/include/spa/buffer.h b/spa/include/spa/buffer.h index 1b58c56a6..94eb81bf9 100644 --- a/spa/include/spa/buffer.h +++ b/spa/include/spa/buffer.h @@ -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; diff --git a/spa/lib/debug.c b/spa/lib/debug.c index 02e8bb321..8b3582439 100644 --- a/spa/lib/debug.c +++ b/spa/lib/debug.c @@ -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; } diff --git a/spa/plugins/v4l2/v4l2-utils.c b/spa/plugins/v4l2/v4l2-utils.c index de291aa10..874fe709d 100644 --- a/spa/plugins/v4l2/v4l2-utils.c +++ b/spa/plugins/v4l2/v4l2-utils.c @@ -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; diff --git a/spa/plugins/videotestsrc/videotestsrc.c b/spa/plugins/videotestsrc/videotestsrc.c index be8cf93b9..292882ab6 100644 --- a/spa/plugins/videotestsrc/videotestsrc.c +++ b/spa/plugins/videotestsrc/videotestsrc.c @@ -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;