Skip to content

Commit b3b18f9

Browse files
committed
aplay/pipewire: Prevent underruns by writing silence
This makes sure that pipewire always gets a steady stream of samples, even when we're not receiving anything. This prevents the error count in pw-top skyrocketing when the sender stops sending.
1 parent ce0eff8 commit b3b18f9

File tree

1 file changed

+20
-7
lines changed

1 file changed

+20
-7
lines changed

src/audio/playback/pipewire.cpp

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,13 @@ static void audio_play_pw_help(){
9494
static void on_process(void *userdata) noexcept{
9595
auto s = static_cast<state_pipewire_play *>(userdata);
9696

97-
auto avail = ring_get_current_size(s->ring_buf.get());
97+
const int frame_size = s->desc.ch_count * s->desc.bps;
98+
unsigned avail_frames = ring_get_current_size(s->ring_buf.get()) / frame_size;
9899

99-
while(avail > 0){
100+
//Write at least quant frames to prevent underrun on pipewire side
101+
auto remaining_write_frames = std::max(s->quant, avail_frames);
102+
103+
while(remaining_write_frames > 0){
100104
struct pw_buffer *b = pw_stream_dequeue_buffer(s->stream.get());
101105
if (!b) {
102106
pw_log_warn("out of buffers: %m");
@@ -108,14 +112,23 @@ static void on_process(void *userdata) noexcept{
108112
if (!dst)
109113
return;
110114

111-
int to_write = std::min<int>(buf->datas[0].maxsize, avail);
115+
const int to_write_total = std::min<int>(buf->datas[0].maxsize / frame_size, remaining_write_frames);
116+
const int to_write_audio = std::min<int>(to_write_total, avail_frames);
117+
118+
if(to_write_audio > 0){
119+
ring_buffer_read(s->ring_buf.get(), dst, to_write_audio * frame_size);
120+
avail_frames -= to_write_audio;
121+
remaining_write_frames -= to_write_audio;
122+
dst += to_write_audio * frame_size;
123+
}
112124

113-
ring_buffer_read(s->ring_buf.get(), dst, to_write);
114-
avail -= to_write;
125+
const int to_write_silence = to_write_total - to_write_audio;
126+
memset(dst, 0, to_write_silence * frame_size);
127+
remaining_write_frames -= to_write_silence;
115128

116129
buf->datas[0].chunk->offset = 0;
117-
buf->datas[0].chunk->stride = s->desc.ch_count * s->desc.bps;
118-
buf->datas[0].chunk->size = to_write;
130+
buf->datas[0].chunk->stride = frame_size;
131+
buf->datas[0].chunk->size = to_write_total * frame_size;
119132

120133
pw_stream_queue_buffer(s->stream.get(), b);
121134
}

0 commit comments

Comments
 (0)