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