mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-01 22:58:50 -04: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;
|
||||||
}
|
}
|
||||||
pw_log_info("input port %s[%d]:%s",
|
|
||||||
|
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",
|
||||||
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->desc = d;
|
gp = &graph->input[graph->n_input++];
|
||||||
gp->hndl = &port->node->hndl[i];
|
gp->desc = d;
|
||||||
gp->port = port->p;
|
gp->hndl = &port->node->hndl[i];
|
||||||
|
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;
|
||||||
|
|
||||||
for (i = 0; i < n_hndl; i++) {
|
if (!node->disabled) {
|
||||||
gh = &graph->hndl[graph->n_hndl++];
|
for (i = 0; i < n_hndl; i++) {
|
||||||
gh->hndl = &node->hndl[i];
|
gh = &graph->hndl[graph->n_hndl++];
|
||||||
gh->desc = d;
|
gh->hndl = &node->hndl[i];
|
||||||
|
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