Clean up pass
All checks were successful
CI / React UI Build (push) Successful in 11s
CI / Native Windows Build And Tests (push) Successful in 2m55s
CI / Windows Release Package (push) Successful in 3m14s

This commit is contained in:
Aiden
2026-05-12 13:14:52 +10:00
parent 9938a6cc26
commit bc690e2a87
13 changed files with 417 additions and 220 deletions

View File

@@ -1,12 +1,10 @@
#pragma once
#include "AppConfig.h"
#include "AppConfigProvider.h"
#include "../json/JsonWriter.h"
#include "../logging/Logger.h"
#include "../runtime/RuntimeShaderBridge.h"
#include "../telemetry/CadenceTelemetryJson.h"
#include "../telemetry/TelemetryPrinter.h"
#include "../control/RuntimeStateJson.h"
#include "../telemetry/TelemetryHealthMonitor.h"
#include "../video/DeckLinkOutput.h"
#include "../video/DeckLinkOutputThread.h"
@@ -55,7 +53,7 @@ public:
mFrameExchange(frameExchange),
mConfig(config),
mOutputThread(mOutput, mFrameExchange, mConfig.outputThread),
mTelemetry(mConfig.telemetry)
mTelemetryHealth(mConfig.telemetry)
{
}
@@ -69,18 +67,6 @@ public:
bool Start(std::string& error)
{
Log("app", "Initializing DeckLink output.");
if (!mOutput.Initialize(
mConfig.deckLink,
[this](const VideoIOCompletion& completion) {
mFrameExchange.ReleaseScheduledByBytes(completion.outputFrameBuffer);
},
error))
{
LogError("app", "DeckLink output initialization failed: " + error);
return false;
}
Log("app", "Starting render thread.");
if (!detail::StartRenderThread(mRenderThread, error, 0))
{
@@ -99,33 +85,8 @@ public:
return false;
}
Log("app", "Starting DeckLink output thread.");
if (!mOutputThread.Start())
{
error = "DeckLink output thread failed to start.";
LogError("app", error);
Stop();
return false;
}
Log("app", "Waiting for DeckLink preroll frames.");
if (!WaitForPreroll())
{
error = "Timed out waiting for DeckLink preroll frames.";
LogError("app", error);
Stop();
return false;
}
Log("app", "Starting DeckLink scheduled playback.");
if (!mOutput.StartScheduledPlayback(error))
{
LogError("app", "DeckLink scheduled playback failed: " + error);
Stop();
return false;
}
mTelemetry.Start(mFrameExchange, mOutput, mOutputThread, mRenderThread);
StartOptionalVideoOutput();
mTelemetryHealth.Start(mFrameExchange, mOutput, mOutputThread, mRenderThread);
StartHttpServer();
Log("app", "RenderCadenceCompositor started.");
mStarted = true;
@@ -135,7 +96,7 @@ public:
void Stop()
{
mHttpServer.Stop();
mTelemetry.Stop();
mTelemetryHealth.Stop();
mOutputThread.Stop();
mOutput.Stop();
StopRuntimeShaderBuild();
@@ -150,6 +111,58 @@ public:
const DeckLinkOutput& Output() const { return mOutput; }
private:
void StartOptionalVideoOutput()
{
std::string outputError;
Log("app", "Initializing optional DeckLink output.");
if (!mOutput.Initialize(
mConfig.deckLink,
[this](const VideoIOCompletion& completion) {
mFrameExchange.ReleaseScheduledByBytes(completion.outputFrameBuffer);
},
outputError))
{
DisableVideoOutput("DeckLink output unavailable: " + outputError);
return;
}
Log("app", "Starting DeckLink output thread.");
if (!mOutputThread.Start())
{
DisableVideoOutput("DeckLink output thread failed to start.");
return;
}
Log("app", "Waiting for DeckLink preroll frames.");
if (!WaitForPreroll())
{
DisableVideoOutput("Timed out waiting for DeckLink preroll frames.");
return;
}
Log("app", "Starting DeckLink scheduled playback.");
if (!mOutput.StartScheduledPlayback(outputError))
{
DisableVideoOutput("DeckLink scheduled playback failed: " + outputError);
return;
}
mVideoOutputEnabled = true;
mVideoOutputStatus = "DeckLink scheduled output running.";
Log("app", mVideoOutputStatus);
}
void DisableVideoOutput(const std::string& reason)
{
mOutputThread.Stop();
mOutput.Stop();
mOutput.ReleaseResources();
mFrameExchange.Clear();
mVideoOutputEnabled = false;
mVideoOutputStatus = reason;
LogWarning("app", reason + " Continuing without video output.");
}
void StartHttpServer()
{
HttpControlServerCallbacks callbacks;
@@ -168,65 +181,13 @@ private:
std::string BuildStateJson()
{
CadenceTelemetrySnapshot telemetry = mHttpTelemetry.Sample(mFrameExchange, mOutput, mOutputThread, mRenderThread);
JsonWriter writer;
writer.BeginObject();
writer.Key("app");
writer.BeginObject();
writer.KeyUInt("serverPort", mHttpServer.Port());
writer.KeyUInt("oscPort", mConfig.oscPort);
writer.KeyString("oscBindAddress", mConfig.oscBindAddress);
writer.KeyDouble("oscSmoothing", mConfig.oscSmoothing);
writer.KeyBool("autoReload", mConfig.autoReload);
writer.KeyUInt("maxTemporalHistoryFrames", static_cast<uint64_t>(mConfig.maxTemporalHistoryFrames));
writer.KeyDouble("previewFps", mConfig.previewFps);
writer.KeyBool("enableExternalKeying", mConfig.deckLink.externalKeyingEnabled);
writer.KeyString("inputVideoFormat", mConfig.inputVideoFormat);
writer.KeyString("inputFrameRate", mConfig.inputFrameRate);
writer.KeyString("outputVideoFormat", mConfig.outputVideoFormat);
writer.KeyString("outputFrameRate", mConfig.outputFrameRate);
writer.EndObject();
writer.Key("runtime");
writer.BeginObject();
writer.KeyUInt("layerCount", 0);
writer.KeyBool("compileSucceeded", true);
writer.KeyString("compileMessage", "Runtime state is not ported into RenderCadenceCompositor yet.");
writer.EndObject();
writer.KeyNull("video");
writer.KeyNull("decklink");
writer.KeyNull("videoIO");
writer.Key("performance");
writer.BeginObject();
writer.KeyDouble("frameBudgetMs", FrameDurationMillisecondsFromRateString(mConfig.outputFrameRate));
writer.KeyNull("renderMs");
writer.KeyNull("smoothedRenderMs");
writer.KeyNull("budgetUsedPercent");
writer.KeyNull("completionIntervalMs");
writer.KeyNull("smoothedCompletionIntervalMs");
writer.KeyNull("maxCompletionIntervalMs");
writer.KeyUInt("lateFrameCount", telemetry.displayedLate);
writer.KeyUInt("droppedFrameCount", telemetry.dropped);
writer.KeyNull("flushedFrameCount");
writer.Key("cadence");
WriteCadenceTelemetryJson(writer, telemetry);
writer.EndObject();
writer.KeyNull("backendPlayout");
writer.KeyNull("runtimeEvents");
writer.Key("shaders");
writer.BeginArray();
writer.EndArray();
writer.Key("stackPresets");
writer.BeginArray();
writer.EndArray();
writer.Key("layers");
writer.BeginArray();
writer.EndArray();
writer.EndObject();
return writer.StringValue();
return RuntimeStateToJson(RuntimeStateJsonInput{
mConfig,
telemetry,
mHttpServer.Port(),
mVideoOutputEnabled,
mVideoOutputStatus
});
}
bool WaitForPreroll() const
@@ -270,10 +231,12 @@ private:
AppConfig mConfig;
DeckLinkOutput mOutput;
DeckLinkOutputThread<SystemFrameExchange> mOutputThread;
TelemetryPrinter mTelemetry;
TelemetryHealthMonitor mTelemetryHealth;
CadenceTelemetry mHttpTelemetry;
HttpControlServer mHttpServer;
RuntimeShaderBridge mShaderBridge;
bool mStarted = false;
bool mVideoOutputEnabled = false;
std::string mVideoOutputStatus = "DeckLink output not started.";
};
}