mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -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