decoder/plugin: add method protocols()
Similar to commit 4e2a551f30
but for
decoder plugins. This is tailored for the FFmpeg decoder plugin which
implements some protocols (e.g. RTSP) as demuxer plugin.
This commit is contained in:
parent
d3c257d97d
commit
85849c9396
|
@ -154,6 +154,10 @@ static void version()
|
|||
for (; *suffixes != nullptr; ++suffixes)
|
||||
printf(" %s", *suffixes);
|
||||
|
||||
if (plugin.protocols != nullptr)
|
||||
for (const auto &i : plugin.protocols())
|
||||
printf(" %s", i.c_str());
|
||||
|
||||
printf("\n");
|
||||
});
|
||||
|
||||
|
|
|
@ -18,10 +18,24 @@
|
|||
*/
|
||||
|
||||
#include "DecoderPlugin.hxx"
|
||||
#include "util/StringCompare.hxx"
|
||||
#include "util/StringUtil.hxx"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
|
||||
bool
|
||||
DecoderPlugin::SupportsUri(const char *uri) const noexcept
|
||||
{
|
||||
if (protocols != nullptr) {
|
||||
const auto p = protocols();
|
||||
return std::any_of(p.begin(), p.end(), [uri](const auto &schema)
|
||||
{ return StringStartsWithIgnoreCase(uri, schema.c_str()); } );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
DecoderPlugin::SupportsSuffix(const char *suffix) const noexcept
|
||||
{
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
#include "util/Compiler.h"
|
||||
|
||||
#include <forward_list> // IWYU pragma: export
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
struct ConfigBlock;
|
||||
class InputStream;
|
||||
|
@ -50,6 +52,16 @@ struct DecoderPlugin {
|
|||
*/
|
||||
void (*finish)() noexcept = nullptr;
|
||||
|
||||
/**
|
||||
* Return a set of supported protocols.
|
||||
*/
|
||||
std::set<std::string> (*protocols)() noexcept = nullptr;
|
||||
|
||||
/**
|
||||
* Decode an URI with a protocol listed in protocols().
|
||||
*/
|
||||
void (*uri_decode)(DecoderClient &client, const char *uri) = nullptr;
|
||||
|
||||
/**
|
||||
* Decode a stream (data read from an #InputStream object).
|
||||
*
|
||||
|
@ -143,6 +155,14 @@ struct DecoderPlugin {
|
|||
return copy;
|
||||
}
|
||||
|
||||
constexpr auto WithProtocols(std::set<std::string> (*_protocols)() noexcept,
|
||||
void (*_uri_decode)(DecoderClient &client, const char *uri)) noexcept {
|
||||
auto copy = *this;
|
||||
copy.protocols = _protocols;
|
||||
copy.uri_decode = _uri_decode;
|
||||
return copy;
|
||||
}
|
||||
|
||||
constexpr auto WithSuffixes(const char *const*_suffixes) noexcept {
|
||||
auto copy = *this;
|
||||
copy.suffixes = _suffixes;
|
||||
|
@ -183,6 +203,13 @@ struct DecoderPlugin {
|
|||
stream_decode(client, is);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode an URI which is supported (check SupportsUri()).
|
||||
*/
|
||||
void UriDecode(DecoderClient &client, const char *uri) const {
|
||||
uri_decode(client, uri);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode a file.
|
||||
*/
|
||||
|
@ -218,6 +245,9 @@ struct DecoderPlugin {
|
|||
return container_scan(path, tnum);
|
||||
}
|
||||
|
||||
gcc_pure
|
||||
bool SupportsUri(const char *uri) const noexcept;
|
||||
|
||||
/**
|
||||
* Does the plugin announce the specified file name suffix?
|
||||
*/
|
||||
|
|
|
@ -46,6 +46,42 @@
|
|||
|
||||
static constexpr Domain decoder_thread_domain("decoder_thread");
|
||||
|
||||
/**
|
||||
* Decode a URI with the given decoder plugin.
|
||||
*
|
||||
* Caller holds DecoderControl::mutex.
|
||||
*/
|
||||
static bool
|
||||
DecoderUriDecode(const DecoderPlugin &plugin,
|
||||
DecoderBridge &bridge, const char *uri)
|
||||
{
|
||||
assert(plugin.uri_decode != nullptr);
|
||||
assert(bridge.stream_tag == nullptr);
|
||||
assert(bridge.decoder_tag == nullptr);
|
||||
assert(uri != nullptr);
|
||||
assert(bridge.dc.state == DecoderState::START);
|
||||
|
||||
FormatDebug(decoder_thread_domain, "probing plugin %s", plugin.name);
|
||||
|
||||
if (bridge.dc.command == DecoderCommand::STOP)
|
||||
throw StopDecoder();
|
||||
|
||||
{
|
||||
const ScopeUnlock unlock(bridge.dc.mutex);
|
||||
|
||||
FormatThreadName("decoder:%s", plugin.name);
|
||||
|
||||
plugin.UriDecode(bridge, uri);
|
||||
|
||||
SetThreadName("decoder");
|
||||
}
|
||||
|
||||
assert(bridge.dc.state == DecoderState::START ||
|
||||
bridge.dc.state == DecoderState::DECODE);
|
||||
|
||||
return bridge.dc.state != DecoderState::START;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode a stream with the given decoder plugin.
|
||||
*
|
||||
|
@ -236,6 +272,24 @@ MaybeLoadReplayGain(DecoderBridge &bridge, InputStream &is)
|
|||
LoadReplayGain(bridge, is);
|
||||
}
|
||||
|
||||
/**
|
||||
* Try decoding a URI.
|
||||
*
|
||||
* DecoderControl::mutex is not be locked by caller.
|
||||
*/
|
||||
static bool
|
||||
TryUriDecode(DecoderBridge &bridge, const char *uri)
|
||||
{
|
||||
return decoder_plugins_try([&bridge, uri](const DecoderPlugin &plugin){
|
||||
if (!plugin.SupportsUri(uri))
|
||||
return false;
|
||||
|
||||
std::unique_lock<Mutex> lock(bridge.dc.mutex);
|
||||
bridge.Reset();
|
||||
return DecoderUriDecode(plugin, bridge, uri);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Try decoding a stream.
|
||||
*
|
||||
|
@ -244,6 +298,9 @@ MaybeLoadReplayGain(DecoderBridge &bridge, InputStream &is)
|
|||
static bool
|
||||
decoder_run_stream(DecoderBridge &bridge, const char *uri)
|
||||
{
|
||||
if (TryUriDecode(bridge, uri))
|
||||
return true;
|
||||
|
||||
DecoderControl &dc = bridge.dc;
|
||||
|
||||
auto input_stream = bridge.OpenUri(uri);
|
||||
|
|
16
src/ls.cxx
16
src/ls.cxx
|
@ -21,6 +21,8 @@
|
|||
#include "ls.hxx"
|
||||
#include "input/Registry.hxx"
|
||||
#include "input/InputPlugin.hxx"
|
||||
#include "decoder/DecoderList.hxx"
|
||||
#include "decoder/DecoderPlugin.hxx"
|
||||
#include "client/Response.hxx"
|
||||
#include "util/UriExtract.hxx"
|
||||
|
||||
|
@ -39,6 +41,11 @@ void print_supported_uri_schemes_to_fp(FILE *fp)
|
|||
protocols.emplace(uri);
|
||||
});
|
||||
|
||||
decoder_plugins_for_each([&protocols](const auto &plugin){
|
||||
if (plugin.protocols != nullptr)
|
||||
protocols.merge(plugin.protocols());
|
||||
});
|
||||
|
||||
for (const auto& protocol : protocols) {
|
||||
fprintf(fp, " %s", protocol.c_str());
|
||||
}
|
||||
|
@ -54,6 +61,11 @@ print_supported_uri_schemes(Response &r)
|
|||
protocols.emplace(uri);
|
||||
});
|
||||
|
||||
decoder_plugins_for_each_enabled([&protocols](const auto &plugin){
|
||||
if (plugin.protocols != nullptr)
|
||||
protocols.merge(plugin.protocols());
|
||||
});
|
||||
|
||||
for (const auto& protocol : protocols) {
|
||||
r.Format("handler: %s\n", protocol.c_str());
|
||||
}
|
||||
|
@ -68,5 +80,7 @@ uri_supported_scheme(const char *uri) noexcept
|
|||
if (plugin->SupportsUri(uri))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
return decoder_plugins_try([uri](const auto &plugin){
|
||||
return plugin.SupportsUri(uri);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -204,7 +204,12 @@ try {
|
|||
}
|
||||
|
||||
MyDecoderClient client(c.seek_where);
|
||||
if (plugin->file_decode != nullptr) {
|
||||
if (plugin->SupportsUri(c.uri)) {
|
||||
try {
|
||||
plugin->UriDecode(client, c.uri);
|
||||
} catch (StopDecoder) {
|
||||
}
|
||||
} else if (plugin->file_decode != nullptr) {
|
||||
try {
|
||||
plugin->FileDecode(client, FromNarrowPath(c.uri));
|
||||
} catch (StopDecoder) {
|
||||
|
|
Loading…
Reference in New Issue