impl-node: keep separate elapsed time

Don't directly update the offset when not running. The running time
is position - offset and stays constant when not running.

Instead keep an extra elapsed variable that is updated when the state
is running. The offset is then always posision - elapsed. This is more
reliable and can compensate for jumps in the position timestamps.

Fixes #3544
See #3189
This commit is contained in:
Wim Taymans 2023-10-05 16:08:01 +02:00
parent 2c5cdb57e5
commit a18d495b59
2 changed files with 6 additions and 2 deletions

View file

@ -1322,6 +1322,7 @@ static void reset_position(struct pw_impl_node *this, struct spa_io_position *po
this->target_rate = SPA_FRACTION(1, rate);
this->target_quantum = quantum;
this->elapsed = 0;
pos->clock.rate = pos->clock.target_rate = this->target_rate;
pos->clock.duration = pos->clock.target_duration = this->target_quantum;
@ -1745,8 +1746,10 @@ static inline void update_position(struct pw_impl_node *node, int all_ready, uin
if (all_ready)
a->position.state = SPA_IO_POSITION_STATE_RUNNING;
}
if (SPA_LIKELY(a->position.state != SPA_IO_POSITION_STATE_RUNNING))
a->position.offset += a->position.clock.duration;
if (SPA_LIKELY(a->position.state == SPA_IO_POSITION_STATE_RUNNING))
node->elapsed += a->position.clock.duration;
a->position.offset = a->position.clock.position - node->elapsed;
}
/* Called from the data-loop and it is the starting point for driver nodes.

View file

@ -732,6 +732,7 @@ struct pw_impl_node {
uint64_t target_quantum;
uint64_t driver_start;
uint64_t elapsed; /* elapsed time in playing */
void *user_data; /**< extra user data */
};