mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2026-06-13 14:33:03 -04:00
audiomixer: allocate DSP mixer port buffers dynamically
Like the audioconvert node, the DSP mixer embedded a fixed buffers[MAX_BUFFERS] array (MAX_BUFFERS == 64) in struct port, each struct buffer holding datas[MAX_DATAS] (MAX_DATAS == 64), reserving ~37 KB per port regardless of the actual buffer/channel count. A DSP mixer port is created for every link set that mixes into a port, so this adds up. Allocate the buffer table and the per-buffer data-pointer pool in a single calloc in port_use_buffers(), sized to the real number of buffers and their data blocks, and release it in clear_buffers(). remove_port() now clears the port before zeroing it so a pooled port does not leak its allocation, and impl_clear() clears the input and output ports on teardown. Mirrors the audioconvert dynamic-allocation change. Co-authored-by: Copilot copilot@github.com Change-Id: I47286a36ae60cc10d520c0cd500fcd00d6d37657
This commit is contained in:
parent
65a5fa0250
commit
476d068738
1 changed files with 34 additions and 7 deletions
|
|
@ -58,7 +58,7 @@ struct buffer {
|
||||||
struct spa_meta_header *h;
|
struct spa_meta_header *h;
|
||||||
struct spa_buffer buf;
|
struct spa_buffer buf;
|
||||||
|
|
||||||
void *datas[MAX_DATAS];
|
void **datas;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct port {
|
struct port {
|
||||||
|
|
@ -77,7 +77,7 @@ struct port {
|
||||||
|
|
||||||
unsigned int have_format:1;
|
unsigned int have_format:1;
|
||||||
|
|
||||||
struct buffer buffers[MAX_BUFFERS];
|
struct buffer *buffers;
|
||||||
uint32_t n_buffers;
|
uint32_t n_buffers;
|
||||||
|
|
||||||
struct spa_list queue;
|
struct spa_list queue;
|
||||||
|
|
@ -141,6 +141,8 @@ struct impl {
|
||||||
#define GET_PORT(this,d,p) (d == SPA_DIRECTION_INPUT ? GET_IN_PORT(this,p) : GET_OUT_PORT(this,p))
|
#define GET_PORT(this,d,p) (d == SPA_DIRECTION_INPUT ? GET_IN_PORT(this,p) : GET_OUT_PORT(this,p))
|
||||||
#define GET_PORT_ANY(this,d,p) (CHECK_ANY_IN(this,d,p) ? NULL : GET_PORT(this,d,p))
|
#define GET_PORT_ANY(this,d,p) (CHECK_ANY_IN(this,d,p) ? NULL : GET_PORT(this,d,p))
|
||||||
|
|
||||||
|
static int clear_buffers(struct impl *this, struct port *port);
|
||||||
|
|
||||||
static int impl_node_enum_params(void *object, int seq,
|
static int impl_node_enum_params(void *object, int seq,
|
||||||
uint32_t id, uint32_t start, uint32_t num,
|
uint32_t id, uint32_t start, uint32_t num,
|
||||||
const struct spa_pod *filter)
|
const struct spa_pod *filter)
|
||||||
|
|
@ -313,6 +315,7 @@ impl_node_remove_port(void *object, enum spa_direction direction, uint32_t port_
|
||||||
if (--this->n_formats == 0)
|
if (--this->n_formats == 0)
|
||||||
this->have_format = false;
|
this->have_format = false;
|
||||||
}
|
}
|
||||||
|
clear_buffers(this, port);
|
||||||
spa_memzero(port, sizeof(struct port));
|
spa_memzero(port, sizeof(struct port));
|
||||||
spa_list_append(&this->free_list, &port->link);
|
spa_list_append(&this->free_list, &port->link);
|
||||||
|
|
||||||
|
|
@ -475,6 +478,8 @@ static int clear_buffers(struct impl *this, struct port *port)
|
||||||
SPA_FLAG_CLEAR(b->flags, BUFFER_FLAG_MAPPED);
|
SPA_FLAG_CLEAR(b->flags, BUFFER_FLAG_MAPPED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
free(port->buffers);
|
||||||
|
port->buffers = NULL;
|
||||||
port->n_buffers = 0;
|
port->n_buffers = 0;
|
||||||
spa_list_init(&port->queue);
|
spa_list_init(&port->queue);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -628,16 +633,36 @@ impl_node_port_use_buffers(void *object,
|
||||||
|
|
||||||
clear_buffers(this, port);
|
clear_buffers(this, port);
|
||||||
|
|
||||||
|
if (n_buffers > 0) {
|
||||||
|
size_t buffers_size = n_buffers * sizeof(struct buffer);
|
||||||
|
size_t total_datas = 0;
|
||||||
|
void **datas;
|
||||||
|
|
||||||
|
for (i = 0; i < n_buffers; i++) {
|
||||||
|
if (buffers[i]->n_datas > MAX_DATAS) {
|
||||||
|
res = -ENOSPC;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
total_datas += buffers[i]->n_datas;
|
||||||
|
}
|
||||||
|
|
||||||
|
port->buffers = calloc(1, buffers_size + total_datas * sizeof(void*));
|
||||||
|
if (port->buffers == NULL) {
|
||||||
|
res = -errno;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
datas = SPA_PTROFF(port->buffers, buffers_size, void*);
|
||||||
|
for (i = 0; i < n_buffers; i++) {
|
||||||
|
port->buffers[i].datas = datas;
|
||||||
|
datas += buffers[i]->n_datas;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < n_buffers; i++) {
|
for (i = 0; i < n_buffers; i++) {
|
||||||
struct buffer *b;
|
struct buffer *b;
|
||||||
uint32_t n_datas = buffers[i]->n_datas;
|
uint32_t n_datas = buffers[i]->n_datas;
|
||||||
struct spa_data *d = buffers[i]->datas;
|
struct spa_data *d = buffers[i]->datas;
|
||||||
|
|
||||||
if (n_datas > MAX_DATAS) {
|
|
||||||
res = -ENOSPC;
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
b = &port->buffers[i];
|
b = &port->buffers[i];
|
||||||
b->buffer = buffers[i];
|
b->buffer = buffers[i];
|
||||||
b->flags = 0;
|
b->flags = 0;
|
||||||
|
|
@ -929,9 +954,11 @@ static int impl_clear(struct spa_handle *handle)
|
||||||
|
|
||||||
this = (struct impl *) handle;
|
this = (struct impl *) handle;
|
||||||
|
|
||||||
|
clear_buffers(this, GET_OUT_PORT(this, 0));
|
||||||
spa_list_insert_list(&this->free_list, &this->port_list);
|
spa_list_insert_list(&this->free_list, &this->port_list);
|
||||||
spa_list_consume(port, &this->free_list, link) {
|
spa_list_consume(port, &this->free_list, link) {
|
||||||
spa_list_remove(&port->link);
|
spa_list_remove(&port->link);
|
||||||
|
clear_buffers(this, port);
|
||||||
free(port);
|
free(port);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue