mirror of https://github.com/mpv-player/mpv
audio/out/pull: avoid dropping some audio when draining
If the audio API takes a while for starting the audio callback, the current heuristic can be off. In particular, with very short files, it can happen that the audio callback is not called before playback is stopped, so no audio is output at all. Change draining so that it essentially waits for the ringbuffer to empty. The assumption is that once the audio API has read the data via the callback, it will always output it, even if the audio API is stopped right after the callback has returned.
This commit is contained in:
parent
a2b1c6d3f6
commit
211088943c
|
@ -206,15 +206,6 @@ static void resume(struct ao *ao)
|
||||||
ao->driver->resume(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)
|
static bool get_eof(struct ao *ao)
|
||||||
{
|
{
|
||||||
struct ao_pull_state *p = ao->api_priv;
|
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;
|
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)
|
static void uninit(struct ao *ao)
|
||||||
{
|
{
|
||||||
ao->driver->uninit(ao);
|
ao->driver->uninit(ao);
|
||||||
|
|
Loading…
Reference in New Issue