mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-01 22:58:50 -04: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 = p->global_mix) == NULL))
|
||||
return NULL;
|
||||
|
||||
if (SPA_UNLIKELY(mix->n_buffers == 0))
|
||||
goto done;
|
||||
pw_log_trace_fp("%p: port %p %d get buffer %d n_buffers:%d",
|
||||
c, p, p->id, frames, mix->n_buffers);
|
||||
|
||||
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(mix->n_buffers == 0))
|
||||
return NULL;
|
||||
|
||||
if (SPA_UNLIKELY((b = dequeue_buffer(mix)) == NULL)) {
|
||||
pw_log_warn("port %p: out of buffers", p);
|
||||
goto done;
|
||||
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;
|
||||
}
|
||||
reuse_buffer(c, mix, b->id);
|
||||
ptr = b->datas[0].data;
|
||||
if (buf)
|
||||
*buf = b;
|
||||
|
||||
b->datas[0].chunk->offset = 0;
|
||||
b->datas[0].chunk->size = frames * sizeof(float);
|
||||
b->datas[0].chunk->stride = stride;
|
||||
|
|
@ -1004,48 +1005,58 @@ 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)
|
||||
{
|
||||
void *ptr;
|
||||
|
||||
switch (p->object->port.type_id) {
|
||||
case TYPE_ID_AUDIO:
|
||||
ptr = get_buffer_output(p, frames, sizeof(float), NULL);
|
||||
if (SPA_LIKELY(ptr != NULL))
|
||||
memcpy(ptr, p->emptyptr, frames * sizeof(float));
|
||||
break;
|
||||
case TYPE_ID_MIDI:
|
||||
{
|
||||
struct buffer *b;
|
||||
ptr = get_buffer_output(p, MAX_BUFFER_FRAMES, 1, &b);
|
||||
if (SPA_LIKELY(ptr != NULL)) {
|
||||
b->datas[0].chunk->size = convert_from_midi(p->emptyptr,
|
||||
ptr, MAX_BUFFER_FRAMES * sizeof(float));
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
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) {
|
||||
void *ptr;
|
||||
if (SPA_UNLIKELY(p->empty_out))
|
||||
process_empty(p, frames);
|
||||
|
||||
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);
|
||||
if (SPA_LIKELY(ptr != NULL))
|
||||
memcpy(ptr, p->emptyptr, frames * sizeof(float));
|
||||
break;
|
||||
case TYPE_ID_MIDI:
|
||||
{
|
||||
struct buffer *b;
|
||||
ptr = get_buffer_output(p, MAX_BUFFER_FRAMES, 1, &b);
|
||||
if (SPA_LIKELY(ptr != NULL)) {
|
||||
b->datas[0].chunk->size = convert_from_midi(p->emptyptr,
|
||||
ptr, MAX_BUFFER_FRAMES * sizeof(float));
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
pw_log_warn("port %p: unhandled format %d", p, p->object->port.type_id);
|
||||
break;
|
||||
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