From 441fdb23337cc63c99976c55788886f4c87f846b Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Thu, 19 Mar 2020 13:12:49 +0100 Subject: [PATCH] alsa: fix buffer recycle We only set the OUT flag when we put the buffer on an io area and might need to recycle later. Before placing the output buffer into the io area, recycle any buffer that might be left in there. Only emit the ready callback when we have some data queued. --- spa/plugins/alsa/alsa-pcm-source.c | 16 +++----------- spa/plugins/alsa/alsa-pcm.c | 35 ++++++++++++++++++++++-------- spa/plugins/alsa/alsa-pcm.h | 2 ++ 3 files changed, 31 insertions(+), 22 deletions(-) diff --git a/spa/plugins/alsa/alsa-pcm-source.c b/spa/plugins/alsa/alsa-pcm-source.c index 46cce4efe..e2bc595cf 100644 --- a/spa/plugins/alsa/alsa-pcm-source.c +++ b/spa/plugins/alsa/alsa-pcm-source.c @@ -337,17 +337,6 @@ static int impl_node_remove_port(void *object, enum spa_direction direction, uin return -ENOTSUP; } -static void recycle_buffer(struct state *this, uint32_t buffer_id) -{ - struct buffer *b = &this->buffers[buffer_id]; - - if (SPA_FLAG_IS_SET(b->flags, BUFFER_FLAG_OUT)) { - spa_log_trace_fp(this->log, NAME " %p: recycle buffer %u", this, buffer_id); - spa_list_append(&this->free, &b->link); - SPA_FLAG_CLEAR(b->flags, BUFFER_FLAG_OUT); - } -} - static int impl_node_port_enum_params(void *object, int seq, enum spa_direction direction, uint32_t port_id, @@ -623,7 +612,7 @@ static int impl_node_port_reuse_buffer(void *object, uint32_t port_id, uint32_t if (buffer_id >= this->n_buffers) return -EINVAL; - recycle_buffer(this, buffer_id); + spa_alsa_recycle_buffer(this, buffer_id); return 0; } @@ -643,7 +632,7 @@ static int impl_node_process(void *object) return SPA_STATUS_HAVE_DATA; if (io->buffer_id < this->n_buffers) { - recycle_buffer(this, io->buffer_id); + spa_alsa_recycle_buffer(this, io->buffer_id); io->buffer_id = SPA_ID_INVALID; } @@ -655,6 +644,7 @@ static int impl_node_process(void *object) b = spa_list_first(&this->ready, struct buffer, link); spa_list_remove(&b->link); + SPA_FLAG_SET(b->flags, BUFFER_FLAG_OUT); spa_log_trace_fp(this->log, NAME " %p: dequeue buffer %d", this, b->id); diff --git a/spa/plugins/alsa/alsa-pcm.c b/spa/plugins/alsa/alsa-pcm.c index ef7dd9241..f1b8a08cf 100644 --- a/spa/plugins/alsa/alsa-pcm.c +++ b/spa/plugins/alsa/alsa-pcm.c @@ -858,6 +858,17 @@ again: return 0; } +void spa_alsa_recycle_buffer(struct state *this, uint32_t buffer_id) +{ + struct buffer *b = &this->buffers[buffer_id]; + + if (SPA_FLAG_IS_SET(b->flags, BUFFER_FLAG_OUT)) { + spa_log_trace_fp(this->log, NAME " %p: recycle buffer %u", this, buffer_id); + spa_list_append(&this->free, &b->link); + SPA_FLAG_CLEAR(b->flags, BUFFER_FLAG_OUT); + } +} + static snd_pcm_uframes_t push_frames(struct state *state, const snd_pcm_channel_area_t *my_areas, @@ -909,7 +920,6 @@ push_frames(struct state *state, d[0].chunk->size = n_bytes; d[0].chunk->stride = state->frame_size; - SPA_FLAG_SET(b->flags, BUFFER_FLAG_OUT); spa_list_append(&state->ready, &b->link); } return total_frames - keep; @@ -1054,15 +1064,22 @@ static int handle_capture(struct state *state, uint64_t nsec, if ((res = spa_alsa_read(state, target)) < 0) return res; - if (!spa_list_is_empty(&state->ready)) { - io = state->io; - if (io != NULL && io->status != SPA_STATUS_HAVE_DATA) { - struct buffer *b = spa_list_first(&state->ready, struct buffer, link); - spa_list_remove(&b->link); + if (spa_list_is_empty(&state->ready)) + return 0; - io->buffer_id = b->id; - io->status = SPA_STATUS_HAVE_DATA; - } + io = state->io; + if (io != NULL && io->status != SPA_STATUS_HAVE_DATA) { + struct buffer *b; + + if (io->buffer_id < state->n_buffers) + spa_alsa_recycle_buffer(state, io->buffer_id); + + b = spa_list_first(&state->ready, struct buffer, link); + spa_list_remove(&b->link); + SPA_FLAG_SET(b->flags, BUFFER_FLAG_OUT); + + io->buffer_id = b->id; + io->status = SPA_STATUS_HAVE_DATA; } spa_node_call_ready(&state->callbacks, SPA_STATUS_HAVE_DATA); return 0; diff --git a/spa/plugins/alsa/alsa-pcm.h b/spa/plugins/alsa/alsa-pcm.h index 733b0b0b9..8dd4527a1 100644 --- a/spa/plugins/alsa/alsa-pcm.h +++ b/spa/plugins/alsa/alsa-pcm.h @@ -172,6 +172,8 @@ int spa_alsa_close(struct state *state); int spa_alsa_write(struct state *state, snd_pcm_uframes_t silence); int spa_alsa_read(struct state *state, snd_pcm_uframes_t silence); +void spa_alsa_recycle_buffer(struct state *state, uint32_t buffer_id); + #ifdef __cplusplus } /* extern "C" */ #endif