From 05e06f16bacdd30a4c807f51fd9dae86cab4fcea Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Wed, 16 Dec 2020 12:53:11 +0100 Subject: [PATCH] audioconvert: improve channel remap some more See #461 --- spa/plugins/audioconvert/fmtconvert.c | 54 +++++++++++++-------------- spa/plugins/audioconvert/merger.c | 38 +++++++++++-------- spa/plugins/audioconvert/splitter.c | 43 ++++++++++----------- 3 files changed, 66 insertions(+), 69 deletions(-) diff --git a/spa/plugins/audioconvert/fmtconvert.c b/spa/plugins/audioconvert/fmtconvert.c index 65f97eda6..4e31266cc 100644 --- a/spa/plugins/audioconvert/fmtconvert.c +++ b/spa/plugins/audioconvert/fmtconvert.c @@ -119,8 +119,8 @@ struct impl { struct port ports[2][1]; - uint32_t remap[SPA_AUDIO_MAX_CHANNELS]; - uint32_t noremap[SPA_AUDIO_MAX_CHANNELS]; + uint32_t src_remap[SPA_AUDIO_MAX_CHANNELS]; + uint32_t dst_remap[SPA_AUDIO_MAX_CHANNELS]; uint32_t cpu_flags; struct convert conv; @@ -174,12 +174,12 @@ static int setup_convert(struct impl *this) return -EINVAL; for (i = 0; i < informat.info.raw.channels; i++) { - this->noremap[i] = i; for (j = 0; j < outformat.info.raw.channels; j++) { if (informat.info.raw.position[i] != outformat.info.raw.position[j]) continue; - this->remap[i] = j; + this->src_remap[j] = i; + this->dst_remap[i] = j; spa_log_debug(this->log, NAME " %p: channel %d -> %d (%s -> %s)", this, i, j, spa_debug_type_find_short_name(spa_type_audio_channel, @@ -198,11 +198,11 @@ static int setup_convert(struct impl *this) if ((res = convert_init(&this->conv)) < 0) return res; - spa_log_debug(this->log, NAME " %p: got converter features %08x:%08x", this, - this->cpu_flags, this->conv.cpu_flags); - this->is_passthrough = this->conv.is_passthrough; + spa_log_debug(this->log, NAME " %p: got converter features %08x:%08x passthrough:%d", this, + this->cpu_flags, this->conv.cpu_flags, this->is_passthrough); + return 0; } @@ -826,9 +826,9 @@ static int impl_node_process(void *object) struct buffer *inbuf, *outbuf; struct spa_buffer *inb, *outb; const void **src_datas; - void **dst_datas, *ptr; + void **dst_datas; uint32_t i, n_src_datas, n_dst_datas; - uint32_t n_samples, size, maxsize, offs, *src_remap, *dst_remap; + uint32_t n_samples, size, maxsize, offs; spa_return_val_if_fail(this != NULL, -EINVAL); @@ -874,22 +874,13 @@ static int impl_node_process(void *object) n_dst_datas = outb->n_datas; dst_datas = alloca(sizeof(void*) * n_dst_datas); - if (n_src_datas > 1) { - src_remap = this->remap; - dst_remap = this->noremap; - } else if (n_dst_datas > 1) { - src_remap = this->noremap; - dst_remap = this->remap; - } else { - src_remap = dst_remap = this->noremap; - } - size = UINT32_MAX; for (i = 0; i < n_src_datas; i++) { - offs = SPA_MIN(inb->datas[i].chunk->offset, inb->datas[i].maxsize); - size = SPA_MIN(size, SPA_MIN(inb->datas[i].maxsize - offs, inb->datas[i].chunk->size)); - ptr = SPA_MEMBER(inb->datas[i].data, offs, void); - src_datas[src_remap[i]] = ptr; + struct spa_data *sd = &inb->datas[i]; + uint32_t src_remap = n_src_datas > 1 ? this->src_remap[i] : 0; + offs = SPA_MIN(sd->chunk->offset, sd->maxsize); + size = SPA_MIN(size, SPA_MIN(sd->maxsize - offs, sd->chunk->size)); + src_datas[src_remap] = SPA_MEMBER(sd->data, offs, void); } n_samples = size / inport->stride; @@ -901,13 +892,18 @@ static int impl_node_process(void *object) this->is_passthrough); for (i = 0; i < n_dst_datas; i++) { - ptr = this->is_passthrough ? (void*)src_datas[i] : outbuf->datas[i]; - outb->datas[i].data = ptr; - outb->datas[i].chunk->offset = 0; - outb->datas[i].chunk->size = n_samples * outport->stride; - dst_datas[dst_remap[i]] = ptr; - } + uint32_t dst_remap = n_dst_datas > 1 ? this->dst_remap[i] : 0; + uint32_t src_remap = n_src_datas > 1 ? i : 0; + struct spa_data *dd = outb->datas; + if (this->is_passthrough) + dd[i].data = (void *)src_datas[src_remap]; + else + dst_datas[dst_remap] = dd[i].data = outbuf->datas[i]; + + dd[i].chunk->offset = 0; + dd[i].chunk->size = n_samples * outport->stride; + } if (!this->is_passthrough) convert_process(&this->conv, dst_datas, src_datas, n_samples); diff --git a/spa/plugins/audioconvert/merger.c b/spa/plugins/audioconvert/merger.c index 926ba7a02..c286a67e6 100644 --- a/spa/plugins/audioconvert/merger.c +++ b/spa/plugins/audioconvert/merger.c @@ -41,7 +41,6 @@ #include #include #include -#include #include #include "fmt-ops.h" @@ -118,7 +117,8 @@ struct impl { unsigned int started:1; unsigned int monitor:1; - uint32_t remap[SPA_AUDIO_MAX_CHANNELS]; + uint32_t src_remap[SPA_AUDIO_MAX_CHANNELS]; + uint32_t dst_remap[SPA_AUDIO_MAX_CHANNELS]; float empty[MAX_SAMPLES + MAX_ALIGN]; }; @@ -620,7 +620,8 @@ static int setup_convert(struct impl *this) if (informat.info.raw.position[i] != outformat.info.raw.position[j]) continue; - this->remap[i] = j; + this->src_remap[j] = i; + this->dst_remap[i] = j; spa_log_debug(this->log, NAME " %p: channel %d -> %d (%s -> %s)", this, i, j, spa_debug_type_find_short_name(spa_type_audio_channel, @@ -996,7 +997,7 @@ static int impl_node_process(void *object) struct buffer *sbuf, *dbuf; uint32_t n_src_datas, n_dst_datas; const void **src_datas; - void **dst_datas, **tmp; + void **dst_datas; int res; spa_return_val_if_fail(this != NULL, -EINVAL); @@ -1021,25 +1022,25 @@ static int impl_node_process(void *object) else n_samples = maxsize / outport->stride; - src_datas = alloca(sizeof(void*) * this->port_count); n_dst_datas = dbuf->buf->n_datas; dst_datas = alloca(sizeof(void*) * n_dst_datas); - tmp = alloca(sizeof(void*) * n_dst_datas); + + n_src_datas = this->port_count; + src_datas = alloca(sizeof(void*) * this->port_count); /* produce more output if possible */ - n_src_datas = 0; - for (i = 0; i < this->port_count; i++) { + for (i = 0; i < n_src_datas; i++) { struct port *inport = GET_IN_PORT(this, i); if (SPA_UNLIKELY(get_in_buffer(this, inport, &sbuf) < 0)) { - src_datas[n_src_datas++] = SPA_PTR_ALIGN(this->empty, MAX_ALIGN, void); + src_datas[i] = SPA_PTR_ALIGN(this->empty, MAX_ALIGN, void); continue; } sd = &sbuf->buf->datas[0]; - src_datas[n_src_datas++] = SPA_MEMBER(sd->data, sd->chunk->offset, void); + src_datas[i] = SPA_MEMBER(sd->data, sd->chunk->offset, void); n_samples = SPA_MIN(n_samples, sd->chunk->size / inport->stride); @@ -1051,13 +1052,18 @@ static int impl_node_process(void *object) handle_monitor(this, src_datas[i], n_samples, GET_OUT_PORT(this, i + 1)); for (i = 0; i < n_dst_datas; i++) { - tmp[i] = this->is_passthrough ? (void*)src_datas[i] : dbuf->datas[i]; - dbuf->buf->datas[i].data = tmp[i]; - dbuf->buf->datas[i].chunk->offset = 0; - dbuf->buf->datas[i].chunk->size = n_samples * outport->stride; + uint32_t dst_remap = this->dst_remap[i]; + uint32_t src_remap = this->src_remap[i]; + struct spa_data *dd = dbuf->buf->datas; + + if (this->is_passthrough) + dd[i].data = (void *)src_datas[src_remap]; + else + dst_datas[dst_remap] = dd[i].data = dbuf->datas[i]; + + dd[i].chunk->offset = 0; + dd[i].chunk->size = n_samples * outport->stride; } - for (i = 0; i < n_dst_datas; i++) - dst_datas[i] = tmp[this->remap[i]]; spa_log_trace_fp(this->log, NAME " %p: n_src:%d n_dst:%d n_samples:%d max:%d p:%d", this, n_src_datas, n_dst_datas, n_samples, maxsize, this->is_passthrough); diff --git a/spa/plugins/audioconvert/splitter.c b/spa/plugins/audioconvert/splitter.c index abf78f551..1906e5669 100644 --- a/spa/plugins/audioconvert/splitter.c +++ b/spa/plugins/audioconvert/splitter.c @@ -39,7 +39,6 @@ #include #include #include -#include #include #include "fmt-ops.h" @@ -117,7 +116,8 @@ struct impl { unsigned int is_passthrough:1; unsigned int started:1; - uint32_t remap[SPA_AUDIO_MAX_CHANNELS]; + uint32_t src_remap[SPA_AUDIO_MAX_CHANNELS]; + uint32_t dst_remap[SPA_AUDIO_MAX_CHANNELS]; float empty[MAX_SAMPLES + MAX_ALIGN]; }; @@ -602,7 +602,8 @@ static int setup_convert(struct impl *this) if (informat.info.raw.position[i] != outformat.info.raw.position[j]) continue; - this->remap[i] = j; + this->src_remap[i] = j; + this->dst_remap[j] = i; spa_log_debug(this->log, NAME " %p: channel %d -> %d (%s -> %s)", this, i, j, spa_debug_type_find_short_name(spa_type_audio_channel, @@ -881,12 +882,12 @@ static int impl_node_process(void *object) struct impl *this = object; struct port *inport; struct spa_io_buffers *inio; - uint32_t i, j, maxsize, n_samples; + uint32_t i, maxsize, n_samples; struct spa_data *sd, *dd; struct buffer *sbuf, *dbuf; uint32_t n_src_datas, n_dst_datas; const void **src_datas; - void **dst_datas, **tmp; + void **dst_datas; int res = 0; spa_return_val_if_fail(this != NULL, -EINVAL); @@ -919,13 +920,14 @@ static int impl_node_process(void *object) } n_samples = maxsize / inport->stride; - dst_datas = alloca(sizeof(void*) * MAX_PORTS); - tmp = alloca(sizeof(void*) * MAX_PORTS); + n_dst_datas = this->port_count; + dst_datas = alloca(sizeof(void*) * n_dst_datas); - n_dst_datas = 0; - for (i = 0; i < this->port_count; i++) { + for (i = 0; i < n_dst_datas; i++) { struct port *outport = GET_OUT_PORT(this, i); struct spa_io_buffers *outio; + uint32_t src_remap = this->src_remap[i]; + uint32_t dst_remap = this->dst_remap[i]; if (SPA_UNLIKELY((outio = outport->io) == NULL)) goto empty; @@ -947,7 +949,7 @@ static int impl_node_process(void *object) outio->status = -EPIPE; empty: spa_log_trace_fp(this->log, NAME" %p: %d skip output", this, i); - tmp[n_dst_datas++] = SPA_PTR_ALIGN(this->empty, MAX_ALIGN, void); + dst_datas[dst_remap] = SPA_PTR_ALIGN(this->empty, MAX_ALIGN, void); continue; } @@ -956,25 +958,18 @@ static int impl_node_process(void *object) maxsize = dd->maxsize; n_samples = SPA_MIN(n_samples, maxsize / outport->stride); - for (j = 0; j < dbuf->buf->n_datas; j++) { - tmp[n_dst_datas] = this->is_passthrough ? - (void *)src_datas[n_dst_datas] : - dbuf->datas[j]; - dd[j].data = tmp[n_dst_datas++]; - dd[j].chunk->offset = 0; - dd[j].chunk->size = n_samples * outport->stride; - } + if (this->is_passthrough) + dd[0].data = (void *)src_datas[src_remap]; + else + dst_datas[dst_remap] = dd[0].data = dbuf->datas[0]; + + dd[0].chunk->offset = 0; + dd[0].chunk->size = n_samples * outport->stride; outio->status = SPA_STATUS_HAVE_DATA; outio->buffer_id = dbuf->id; res |= SPA_STATUS_HAVE_DATA; } - while (n_dst_datas < this->port_count) { - spa_log_trace_fp(this->log, NAME" %p: %d fill output", this, n_dst_datas); - tmp[n_dst_datas++] = SPA_PTR_ALIGN(this->empty, MAX_ALIGN, void); - } - for (i = 0; i < this->port_count; i++) - dst_datas[i] = tmp[this->remap[i]]; spa_log_trace_fp(this->log, NAME " %p: n_src:%d n_dst:%d n_samples:%d max:%d stride:%d p:%d", this, n_src_datas, n_dst_datas, n_samples, maxsize, inport->stride,