mirror of https://github.com/mpv-player/mpv
audio: drain ao before setting pause
There's an edge cause with gapless audio and pausing. Since, gapless audio works by sending an EOF immediately, it's possible to pause on the next file before audio actually finishes playing and thus the sound gets cut off. The fix is to simply just always do an ao_drain if the ao is about to set a pause on EOF and we still have audio playing. Fixes #8898.
This commit is contained in:
parent
908dc79129
commit
41c0321208
|
@ -98,7 +98,7 @@ void ao_set_gain(struct ao *ao, float gain);
|
||||||
double ao_get_delay(struct ao *ao);
|
double ao_get_delay(struct ao *ao);
|
||||||
void ao_reset(struct ao *ao);
|
void ao_reset(struct ao *ao);
|
||||||
void ao_start(struct ao *ao);
|
void ao_start(struct ao *ao);
|
||||||
void ao_set_paused(struct ao *ao, bool paused);
|
void ao_set_paused(struct ao *ao, bool paused, bool eof);
|
||||||
void ao_drain(struct ao *ao);
|
void ao_drain(struct ao *ao);
|
||||||
bool ao_is_playing(struct ao *ao);
|
bool ao_is_playing(struct ao *ao);
|
||||||
struct mp_async_queue;
|
struct mp_async_queue;
|
||||||
|
|
|
@ -349,12 +349,17 @@ void ao_start(struct ao *ao)
|
||||||
ao_wakeup_playthread(ao);
|
ao_wakeup_playthread(ao);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ao_set_paused(struct ao *ao, bool paused)
|
void ao_set_paused(struct ao *ao, bool paused, bool eof)
|
||||||
{
|
{
|
||||||
struct buffer_state *p = ao->buffer_state;
|
struct buffer_state *p = ao->buffer_state;
|
||||||
bool wakeup = false;
|
bool wakeup = false;
|
||||||
bool do_reset = false, do_start = false;
|
bool do_reset = false, do_start = false;
|
||||||
|
|
||||||
|
// If we are going to pause on eof and ao is still playing,
|
||||||
|
// be sure to drain the ao first for gapless.
|
||||||
|
if (eof && paused && ao_is_playing(ao))
|
||||||
|
ao_drain(ao);
|
||||||
|
|
||||||
pthread_mutex_lock(&p->lock);
|
pthread_mutex_lock(&p->lock);
|
||||||
|
|
||||||
if ((p->playing || !ao->driver->write) && !p->paused && paused) {
|
if ((p->playing || !ao->driver->write) && !p->paused && paused) {
|
||||||
|
|
|
@ -486,7 +486,8 @@ static int reinit_audio_filters_and_output(struct MPContext *mpctx)
|
||||||
ao_c->ao_resume_time =
|
ao_c->ao_resume_time =
|
||||||
opts->audio_wait_open > 0 ? mp_time_sec() + opts->audio_wait_open : 0;
|
opts->audio_wait_open > 0 ? mp_time_sec() + opts->audio_wait_open : 0;
|
||||||
|
|
||||||
ao_set_paused(mpctx->ao, get_internal_paused(mpctx));
|
bool eof = mpctx->audio_status == STATUS_EOF;
|
||||||
|
ao_set_paused(mpctx->ao, get_internal_paused(mpctx), eof);
|
||||||
|
|
||||||
ao_chain_set_ao(ao_c, mpctx->ao);
|
ao_chain_set_ao(ao_c, mpctx->ao);
|
||||||
|
|
||||||
|
|
|
@ -162,8 +162,10 @@ void set_pause_state(struct MPContext *mpctx, bool user_pause)
|
||||||
if (internal_paused != mpctx->paused) {
|
if (internal_paused != mpctx->paused) {
|
||||||
mpctx->paused = internal_paused;
|
mpctx->paused = internal_paused;
|
||||||
|
|
||||||
if (mpctx->ao)
|
if (mpctx->ao) {
|
||||||
ao_set_paused(mpctx->ao, internal_paused);
|
bool eof = mpctx->audio_status == STATUS_EOF;
|
||||||
|
ao_set_paused(mpctx->ao, internal_paused, eof);
|
||||||
|
}
|
||||||
|
|
||||||
if (mpctx->video_out)
|
if (mpctx->video_out)
|
||||||
vo_set_paused(mpctx->video_out, internal_paused);
|
vo_set_paused(mpctx->video_out, internal_paused);
|
||||||
|
|
Loading…
Reference in New Issue