jack: optimize get_buffer

Keep track of global mix port.
Calculate the get_buffer function beforehand.
This commit is contained in:
Wim Taymans 2020-09-30 11:59:41 +02:00
parent ac4d4582a4
commit 68bff629b3

View file

@ -127,6 +127,7 @@ struct object {
jack_latency_range_t capture_latency;
jack_latency_range_t playback_latency;
int32_t priority;
struct port *port;
} port;
};
};
@ -191,12 +192,15 @@ struct port {
struct spa_io_buffers io;
struct spa_list mix;
struct mix *global_mix;
unsigned int empty_out:1;
unsigned int zeroed:1;
float *emptyptr;
float empty[MAX_BUFFER_FRAMES + MAX_ALIGN];
void *(*get_buffer) (struct port *p, jack_nframes_t frames);
};
struct link {
@ -386,6 +390,17 @@ static void free_object(struct client *c, struct object *o)
spa_list_append(&c->context.free_objects, &o->link);
}
static void init_mix(struct mix *mix, uint32_t mix_id, struct port *port)
{
mix->id = mix_id;
mix->port = port;
mix->io = NULL;
mix->n_buffers = 0;
spa_list_init(&mix->queue);
if (mix_id == SPA_ID_INVALID)
port->global_mix = mix;
}
static struct mix *find_mix(struct client *c, struct port *port, uint32_t mix_id)
{
struct mix *mix;
@ -417,11 +432,7 @@ static struct mix *ensure_mix(struct client *c, struct port *port, uint32_t mix_
spa_list_append(&port->mix, &mix->port_link);
mix->id = mix_id;
mix->port = port;
mix->io = NULL;
mix->n_buffers = 0;
spa_list_init(&mix->queue);
init_mix(mix, mix_id, port);
return mix;
}
@ -451,6 +462,8 @@ static void free_mix(struct client *c, struct mix *mix)
{
clear_buffers(c, mix);
spa_list_remove(&mix->port_link);
if (mix->id == SPA_ID_INVALID)
mix->port->global_mix = NULL;
spa_list_append(&c->free_mix, &mix->link);
}
@ -483,6 +496,7 @@ static struct port * alloc_port(struct client *c, enum spa_direction direction)
o->id = SPA_ID_INVALID;
o->port.node_id = c->node_id;
o->port.port_id = p->id;
o->port.port = p;
p->valid = true;
p->zeroed = false;
@ -728,7 +742,7 @@ static void unhandle_socket(struct client *c)
do_remove_sources, 1, NULL, 0, true, c);
}
static void reuse_buffer(struct client *c, struct mix *mix, uint32_t id)
static inline void reuse_buffer(struct client *c, struct mix *mix, uint32_t id)
{
struct buffer *b;
@ -800,9 +814,10 @@ static void convert_to_midi(struct spa_pod_sequence **seq, uint32_t n_seq, void
}
static void *get_buffer_output(struct client *c, struct port *p, uint32_t frames, uint32_t stride)
static inline void *get_buffer_output(struct port *p, uint32_t frames, uint32_t stride)
{
struct mix *mix;
struct client *c = p->client;
void *ptr = NULL;
p->io.status = -EPIPE;
@ -811,7 +826,7 @@ static void *get_buffer_output(struct client *c, struct port *p, uint32_t frames
if (frames == 0)
return NULL;
if (SPA_LIKELY((mix = find_mix(c, p, -1)) != NULL)) {
if (SPA_LIKELY((mix = p->global_mix) != NULL)) {
struct buffer *b;
if (SPA_UNLIKELY(mix->n_buffers == 0))
@ -858,12 +873,12 @@ static void process_tee(struct client *c, uint32_t frames)
switch (p->object->port.type_id) {
case TYPE_ID_AUDIO:
ptr = get_buffer_output(c, p, frames, sizeof(float));
ptr = get_buffer_output(p, frames, sizeof(float));
if (SPA_LIKELY(ptr != NULL))
memcpy(ptr, p->emptyptr, frames * sizeof(float));
break;
case TYPE_ID_MIDI:
ptr = get_buffer_output(c, p, MAX_BUFFER_FRAMES, 1);
ptr = get_buffer_output(p, MAX_BUFFER_FRAMES, 1);
if (SPA_LIKELY(ptr != NULL))
convert_from_midi(p->emptyptr, ptr, MAX_BUFFER_FRAMES * sizeof(float));
break;
@ -1636,7 +1651,7 @@ static int client_node_port_set_param(void *object,
NULL);
}
static void *init_buffer(struct port *p)
static inline void *init_buffer(struct port *p)
{
void *data = p->emptyptr;
if (p->zeroed)
@ -3139,6 +3154,13 @@ float jack_cpu_load (jack_client_t *client)
#include "statistics.c"
static void *get_buffer_input_float(struct port *p, jack_nframes_t frames);
static void *get_buffer_input_midi(struct port *p, jack_nframes_t frames);
static void *get_buffer_input_empty(struct port *p, jack_nframes_t frames);
static void *get_buffer_output_float(struct port *p, jack_nframes_t frames);
static void *get_buffer_output_midi(struct port *p, jack_nframes_t frames);
static void *get_buffer_output_empty(struct port *p, jack_nframes_t frames);
SPA_EXPORT
jack_port_t * jack_port_register (jack_client_t *client,
const char *port_name,
@ -3188,6 +3210,34 @@ jack_port_t * jack_port_register (jack_client_t *client,
init_buffer(p);
if (direction == SPA_DIRECTION_INPUT) {
switch (type_id) {
case TYPE_ID_AUDIO:
case TYPE_ID_VIDEO:
p->get_buffer = get_buffer_input_float;
break;
case TYPE_ID_MIDI:
p->get_buffer = get_buffer_input_midi;
break;
default:
p->get_buffer = get_buffer_input_empty;
break;
}
} else {
switch (type_id) {
case TYPE_ID_AUDIO:
case TYPE_ID_VIDEO:
p->get_buffer = get_buffer_output_float;
break;
case TYPE_ID_MIDI:
p->get_buffer = get_buffer_output_midi;
break;
default:
p->get_buffer = get_buffer_output_empty;
break;
}
}
pw_log_debug(NAME" %p: port %p", c, p);
spa_list_init(&p->mix);
@ -3269,7 +3319,7 @@ int jack_port_unregister (jack_client_t *client, jack_port_t *port)
return res;
}
static inline void *get_buffer_input_float(struct client *c, struct port *p, jack_nframes_t frames)
static void *get_buffer_input_float(struct port *p, jack_nframes_t frames)
{
struct mix *mix;
struct buffer *b;
@ -3279,7 +3329,7 @@ static inline void *get_buffer_input_float(struct client *c, struct port *p, jac
spa_list_for_each(mix, &p->mix, port_link) {
pw_log_trace_fp(NAME" %p: port %p mix %d.%d get buffer %d",
c, p, p->id, mix->id, frames);
p->client, p, p->id, mix->id, frames);
io = mix->io;
if (io == NULL ||
io->status != SPA_STATUS_HAVE_DATA ||
@ -3296,10 +3346,12 @@ static inline void *get_buffer_input_float(struct client *c, struct port *p, jac
p->zeroed = false;
}
}
if (ptr == NULL)
ptr = init_buffer(p);
return ptr;
}
static inline void *get_buffer_input_midi(struct client *c, struct port *p, jack_nframes_t frames)
static void *get_buffer_input_midi(struct port *p, jack_nframes_t frames)
{
struct mix *mix;
struct spa_io_buffers *io;
@ -3314,7 +3366,7 @@ static inline void *get_buffer_input_midi(struct client *c, struct port *p, jack
void *pod;
pw_log_trace_fp(NAME" %p: port %p mix %d.%d get buffer %d",
c, p, p->id, mix->id, frames);
p->client, p, p->id, mix->id, frames);
io = mix->io;
if (io == NULL ||
@ -3337,68 +3389,45 @@ static inline void *get_buffer_input_midi(struct client *c, struct port *p, jack
return ptr;
}
static inline void *get_buffer_output_float(struct client *c, struct port *p, jack_nframes_t frames)
static void *get_buffer_output_float(struct port *p, jack_nframes_t frames)
{
void *ptr;
ptr = get_buffer_output(c, p, frames, sizeof(float));
if (SPA_UNLIKELY(ptr == NULL)) {
p->empty_out = true;
ptr = get_buffer_output(p, frames, sizeof(float));
if (SPA_UNLIKELY(p->empty_out = (ptr == NULL)))
ptr = p->emptyptr;
} else {
p->empty_out = false;
}
return ptr;
}
static inline void *get_buffer_output_midi(struct client *c, struct port *p, jack_nframes_t frames)
static void *get_buffer_output_midi(struct port *p, jack_nframes_t frames)
{
p->empty_out = true;
return p->emptyptr;
}
static void *get_buffer_output_empty(struct port *p, jack_nframes_t frames)
{
p->empty_out = true;
return p->emptyptr;
}
static void *get_buffer_input_empty(struct port *p, jack_nframes_t frames)
{
return init_buffer(p);
}
SPA_EXPORT
void * jack_port_get_buffer (jack_port_t *port, jack_nframes_t frames)
{
struct object *o = (struct object *) port;
struct client *c;
struct port *p;
void *ptr = NULL;
void *ptr;
spa_return_val_if_fail(o != NULL, NULL);
c = o->client;
p = GET_PORT(c, GET_DIRECTION(o->port.flags), o->port.port_id);
if (p->direction == SPA_DIRECTION_INPUT) {
switch (p->object->port.type_id) {
case TYPE_ID_AUDIO:
ptr = get_buffer_input_float(c, p, frames);
break;
case TYPE_ID_MIDI:
ptr = get_buffer_input_midi(c, p, frames);
break;
case TYPE_ID_VIDEO:
ptr = get_buffer_input_float(c, p, frames);
break;
}
if (ptr == NULL) {
ptr = init_buffer(p);
}
} else {
switch (p->object->port.type_id) {
case TYPE_ID_AUDIO:
ptr = get_buffer_output_float(c, p, frames);
break;
case TYPE_ID_MIDI:
ptr = get_buffer_output_midi(c, p, frames);
break;
case TYPE_ID_VIDEO:
ptr = get_buffer_output_float(c, p, frames);
break;
}
}
pw_log_trace_fp(NAME" %p: port %p buffer %p empty:%u", c, p, ptr, p->empty_out);
p = o->port.port;
ptr = p->get_buffer(p, frames);
pw_log_trace_fp(NAME" %p: port %p buffer %p empty:%u", p->client, p, ptr, p->empty_out);
return ptr;
}