diff options
author | Misaki Kasumi <misakikasumi@outlook.com> | 2024-03-26 04:08:13 +0800 |
---|---|---|
committer | sfan5 <sfan5@live.de> | 2024-04-03 23:40:05 +0200 |
commit | 93a924a5538afd4a6f98878c8ae16f17ee80b958 (patch) | |
tree | f7d5a3e778bff6a8058db101c57eb6450b207960 /audio/out | |
parent | 8d85627aad4a8e98db19aec7e4e28ca61b1bbe25 (diff) | |
download | mpv-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.c | 33 | ||||
-rw-r--r-- | audio/out/internal.h | 6 |
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 |