ao_wasapi: fix retry budget on DEVICE_INVALIDATED

The retry path in wasapi_thread_init() used MP_TIME_US_TO_NS, giving a
total budget of ~15 us before MP_FATAL killed the audio thread. The
resulting log line "Retrying in 1000 ns" makes the unit confusion
obvious.

In practice AUDCLNT_E_DEVICE_INVALIDATED is most often hit right after
the system resumes from sleep, or when the default endpoint changes,
where the audio endpoint typically needs hundreds of milliseconds to
come back. The current budget never covers that window, so the first
playback after wake-up permanently fell back to "no audio" until the
user manually restarted playback.

Switch the retry schedule to milliseconds: start at 1 ms (~one Windows
timer tick, effectively an immediate yield), multiply by 10 each
iteration, and cap at 1 s -- i.e. 1/10/100/1000 ms, 4 retries, ~1.1 s
total. Use MP_TIME_NS_TO_MS for the warning so the unit in the log
matches reality.
This commit is contained in:
Richasy authored and Kacper Michajłow committed 2026-05-01 05:01:00 +02:00
1 parent 2f58ee36ce
commit 986dd6387d
1 file changed
+4 -4
+4 -4
View File
@@ -1013,7 +1013,7 @@ bool wasapi_thread_init(struct ao *ao)
{
struct wasapi_state *state = ao->priv;
MP_DBG(ao, "Init wasapi thread\n");
int64_t retry_wait = MP_TIME_US_TO_NS(1);
int64_t retry_wait = MP_TIME_MS_TO_NS(1);
bool align_hack = false;
HRESULT hr;
@@ -1096,14 +1096,14 @@ retry:
goto retry;
case AUDCLNT_E_DEVICE_IN_USE:
case AUDCLNT_E_DEVICE_INVALIDATED:
if (retry_wait > MP_TIME_US_TO_NS(8)) {
if (retry_wait > MP_TIME_MS_TO_NS(1000)) {
MP_FATAL(ao, "Bad device retry failed\n");
return false;
}
wasapi_thread_uninit(ao);
MP_WARN(ao, "Retrying in %"PRId64" ns\n", retry_wait);
MP_WARN(ao, "Retrying in %.0f ms\n", MP_TIME_NS_TO_MS(retry_wait));
mp_sleep_ns(retry_wait);
retry_wait *= 2;
retry_wait *= 10;
goto retry;
}
return SUCCEEDED(hr);