diff --git a/src/pipewire/context.c b/src/pipewire/context.c index 2f72e408c..eeb863f5a 100644 --- a/src/pipewire/context.c +++ b/src/pipewire/context.c @@ -1019,6 +1019,22 @@ static void suspend_driver(struct pw_context *context, struct pw_impl_node *n) pw_impl_node_set_state(n, PW_NODE_STATE_SUSPENDED); } +/* find smaller power of 2 */ +static uint32_t flp2(uint32_t x) +{ + x = x | (x >> 1); + x = x | (x >> 2); + x = x | (x >> 4); + x = x | (x >> 8); + x = x | (x >> 16); + return x - (x >> 1); +} + +static int64_t fraction_compare(const struct spa_fraction *a, const struct spa_fraction *b) +{ + return (int64_t)(a->num * b->denom) - (int64_t)(b->num * a->denom); +} + int pw_context_recalc_graph(struct pw_context *context, const char *reason) { struct impl *impl = SPA_CONTAINER_OF(context, struct impl, this); @@ -1113,7 +1129,9 @@ again: /* assign final quantum and set state for followers and drivers */ spa_list_for_each(n, &context->driver_list, driver_link) { bool running = false, lock_quantum = false; - uint32_t quantum = 0; + struct spa_fraction latency = SPA_FRACTION(0, 0); + struct spa_fraction max_latency = SPA_FRACTION(0, 0); + uint32_t quantum; if (!n->driving || n->exported) continue; @@ -1123,22 +1141,33 @@ again: lock_quantum |= s->lock_quantum; - if (s->quantum_size > 0) { - if (quantum == 0 || s->quantum_size < quantum) - quantum = s->quantum_size; - } - if (s->max_quantum_size > 0) { - if (s->max_quantum_size < max_quantum) - max_quantum = s->max_quantum_size; - } + if (latency.denom == 0 || + (s->latency.denom > 0 && + fraction_compare(&s->latency, &latency) < 0)) + latency = s->latency; + + if (max_latency.denom == 0 || + (s->max_latency.denom > 0 && + fraction_compare(&s->max_latency, &max_latency) < 0)) + max_latency = s->max_latency; + if (s->active) running = !n->passive; } - if (quantum == 0) - quantum = def_quantum; + if (max_latency.denom != 0) { + uint32_t tmp = (max_latency.num * def_rate / max_latency.denom); + if (tmp < max_quantum) + max_quantum = tmp; + } + quantum = def_quantum; + if (latency.denom != 0) + quantum = (latency.num * def_rate / latency.denom); quantum = SPA_CLAMP(quantum, min_quantum, max_quantum); + if (context->settings.clock_power_of_two_quantum) + quantum = flp2(quantum); + if (def_rate != n->rt.position->clock.rate.denom) { pw_log_info("(%s-%u) new rate:%u->%u", n->name, n->info.id, diff --git a/src/pipewire/impl-node.c b/src/pipewire/impl-node.c index ba1b0d6cb..57d78c64b 100644 --- a/src/pipewire/impl-node.c +++ b/src/pipewire/impl-node.c @@ -817,6 +817,7 @@ static void check_properties(struct pw_impl_node *node) struct impl *impl = SPA_CONTAINER_OF(node, struct impl, this); struct pw_context *context = node->context; const char *str, *recalc_reason = NULL; + struct spa_fraction frac; bool driver; if ((str = pw_properties_get(node->properties, PW_KEY_PRIORITY_DRIVER))) { @@ -873,43 +874,23 @@ static void check_properties(struct pw_impl_node *node) node->want_driver = true; if ((str = pw_properties_get(node->properties, PW_KEY_NODE_LATENCY))) { - uint32_t num, denom; - if (sscanf(str, "%u/%u", &num, &denom) == 2 && denom != 0) { - uint32_t quantum_size; - - node->latency = SPA_FRACTION(num, denom); - 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->settings.clock_rate); - pw_log_info("(%s-%u) latency:%s ->quantum %u/%u", node->name, - node->info.id, str, quantum_size, - context->settings.clock_rate); - node->quantum_size = quantum_size; + if (sscanf(str, "%u/%u", &frac.num, &frac.denom) == 2 && frac.denom != 0) { + if (node->latency.num != frac.num || node->latency.denom != frac.denom) { + pw_log_info("(%s-%u) latency:%u/%u -> %u/%u", node->name, + node->info.id, node->latency.num, + node->latency.denom, frac.num, frac.denom); + node->latency = frac; recalc_reason = "quantum changed"; } } } if ((str = pw_properties_get(node->properties, PW_KEY_NODE_MAX_LATENCY))) { - uint32_t num, denom; - if (sscanf(str, "%u/%u", &num, &denom) == 2 && denom != 0) { - uint32_t max_quantum_size; - - node->max_latency = SPA_FRACTION(num, denom); - 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->settings.clock_rate); - pw_log_info("(%s-%u) max latency:%s ->quantum %u/%u", node->name, - node->info.id, str, max_quantum_size, - context->settings.clock_rate); - node->max_quantum_size = max_quantum_size; + if (sscanf(str, "%u/%u", &frac.num, &frac.denom) == 2 && frac.denom != 0) { + if (node->max_latency.num != frac.num || node->max_latency.denom != frac.denom) { + pw_log_info("(%s-%u) max-latency:%u/%u -> %u/%u", node->name, + node->info.id, node->max_latency.num, + node->max_latency.denom, frac.num, frac.denom); + node->max_latency = frac; recalc_reason = "max quantum changed"; } } diff --git a/src/pipewire/private.h b/src/pipewire/private.h index 6fb195012..162894482 100644 --- a/src/pipewire/private.h +++ b/src/pipewire/private.h @@ -701,9 +701,7 @@ struct pw_impl_node { struct pw_loop *data_loop; /**< the data loop for this node */ struct spa_fraction latency; /**< requested latency */ - uint32_t quantum_size; /**< desired quantum */ struct spa_fraction max_latency; /**< maximum latency */ - uint32_t max_quantum_size; /**< max supported quantum */ struct spa_source source; /**< source to remotely trigger this node */ struct pw_memblock *activation; struct {