mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	filter-chain: optimize copy plugin
A copy plugin at the input ports can be replaced by directly writing into the peer input ports so that we can avoid a memcpy.
This commit is contained in:
		
							parent
							
								
									f673764e58
								
							
						
					
					
						commit
						5f000b007d
					
				
					 3 changed files with 55 additions and 20 deletions
				
			
		| 
						 | 
					@ -505,6 +505,7 @@ struct node {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	unsigned int n_deps;
 | 
						unsigned int n_deps;
 | 
				
			||||||
	unsigned int visited:1;
 | 
						unsigned int visited:1;
 | 
				
			||||||
 | 
						unsigned int disabled:1;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct link {
 | 
					struct link {
 | 
				
			||||||
| 
						 | 
					@ -521,6 +522,7 @@ struct graph_port {
 | 
				
			||||||
	const struct fc_descriptor *desc;
 | 
						const struct fc_descriptor *desc;
 | 
				
			||||||
	void **hndl;
 | 
						void **hndl;
 | 
				
			||||||
	uint32_t port;
 | 
						uint32_t port;
 | 
				
			||||||
 | 
						unsigned next:1;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct graph_hndl {
 | 
					struct graph_hndl {
 | 
				
			||||||
| 
						 | 
					@ -599,7 +601,7 @@ static void playback_process(void *d)
 | 
				
			||||||
	struct impl *impl = d;
 | 
						struct impl *impl = d;
 | 
				
			||||||
	struct pw_buffer *in, *out;
 | 
						struct pw_buffer *in, *out;
 | 
				
			||||||
	struct graph *graph = &impl->graph;
 | 
						struct graph *graph = &impl->graph;
 | 
				
			||||||
	uint32_t i, insize = 0, outsize = 0, n_hndl = graph->n_hndl;
 | 
						uint32_t i, j, insize = 0, outsize = 0, n_hndl = graph->n_hndl;
 | 
				
			||||||
	int32_t stride = 0;
 | 
						int32_t stride = 0;
 | 
				
			||||||
	struct graph_port *port;
 | 
						struct graph_port *port;
 | 
				
			||||||
	struct spa_data *bd;
 | 
						struct spa_data *bd;
 | 
				
			||||||
| 
						 | 
					@ -613,7 +615,7 @@ static void playback_process(void *d)
 | 
				
			||||||
	if (in == NULL || out == NULL)
 | 
						if (in == NULL || out == NULL)
 | 
				
			||||||
		goto done;
 | 
							goto done;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (i = 0; i < in->buffer->n_datas; i++) {
 | 
						for (i = 0, j = 0; i < in->buffer->n_datas; i++) {
 | 
				
			||||||
		uint32_t offs, size;
 | 
							uint32_t offs, size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		bd = &in->buffer->datas[i];
 | 
							bd = &in->buffer->datas[i];
 | 
				
			||||||
| 
						 | 
					@ -621,12 +623,15 @@ static void playback_process(void *d)
 | 
				
			||||||
		offs = SPA_MIN(bd->chunk->offset, bd->maxsize);
 | 
							offs = SPA_MIN(bd->chunk->offset, bd->maxsize);
 | 
				
			||||||
		size = SPA_MIN(bd->chunk->size, bd->maxsize - offs);
 | 
							size = SPA_MIN(bd->chunk->size, bd->maxsize - offs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		port = i < graph->n_input ? &graph->input[i] : NULL;
 | 
							while (j < graph->n_input) {
 | 
				
			||||||
 | 
								port = &graph->input[j++];
 | 
				
			||||||
		if (port && port->desc)
 | 
								if (port->desc)
 | 
				
			||||||
				port->desc->connect_port(*port->hndl, port->port,
 | 
									port->desc->connect_port(*port->hndl, port->port,
 | 
				
			||||||
					SPA_PTROFF(bd->data, offs, void));
 | 
										SPA_PTROFF(bd->data, offs, void));
 | 
				
			||||||
 | 
								if (!port->next)
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		insize = i == 0 ? size : SPA_MIN(insize, size);
 | 
							insize = i == 0 ? size : SPA_MIN(insize, size);
 | 
				
			||||||
		stride = SPA_MAX(stride, bd->chunk->stride);
 | 
							stride = SPA_MAX(stride, bd->chunk->stride);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -1849,7 +1854,7 @@ static int setup_graph(struct graph *graph, struct spa_json *inputs, struct spa_
 | 
				
			||||||
		n_nodes++;
 | 
							n_nodes++;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	graph->n_input = 0;
 | 
						graph->n_input = 0;
 | 
				
			||||||
	graph->input = calloc(n_input * n_hndl, sizeof(struct graph_port));
 | 
						graph->input = calloc(n_input * 16 * n_hndl, sizeof(struct graph_port));
 | 
				
			||||||
	graph->n_output = 0;
 | 
						graph->n_output = 0;
 | 
				
			||||||
	graph->output = calloc(n_output * n_hndl, sizeof(struct graph_port));
 | 
						graph->output = calloc(n_output * n_hndl, sizeof(struct graph_port));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1869,8 +1874,8 @@ static int setup_graph(struct graph *graph, struct spa_json *inputs, struct spa_
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			struct spa_json it = *inputs;
 | 
								struct spa_json it = *inputs;
 | 
				
			||||||
			while (spa_json_get_string(&it, v, sizeof(v)) > 0) {
 | 
								while (spa_json_get_string(&it, v, sizeof(v)) > 0) {
 | 
				
			||||||
				gp = &graph->input[graph->n_input];
 | 
					 | 
				
			||||||
				if (spa_streq(v, "null")) {
 | 
									if (spa_streq(v, "null")) {
 | 
				
			||||||
 | 
										gp = &graph->input[graph->n_input++];
 | 
				
			||||||
					gp->desc = NULL;
 | 
										gp->desc = NULL;
 | 
				
			||||||
					pw_log_info("ignore input port %d", graph->n_input);
 | 
										pw_log_info("ignore input port %d", graph->n_input);
 | 
				
			||||||
				} else if ((port = find_port(first, v, FC_PORT_INPUT)) == NULL) {
 | 
									} else if ((port = find_port(first, v, FC_PORT_INPUT)) == NULL) {
 | 
				
			||||||
| 
						 | 
					@ -1893,14 +1898,41 @@ static int setup_graph(struct graph *graph, struct spa_json *inputs, struct spa_
 | 
				
			||||||
						res = -EBUSY;
 | 
											res = -EBUSY;
 | 
				
			||||||
						goto error;
 | 
											goto error;
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										if (d->flags & FC_DESCRIPTOR_COPY) {
 | 
				
			||||||
 | 
											for (j = 0; j < desc->n_output; j++) {
 | 
				
			||||||
 | 
												struct port *p = &port->node->output_port[j];
 | 
				
			||||||
 | 
												struct link *link;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
												gp = NULL;
 | 
				
			||||||
 | 
												spa_list_for_each(link, &p->link_list, output_link) {
 | 
				
			||||||
 | 
													struct port *peer = link->input;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
													pw_log_info("copy input port %s[%d]:%s",
 | 
				
			||||||
 | 
														port->node->name, i,
 | 
				
			||||||
 | 
														d->ports[port->p].name);
 | 
				
			||||||
 | 
													peer->external = graph->n_input;
 | 
				
			||||||
 | 
													gp = &graph->input[graph->n_input++];
 | 
				
			||||||
 | 
													gp->desc = peer->node->desc->desc;
 | 
				
			||||||
 | 
													gp->hndl = &peer->node->hndl[i];
 | 
				
			||||||
 | 
													gp->port = peer->p;
 | 
				
			||||||
 | 
													gp->next = true;
 | 
				
			||||||
 | 
												}
 | 
				
			||||||
 | 
												if (gp != NULL)
 | 
				
			||||||
 | 
													gp->next = false;
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
											port->node->disabled = true;
 | 
				
			||||||
 | 
										} else {
 | 
				
			||||||
						pw_log_info("input port %s[%d]:%s",
 | 
											pw_log_info("input port %s[%d]:%s",
 | 
				
			||||||
							port->node->name, i, d->ports[port->p].name);
 | 
												port->node->name, i, d->ports[port->p].name);
 | 
				
			||||||
						port->external = graph->n_input;
 | 
											port->external = graph->n_input;
 | 
				
			||||||
 | 
											gp = &graph->input[graph->n_input++];
 | 
				
			||||||
						gp->desc = d;
 | 
											gp->desc = d;
 | 
				
			||||||
						gp->hndl = &port->node->hndl[i];
 | 
											gp->hndl = &port->node->hndl[i];
 | 
				
			||||||
						gp->port = port->p;
 | 
											gp->port = port->p;
 | 
				
			||||||
 | 
											gp->next = false;
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				graph->n_input++;
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if (outputs == NULL) {
 | 
							if (outputs == NULL) {
 | 
				
			||||||
| 
						 | 
					@ -1965,11 +1997,12 @@ static int setup_graph(struct graph *graph, struct spa_json *inputs, struct spa_
 | 
				
			||||||
		desc = node->desc;
 | 
							desc = node->desc;
 | 
				
			||||||
		d = desc->desc;
 | 
							d = desc->desc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (!node->disabled) {
 | 
				
			||||||
			for (i = 0; i < n_hndl; i++) {
 | 
								for (i = 0; i < n_hndl; i++) {
 | 
				
			||||||
				gh = &graph->hndl[graph->n_hndl++];
 | 
									gh = &graph->hndl[graph->n_hndl++];
 | 
				
			||||||
				gh->hndl = &node->hndl[i];
 | 
									gh->hndl = &node->hndl[i];
 | 
				
			||||||
				gh->desc = d;
 | 
									gh->desc = d;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		for (i = 0; i < desc->n_output; i++) {
 | 
							for (i = 0; i < desc->n_output; i++) {
 | 
				
			||||||
			spa_list_for_each(link, &node->output_port[i].link_list, output_link)
 | 
								spa_list_for_each(link, &node->output_port[i].link_list, output_link)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -101,6 +101,7 @@ static struct fc_port copy_ports[] = {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const struct fc_descriptor copy_desc = {
 | 
					static const struct fc_descriptor copy_desc = {
 | 
				
			||||||
	.name = "copy",
 | 
						.name = "copy",
 | 
				
			||||||
 | 
						.flags = FC_DESCRIPTOR_COPY,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	.n_ports = 2,
 | 
						.n_ports = 2,
 | 
				
			||||||
	.ports = copy_ports,
 | 
						.ports = copy_ports,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -64,6 +64,7 @@ struct fc_port {
 | 
				
			||||||
struct fc_descriptor {
 | 
					struct fc_descriptor {
 | 
				
			||||||
	const char *name;
 | 
						const char *name;
 | 
				
			||||||
#define FC_DESCRIPTOR_SUPPORTS_NULL_DATA	(1ULL << 0)
 | 
					#define FC_DESCRIPTOR_SUPPORTS_NULL_DATA	(1ULL << 0)
 | 
				
			||||||
 | 
					#define FC_DESCRIPTOR_COPY			(1ULL << 1)
 | 
				
			||||||
	uint64_t flags;
 | 
						uint64_t flags;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void (*free) (const struct fc_descriptor *desc);
 | 
						void (*free) (const struct fc_descriptor *desc);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue