#include "app/AppConfig.h" #include "app/AppConfigProvider.h" #include "app/RenderCadenceApp.h" #include "frames/InputFrameMailbox.h" #include "frames/SystemFrameExchange.h" #include "logging/Logger.h" #include "render/RenderThread.h" #include "video/SyntheticInputProducer.h" #include "VideoIOFormat.h" #include #include #include #include namespace { class ComInitGuard { public: ~ComInitGuard() { if (mInitialized) CoUninitialize(); } bool Initialize() { const HRESULT result = CoInitialize(nullptr); mInitialized = SUCCEEDED(result); mResult = result; return mInitialized; } HRESULT Result() const { return mResult; } private: bool mInitialized = false; HRESULT mResult = S_OK; }; } int main(int argc, char** argv) { RenderCadenceCompositor::AppConfigProvider configProvider; std::string configError; if (!configProvider.LoadDefault(configError)) { RenderCadenceCompositor::Logger::Instance().Start(RenderCadenceCompositor::DefaultAppConfig().logging); RenderCadenceCompositor::LogError("app", "Config load failed: " + configError); RenderCadenceCompositor::Logger::Instance().Stop(); return 1; } configProvider.ApplyCommandLine(argc, argv); RenderCadenceCompositor::AppConfig appConfig = configProvider.Config(); 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::Log("app", "Loaded config from " + configProvider.SourcePath().string()); ComInitGuard com; if (!com.Initialize()) { std::ostringstream message; message << "COM initialization failed: 0x" << std::hex << com.Result(); RenderCadenceCompositor::LogError("app", message.str()); RenderCadenceCompositor::Logger::Instance().Stop(); return 1; } SystemFrameExchangeConfig frameExchangeConfig; RenderCadenceCompositor::VideoFormatDimensions( appConfig.outputVideoFormat, frameExchangeConfig.width, frameExchangeConfig.height); frameExchangeConfig.pixelFormat = VideoIOPixelFormat::Bgra8; frameExchangeConfig.rowBytes = VideoIORowBytes(frameExchangeConfig.pixelFormat, frameExchangeConfig.width); frameExchangeConfig.capacity = 12; SystemFrameExchange frameExchange(frameExchangeConfig); InputFrameMailboxConfig inputMailboxConfig; RenderCadenceCompositor::VideoFormatDimensions( appConfig.inputVideoFormat, inputMailboxConfig.width, inputMailboxConfig.height); inputMailboxConfig.pixelFormat = VideoIOPixelFormat::Bgra8; inputMailboxConfig.rowBytes = VideoIORowBytes(inputMailboxConfig.pixelFormat, inputMailboxConfig.width); inputMailboxConfig.capacity = 4; InputFrameMailbox inputMailbox(inputMailboxConfig); RenderCadenceCompositor::SyntheticInputProducerConfig inputProducerConfig; inputProducerConfig.width = inputMailboxConfig.width; inputProducerConfig.height = inputMailboxConfig.height; inputProducerConfig.frameDurationMilliseconds = RenderCadenceCompositor::FrameDurationMillisecondsFromRateString(appConfig.inputFrameRate); RenderCadenceCompositor::SyntheticInputProducer syntheticInput(inputMailbox, inputProducerConfig); if (syntheticInput.Start()) RenderCadenceCompositor::Log("app", "Synthetic BGRA8 input producer started."); else RenderCadenceCompositor::LogWarning("app", "Synthetic input producer did not start; shaders will use fallback input."); RenderThread::Config renderConfig; renderConfig.width = frameExchangeConfig.width; renderConfig.height = frameExchangeConfig.height; renderConfig.frameDurationMilliseconds = RenderCadenceCompositor::FrameDurationMillisecondsFromRateString(appConfig.outputFrameRate); renderConfig.pboDepth = 6; RenderThread renderThread(frameExchange, &inputMailbox, renderConfig); RenderCadenceCompositor::RenderCadenceApp app(renderThread, frameExchange, appConfig); std::string error; if (!app.Start(error)) { RenderCadenceCompositor::LogError("app", "RenderCadenceCompositor start failed: " + error); syntheticInput.Stop(); RenderCadenceCompositor::Logger::Instance().Stop(); return 1; } std::string line; std::getline(std::cin, line); app.Stop(); syntheticInput.Stop(); RenderCadenceCompositor::Log("app", "RenderCadenceCompositor stopped."); RenderCadenceCompositor::Logger::Instance().Stop(); return 0; }