diff --git a/spa/include/spa/buffer/buffer.h b/spa/include/spa/buffer/buffer.h index 2f9bba914..fb1099fa7 100644 --- a/spa/include/spa/buffer/buffer.h +++ b/spa/include/spa/buffer/buffer.h @@ -32,33 +32,37 @@ extern "C" { * * Buffers describe the data and metadata that is exchanged between * ports of a node. - * */ #define SPA_TYPE__Buffer SPA_TYPE_POINTER_BASE "Buffer" #define SPA_TYPE_BUFFER_BASE SPA_TYPE__Buffer ":" +/** Buffers contain data of a certain type */ #define SPA_TYPE__Data SPA_TYPE_ENUM_BASE "DataType" #define SPA_TYPE_DATA_BASE SPA_TYPE__Data ":" +/** The data type for a plain memory pointer. The data member points to + * the memory. */ #define SPA_TYPE_DATA__MemPtr SPA_TYPE_DATA_BASE "MemPtr" -#define SPA_TYPE_DATA__MemFd SPA_TYPE_DATA_BASE "MemFd" -#define SPA_TYPE_DATA__DmaBuf SPA_TYPE_DATA_BASE "DmaBuf" -#define SPA_TYPE_DATA__Id SPA_TYPE_DATA_BASE "Id" + +/** base type for fd based memory */ +#define SPA_TYPE_DATA__Fd SPA_TYPE_DATA_BASE "Fd" +#define SPA_TYPE_DATA_FD_BASE SPA_TYPE_DATA__Fd ":" + +#define SPA_TYPE_DATA_FD__MemFd SPA_TYPE_DATA_FD_BASE "MemFd" +#define SPA_TYPE_DATA_FD__DmaBuf SPA_TYPE_DATA_FD_BASE "DmaBuf" struct spa_type_data { - uint32_t MemPtr; - uint32_t MemFd; - uint32_t DmaBuf; - uint32_t Id; + uint32_t MemPtr; /**< system memory */ + uint32_t MemFd; /**< memory accesible with an fd */ + uint32_t DmaBuf; /**< dmabuf fd */ }; static inline void spa_type_data_map(struct spa_type_map *map, struct spa_type_data *type) { if (type->MemPtr == 0) { type->MemPtr = spa_type_map_get_id(map, SPA_TYPE_DATA__MemPtr); - type->MemFd = spa_type_map_get_id(map, SPA_TYPE_DATA__MemFd); - type->DmaBuf = spa_type_map_get_id(map, SPA_TYPE_DATA__DmaBuf); - type->Id = spa_type_map_get_id(map, SPA_TYPE_DATA__Id); + type->MemFd = spa_type_map_get_id(map, SPA_TYPE_DATA_FD__MemFd); + type->DmaBuf = spa_type_map_get_id(map, SPA_TYPE_DATA_FD__DmaBuf); } } diff --git a/src/examples/video-play.c b/src/examples/video-play.c index dcf84bc05..92b1dc0c2 100644 --- a/src/examples/video-play.c +++ b/src/examples/video-play.c @@ -111,7 +111,8 @@ on_stream_new_buffer(void *_data, uint32_t id) buf = pw_stream_peek_buffer(stream, id); - if (buf->datas[0].type == data->type.data.MemFd) { + if (buf->datas[0].type == data->type.data.MemFd || + buf->datas[0].type == data->type.data.DmaBuf) { map = mmap(NULL, buf->datas[0].maxsize + buf->datas[0].mapoffset, PROT_READ, MAP_PRIVATE, buf->datas[0].fd, 0); sdata = SPA_MEMBER(map, buf->datas[0].mapoffset, uint8_t); diff --git a/src/extensions/client-node.h b/src/extensions/client-node.h index 7b136ea6c..0d3f40b46 100644 --- a/src/extensions/client-node.h +++ b/src/extensions/client-node.h @@ -405,9 +405,7 @@ struct pw_client_node_proxy_events { uint32_t mem_id, uint32_t type, int memfd, - uint32_t flags, - uint32_t offset, - uint32_t size); + uint32_t flags); /** * Notify the port of buffers * diff --git a/src/modules/module-client-node/client-node.c b/src/modules/module-client-node/client-node.c index 4384b332c..e7782904f 100644 --- a/src/modules/module-client-node/client-node.c +++ b/src/modules/module-client-node/client-node.c @@ -544,8 +544,7 @@ spa_proxy_node_port_set_io(struct spa_node *node, direction, port_id, memid, t->data.MemFd, - mem->fd, mem->flags, - 0, mem->offset + mem->size); + mem->fd, mem->flags); pw_client_node_resource_port_set_io(this->resource, this->seq, @@ -634,7 +633,7 @@ spa_proxy_node_port_use_buffers(struct spa_node *node, mb[i].buffer = &b->buffer; mb[i].mem_id = n_mem++; - mb[i].offset = 0; + mb[i].offset = SPA_PTRDIFF(baseptr, m->ptr + m->offset); mb[i].size = data_size; pw_client_node_resource_port_add_mem(this->resource, @@ -642,9 +641,7 @@ spa_proxy_node_port_use_buffers(struct spa_node *node, port_id, mb[i].mem_id, t->data.MemFd, - m->fd, m->flags, - SPA_PTRDIFF(baseptr, m->ptr + m->offset), - data_size); + m->fd, m->flags); for (j = 0; j < buffers[i]->n_metas; j++) memcpy(&b->buffer.metas[j], &buffers[i]->metas[j], sizeof(struct spa_meta)); @@ -663,8 +660,7 @@ spa_proxy_node_port_use_buffers(struct spa_node *node, n_mem, d->type, d->fd, - d->flags, d->mapoffset, d->maxsize); - b->buffer.datas[j].type = t->data.Id; + d->flags); b->buffer.datas[j].data = SPA_UINT32_TO_PTR(n_mem); n_mem++; } else if (d->type == t->data.MemPtr) { diff --git a/src/modules/module-client-node/protocol-native.c b/src/modules/module-client-node/protocol-native.c index b83553f3e..fbfec10c4 100644 --- a/src/modules/module-client-node/protocol-native.c +++ b/src/modules/module-client-node/protocol-native.c @@ -298,7 +298,7 @@ static bool client_node_demarshal_port_add_mem(void *object, void *data, size_t { struct pw_proxy *proxy = object; struct spa_pod_parser prs; - uint32_t direction, port_id, mem_id, type, memfd_idx, flags, offset, sz; + uint32_t direction, port_id, mem_id, type, memfd_idx, flags; int memfd; spa_pod_parser_init(&prs, data, size, 0); @@ -309,9 +309,7 @@ static bool client_node_demarshal_port_add_mem(void *object, void *data, size_t "i", &mem_id, "I", &type, "i", &memfd_idx, - "i", &flags, - "i", &offset, - "i", &sz, NULL) < 0) + "i", &flags, NULL) < 0) return false; memfd = pw_protocol_native_get_proxy_fd(proxy, memfd_idx); @@ -320,7 +318,7 @@ static bool client_node_demarshal_port_add_mem(void *object, void *data, size_t port_id, mem_id, type, - memfd, flags, offset, sz); + memfd, flags); return true; } @@ -564,7 +562,7 @@ client_node_marshal_port_add_mem(void *object, uint32_t port_id, uint32_t mem_id, uint32_t type, - int memfd, uint32_t flags, uint32_t offset, uint32_t size) + int memfd, uint32_t flags) { struct pw_resource *resource = object; struct spa_pod_builder *b; @@ -577,9 +575,7 @@ client_node_marshal_port_add_mem(void *object, "i", mem_id, "I", type, "i", pw_protocol_native_add_resource_fd(resource, memfd), - "i", flags, - "i", offset, - "i", size); + "i", flags); pw_protocol_native_end_resource(resource, b); } diff --git a/src/pipewire/remote.c b/src/pipewire/remote.c index 35330f3ca..e28f1374e 100644 --- a/src/pipewire/remote.c +++ b/src/pipewire/remote.c @@ -50,16 +50,15 @@ struct mem_id { uint32_t id; int fd; uint32_t flags; - void *ptr; - uint32_t offset; - uint32_t size; }; struct buffer_id { struct spa_list link; uint32_t id; - void *buf_ptr; struct spa_buffer *buf; + void *ptr; + uint32_t offset; + uint32_t size; }; struct port { @@ -851,9 +850,6 @@ static struct mem_id *find_mem(struct port *port, uint32_t id) static void clear_memid(struct mem_id *mid) { - if (mid->ptr != NULL) - munmap(mid->ptr, mid->size + mid->offset); - mid->ptr = NULL; close(mid->fd); } @@ -873,6 +869,11 @@ static void clear_buffers(struct port *port) pw_log_debug("port %p: clear buffers", port); pw_array_for_each(bid, &port->buffer_ids) { + if (bid->ptr != NULL) { + if (munmap(bid->ptr, bid->size + bid->offset) < 0) + pw_log_warn("failed to unmap: %m"); + } + bid->ptr = NULL; free(bid->buf); bid->buf = NULL; } @@ -891,7 +892,7 @@ static void client_node_port_add_mem(void *object, enum spa_direction direction, uint32_t port_id, uint32_t mem_id, - uint32_t type, int memfd, uint32_t flags, uint32_t offset, uint32_t size) + uint32_t type, int memfd, uint32_t flags) { struct pw_proxy *proxy = object; struct node_data *data = proxy->user_data; @@ -900,20 +901,17 @@ client_node_port_add_mem(void *object, m = find_mem(port, mem_id); if (m) { - pw_log_debug("update mem %u, fd %d, flags %d, off %d, size %d", - mem_id, memfd, flags, offset, size); + pw_log_debug("update mem %u, fd %d, flags %d", + mem_id, memfd, flags); clear_memid(m); } else { m = pw_array_add(&port->mem_ids, sizeof(struct mem_id)); - pw_log_debug("add mem %u, fd %d, flags %d, off %d, size %d", - mem_id, memfd, flags, offset, size); + pw_log_debug("add mem %u, fd %d, flags %d", + mem_id, memfd, flags); } m->id = mem_id; m->fd = memfd; m->flags = flags; - m->ptr = NULL; - m->offset = offset; - m->size = size; } static void @@ -928,6 +926,7 @@ client_node_port_use_buffers(void *object, uint32_t i, j, len; struct spa_buffer *b, **bufs; struct port *port; + struct pw_type *t = &proxy->remote->core->type; int res, prot; port = find_port(data, direction, port_id); @@ -954,22 +953,23 @@ client_node_port_use_buffers(void *object, continue; } - if (mid->ptr == NULL) { - mid->ptr = - mmap(NULL, mid->size + mid->offset, prot, MAP_SHARED, mid->fd, 0); - if (mid->ptr == MAP_FAILED) { - mid->ptr = NULL; - pw_log_warn("Failed to mmap memory %d %p: %s", mid->size, mid, - strerror(errno)); - continue; - } - } len = pw_array_get_len(&port->buffer_ids, struct buffer_id); bid = pw_array_add(&port->buffer_ids, sizeof(struct buffer_id)); + bid->offset = buffers[i].offset; + bid->size = buffers[i].size; + bid->ptr = mmap(NULL, bid->offset + bid->size, prot, MAP_SHARED, mid->fd, 0); + if (bid->ptr == MAP_FAILED) { + bid->ptr = NULL; + pw_log_warn("Failed to mmap memory %u %p: %s", bid->size, mid, + strerror(errno)); + continue; + } + if (mlock(bid->ptr, bid->offset + bid->size) < 0) + pw_log_warn("Failed to lock memory %u %s", bid->offset + bid->size, strerror(errno)); + b = buffers[i].buffer; - bid->buf_ptr = SPA_MEMBER(mid->ptr, mid->offset + buffers[i].offset, void); { size_t size; @@ -992,13 +992,13 @@ client_node_port_use_buffers(void *object, if (bid->id != len) { pw_log_warn("unexpected id %u found, expected %u", bid->id, len); } - pw_log_debug("add buffer %d %d %u", mid->id, bid->id, buffers[i].offset); + pw_log_debug("add buffer %d %d %u %u", mid->id, bid->id, bid->offset, bid->size); - offset = 0; + offset = bid->offset; for (j = 0; j < b->n_metas; j++) { struct spa_meta *m = &b->metas[j]; memcpy(m, &buffers[i].buffer->metas[j], sizeof(struct spa_meta)); - m->data = SPA_MEMBER(bid->buf_ptr, offset, void); + m->data = SPA_MEMBER(bid->ptr, offset, void); offset += m->size; } @@ -1007,25 +1007,17 @@ client_node_port_use_buffers(void *object, memcpy(d, &buffers[i].buffer->datas[j], sizeof(struct spa_data)); d->chunk = - SPA_MEMBER(bid->buf_ptr, offset + sizeof(struct spa_chunk) * j, + SPA_MEMBER(bid->ptr, offset + sizeof(struct spa_chunk) * j, struct spa_chunk); - if (d->type == proxy->remote->core->type.data.Id) { + if (d->type == t->data.MemFd || d->type == t->data.DmaBuf) { struct mem_id *bmid = find_mem(port, SPA_PTR_TO_UINT32(d->data)); - void *map; - d->type = proxy->remote->core->type.data.MemFd; + d->data = NULL; d->fd = bmid->fd; - map = mmap(NULL, d->maxsize + d->mapoffset, prot, MAP_SHARED, d->fd, 0); - if (map == MAP_FAILED) { - pw_log_error("data %d failed to mmap memory %m", j); - res = errno; - goto done; - } - d->data = SPA_MEMBER(map, d->mapoffset, uint8_t); - pw_log_debug(" data %d %u -> fd %d mem %p", j, bmid->id, bmid->fd, map); - } else if (d->type == proxy->remote->core->type.data.MemPtr) { - d->data = SPA_MEMBER(bid->buf_ptr, SPA_PTR_TO_INT(d->data), void); + pw_log_debug(" data %d %u -> fd %d", j, bmid->id, bmid->fd); + } else if (d->type == t->data.MemPtr) { + d->data = SPA_MEMBER(bid->ptr, bid->offset + SPA_PTR_TO_INT(d->data), void); d->fd = -1; pw_log_debug(" data %d %u -> mem %p", j, bid->id, d->data); } else { @@ -1076,6 +1068,7 @@ client_node_port_set_io(void *object, struct node_data *data = proxy->user_data; struct port *port; struct mem_id *mid; + void *ptr; port = find_port(data, direction, port_id); if (port == NULL) @@ -1087,21 +1080,17 @@ client_node_port_set_io(void *object, return; } - if (mid->ptr == NULL) { - 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; - pw_log_warn("Failed to mmap memory %d %p: %s", mid->size, mid, - strerror(errno)); - return; - } + ptr = mmap(NULL, offset + size, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_LOCKED, mid->fd, 0); + if (ptr == MAP_FAILED) { + pw_log_warn("Failed to mmap memory %d %p: %s", size, mid, + strerror(errno)); + return; } spa_node_port_set_io(port->port->node->node, direction, port_id, id, - SPA_MEMBER(mid->ptr, offset, void), + SPA_MEMBER(ptr, offset, void), size); } diff --git a/src/pipewire/stream.c b/src/pipewire/stream.c index 1b8f2ccdc..96a0ddbc1 100644 --- a/src/pipewire/stream.c +++ b/src/pipewire/stream.c @@ -46,17 +46,16 @@ struct mem_id { uint32_t id; int fd; uint32_t flags; - void *ptr; - uint32_t offset; - uint32_t size; }; struct buffer_id { struct spa_list link; uint32_t id; bool used; - void *buf_ptr; struct spa_buffer *buf; + void *ptr; + uint32_t offset; + uint32_t size; }; struct stream { @@ -109,9 +108,6 @@ struct stream { static void clear_memid(struct stream *impl, struct mem_id *mid) { - if (mid->ptr != NULL) - munmap(mid->ptr, mid->size + mid->offset); - mid->ptr = NULL; if (mid->fd != -1) { bool has_ref = false; int fd; @@ -149,6 +145,10 @@ static void clear_buffers(struct pw_stream *stream) pw_array_for_each(bid, &impl->buffer_ids) { spa_hook_list_call(&stream->listener_list, struct pw_stream_events, remove_buffer, bid->id); + if (bid->ptr != NULL) + if (munmap(bid->ptr, bid->size + bid->offset) < 0) + pw_log_warn("failed to unmap buffer: %m"); + bid->ptr = NULL; free(bid->buf); bid->buf = NULL; bid->used = false; @@ -797,7 +797,7 @@ static void client_node_port_add_mem(void *data, enum spa_direction direction, uint32_t port_id, uint32_t mem_id, - uint32_t type, int memfd, uint32_t flags, uint32_t offset, uint32_t size) + uint32_t type, int memfd, uint32_t flags) { struct stream *impl = data; struct pw_stream *stream = &impl->this; @@ -805,20 +805,17 @@ client_node_port_add_mem(void *data, m = find_mem(stream, mem_id); if (m) { - pw_log_debug("update mem %u, fd %d, flags %d, off %d, size %d", - mem_id, memfd, flags, offset, size); + pw_log_debug("update mem %u, fd %d, flags %d", + mem_id, memfd, flags); clear_memid(impl, m); } else { m = pw_array_add(&impl->mem_ids, sizeof(struct mem_id)); - pw_log_debug("add mem %u, fd %d, flags %d, off %d, size %d", - mem_id, memfd, flags, offset, size); + pw_log_debug("add mem %u, fd %d, flags %d", + mem_id, memfd, flags); } m->id = mem_id; m->fd = memfd; m->flags = flags; - m->ptr = NULL; - m->offset = offset; - m->size = size; } static void @@ -829,6 +826,7 @@ client_node_port_use_buffers(void *data, { struct stream *impl = data; struct pw_stream *stream = &impl->this; + struct pw_type *t = &stream->remote->core->type; struct buffer_id *bid; uint32_t i, j, len; struct spa_buffer *b; @@ -848,16 +846,6 @@ client_node_port_use_buffers(void *data, continue; } - if (mid->ptr == NULL) { - mid->ptr = - mmap(NULL, mid->size + mid->offset, prot, MAP_SHARED, mid->fd, 0); - if (mid->ptr == MAP_FAILED) { - mid->ptr = NULL; - pw_log_warn("Failed to mmap memory %d %p: %s", mid->size, mid, - strerror(errno)); - continue; - } - } len = pw_array_get_len(&impl->buffer_ids, struct buffer_id); bid = pw_array_add(&impl->buffer_ids, sizeof(struct buffer_id)); if (impl->direction == SPA_DIRECTION_OUTPUT) { @@ -869,7 +857,17 @@ client_node_port_use_buffers(void *data, b = buffers[i].buffer; - bid->buf_ptr = SPA_MEMBER(mid->ptr, mid->offset + buffers[i].offset, void); + bid->offset = buffers[i].offset; + bid->size = buffers[i].size; + + bid->ptr = mmap(NULL, bid->offset + bid->size, prot, MAP_SHARED, mid->fd, 0); + if (bid->ptr == MAP_FAILED) { + bid->ptr = NULL; + pw_log_warn("Failed to mmap memory %d %p: %s", bid->size, mid, + strerror(errno)); + continue; + } + { size_t size; @@ -893,13 +891,13 @@ client_node_port_use_buffers(void *data, pw_log_warn("unexpected id %u found, expected %u", bid->id, len); impl->in_order = false; } - pw_log_debug("add buffer %d %d %u", mid->id, bid->id, buffers[i].offset); + pw_log_debug("add buffer %d %d %u %u", mid->id, bid->id, bid->offset, bid->size); - offset = 0; + offset = bid->offset; for (j = 0; j < b->n_metas; j++) { struct spa_meta *m = &b->metas[j]; memcpy(m, &buffers[i].buffer->metas[j], sizeof(struct spa_meta)); - m->data = SPA_MEMBER(bid->buf_ptr, offset, void); + m->data = SPA_MEMBER(bid->ptr, offset, void); offset += m->size; } @@ -908,17 +906,16 @@ client_node_port_use_buffers(void *data, memcpy(d, &buffers[i].buffer->datas[j], sizeof(struct spa_data)); d->chunk = - SPA_MEMBER(bid->buf_ptr, offset + sizeof(struct spa_chunk) * j, + SPA_MEMBER(bid->ptr, offset + sizeof(struct spa_chunk) * j, struct spa_chunk); - if (d->type == stream->remote->core->type.data.Id) { + if (d->type == t->data.MemFd || d->type == t->data.DmaBuf) { struct mem_id *bmid = find_mem(stream, SPA_PTR_TO_UINT32(d->data)); - d->type = stream->remote->core->type.data.MemFd; d->data = NULL; d->fd = bmid->fd; pw_log_debug(" data %d %u -> fd %d", j, bmid->id, bmid->fd); - } else if (d->type == stream->remote->core->type.data.MemPtr) { - d->data = SPA_MEMBER(bid->buf_ptr, SPA_PTR_TO_INT(d->data), void); + } else if (d->type == t->data.MemPtr) { + d->data = SPA_MEMBER(bid->ptr, bid->offset + SPA_PTR_TO_INT(d->data), void); d->fd = -1; pw_log_debug(" data %d %u -> mem %p", j, bid->id, d->data); } else {