Update VideoBackendFactory.cpp
This commit is contained in:
@@ -7,9 +7,13 @@
|
||||
#include "video/decklink/DeckLinkOutput.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string_view>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
namespace RenderCadenceCompositor
|
||||
{
|
||||
@@ -26,15 +30,9 @@ std::string NormalizeBackendName(std::string name)
|
||||
return name;
|
||||
}
|
||||
|
||||
bool IsDeckLinkBackend(const std::string& name)
|
||||
bool BackendNameMatches(std::string_view normalizedName, const std::vector<std::string_view>& aliases)
|
||||
{
|
||||
return NormalizeBackendName(name) == "decklink";
|
||||
}
|
||||
|
||||
bool IsNoneBackend(const std::string& name)
|
||||
{
|
||||
const std::string normalized = NormalizeBackendName(name);
|
||||
return normalized == "none" || normalized == "disabled" || normalized == "off";
|
||||
return std::find(aliases.begin(), aliases.end(), normalizedName) != aliases.end();
|
||||
}
|
||||
|
||||
bool WaitForInputWarmup(InputFrameMailbox& mailbox, std::size_t targetReadyFrames, std::chrono::milliseconds timeout)
|
||||
@@ -50,6 +48,32 @@ bool WaitForInputWarmup(InputFrameMailbox& mailbox, std::size_t targetReadyFrame
|
||||
return false;
|
||||
}
|
||||
|
||||
struct VideoInputBackendStartContext
|
||||
{
|
||||
const AppConfig& config;
|
||||
InputFrameMailbox& mailbox;
|
||||
InputFrameMailboxConfig& mailboxConfig;
|
||||
const VideoFormat& inputVideoMode;
|
||||
bool inputVideoModeResolved = false;
|
||||
};
|
||||
|
||||
using VideoOutputBackendCreateFn = std::unique_ptr<IVideoOutputEdge> (*)();
|
||||
using VideoInputBackendStartFn = std::unique_ptr<VideoInputBackendSession> (*)(const VideoInputBackendStartContext&);
|
||||
|
||||
struct VideoOutputBackendRegistration
|
||||
{
|
||||
std::vector<std::string_view> aliases;
|
||||
bool requiresCom = false;
|
||||
VideoOutputBackendCreateFn create = nullptr;
|
||||
};
|
||||
|
||||
struct VideoInputBackendRegistration
|
||||
{
|
||||
std::vector<std::string_view> aliases;
|
||||
bool requiresCom = false;
|
||||
VideoInputBackendStartFn start = nullptr;
|
||||
};
|
||||
|
||||
class DisabledVideoOutputEdge final : public IVideoOutputEdge
|
||||
{
|
||||
public:
|
||||
@@ -174,20 +198,95 @@ private:
|
||||
DeckLinkInputThread mThread;
|
||||
bool mStarted = false;
|
||||
};
|
||||
|
||||
std::unique_ptr<IVideoOutputEdge> CreateDeckLinkOutputBackend()
|
||||
{
|
||||
return std::make_unique<DeckLinkOutput>();
|
||||
}
|
||||
|
||||
std::unique_ptr<IVideoOutputEdge> CreateDisabledOutputBackend()
|
||||
{
|
||||
return std::make_unique<DisabledVideoOutputEdge>("Video output backend is disabled by config.");
|
||||
}
|
||||
|
||||
std::unique_ptr<VideoInputBackendSession> StartNoInputBackend(const VideoInputBackendStartContext&)
|
||||
{
|
||||
Log("app", "Video input backend disabled by config.");
|
||||
return std::make_unique<NoInputBackendSession>("none");
|
||||
}
|
||||
|
||||
std::unique_ptr<VideoInputBackendSession> StartDeckLinkInputBackend(const VideoInputBackendStartContext& context)
|
||||
{
|
||||
if (!context.inputVideoModeResolved)
|
||||
{
|
||||
LogWarning("app", "DeckLink input mode was not resolved; runtime shaders will use fallback input until a real input edge is available.");
|
||||
return std::make_unique<NoInputBackendSession>("decklink");
|
||||
}
|
||||
|
||||
auto session = std::make_unique<DeckLinkInputBackendSession>(context.mailbox);
|
||||
std::string error;
|
||||
if (!session->Start(context.mailbox, context.mailboxConfig, context.inputVideoMode, error))
|
||||
{
|
||||
LogWarning("app", "DeckLink input edge unavailable; runtime shaders will use fallback input until a real input edge is available. " + error);
|
||||
return std::make_unique<NoInputBackendSession>("decklink");
|
||||
}
|
||||
return session;
|
||||
}
|
||||
|
||||
const std::vector<VideoOutputBackendRegistration>& VideoOutputBackendRegistry()
|
||||
{
|
||||
static const std::vector<VideoOutputBackendRegistration> registry = {
|
||||
VideoOutputBackendRegistration{ { "decklink" }, true, &CreateDeckLinkOutputBackend },
|
||||
VideoOutputBackendRegistration{ { "none", "disabled", "off" }, false, &CreateDisabledOutputBackend },
|
||||
};
|
||||
return registry;
|
||||
}
|
||||
|
||||
const std::vector<VideoInputBackendRegistration>& VideoInputBackendRegistry()
|
||||
{
|
||||
static const std::vector<VideoInputBackendRegistration> registry = {
|
||||
VideoInputBackendRegistration{ { "decklink" }, true, &StartDeckLinkInputBackend },
|
||||
VideoInputBackendRegistration{ { "none", "disabled", "off" }, false, &StartNoInputBackend },
|
||||
};
|
||||
return registry;
|
||||
}
|
||||
|
||||
const VideoOutputBackendRegistration* FindVideoOutputBackend(std::string_view backendName)
|
||||
{
|
||||
for (const VideoOutputBackendRegistration& backend : VideoOutputBackendRegistry())
|
||||
{
|
||||
if (BackendNameMatches(backendName, backend.aliases))
|
||||
return &backend;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const VideoInputBackendRegistration* FindVideoInputBackend(std::string_view backendName)
|
||||
{
|
||||
for (const VideoInputBackendRegistration& backend : VideoInputBackendRegistry())
|
||||
{
|
||||
if (BackendNameMatches(backendName, backend.aliases))
|
||||
return &backend;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool VideoBackendsRequireCom(const AppConfig& config)
|
||||
{
|
||||
return IsDeckLinkBackend(config.videoInputBackend) || IsDeckLinkBackend(config.videoOutputBackend);
|
||||
const std::string inputBackend = NormalizeBackendName(config.videoInputBackend);
|
||||
const std::string outputBackend = NormalizeBackendName(config.videoOutputBackend);
|
||||
const VideoInputBackendRegistration* input = FindVideoInputBackend(inputBackend);
|
||||
const VideoOutputBackendRegistration* output = FindVideoOutputBackend(outputBackend);
|
||||
return (input != nullptr && input->requiresCom) || (output != nullptr && output->requiresCom);
|
||||
}
|
||||
|
||||
std::unique_ptr<IVideoOutputEdge> CreateVideoOutputBackend(const AppConfig& config)
|
||||
{
|
||||
if (IsDeckLinkBackend(config.videoOutputBackend))
|
||||
return std::make_unique<DeckLinkOutput>();
|
||||
|
||||
if (IsNoneBackend(config.videoOutputBackend))
|
||||
return std::make_unique<DisabledVideoOutputEdge>("Video output backend is disabled by config.");
|
||||
const std::string backendName = NormalizeBackendName(config.videoOutputBackend);
|
||||
const VideoOutputBackendRegistration* backend = FindVideoOutputBackend(backendName);
|
||||
if (backend != nullptr && backend->create != nullptr)
|
||||
return backend->create();
|
||||
|
||||
return std::make_unique<DisabledVideoOutputEdge>("Unsupported videoOutputBackend: " + config.videoOutputBackend);
|
||||
}
|
||||
@@ -199,31 +298,15 @@ std::unique_ptr<VideoInputBackendSession> StartVideoInputBackend(
|
||||
const VideoFormat& inputVideoMode,
|
||||
bool inputVideoModeResolved)
|
||||
{
|
||||
if (IsNoneBackend(config.videoInputBackend))
|
||||
const std::string backendName = NormalizeBackendName(config.videoInputBackend);
|
||||
const VideoInputBackendRegistration* backend = FindVideoInputBackend(backendName);
|
||||
if (backend != nullptr && backend->start != nullptr)
|
||||
{
|
||||
Log("app", "Video input backend disabled by config.");
|
||||
return std::make_unique<NoInputBackendSession>("none");
|
||||
VideoInputBackendStartContext context{ config, mailbox, mailboxConfig, inputVideoMode, inputVideoModeResolved };
|
||||
return backend->start(context);
|
||||
}
|
||||
|
||||
if (!IsDeckLinkBackend(config.videoInputBackend))
|
||||
{
|
||||
LogWarning("app", "Unsupported videoInputBackend '" + config.videoInputBackend + "'; runtime shaders will use fallback input.");
|
||||
return std::make_unique<NoInputBackendSession>(config.videoInputBackend);
|
||||
}
|
||||
|
||||
if (!inputVideoModeResolved)
|
||||
{
|
||||
LogWarning("app", "DeckLink input mode was not resolved; runtime shaders will use fallback input until a real input edge is available.");
|
||||
return std::make_unique<NoInputBackendSession>("decklink");
|
||||
}
|
||||
|
||||
auto session = std::make_unique<DeckLinkInputBackendSession>(mailbox);
|
||||
std::string error;
|
||||
if (!session->Start(mailbox, mailboxConfig, inputVideoMode, error))
|
||||
{
|
||||
LogWarning("app", "DeckLink input edge unavailable; runtime shaders will use fallback input until a real input edge is available. " + error);
|
||||
return std::make_unique<NoInputBackendSession>("decklink");
|
||||
}
|
||||
return session;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user