summaryrefslogtreecommitdiffstats
path: root/audio
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2014-05-30 02:14:45 +0200
committerwm4 <wm4@nowhere>2014-05-30 02:17:15 +0200
commit8ba346a5541294cb17b0e0e53306dd96c985eab4 (patch)
tree141d6348f545a03e287e4575d96ee65c5e576554 /audio
parentc79689206c489b2ba449b8d21e0b5819298c949a (diff)
downloadmpv-8ba346a5541294cb17b0e0e53306dd96c985eab4.tar.bz2
mpv-8ba346a5541294cb17b0e0e53306dd96c985eab4.tar.xz
audio/out/push: handle draining correctly
This did not flush remaining audio in the buffer correctly (in case an AO has an internal block size). So we have to make the audio feed thread to write the remaining audio, and wait until it's done. Checking the avoid_ao_wait variable should be enough to be sure that all data that can be written was written to the AO driver.
Diffstat (limited to 'audio')
-rw-r--r--audio/out/push.c29
1 files changed, 22 insertions, 7 deletions
diff --git a/audio/out/push.c b/audio/out/push.c
index b779dac69a..409a5f50e0 100644
--- a/audio/out/push.c
+++ b/audio/out/push.c
@@ -44,12 +44,14 @@ struct ao_push_state {
pthread_t thread;
pthread_mutex_t lock;
pthread_cond_t wakeup;
+ pthread_cond_t wakeup_drain;
// --- protected by lock
struct mp_audio_buffer *buffer;
bool terminate;
+ bool drain;
bool buffers_full;
bool avoid_ao_wait;
bool need_wakeup;
@@ -141,14 +143,18 @@ static void resume(struct ao *ao)
static void drain(struct ao *ao)
{
- if (ao->driver->drain) {
- struct ao_push_state *p = ao->api_priv;
- pthread_mutex_lock(&p->lock);
- ao->driver->drain(ao);
- pthread_mutex_unlock(&p->lock);
- } else {
+ struct ao_push_state *p = ao->api_priv;
+
+ pthread_mutex_lock(&p->lock);
+ p->final_chunk = true;
+ p->drain = true;
+ wakeup_playthread(ao);
+ while (p->drain)
+ pthread_cond_wait(&p->wakeup_drain, &p->lock);
+ pthread_mutex_unlock(&p->lock);
+
+ if (!ao->driver->drain)
ao_wait_drain(ao);
- }
}
static int unlocked_get_space(struct ao *ao)
@@ -290,6 +296,13 @@ static void *playthread(void *arg)
p->requested_data = true;
}
+ if (p->drain && p->avoid_ao_wait) {
+ if (ao->driver->drain)
+ ao->driver->drain(ao);
+ p->drain = false;
+ pthread_cond_signal(&p->wakeup_drain);
+ }
+
if (!p->need_wakeup) {
MP_STATS(ao, "start audio wait");
if (p->avoid_ao_wait) {
@@ -334,6 +347,7 @@ static void uninit(struct ao *ao)
close(p->wakeup_pipe[n]);
pthread_cond_destroy(&p->wakeup);
+ pthread_cond_destroy(&p->wakeup_drain);
pthread_mutex_destroy(&p->lock);
}
@@ -343,6 +357,7 @@ static int init(struct ao *ao)
pthread_mutex_init(&p->lock, NULL);
pthread_cond_init(&p->wakeup, NULL);
+ pthread_cond_init(&p->wakeup_drain, NULL);
mp_make_wakeup_pipe(p->wakeup_pipe);
p->buffer = mp_audio_buffer_create(ao);