ao: correctly set state.playing for non-gapless audio after eof

The problem here is likely ao_alsa specific and has the same symptons as
what the previous commit fixed (audio not playing when the file changes
but the details are a bit different here and the sample rate does not
matter. When using gapless audio (the default), the core player
immediately marks the audio status as EOF after it starts draining and
allows the remaining audio buffers to play while it marches on. This
works fine. When not using gapless audio, it doesn't immediately set EOF
and instead waits for the audio to finish playing before it does
anything else. The problem is that ao_is_playing is always true so the
core waits forever thinking audio is still playing when it actually
isn't.

ao_play_data is what is in charge of setting the mp_pcm_state with it
calling out to the backend for additional help. Unfortunately, this
doesn't work for alsa because it's too dumb to signal the desired states
in this edge case so we have to help it a bit. The main thing to notice
here is that even though we can get EOF from a frame, there can still be
additional valid samples that compe after it. So we can't just
immediately quit after EOF is seen. The approach here is to simply save
if we got eof sometime in the past, wait until we get no more samples,
mark state.playing as false and then jump over to the eof code. This
will set p->playing to false as desired which allows the core code to
set EOF and finally we can go through the reset logic and actually play
audio for the next file.
This commit is contained in:
Dudemanguy committed 2024-12-11 17:12:22 +00:00
1 parent a7f6460e7e
commit d33e54250e
1 file changed
+8 -1
+8 -1
View File
@@ -56,6 +56,7 @@ struct buffer_state {
struct mp_filter *input; // connected to queue
struct mp_aframe *pending; // last, not fully consumed output
bool got_eof; // received eof in recent past
bool streaming; // AO streaming active
bool playing; // logically playing audio from buffer
bool paused; // logically paused
@@ -682,13 +683,19 @@ static bool ao_play_data(struct ao *ao)
p->streaming = true;
state.playing = true;
}
} else if (p->streaming && p->got_eof && !samples) {
p->got_eof = false;
state.playing = false;
goto eof;
}
MP_TRACE(ao, "in=%d space=%d(%d) pl=%d, eof=%d\n",
samples, space, state.free_samples, p->playing, got_eof);
if (got_eof)
if (got_eof) {
p->got_eof = got_eof;
goto eof;
}
return samples > 0 && (samples < space || ao->untimed);