summaryrefslogtreecommitdiffstats
path: root/audio
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2017-06-28 12:26:27 +0200
committerwm4 <wm4@nowhere>2017-06-28 13:18:59 +0200
commitc5a82f729bd09745488ef96fa7c76307c41c0073 (patch)
treeb4b14a1252934679c6d8acf59ba145adb08342a0 /audio
parent0af561953a2a4b10b23367dccbc0c22730d69999 (diff)
downloadmpv-c5a82f729bd09745488ef96fa7c76307c41c0073.tar.bz2
mpv-c5a82f729bd09745488ef96fa7c76307c41c0073.tar.xz
audio/out/pull: detect and log underflows
Mostly for debugging, I guess.
Diffstat (limited to 'audio')
-rw-r--r--audio/out/pull.c20
1 files changed, 20 insertions, 0 deletions
diff --git a/audio/out/pull.c b/audio/out/pull.c
index a656de6fdd..6da3825965 100644
--- a/audio/out/pull.c
+++ b/audio/out/pull.c
@@ -55,6 +55,13 @@ struct ao_pull_state {
// AO_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.
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);
if (!IS_PLAYING(state)) {
+ atomic_store(&p->draining, false);
+ atomic_store(&p->underflow, 0);
set_state(ao, AO_STATE_PLAY);
if (!ao->stream_silence)
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;
}
@@ -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]);
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)
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;
int state = atomic_load(&p->state);
if (IS_PLAYING(state)) {
+ atomic_store(&p->draining, true);
// 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