output/Source: release the mutex while the filter runs

The filter can take some time to finish, even more so on a weak
machine with a saturated CPU.  By not holding the mutex during that
time, we can reduce PlayerThread latency a lot, because that thread
needs to synchronize a lot with all outputs.
This commit is contained in:
Max Kellermann 2016-12-26 20:02:15 +01:00
parent 86d3b25aec
commit b6004b6837
3 changed files with 12 additions and 3 deletions

View File

@ -264,7 +264,7 @@ AudioOutput::WaitForDelay()
bool bool
AudioOutput::FillSourceOrClose() AudioOutput::FillSourceOrClose()
try { try {
return source.Fill(); return source.Fill(mutex);
} catch (const std::runtime_error &e) { } catch (const std::runtime_error &e) {
FormatError(e, "Failed to filter for output \"%s\" [%s]", FormatError(e, "Failed to filter for output \"%s\" [%s]",
name, plugin.name); name, plugin.name);

View File

@ -23,6 +23,7 @@
#include "filter/FilterInternal.hxx" #include "filter/FilterInternal.hxx"
#include "filter/plugins/ReplayGainFilterPlugin.hxx" #include "filter/plugins/ReplayGainFilterPlugin.hxx"
#include "pcm/PcmMix.hxx" #include "pcm/PcmMix.hxx"
#include "thread/Mutex.hxx"
#include "util/ConstBuffer.hxx" #include "util/ConstBuffer.hxx"
#include "util/RuntimeError.hxx" #include "util/RuntimeError.hxx"
@ -187,7 +188,7 @@ AudioOutputSource::FilterChunk(const MusicChunk &chunk)
} }
bool bool
AudioOutputSource::Fill() AudioOutputSource::Fill(Mutex &mutex)
{ {
if (current_chunk != nullptr && pending_tag == nullptr && if (current_chunk != nullptr && pending_tag == nullptr &&
pending_data.IsEmpty()) pending_data.IsEmpty())
@ -203,6 +204,10 @@ AudioOutputSource::Fill()
pending_tag = current_chunk->tag; pending_tag = current_chunk->tag;
try { try {
/* release the mutex while the filter runs, because
that may take a while */
const ScopeUnlock unlock(mutex);
pending_data = pending_data.FromVoid(FilterChunk(*current_chunk)); pending_data = pending_data.FromVoid(FilterChunk(*current_chunk));
} catch (...) { } catch (...) {
current_chunk = nullptr; current_chunk = nullptr;

View File

@ -36,6 +36,7 @@
struct MusicChunk; struct MusicChunk;
struct Tag; struct Tag;
class Mutex;
class Filter; class Filter;
class PreparedFilter; class PreparedFilter;
@ -147,10 +148,13 @@ public:
* *
* Throws std::runtime_error on error * Throws std::runtime_error on error
* *
* @param mutex the #Mutex which protects the
* #SharedPipeConsumer; it is locked by the caller, and may be
* unlocked temporarily by this method
* @return true if any input is available, false if the source * @return true if any input is available, false if the source
* has (temporarily?) run empty * has (temporarily?) run empty
*/ */
bool Fill(); bool Fill(Mutex &mutex);
/** /**
* Reads the #Tag to be processed. Be sure to call Fill() * Reads the #Tag to be processed. Be sure to call Fill()