input/ffmpeg: offload FFmpeg calls to thread
Prepare for interruptible I/O.
This commit is contained in:
parent
ec30716e01
commit
959826d1d1
|
@ -7,36 +7,35 @@
|
||||||
#include "FfmpegInputPlugin.hxx"
|
#include "FfmpegInputPlugin.hxx"
|
||||||
#include "lib/ffmpeg/IOContext.hxx"
|
#include "lib/ffmpeg/IOContext.hxx"
|
||||||
#include "lib/ffmpeg/Init.hxx"
|
#include "lib/ffmpeg/Init.hxx"
|
||||||
#include "../InputStream.hxx"
|
#include "../ThreadInputStream.hxx"
|
||||||
#include "PluginUnavailable.hxx"
|
#include "PluginUnavailable.hxx"
|
||||||
#include "../InputPlugin.hxx"
|
#include "../InputPlugin.hxx"
|
||||||
#include "util/StringAPI.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;
|
Ffmpeg::IOContext io;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FfmpegInputStream(const char *_uri, Mutex &_mutex)
|
FfmpegInputStream(const char *_uri, Mutex &_mutex)
|
||||||
:InputStream(_uri, _mutex),
|
:ThreadInputStream("ffmpeg", _uri, _mutex, BUFFER_SIZE)
|
||||||
io(_uri, AVIO_FLAG_READ)
|
|
||||||
{
|
{
|
||||||
seekable = (io->seekable & AVIO_SEEKABLE_NORMAL) != 0;
|
Start();
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* virtual methods from InputStream */
|
~FfmpegInputStream() noexcept override {
|
||||||
[[nodiscard]] bool IsEOF() const noexcept override;
|
Stop();
|
||||||
size_t Read(std::unique_lock<Mutex> &lock,
|
}
|
||||||
std::span<std::byte> dest) override;
|
|
||||||
void Seek(std::unique_lock<Mutex> &lock,
|
/* virtual methods from ThreadInputStream */
|
||||||
offset_type offset) override;
|
void Open() override;
|
||||||
|
std::size_t ThreadRead(std::span<std::byte> dest) override;
|
||||||
|
void ThreadSeek(offset_type offset) override;
|
||||||
|
|
||||||
|
void Close() noexcept override {
|
||||||
|
io = {};
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
[[gnu::const]]
|
[[gnu::const]]
|
||||||
|
@ -89,38 +88,31 @@ input_ffmpeg_open(const char *uri,
|
||||||
return std::make_unique<FfmpegInputStream>(uri, mutex);
|
return std::make_unique<FfmpegInputStream>(uri, mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
void
|
||||||
FfmpegInputStream::Read(std::unique_lock<Mutex> &,
|
FfmpegInputStream::Open()
|
||||||
std::span<std::byte> dest)
|
|
||||||
{
|
{
|
||||||
size_t result;
|
io = {GetURI(), AVIO_FLAG_READ};
|
||||||
|
|
||||||
{
|
seekable = (io->seekable & AVIO_SEEKABLE_NORMAL) != 0;
|
||||||
const ScopeUnlock unlock(mutex);
|
size = io.GetSize();
|
||||||
result = io.Read(dest);
|
|
||||||
}
|
|
||||||
|
|
||||||
offset += result;
|
/* hack to make MPD select the "ffmpeg" decoder plugin - since
|
||||||
return (size_t)result;
|
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
|
std::size_t
|
||||||
FfmpegInputStream::IsEOF() const noexcept
|
FfmpegInputStream::ThreadRead(std::span<std::byte> dest)
|
||||||
{
|
{
|
||||||
return io.IsEOF();
|
return io.Read(dest);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
FfmpegInputStream::Seek(std::unique_lock<Mutex> &, offset_type new_offset)
|
FfmpegInputStream::ThreadSeek(offset_type new_offset)
|
||||||
{
|
{
|
||||||
uint64_t result;
|
io.Seek(new_offset);
|
||||||
|
|
||||||
{
|
|
||||||
const ScopeUnlock unlock(mutex);
|
|
||||||
result = io.Seek(new_offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
offset = result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const InputPlugin input_plugin_ffmpeg = {
|
const InputPlugin input_plugin_ffmpeg = {
|
||||||
|
|
Loading…
Reference in New Issue