summaryrefslogtreecommitdiffstats
path: root/audio
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2014-10-10 13:18:53 +0200
committerwm4 <wm4@nowhere>2014-10-10 13:18:53 +0200
commitbd41fc7723a6e163de88c678826ff87779ee1af6 (patch)
treec80e4600d473001e62e8288928b8911875eb199b /audio
parenta8ec044d54817186193191f07b6d763cb823f1a1 (diff)
downloadmpv-bd41fc7723a6e163de88c678826ff87779ee1af6.tar.bz2
mpv-bd41fc7723a6e163de88c678826ff87779ee1af6.tar.xz
audio/out/push: fix EOF heuristic
Since the internal AO driver API has no proper way to determine EOF, we need to guess by querying get_delay. But some AOs (e.g. ao_pulse with no-latency-hacks set) may never reach 0, maybe because they naively add the latency to the buffer level. In this case our heuristic can break. Fix by always using the delay to estimate the EOF time. It's not even that important - it's mostly used to avoid blocking draining. So this should be ok. CC: @mpv-player/stable (maybe)
Diffstat (limited to 'audio')
-rw-r--r--audio/out/internal.h5
-rw-r--r--audio/out/push.c32
2 files changed, 14 insertions, 23 deletions
diff --git a/audio/out/internal.h b/audio/out/internal.h
index 7c5647d8fe..4532ff2c0c 100644
--- a/audio/out/internal.h
+++ b/audio/out/internal.h
@@ -24,11 +24,6 @@
#include "audio/out/ao.h"
-// If ao_get_delay() reaches this value after ao_play() was called with the
-// AOPLAY_FINAL_CHUNK flag set, the playback core expects that the audio has
-// all been played.
-#define AO_EOF_DELAY 0.05
-
/* global data used by ao.c and ao drivers */
struct ao {
int samplerate;
diff --git a/audio/out/push.c b/audio/out/push.c
index 55359cf4fe..27220e1d29 100644
--- a/audio/out/push.c
+++ b/audio/out/push.c
@@ -90,15 +90,7 @@ static double unlocked_get_delay(struct ao *ao)
double driver_delay = 0;
if (ao->driver->get_delay)
driver_delay = ao->driver->get_delay(ao);
- double delay = driver_delay + mp_audio_buffer_seconds(p->buffer);
- if (delay >= AO_EOF_DELAY && p->expected_end_time) {
- if (mp_time_sec() > p->expected_end_time) {
- MP_ERR(ao, "Audio device EOF reporting is broken!\n");
- MP_ERR(ao, "Please report this problem.\n");
- delay = 0;
- }
- }
- return delay;
+ return driver_delay + mp_audio_buffer_seconds(p->buffer);
}
static float get_delay(struct ao *ao)
@@ -240,7 +232,6 @@ static int play(struct ao *ao, void **data, int samples, int flags)
bool got_data = write_samples > 0 || p->paused || p->final_chunk != is_final;
- p->expected_end_time = 0;
p->final_chunk = is_final;
p->paused = false;
p->still_playing |= write_samples > 0;
@@ -284,11 +275,8 @@ static void ao_play_data(struct ao *ao)
r = max;
}
mp_audio_buffer_skip(p->buffer, r);
- if (p->final_chunk && mp_audio_buffer_samples(p->buffer) == 0) {
- p->expected_end_time = mp_time_sec() + AO_EOF_DELAY + 0.25; // + margin
- if (ao->driver->get_delay)
- p->expected_end_time += ao->driver->get_delay(ao);
- }
+ if (r > 0)
+ p->expected_end_time = 0;
// Nothing written, but more input data than space - this must mean the
// AO's get_space() doesn't do period alignment correctly.
bool stuck = r == 0 && max >= space && space > 0;
@@ -330,10 +318,17 @@ static void *playthread(void *arg)
bool was_playing = p->still_playing;
double timeout = -1;
- if (p->still_playing && !p->paused) {
- timeout = unlocked_get_delay(ao);
- if (timeout < AO_EOF_DELAY)
+ if (p->still_playing && !p->paused && p->final_chunk &&
+ !mp_audio_buffer_samples(p->buffer))
+ {
+ double now = mp_time_sec();
+ if (!p->expected_end_time)
+ p->expected_end_time = now + unlocked_get_delay(ao);
+ if (p->expected_end_time < now) {
p->still_playing = false;
+ } else {
+ timeout = p->expected_end_time - now;
+ }
}
if (was_playing && !p->still_playing)
@@ -346,6 +341,7 @@ static void *playthread(void *arg)
pthread_cond_wait(&p->wakeup, &p->lock);
}
} else {
+ // Wait until the device wants us to write more data to it.
if (!ao->driver->wait || ao->driver->wait(ao, &p->lock) < 0) {
// Fallback to guessing.
double timeout = 0;