mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-10-29 05:40:27 -04:00
examples: improve the ringbuffer example a little
Write the remaining samples in the ringbuffer and fill up the rest with silence. Add some more comments.
This commit is contained in:
parent
ca488a5dcc
commit
e095a1c4ac
1 changed files with 23 additions and 17 deletions
|
|
@ -55,6 +55,8 @@ static void fill_f32(struct data *d, uint32_t offset, int n_frames)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* this is called from the main-thread when we need to fill up the ringbuffer
|
||||||
|
* with more data */
|
||||||
static void do_refill(void *userdata, uint64_t count)
|
static void do_refill(void *userdata, uint64_t count)
|
||||||
{
|
{
|
||||||
struct data *data = userdata;
|
struct data *data = userdata;
|
||||||
|
|
@ -84,6 +86,8 @@ static void do_refill(void *userdata, uint64_t count)
|
||||||
* b = pw_stream_dequeue_buffer(stream);
|
* b = pw_stream_dequeue_buffer(stream);
|
||||||
*
|
*
|
||||||
* .. generate stuff in the buffer ...
|
* .. generate stuff in the buffer ...
|
||||||
|
* In this case we read samples from a ringbuffer. The ringbuffer is
|
||||||
|
* filled up by another thread.
|
||||||
*
|
*
|
||||||
* pw_stream_queue_buffer(stream, b);
|
* pw_stream_queue_buffer(stream, b);
|
||||||
*/
|
*/
|
||||||
|
|
@ -92,10 +96,9 @@ static void on_process(void *userdata)
|
||||||
struct data *data = userdata;
|
struct data *data = userdata;
|
||||||
struct pw_buffer *b;
|
struct pw_buffer *b;
|
||||||
struct spa_buffer *buf;
|
struct spa_buffer *buf;
|
||||||
int n_frames, stride;
|
|
||||||
uint8_t *p;
|
uint8_t *p;
|
||||||
uint32_t index;
|
uint32_t index, to_read, to_silence;
|
||||||
int32_t avail;
|
int32_t avail, n_frames, stride;
|
||||||
|
|
||||||
if ((b = pw_stream_dequeue_buffer(data->stream)) == NULL) {
|
if ((b = pw_stream_dequeue_buffer(data->stream)) == NULL) {
|
||||||
pw_log_warn("out of buffers: %m");
|
pw_log_warn("out of buffers: %m");
|
||||||
|
|
@ -112,32 +115,35 @@ static void on_process(void *userdata)
|
||||||
stride = sizeof(float) * DEFAULT_CHANNELS;
|
stride = sizeof(float) * DEFAULT_CHANNELS;
|
||||||
n_frames = buf->datas[0].maxsize / stride;
|
n_frames = buf->datas[0].maxsize / stride;
|
||||||
if (b->requested)
|
if (b->requested)
|
||||||
n_frames = SPA_MIN((int)b->requested, n_frames);
|
n_frames = SPA_MIN((int32_t)b->requested, n_frames);
|
||||||
|
|
||||||
if (avail < (int32_t)n_frames) {
|
/* we can read if there is something available */
|
||||||
/* there is not enough data available in the ringbuffer,
|
to_read = avail > 0 ? SPA_MIN(avail, n_frames) : 0;
|
||||||
* fill with silence and hope it will be filled next time */
|
/* and fill the remainder with silence */
|
||||||
memset(p, 0, n_frames * stride);
|
to_silence = n_frames - to_read;
|
||||||
pw_log_warn("underrun");
|
|
||||||
} else {
|
if (to_read > 0) {
|
||||||
/* enough data in the ringbuffer, copy it into the buffer data.
|
/* read data into the buffer */
|
||||||
* We use the number of samples as the read/write counters so we
|
|
||||||
* need to multiply with the stride to get the byte offsets. */
|
|
||||||
spa_ringbuffer_read_data(&data->ring,
|
spa_ringbuffer_read_data(&data->ring,
|
||||||
data->buffer, BUFFER_SIZE * stride,
|
data->buffer, BUFFER_SIZE * stride,
|
||||||
(index % BUFFER_SIZE) * stride,
|
(index % BUFFER_SIZE) * stride,
|
||||||
p, n_frames * stride);
|
p, to_read * stride);
|
||||||
/* update the read pointer */
|
/* update the read pointer */
|
||||||
spa_ringbuffer_read_update(&data->ring, index + n_frames);
|
spa_ringbuffer_read_update(&data->ring, index + to_read);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
if (to_silence > 0)
|
||||||
|
/* set the rest of the buffer to silence */
|
||||||
|
memset(SPA_PTROFF(p, to_read * stride, void), 0, to_silence * stride);
|
||||||
|
|
||||||
buf->datas[0].chunk->offset = 0;
|
buf->datas[0].chunk->offset = 0;
|
||||||
buf->datas[0].chunk->stride = stride;
|
buf->datas[0].chunk->stride = stride;
|
||||||
buf->datas[0].chunk->size = n_frames * stride;
|
buf->datas[0].chunk->size = n_frames * stride;
|
||||||
|
|
||||||
pw_stream_queue_buffer(data->stream, b);
|
pw_stream_queue_buffer(data->stream, b);
|
||||||
|
|
||||||
/* signal the main thread to fill the ringbuffer */
|
/* signal the main thread to fill the ringbuffer, we can only do this, for
|
||||||
|
* example when the available ringbuffer space falls below a certain
|
||||||
|
* level. */
|
||||||
pw_loop_signal_event(data->loop, data->refill_event);
|
pw_loop_signal_event(data->loop, data->refill_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue