summaryrefslogtreecommitdiffstats
path: root/audio/out
diff options
context:
space:
mode:
authorMisaki Kasumi <misakikasumi@outlook.com>2024-03-26 04:08:13 +0800
committersfan5 <sfan5@live.de>2024-04-03 23:40:05 +0200
commit93a924a5538afd4a6f98878c8ae16f17ee80b958 (patch)
treef7d5a3e778bff6a8058db101c57eb6450b207960 /audio/out
parent8d85627aad4a8e98db19aec7e4e28ca61b1bbe25 (diff)
downloadmpv-93a924a5538afd4a6f98878c8ae16f17ee80b958.tar.bz2
mpv-93a924a5538afd4a6f98878c8ae16f17ee80b958.tar.xz
ao: set_pause for pull based ao
Diffstat (limited to 'audio/out')
-rw-r--r--audio/out/buffer.c33
-rw-r--r--audio/out/internal.h6
2 files changed, 29 insertions, 10 deletions
diff --git a/audio/out/buffer.c b/audio/out/buffer.c
index d3026a8574..c9e5d3e2f2 100644
--- a/audio/out/buffer.c
+++ b/audio/out/buffer.c
@@ -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;
@@ -381,7 +386,7 @@ 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,10 +430,22 @@ 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);
diff --git a/audio/out/internal.h b/audio/out/internal.h
index 7951b3861e..3a2e5ae554 100644
--- a/audio/out/internal.h
+++ b/audio/out/internal.h
@@ -108,6 +108,7 @@ struct mp_pcm_state {
* start
* Optional for both types:
* control
+ * set_pause
* a) ->write is called to queue audio. push.c creates a thread to regularly
* refill audio device buffers with ->write, but all driver functions are
* always called under an exclusive lock.
@@ -115,8 +116,6 @@ struct mp_pcm_state {
* reset
* write
* get_state
- * Optional:
- * set_pause
* b) ->write must be NULL. ->start must be provided, and should make the
* audio API start calling the audio callback. Your audio callback should
* in turn call ao_read_data() to get audio data. Most functions are
@@ -149,6 +148,9 @@ struct ao_driver {
// Stop all audio playback, clear buffers, back to state after init().
// Optional for pull AOs.
void (*reset)(struct ao *ao);
+ // pull based: set pause state. Only called after start() and before reset().
+ // The return value is ignored.
+ // The pausing state is also cleared by reset().
// push based: set pause state. Only called after start() and before reset().
// returns success (this is intended for paused=true; if it
// returns false, playback continues, and the core emulates via