From 1f4254b344f40fad0e31d256f78f7cba67d906df Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Tue, 14 Dec 2021 15:48:54 +0100 Subject: [PATCH] pulse-server: track quantum and update tlength Keep track of the current quantum and recalculate the tlength in the same way that pulseaudio does. Send a bufferattr changed message to a client when we change the parameters. This fixes the case where the quantum is increased and there needs to be more buffering to keep the stream going. --- .../module-protocol-pulse/pulse-server.c | 15 +++++-- src/modules/module-protocol-pulse/stream.c | 39 +++++++++++++++++++ src/modules/module-protocol-pulse/stream.h | 7 +++- 3 files changed, 56 insertions(+), 5 deletions(-) diff --git a/src/modules/module-protocol-pulse/pulse-server.c b/src/modules/module-protocol-pulse/pulse-server.c index 6e114c4b0..7fd67f42a 100644 --- a/src/modules/module-protocol-pulse/pulse-server.c +++ b/src/modules/module-protocol-pulse/pulse-server.c @@ -1089,6 +1089,9 @@ static void stream_io_changed(void *data, uint32_t id, void *area, uint32_t size case SPA_IO_RateMatch: stream->rate_match = area; break; + case SPA_IO_Position: + stream->position = area; + break; } } @@ -1099,7 +1102,8 @@ struct process_data { uint32_t underrun_for; uint32_t playing_for; uint32_t missing; - uint32_t maxmissing; + uint32_t minreq; + uint32_t quantum; unsigned int underrun:1; }; @@ -1121,6 +1125,10 @@ do_process_done(struct spa_loop *loop, stream->delay = 0; if (stream->direction == PW_DIRECTION_OUTPUT) { + if (stream->last_quantum != 0 && pd->quantum != stream->last_quantum) + stream_update_minreq(stream, pd->minreq); + stream->last_quantum = pd->quantum; + stream->read_index += pd->read_inc; if (stream->corked) { if (stream->underrun_for != (uint64_t)-1) @@ -1138,7 +1146,7 @@ do_process_done(struct spa_loop *loop, stream_send_started(stream); } stream->missing += pd->missing; - stream->missing = SPA_MIN(stream->missing, pd->maxmissing); + stream->missing = SPA_MIN(stream->missing, (int64_t)stream->attr.tlength); stream->playing_for += pd->playing_for; if (stream->underrun_for != (uint64_t)-1) stream->underrun_for += pd->underrun_for; @@ -1232,7 +1240,8 @@ static void stream_process(void *data) if (minreq == 0) minreq = stream->attr.minreq; - pd.maxmissing = SPA_MAX(minreq, stream->attr.tlength); + pd.minreq = minreq; + pd.quantum = stream->position ? stream->position->clock.duration : minreq; if (avail < (int32_t)minreq || stream->corked) { /* underrun, produce a silence buffer */ diff --git a/src/modules/module-protocol-pulse/stream.c b/src/modules/module-protocol-pulse/stream.c index 903b44add..a7b7f3a7d 100644 --- a/src/modules/module-protocol-pulse/stream.c +++ b/src/modules/module-protocol-pulse/stream.c @@ -256,3 +256,42 @@ int stream_send_request(struct stream *stream) return client_queue_message(client, msg); } + +int stream_update_minreq(struct stream *stream, uint32_t minreq) +{ + struct client *client = stream->client; + struct impl *impl = client->impl; + uint32_t old_tlength = stream->attr.tlength; + uint32_t new_tlength = minreq + 2 * stream->attr.minreq; + uint64_t lat_usec; + + if (new_tlength == old_tlength) + return 0; + + if (old_tlength > new_tlength) + stream->missing -= old_tlength - new_tlength; + else + stream->missing += new_tlength - old_tlength; + + stream->attr.tlength = new_tlength; + + if (client->version >= 15) { + struct message *msg; + + lat_usec = minreq * SPA_USEC_PER_SEC / stream->ss.rate; + + msg = message_alloc(impl, -1, 0); + message_put(msg, + TAG_U32, COMMAND_PLAYBACK_BUFFER_ATTR_CHANGED, + TAG_U32, -1, + TAG_U32, stream->channel, + TAG_U32, stream->attr.maxlength, + TAG_U32, stream->attr.tlength, + TAG_U32, stream->attr.prebuf, + TAG_U32, stream->attr.minreq, + TAG_USEC, lat_usec, + TAG_INVALID); + return client_queue_message(client, msg); + } + return 0; +} diff --git a/src/modules/module-protocol-pulse/stream.h b/src/modules/module-protocol-pulse/stream.h index e094ce402..4bf26f397 100644 --- a/src/modules/module-protocol-pulse/stream.h +++ b/src/modules/module-protocol-pulse/stream.h @@ -67,6 +67,7 @@ struct stream { struct spa_hook stream_listener; struct spa_io_rate_match *rate_match; + struct spa_io_position *position; struct spa_ringbuffer ring; void *buffer; @@ -78,8 +79,9 @@ struct stream { uint64_t timestamp; int64_t delay; - uint32_t missing; - uint32_t requested; + uint32_t last_quantum; + int64_t missing; + int64_t requested; struct sample_spec ss; struct channel_map map; @@ -112,5 +114,6 @@ int stream_send_overflow(struct stream *stream); int stream_send_killed(struct stream *stream); int stream_send_started(struct stream *stream); int stream_send_request(struct stream *stream); +int stream_update_minreq(struct stream *stream, uint32_t minreq); #endif /* PULSER_SERVER_STREAM_H */