output/Thread: skip drain calls if there is no data to be played

Keep track of whether there is data being played, and don't call
AudioOutput::Drain() after Cancel() has been called already.
This commit is contained in:
Max Kellermann 2021-02-15 16:15:27 +01:00
parent f1b8bcd6b2
commit efde78db77
2 changed files with 21 additions and 1 deletions

View File

@ -181,6 +181,14 @@ class AudioOutputControl {
*/
bool open = false;
/**
* Is the device currently playing, i.e. is its buffer
* (likely) non-empty? If not, then it will never be drained.
*
* This field is only valid while the output is open.
*/
bool playing;
/**
* Is the device paused? i.e. the output thread is in the
* ao_pause() loop.

View File

@ -53,7 +53,7 @@ AudioOutputControl::InternalOpen2(const AudioFormat in_audio_format)
if (open && cf != output->filter_audio_format)
/* if the filter's output format changes, the output
must be reopened as well */
InternalCloseOutput(true);
InternalCloseOutput(playing);
output->filter_audio_format = cf;
@ -64,6 +64,7 @@ AudioOutputControl::InternalOpen2(const AudioFormat in_audio_format)
}
open = true;
playing = false;
} else if (in_audio_format != output->out_audio_format) {
/* reconfigure the final ConvertFilter for its new
input AudioFormat */
@ -285,6 +286,9 @@ AudioOutputControl::PlayChunk(std::unique_lock<Mutex> &lock) noexcept
assert(nbytes % output->out_audio_format.GetFrameSize() == 0);
source.ConsumeData(nbytes);
/* there's data to be drained from now on */
playing = true;
}
return true;
@ -371,6 +375,9 @@ AudioOutputControl::InternalPause(std::unique_lock<Mutex> &lock) noexcept
}
skip_delay = true;
/* ignore drain commands until we got something new to play */
playing = false;
}
static void
@ -390,6 +397,10 @@ PlayFull(FilteredAudioOutput &output, ConstBuffer<void> _buffer)
inline void
AudioOutputControl::InternalDrain() noexcept
{
/* after this method finishes, there's nothing left to be
drained */
playing = false;
try {
/* flush the filter and play its remaining output */
@ -518,6 +529,7 @@ AudioOutputControl::Task() noexcept
source.Cancel();
if (open) {
playing = false;
const ScopeUnlock unlock(mutex);
output->Cancel();
}