diff options
author | Max Kellermann <max@musicpd.org> | 2018-01-01 19:22:45 +0100 |
---|---|---|
committer | Max Kellermann <max@musicpd.org> | 2018-01-02 23:15:51 +0100 |
commit | 6d0d8cf9cf07a5d0905f715be9a79f5de86e8b37 (patch) | |
tree | 2fd9692a25b7e80ed67320a395bf0bbed1f9f91c /src/filter | |
parent | 14f669f4fbac72833e622f66f81950b4be3e3c12 (diff) |
filter/Filter: add virtual method Flush()
This will be used by filters which have internal buffers which need to
be flushed at the end, e.g. the "soxr" resampler.
Diffstat (limited to 'src/filter')
-rw-r--r-- | src/filter/Filter.cxx | 27 | ||||
-rw-r--r-- | src/filter/Filter.hxx | 6 | ||||
-rw-r--r-- | src/filter/Observer.cxx | 4 | ||||
-rw-r--r-- | src/filter/plugins/ChainFilterPlugin.cxx | 49 |
4 files changed, 80 insertions, 6 deletions
diff --git a/src/filter/Filter.cxx b/src/filter/Filter.cxx new file mode 100644 index 000000000..6a291cde9 --- /dev/null +++ b/src/filter/Filter.cxx @@ -0,0 +1,27 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "Filter.hxx" +#include "util/ConstBuffer.hxx" + +ConstBuffer<void> +Filter::Flush() +{ + return nullptr; +} diff --git a/src/filter/Filter.hxx b/src/filter/Filter.hxx index 6af002adc..7d714df79 100644 --- a/src/filter/Filter.hxx +++ b/src/filter/Filter.hxx @@ -62,6 +62,12 @@ public: * or Reset() call) */ virtual ConstBuffer<void> FilterPCM(ConstBuffer<void> src) = 0; + + /** + * Flush pending data and return it. This should be called + * repepatedly until it returns nullptr. + */ + virtual ConstBuffer<void> Flush(); }; #endif diff --git a/src/filter/Observer.cxx b/src/filter/Observer.cxx index d51d6329e..a56efc70f 100644 --- a/src/filter/Observer.cxx +++ b/src/filter/Observer.cxx @@ -75,6 +75,10 @@ public: ConstBuffer<void> FilterPCM(ConstBuffer<void> src) override { return filter->FilterPCM(src); } + + ConstBuffer<void> Flush() noexcept override { + return filter->Flush(); + } }; Filter * diff --git a/src/filter/plugins/ChainFilterPlugin.cxx b/src/filter/plugins/ChainFilterPlugin.cxx index 6fa273729..d95ae3768 100644 --- a/src/filter/plugins/ChainFilterPlugin.cxx +++ b/src/filter/plugins/ChainFilterPlugin.cxx @@ -43,6 +43,11 @@ class ChainFilter final : public Filter { std::list<Child> children; + /** + * The child which will be flushed in the next Flush() call. + */ + std::list<Child>::iterator flushing = children.end(); + public: explicit ChainFilter(AudioFormat _audio_format) :Filter(_audio_format) {} @@ -54,11 +59,20 @@ public: assert(out_audio_format.IsValid()); children.emplace_back(name, std::move(filter)); + + RewindFlush(); } /* virtual methods from class Filter */ void Reset() noexcept override; ConstBuffer<void> FilterPCM(ConstBuffer<void> src) override; + ConstBuffer<void> Flush() override; + +private: + void RewindFlush() { + flushing = children.begin(); + } + }; class PreparedChainFilter final : public PreparedFilter { @@ -118,23 +132,46 @@ PreparedChainFilter::Open(AudioFormat &in_audio_format) void ChainFilter::Reset() noexcept { + RewindFlush(); + for (auto &child : children) child.filter->Reset(); } -ConstBuffer<void> -ChainFilter::FilterPCM(ConstBuffer<void> src) +template<typename I> +static ConstBuffer<void> +ApplyFilterChain(I begin, I end, ConstBuffer<void> src) { - for (auto &child : children) { + for (auto i = begin; i != end; ++i) /* feed the output of the previous filter as input into the current one */ - src = child.filter->FilterPCM(src); - } + src = i->filter->FilterPCM(src); - /* return the output of the last filter */ return src; } +ConstBuffer<void> +ChainFilter::FilterPCM(ConstBuffer<void> src) +{ + RewindFlush(); + + /* return the output of the last filter */ + return ApplyFilterChain(children.begin(), children.end(), src); +} + +ConstBuffer<void> +ChainFilter::Flush() +{ + for (auto end = children.end(); flushing != end; ++flushing) { + auto data = flushing->filter->Flush(); + if (!data.IsNull()) + return ApplyFilterChain(std::next(flushing), end, + data); + } + + return nullptr; +} + std::unique_ptr<PreparedFilter> filter_chain_new() noexcept { |