Commit f95e404b authored by Max Kellermann's avatar Max Kellermann

outputThread: optimize Command::OPEN

Try harder to skip steps (reopen filter, reopen output) if the AudioOutput is already open.
parent ffb8b4fc
......@@ -172,6 +172,14 @@ struct AudioOutput {
AudioFormat in_audio_format;
/**
* The #AudioFormat which is emitted by the #Filter, with
* #config_audio_format already applied. This is used to
* decide whether this object needs to be closed and reopened
* upon #AudioFormat changes.
*/
AudioFormat filter_audio_format;
/**
* The audio_format which is really sent to the device. This
* is basically config_audio_format (if configured) or
* in_audio_format, but may have been modified by
......@@ -446,15 +454,6 @@ private:
void Open();
/**
* Open the #ChainFilter and call OpenOutputAndConvert().
*
* Caller must not lock the mutex.
*
* @return true on success
*/
bool OpenFilterAndOutput();
/**
* Invoke OutputPlugin::open() and configure the
* #ConvertFilter.
*
......@@ -465,7 +464,6 @@ private:
bool OpenOutputAndConvert(AudioFormat audio_format);
void Close(bool drain);
void Reopen();
/**
* Close the output plugin.
......@@ -486,8 +484,6 @@ private:
*/
void CloseFilter();
void ReopenFilter();
/**
* Wait until the output's delay reaches zero.
*
......
......@@ -133,54 +133,61 @@ AudioOutput::CloseFilter()
inline void
AudioOutput::Open()
{
assert(!open);
assert(request.audio_format.IsValid());
fail_timer.Reset();
/* enable the device (just in case the last enable has failed) */
if (!Enable())
if (!Enable()) {
/* still no luck */
fail_timer.Update();
return;
}
in_audio_format = request.audio_format;
pipe.Init(*request.pipe);
if (!open || request.pipe != &pipe.GetPipe())
pipe.Init(*request.pipe);
bool success;
/* (re)open the filter */
{
const ScopeUnlock unlock(mutex);
success = OpenFilterAndOutput();
}
if (filter_instance != nullptr &&
request.audio_format != in_audio_format)
/* the filter must be reopened on all input format
changes */
CloseFilter();
if (success)
open = true;
else
fail_timer.Update();
}
if (filter_instance == nullptr) {
/* open the filter */
AudioFormat f;
try {
f = OpenFilter(request.audio_format)
.WithMask(config_audio_format);
} catch (const std::runtime_error &e) {
FormatError(e, "Failed to open filter for \"%s\" [%s]",
name, plugin.name);
fail_timer.Update();
return;
}
bool
AudioOutput::OpenFilterAndOutput()
{
AudioFormat filter_audio_format;
try {
filter_audio_format = OpenFilter(in_audio_format);
} catch (const std::runtime_error &e) {
FormatError(e, "Failed to open filter for \"%s\" [%s]",
name, plugin.name);
return false;
}
if (open && f != filter_audio_format) {
/* if the filter's output format changes, the
outpuit must be reopened as well */
CloseOutput(true);
open = false;
}
assert(filter_audio_format.IsValid());
filter_audio_format = f;
}
const auto audio_format =
filter_audio_format.WithMask(config_audio_format);
bool success = OpenOutputAndConvert(audio_format);
if (!success)
CloseFilter();
in_audio_format = request.audio_format;
return success;
if (!open) {
if (OpenOutputAndConvert(filter_audio_format)) {
open = true;
} else {
CloseFilter();
fail_timer.Update();
}
}
}
bool
......@@ -263,41 +270,6 @@ AudioOutput::CloseOutput(bool drain)
ao_plugin_close(this);
}
void
AudioOutput::ReopenFilter()
{
try {
const ScopeUnlock unlock(mutex);
CloseFilter();
OpenFilter(in_audio_format);
convert_filter_set(convert_filter.Get(), out_audio_format);
} catch (const std::runtime_error &e) {
FormatError(e,
"Failed to open filter for \"%s\" [%s]",
name, plugin.name);
Close(false);
}
}
void
AudioOutput::Reopen()
{
assert(open);
if ((request.audio_format != in_audio_format &&
!config_audio_format.IsFullyDefined()) ||
request.pipe != &pipe.GetPipe()) {
Close(true);
Open();
} else {
/* the audio format has changed, and all filters have
to be reconfigured */
in_audio_format = request.audio_format;
ReopenFilter();
}
}
/**
* Wait until the output's delay reaches zero.
*
......@@ -578,10 +550,7 @@ AudioOutput::Task()
break;
case Command::OPEN:
if (open)
Reopen();
else
Open();
Open();
CommandFinished();
break;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment