mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	jack: reorganize jack_port_get_buffer()
Dequeue a new buffer only once and reuse this queued buffer when jack_port_get_buffer() is called multiple times in process(). Recycle an old buffer in the next cycle. After calling process, mark all input buffers as consumed, process the empty buffers and move the output buffers to the mix ports. Fixes #1748
This commit is contained in:
		
							parent
							
								
									6f75b1433c
								
							
						
					
					
						commit
						31f387868a
					
				
					 1 changed files with 65 additions and 59 deletions
				
			
		| 
						 | 
				
			
			@ -972,31 +972,32 @@ static inline void *get_buffer_output(struct port *p, uint32_t frames, uint32_t
 | 
			
		|||
	struct mix *mix;
 | 
			
		||||
	struct client *c = p->client;
 | 
			
		||||
	void *ptr = NULL;
 | 
			
		||||
 | 
			
		||||
	p->io.status = -EPIPE;
 | 
			
		||||
	p->io.buffer_id = SPA_ID_INVALID;
 | 
			
		||||
	struct buffer *b;
 | 
			
		||||
 | 
			
		||||
	if (frames == 0)
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	if (SPA_LIKELY((mix = p->global_mix) != NULL)) {
 | 
			
		||||
		struct buffer *b;
 | 
			
		||||
 | 
			
		||||
		if (SPA_UNLIKELY(mix->n_buffers == 0))
 | 
			
		||||
			goto done;
 | 
			
		||||
	if (SPA_UNLIKELY((mix = p->global_mix) == NULL))
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	pw_log_trace_fp("%p: port %p %d get buffer %d n_buffers:%d",
 | 
			
		||||
			c, p, p->id, frames, mix->n_buffers);
 | 
			
		||||
 | 
			
		||||
		if (SPA_UNLIKELY((b = dequeue_buffer(mix)) == NULL)) {
 | 
			
		||||
			pw_log_warn("port %p: out of buffers", p);
 | 
			
		||||
			goto done;
 | 
			
		||||
		}
 | 
			
		||||
		reuse_buffer(c, mix, b->id);
 | 
			
		||||
		ptr = b->datas[0].data;
 | 
			
		||||
		if (buf)
 | 
			
		||||
			*buf = b;
 | 
			
		||||
	if (SPA_UNLIKELY(mix->n_buffers == 0))
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	if (p->io.status == SPA_STATUS_HAVE_DATA &&
 | 
			
		||||
	    p->io.buffer_id < mix->n_buffers) {
 | 
			
		||||
		b = &mix->buffers[p->io.buffer_id];
 | 
			
		||||
	} else {
 | 
			
		||||
		if (p->io.buffer_id < mix->n_buffers) {
 | 
			
		||||
			reuse_buffer(c, mix, p->io.buffer_id);
 | 
			
		||||
			p->io.buffer_id = SPA_ID_INVALID;
 | 
			
		||||
		}
 | 
			
		||||
		if (SPA_UNLIKELY((b = dequeue_buffer(c, mix)) == NULL)) {
 | 
			
		||||
			pw_log_warn("port %p: out of buffers", p);
 | 
			
		||||
			return NULL;
 | 
			
		||||
		}
 | 
			
		||||
		b->datas[0].chunk->offset = 0;
 | 
			
		||||
		b->datas[0].chunk->size = frames * sizeof(float);
 | 
			
		||||
		b->datas[0].chunk->stride = stride;
 | 
			
		||||
| 
						 | 
				
			
			@ -1004,28 +1005,16 @@ static inline void *get_buffer_output(struct port *p, uint32_t frames, uint32_t
 | 
			
		|||
		p->io.status = SPA_STATUS_HAVE_DATA;
 | 
			
		||||
		p->io.buffer_id = b->id;
 | 
			
		||||
	}
 | 
			
		||||
done:
 | 
			
		||||
	spa_list_for_each(mix, &p->mix, port_link) {
 | 
			
		||||
		struct spa_io_buffers *mio = mix->io;
 | 
			
		||||
		if (SPA_UNLIKELY(mio == NULL))
 | 
			
		||||
			continue;
 | 
			
		||||
		pw_log_trace_fp("%p: port %p tee %d.%d get buffer %d io:%p",
 | 
			
		||||
				c, p, p->id, mix->id, frames, mio);
 | 
			
		||||
		*mio = p->io;
 | 
			
		||||
	}
 | 
			
		||||
	ptr = b->datas[0].data;
 | 
			
		||||
	if (buf)
 | 
			
		||||
		*buf = b;
 | 
			
		||||
	return ptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void process_tee(struct client *c, uint32_t frames)
 | 
			
		||||
static inline void process_empty(struct port *p, uint32_t frames)
 | 
			
		||||
{
 | 
			
		||||
	struct port *p;
 | 
			
		||||
 | 
			
		||||
	spa_list_for_each(p, &c->ports[SPA_DIRECTION_OUTPUT], link) {
 | 
			
		||||
	void *ptr;
 | 
			
		||||
 | 
			
		||||
		if (SPA_LIKELY(!p->empty_out))
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
	switch (p->object->port.type_id) {
 | 
			
		||||
	case TYPE_ID_AUDIO:
 | 
			
		||||
		ptr = get_buffer_output(p, frames, sizeof(float), NULL);
 | 
			
		||||
| 
						 | 
				
			
			@ -1046,6 +1035,28 @@ static void process_tee(struct client *c, uint32_t frames)
 | 
			
		|||
		pw_log_warn("port %p: unhandled format %d", p, p->object->port.type_id);
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void complete_process(struct client *c, uint32_t frames)
 | 
			
		||||
{
 | 
			
		||||
	struct port *p;
 | 
			
		||||
	struct mix *mix;
 | 
			
		||||
 | 
			
		||||
	spa_list_for_each(p, &c->ports[SPA_DIRECTION_INPUT], link) {
 | 
			
		||||
		spa_list_for_each(mix, &p->mix, port_link) {
 | 
			
		||||
			if (SPA_LIKELY(mix->io != NULL))
 | 
			
		||||
				mix->io->status = SPA_STATUS_NEED_DATA;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	spa_list_for_each(p, &c->ports[SPA_DIRECTION_OUTPUT], link) {
 | 
			
		||||
		if (SPA_UNLIKELY(p->empty_out))
 | 
			
		||||
			process_empty(p, frames);
 | 
			
		||||
 | 
			
		||||
		spa_list_for_each(mix, &p->mix, port_link) {
 | 
			
		||||
			if (SPA_LIKELY(mix->io != NULL))
 | 
			
		||||
				*mix->io = p->io;
 | 
			
		||||
		}
 | 
			
		||||
		p->io.status = SPA_STATUS_NEED_DATA;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1312,7 +1323,7 @@ static inline void signal_sync(struct client *c)
 | 
			
		|||
	struct link *l;
 | 
			
		||||
	struct pw_node_activation *activation = c->activation;
 | 
			
		||||
 | 
			
		||||
	process_tee(c, c->buffer_frames);
 | 
			
		||||
	complete_process(c, c->buffer_frames);
 | 
			
		||||
 | 
			
		||||
	clock_gettime(CLOCK_MONOTONIC, &ts);
 | 
			
		||||
	nsec = SPA_TIMESPEC_TO_NSEC(&ts);
 | 
			
		||||
| 
						 | 
				
			
			@ -4086,7 +4097,6 @@ static void *get_buffer_input_float(struct port *p, jack_nframes_t frames)
 | 
			
		|||
		if ((b = get_mix_buffer(mix)) == NULL)
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		mix->io->status = SPA_STATUS_NEED_DATA;
 | 
			
		||||
		if (layer++ == 0)
 | 
			
		||||
			ptr = b->datas[0].data;
 | 
			
		||||
		else  {
 | 
			
		||||
| 
						 | 
				
			
			@ -4103,7 +4113,6 @@ 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)
 | 
			
		||||
{
 | 
			
		||||
	struct mix *mix;
 | 
			
		||||
	struct spa_io_buffers *io;
 | 
			
		||||
	void *ptr = p->emptyptr;
 | 
			
		||||
	struct spa_pod_sequence *seq[CONNECTION_NUM_FOR_PORT];
 | 
			
		||||
	uint32_t n_seq = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -4112,19 +4121,16 @@ static void *get_buffer_input_midi(struct port *p, jack_nframes_t frames)
 | 
			
		|||
 | 
			
		||||
	spa_list_for_each(mix, &p->mix, port_link) {
 | 
			
		||||
		struct spa_data *d;
 | 
			
		||||
		struct buffer *b;
 | 
			
		||||
		void *pod;
 | 
			
		||||
 | 
			
		||||
		pw_log_trace_fp("%p: port %p mix %d.%d get buffer %d",
 | 
			
		||||
				p->client, p, p->id, mix->id, frames);
 | 
			
		||||
 | 
			
		||||
		io = mix->io;
 | 
			
		||||
		if (io == NULL ||
 | 
			
		||||
		    io->status != SPA_STATUS_HAVE_DATA ||
 | 
			
		||||
		    io->buffer_id >= mix->n_buffers)
 | 
			
		||||
		if ((b = get_mix_buffer(mix)) == NULL)
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		io->status = SPA_STATUS_NEED_DATA;
 | 
			
		||||
		d = &mix->buffers[io->buffer_id].datas[0];
 | 
			
		||||
		d = &b->datas[0];
 | 
			
		||||
 | 
			
		||||
		if ((pod = spa_pod_from_data(d->data, d->maxsize, d->chunk->offset, d->chunk->size)) == NULL)
 | 
			
		||||
			continue;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue