summaryrefslogtreecommitdiffstats
path: root/audio/out/buffer.c
diff options
context:
space:
mode:
Diffstat (limited to 'audio/out/buffer.c')
-rw-r--r--audio/out/buffer.c61
1 files changed, 39 insertions, 22 deletions
diff --git a/audio/out/buffer.c b/audio/out/buffer.c
index 5b8b523..97f7ea1 100644
--- a/audio/out/buffer.c
+++ b/audio/out/buffer.c
@@ -41,7 +41,7 @@ struct buffer_state {
mp_mutex lock;
mp_cond wakeup;
- // Playthread sleep
+ // AO thread sleep
mp_mutex pt_lock;
mp_cond pt_wakeup;
@@ -62,6 +62,11 @@ struct buffer_state {
bool paused; // logically paused
int64_t end_time_ns; // absolute output time of last played sample
+ int64_t queued_time_ns; // duration of samples that have been queued to
+ // the device but have not been played.
+ // This field is only set in ao_set_paused(),
+ // and is considered as a temporary solution;
+ // DO NOT USE IT IN OTHER PLACES.
bool initial_unblocked;
@@ -78,9 +83,9 @@ struct buffer_state {
bool terminate; // exit thread
};
-static MP_THREAD_VOID playthread(void *arg);
+static MP_THREAD_VOID ao_thread(void *arg);
-void ao_wakeup_playthread(struct ao *ao)
+void ao_wakeup(struct ao *ao)
{
struct buffer_state *p = ao->buffer_state;
mp_mutex_lock(&p->pt_lock);
@@ -173,8 +178,8 @@ static int read_buffer(struct ao *ao, void **data, int samples, bool *eof,
return pos;
}
-static int ao_read_data_unlocked(struct ao *ao, void **data, int samples,
- int64_t out_time_ns, bool pad_silence)
+static int ao_read_data_locked(struct ao *ao, void **data, int samples,
+ int64_t out_time_ns, bool pad_silence)
{
struct buffer_state *p = ao->buffer_state;
assert(!ao->driver->write);
@@ -208,7 +213,7 @@ int ao_read_data(struct ao *ao, void **data, int samples, int64_t out_time_ns)
mp_mutex_lock(&p->lock);
- int pos = ao_read_data_unlocked(ao, data, samples, out_time_ns, true);
+ int pos = ao_read_data_locked(ao, data, samples, out_time_ns, true);
mp_mutex_unlock(&p->lock);
@@ -224,7 +229,7 @@ int ao_read_data_nonblocking(struct ao *ao, void **data, int samples, int64_t ou
if (mp_mutex_trylock(&p->lock))
return 0;
- int pos = ao_read_data_unlocked(ao, data, samples, out_time_ns, false);
+ int pos = ao_read_data_locked(ao, data, samples, out_time_ns, false);
mp_mutex_unlock(&p->lock);
@@ -347,7 +352,7 @@ void ao_reset(struct ao *ao)
ao->driver->reset(ao);
if (wakeup)
- ao_wakeup_playthread(ao);
+ ao_wakeup(ao);
}
// Initiate playback. This moves from the stop/underrun state to actually
@@ -374,14 +379,14 @@ void ao_start(struct ao *ao)
if (do_start)
ao->driver->start(ao);
- ao_wakeup_playthread(ao);
+ ao_wakeup(ao);
}
void ao_set_paused(struct ao *ao, bool paused, bool eof)
{
struct buffer_state *p = ao->buffer_state;
bool wakeup = false;
- bool do_reset = false, do_start = false;
+ bool do_change_state = false;
// If we are going to pause on eof and ao is still playing,
// be sure to drain the ao first for gapless.
@@ -402,9 +407,9 @@ void ao_set_paused(struct ao *ao, bool paused, bool eof)
p->streaming = false;
p->recover_pause = !ao->untimed;
}
- } else if (ao->driver->reset) {
+ } else if (ao->driver->reset || ao->driver->set_pause) {
// See ao_reset() why this is done outside of the lock.
- do_reset = true;
+ do_change_state = true;
p->streaming = false;
}
}
@@ -416,7 +421,7 @@ void ao_set_paused(struct ao *ao, bool paused, bool eof)
p->hw_paused = false;
} else {
if (!p->streaming)
- do_start = true;
+ do_change_state = true;
p->streaming = true;
}
wakeup = true;
@@ -425,13 +430,25 @@ void ao_set_paused(struct ao *ao, bool paused, bool eof)
mp_mutex_unlock(&p->lock);
- if (do_reset)
- ao->driver->reset(ao);
- if (do_start)
- ao->driver->start(ao);
+ if (do_change_state) {
+ if (ao->driver->set_pause) {
+ if (paused) {
+ ao->driver->set_pause(ao, true);
+ p->queued_time_ns = p->end_time_ns - mp_time_ns();
+ } else {
+ p->end_time_ns = p->queued_time_ns + mp_time_ns();
+ ao->driver->set_pause(ao, false);
+ }
+ } else {
+ if (paused)
+ ao->driver->reset(ao);
+ else
+ ao->driver->start(ao);
+ }
+ }
if (wakeup)
- ao_wakeup_playthread(ao);
+ ao_wakeup(ao);
}
// Whether audio is playing. This means that there is still data in the buffers,
@@ -486,7 +503,7 @@ void ao_drain(struct ao *ao)
static void wakeup_filters(void *ctx)
{
struct ao *ao = ctx;
- ao_wakeup_playthread(ao);
+ ao_wakeup(ao);
}
void ao_uninit(struct ao *ao)
@@ -561,7 +578,7 @@ bool init_buffer_post(struct ao *ao)
mp_filter_graph_set_wakeup_cb(p->filter_root, wakeup_filters, ao);
p->thread_valid = true;
- if (mp_thread_create(&p->thread, playthread, ao)) {
+ if (mp_thread_create(&p->thread, ao_thread, ao)) {
p->thread_valid = false;
return false;
}
@@ -684,7 +701,7 @@ eof:
return true;
}
-static MP_THREAD_VOID playthread(void *arg)
+static MP_THREAD_VOID ao_thread(void *arg)
{
struct ao *ao = arg;
struct buffer_state *p = ao->buffer_state;
@@ -731,6 +748,6 @@ void ao_unblock(struct ao *ao)
mp_mutex_lock(&p->lock);
p->initial_unblocked = true;
mp_mutex_unlock(&p->lock);
- ao_wakeup_playthread(ao);
+ ao_wakeup(ao);
}
}