context: improve settings and defaults

Make structure with defaults that holds the defaults as they are loaded
from the config file or initialized with default values.

Copy this structure to a settings version that is used at runtime.

Add a force-quantum and force-rate field in the settings that can be
used to force a quantum and samplerate if != 0.
This commit is contained in:
Wim Taymans 2021-06-14 17:05:13 +02:00
parent 2ad202b8e8
commit d8ad87fd09
8 changed files with 70 additions and 46 deletions

View file

@ -2796,8 +2796,8 @@ jack_client_t * jack_client_open (const char *client_name,
if (client->context.context == NULL) if (client->context.context == NULL)
goto no_props; goto no_props;
client->allow_mlock = client->context.context->defaults.mem_allow_mlock; client->allow_mlock = client->context.context->settings.mem_allow_mlock;
client->warn_mlock = client->context.context->defaults.mem_warn_mlock; client->warn_mlock = client->context.context->settings.mem_warn_mlock;
if ((str = pw_context_get_conf_section(client->context.context, if ((str = pw_context_get_conf_section(client->context.context,
"jack.properties")) != NULL) "jack.properties")) != NULL)

View file

@ -1219,11 +1219,11 @@ static struct pw_proxy *node_export(struct pw_core *core, void *object, bool do_
data->client_node = (struct pw_client_node *)client_node; data->client_node = (struct pw_client_node *)client_node;
data->remote_id = SPA_ID_INVALID; data->remote_id = SPA_ID_INVALID;
data->allow_mlock = data->context->defaults.mem_allow_mlock; data->allow_mlock = data->context->settings.mem_allow_mlock;
if ((str = pw_properties_get(node->properties, "mem.allow-mlock")) != NULL) if ((str = pw_properties_get(node->properties, "mem.allow-mlock")) != NULL)
data->allow_mlock = pw_properties_parse_bool(str); data->allow_mlock = pw_properties_parse_bool(str);
data->warn_mlock = data->context->defaults.mem_warn_mlock; data->warn_mlock = data->context->settings.mem_warn_mlock;
if ((str = pw_properties_get(node->properties, "mem.warn-mlock")) != NULL) if ((str = pw_properties_get(node->properties, "mem.warn-mlock")) != NULL)
data->warn_mlock = pw_properties_parse_bool(str); data->warn_mlock = pw_properties_parse_bool(str);

View file

@ -278,7 +278,7 @@ int pw_buffers_negotiate(struct pw_context *context, uint32_t flags,
offset += SPA_ROUND_UP_N(SPA_POD_SIZE(params[i]), 8); offset += SPA_ROUND_UP_N(SPA_POD_SIZE(params[i]), 8);
} }
max_buffers = context->defaults.link_max_buffers; max_buffers = context->settings.link_max_buffers;
if ((str = pw_properties_get(context->properties, PW_KEY_CPU_MAX_ALIGN)) != NULL) if ((str = pw_properties_get(context->properties, PW_KEY_CPU_MAX_ALIGN)) != NULL)
align = pw_properties_parse_int(str); align = pw_properties_parse_int(str);

View file

@ -47,9 +47,6 @@
#define NAME "context" #define NAME "context"
#define CLOCK_MIN_QUANTUM 4u
#define CLOCK_MAX_QUANTUM 8192u
#define DEFAULT_CLOCK_RATE 48000u #define DEFAULT_CLOCK_RATE 48000u
#define DEFAULT_CLOCK_QUANTUM 1024u #define DEFAULT_CLOCK_QUANTUM 1024u
#define DEFAULT_CLOCK_MIN_QUANTUM 32u #define DEFAULT_CLOCK_MIN_QUANTUM 32u
@ -141,26 +138,30 @@ static bool get_default_bool(struct pw_properties *properties, const char *name,
static void fill_defaults(struct pw_context *this) static void fill_defaults(struct pw_context *this)
{ {
struct pw_properties *p = this->properties; struct pw_properties *p = this->properties;
this->defaults.clock_power_of_two_quantum = get_default_bool(p, "clock.power-of-two-quantum", struct settings *d = &this->defaults;
DEFAULT_CLOCK_POWER_OF_TWO_QUANTUM);
this->defaults.clock_rate = get_default_int(p, "default.clock.rate", DEFAULT_CLOCK_RATE);
this->defaults.clock_quantum = get_default_int(p, "default.clock.quantum", DEFAULT_CLOCK_QUANTUM);
this->defaults.clock_min_quantum = get_default_int(p, "default.clock.min-quantum", DEFAULT_CLOCK_MIN_QUANTUM);
this->defaults.clock_max_quantum = get_default_int(p, "default.clock.max-quantum", DEFAULT_CLOCK_MAX_QUANTUM);
this->defaults.video_size.width = get_default_int(p, "default.video.width", DEFAULT_VIDEO_WIDTH);
this->defaults.video_size.height = get_default_int(p, "default.video.height", DEFAULT_VIDEO_HEIGHT);
this->defaults.video_rate.num = get_default_int(p, "default.video.rate.num", DEFAULT_VIDEO_RATE_NUM);
this->defaults.video_rate.denom = get_default_int(p, "default.video.rate.denom", DEFAULT_VIDEO_RATE_DENOM);
this->defaults.link_max_buffers = get_default_int(p, "link.max-buffers", DEFAULT_LINK_MAX_BUFFERS);
this->defaults.mem_warn_mlock = get_default_bool(p, "mem.warn-mlock", DEFAULT_MEM_WARN_MLOCK);
this->defaults.mem_allow_mlock = get_default_bool(p, "mem.allow-mlock", DEFAULT_MEM_ALLOW_MLOCK);
this->defaults.clock_max_quantum = SPA_CLAMP(this->defaults.clock_max_quantum, d->clock_rate = get_default_int(p, "default.clock.rate", DEFAULT_CLOCK_RATE);
d->clock_quantum = get_default_int(p, "default.clock.quantum", DEFAULT_CLOCK_QUANTUM);
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->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);
d->video_rate.denom = get_default_int(p, "default.video.rate.denom", DEFAULT_VIDEO_RATE_DENOM);
d->log_level = get_default_int(p, "log.level", pw_log_level);
d->clock_power_of_two_quantum = get_default_bool(p, "clock.power-of-two-quantum",
DEFAULT_CLOCK_POWER_OF_TWO_QUANTUM);
d->link_max_buffers = get_default_int(p, "link.max-buffers", DEFAULT_LINK_MAX_BUFFERS);
d->mem_warn_mlock = get_default_bool(p, "mem.warn-mlock", DEFAULT_MEM_WARN_MLOCK);
d->mem_allow_mlock = get_default_bool(p, "mem.allow-mlock", DEFAULT_MEM_ALLOW_MLOCK);
d->clock_max_quantum = SPA_CLAMP(d->clock_max_quantum,
CLOCK_MIN_QUANTUM, CLOCK_MAX_QUANTUM); CLOCK_MIN_QUANTUM, CLOCK_MAX_QUANTUM);
this->defaults.clock_min_quantum = SPA_CLAMP(this->defaults.clock_min_quantum, d->clock_min_quantum = SPA_CLAMP(d->clock_min_quantum,
CLOCK_MIN_QUANTUM, this->defaults.clock_max_quantum); CLOCK_MIN_QUANTUM, d->clock_max_quantum);
this->defaults.clock_quantum = SPA_CLAMP(this->defaults.clock_quantum, d->clock_quantum = SPA_CLAMP(d->clock_quantum,
this->defaults.clock_min_quantum, this->defaults.clock_max_quantum); d->clock_min_quantum, d->clock_max_quantum);
} }
static int try_load_conf(struct pw_context *this, const char *conf_prefix, static int try_load_conf(struct pw_context *this, const char *conf_prefix,
@ -306,6 +307,7 @@ struct pw_context *pw_context_new(struct pw_loop *main_loop,
} }
fill_defaults(this); fill_defaults(this);
this->settings = this->defaults;
pr = pw_properties_copy(properties); pr = pw_properties_copy(properties);
if ((str = pw_properties_get(pr, "context.data-loop." PW_KEY_LIBRARY_NAME_SYSTEM))) if ((str = pw_properties_get(pr, "context.data-loop." PW_KEY_LIBRARY_NAME_SYSTEM)))
@ -953,10 +955,24 @@ static int collect_nodes(struct pw_context *context, struct pw_impl_node *driver
return 0; return 0;
} }
static inline void get_quantums(struct pw_context *context, uint32_t *def, uint32_t *min, uint32_t *max)
{
struct settings *s = &context->settings;
*def = s->clock_force_quantum == 0 ? s->clock_quantum : s->clock_force_quantum;
*min = s->clock_force_quantum == 0 ? s->clock_min_quantum : s->clock_force_quantum;
*max = s->clock_force_quantum == 0 ? s->clock_max_quantum : s->clock_force_quantum;
}
static inline void get_rate(struct pw_context *context, uint32_t *def)
{
struct settings *s = &context->settings;
*def = s->clock_force_rate == 0 ? s->clock_rate : s->clock_force_rate;
}
int pw_context_recalc_graph(struct pw_context *context, const char *reason) int pw_context_recalc_graph(struct pw_context *context, const char *reason)
{ {
struct impl *impl = SPA_CONTAINER_OF(context, struct impl, this); struct impl *impl = SPA_CONTAINER_OF(context, struct impl, this);
struct pw_impl_node *n, *s, *target, *fallback; struct pw_impl_node *n, *s, *target, *fallback;
uint32_t max_quantum, min_quantum, def_quantum, def_rate;
pw_log_info(NAME" %p: busy:%d reason:%s", context, impl->recalc, reason); pw_log_info(NAME" %p: busy:%d reason:%s", context, impl->recalc, reason);
@ -968,6 +984,9 @@ int pw_context_recalc_graph(struct pw_context *context, const char *reason)
again: again:
impl->recalc = true; impl->recalc = true;
get_quantums(context, &def_quantum, &min_quantum, &max_quantum);
get_rate(context, &def_rate);
/* start from all drivers and group all nodes that are linked /* start from all drivers and group all nodes that are linked
* to it. Some nodes are not (yet) linked to anything and they * to it. Some nodes are not (yet) linked to anything and they
* will end up 'unassigned' to a driver. Other nodes are drivers * will end up 'unassigned' to a driver. Other nodes are drivers
@ -1036,7 +1055,6 @@ again:
/* assign final quantum and set state for followers and drivers */ /* assign final quantum and set state for followers and drivers */
spa_list_for_each(n, &context->driver_list, driver_link) { spa_list_for_each(n, &context->driver_list, driver_link) {
bool running = false; bool running = false;
uint32_t max_quantum = context->defaults.clock_max_quantum;
uint32_t quantum = 0; uint32_t quantum = 0;
if (!n->driving || n->exported) if (!n->driving || n->exported)
@ -1057,12 +1075,11 @@ again:
running = !n->passive; running = !n->passive;
} }
if (quantum == 0) if (quantum == 0)
quantum = context->defaults.clock_quantum; quantum = def_quantum;
quantum = SPA_CLAMP(quantum, quantum = SPA_CLAMP(quantum, min_quantum, max_quantum);
context->defaults.clock_min_quantum,
max_quantum);
n->rt.position->clock.rate = SPA_FRACTION(1, def_rate);
if (n->rt.position && quantum != n->rt.position->clock.duration) { if (n->rt.position && quantum != n->rt.position->clock.duration) {
pw_log_info("(%s-%u) new quantum:%"PRIu64"->%u", pw_log_info("(%s-%u) new quantum:%"PRIu64"->%u",
n->name, n->info.id, n->name, n->info.id,

View file

@ -1048,8 +1048,8 @@ filter_new(struct pw_context *context, const char *name,
this->state = PW_FILTER_STATE_UNCONNECTED; this->state = PW_FILTER_STATE_UNCONNECTED;
impl->context = context; impl->context = context;
impl->allow_mlock = context->defaults.mem_allow_mlock; impl->allow_mlock = context->settings.mem_allow_mlock;
impl->warn_mlock = context->defaults.mem_warn_mlock; impl->warn_mlock = context->settings.mem_warn_mlock;
return impl; return impl;

View file

@ -879,16 +879,16 @@ static void check_properties(struct pw_impl_node *node)
uint32_t quantum_size; uint32_t quantum_size;
node->latency = SPA_FRACTION(num, denom); node->latency = SPA_FRACTION(num, denom);
quantum_size = (num * context->defaults.clock_rate / denom); quantum_size = (num * context->settings.clock_rate / denom);
if (context->defaults.clock_power_of_two_quantum) if (context->settings.clock_power_of_two_quantum)
quantum_size = flp2(quantum_size); quantum_size = flp2(quantum_size);
if (quantum_size != node->quantum_size) { if (quantum_size != node->quantum_size) {
pw_log_debug(NAME" %p: latency '%s' quantum %u/%u", pw_log_debug(NAME" %p: latency '%s' quantum %u/%u",
node, str, quantum_size, context->defaults.clock_rate); node, str, quantum_size, context->settings.clock_rate);
pw_log_info("(%s-%u) latency:%s ->quantum %u/%u", node->name, pw_log_info("(%s-%u) latency:%s ->quantum %u/%u", node->name,
node->info.id, str, quantum_size, node->info.id, str, quantum_size,
context->defaults.clock_rate); context->settings.clock_rate);
node->quantum_size = quantum_size; node->quantum_size = quantum_size;
recalc_reason = "quantum changed"; recalc_reason = "quantum changed";
} }
@ -900,16 +900,16 @@ static void check_properties(struct pw_impl_node *node)
uint32_t max_quantum_size; uint32_t max_quantum_size;
node->max_latency = SPA_FRACTION(num, denom); node->max_latency = SPA_FRACTION(num, denom);
max_quantum_size = (num * context->defaults.clock_rate / denom); max_quantum_size = (num * context->settings.clock_rate / denom);
if (context->defaults.clock_power_of_two_quantum) if (context->settings.clock_power_of_two_quantum)
max_quantum_size = flp2(max_quantum_size); max_quantum_size = flp2(max_quantum_size);
if (max_quantum_size != node->max_quantum_size) { if (max_quantum_size != node->max_quantum_size) {
pw_log_debug(NAME" %p: max latency '%s' quantum %u/%u", pw_log_debug(NAME" %p: max latency '%s' quantum %u/%u",
node, str, max_quantum_size, context->defaults.clock_rate); node, str, max_quantum_size, context->settings.clock_rate);
pw_log_info("(%s-%u) max latency:%s ->quantum %u/%u", node->name, pw_log_info("(%s-%u) max latency:%s ->quantum %u/%u", node->name,
node->info.id, str, max_quantum_size, node->info.id, str, max_quantum_size,
context->defaults.clock_rate); context->settings.clock_rate);
node->max_quantum_size = max_quantum_size; node->max_quantum_size = max_quantum_size;
recalc_reason = "max quantum changed"; recalc_reason = "max quantum changed";
} }
@ -1105,7 +1105,7 @@ static void reset_segment(struct spa_io_segment *seg)
static void reset_position(struct pw_impl_node *this, struct spa_io_position *pos) static void reset_position(struct pw_impl_node *this, struct spa_io_position *pos)
{ {
uint32_t i; uint32_t i;
struct defaults *def = &this->context->defaults; struct settings *def = &this->context->settings;
pos->clock.rate = SPA_FRACTION(1, def->clock_rate); pos->clock.rate = SPA_FRACTION(1, def->clock_rate);
pos->clock.duration = def->clock_quantum; pos->clock.duration = def->clock_quantum;

View file

@ -49,7 +49,11 @@ struct ucred {
#define spa_debug(...) pw_log_trace(__VA_ARGS__) #define spa_debug(...) pw_log_trace(__VA_ARGS__)
#endif #endif
struct defaults { #define CLOCK_MIN_QUANTUM 4u
#define CLOCK_MAX_QUANTUM 8192u
struct settings {
uint32_t log_level;
uint32_t clock_rate; uint32_t clock_rate;
uint32_t clock_quantum; uint32_t clock_quantum;
uint32_t clock_min_quantum; uint32_t clock_min_quantum;
@ -60,6 +64,8 @@ struct defaults {
unsigned int mem_warn_mlock:1; unsigned int mem_warn_mlock:1;
unsigned int mem_allow_mlock:1; unsigned int mem_allow_mlock:1;
unsigned int clock_power_of_two_quantum:1; unsigned int clock_power_of_two_quantum:1;
uint32_t clock_force_rate;
uint32_t clock_force_quantum;
}; };
struct ratelimit { struct ratelimit {
@ -378,7 +384,8 @@ struct pw_context {
struct pw_properties *conf; /**< configuration of the context */ struct pw_properties *conf; /**< configuration of the context */
struct pw_properties *properties; /**< properties of the context */ struct pw_properties *properties; /**< properties of the context */
struct defaults defaults; /**< default parameters */ struct settings defaults; /**< default parameters */
struct settings settings; /**< current parameters */
struct pw_mempool *pool; /**< global memory pool */ struct pw_mempool *pool; /**< global memory pool */

View file

@ -1295,8 +1295,8 @@ stream_new(struct pw_context *context, const char *name,
this->state = PW_STREAM_STATE_UNCONNECTED; this->state = PW_STREAM_STATE_UNCONNECTED;
impl->context = context; impl->context = context;
impl->allow_mlock = context->defaults.mem_allow_mlock; impl->allow_mlock = context->settings.mem_allow_mlock;
impl->warn_mlock = context->defaults.mem_warn_mlock; impl->warn_mlock = context->settings.mem_warn_mlock;
spa_hook_list_append(&impl->context->driver_listener_list, spa_hook_list_append(&impl->context->driver_listener_list,
&impl->context_listener, &impl->context_listener,