mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-04 13:30:12 -05:00
jack: optimize get_buffer
Keep track of global mix port. Calculate the get_buffer function beforehand.
This commit is contained in:
parent
ac4d4582a4
commit
68bff629b3
1 changed files with 86 additions and 57 deletions
|
|
@ -127,6 +127,7 @@ struct object {
|
||||||
jack_latency_range_t capture_latency;
|
jack_latency_range_t capture_latency;
|
||||||
jack_latency_range_t playback_latency;
|
jack_latency_range_t playback_latency;
|
||||||
int32_t priority;
|
int32_t priority;
|
||||||
|
struct port *port;
|
||||||
} port;
|
} port;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
@ -191,12 +192,15 @@ struct port {
|
||||||
|
|
||||||
struct spa_io_buffers io;
|
struct spa_io_buffers io;
|
||||||
struct spa_list mix;
|
struct spa_list mix;
|
||||||
|
struct mix *global_mix;
|
||||||
|
|
||||||
unsigned int empty_out:1;
|
unsigned int empty_out:1;
|
||||||
unsigned int zeroed:1;
|
unsigned int zeroed:1;
|
||||||
|
|
||||||
float *emptyptr;
|
float *emptyptr;
|
||||||
float empty[MAX_BUFFER_FRAMES + MAX_ALIGN];
|
float empty[MAX_BUFFER_FRAMES + MAX_ALIGN];
|
||||||
|
|
||||||
|
void *(*get_buffer) (struct port *p, jack_nframes_t frames);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct link {
|
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);
|
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)
|
static struct mix *find_mix(struct client *c, struct port *port, uint32_t mix_id)
|
||||||
{
|
{
|
||||||
struct mix *mix;
|
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);
|
spa_list_append(&port->mix, &mix->port_link);
|
||||||
|
|
||||||
mix->id = mix_id;
|
init_mix(mix, mix_id, port);
|
||||||
mix->port = port;
|
|
||||||
mix->io = NULL;
|
|
||||||
mix->n_buffers = 0;
|
|
||||||
spa_list_init(&mix->queue);
|
|
||||||
|
|
||||||
return mix;
|
return mix;
|
||||||
}
|
}
|
||||||
|
|
@ -451,6 +462,8 @@ static void free_mix(struct client *c, struct mix *mix)
|
||||||
{
|
{
|
||||||
clear_buffers(c, mix);
|
clear_buffers(c, mix);
|
||||||
spa_list_remove(&mix->port_link);
|
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);
|
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->id = SPA_ID_INVALID;
|
||||||
o->port.node_id = c->node_id;
|
o->port.node_id = c->node_id;
|
||||||
o->port.port_id = p->id;
|
o->port.port_id = p->id;
|
||||||
|
o->port.port = p;
|
||||||
|
|
||||||
p->valid = true;
|
p->valid = true;
|
||||||
p->zeroed = false;
|
p->zeroed = false;
|
||||||
|
|
@ -728,7 +742,7 @@ static void unhandle_socket(struct client *c)
|
||||||
do_remove_sources, 1, NULL, 0, true, 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;
|
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 mix *mix;
|
||||||
|
struct client *c = p->client;
|
||||||
void *ptr = NULL;
|
void *ptr = NULL;
|
||||||
|
|
||||||
p->io.status = -EPIPE;
|
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)
|
if (frames == 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (SPA_LIKELY((mix = find_mix(c, p, -1)) != NULL)) {
|
if (SPA_LIKELY((mix = p->global_mix) != NULL)) {
|
||||||
struct buffer *b;
|
struct buffer *b;
|
||||||
|
|
||||||
if (SPA_UNLIKELY(mix->n_buffers == 0))
|
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) {
|
switch (p->object->port.type_id) {
|
||||||
case TYPE_ID_AUDIO:
|
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))
|
if (SPA_LIKELY(ptr != NULL))
|
||||||
memcpy(ptr, p->emptyptr, frames * sizeof(float));
|
memcpy(ptr, p->emptyptr, frames * sizeof(float));
|
||||||
break;
|
break;
|
||||||
case TYPE_ID_MIDI:
|
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))
|
if (SPA_LIKELY(ptr != NULL))
|
||||||
convert_from_midi(p->emptyptr, ptr, MAX_BUFFER_FRAMES * sizeof(float));
|
convert_from_midi(p->emptyptr, ptr, MAX_BUFFER_FRAMES * sizeof(float));
|
||||||
break;
|
break;
|
||||||
|
|
@ -1636,7 +1651,7 @@ static int client_node_port_set_param(void *object,
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *init_buffer(struct port *p)
|
static inline void *init_buffer(struct port *p)
|
||||||
{
|
{
|
||||||
void *data = p->emptyptr;
|
void *data = p->emptyptr;
|
||||||
if (p->zeroed)
|
if (p->zeroed)
|
||||||
|
|
@ -3139,6 +3154,13 @@ float jack_cpu_load (jack_client_t *client)
|
||||||
|
|
||||||
#include "statistics.c"
|
#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
|
SPA_EXPORT
|
||||||
jack_port_t * jack_port_register (jack_client_t *client,
|
jack_port_t * jack_port_register (jack_client_t *client,
|
||||||
const char *port_name,
|
const char *port_name,
|
||||||
|
|
@ -3188,6 +3210,34 @@ jack_port_t * jack_port_register (jack_client_t *client,
|
||||||
|
|
||||||
init_buffer(p);
|
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);
|
pw_log_debug(NAME" %p: port %p", c, p);
|
||||||
|
|
||||||
spa_list_init(&p->mix);
|
spa_list_init(&p->mix);
|
||||||
|
|
@ -3269,7 +3319,7 @@ int jack_port_unregister (jack_client_t *client, jack_port_t *port)
|
||||||
return res;
|
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 mix *mix;
|
||||||
struct buffer *b;
|
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) {
|
spa_list_for_each(mix, &p->mix, port_link) {
|
||||||
pw_log_trace_fp(NAME" %p: port %p mix %d.%d get buffer %d",
|
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;
|
io = mix->io;
|
||||||
if (io == NULL ||
|
if (io == NULL ||
|
||||||
io->status != SPA_STATUS_HAVE_DATA ||
|
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;
|
p->zeroed = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (ptr == NULL)
|
||||||
|
ptr = init_buffer(p);
|
||||||
return ptr;
|
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 mix *mix;
|
||||||
struct spa_io_buffers *io;
|
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;
|
void *pod;
|
||||||
|
|
||||||
pw_log_trace_fp(NAME" %p: port %p mix %d.%d get buffer %d",
|
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;
|
io = mix->io;
|
||||||
if (io == NULL ||
|
if (io == NULL ||
|
||||||
|
|
@ -3337,68 +3389,45 @@ static inline void *get_buffer_input_midi(struct client *c, struct port *p, jack
|
||||||
return ptr;
|
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;
|
void *ptr;
|
||||||
|
|
||||||
ptr = get_buffer_output(c, p, frames, sizeof(float));
|
ptr = get_buffer_output(p, frames, sizeof(float));
|
||||||
if (SPA_UNLIKELY(ptr == NULL)) {
|
if (SPA_UNLIKELY(p->empty_out = (ptr == NULL)))
|
||||||
p->empty_out = true;
|
|
||||||
ptr = p->emptyptr;
|
ptr = p->emptyptr;
|
||||||
} else {
|
|
||||||
p->empty_out = false;
|
|
||||||
}
|
|
||||||
return ptr;
|
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;
|
p->empty_out = true;
|
||||||
return p->emptyptr;
|
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
|
SPA_EXPORT
|
||||||
void * jack_port_get_buffer (jack_port_t *port, jack_nframes_t frames)
|
void * jack_port_get_buffer (jack_port_t *port, jack_nframes_t frames)
|
||||||
{
|
{
|
||||||
struct object *o = (struct object *) port;
|
struct object *o = (struct object *) port;
|
||||||
struct client *c;
|
|
||||||
struct port *p;
|
struct port *p;
|
||||||
void *ptr = NULL;
|
void *ptr;
|
||||||
|
|
||||||
spa_return_val_if_fail(o != NULL, NULL);
|
spa_return_val_if_fail(o != NULL, NULL);
|
||||||
|
|
||||||
c = o->client;
|
p = o->port.port;
|
||||||
p = GET_PORT(c, GET_DIRECTION(o->port.flags), o->port.port_id);
|
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);
|
||||||
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);
|
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue