diff --git a/src/pipewire/stream.c b/src/pipewire/stream.c index 9a6383ce7..94956bda2 100644 --- a/src/pipewire/stream.c +++ b/src/pipewire/stream.c @@ -2479,6 +2479,41 @@ int pw_stream_queue_buffer(struct pw_stream *stream, struct pw_buffer *buffer) return res; } +static inline int queue_push_front(struct stream *stream, struct queue *queue, struct buffer *buffer) +{ + int ret = 0; + uint32_t index; + + if ((ret = spa_ringbuffer_get_read_index(&queue->ring, &index)) < 0) + return ret; + + /* undo the pop operation and place the buffer in front of the queue */ + index -= 1; + queue->ids[index & MASK_BUFFERS] = buffer->id; + queue->outcount -= buffer->this.size; + SPA_FLAG_SET(buffer->flags, BUFFER_FLAG_QUEUED); + spa_ringbuffer_read_update(&queue->ring, index); + + return ret; +} + +SPA_EXPORT +int pw_stream_return_buffer(struct pw_stream *stream, struct pw_buffer *buffer) +{ + struct stream *impl = SPA_CONTAINER_OF(stream, struct stream, this); + struct buffer *b = SPA_CONTAINER_OF(buffer, struct buffer, this); + + pw_log_trace_fp("%p: %p id: %d", impl, buffer, b->id); + + /* dequeue increments the busy count, so undo that */ + if (b->busy) { + SPA_ATOMIC_DEC(b->busy->count); + pw_log_trace_fp("%p: %p: %p busy count %u", impl, b, b->busy, SPA_ATOMIC_LOAD(b->busy->count)); + } + + return queue_push_front(impl, &impl->dequeued, b); +} + static int do_flush(struct spa_loop *loop, bool async, uint32_t seq, const void *data, size_t size, void *user_data) diff --git a/src/pipewire/stream.h b/src/pipewire/stream.h index 506a01238..a1fe2809f 100644 --- a/src/pipewire/stream.h +++ b/src/pipewire/stream.h @@ -597,6 +597,10 @@ struct pw_buffer *pw_stream_dequeue_buffer(struct pw_stream *stream); /** Submit a buffer for playback or recycle a buffer for capture. */ int pw_stream_queue_buffer(struct pw_stream *stream, struct pw_buffer *buffer); +/** Return a buffer to the queue without using it. This makes the buffer + * immediately available to dequeue again. */ +int pw_stream_return_buffer(struct pw_stream *stream, struct pw_buffer *buffer); + /** Activate or deactivate the stream */ int pw_stream_set_active(struct pw_stream *stream, bool active);