impl-node: disable async for driver nodes

Make it so that a driver node can never be scheduled async. It could
possibly make sense when the driver node is not currently driving the
graph but when it drives the graph it always needs to be sync. This
also simplifies the target activation because we can simply check the
async state and ignore if the node is driving or not.

Also make sure that we never make an async link with a driver output port.
This does not make sense because the driver node will always be
triggered sync first and before the async node so we can simply make
a sync link.

This fixes the modified (only generate 1 buffer) video-src -> video-play
case where the buffer never arrives in video-play because of the
useless async link.

Fixes #4092
This commit is contained in:
Wim Taymans 2024-07-03 13:31:24 +02:00
parent 586e116f3c
commit 59b9da9477
3 changed files with 8 additions and 8 deletions

View file

@ -1321,7 +1321,8 @@ struct pw_impl_link *pw_context_create_link(struct pw_context *context,
if (this->passive && str == NULL)
pw_properties_set(properties, PW_KEY_LINK_PASSIVE, "true");
impl->async = (output_node->async || input_node->async) &&
impl->async = !output_node->driver &&
(output_node->async || input_node->async) &&
SPA_FLAG_IS_SET(output->flags, PW_IMPL_PORT_FLAG_ASYNC) &&
SPA_FLAG_IS_SET(input->flags, PW_IMPL_PORT_FLAG_ASYNC);
@ -1375,8 +1376,9 @@ struct pw_impl_link *pw_context_create_link(struct pw_context *context,
this->name = spa_aprintf("%d.%d.%d -> %d.%d.%d",
output_node->info.id, output->port_id, this->rt.out_mix.port.port_id,
input_node->info.id, input->port_id, this->rt.in_mix.port.port_id);
pw_log_info("(%s) (%s) -> (%s) async:%04x:%04x:%d", this->name, output_node->name,
input_node->name, output->flags, input->flags, impl->async);
pw_log_info("(%s) (%s) -> (%s) async:%d:%04x:%04x:%d", this->name, output_node->name,
input_node->name, output_node->driving,
output->flags, input->flags, impl->async);
pw_impl_port_emit_link_added(output, this);
pw_impl_port_emit_link_added(input, this);

View file

@ -112,13 +112,12 @@ static inline void activate_target(struct pw_impl_node *node, struct pw_node_tar
{
struct pw_node_activation_state *state = &t->activation->state[0];
if (!t->active) {
if (!node->async || node->driving) {
if (!node->async) {
if (!node->exported) {
SPA_ATOMIC_INC(state->required);
SPA_ATOMIC_INC(state->pending);
}
}
t->active_driving = node->driving;
t->active = true;
pw_log_debug("%p: target state:%p id:%d pending:%d/%d %d:%d:%d",
node, state, t->id, state->pending, state->required,
@ -130,7 +129,7 @@ static inline void deactivate_target(struct pw_impl_node *node, struct pw_node_t
{
if (t->active) {
struct pw_node_activation_state *state = &t->activation->state[0];
if (!node->async || t->active_driving) {
if (!node->async) {
/* the driver copies the required to the pending state
* so first try to resume the node and then decrement the
* required state. This way we either resume with the old value
@ -141,7 +140,6 @@ static inline void deactivate_target(struct pw_impl_node *node, struct pw_node_t
SPA_ATOMIC_DEC(state->required);
}
t->active = false;
t->active_driving = false;
pw_log_debug("%p: target state:%p id:%d pending:%d/%d %d:%d:%d trigger:%"PRIu64,
node, state, t->id, state->pending, state->required,
node->async, node->driving, node->exported, trigger);
@ -1202,6 +1200,7 @@ static void check_properties(struct pw_impl_node *node)
recalc_reason = "transport changed";
}
async = pw_properties_get_bool(node->properties, PW_KEY_NODE_ASYNC, false);
async &= !node->driver;
if (async != node->async) {
pw_log_info("%p: async %d -> %d", node, node->async, async);
node->async = async;

View file

@ -541,7 +541,6 @@ struct pw_node_target {
int fd;
void (*trigger)(struct pw_node_target *t, uint64_t nsec);
unsigned int active:1;
unsigned int active_driving:1;
unsigned int added:1;
};