summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--audio/out/pull.c27
1 files changed, 18 insertions, 9 deletions
diff --git a/audio/out/pull.c b/audio/out/pull.c
index c658144a2d..ed85c4ee00 100644
--- a/audio/out/pull.c
+++ b/audio/out/pull.c
@@ -206,15 +206,6 @@ static void resume(struct ao *ao)
ao->driver->resume(ao);
}
-static void drain(struct ao *ao)
-{
- struct ao_pull_state *p = ao->api_priv;
- int state = atomic_load(&p->state);
- if (IS_PLAYING(state))
- mp_sleep_us(get_delay(ao) * 1000000);
- reset(ao);
-}
-
static bool get_eof(struct ao *ao)
{
struct ao_pull_state *p = ao->api_priv;
@@ -223,6 +214,24 @@ static bool get_eof(struct ao *ao)
return mp_ring_buffered(p->buffers[0]) == 0;
}
+static void drain(struct ao *ao)
+{
+ struct ao_pull_state *p = ao->api_priv;
+ int state = atomic_load(&p->state);
+ if (IS_PLAYING(state)) {
+ // Wait for lower bound.
+ mp_sleep_us(mp_ring_buffered(p->buffers[0]) / (double)ao->bps * 1e6);
+ // And then poll for actual end. (Unfortunately, this code considers
+ // audio APIs which do not want you to use mutexes in the audio
+ // callback, and an extra semaphore would require slightly more effort.)
+ // Limit to arbitrary ~250ms max. waiting for robustness.
+ int64_t max = mp_time_us() + 250000;
+ while (mp_time_us() < max && !get_eof(ao))
+ mp_sleep_us(1);
+ }
+ reset(ao);
+}
+
static void uninit(struct ao *ao)
{
ao->driver->uninit(ao);