mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -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 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…
	
	Add table
		Add a link
		
	
		Reference in a new issue