mirror of
https://gitlab.freedesktop.org/pipewire/pipewire
synced 2024-09-16 06:29:56 +00: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
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue