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)
goto no_props;
client->allow_mlock = client->context.context->defaults.mem_allow_mlock;
client->warn_mlock = client->context.context->defaults.mem_warn_mlock;
client->allow_mlock = client->context.context->settings.mem_allow_mlock;
client->warn_mlock = client->context.context->settings.mem_warn_mlock;
if ((str = pw_context_get_conf_section(client->context.context,
"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->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)
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)
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);
}
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)
align = pw_properties_parse_int(str);

View file

@ -47,9 +47,6 @@
#define NAME "context"
#define CLOCK_MIN_QUANTUM 4u
#define CLOCK_MAX_QUANTUM 8192u
#define DEFAULT_CLOCK_RATE 48000u
#define DEFAULT_CLOCK_QUANTUM 1024u
#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)
{
struct pw_properties *p = this->properties;
this->defaults.clock_power_of_two_quantum = get_default_bool(p, "clock.power-of-two-quantum",
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);
struct settings *d = &this->defaults;
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);
this->defaults.clock_min_quantum = SPA_CLAMP(this->defaults.clock_min_quantum,
CLOCK_MIN_QUANTUM, this->defaults.clock_max_quantum);
this->defaults.clock_quantum = SPA_CLAMP(this->defaults.clock_quantum,
this->defaults.clock_min_quantum, this->defaults.clock_max_quantum);
d->clock_min_quantum = SPA_CLAMP(d->clock_min_quantum,
CLOCK_MIN_QUANTUM, d->clock_max_quantum);
d->clock_quantum = SPA_CLAMP(d->clock_quantum,
d->clock_min_quantum, d->clock_max_quantum);
}
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);
this->settings = this->defaults;
pr = pw_properties_copy(properties);
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;
}
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)
{
struct impl *impl = SPA_CONTAINER_OF(context, struct impl, this);
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);
@ -968,6 +984,9 @@ int pw_context_recalc_graph(struct pw_context *context, const char *reason)
again:
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
* to it. Some nodes are not (yet) linked to anything and they
* 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 */
spa_list_for_each(n, &context->driver_list, driver_link) {
bool running = false;
uint32_t max_quantum = context->defaults.clock_max_quantum;
uint32_t quantum = 0;
if (!n->driving || n->exported)
@ -1057,12 +1075,11 @@ again:
running = !n->passive;
}
if (quantum == 0)
quantum = context->defaults.clock_quantum;
quantum = def_quantum;
quantum = SPA_CLAMP(quantum,
context->defaults.clock_min_quantum,
max_quantum);
quantum = SPA_CLAMP(quantum, min_quantum, max_quantum);
n->rt.position->clock.rate = SPA_FRACTION(1, def_rate);
if (n->rt.position && quantum != n->rt.position->clock.duration) {
pw_log_info("(%s-%u) new quantum:%"PRIu64"->%u",
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;
impl->context = context;
impl->allow_mlock = context->defaults.mem_allow_mlock;
impl->warn_mlock = context->defaults.mem_warn_mlock;
impl->allow_mlock = context->settings.mem_allow_mlock;
impl->warn_mlock = context->settings.mem_warn_mlock;
return impl;

View file

@ -879,16 +879,16 @@ static void check_properties(struct pw_impl_node *node)
uint32_t quantum_size;
node->latency = SPA_FRACTION(num, denom);
quantum_size = (num * context->defaults.clock_rate / denom);
if (context->defaults.clock_power_of_two_quantum)
quantum_size = (num * context->settings.clock_rate / denom);
if (context->settings.clock_power_of_two_quantum)
quantum_size = flp2(quantum_size);
if (quantum_size != node->quantum_size) {
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,
node->info.id, str, quantum_size,
context->defaults.clock_rate);
context->settings.clock_rate);
node->quantum_size = quantum_size;
recalc_reason = "quantum changed";
}
@ -900,16 +900,16 @@ static void check_properties(struct pw_impl_node *node)
uint32_t max_quantum_size;
node->max_latency = SPA_FRACTION(num, denom);
max_quantum_size = (num * context->defaults.clock_rate / denom);
if (context->defaults.clock_power_of_two_quantum)
max_quantum_size = (num * context->settings.clock_rate / denom);
if (context->settings.clock_power_of_two_quantum)
max_quantum_size = flp2(max_quantum_size);
if (max_quantum_size != node->max_quantum_size) {
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,
node->info.id, str, max_quantum_size,
context->defaults.clock_rate);
context->settings.clock_rate);
node->max_quantum_size = max_quantum_size;
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)
{
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.duration = def->clock_quantum;

View file

@ -49,7 +49,11 @@ struct ucred {
#define spa_debug(...) pw_log_trace(__VA_ARGS__)
#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_quantum;
uint32_t clock_min_quantum;
@ -60,6 +64,8 @@ struct defaults {
unsigned int mem_warn_mlock:1;
unsigned int mem_allow_mlock:1;
unsigned int clock_power_of_two_quantum:1;
uint32_t clock_force_rate;
uint32_t clock_force_quantum;
};
struct ratelimit {
@ -378,7 +384,8 @@ struct pw_context {
struct pw_properties *conf; /**< configuration 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 */

View file

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