From 396756e58ab37d262ca31fece673329d224eca0a Mon Sep 17 00:00:00 2001 From: wm4 Date: Wed, 17 Sep 2014 00:20:20 +0200 Subject: ao_oss: prevent hang when unpausing after device was lost Pausing/unpausing while the audio device can't be reopened, and then unpausing again when the device is finally reopened, can hang the player for a while. This happens because p->prepause_samples grows without bounds each time the player is unpaused while the device is lost. On unpause, ao_oss plays prepause_samples of silence to compensate for A/V timing issues due to the partially lost buffer (we can't pause the device at an arbitrary sample position, and the current period will be lost). This in turn will make the player appear to be frozen if too much audio is queued. (Normally, play() must never block, but here it happens because more data is written than get_space() reports. A better implementation would never let prepause_samples grow larger than the period size.) The unbounded growth happens because get_space() always returns that the device can be written while the device is lost. So limit it to 200ms. (A better implementation would limit it to the period size.) Also see #1080. --- audio/out/ao_oss.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'audio') diff --git a/audio/out/ao_oss.c b/audio/out/ao_oss.c index 9ed10cf6c1..b78f244a7b 100644 --- a/audio/out/ao_oss.c +++ b/audio/out/ao_oss.c @@ -579,6 +579,9 @@ static int get_space(struct ao *ao) return zz.fragments * zz.fragsize / ao->sstride; } + if (p->audio_fd < 0 && p->device_failed && get_delay(ao) > 0.2) + return 0; + if (p->audio_fd < 0 || device_writable(ao) > 0) return p->outburst / ao->sstride; -- cgit v1.2.3