summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--audio/out/ao.c14
-rw-r--r--audio/out/ao.h2
-rw-r--r--audio/out/internal.h8
-rw-r--r--player/audio.c2
4 files changed, 25 insertions, 1 deletions
diff --git a/audio/out/ao.c b/audio/out/ao.c
index e7af02276f..817aa29399 100644
--- a/audio/out/ao.c
+++ b/audio/out/ao.c
@@ -402,6 +402,7 @@ void ao_reset(struct ao *ao)
{
if (ao->api->reset)
ao->api->reset(ao);
+ atomic_fetch_and(&ao->events_, ~(unsigned int)AO_EVENT_UNDERRUN);
}
// Pause playback. Keep the current buffer. ao_get_delay() must return the
@@ -457,6 +458,14 @@ void ao_hotplug_event(struct ao *ao)
ao_add_events(ao, AO_EVENT_HOTPLUG);
}
+void ao_underrun_event(struct ao *ao)
+{
+ // Racy check, but it's just for the message.
+ if (!(atomic_load(&ao->events_) & AO_EVENT_UNDERRUN))
+ MP_WARN(ao, "Device underrun detected.\n");
+ ao_add_events(ao, AO_EVENT_UNDERRUN);
+}
+
bool ao_chmap_sel_adjust(struct ao *ao, const struct mp_chmap_sel *s,
struct mp_chmap *map)
{
@@ -517,6 +526,11 @@ const char *ao_get_description(struct ao *ao)
return ao->driver->description;
}
+bool ao_get_reports_underruns(struct ao *ao)
+{
+ return ao->driver->reports_underruns;
+}
+
bool ao_untimed(struct ao *ao)
{
return ao->untimed;
diff --git a/audio/out/ao.h b/audio/out/ao.h
index d66391ef1d..f8b3e676fa 100644
--- a/audio/out/ao.h
+++ b/audio/out/ao.h
@@ -49,6 +49,7 @@ enum {
AO_EVENT_RELOAD = 1,
AO_EVENT_HOTPLUG = 2,
AO_EVENT_INITIAL_UNBLOCK = 4,
+ AO_EVENT_UNDERRUN = 8,
};
enum {
@@ -100,6 +101,7 @@ void ao_get_format(struct ao *ao,
int *samplerate, int *format, struct mp_chmap *channels);
const char *ao_get_name(struct ao *ao);
const char *ao_get_description(struct ao *ao);
+bool ao_get_reports_underruns(struct ao *ao);
bool ao_untimed(struct ao *ao);
int ao_play(struct ao *ao, void **data, int samples, int flags);
int ao_control(struct ao *ao, enum aocontrol cmd, void *arg);
diff --git a/audio/out/internal.h b/audio/out/internal.h
index bf769d7e1c..807f124a17 100644
--- a/audio/out/internal.h
+++ b/audio/out/internal.h
@@ -68,7 +68,7 @@ struct ao {
char *redirect;
// Internal events (use ao_request_reload(), ao_hotplug_event())
- atomic_int events_;
+ atomic_uint events_;
// Float gain multiplicator
mp_atomic_float gain;
@@ -134,6 +134,11 @@ struct ao_driver {
// first play() call is done. Encode mode uses this, and push mode
// respects it automatically (don't use with pull mode).
bool initially_blocked;
+ // Whether underruns are strictly _always_ reported via ao_underrun_event().
+ // Do not set this to true if underruns may be missed in some way. If the
+ // AO can't guarantee to play silence after underruns, it may be better not
+ // to set this.
+ bool reports_underruns;
// Init the device using ao->format/ao->channels/ao->samplerate. If the
// device doesn't accept these parameters, you can attempt to negotiate
// fallback parameters, and set the ao format fields accordingly.
@@ -206,6 +211,7 @@ struct pollfd;
int ao_wait_poll(struct ao *ao, struct pollfd *fds, int num_fds,
pthread_mutex_t *lock);
void ao_wakeup_poll(struct ao *ao);
+void ao_underrun_event(struct ao *ao);
bool ao_chmap_sel_adjust(struct ao *ao, const struct mp_chmap_sel *s,
struct mp_chmap *map);
diff --git a/player/audio.c b/player/audio.c
index e93f6b49a9..20f80256b2 100644
--- a/player/audio.c
+++ b/player/audio.c
@@ -855,6 +855,8 @@ void fill_audio_out_buffers(struct MPContext *mpctx)
int playsize = ao_get_space(mpctx->ao);
+ ao_query_and_reset_events(mpctx->ao, AO_EVENT_UNDERRUN);
+
int skip = 0;
bool sync_known = get_sync_samples(mpctx, &skip);
if (skip > 0) {