From a79d1fc86680e99aee0be61fa47adee4acfd3e6d Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Fri, 25 Sep 2020 17:06:46 +0200 Subject: [PATCH] pulse: tweak buffer attributes some more Seems to work well with vlc and firefox other apps now. paplay without ADJUST_LATENCY reports wrong latency still. --- pipewire-pulseaudio/src/stream.c | 59 +++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 20 deletions(-) diff --git a/pipewire-pulseaudio/src/stream.c b/pipewire-pulseaudio/src/stream.c index 1961b0fc6..969ddf332 100644 --- a/pipewire-pulseaudio/src/stream.c +++ b/pipewire-pulseaudio/src/stream.c @@ -33,7 +33,7 @@ #include "core-format.h" #include "internal.h" -#define MIN_SAMPLES 8u +#define MIN_SAMPLES 24u #define MIN_BUFFERS 8u #define MAX_BUFFERS 64u @@ -144,11 +144,11 @@ static const struct spa_pod *get_buffers_param(pa_stream *s, pa_buffer_attr *att blocks = 1; stride = pa_frame_size(&s->sample_spec); - maxsize = attr->tlength * MAX_BUFFERS; - size = attr->tlength; + maxsize = attr->tlength; + size = attr->minreq; buffers = SPA_CLAMP(maxsize / size, MIN_BUFFERS, MAX_BUFFERS); - pw_log_debug("stream %p: stride %d maxsize %d size %u buffers %d", s, stride, maxsize, + pw_log_info("stream %p: stride %d maxsize %d size %u buffers %d", s, stride, maxsize, size, buffers); param = spa_pod_builder_add_object(b, @@ -222,19 +222,15 @@ static void patch_buffer_attr(pa_stream *s, pa_buffer_attr *attr, pa_stream_flag attr->tlength = (uint32_t) pa_usec_to_bytes(2*PA_USEC_PER_SEC, &s->sample_spec); attr->tlength = SPA_MIN(attr->tlength, attr->maxlength); attr->tlength -= attr->tlength % stride; - attr->tlength = SPA_MAX(attr->tlength, MIN_SAMPLES * stride * MIN_BUFFERS); if (attr->minreq == (uint32_t) -1) - attr->minreq = pa_usec_to_bytes(25*PA_USEC_PER_MSEC, &s->sample_spec); - attr->minreq = SPA_MIN(attr->minreq, attr->tlength / MIN_BUFFERS); + attr->minreq = pa_usec_to_bytes(20*PA_USEC_PER_MSEC, &s->sample_spec); + attr->minreq = SPA_MIN(attr->minreq, attr->tlength / 4); + attr->minreq = SPA_MAX(attr->minreq, MIN_SAMPLES * stride); attr->minreq -= attr->minreq % stride; attr->minreq = SPA_MAX(attr->minreq, stride); - if (attr->fragsize == (uint32_t) -1) - attr->fragsize = pa_usec_to_bytes(25*PA_USEC_PER_MSEC, &s->sample_spec); - attr->fragsize = SPA_MIN(attr->fragsize, attr->tlength / MIN_BUFFERS); - attr->fragsize -= attr->fragsize % stride; - attr->fragsize = SPA_MAX(attr->fragsize, stride); + attr->tlength = SPA_MAX(attr->tlength, attr->minreq * 4); if (attr->prebuf == (uint32_t) -1) attr->prebuf = attr->tlength - attr->minreq; @@ -242,6 +238,13 @@ static void patch_buffer_attr(pa_stream *s, pa_buffer_attr *attr, pa_stream_flag attr->prebuf -= attr->prebuf % stride; attr->prebuf = SPA_MAX(attr->prebuf, stride); + if (attr->fragsize == (uint32_t) -1) + attr->fragsize = pa_usec_to_bytes(20*PA_USEC_PER_MSEC, &s->sample_spec); + attr->fragsize = SPA_MIN(attr->fragsize, attr->tlength / 4); + attr->fragsize -= attr->fragsize % stride; + attr->fragsize = SPA_MAX(attr->fragsize, MIN_SAMPLES * stride); + attr->fragsize = SPA_MAX(attr->fragsize, stride); + dump_buffer_attr(s, attr); } @@ -451,6 +454,15 @@ static inline uint32_t queued_size(const pa_stream *s, uint64_t elapsed) queued -= SPA_MIN(queued, elapsed); return queued; } +static inline uint32_t target_queue(const pa_stream *s) +{ + return s->buffer_attr.tlength; +} + +static inline uint32_t wanted_size(const pa_stream *s, uint32_t queued, uint32_t target) +{ + return target - SPA_MIN(queued, target); +} static inline uint32_t writable_size(const pa_stream *s, uint64_t queued) { @@ -459,7 +471,7 @@ static inline uint32_t writable_size(const pa_stream *s, uint64_t queued) static inline uint32_t required_size(const pa_stream *s) { - return s->buffer_attr.tlength; + return s->buffer_attr.minreq; } static void stream_process(void *data) @@ -470,16 +482,22 @@ static void stream_process(void *data) update_timing_info(s); if (s->direction == PA_STREAM_PLAYBACK) { - uint64_t queued, writable, required; + uint32_t queued, target, wanted, required; queue_output(s); queued = queued_size(s, 0); - writable = writable_size(s, queued); + target = target_queue(s); + wanted = wanted_size(s, queued, target); required = required_size(s); - if (s->write_callback && s->state == PA_STREAM_READY && queued < required && writable >= required) - s->write_callback(s, required, s->write_userdata); + pw_log_trace("stream %p, queued:%u target:%u wanted:%u required:%u", + s, queued, target, wanted, required); + + if (s->write_callback && s->state == PA_STREAM_READY && + queued < wanted && + wanted >= required) + s->write_callback(s, wanted, s->write_userdata); } else { pull_input(s); @@ -986,7 +1004,7 @@ static int create_stream(pa_stream_direction_t direction, if (monitor) sprintf(latency, "%u/%u", s->buffer_attr.fragsize / stride, s->sample_spec.rate); else - sprintf(latency, "%u/%u", s->buffer_attr.tlength / 2 / stride, s->sample_spec.rate); + sprintf(latency, "%u/%u", s->buffer_attr.minreq * 2 / stride, s->sample_spec.rate); n_items = 0; items[n_items++] = SPA_DICT_ITEM_INIT(PW_KEY_NODE_LATENCY, latency); items[n_items++] = SPA_DICT_ITEM_INIT(PW_KEY_MEDIA_TYPE, "Audio"); @@ -1293,8 +1311,9 @@ size_t pa_stream_writable_size(PA_CONST pa_stream *s) writable = writable_size(s, queued); required = required_size(s); - pw_log_debug("stream %p: %"PRIu64" minreq:%u maxblock:%zu", s, - writable, s->buffer_attr.minreq, s->maxblock); + pw_log_debug("stream %p: writable:%"PRIu64" queued:%"PRIu64" required:%"PRIu64, s, + writable, queued, required); + if (writable < required) writable = 0;