impl-node: rework resume after rate switch

We only need to resume the SUSPENDED node when it has !pause-on-idle.
So, set the need_resume flag when we suspend in that case.

Clear the flag in the next round and make sure we set the node to
running again. We don't need to clear any flags when the state change
completes anymore with this change.

This also fixes a case where strawberry would fail to configure the
correct sample rate. 44.1KHz would be used (the rate of the probe
stream) because the scheduler was thinking the node was still being
reconfigured because the reconfigure flag was only cleared when going
to the running state (an alsa sink has !pause_on_idle).

See #2929
This commit is contained in:
Wim Taymans 2023-10-09 17:46:38 +02:00
parent 2278dd1460
commit 4b940100b1
3 changed files with 24 additions and 16 deletions

View file

@ -1027,7 +1027,7 @@ static void reconfigure_driver(struct pw_context *context, struct pw_impl_node *
context, n, n->name);
if (n->info.state >= PW_NODE_STATE_IDLE)
n->reconfigure = true;
n->need_resume = !n->pause_on_idle;
pw_impl_node_set_state(n, PW_NODE_STATE_SUSPENDED);
}
@ -1309,7 +1309,7 @@ again:
uint32_t target_quantum, target_rate, current_rate, current_quantum;
uint64_t quantum_stamp = 0, rate_stamp = 0;
bool force_rate, force_quantum, restore_rate = false, restore_quantum = false;
bool do_reconfigure = false, was_target_pending;
bool do_reconfigure = false, need_resume, was_target_pending;
const uint32_t *node_rates;
uint32_t node_n_rates, node_def_rate;
uint32_t node_max_quantum, node_min_quantum, node_def_quantum, node_rate_quantum;
@ -1399,13 +1399,22 @@ again:
if (force_rate)
lock_rate = false;
if (n->reconfigure)
need_resume = n->need_resume;
if (need_resume) {
running = true;
n->need_resume = false;
}
current_rate = n->target_rate.denom;
if (!restore_rate &&
(lock_rate || n->reconfigure || !running ||
(!force_rate && (n->info.state > PW_NODE_STATE_IDLE))))
(lock_rate || need_resume || !running ||
(!force_rate && (n->info.state > PW_NODE_STATE_IDLE)))) {
pw_log_debug("%p: keep rate:1/%u restore:%u lock:%u resume:%u "
"running:%u force:%u state:%s", context,
current_rate, restore_rate, lock_rate, need_resume,
running, force_rate,
pw_node_state_as_string(n->info.state));
/* when we don't need to restore or rate and
* when someone wants us to lock the rate of this driver or
* when we are in the process of reconfiguring the driver or
@ -1413,6 +1422,7 @@ again:
* when the driver is busy and we don't need to force a rate,
* keep the current rate */
target_rate = current_rate;
}
else {
/* Here we are allowed to change the rate of the driver.
* Start with the default rate. If the desired rate is
@ -1464,9 +1474,15 @@ again:
current_quantum = n->target_quantum;
if (!restore_quantum &&
(lock_quantum || n->reconfigure || !running ||
(!force_quantum && (n->info.state > PW_NODE_STATE_IDLE))))
(lock_quantum || need_resume || !running ||
(!force_quantum && (n->info.state > PW_NODE_STATE_IDLE)))) {
pw_log_debug("%p: keep quantum:%u restore:%u lock:%u resume:%u "
"running:%u force:%u state:%s", context,
current_quantum, restore_quantum, lock_quantum, need_resume,
running, force_quantum,
pw_node_state_as_string(n->info.state));
target_quantum = current_quantum;
}
else {
target_quantum = node_def_quantum;
if (latency.denom != 0)

View file

@ -418,14 +418,6 @@ static void node_update_state(struct pw_impl_node *node, enum pw_node_state stat
spa_list_for_each(resource, &node->global->resource_list, link)
pw_resource_error(resource, res, error);
}
if (node->reconfigure) {
if (state == PW_NODE_STATE_SUSPENDED &&
node->pause_on_idle) {
node->reconfigure = false;
}
if (state == PW_NODE_STATE_RUNNING)
node->reconfigure = false;
}
if (old == PW_NODE_STATE_RUNNING &&
state == PW_NODE_STATE_IDLE &&
node->suspend_on_idle) {

View file

@ -671,7 +671,7 @@ struct pw_impl_node {
unsigned int added:1; /**< the node was add to graph */
unsigned int pause_on_idle:1; /**< Pause processing when IDLE */
unsigned int suspend_on_idle:1;
unsigned int reconfigure:1;
unsigned int need_resume:1;
unsigned int forced_rate:1;
unsigned int forced_quantum:1;
unsigned int trigger:1; /**< has the TRIGGER property and needs an extra