bluez5: iso-io: more accurate resync after overrun

Take active rate correction properly into account when dropping data on
overrun resync.

Drop data only for the currently processed stream, after data has been
consumed from it. Make sure the rate correction factor is updated after
this for the next cycle of the stream.

Also fix buffer fill level calculation: the fill level interpolation
should use node rate corr, not clock rate diff, since the calculations
are done in system clock domain. Fix same issue in fractional delay
calculation, and take no resampler prefill into account.

Later, we maybe need some more resampler APIs to avoid such details
leaking in.

Previously, stream could have its old rate correction locked in, and its
fill level would then end up off the target on the next cycle.
This commit is contained in:
Pauli Virtanen 2026-01-01 16:17:40 +02:00 committed by Wim Taymans
parent b535534611
commit 11389d101a
3 changed files with 86 additions and 43 deletions

View file

@ -888,6 +888,15 @@ static void media_on_timeout(struct spa_source *source)
this->clock->next_nsec = this->next_time;
}
/* Set next position also here in case impl_node_process() fails to be scheduled */
if (this->transport_started)
spa_bt_decode_buffer_set_next(&port->buffer,
this->position ? this->position->clock.next_nsec : 0,
this->resampling ? this->port.rate_match->delay : 0,
this->resampling ? this->port.rate_match->delay_frac : 0,
this->resampling && this->matching ? port->rate_match->rate : 1.0,
true);
spa_node_call_ready(&this->callbacks, SPA_STATUS_HAVE_DATA);
set_timeout(this, this->next_time);
@ -1831,8 +1840,6 @@ static void process_buffering(struct impl *this)
spa_bt_decode_buffer_recover(&port->buffer);
}
setup_matching(this);
/* copy data to buffers */
if (!spa_list_is_empty(&port->free)) {
struct buffer *buffer;
@ -1883,8 +1890,13 @@ static void process_buffering(struct impl *this)
if (this->transport->iso_io && this->position && !this->initial_buffering)
spa_bt_iso_io_check_rx_sync(this->transport->iso_io, this->position->clock.position);
if (!port->buffer.buffering)
setup_matching(this);
if (!port->buffer.buffering) {
if (this->initial_buffering && this->transport->iso_io)
this->transport->iso_io->need_resync = true;
this->initial_buffering = false;
}
if (this->update_delay_event) {
int32_t target = spa_bt_decode_buffer_get_target_latency(&port->buffer);
@ -1987,10 +1999,10 @@ static int impl_node_process(void *object)
/* Update decode buffer vs. next wakeup timing */
spa_bt_decode_buffer_set_next(&port->buffer,
this->position ? this->position->clock.rate_diff : 1.0,
this->position ? this->position->clock.next_nsec : 0,
this->resampling ? this->port.rate_match->delay : 0,
this->resampling ? this->port.rate_match->delay_frac : 0,
this->resampling && this->matching ? port->rate_match->rate : 1.0,
this->following);
return ret;