diff --git a/spa/plugins/audioconvert/audioconvert.c b/spa/plugins/audioconvert/audioconvert.c index 812ce5ecd..e086c30a7 100644 --- a/spa/plugins/audioconvert/audioconvert.c +++ b/spa/plugins/audioconvert/audioconvert.c @@ -140,7 +140,7 @@ struct buffer { uint32_t flags; struct spa_list link; struct spa_buffer *buf; - void *datas[MAX_DATAS]; + void **datas; }; struct port { @@ -162,7 +162,7 @@ struct port { struct spa_param_info params[N_PORT_PARAMS]; char position[16]; - struct buffer buffers[MAX_BUFFERS]; + struct buffer *buffers; uint32_t n_buffers; 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); } } + free(port->buffers); + port->buffers = NULL; port->n_buffers = 0; spa_list_init(&port->queue); return 0; @@ -3351,6 +3353,21 @@ impl_node_port_use_buffers(void *object, 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++) { struct buffer *b; 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; } -static void free_dir(struct dir *dir) +static void free_dir(struct impl *this, struct dir *dir) { uint32_t i; - for (i = 0; i < MAX_PORTS; i++) - free(dir->ports[i]); + for (i = 0; i < MAX_PORTS; i++) { + if (dir->ports[i] != NULL) { + clear_buffers(this, dir->ports[i]); + free(dir->ports[i]); + } + } if (dir->conv.free) convert_free(&dir->conv); free(dir->tag); @@ -4355,8 +4376,8 @@ static int impl_clear(struct spa_handle *handle) this = (struct impl *) handle; - free_dir(&this->dir[SPA_DIRECTION_INPUT]); - free_dir(&this->dir[SPA_DIRECTION_OUTPUT]); + free_dir(this, &this->dir[SPA_DIRECTION_INPUT]); + free_dir(this, &this->dir[SPA_DIRECTION_OUTPUT]); free_tmp(this); diff --git a/spa/plugins/audiomixer/mixer-dsp.c b/spa/plugins/audiomixer/mixer-dsp.c index d768c9bfb..f23851507 100644 --- a/spa/plugins/audiomixer/mixer-dsp.c +++ b/spa/plugins/audiomixer/mixer-dsp.c @@ -58,7 +58,7 @@ struct buffer { struct spa_meta_header *h; struct spa_buffer buf; - void *datas[MAX_DATAS]; + void **datas; }; struct port { @@ -77,7 +77,7 @@ struct port { unsigned int have_format:1; - struct buffer buffers[MAX_BUFFERS]; + struct buffer *buffers; uint32_t n_buffers; 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_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, uint32_t id, uint32_t start, uint32_t num, 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) this->have_format = false; } + clear_buffers(this, port); spa_memzero(port, sizeof(struct port)); 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); } } + free(port->buffers); + port->buffers = NULL; port->n_buffers = 0; spa_list_init(&port->queue); return 0; @@ -628,16 +633,36 @@ impl_node_port_use_buffers(void *object, 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++) { struct buffer *b; uint32_t n_datas = buffers[i]->n_datas; struct spa_data *d = buffers[i]->datas; - if (n_datas > MAX_DATAS) { - res = -ENOSPC; - goto error; - } - b = &port->buffers[i]; b->buffer = buffers[i]; b->flags = 0; @@ -929,9 +954,11 @@ static int impl_clear(struct spa_handle *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_consume(port, &this->free_list, link) { spa_list_remove(&port->link); + clear_buffers(this, port); free(port); } return 0;