[client] audio/pw: use rate matching

This can prevent glitches when the PipeWire quantum size changes.
This commit is contained in:
Chris Spencer 2022-01-10 21:46:34 +00:00 committed by Geoffrey McRae
parent ef9b2958ec
commit 8a61c8ebc2

View File

@ -48,6 +48,7 @@ struct PipeWire
struct struct
{ {
struct pw_stream * stream; struct pw_stream * stream;
struct spa_io_rate_match * rateMatch;
int channels; int channels;
int sampleRate; int sampleRate;
@ -74,6 +75,17 @@ struct PipeWire
static struct PipeWire pw = {0}; static struct PipeWire pw = {0};
static void pipewire_onPlaybackIoChanged(void * userdata, uint32_t id,
void * data, uint32_t size)
{
switch (id)
{
case SPA_IO_RateMatch:
pw.playback.rateMatch = data;
break;
}
}
static void pipewire_onPlaybackProcess(void * userdata) static void pipewire_onPlaybackProcess(void * userdata)
{ {
struct pw_buffer * pbuf; struct pw_buffer * pbuf;
@ -104,6 +116,9 @@ static void pipewire_onPlaybackProcess(void * userdata)
return; return;
int frames = sbuf->datas[0].maxsize / pw.playback.stride; int frames = sbuf->datas[0].maxsize / pw.playback.stride;
if (pw.playback.rateMatch && pw.playback.rateMatch->size > 0)
frames = min(frames, pw.playback.rateMatch->size);
void * values = ringbuffer_consume(pw.playback.buffer, &frames); void * values = ringbuffer_consume(pw.playback.buffer, &frames);
memcpy(dst, values, frames * pw.playback.stride); memcpy(dst, values, frames * pw.playback.stride);
@ -180,7 +195,8 @@ static void pipewire_playbackStopStream(void)
pw_thread_loop_lock(pw.thread); pw_thread_loop_lock(pw.thread);
pw_stream_destroy(pw.playback.stream); pw_stream_destroy(pw.playback.stream);
pw.playback.stream = NULL; pw.playback.stream = NULL;
pw.playback.rateMatch = NULL;
pw_thread_loop_unlock(pw.thread); pw_thread_loop_unlock(pw.thread);
} }
@ -191,9 +207,10 @@ static void pipewire_playbackStart(int channels, int sampleRate)
struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer)); struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
static const struct pw_stream_events events = static const struct pw_stream_events events =
{ {
.version = PW_VERSION_STREAM_EVENTS, .version = PW_VERSION_STREAM_EVENTS,
.process = pipewire_onPlaybackProcess, .io_changed = pipewire_onPlaybackIoChanged,
.drained = pipewire_onPlaybackDrained .process = pipewire_onPlaybackProcess,
.drained = pipewire_onPlaybackDrained
}; };
if (pw.playback.stream && if (pw.playback.stream &&