From 7798cf7364af2497305e225efb471338aacb913e Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Thu, 17 Oct 2019 09:34:27 +0200 Subject: [PATCH] core: improve alignment Use the CPU alignment to align memory of allocated buffers. This makes it more likely that all CPU optimizations can be done. --- spa/plugins/audioconvert/audioadapter.c | 15 +++++++++++++-- spa/plugins/audioconvert/audioconvert.c | 18 +++++++++++++++++- spa/plugins/audioconvert/merger.c | 3 ++- spa/plugins/audiomixer/mixer-dsp.c | 16 +++++++++------- src/pipewire/buffers.c | 9 +++++++-- src/pipewire/core.c | 5 +++++ 6 files changed, 53 insertions(+), 13 deletions(-) diff --git a/spa/plugins/audioconvert/audioadapter.c b/spa/plugins/audioconvert/audioadapter.c index 569677053..e9bcf7e25 100644 --- a/spa/plugins/audioconvert/audioadapter.c +++ b/spa/plugins/audioconvert/audioadapter.c @@ -23,6 +23,7 @@ */ #include +#include #include #include @@ -44,7 +45,9 @@ struct impl { struct spa_node node; struct spa_log *log; + struct spa_cpu *cpu; + uint32_t max_align; enum spa_direction direction; struct spa_node *target; @@ -642,9 +645,9 @@ static int negotiate_buffers(struct impl *this) struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer)); uint32_t state; struct spa_pod *param; - int res, i; + int res; bool slave_alloc, conv_alloc; - int32_t size, buffers, blocks, align, flags; + uint32_t i, size, buffers, blocks, align, flags; uint32_t *aligns; struct spa_data *datas; uint32_t slave_flags, conv_flags; @@ -702,6 +705,8 @@ static int negotiate_buffers(struct impl *this) spa_log_debug(this->log, "%p: buffers %d, blocks %d, size %d, align %d %d:%d", this, buffers, blocks, size, align, slave_alloc, conv_alloc); + align = SPA_MAX(align, this->max_align); + datas = alloca(sizeof(struct spa_data) * blocks); memset(datas, 0, sizeof(struct spa_data) * blocks); aligns = alloca(sizeof(uint32_t) * blocks); @@ -962,6 +967,9 @@ impl_init(const struct spa_handle_factory *factory, case SPA_TYPE_INTERFACE_Log: this->log = support[i].data; break; + case SPA_TYPE_INTERFACE_CPU: + this->cpu = support[i].data; + break; } } if (info == NULL || (str = spa_dict_lookup(info, "audio.adapt.slave")) == NULL) @@ -971,6 +979,9 @@ impl_init(const struct spa_handle_factory *factory, if (this->slave == NULL) return -EINVAL; + if (this->cpu) + this->max_align = spa_cpu_get_max_align(this->cpu); + spa_hook_list_init(&this->hooks); this->node.iface = SPA_INTERFACE_INIT( diff --git a/spa/plugins/audioconvert/audioconvert.c b/spa/plugins/audioconvert/audioconvert.c index 0859bf732..a6400d254 100644 --- a/spa/plugins/audioconvert/audioconvert.c +++ b/spa/plugins/audioconvert/audioconvert.c @@ -27,6 +27,7 @@ #include #include +#include #include #include #include @@ -68,6 +69,9 @@ struct impl { struct spa_node node; struct spa_log *log; + struct spa_cpu *cpu; + + uint32_t max_align; struct spa_hook_list hooks; @@ -345,6 +349,8 @@ static int negotiate_link_buffers(struct impl *this, struct link *link) spa_log_debug(this->log, "%p: buffers %d, blocks %d, size %d, align %d %d:%d", this, buffers, blocks, size, align, out_alloc, in_alloc); + align = SPA_MAX(align, this->max_align); + datas = alloca(sizeof(struct spa_data) * blocks); memset(datas, 0, sizeof(struct spa_data) * blocks); aligns = alloca(sizeof(uint32_t) * blocks); @@ -1191,9 +1197,19 @@ impl_init(const struct spa_handle_factory *factory, this = (struct impl *) handle; for (i = 0; i < n_support; i++) { - if (support[i].type == SPA_TYPE_INTERFACE_Log) + switch (support[i].type) { + case SPA_TYPE_INTERFACE_Log: this->log = support[i].data; + break; + case SPA_TYPE_INTERFACE_CPU: + this->cpu = support[i].data; + break; + } } + + if (this->cpu) + this->max_align = spa_cpu_get_max_align(this->cpu); + this->node.iface = SPA_INTERFACE_INIT( SPA_TYPE_INTERFACE_Node, SPA_VERSION_NODE, diff --git a/spa/plugins/audioconvert/merger.c b/spa/plugins/audioconvert/merger.c index a22af59a9..daa4c8c30 100644 --- a/spa/plugins/audioconvert/merger.c +++ b/spa/plugins/audioconvert/merger.c @@ -73,7 +73,6 @@ struct port { struct spa_param_info params[8]; char position[16]; - bool have_format; struct spa_audio_info format; uint32_t blocks; uint32_t stride; @@ -82,6 +81,8 @@ struct port { uint32_t n_buffers; struct spa_list queue; + + unsigned int have_format:1; }; struct impl { diff --git a/spa/plugins/audiomixer/mixer-dsp.c b/spa/plugins/audiomixer/mixer-dsp.c index 3b1241ab6..ff8141fc0 100644 --- a/spa/plugins/audiomixer/mixer-dsp.c +++ b/spa/plugins/audiomixer/mixer-dsp.c @@ -41,9 +41,10 @@ #define NAME "mixer-dsp" -#define MAX_BUFFERS 64 -#define MAX_PORTS 128 -#define MAX_SAMPLES 1024 +#define MAX_BUFFERS 64 +#define MAX_PORTS 128 +#define MAX_SAMPLES 1024 +#define MAX_ALIGN 64 #define PORT_DEFAULT_VOLUME 1.0 #define PORT_DEFAULT_MUTE false @@ -115,13 +116,14 @@ struct impl { struct port in_ports[MAX_PORTS]; struct port out_ports[1]; - bool have_format; int n_formats; struct spa_audio_info format; uint32_t stride; - bool started; - float empty[MAX_SAMPLES + 15]; + unsigned int have_format:1; + unsigned int started:1; + + float empty[MAX_SAMPLES + MAX_ALIGN]; }; #define CHECK_FREE_IN_PORT(this,d,p) ((d) == SPA_DIRECTION_INPUT && (p) < MAX_PORTS && !this->in_ports[(p)].valid) @@ -725,7 +727,7 @@ static int impl_node_process(void *object) else { outb->buffer->n_datas = 1; outb->buffer->datas = outb->datas; - outb->datas[0].data = SPA_PTR_ALIGN(this->empty, 16, void); + outb->datas[0].data = SPA_PTR_ALIGN(this->empty, MAX_ALIGN, void); outb->datas[0].chunk = outb->chunk; outb->datas[0].chunk->offset = 0; outb->datas[0].chunk->size = n_samples * sizeof(float); diff --git a/src/pipewire/buffers.c b/src/pipewire/buffers.c index a30ac5077..c55d47a51 100644 --- a/src/pipewire/buffers.c +++ b/src/pipewire/buffers.c @@ -37,7 +37,8 @@ #define NAME "buffers" -#define MAX_BUFFERS 64 +#define MAX_ALIGN 32 +#define MAX_BUFFERS 64 struct port { struct spa_node *node; @@ -246,8 +247,12 @@ int pw_buffers_negotiate(struct pw_core *core, uint32_t flags, else max_buffers = MAX_BUFFERS; + if ((str = pw_properties_get(core->properties, "cpu.max-align")) != NULL) + align = pw_properties_parse_int(str); + else + align = MAX_ALIGN; + minsize = stride = 0; - align = 8; param = find_param(params, n_params, SPA_TYPE_OBJECT_ParamBuffers); if (param) { uint32_t qmax_buffers = max_buffers, diff --git a/src/pipewire/core.c b/src/pipewire/core.c index ead2487f1..47463ef0b 100644 --- a/src/pipewire/core.c +++ b/src/pipewire/core.c @@ -29,6 +29,7 @@ #include +#include #include #include #include @@ -479,6 +480,7 @@ struct pw_core *pw_core_new(struct pw_loop *main_loop, void *dbus_iface = NULL; uint32_t n_support; struct pw_properties *pr; + struct spa_cpu *cpu; int res = 0; impl = calloc(1, sizeof(struct impl) + user_data_size); @@ -526,6 +528,9 @@ struct pw_core *pw_core_new(struct pw_loop *main_loop, this->support[n_support++] = SPA_SUPPORT_INIT(SPA_TYPE_INTERFACE_DataSystem, this->data_system); this->support[n_support++] = SPA_SUPPORT_INIT(SPA_TYPE_INTERFACE_DataLoop, this->data_loop->loop); + if ((cpu = spa_support_find(this->support, n_support, SPA_TYPE_INTERFACE_CPU)) != NULL) + pw_properties_setf(properties, "cpu.max-align", "%u", spa_cpu_get_max_align(cpu)); + lib = pw_properties_get(properties, PW_KEY_LIBRARY_NAME_DBUS); if (lib == NULL) lib = "support/libspa-dbus";