From 959826d1d125a50bc885c374b10f3a15eea644fb Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 30 Jul 2024 12:27:51 +0200 Subject: [PATCH] input/ffmpeg: offload FFmpeg calls to thread Prepare for interruptible I/O. --- src/input/plugins/FfmpegInputPlugin.cxx | 74 +++++++++++-------------- 1 file changed, 33 insertions(+), 41 deletions(-) diff --git a/src/input/plugins/FfmpegInputPlugin.cxx b/src/input/plugins/FfmpegInputPlugin.cxx index dff5fbb7f..3f9c69a7d 100644 --- a/src/input/plugins/FfmpegInputPlugin.cxx +++ b/src/input/plugins/FfmpegInputPlugin.cxx @@ -7,36 +7,35 @@ #include "FfmpegInputPlugin.hxx" #include "lib/ffmpeg/IOContext.hxx" #include "lib/ffmpeg/Init.hxx" -#include "../InputStream.hxx" +#include "../ThreadInputStream.hxx" #include "PluginUnavailable.hxx" #include "../InputPlugin.hxx" #include "util/StringAPI.hxx" -class FfmpegInputStream final : public InputStream { +class FfmpegInputStream final : public ThreadInputStream { + static constexpr std::size_t BUFFER_SIZE = 256 * 1024; + Ffmpeg::IOContext io; public: FfmpegInputStream(const char *_uri, Mutex &_mutex) - :InputStream(_uri, _mutex), - io(_uri, AVIO_FLAG_READ) + :ThreadInputStream("ffmpeg", _uri, _mutex, BUFFER_SIZE) { - seekable = (io->seekable & AVIO_SEEKABLE_NORMAL) != 0; - size = io.GetSize(); - - /* hack to make MPD select the "ffmpeg" decoder plugin - - since avio.h doesn't tell us the MIME type of the - resource, we can't select a decoder plugin, but the - "ffmpeg" plugin is quite good at auto-detection */ - SetMimeType("audio/x-mpd-ffmpeg"); - SetReady(); + Start(); } - /* virtual methods from InputStream */ - [[nodiscard]] bool IsEOF() const noexcept override; - size_t Read(std::unique_lock &lock, - std::span dest) override; - void Seek(std::unique_lock &lock, - offset_type offset) override; + ~FfmpegInputStream() noexcept override { + Stop(); + } + + /* virtual methods from ThreadInputStream */ + void Open() override; + std::size_t ThreadRead(std::span dest) override; + void ThreadSeek(offset_type offset) override; + + void Close() noexcept override { + io = {}; + } }; [[gnu::const]] @@ -89,38 +88,31 @@ input_ffmpeg_open(const char *uri, return std::make_unique(uri, mutex); } -size_t -FfmpegInputStream::Read(std::unique_lock &, - std::span dest) +void +FfmpegInputStream::Open() { - size_t result; + io = {GetURI(), AVIO_FLAG_READ}; - { - const ScopeUnlock unlock(mutex); - result = io.Read(dest); - } + seekable = (io->seekable & AVIO_SEEKABLE_NORMAL) != 0; + size = io.GetSize(); - offset += result; - return (size_t)result; + /* hack to make MPD select the "ffmpeg" decoder plugin - since + avio.h doesn't tell us the MIME type of the resource, we + can't select a decoder plugin, but the "ffmpeg" plugin is + quite good at auto-detection */ + SetMimeType("audio/x-mpd-ffmpeg"); } -bool -FfmpegInputStream::IsEOF() const noexcept +std::size_t +FfmpegInputStream::ThreadRead(std::span dest) { - return io.IsEOF(); + return io.Read(dest); } void -FfmpegInputStream::Seek(std::unique_lock &, offset_type new_offset) +FfmpegInputStream::ThreadSeek(offset_type new_offset) { - uint64_t result; - - { - const ScopeUnlock unlock(mutex); - result = io.Seek(new_offset); - } - - offset = result; + io.Seek(new_offset); } const InputPlugin input_plugin_ffmpeg = {