mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-02 09:01:50 -05:00
impl-node: rework quantum and max_quantum handling
Rework the quantum and max_quantum handling. Work directly with the latency fractions and calculate the final quantum size until we know the samplerate.
This commit is contained in:
parent
7bec96640c
commit
6acf72dc30
3 changed files with 53 additions and 45 deletions
|
|
@ -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);
|
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)
|
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);
|
||||||
|
|
@ -1113,7 +1129,9 @@ 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, lock_quantum = false;
|
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)
|
if (!n->driving || n->exported)
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -1123,22 +1141,33 @@ again:
|
||||||
|
|
||||||
lock_quantum |= s->lock_quantum;
|
lock_quantum |= s->lock_quantum;
|
||||||
|
|
||||||
if (s->quantum_size > 0) {
|
if (latency.denom == 0 ||
|
||||||
if (quantum == 0 || s->quantum_size < quantum)
|
(s->latency.denom > 0 &&
|
||||||
quantum = s->quantum_size;
|
fraction_compare(&s->latency, &latency) < 0))
|
||||||
}
|
latency = s->latency;
|
||||||
if (s->max_quantum_size > 0) {
|
|
||||||
if (s->max_quantum_size < max_quantum)
|
if (max_latency.denom == 0 ||
|
||||||
max_quantum = s->max_quantum_size;
|
(s->max_latency.denom > 0 &&
|
||||||
}
|
fraction_compare(&s->max_latency, &max_latency) < 0))
|
||||||
|
max_latency = s->max_latency;
|
||||||
|
|
||||||
if (s->active)
|
if (s->active)
|
||||||
running = !n->passive;
|
running = !n->passive;
|
||||||
}
|
}
|
||||||
if (quantum == 0)
|
if (max_latency.denom != 0) {
|
||||||
quantum = def_quantum;
|
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);
|
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) {
|
if (def_rate != n->rt.position->clock.rate.denom) {
|
||||||
pw_log_info("(%s-%u) new rate:%u->%u",
|
pw_log_info("(%s-%u) new rate:%u->%u",
|
||||||
n->name, n->info.id,
|
n->name, n->info.id,
|
||||||
|
|
|
||||||
|
|
@ -817,6 +817,7 @@ static void check_properties(struct pw_impl_node *node)
|
||||||
struct impl *impl = SPA_CONTAINER_OF(node, struct impl, this);
|
struct impl *impl = SPA_CONTAINER_OF(node, struct impl, this);
|
||||||
struct pw_context *context = node->context;
|
struct pw_context *context = node->context;
|
||||||
const char *str, *recalc_reason = NULL;
|
const char *str, *recalc_reason = NULL;
|
||||||
|
struct spa_fraction frac;
|
||||||
bool driver;
|
bool driver;
|
||||||
|
|
||||||
if ((str = pw_properties_get(node->properties, PW_KEY_PRIORITY_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;
|
node->want_driver = true;
|
||||||
|
|
||||||
if ((str = pw_properties_get(node->properties, PW_KEY_NODE_LATENCY))) {
|
if ((str = pw_properties_get(node->properties, PW_KEY_NODE_LATENCY))) {
|
||||||
uint32_t num, denom;
|
if (sscanf(str, "%u/%u", &frac.num, &frac.denom) == 2 && frac.denom != 0) {
|
||||||
if (sscanf(str, "%u/%u", &num, &denom) == 2 && denom != 0) {
|
if (node->latency.num != frac.num || node->latency.denom != frac.denom) {
|
||||||
uint32_t quantum_size;
|
pw_log_info("(%s-%u) latency:%u/%u -> %u/%u", node->name,
|
||||||
|
node->info.id, node->latency.num,
|
||||||
node->latency = SPA_FRACTION(num, denom);
|
node->latency.denom, frac.num, frac.denom);
|
||||||
quantum_size = (num * context->settings.clock_rate / denom);
|
node->latency = frac;
|
||||||
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;
|
|
||||||
recalc_reason = "quantum changed";
|
recalc_reason = "quantum changed";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((str = pw_properties_get(node->properties, PW_KEY_NODE_MAX_LATENCY))) {
|
if ((str = pw_properties_get(node->properties, PW_KEY_NODE_MAX_LATENCY))) {
|
||||||
uint32_t num, denom;
|
if (sscanf(str, "%u/%u", &frac.num, &frac.denom) == 2 && frac.denom != 0) {
|
||||||
if (sscanf(str, "%u/%u", &num, &denom) == 2 && denom != 0) {
|
if (node->max_latency.num != frac.num || node->max_latency.denom != frac.denom) {
|
||||||
uint32_t max_quantum_size;
|
pw_log_info("(%s-%u) max-latency:%u/%u -> %u/%u", node->name,
|
||||||
|
node->info.id, node->max_latency.num,
|
||||||
node->max_latency = SPA_FRACTION(num, denom);
|
node->max_latency.denom, frac.num, frac.denom);
|
||||||
max_quantum_size = (num * context->settings.clock_rate / denom);
|
node->max_latency = frac;
|
||||||
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;
|
|
||||||
recalc_reason = "max quantum changed";
|
recalc_reason = "max quantum changed";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -701,9 +701,7 @@ struct pw_impl_node {
|
||||||
struct pw_loop *data_loop; /**< the data loop for this node */
|
struct pw_loop *data_loop; /**< the data loop for this node */
|
||||||
|
|
||||||
struct spa_fraction latency; /**< requested latency */
|
struct spa_fraction latency; /**< requested latency */
|
||||||
uint32_t quantum_size; /**< desired quantum */
|
|
||||||
struct spa_fraction max_latency; /**< maximum latency */
|
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 spa_source source; /**< source to remotely trigger this node */
|
||||||
struct pw_memblock *activation;
|
struct pw_memblock *activation;
|
||||||
struct {
|
struct {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue