Merge branch 'master' into 'master'

audioconvert: allocate port buffers dynamically

See merge request pipewire/pipewire!2858
This commit is contained in:
Torkel Niklasson 2026-06-12 18:19:59 +00:00
commit fc26f2a672
2 changed files with 62 additions and 14 deletions

View file

@ -140,7 +140,7 @@ struct buffer {
uint32_t flags; uint32_t flags;
struct spa_list link; struct spa_list link;
struct spa_buffer *buf; struct spa_buffer *buf;
void *datas[MAX_DATAS]; void **datas;
}; };
struct port { struct port {
@ -162,7 +162,7 @@ struct port {
struct spa_param_info params[N_PORT_PARAMS]; struct spa_param_info params[N_PORT_PARAMS];
char position[16]; char position[16];
struct buffer buffers[MAX_BUFFERS]; struct buffer *buffers;
uint32_t n_buffers; uint32_t n_buffers;
struct spa_latency_info latency[2]; struct spa_latency_info latency[2];
@ -3051,6 +3051,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;
@ -3351,6 +3353,21 @@ impl_node_port_use_buffers(void *object,
maxsize = this->quantum_limit * sizeof(float); maxsize = this->quantum_limit * sizeof(float);
if (n_buffers > 0) {
void **datas;
size_t buffers_size = n_buffers * sizeof(struct buffer);
port->buffers = calloc(1, buffers_size +
n_buffers * port->blocks * 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[i * port->blocks];
}
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;
@ -4336,11 +4353,15 @@ static int impl_get_interface(struct spa_handle *handle, const char *type, void
return 0; return 0;
} }
static void free_dir(struct dir *dir) static void free_dir(struct impl *this, struct dir *dir)
{ {
uint32_t i; uint32_t i;
for (i = 0; i < MAX_PORTS; i++) for (i = 0; i < MAX_PORTS; i++) {
free(dir->ports[i]); if (dir->ports[i] != NULL) {
clear_buffers(this, dir->ports[i]);
free(dir->ports[i]);
}
}
if (dir->conv.free) if (dir->conv.free)
convert_free(&dir->conv); convert_free(&dir->conv);
free(dir->tag); free(dir->tag);
@ -4355,8 +4376,8 @@ static int impl_clear(struct spa_handle *handle)
this = (struct impl *) handle; this = (struct impl *) handle;
free_dir(&this->dir[SPA_DIRECTION_INPUT]); free_dir(this, &this->dir[SPA_DIRECTION_INPUT]);
free_dir(&this->dir[SPA_DIRECTION_OUTPUT]); free_dir(this, &this->dir[SPA_DIRECTION_OUTPUT]);
free_tmp(this); free_tmp(this);

View file

@ -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;