From 6d0d8cf9cf07a5d0905f715be9a79f5de86e8b37 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 1 Jan 2018 19:22:45 +0100 Subject: 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. --- src/filter/Filter.cxx | 27 ++++++++++++++++++ src/filter/Filter.hxx | 6 ++++ src/filter/Observer.cxx | 4 +++ src/filter/plugins/ChainFilterPlugin.cxx | 49 ++++++++++++++++++++++++++++---- 4 files changed, 80 insertions(+), 6 deletions(-) create mode 100644 src/filter/Filter.cxx (limited to 'src/filter') 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 +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 FilterPCM(ConstBuffer src) = 0; + + /** + * Flush pending data and return it. This should be called + * repepatedly until it returns nullptr. + */ + virtual ConstBuffer 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 FilterPCM(ConstBuffer src) override { return filter->FilterPCM(src); } + + ConstBuffer 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 children; + /** + * The child which will be flushed in the next Flush() call. + */ + std::list::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 FilterPCM(ConstBuffer src) override; + ConstBuffer 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 -ChainFilter::FilterPCM(ConstBuffer src) +template +static ConstBuffer +ApplyFilterChain(I begin, I end, ConstBuffer 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 +ChainFilter::FilterPCM(ConstBuffer src) +{ + RewindFlush(); + + /* return the output of the last filter */ + return ApplyFilterChain(children.begin(), children.end(), src); +} + +ConstBuffer +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 filter_chain_new() noexcept { -- cgit v1.2.3