audioconvert: improve tmp buffer allocation

Use per port allocated memory so that we can easily increase the size
and add more buffers. This is necessary when we add filter-graphs that
require more ports.
This commit is contained in:
Wim Taymans 2025-03-21 15:17:15 +01:00
parent b8d5334462
commit de54cfc475

View file

@ -316,7 +316,7 @@ struct impl {
uint32_t scratch_ports;
float *empty;
float *scratch;
float *tmp[2];
float *tmp[2][MAX_PORTS];
float *tmp_datas[2][MAX_PORTS];
struct wav_file *wav_file;
@ -1057,6 +1057,83 @@ static int setup_filter_graph(struct impl *this, struct filter_graph *g,
static int setup_channelmix(struct impl *this, uint32_t channels, uint32_t *position);
static void free_tmp(struct impl *this)
{
uint32_t i;
spa_log_debug(this->log, "free tmp %d", this->scratch_size);
free(this->empty);
this->empty = NULL;
this->scratch_size = 0;
this->scratch_ports = 0;
free(this->scratch);
this->scratch = NULL;
for (i = 0; i < MAX_PORTS; i++) {
free(this->tmp[0][i]);
this->tmp[0][i] = NULL;
free(this->tmp[1][i]);
this->tmp[1][i] = NULL;
this->tmp_datas[0][i] = NULL;
this->tmp_datas[1][i] = NULL;
}
}
static int ensure_tmp(struct impl *this)
{
uint32_t maxsize = this->maxsize, maxports = this->maxports;
uint32_t i;
float *empty, *scratch, *tmp[2];
if (maxsize > this->scratch_size) {
spa_log_info(this->log, "resize tmp %d -> %d", this->scratch_size, maxsize);
if ((empty = realloc(this->empty, maxsize + MAX_ALIGN)) != NULL)
this->empty = empty;
if ((scratch = realloc(this->scratch, maxsize + MAX_ALIGN)) != NULL)
this->scratch = scratch;
if (empty == NULL || scratch == NULL) {
free_tmp(this);
return -ENOMEM;
}
memset(this->empty, 0, maxsize + MAX_ALIGN);
for (i = 0; i < this->scratch_ports; i++) {
if ((tmp[0] = realloc(this->tmp[0][i], maxsize + MAX_ALIGN)) != NULL)
this->tmp[0][i] = tmp[0];
if ((tmp[1] = realloc(this->tmp[1][i], maxsize + MAX_ALIGN)) != NULL)
this->tmp[1][i] = tmp[1];
if (tmp[0] == NULL || tmp[1] == NULL) {
free_tmp(this);
return -ENOMEM;
}
this->tmp_datas[0][i] = SPA_PTR_ALIGN(this->tmp[0][i], MAX_ALIGN, void);
this->tmp_datas[1][i] = SPA_PTR_ALIGN(this->tmp[1][i], MAX_ALIGN, void);
}
this->scratch_size = maxsize;
}
if (maxports > this->scratch_ports) {
spa_log_info(this->log, "resize ports %d -> %d", this->scratch_ports, maxports);
for (i = this->scratch_ports; i < maxports; i++) {
if ((tmp[0] = malloc(maxsize + MAX_ALIGN)) != NULL)
this->tmp[0][i] = tmp[0];
if ((tmp[1] = malloc(maxsize + MAX_ALIGN)) != NULL)
this->tmp[1][i] = tmp[1];
if (tmp[0] == NULL || tmp[1] == NULL) {
free_tmp(this);
return -ENOMEM;
}
this->tmp_datas[0][i] = SPA_PTR_ALIGN(this->tmp[0][i], MAX_ALIGN, void);
this->tmp_datas[0][i] = SPA_PTR_ALIGN(this->tmp[0][i], MAX_ALIGN, void);
}
this->scratch_ports = maxports;
}
return 0;
}
static int setup_filter_graphs(struct impl *impl)
{
int res;
@ -1084,6 +1161,8 @@ static int setup_filter_graphs(struct impl *impl)
impl->maxports = SPA_MAX(impl->maxports, channels);
}
}
if ((res = ensure_tmp(impl)) < 0)
return res;
if ((res = setup_channelmix(impl, channels, position)) < 0)
return res;
@ -2159,64 +2238,6 @@ static int setup_out_convert(struct impl *this)
return 0;
}
static void free_tmp(struct impl *this)
{
uint32_t i;
spa_log_debug(this->log, "free tmp %d", this->scratch_size);
free(this->empty);
this->empty = NULL;
this->scratch_size = 0;
this->scratch_ports = 0;
free(this->scratch);
this->scratch = NULL;
free(this->tmp[0]);
this->tmp[0] = NULL;
free(this->tmp[1]);
this->tmp[1] = NULL;
for (i = 0; i < MAX_PORTS; i++) {
this->tmp_datas[0][i] = NULL;
this->tmp_datas[1][i] = NULL;
}
}
static int ensure_tmp(struct impl *this)
{
uint32_t maxsize = this->maxsize, maxports = this->maxports;
if (maxsize > this->scratch_size || maxports > this->scratch_ports) {
float *empty, *scratch, *tmp[2];
uint32_t i;
spa_log_debug(this->log, "resize tmp %d -> %d", this->scratch_size, maxsize);
if ((empty = realloc(this->empty, maxsize + MAX_ALIGN)) != NULL)
this->empty = empty;
if ((scratch = realloc(this->scratch, maxsize + MAX_ALIGN)) != NULL)
this->scratch = scratch;
if ((tmp[0] = realloc(this->tmp[0], (maxsize + MAX_ALIGN) * maxports)) != NULL)
this->tmp[0] = tmp[0];
if ((tmp[1] = realloc(this->tmp[1], (maxsize + MAX_ALIGN) * maxports)) != NULL)
this->tmp[1] = tmp[1];
if (empty == NULL || scratch == NULL || tmp[0] == NULL || tmp[1] == NULL) {
free_tmp(this);
return -ENOMEM;
}
memset(this->empty, 0, maxsize + MAX_ALIGN);
this->scratch_size = maxsize;
this->scratch_ports = maxports;
for (i = 0; i < maxports; i++) {
this->tmp_datas[0][i] = SPA_PTROFF(tmp[0], maxsize * i, void);
this->tmp_datas[0][i] = SPA_PTR_ALIGN(this->tmp_datas[0][i], MAX_ALIGN, void);
this->tmp_datas[1][i] = SPA_PTROFF(tmp[1], maxsize * i, void);
this->tmp_datas[1][i] = SPA_PTR_ALIGN(this->tmp_datas[1][i], MAX_ALIGN, void);
}
}
return 0;
}
static uint32_t resample_update_rate_match(struct impl *this, bool passthrough, uint32_t size, uint32_t queued)
{
uint32_t delay, match_size;