mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-10-29 05:40:27 -04:00
impl-node: improve xrun handling
To check if the driver was not completed, check the pending state instead of the status. This is more correct and we can do this a little smarter by swapping the current state with 0 atomically. When we detect a non-zero pending state, wake up the driver node. Because we atomically swapped 0, we are the only ones doing this and it will make the node process whatever was in the input ports instead of underrunning. Running 2 apps outputting to a sink and pausing one will still play the output of the other one, this way. See #3509 Fixes #3937
This commit is contained in:
parent
208a343d9f
commit
a01a33aa75
2 changed files with 12 additions and 4 deletions
|
|
@ -1209,6 +1209,12 @@ static inline uint64_t get_time_ns(struct spa_system *system)
|
|||
return SPA_TIMESPEC_TO_NSEC(&ts);
|
||||
}
|
||||
|
||||
static inline void wake_target(struct pw_node_target *t)
|
||||
{
|
||||
if (SPA_UNLIKELY(spa_system_eventfd_write(t->system, t->fd, 1) < 0))
|
||||
pw_log_warn("%p: write failed %m", t->node);
|
||||
}
|
||||
|
||||
/* called from data-loop decrement the dependency counter of the target and when
|
||||
* there are no more dependencies, trigger the node. */
|
||||
static inline void trigger_target(struct pw_node_target *t, uint64_t nsec)
|
||||
|
|
@ -1222,8 +1228,7 @@ static inline void trigger_target(struct pw_node_target *t, uint64_t nsec)
|
|||
if (pw_node_activation_state_dec(state)) {
|
||||
a->status = PW_NODE_ACTIVATION_TRIGGERED;
|
||||
a->signal_time = nsec;
|
||||
if (SPA_UNLIKELY(spa_system_eventfd_write(t->system, t->fd, 1) < 0))
|
||||
pw_log_warn("%p: write failed %m", t->node);
|
||||
wake_target(t);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1838,12 +1843,14 @@ static int node_ready(void *data, int status)
|
|||
int sync_type, all_ready, update_sync, target_sync;
|
||||
uint32_t owner[2], reposition_owner;
|
||||
uint64_t min_timeout = UINT64_MAX;
|
||||
int32_t pending;
|
||||
|
||||
if (SPA_UNLIKELY(a->status != PW_NODE_ACTIVATION_FINISHED)) {
|
||||
if (SPA_UNLIKELY((pending = pw_node_activation_state_xchg(state)) != 0)) {
|
||||
pw_log_debug("(%s-%u) graph not finished: state:%p quantum:%"PRIu64
|
||||
" pending %d/%d", node->name, node->info.id,
|
||||
state, a->position.clock.duration,
|
||||
state->pending, state->required);
|
||||
pending, state->required);
|
||||
wake_target(&node->rt.target);
|
||||
check_states(node, nsec);
|
||||
pw_impl_node_rt_emit_incomplete(node);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -526,6 +526,7 @@ static inline void pw_node_activation_state_reset(struct pw_node_activation_stat
|
|||
}
|
||||
|
||||
#define pw_node_activation_state_dec(s) (SPA_ATOMIC_DEC(s->pending) == 0)
|
||||
#define pw_node_activation_state_xchg(s) SPA_ATOMIC_XCHG(s->pending, 0)
|
||||
|
||||
struct pw_node_target {
|
||||
struct spa_list link;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue