decklink start up to separate factory
This commit is contained in:
@@ -1,13 +1,11 @@
|
||||
#include "app/AppConfig.h"
|
||||
#include "app/AppConfigProvider.h"
|
||||
#include "app/RenderCadenceApp.h"
|
||||
#include "app/VideoBackendFactory.h"
|
||||
#include "frames/InputFrameMailbox.h"
|
||||
#include "frames/SystemFrameExchange.h"
|
||||
#include "logging/Logger.h"
|
||||
#include "render/thread/RenderThread.h"
|
||||
#include "video/decklink/DeckLinkInput.h"
|
||||
#include "video/decklink/DeckLinkInputThread.h"
|
||||
#include "video/decklink/DeckLinkDisplayMode.h"
|
||||
#include "video/core/VideoIOFormat.h"
|
||||
#include "video/core/VideoMode.h"
|
||||
|
||||
@@ -17,7 +15,6 @@
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
namespace
|
||||
{
|
||||
@@ -49,18 +46,6 @@ private:
|
||||
HRESULT mResult = S_OK;
|
||||
};
|
||||
|
||||
bool WaitForInputWarmup(InputFrameMailbox& mailbox, std::size_t targetReadyFrames, std::chrono::milliseconds timeout)
|
||||
{
|
||||
const auto start = std::chrono::steady_clock::now();
|
||||
while (std::chrono::steady_clock::now() - start < timeout)
|
||||
{
|
||||
const InputFrameMailboxMetrics metrics = mailbox.Metrics();
|
||||
if (metrics.readyCount >= targetReadyFrames)
|
||||
return true;
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(2));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
@@ -80,11 +65,11 @@ int main(int argc, char** argv)
|
||||
RenderCadenceCompositor::Logger::Instance().Start(appConfig.logging);
|
||||
RenderCadenceCompositor::Log(
|
||||
"app",
|
||||
"RenderCadenceCompositor starting. Starts render cadence, system-memory exchange, DeckLink scheduled output, and telemetry. Press Enter to stop.");
|
||||
"RenderCadenceCompositor starting. Starts render cadence, configured video I/O backends, and telemetry. Press Enter to stop.");
|
||||
RenderCadenceCompositor::Log("app", "Loaded config from " + configProvider.SourcePath().string());
|
||||
|
||||
ComInitGuard com;
|
||||
if (!com.Initialize())
|
||||
if (RenderCadenceCompositor::VideoBackendsRequireCom(appConfig) && !com.Initialize())
|
||||
{
|
||||
std::ostringstream message;
|
||||
message << "COM initialization failed: 0x" << std::hex << com.Result();
|
||||
@@ -126,7 +111,7 @@ int main(int argc, char** argv)
|
||||
const bool outputVideoModeResolved = ResolveConfiguredVideoFormat(appConfig.outputVideoFormat, appConfig.outputFrameRate, outputVideoMode);
|
||||
if (!inputVideoModeResolved)
|
||||
{
|
||||
inputVideoModeError = "Unsupported DeckLink inputVideoFormat/inputFrameRate in config/runtime-host.json: " +
|
||||
inputVideoModeError = "Unsupported inputVideoFormat/inputFrameRate in config/runtime-host.json: " +
|
||||
appConfig.inputVideoFormat + " / " + appConfig.inputFrameRate;
|
||||
RenderCadenceCompositor::LogWarning("app", inputVideoModeError);
|
||||
}
|
||||
@@ -134,7 +119,7 @@ int main(int argc, char** argv)
|
||||
{
|
||||
RenderCadenceCompositor::LogWarning(
|
||||
"app",
|
||||
"Unsupported DeckLink outputVideoFormat/outputFrameRate in config/runtime-host.json; render cadence will use parsed frame-rate fallback: " +
|
||||
"Unsupported outputVideoFormat/outputFrameRate in config/runtime-host.json; render cadence will use parsed frame-rate fallback: " +
|
||||
appConfig.outputVideoFormat + " / " + appConfig.outputFrameRate);
|
||||
}
|
||||
else
|
||||
@@ -142,55 +127,12 @@ int main(int argc, char** argv)
|
||||
appConfig.deckLink.outputVideoMode = outputVideoMode;
|
||||
}
|
||||
|
||||
RenderCadenceCompositor::DeckLinkInput deckLinkInput(inputMailbox);
|
||||
RenderCadenceCompositor::DeckLinkInputThread deckLinkInputThread(deckLinkInput);
|
||||
bool deckLinkInputStarted = false;
|
||||
if (inputVideoModeResolved)
|
||||
{
|
||||
RenderCadenceCompositor::DeckLinkInputConfig deckLinkInputConfig;
|
||||
deckLinkInputConfig.videoFormat = inputVideoMode;
|
||||
std::string deckLinkInputError;
|
||||
if (deckLinkInput.Initialize(deckLinkInputConfig, deckLinkInputError))
|
||||
{
|
||||
inputMailboxConfig.pixelFormat = deckLinkInput.CapturePixelFormat();
|
||||
inputMailboxConfig.rowBytes = VideoIORowBytes(inputMailboxConfig.pixelFormat, inputMailboxConfig.width);
|
||||
inputMailbox.Configure(inputMailboxConfig);
|
||||
}
|
||||
|
||||
if (deckLinkInput.IsInitialized() && deckLinkInputThread.Start(deckLinkInputError))
|
||||
{
|
||||
deckLinkInputStarted = true;
|
||||
RenderCadenceCompositor::Log("app", "DeckLink input edge started for " + inputVideoMode.displayName + ".");
|
||||
RenderCadenceCompositor::Log("app", "Waiting for DeckLink input warmup frames.");
|
||||
constexpr std::size_t kInputStartupBufferedFrames = 3;
|
||||
constexpr std::chrono::milliseconds kInputWarmupTimeout(1000);
|
||||
if (WaitForInputWarmup(inputMailbox, kInputStartupBufferedFrames, kInputWarmupTimeout))
|
||||
{
|
||||
const InputFrameMailboxMetrics metrics = inputMailbox.Metrics();
|
||||
RenderCadenceCompositor::Log(
|
||||
"app",
|
||||
"DeckLink input warmup complete. ready=" + std::to_string(metrics.readyCount) +
|
||||
" submitted=" + std::to_string(metrics.submittedFrames) + ".");
|
||||
}
|
||||
else
|
||||
{
|
||||
const InputFrameMailboxMetrics metrics = inputMailbox.Metrics();
|
||||
RenderCadenceCompositor::LogWarning(
|
||||
"app",
|
||||
"DeckLink input warmup timed out; starting render cadence with current input buffer. ready=" +
|
||||
std::to_string(metrics.readyCount) + " submitted=" + std::to_string(metrics.submittedFrames) + ".");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RenderCadenceCompositor::LogWarning("app", "DeckLink input edge unavailable; runtime shaders will use fallback input until a real input edge is available. " + deckLinkInputError);
|
||||
deckLinkInput.ReleaseResources();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RenderCadenceCompositor::LogWarning("app", "DeckLink input mode was not resolved; runtime shaders will use fallback input until a real input edge is available.");
|
||||
}
|
||||
auto inputBackend = RenderCadenceCompositor::StartVideoInputBackend(
|
||||
appConfig,
|
||||
inputMailbox,
|
||||
inputMailboxConfig,
|
||||
inputVideoMode,
|
||||
inputVideoModeResolved);
|
||||
|
||||
RenderThread::Config renderConfig;
|
||||
renderConfig.width = frameExchangeConfig.width;
|
||||
@@ -203,17 +145,22 @@ int main(int argc, char** argv)
|
||||
|
||||
RenderThread renderThread(frameExchange, &inputMailbox, renderConfig);
|
||||
|
||||
RenderCadenceCompositor::RenderCadenceApp<RenderThread, SystemFrameExchange> app(renderThread, frameExchange, appConfig);
|
||||
app.SetVideoInputMetricsProvider([&deckLinkInput]() {
|
||||
return deckLinkInput.Metrics();
|
||||
auto outputBackend = RenderCadenceCompositor::CreateVideoOutputBackend(appConfig);
|
||||
RenderCadenceCompositor::RenderCadenceApp<RenderThread, SystemFrameExchange> app(
|
||||
renderThread,
|
||||
frameExchange,
|
||||
appConfig,
|
||||
std::move(outputBackend));
|
||||
app.SetVideoInputMetricsProvider([inputBackend = inputBackend.get()]() {
|
||||
return inputBackend ? inputBackend->Metrics() : RenderCadenceCompositor::VideoInputEdgeMetrics();
|
||||
});
|
||||
|
||||
std::string error;
|
||||
if (!app.Start(error))
|
||||
{
|
||||
RenderCadenceCompositor::LogError("app", "RenderCadenceCompositor start failed: " + error);
|
||||
if (deckLinkInputStarted)
|
||||
deckLinkInputThread.Stop();
|
||||
if (inputBackend)
|
||||
inputBackend->Stop();
|
||||
RenderCadenceCompositor::Logger::Instance().Stop();
|
||||
return 1;
|
||||
}
|
||||
@@ -221,8 +168,8 @@ int main(int argc, char** argv)
|
||||
std::string line;
|
||||
std::getline(std::cin, line);
|
||||
app.Stop();
|
||||
if (deckLinkInputStarted)
|
||||
deckLinkInputThread.Stop();
|
||||
if (inputBackend)
|
||||
inputBackend->Stop();
|
||||
RenderCadenceCompositor::Log("app", "RenderCadenceCompositor stopped.");
|
||||
RenderCadenceCompositor::Logger::Instance().Stop();
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user