From 84af13a10bfd37f585f18ed5ddbd6ac4fbb016d2 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Tue, 12 Mar 2024 10:11:02 +0100 Subject: [PATCH] settings: add default.clock.quantum-floor property Remove some of the hardcoded values (the absolute smallest buffer size, independent on the sample rate) to a config option. Set it to the default value of 4, like what it was before. Change the hardcoded absolute lowest limit to 1 because anything else does not make sense. Enforce the quantum-floor when calculating the final graph quantum. Fixes #3908 --- doc/dox/config/pipewire.conf.5.md | 10 ++++++++-- src/daemon/minimal.conf.in | 1 + src/daemon/pipewire.conf.in | 1 + src/pipewire/context.c | 12 +++++++----- src/pipewire/private.h | 7 ++++--- src/pipewire/settings.c | 10 +++++++--- 6 files changed, 28 insertions(+), 13 deletions(-) diff --git a/doc/dox/config/pipewire.conf.5.md b/doc/dox/config/pipewire.conf.5.md index c2cd7b828..3c1868480 100644 --- a/doc/dox/config/pipewire.conf.5.md +++ b/doc/dox/config/pipewire.conf.5.md @@ -177,7 +177,8 @@ the quantums. It is possible to specify up to 32 alternative sample rates. The graph sample rate will be switched when devices are idle. Note that this is not enabled by default for now because of various kernel and Bluetooth -issues. +issues. Note that the min/max/default quantum values are scaled when +the samplerate changes. @PAR@ pipewire.conf default.clock.min-quantum = 32 Default minimum quantum. @@ -189,7 +190,12 @@ Default maximum quantum. Default quantum used when no client specifies one. @PAR@ pipewire.conf default.clock.quantum-limit = 8192 -Maximum quantum to reserve space for. +Maximum quantum to reserve space for. This is the maximum buffer size used +in the graph, regardless of the samplerate. + +@PAR@ pipewire.conf default.clock.quantum-floor = 4 +Minimum quantum to reserve space for. This is the minimum buffer size used +in the graph, regardless of the samplerate. @PAR@ pipewire.conf default.video.width Default video width diff --git a/src/daemon/minimal.conf.in b/src/daemon/minimal.conf.in index cde4e8203..08a9f38e1 100644 --- a/src/daemon/minimal.conf.in +++ b/src/daemon/minimal.conf.in @@ -32,6 +32,7 @@ context.properties = { #default.clock.min-quantum = 32 #default.clock.max-quantum = 2048 #default.clock.quantum-limit = 8192 + #default.clock.quantum-floor = 4 #default.video.width = 640 #default.video.height = 480 #default.video.rate.num = 25 diff --git a/src/daemon/pipewire.conf.in b/src/daemon/pipewire.conf.in index c78bc1db0..71926f6a0 100644 --- a/src/daemon/pipewire.conf.in +++ b/src/daemon/pipewire.conf.in @@ -32,6 +32,7 @@ context.properties = { #default.clock.min-quantum = 32 #default.clock.max-quantum = 2048 #default.clock.quantum-limit = 8192 + #default.clock.quantum-floor = 4 #default.video.width = 640 #default.video.height = 480 #default.video.rate.num = 25 diff --git a/src/pipewire/context.c b/src/pipewire/context.c index 31973781f..eec4f2225 100644 --- a/src/pipewire/context.c +++ b/src/pipewire/context.c @@ -1023,7 +1023,7 @@ static void remove_from_driver(struct pw_context *context, struct spa_list *node } static inline void get_quantums(struct pw_context *context, uint32_t *def, - uint32_t *min, uint32_t *max, uint32_t *limit, uint32_t *rate) + uint32_t *min, uint32_t *max, uint32_t *rate, uint32_t *floor, uint32_t *ceil) { struct settings *s = &context->settings; if (s->clock_force_quantum != 0) { @@ -1035,7 +1035,8 @@ static inline void get_quantums(struct pw_context *context, uint32_t *def, *max = s->clock_max_quantum; *rate = s->clock_rate; } - *limit = s->clock_quantum_limit; + *floor = s->clock_quantum_floor; + *ceil = s->clock_quantum_limit; } static inline const uint32_t *get_rates(struct pw_context *context, uint32_t *def, uint32_t *n_rates, @@ -1228,7 +1229,7 @@ int pw_context_recalc_graph(struct pw_context *context, const char *reason) struct settings *settings = &context->settings; struct pw_impl_node *n, *s, *target, *fallback; const uint32_t *rates; - uint32_t max_quantum, min_quantum, def_quantum, lim_quantum, rate_quantum; + uint32_t max_quantum, min_quantum, def_quantum, rate_quantum, floor_quantum, ceil_quantum; uint32_t n_rates, def_rate, n_sync; bool freewheel, global_force_rate, global_force_quantum, transport_start; struct spa_list collect; @@ -1265,7 +1266,8 @@ again: } } - get_quantums(context, &def_quantum, &min_quantum, &max_quantum, &lim_quantum, &rate_quantum); + get_quantums(context, &def_quantum, &min_quantum, &max_quantum, &rate_quantum, + &floor_quantum, &ceil_quantum); rates = get_rates(context, &def_rate, &n_rates, &global_force_rate); global_force_quantum = rate_quantum == 0; @@ -1544,7 +1546,7 @@ again: if (latency.denom != 0) target_quantum = (latency.num * current_rate / latency.denom); target_quantum = SPA_CLAMP(target_quantum, node_min_quantum, node_max_quantum); - target_quantum = SPA_MIN(target_quantum, lim_quantum); + target_quantum = SPA_CLAMP(target_quantum, floor_quantum, ceil_quantum); if (settings->clock_power_of_two_quantum && !force_quantum) target_quantum = flp2(target_quantum); diff --git a/src/pipewire/private.h b/src/pipewire/private.h index 005de33e9..6f463f6d2 100644 --- a/src/pipewire/private.h +++ b/src/pipewire/private.h @@ -30,8 +30,8 @@ struct ucred { #endif #define MAX_RATES 32u -#define CLOCK_MIN_QUANTUM 4u -#define CLOCK_MAX_QUANTUM 65536u +#define CLOCK_QUANTUM_FLOOR 1u +#define CLOCK_QUANTUM_LIMIT 65536u #define DEFAULT_LOG_LEVEL SPA_LOG_LEVEL_WARN struct settings { @@ -42,7 +42,8 @@ struct settings { uint32_t clock_quantum; /* default quantum */ uint32_t clock_min_quantum; /* min quantum */ uint32_t clock_max_quantum; /* max quantum */ - uint32_t clock_quantum_limit; /* quantum limit */ + uint32_t clock_quantum_limit; /* quantum limit (upper bound) */ + uint32_t clock_quantum_floor; /* quantum floor (lower bound) */ struct spa_rectangle video_size; struct spa_fraction video_rate; uint32_t link_max_buffers; diff --git a/src/pipewire/settings.c b/src/pipewire/settings.c index 65ac0bd2c..a28aea9f2 100644 --- a/src/pipewire/settings.c +++ b/src/pipewire/settings.c @@ -26,6 +26,7 @@ #define DEFAULT_CLOCK_MIN_QUANTUM 32u #define DEFAULT_CLOCK_MAX_QUANTUM 2048u #define DEFAULT_CLOCK_QUANTUM_LIMIT 8192u +#define DEFAULT_CLOCK_QUANTUM_FLOOR 4u #define DEFAULT_CLOCK_POWER_OF_TWO_QUANTUM true #define DEFAULT_VIDEO_WIDTH 640 #define DEFAULT_VIDEO_HEIGHT 480 @@ -212,6 +213,7 @@ void pw_settings_init(struct pw_context *this) d->clock_min_quantum = get_default_int(p, "default.clock.min-quantum", DEFAULT_CLOCK_MIN_QUANTUM); d->clock_max_quantum = get_default_int(p, "default.clock.max-quantum", DEFAULT_CLOCK_MAX_QUANTUM); d->clock_quantum_limit = get_default_int(p, "default.clock.quantum-limit", DEFAULT_CLOCK_QUANTUM_LIMIT); + d->clock_quantum_floor = get_default_int(p, "default.clock.quantum-floor", DEFAULT_CLOCK_QUANTUM_FLOOR); d->video_size.width = get_default_int(p, "default.video.width", DEFAULT_VIDEO_WIDTH); d->video_size.height = get_default_int(p, "default.video.height", DEFAULT_VIDEO_HEIGHT); d->video_rate.num = get_default_int(p, "default.video.rate.num", DEFAULT_VIDEO_RATE_NUM); @@ -228,11 +230,13 @@ void pw_settings_init(struct pw_context *this) d->check_rate = get_default_bool(p, "settings.check-rate", DEFAULT_CHECK_RATE); d->clock_quantum_limit = SPA_CLAMP(d->clock_quantum_limit, - CLOCK_MIN_QUANTUM, CLOCK_MAX_QUANTUM); + CLOCK_QUANTUM_FLOOR, CLOCK_QUANTUM_LIMIT); + d->clock_quantum_floor = SPA_CLAMP(d->clock_quantum_floor, + CLOCK_QUANTUM_FLOOR, d->clock_quantum_limit); d->clock_max_quantum = SPA_CLAMP(d->clock_max_quantum, - CLOCK_MIN_QUANTUM, d->clock_quantum_limit); + d->clock_quantum_floor, d->clock_quantum_limit); d->clock_min_quantum = SPA_CLAMP(d->clock_min_quantum, - CLOCK_MIN_QUANTUM, d->clock_max_quantum); + d->clock_quantum_floor, d->clock_max_quantum); d->clock_quantum = SPA_CLAMP(d->clock_quantum, d->clock_min_quantum, d->clock_max_quantum); }