From 30047f232baeed445aa5e68ec12a9c9f6d228e67 Mon Sep 17 00:00:00 2001 From: Pauli Virtanen Date: Fri, 11 Jul 2025 15:11:38 +0300 Subject: [PATCH] bluez5: account for driver clock rate difference in rate matching The rate matching calculations are done in the system clock domain. If the driver ticks at a different rate, the correction factor needs to be adjusted by the rate_diff. This fixes ISO streams getting out of sync with each other when target delay changes. This happens because typically one of them is the driver and the other follower. Driver adjust clock rate, and follower does its own adjustment *on top of that* so it rate matches more or less at double speed. (The DLL of the follower to some degree corrects for this, but can't do that when hitting RATE_CTL_DIFF_MAX and moreover it acts with a delay.) --- spa/plugins/bluez5/media-sink.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/spa/plugins/bluez5/media-sink.c b/spa/plugins/bluez5/media-sink.c index 16dcd54fe..711393c23 100644 --- a/spa/plugins/bluez5/media-sink.c +++ b/spa/plugins/bluez5/media-sink.c @@ -678,6 +678,13 @@ static int setup_matching(struct impl *this) if (port->rate_match) { port->rate_match->rate = 1 / port->ratectl.corr; + /* We rate match in the system clock domain. If driver ticks at a + * different rate, we as follower must compensate. + */ + if (this->following && SPA_LIKELY(this->position && + this->position->clock.rate_diff)) + port->rate_match->rate /= this->position->clock.rate_diff; + SPA_FLAG_UPDATE(port->rate_match->flags, SPA_IO_RATE_MATCH_FLAG_ACTIVE, this->following); }