mirror of https://github.com/mpv-player/mpv
audio/out/pull: detect and log underflows
Mostly for debugging, I guess.
This commit is contained in:
parent
0af561953a
commit
c5a82f729b
|
@ -55,6 +55,13 @@ struct ao_pull_state {
|
||||||
// AO_STATE_*
|
// AO_STATE_*
|
||||||
atomic_int state;
|
atomic_int state;
|
||||||
|
|
||||||
|
// Set when the buffer is intentionally not fed anymore in PLAY state.
|
||||||
|
atomic_bool draining;
|
||||||
|
|
||||||
|
// Set by the audio thread when an underflow was detected.
|
||||||
|
// It adds the number of samples.
|
||||||
|
atomic_int underflow;
|
||||||
|
|
||||||
// Device delay of the last written sample, in realtime.
|
// Device delay of the last written sample, in realtime.
|
||||||
atomic_llong end_time_us;
|
atomic_llong end_time_us;
|
||||||
};
|
};
|
||||||
|
@ -100,11 +107,20 @@ static int play(struct ao *ao, void **data, int samples, int flags)
|
||||||
|
|
||||||
int state = atomic_load(&p->state);
|
int state = atomic_load(&p->state);
|
||||||
if (!IS_PLAYING(state)) {
|
if (!IS_PLAYING(state)) {
|
||||||
|
atomic_store(&p->draining, false);
|
||||||
|
atomic_store(&p->underflow, 0);
|
||||||
set_state(ao, AO_STATE_PLAY);
|
set_state(ao, AO_STATE_PLAY);
|
||||||
if (!ao->stream_silence)
|
if (!ao->stream_silence)
|
||||||
ao->driver->resume(ao);
|
ao->driver->resume(ao);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool draining = write_samples == samples && (flags & AOPLAY_FINAL_CHUNK);
|
||||||
|
atomic_store(&p->draining, draining);
|
||||||
|
|
||||||
|
int underflow = atomic_fetch_and(&p->underflow, 0);
|
||||||
|
if (underflow)
|
||||||
|
MP_WARN(ao, "Audio underflow by %d samples.\n", underflow);
|
||||||
|
|
||||||
return write_samples;
|
return write_samples;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,6 +151,9 @@ int ao_read_data(struct ao *ao, void **data, int samples, int64_t out_time_us)
|
||||||
int buffered_bytes = mp_ring_buffered(p->buffers[0]);
|
int buffered_bytes = mp_ring_buffered(p->buffers[0]);
|
||||||
bytes = MPMIN(buffered_bytes, full_bytes);
|
bytes = MPMIN(buffered_bytes, full_bytes);
|
||||||
|
|
||||||
|
if (buffered_bytes < bytes && !atomic_load(&p->draining))
|
||||||
|
atomic_fetch_add(&p->underflow, (bytes - buffered_bytes) / ao->sstride);
|
||||||
|
|
||||||
if (bytes > 0)
|
if (bytes > 0)
|
||||||
atomic_store(&p->end_time_us, out_time_us);
|
atomic_store(&p->end_time_us, out_time_us);
|
||||||
|
|
||||||
|
@ -221,6 +240,7 @@ static void drain(struct ao *ao)
|
||||||
struct ao_pull_state *p = ao->api_priv;
|
struct ao_pull_state *p = ao->api_priv;
|
||||||
int state = atomic_load(&p->state);
|
int state = atomic_load(&p->state);
|
||||||
if (IS_PLAYING(state)) {
|
if (IS_PLAYING(state)) {
|
||||||
|
atomic_store(&p->draining, true);
|
||||||
// Wait for lower bound.
|
// Wait for lower bound.
|
||||||
mp_sleep_us(mp_ring_buffered(p->buffers[0]) / (double)ao->bps * 1e6);
|
mp_sleep_us(mp_ring_buffered(p->buffers[0]) / (double)ao->bps * 1e6);
|
||||||
// And then poll for actual end. (Unfortunately, this code considers
|
// And then poll for actual end. (Unfortunately, this code considers
|
||||||
|
|
Loading…
Reference in New Issue