mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	client-node: track memory for client
Keep track of the memory we sent to the client to only send memory once and choose better memid values.
This commit is contained in:
		
							parent
							
								
									059571cec0
								
							
						
					
					
						commit
						135a0a18d8
					
				
					 1 changed files with 96 additions and 35 deletions
				
			
		| 
						 | 
					@ -63,12 +63,21 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define CHECK_PORT_BUFFER(this,b,p)      (b < p->n_buffers)
 | 
					#define CHECK_PORT_BUFFER(this,b,p)      (b < p->n_buffers)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct mem {
 | 
				
			||||||
 | 
						uint32_t id;
 | 
				
			||||||
 | 
						int ref;
 | 
				
			||||||
 | 
						int fd;
 | 
				
			||||||
 | 
						uint32_t type;
 | 
				
			||||||
 | 
						uint32_t flags;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct buffer {
 | 
					struct buffer {
 | 
				
			||||||
	struct spa_buffer *outbuf;
 | 
						struct spa_buffer *outbuf;
 | 
				
			||||||
	struct spa_buffer buffer;
 | 
						struct spa_buffer buffer;
 | 
				
			||||||
	struct spa_meta metas[4];
 | 
						struct spa_meta metas[4];
 | 
				
			||||||
	struct spa_data datas[4];
 | 
						struct spa_data datas[4];
 | 
				
			||||||
	bool outstanding;
 | 
						bool outstanding;
 | 
				
			||||||
 | 
						struct mem *mem;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct port {
 | 
					struct port {
 | 
				
			||||||
| 
						 | 
					@ -112,7 +121,6 @@ struct node {
 | 
				
			||||||
	uint32_t n_params;
 | 
						uint32_t n_params;
 | 
				
			||||||
	struct spa_pod **params;
 | 
						struct spa_pod **params;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	uint32_t membase;
 | 
					 | 
				
			||||||
	uint32_t seq;
 | 
						uint32_t seq;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -131,6 +139,8 @@ struct impl {
 | 
				
			||||||
	struct spa_hook node_listener;
 | 
						struct spa_hook node_listener;
 | 
				
			||||||
	struct spa_hook resource_listener;
 | 
						struct spa_hook resource_listener;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct pw_array mems;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	int fds[2];
 | 
						int fds[2];
 | 
				
			||||||
	int other_fds[2];
 | 
						int other_fds[2];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -140,12 +150,67 @@ struct impl {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** \endcond */
 | 
					/** \endcond */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct mem *ensure_mem(struct impl *impl, int fd, uint32_t type, uint32_t flags)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct mem *m, *f = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pw_array_for_each(m, &impl->mems) {
 | 
				
			||||||
 | 
							if (m->ref <= 0)
 | 
				
			||||||
 | 
								f = m;
 | 
				
			||||||
 | 
							else if (m->fd == fd)
 | 
				
			||||||
 | 
								goto found;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (f == NULL) {
 | 
				
			||||||
 | 
							m = pw_array_add(&impl->mems, sizeof(struct mem));
 | 
				
			||||||
 | 
							m->id = pw_array_get_len(&impl->mems, struct mem) - 1;
 | 
				
			||||||
 | 
							m->ref = 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else {
 | 
				
			||||||
 | 
							m = f;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						m->fd = fd;
 | 
				
			||||||
 | 
						m->type = type;
 | 
				
			||||||
 | 
						m->flags = flags;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pw_client_node_resource_add_mem(impl->node.resource,
 | 
				
			||||||
 | 
										m->id,
 | 
				
			||||||
 | 
										type,
 | 
				
			||||||
 | 
										m->fd,
 | 
				
			||||||
 | 
										m->flags);
 | 
				
			||||||
 | 
					      found:
 | 
				
			||||||
 | 
						m->ref++;
 | 
				
			||||||
 | 
						return m;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int clear_buffers(struct node *this, struct port *port)
 | 
					static int clear_buffers(struct node *this, struct port *port)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (port->n_buffers) {
 | 
						uint32_t i, j;
 | 
				
			||||||
		spa_log_info(this->log, "node %p: clear buffers", this);
 | 
						struct impl *impl = this->impl;
 | 
				
			||||||
		port->n_buffers = 0;
 | 
						struct pw_type *t = impl->t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < port->n_buffers; i++) {
 | 
				
			||||||
 | 
							struct buffer *b = &port->buffers[i];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							spa_log_debug(this->log, "node %p: clear buffer %d", this, i);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for (j = 0; j < b->buffer.n_datas; j++) {
 | 
				
			||||||
 | 
								struct spa_data *d = &b->datas[j];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (d->type == t->data.DmaBuf ||
 | 
				
			||||||
 | 
								    d->type == t->data.MemFd) {
 | 
				
			||||||
 | 
									uint32_t id;
 | 
				
			||||||
 | 
									struct mem *m;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									id = SPA_PTR_TO_UINT32(b->buffer.datas[j].data);
 | 
				
			||||||
 | 
									m = pw_array_get_unchecked(&impl->mems, id, struct mem);
 | 
				
			||||||
 | 
									m->ref--;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							b->mem->ref--;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						port->n_buffers = 0;
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -434,8 +499,8 @@ impl_node_remove_port(struct spa_node *node, enum spa_direction direction, uint3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int
 | 
					static int
 | 
				
			||||||
impl_node_port_get_info(struct spa_node *node,
 | 
					impl_node_port_get_info(struct spa_node *node,
 | 
				
			||||||
			enum spa_direction direction,
 | 
								enum spa_direction direction, uint32_t port_id,
 | 
				
			||||||
			uint32_t port_id, const struct spa_port_info **info)
 | 
								const struct spa_port_info **info)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct node *this;
 | 
						struct node *this;
 | 
				
			||||||
	struct port *port;
 | 
						struct port *port;
 | 
				
			||||||
| 
						 | 
					@ -528,15 +593,18 @@ impl_node_port_set_io(struct spa_node *node,
 | 
				
			||||||
		      void *data, size_t size)
 | 
							      void *data, size_t size)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct node *this;
 | 
						struct node *this;
 | 
				
			||||||
 | 
						struct impl *impl;
 | 
				
			||||||
	struct pw_type *t;
 | 
						struct pw_type *t;
 | 
				
			||||||
	struct pw_memblock *mem;
 | 
						struct pw_memblock *mem;
 | 
				
			||||||
 | 
						struct mem *m;
 | 
				
			||||||
	uint32_t memid, mem_offset, mem_size;
 | 
						uint32_t memid, mem_offset, mem_size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (node == NULL)
 | 
						if (node == NULL)
 | 
				
			||||||
		return -EINVAL;
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	this = SPA_CONTAINER_OF(node, struct node, node);
 | 
						this = SPA_CONTAINER_OF(node, struct node, node);
 | 
				
			||||||
	t = this->impl->t;
 | 
						impl = this->impl;
 | 
				
			||||||
 | 
						t = impl->t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (this->resource == NULL)
 | 
						if (this->resource == NULL)
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
| 
						 | 
					@ -548,17 +616,13 @@ impl_node_port_set_io(struct spa_node *node,
 | 
				
			||||||
		if ((mem = pw_memblock_find(data)) == NULL)
 | 
							if ((mem = pw_memblock_find(data)) == NULL)
 | 
				
			||||||
			return -EINVAL;
 | 
								return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		memid = this->membase++;
 | 
					 | 
				
			||||||
		mem_offset = mem->offset;
 | 
							mem_offset = mem->offset;
 | 
				
			||||||
		if (mem->size - mem_offset < size)
 | 
							mem_size = mem->size;
 | 
				
			||||||
 | 
							if (mem_size - mem_offset < size)
 | 
				
			||||||
			return -EINVAL;
 | 
								return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		mem_size = mem->size;
 | 
							m = ensure_mem(impl, mem->fd, t->data.MemFd, mem->flags);
 | 
				
			||||||
 | 
							memid = m->id;
 | 
				
			||||||
		pw_client_node_resource_add_mem(this->resource,
 | 
					 | 
				
			||||||
						memid,
 | 
					 | 
				
			||||||
						t->data.MemFd,
 | 
					 | 
				
			||||||
						mem->fd, mem->flags);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	else {
 | 
						else {
 | 
				
			||||||
		memid = SPA_ID_INVALID;
 | 
							memid = SPA_ID_INVALID;
 | 
				
			||||||
| 
						 | 
					@ -618,7 +682,8 @@ impl_node_port_use_buffers(struct spa_node *node,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (i = 0; i < n_buffers; i++) {
 | 
						for (i = 0; i < n_buffers; i++) {
 | 
				
			||||||
		struct buffer *b = &port->buffers[i];
 | 
							struct buffer *b = &port->buffers[i];
 | 
				
			||||||
		struct pw_memblock *m;
 | 
							struct pw_memblock *mem;
 | 
				
			||||||
 | 
							struct mem *m;
 | 
				
			||||||
		size_t data_size, size;
 | 
							size_t data_size, size;
 | 
				
			||||||
		void *baseptr;
 | 
							void *baseptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -634,7 +699,7 @@ impl_node_port_use_buffers(struct spa_node *node,
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
			return -EINVAL;
 | 
								return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if ((m = pw_memblock_find(baseptr)) == NULL)
 | 
							if ((mem = pw_memblock_find(baseptr)) == NULL)
 | 
				
			||||||
			return -EINVAL;
 | 
								return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		data_size = 0;
 | 
							data_size = 0;
 | 
				
			||||||
| 
						 | 
					@ -648,15 +713,12 @@ impl_node_port_use_buffers(struct spa_node *node,
 | 
				
			||||||
				data_size += d->maxsize;
 | 
									data_size += d->maxsize;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		mb[i].buffer = &b->buffer;
 | 
							b->mem = m = ensure_mem(impl, mem->fd, t->data.MemFd, mem->flags);
 | 
				
			||||||
		mb[i].mem_id = this->membase++;
 | 
					 | 
				
			||||||
		mb[i].offset = SPA_PTRDIFF(baseptr, m->ptr + m->offset);
 | 
					 | 
				
			||||||
		mb[i].size = data_size;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		pw_client_node_resource_add_mem(this->resource,
 | 
							mb[i].buffer = &b->buffer;
 | 
				
			||||||
						mb[i].mem_id,
 | 
							mb[i].mem_id = m->id;
 | 
				
			||||||
						t->data.MemFd,
 | 
							mb[i].offset = SPA_PTRDIFF(baseptr, mem->ptr + mem->offset);
 | 
				
			||||||
						m->fd, m->flags);
 | 
							mb[i].size = data_size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for (j = 0; j < buffers[i]->n_metas; j++)
 | 
							for (j = 0; j < buffers[i]->n_metas; j++)
 | 
				
			||||||
			memcpy(&b->buffer.metas[j], &buffers[i]->metas[j], sizeof(struct spa_meta));
 | 
								memcpy(&b->buffer.metas[j], &buffers[i]->metas[j], sizeof(struct spa_meta));
 | 
				
			||||||
| 
						 | 
					@ -670,13 +732,8 @@ impl_node_port_use_buffers(struct spa_node *node,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (d->type == t->data.DmaBuf ||
 | 
								if (d->type == t->data.DmaBuf ||
 | 
				
			||||||
			    d->type == t->data.MemFd) {
 | 
								    d->type == t->data.MemFd) {
 | 
				
			||||||
				pw_client_node_resource_add_mem(this->resource,
 | 
									m = ensure_mem(impl, d->fd, d->type, d->flags);
 | 
				
			||||||
								this->membase,
 | 
									b->buffer.datas[j].data = SPA_UINT32_TO_PTR(m->id);
 | 
				
			||||||
								d->type,
 | 
					 | 
				
			||||||
								d->fd,
 | 
					 | 
				
			||||||
								d->flags);
 | 
					 | 
				
			||||||
				b->buffer.datas[j].data = SPA_UINT32_TO_PTR(this->membase);
 | 
					 | 
				
			||||||
				this->membase++;
 | 
					 | 
				
			||||||
			} else if (d->type == t->data.MemPtr) {
 | 
								} else if (d->type == t->data.MemPtr) {
 | 
				
			||||||
				b->buffer.datas[j].data = SPA_INT_TO_PTR(size);
 | 
									b->buffer.datas[j].data = SPA_INT_TO_PTR(size);
 | 
				
			||||||
				size += d->maxsize;
 | 
									size += d->maxsize;
 | 
				
			||||||
| 
						 | 
					@ -1158,6 +1215,8 @@ static void node_free(void *data)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spa_hook_remove(&impl->node_listener);
 | 
						spa_hook_remove(&impl->node_listener);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pw_array_clear(&impl->mems);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (impl->fds[0] != -1)
 | 
						if (impl->fds[0] != -1)
 | 
				
			||||||
		close(impl->fds[0]);
 | 
							close(impl->fds[0]);
 | 
				
			||||||
	if (impl->fds[1] != -1)
 | 
						if (impl->fds[1] != -1)
 | 
				
			||||||
| 
						 | 
					@ -1215,6 +1274,8 @@ struct pw_client_node *pw_client_node_new(struct pw_resource *resource,
 | 
				
			||||||
	node_init(&impl->node, NULL, support, n_support);
 | 
						node_init(&impl->node, NULL, support, n_support);
 | 
				
			||||||
	impl->node.impl = impl;
 | 
						impl->node.impl = impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pw_array_init(&impl->mems, 64);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((name = pw_properties_get(properties, "node.name")) == NULL)
 | 
						if ((name = pw_properties_get(properties, "node.name")) == NULL)
 | 
				
			||||||
		name = "client-node";
 | 
							name = "client-node";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue