context: add some comments

This commit is contained in:
Wim Taymans 2022-04-14 10:16:20 +02:00
parent 2268d1838b
commit b0dcfa886d

View file

@ -1084,6 +1084,24 @@ static bool rates_contains(uint32_t *rates, uint32_t n_rates, uint32_t rate)
return false; return false;
} }
/* here we evaluate the complete state of the graph.
*
* It roughly operates in 3 stages:
*
* 1. go over all drivers and collect the nodes that need to be scheduled with the
* driver. This include all nodes that have an active link with the driver or
* with a node already scheduled with the driver.
*
* 2. go over all nodes that are not assigned to a driver. The ones that require
* a driver are moved to some random active driver found in step 1.
*
* 3. go over all drivers again, collect the quantum/rate of all followers, select
* the desired final value and activate the followers and then the driver.
*
* A complete graph evaluation is performed for each change that is made to the
* graph, such as making/destroting links, adding/removing nodes, property changes such
* as quantum/rate changes or metadata changes.
*/
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);
@ -1253,9 +1271,14 @@ again:
if (lock_rate || if (lock_rate ||
(!force_rate && (!force_rate &&
(n->info.state > PW_NODE_STATE_IDLE))) (n->info.state > PW_NODE_STATE_IDLE)))
/* when someone wants us to lock the rate of this driver or
* when the driver is busy and we don't need to force a rate,
* keep the current rate */
target_rate = current_rate; target_rate = current_rate;
else { else {
/* calculate desired rate */ /* Here we are allowed to change the rate of the driver.
* Start with the default rate. If the desired rate is
* allowed, switch to it */
target_rate = def_rate; target_rate = def_rate;
if (rate.denom != 0 && rate.num == 1) { if (rate.denom != 0 && rate.num == 1) {
if (rates_contains(rates, n_rates, rate.denom)) if (rates_contains(rates, n_rates, rate.denom))
@ -1264,6 +1287,7 @@ again:
} }
if (target_rate != current_rate) { if (target_rate != current_rate) {
/* we doing a rate switch */
pw_log_info("(%s-%u) state:%s new rate:%u->%u", pw_log_info("(%s-%u) state:%s new rate:%u->%u",
n->name, n->info.id, n->name, n->info.id,
pw_node_state_as_string(n->info.state), pw_node_state_as_string(n->info.state),
@ -1277,6 +1301,8 @@ again:
if (n->info.state >= PW_NODE_STATE_IDLE) if (n->info.state >= PW_NODE_STATE_IDLE)
suspend_driver(context, n); suspend_driver(context, n);
} }
/* we're setting the pending rate. This will become the new
* current rate in the next iteration of the graph. */
n->current_rate = SPA_FRACTION(1, target_rate); n->current_rate = SPA_FRACTION(1, target_rate);
n->current_pending = true; n->current_pending = true;
current_rate = target_rate; current_rate = target_rate;
@ -1285,6 +1311,7 @@ again:
} }
if (rate_quantum != 0 && current_rate != rate_quantum) { if (rate_quantum != 0 && current_rate != rate_quantum) {
/* the quantum values are scaled with the current rate */
def_quantum = def_quantum * current_rate / rate_quantum; def_quantum = def_quantum * current_rate / rate_quantum;
min_quantum = min_quantum * current_rate / rate_quantum; min_quantum = min_quantum * current_rate / rate_quantum;
max_quantum = max_quantum * current_rate / rate_quantum; max_quantum = max_quantum * current_rate / rate_quantum;
@ -1311,11 +1338,16 @@ again:
n->name, n->info.id, n->name, n->info.id,
n->current_quantum, n->current_quantum,
quantum); quantum);
/* this is the new pending quantum */
n->current_quantum = quantum; n->current_quantum = quantum;
n->current_pending = true; n->current_pending = true;
} }
if (n->info.state < PW_NODE_STATE_RUNNING && n->current_pending) { if (n->info.state < PW_NODE_STATE_RUNNING && n->current_pending) {
/* the driver node is not actually running and we have a
* panding change. Apply the change to the position now so
* that we have the right values when we change the node
* states of the driver and followers to RUNNING below */
n->rt.position->clock.duration = n->current_quantum; n->rt.position->clock.duration = n->current_quantum;
n->rt.position->clock.rate = n->current_rate; n->rt.position->clock.rate = n->current_rate;
n->current_pending = false; n->current_pending = false;
@ -1324,6 +1356,7 @@ again:
pw_log_debug("%p: driving %p running:%d passive:%d quantum:%u '%s'", pw_log_debug("%p: driving %p running:%d passive:%d quantum:%u '%s'",
context, n, running, n->passive, quantum, n->name); context, n, running, n->passive, quantum, n->name);
/* first change the node states of the followers to the new target */
spa_list_for_each(s, &n->follower_list, follower_link) { spa_list_for_each(s, &n->follower_list, follower_link) {
if (s == n) if (s == n)
continue; continue;
@ -1331,6 +1364,7 @@ again:
context, s, s->active, s->name); context, s, s->active, s->name);
ensure_state(s, running); ensure_state(s, running);
} }
/* now that all the followers are ready, start the driver */
ensure_state(n, running); ensure_state(n, running);
} }
impl->recalc = false; impl->recalc = false;