Health
This commit is contained in:
@@ -202,7 +202,7 @@ void OpenGLComposite::PublishVideoIOStatus(const std::string& statusMessage)
|
||||
if (!statusMessage.empty())
|
||||
mVideoBackend->SetStatusMessage(statusMessage);
|
||||
|
||||
mRuntimeHost->SetVideoIOStatus(
|
||||
mRuntimeHost->GetHealthTelemetry().ReportVideoIOStatus(
|
||||
"decklink",
|
||||
mVideoBackend->OutputModelName(),
|
||||
mVideoBackend->SupportsInternalKeying(),
|
||||
|
||||
@@ -1,43 +1,141 @@
|
||||
#include "stdafx.h"
|
||||
#include "HealthTelemetry.h"
|
||||
|
||||
#include "RuntimeHost.h"
|
||||
|
||||
HealthTelemetry::HealthTelemetry(RuntimeHost& runtimeHost) :
|
||||
mRuntimeHost(runtimeHost)
|
||||
{
|
||||
}
|
||||
|
||||
void HealthTelemetry::ReportSignalStatus(bool hasSignal, unsigned width, unsigned height, const std::string& modeName)
|
||||
{
|
||||
mRuntimeHost.WriteSignalStatus(hasSignal, width, height, modeName);
|
||||
std::lock_guard<std::mutex> lock(mMutex);
|
||||
mSignalStatus.hasSignal = hasSignal;
|
||||
mSignalStatus.width = width;
|
||||
mSignalStatus.height = height;
|
||||
mSignalStatus.modeName = modeName;
|
||||
}
|
||||
|
||||
bool HealthTelemetry::TryReportSignalStatus(bool hasSignal, unsigned width, unsigned height, const std::string& modeName)
|
||||
{
|
||||
return mRuntimeHost.TryWriteSignalStatus(hasSignal, width, height, modeName);
|
||||
std::unique_lock<std::mutex> lock(mMutex, std::try_to_lock);
|
||||
if (!lock.owns_lock())
|
||||
return false;
|
||||
|
||||
mSignalStatus.hasSignal = hasSignal;
|
||||
mSignalStatus.width = width;
|
||||
mSignalStatus.height = height;
|
||||
mSignalStatus.modeName = modeName;
|
||||
return true;
|
||||
}
|
||||
|
||||
void HealthTelemetry::ReportVideoIOStatus(const std::string& backendName, const std::string& modelName,
|
||||
bool supportsInternalKeying, bool supportsExternalKeying, bool keyerInterfaceAvailable,
|
||||
bool externalKeyingRequested, bool externalKeyingActive, const std::string& statusMessage)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mMutex);
|
||||
mVideoIOStatus.backendName = backendName;
|
||||
mVideoIOStatus.modelName = modelName;
|
||||
mVideoIOStatus.supportsInternalKeying = supportsInternalKeying;
|
||||
mVideoIOStatus.supportsExternalKeying = supportsExternalKeying;
|
||||
mVideoIOStatus.keyerInterfaceAvailable = keyerInterfaceAvailable;
|
||||
mVideoIOStatus.externalKeyingRequested = externalKeyingRequested;
|
||||
mVideoIOStatus.externalKeyingActive = externalKeyingActive;
|
||||
mVideoIOStatus.statusMessage = statusMessage;
|
||||
}
|
||||
|
||||
bool HealthTelemetry::TryReportVideoIOStatus(const std::string& backendName, const std::string& modelName,
|
||||
bool supportsInternalKeying, bool supportsExternalKeying, bool keyerInterfaceAvailable,
|
||||
bool externalKeyingRequested, bool externalKeyingActive, const std::string& statusMessage)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mMutex, std::try_to_lock);
|
||||
if (!lock.owns_lock())
|
||||
return false;
|
||||
|
||||
mVideoIOStatus.backendName = backendName;
|
||||
mVideoIOStatus.modelName = modelName;
|
||||
mVideoIOStatus.supportsInternalKeying = supportsInternalKeying;
|
||||
mVideoIOStatus.supportsExternalKeying = supportsExternalKeying;
|
||||
mVideoIOStatus.keyerInterfaceAvailable = keyerInterfaceAvailable;
|
||||
mVideoIOStatus.externalKeyingRequested = externalKeyingRequested;
|
||||
mVideoIOStatus.externalKeyingActive = externalKeyingActive;
|
||||
mVideoIOStatus.statusMessage = statusMessage;
|
||||
return true;
|
||||
}
|
||||
|
||||
void HealthTelemetry::RecordPerformanceStats(double frameBudgetMilliseconds, double renderMilliseconds)
|
||||
{
|
||||
mRuntimeHost.WritePerformanceStats(frameBudgetMilliseconds, renderMilliseconds);
|
||||
std::lock_guard<std::mutex> lock(mMutex);
|
||||
mPerformance.frameBudgetMilliseconds = std::max(frameBudgetMilliseconds, 0.0);
|
||||
mPerformance.renderMilliseconds = std::max(renderMilliseconds, 0.0);
|
||||
if (mPerformance.smoothedRenderMilliseconds <= 0.0)
|
||||
mPerformance.smoothedRenderMilliseconds = mPerformance.renderMilliseconds;
|
||||
else
|
||||
mPerformance.smoothedRenderMilliseconds = mPerformance.smoothedRenderMilliseconds * 0.9 + mPerformance.renderMilliseconds * 0.1;
|
||||
}
|
||||
|
||||
bool HealthTelemetry::TryRecordPerformanceStats(double frameBudgetMilliseconds, double renderMilliseconds)
|
||||
{
|
||||
return mRuntimeHost.TryWritePerformanceStats(frameBudgetMilliseconds, renderMilliseconds);
|
||||
std::unique_lock<std::mutex> lock(mMutex, std::try_to_lock);
|
||||
if (!lock.owns_lock())
|
||||
return false;
|
||||
|
||||
mPerformance.frameBudgetMilliseconds = std::max(frameBudgetMilliseconds, 0.0);
|
||||
mPerformance.renderMilliseconds = std::max(renderMilliseconds, 0.0);
|
||||
if (mPerformance.smoothedRenderMilliseconds <= 0.0)
|
||||
mPerformance.smoothedRenderMilliseconds = mPerformance.renderMilliseconds;
|
||||
else
|
||||
mPerformance.smoothedRenderMilliseconds = mPerformance.smoothedRenderMilliseconds * 0.9 + mPerformance.renderMilliseconds * 0.1;
|
||||
return true;
|
||||
}
|
||||
|
||||
void HealthTelemetry::RecordFramePacingStats(double completionIntervalMilliseconds, double smoothedCompletionIntervalMilliseconds,
|
||||
double maxCompletionIntervalMilliseconds, uint64_t lateFrameCount, uint64_t droppedFrameCount, uint64_t flushedFrameCount)
|
||||
{
|
||||
mRuntimeHost.WriteFramePacingStats(completionIntervalMilliseconds, smoothedCompletionIntervalMilliseconds,
|
||||
maxCompletionIntervalMilliseconds, lateFrameCount, droppedFrameCount, flushedFrameCount);
|
||||
std::lock_guard<std::mutex> lock(mMutex);
|
||||
mPerformance.completionIntervalMilliseconds = std::max(completionIntervalMilliseconds, 0.0);
|
||||
mPerformance.smoothedCompletionIntervalMilliseconds = std::max(smoothedCompletionIntervalMilliseconds, 0.0);
|
||||
mPerformance.maxCompletionIntervalMilliseconds = std::max(maxCompletionIntervalMilliseconds, 0.0);
|
||||
mPerformance.lateFrameCount = lateFrameCount;
|
||||
mPerformance.droppedFrameCount = droppedFrameCount;
|
||||
mPerformance.flushedFrameCount = flushedFrameCount;
|
||||
}
|
||||
|
||||
bool HealthTelemetry::TryRecordFramePacingStats(double completionIntervalMilliseconds, double smoothedCompletionIntervalMilliseconds,
|
||||
double maxCompletionIntervalMilliseconds, uint64_t lateFrameCount, uint64_t droppedFrameCount, uint64_t flushedFrameCount)
|
||||
{
|
||||
return mRuntimeHost.TryWriteFramePacingStats(completionIntervalMilliseconds, smoothedCompletionIntervalMilliseconds,
|
||||
maxCompletionIntervalMilliseconds, lateFrameCount, droppedFrameCount, flushedFrameCount);
|
||||
std::unique_lock<std::mutex> lock(mMutex, std::try_to_lock);
|
||||
if (!lock.owns_lock())
|
||||
return false;
|
||||
|
||||
mPerformance.completionIntervalMilliseconds = std::max(completionIntervalMilliseconds, 0.0);
|
||||
mPerformance.smoothedCompletionIntervalMilliseconds = std::max(smoothedCompletionIntervalMilliseconds, 0.0);
|
||||
mPerformance.maxCompletionIntervalMilliseconds = std::max(maxCompletionIntervalMilliseconds, 0.0);
|
||||
mPerformance.lateFrameCount = lateFrameCount;
|
||||
mPerformance.droppedFrameCount = droppedFrameCount;
|
||||
mPerformance.flushedFrameCount = flushedFrameCount;
|
||||
return true;
|
||||
}
|
||||
|
||||
HealthTelemetry::SignalStatusSnapshot HealthTelemetry::GetSignalStatusSnapshot() const
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mMutex);
|
||||
return mSignalStatus;
|
||||
}
|
||||
|
||||
HealthTelemetry::VideoIOStatusSnapshot HealthTelemetry::GetVideoIOStatusSnapshot() const
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mMutex);
|
||||
return mVideoIOStatus;
|
||||
}
|
||||
|
||||
HealthTelemetry::PerformanceSnapshot HealthTelemetry::GetPerformanceSnapshot() const
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mMutex);
|
||||
return mPerformance;
|
||||
}
|
||||
|
||||
HealthTelemetry::Snapshot HealthTelemetry::GetSnapshot() const
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mMutex);
|
||||
|
||||
Snapshot snapshot;
|
||||
snapshot.signal = mSignalStatus;
|
||||
snapshot.videoIO = mVideoIOStatus;
|
||||
snapshot.performance = mPerformance;
|
||||
return snapshot;
|
||||
}
|
||||
|
||||
@@ -1,21 +1,67 @@
|
||||
#pragma once
|
||||
|
||||
#include <mutex>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
class RuntimeHost;
|
||||
|
||||
// Phase 1 compatibility seam for status and timing reporting. The current
|
||||
// implementation still writes through RuntimeHost, but callers can now target
|
||||
// HealthTelemetry as the home for operational visibility work.
|
||||
// Phase 1 compatibility seam for status and timing reporting. HealthTelemetry
|
||||
// now owns the current operational status snapshot directly, so callers can
|
||||
// target it without flowing through RuntimeHost-owned backing fields.
|
||||
class HealthTelemetry
|
||||
{
|
||||
public:
|
||||
explicit HealthTelemetry(RuntimeHost& runtimeHost);
|
||||
struct SignalStatusSnapshot
|
||||
{
|
||||
bool hasSignal = false;
|
||||
unsigned width = 0;
|
||||
unsigned height = 0;
|
||||
std::string modeName;
|
||||
};
|
||||
|
||||
struct VideoIOStatusSnapshot
|
||||
{
|
||||
std::string backendName = "decklink";
|
||||
std::string modelName;
|
||||
bool supportsInternalKeying = false;
|
||||
bool supportsExternalKeying = false;
|
||||
bool keyerInterfaceAvailable = false;
|
||||
bool externalKeyingRequested = false;
|
||||
bool externalKeyingActive = false;
|
||||
std::string statusMessage;
|
||||
};
|
||||
|
||||
struct PerformanceSnapshot
|
||||
{
|
||||
double frameBudgetMilliseconds = 0.0;
|
||||
double renderMilliseconds = 0.0;
|
||||
double smoothedRenderMilliseconds = 0.0;
|
||||
double completionIntervalMilliseconds = 0.0;
|
||||
double smoothedCompletionIntervalMilliseconds = 0.0;
|
||||
double maxCompletionIntervalMilliseconds = 0.0;
|
||||
uint64_t lateFrameCount = 0;
|
||||
uint64_t droppedFrameCount = 0;
|
||||
uint64_t flushedFrameCount = 0;
|
||||
};
|
||||
|
||||
struct Snapshot
|
||||
{
|
||||
SignalStatusSnapshot signal;
|
||||
VideoIOStatusSnapshot videoIO;
|
||||
PerformanceSnapshot performance;
|
||||
};
|
||||
|
||||
HealthTelemetry() = default;
|
||||
|
||||
void ReportSignalStatus(bool hasSignal, unsigned width, unsigned height, const std::string& modeName);
|
||||
bool TryReportSignalStatus(bool hasSignal, unsigned width, unsigned height, const std::string& modeName);
|
||||
|
||||
void ReportVideoIOStatus(const std::string& backendName, const std::string& modelName,
|
||||
bool supportsInternalKeying, bool supportsExternalKeying, bool keyerInterfaceAvailable,
|
||||
bool externalKeyingRequested, bool externalKeyingActive, const std::string& statusMessage);
|
||||
bool TryReportVideoIOStatus(const std::string& backendName, const std::string& modelName,
|
||||
bool supportsInternalKeying, bool supportsExternalKeying, bool keyerInterfaceAvailable,
|
||||
bool externalKeyingRequested, bool externalKeyingActive, const std::string& statusMessage);
|
||||
|
||||
void RecordPerformanceStats(double frameBudgetMilliseconds, double renderMilliseconds);
|
||||
bool TryRecordPerformanceStats(double frameBudgetMilliseconds, double renderMilliseconds);
|
||||
|
||||
@@ -24,6 +70,14 @@ public:
|
||||
bool TryRecordFramePacingStats(double completionIntervalMilliseconds, double smoothedCompletionIntervalMilliseconds,
|
||||
double maxCompletionIntervalMilliseconds, uint64_t lateFrameCount, uint64_t droppedFrameCount, uint64_t flushedFrameCount);
|
||||
|
||||
SignalStatusSnapshot GetSignalStatusSnapshot() const;
|
||||
VideoIOStatusSnapshot GetVideoIOStatusSnapshot() const;
|
||||
PerformanceSnapshot GetPerformanceSnapshot() const;
|
||||
Snapshot GetSnapshot() const;
|
||||
|
||||
private:
|
||||
RuntimeHost& mRuntimeHost;
|
||||
mutable std::mutex mMutex;
|
||||
SignalStatusSnapshot mSignalStatus;
|
||||
VideoIOStatusSnapshot mVideoIOStatus;
|
||||
PerformanceSnapshot mPerformance;
|
||||
};
|
||||
|
||||
@@ -699,22 +699,10 @@ bool ParseParameterDefinitions(const JsonValue& manifestJson, ShaderPackage& sha
|
||||
}
|
||||
|
||||
RuntimeHost::RuntimeHost()
|
||||
: mHealthTelemetry(*this),
|
||||
: mHealthTelemetry(),
|
||||
mReloadRequested(false),
|
||||
mCompileSucceeded(false),
|
||||
mHasSignal(false),
|
||||
mSignalWidth(0),
|
||||
mSignalHeight(0),
|
||||
mFrameBudgetMilliseconds(0.0),
|
||||
mRenderMilliseconds(0.0),
|
||||
mSmoothedRenderMilliseconds(0.0),
|
||||
mCompletionIntervalMilliseconds(0.0),
|
||||
mSmoothedCompletionIntervalMilliseconds(0.0),
|
||||
mMaxCompletionIntervalMilliseconds(0.0),
|
||||
mStartupRandom(GenerateStartupRandom()),
|
||||
mLateFrameCount(0),
|
||||
mDroppedFrameCount(0),
|
||||
mFlushedFrameCount(0),
|
||||
mServerPort(8080),
|
||||
mAutoReloadEnabled(true),
|
||||
mStartTime(std::chrono::steady_clock::now()),
|
||||
@@ -1353,42 +1341,35 @@ void RuntimeHost::SetCompileStatus(bool succeeded, const std::string& message)
|
||||
|
||||
void RuntimeHost::SetSignalStatus(bool hasSignal, unsigned width, unsigned height, const std::string& modeName)
|
||||
{
|
||||
const HealthTelemetry::SignalStatusSnapshot previousStatus = mHealthTelemetry.GetSignalStatusSnapshot();
|
||||
mHealthTelemetry.ReportSignalStatus(hasSignal, width, height, modeName);
|
||||
|
||||
if (previousStatus.hasSignal != hasSignal ||
|
||||
previousStatus.width != width ||
|
||||
previousStatus.height != height ||
|
||||
previousStatus.modeName != modeName)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mMutex);
|
||||
MarkRenderStateDirtyLocked();
|
||||
}
|
||||
}
|
||||
|
||||
bool RuntimeHost::TrySetSignalStatus(bool hasSignal, unsigned width, unsigned height, const std::string& modeName)
|
||||
{
|
||||
return mHealthTelemetry.TryReportSignalStatus(hasSignal, width, height, modeName);
|
||||
}
|
||||
|
||||
void RuntimeHost::WriteSignalStatus(bool hasSignal, unsigned width, unsigned height, const std::string& modeName)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mMutex);
|
||||
SetSignalStatusLocked(hasSignal, width, height, modeName);
|
||||
}
|
||||
|
||||
bool RuntimeHost::TryWriteSignalStatus(bool hasSignal, unsigned width, unsigned height, const std::string& modeName)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mMutex, std::try_to_lock);
|
||||
if (!lock.owns_lock())
|
||||
const HealthTelemetry::SignalStatusSnapshot previousStatus = mHealthTelemetry.GetSignalStatusSnapshot();
|
||||
if (!mHealthTelemetry.TryReportSignalStatus(hasSignal, width, height, modeName))
|
||||
return false;
|
||||
|
||||
SetSignalStatusLocked(hasSignal, width, height, modeName);
|
||||
return true;
|
||||
}
|
||||
|
||||
void RuntimeHost::SetSignalStatusLocked(bool hasSignal, unsigned width, unsigned height, const std::string& modeName)
|
||||
{
|
||||
const bool changed = mHasSignal != hasSignal ||
|
||||
mSignalWidth != width ||
|
||||
mSignalHeight != height ||
|
||||
mSignalModeName != modeName;
|
||||
mHasSignal = hasSignal;
|
||||
mSignalWidth = width;
|
||||
mSignalHeight = height;
|
||||
mSignalModeName = modeName;
|
||||
if (changed)
|
||||
if (previousStatus.hasSignal != hasSignal ||
|
||||
previousStatus.width != width ||
|
||||
previousStatus.height != height ||
|
||||
previousStatus.modeName != modeName)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mMutex);
|
||||
MarkRenderStateDirtyLocked();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void RuntimeHost::MarkRenderStateDirtyLocked()
|
||||
@@ -1412,15 +1393,15 @@ void RuntimeHost::SetDeckLinkOutputStatus(const std::string& modelName, bool sup
|
||||
void RuntimeHost::SetVideoIOStatus(const std::string& backendName, const std::string& modelName, bool supportsInternalKeying, bool supportsExternalKeying,
|
||||
bool keyerInterfaceAvailable, bool externalKeyingRequested, bool externalKeyingActive, const std::string& statusMessage)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mMutex);
|
||||
mDeckLinkOutputStatus.backendName = backendName;
|
||||
mDeckLinkOutputStatus.modelName = modelName;
|
||||
mDeckLinkOutputStatus.supportsInternalKeying = supportsInternalKeying;
|
||||
mDeckLinkOutputStatus.supportsExternalKeying = supportsExternalKeying;
|
||||
mDeckLinkOutputStatus.keyerInterfaceAvailable = keyerInterfaceAvailable;
|
||||
mDeckLinkOutputStatus.externalKeyingRequested = externalKeyingRequested;
|
||||
mDeckLinkOutputStatus.externalKeyingActive = externalKeyingActive;
|
||||
mDeckLinkOutputStatus.statusMessage = statusMessage;
|
||||
mHealthTelemetry.ReportVideoIOStatus(
|
||||
backendName,
|
||||
modelName,
|
||||
supportsInternalKeying,
|
||||
supportsExternalKeying,
|
||||
keyerInterfaceAvailable,
|
||||
externalKeyingRequested,
|
||||
externalKeyingActive,
|
||||
statusMessage);
|
||||
}
|
||||
|
||||
void RuntimeHost::SetPerformanceStats(double frameBudgetMilliseconds, double renderMilliseconds)
|
||||
@@ -1433,32 +1414,6 @@ bool RuntimeHost::TrySetPerformanceStats(double frameBudgetMilliseconds, double
|
||||
return mHealthTelemetry.TryRecordPerformanceStats(frameBudgetMilliseconds, renderMilliseconds);
|
||||
}
|
||||
|
||||
void RuntimeHost::WritePerformanceStats(double frameBudgetMilliseconds, double renderMilliseconds)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mMutex);
|
||||
SetPerformanceStatsLocked(frameBudgetMilliseconds, renderMilliseconds);
|
||||
}
|
||||
|
||||
bool RuntimeHost::TryWritePerformanceStats(double frameBudgetMilliseconds, double renderMilliseconds)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mMutex, std::try_to_lock);
|
||||
if (!lock.owns_lock())
|
||||
return false;
|
||||
|
||||
SetPerformanceStatsLocked(frameBudgetMilliseconds, renderMilliseconds);
|
||||
return true;
|
||||
}
|
||||
|
||||
void RuntimeHost::SetPerformanceStatsLocked(double frameBudgetMilliseconds, double renderMilliseconds)
|
||||
{
|
||||
mFrameBudgetMilliseconds = std::max(frameBudgetMilliseconds, 0.0);
|
||||
mRenderMilliseconds = std::max(renderMilliseconds, 0.0);
|
||||
if (mSmoothedRenderMilliseconds <= 0.0)
|
||||
mSmoothedRenderMilliseconds = mRenderMilliseconds;
|
||||
else
|
||||
mSmoothedRenderMilliseconds = mSmoothedRenderMilliseconds * 0.9 + mRenderMilliseconds * 0.1;
|
||||
}
|
||||
|
||||
void RuntimeHost::SetFramePacingStats(double completionIntervalMilliseconds, double smoothedCompletionIntervalMilliseconds,
|
||||
double maxCompletionIntervalMilliseconds, uint64_t lateFrameCount, uint64_t droppedFrameCount, uint64_t flushedFrameCount)
|
||||
{
|
||||
@@ -1473,37 +1428,6 @@ bool RuntimeHost::TrySetFramePacingStats(double completionIntervalMilliseconds,
|
||||
maxCompletionIntervalMilliseconds, lateFrameCount, droppedFrameCount, flushedFrameCount);
|
||||
}
|
||||
|
||||
void RuntimeHost::WriteFramePacingStats(double completionIntervalMilliseconds, double smoothedCompletionIntervalMilliseconds,
|
||||
double maxCompletionIntervalMilliseconds, uint64_t lateFrameCount, uint64_t droppedFrameCount, uint64_t flushedFrameCount)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mMutex);
|
||||
SetFramePacingStatsLocked(completionIntervalMilliseconds, smoothedCompletionIntervalMilliseconds,
|
||||
maxCompletionIntervalMilliseconds, lateFrameCount, droppedFrameCount, flushedFrameCount);
|
||||
}
|
||||
|
||||
bool RuntimeHost::TryWriteFramePacingStats(double completionIntervalMilliseconds, double smoothedCompletionIntervalMilliseconds,
|
||||
double maxCompletionIntervalMilliseconds, uint64_t lateFrameCount, uint64_t droppedFrameCount, uint64_t flushedFrameCount)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mMutex, std::try_to_lock);
|
||||
if (!lock.owns_lock())
|
||||
return false;
|
||||
|
||||
SetFramePacingStatsLocked(completionIntervalMilliseconds, smoothedCompletionIntervalMilliseconds,
|
||||
maxCompletionIntervalMilliseconds, lateFrameCount, droppedFrameCount, flushedFrameCount);
|
||||
return true;
|
||||
}
|
||||
|
||||
void RuntimeHost::SetFramePacingStatsLocked(double completionIntervalMilliseconds, double smoothedCompletionIntervalMilliseconds,
|
||||
double maxCompletionIntervalMilliseconds, uint64_t lateFrameCount, uint64_t droppedFrameCount, uint64_t flushedFrameCount)
|
||||
{
|
||||
mCompletionIntervalMilliseconds = std::max(completionIntervalMilliseconds, 0.0);
|
||||
mSmoothedCompletionIntervalMilliseconds = std::max(smoothedCompletionIntervalMilliseconds, 0.0);
|
||||
mMaxCompletionIntervalMilliseconds = std::max(maxCompletionIntervalMilliseconds, 0.0);
|
||||
mLateFrameCount = lateFrameCount;
|
||||
mDroppedFrameCount = droppedFrameCount;
|
||||
mFlushedFrameCount = flushedFrameCount;
|
||||
}
|
||||
|
||||
void RuntimeHost::AdvanceFrame()
|
||||
{
|
||||
++mFrameCounter;
|
||||
@@ -1632,6 +1556,8 @@ void RuntimeHost::RefreshDynamicRenderStateFields(std::vector<RuntimeRenderState
|
||||
|
||||
void RuntimeHost::BuildLayerRenderStatesLocked(unsigned outputWidth, unsigned outputHeight, std::vector<RuntimeRenderState>& states) const
|
||||
{
|
||||
const HealthTelemetry::SignalStatusSnapshot signalStatus = mHealthTelemetry.GetSignalStatusSnapshot();
|
||||
|
||||
for (const LayerPersistentState& layer : mPersistentState.layers)
|
||||
{
|
||||
auto shaderIt = mPackagesById.find(layer.shaderId);
|
||||
@@ -1644,8 +1570,8 @@ void RuntimeHost::BuildLayerRenderStatesLocked(unsigned outputWidth, unsigned ou
|
||||
state.shaderName = shaderIt->second.displayName;
|
||||
state.mixAmount = 1.0;
|
||||
state.bypass = layer.bypass ? 1.0 : 0.0;
|
||||
state.inputWidth = mSignalWidth;
|
||||
state.inputHeight = mSignalHeight;
|
||||
state.inputWidth = signalStatus.width;
|
||||
state.inputHeight = signalStatus.height;
|
||||
state.outputWidth = outputWidth;
|
||||
state.outputHeight = outputHeight;
|
||||
state.parameterDefinitions = shaderIt->second.parameters;
|
||||
@@ -2095,6 +2021,7 @@ bool RuntimeHost::ResolvePaths(std::string& error)
|
||||
|
||||
JsonValue RuntimeHost::BuildStateValue() const
|
||||
{
|
||||
const HealthTelemetry::Snapshot telemetrySnapshot = mHealthTelemetry.GetSnapshot();
|
||||
std::lock_guard<std::mutex> lock(mMutex);
|
||||
|
||||
JsonValue root = JsonValue::MakeObject();
|
||||
@@ -2121,44 +2048,47 @@ JsonValue RuntimeHost::BuildStateValue() const
|
||||
root.set("runtime", runtime);
|
||||
|
||||
JsonValue video = JsonValue::MakeObject();
|
||||
video.set("hasSignal", JsonValue(mHasSignal));
|
||||
video.set("width", JsonValue(static_cast<double>(mSignalWidth)));
|
||||
video.set("height", JsonValue(static_cast<double>(mSignalHeight)));
|
||||
video.set("modeName", JsonValue(mSignalModeName));
|
||||
video.set("hasSignal", JsonValue(telemetrySnapshot.signal.hasSignal));
|
||||
video.set("width", JsonValue(static_cast<double>(telemetrySnapshot.signal.width)));
|
||||
video.set("height", JsonValue(static_cast<double>(telemetrySnapshot.signal.height)));
|
||||
video.set("modeName", JsonValue(telemetrySnapshot.signal.modeName));
|
||||
root.set("video", video);
|
||||
|
||||
JsonValue deckLink = JsonValue::MakeObject();
|
||||
deckLink.set("modelName", JsonValue(mDeckLinkOutputStatus.modelName));
|
||||
deckLink.set("supportsInternalKeying", JsonValue(mDeckLinkOutputStatus.supportsInternalKeying));
|
||||
deckLink.set("supportsExternalKeying", JsonValue(mDeckLinkOutputStatus.supportsExternalKeying));
|
||||
deckLink.set("keyerInterfaceAvailable", JsonValue(mDeckLinkOutputStatus.keyerInterfaceAvailable));
|
||||
deckLink.set("externalKeyingRequested", JsonValue(mDeckLinkOutputStatus.externalKeyingRequested));
|
||||
deckLink.set("externalKeyingActive", JsonValue(mDeckLinkOutputStatus.externalKeyingActive));
|
||||
deckLink.set("statusMessage", JsonValue(mDeckLinkOutputStatus.statusMessage));
|
||||
deckLink.set("modelName", JsonValue(telemetrySnapshot.videoIO.modelName));
|
||||
deckLink.set("supportsInternalKeying", JsonValue(telemetrySnapshot.videoIO.supportsInternalKeying));
|
||||
deckLink.set("supportsExternalKeying", JsonValue(telemetrySnapshot.videoIO.supportsExternalKeying));
|
||||
deckLink.set("keyerInterfaceAvailable", JsonValue(telemetrySnapshot.videoIO.keyerInterfaceAvailable));
|
||||
deckLink.set("externalKeyingRequested", JsonValue(telemetrySnapshot.videoIO.externalKeyingRequested));
|
||||
deckLink.set("externalKeyingActive", JsonValue(telemetrySnapshot.videoIO.externalKeyingActive));
|
||||
deckLink.set("statusMessage", JsonValue(telemetrySnapshot.videoIO.statusMessage));
|
||||
root.set("decklink", deckLink);
|
||||
|
||||
JsonValue videoIO = JsonValue::MakeObject();
|
||||
videoIO.set("backend", JsonValue(mDeckLinkOutputStatus.backendName));
|
||||
videoIO.set("modelName", JsonValue(mDeckLinkOutputStatus.modelName));
|
||||
videoIO.set("supportsInternalKeying", JsonValue(mDeckLinkOutputStatus.supportsInternalKeying));
|
||||
videoIO.set("supportsExternalKeying", JsonValue(mDeckLinkOutputStatus.supportsExternalKeying));
|
||||
videoIO.set("keyerInterfaceAvailable", JsonValue(mDeckLinkOutputStatus.keyerInterfaceAvailable));
|
||||
videoIO.set("externalKeyingRequested", JsonValue(mDeckLinkOutputStatus.externalKeyingRequested));
|
||||
videoIO.set("externalKeyingActive", JsonValue(mDeckLinkOutputStatus.externalKeyingActive));
|
||||
videoIO.set("statusMessage", JsonValue(mDeckLinkOutputStatus.statusMessage));
|
||||
videoIO.set("backend", JsonValue(telemetrySnapshot.videoIO.backendName));
|
||||
videoIO.set("modelName", JsonValue(telemetrySnapshot.videoIO.modelName));
|
||||
videoIO.set("supportsInternalKeying", JsonValue(telemetrySnapshot.videoIO.supportsInternalKeying));
|
||||
videoIO.set("supportsExternalKeying", JsonValue(telemetrySnapshot.videoIO.supportsExternalKeying));
|
||||
videoIO.set("keyerInterfaceAvailable", JsonValue(telemetrySnapshot.videoIO.keyerInterfaceAvailable));
|
||||
videoIO.set("externalKeyingRequested", JsonValue(telemetrySnapshot.videoIO.externalKeyingRequested));
|
||||
videoIO.set("externalKeyingActive", JsonValue(telemetrySnapshot.videoIO.externalKeyingActive));
|
||||
videoIO.set("statusMessage", JsonValue(telemetrySnapshot.videoIO.statusMessage));
|
||||
root.set("videoIO", videoIO);
|
||||
|
||||
JsonValue performance = JsonValue::MakeObject();
|
||||
performance.set("frameBudgetMs", JsonValue(mFrameBudgetMilliseconds));
|
||||
performance.set("renderMs", JsonValue(mRenderMilliseconds));
|
||||
performance.set("smoothedRenderMs", JsonValue(mSmoothedRenderMilliseconds));
|
||||
performance.set("budgetUsedPercent", JsonValue(mFrameBudgetMilliseconds > 0.0 ? (mSmoothedRenderMilliseconds / mFrameBudgetMilliseconds) * 100.0 : 0.0));
|
||||
performance.set("completionIntervalMs", JsonValue(mCompletionIntervalMilliseconds));
|
||||
performance.set("smoothedCompletionIntervalMs", JsonValue(mSmoothedCompletionIntervalMilliseconds));
|
||||
performance.set("maxCompletionIntervalMs", JsonValue(mMaxCompletionIntervalMilliseconds));
|
||||
performance.set("lateFrameCount", JsonValue(static_cast<double>(mLateFrameCount)));
|
||||
performance.set("droppedFrameCount", JsonValue(static_cast<double>(mDroppedFrameCount)));
|
||||
performance.set("flushedFrameCount", JsonValue(static_cast<double>(mFlushedFrameCount)));
|
||||
performance.set("frameBudgetMs", JsonValue(telemetrySnapshot.performance.frameBudgetMilliseconds));
|
||||
performance.set("renderMs", JsonValue(telemetrySnapshot.performance.renderMilliseconds));
|
||||
performance.set("smoothedRenderMs", JsonValue(telemetrySnapshot.performance.smoothedRenderMilliseconds));
|
||||
performance.set("budgetUsedPercent", JsonValue(
|
||||
telemetrySnapshot.performance.frameBudgetMilliseconds > 0.0
|
||||
? (telemetrySnapshot.performance.smoothedRenderMilliseconds / telemetrySnapshot.performance.frameBudgetMilliseconds) * 100.0
|
||||
: 0.0));
|
||||
performance.set("completionIntervalMs", JsonValue(telemetrySnapshot.performance.completionIntervalMilliseconds));
|
||||
performance.set("smoothedCompletionIntervalMs", JsonValue(telemetrySnapshot.performance.smoothedCompletionIntervalMilliseconds));
|
||||
performance.set("maxCompletionIntervalMs", JsonValue(telemetrySnapshot.performance.maxCompletionIntervalMilliseconds));
|
||||
performance.set("lateFrameCount", JsonValue(static_cast<double>(telemetrySnapshot.performance.lateFrameCount)));
|
||||
performance.set("droppedFrameCount", JsonValue(static_cast<double>(telemetrySnapshot.performance.droppedFrameCount)));
|
||||
performance.set("flushedFrameCount", JsonValue(static_cast<double>(telemetrySnapshot.performance.flushedFrameCount)));
|
||||
root.set("performance", performance);
|
||||
|
||||
JsonValue shaderLibrary = JsonValue::MakeArray();
|
||||
|
||||
@@ -101,18 +101,6 @@ private:
|
||||
std::string outputFrameRate = "59.94";
|
||||
};
|
||||
|
||||
struct DeckLinkOutputStatus
|
||||
{
|
||||
std::string backendName = "decklink";
|
||||
std::string modelName;
|
||||
bool supportsInternalKeying = false;
|
||||
bool supportsExternalKeying = false;
|
||||
bool keyerInterfaceAvailable = false;
|
||||
bool externalKeyingRequested = false;
|
||||
bool externalKeyingActive = false;
|
||||
std::string statusMessage;
|
||||
};
|
||||
|
||||
struct LayerPersistentState
|
||||
{
|
||||
std::string id;
|
||||
@@ -148,23 +136,10 @@ private:
|
||||
LayerPersistentState* FindLayerById(const std::string& layerId);
|
||||
const LayerPersistentState* FindLayerById(const std::string& layerId) const;
|
||||
std::string GenerateLayerId();
|
||||
void WriteSignalStatus(bool hasSignal, unsigned width, unsigned height, const std::string& modeName);
|
||||
bool TryWriteSignalStatus(bool hasSignal, unsigned width, unsigned height, const std::string& modeName);
|
||||
void SetSignalStatusLocked(bool hasSignal, unsigned width, unsigned height, const std::string& modeName);
|
||||
void MarkRenderStateDirtyLocked();
|
||||
void MarkParameterStateDirtyLocked();
|
||||
void WritePerformanceStats(double frameBudgetMilliseconds, double renderMilliseconds);
|
||||
bool TryWritePerformanceStats(double frameBudgetMilliseconds, double renderMilliseconds);
|
||||
void SetPerformanceStatsLocked(double frameBudgetMilliseconds, double renderMilliseconds);
|
||||
void WriteFramePacingStats(double completionIntervalMilliseconds, double smoothedCompletionIntervalMilliseconds,
|
||||
double maxCompletionIntervalMilliseconds, uint64_t lateFrameCount, uint64_t droppedFrameCount, uint64_t flushedFrameCount);
|
||||
bool TryWriteFramePacingStats(double completionIntervalMilliseconds, double smoothedCompletionIntervalMilliseconds,
|
||||
double maxCompletionIntervalMilliseconds, uint64_t lateFrameCount, uint64_t droppedFrameCount, uint64_t flushedFrameCount);
|
||||
void SetFramePacingStatsLocked(double completionIntervalMilliseconds, double smoothedCompletionIntervalMilliseconds,
|
||||
double maxCompletionIntervalMilliseconds, uint64_t lateFrameCount, uint64_t droppedFrameCount, uint64_t flushedFrameCount);
|
||||
|
||||
private:
|
||||
friend class HealthTelemetry;
|
||||
HealthTelemetry mHealthTelemetry;
|
||||
mutable std::mutex mMutex;
|
||||
AppConfig mConfig;
|
||||
@@ -186,21 +161,7 @@ private:
|
||||
bool mReloadRequested;
|
||||
bool mCompileSucceeded;
|
||||
std::string mCompileMessage;
|
||||
bool mHasSignal;
|
||||
unsigned mSignalWidth;
|
||||
unsigned mSignalHeight;
|
||||
std::string mSignalModeName;
|
||||
double mFrameBudgetMilliseconds;
|
||||
double mRenderMilliseconds;
|
||||
double mSmoothedRenderMilliseconds;
|
||||
double mCompletionIntervalMilliseconds;
|
||||
double mSmoothedCompletionIntervalMilliseconds;
|
||||
double mMaxCompletionIntervalMilliseconds;
|
||||
double mStartupRandom;
|
||||
uint64_t mLateFrameCount;
|
||||
uint64_t mDroppedFrameCount;
|
||||
uint64_t mFlushedFrameCount;
|
||||
DeckLinkOutputStatus mDeckLinkOutputStatus;
|
||||
unsigned short mServerPort;
|
||||
bool mAutoReloadEnabled;
|
||||
std::chrono::steady_clock::time_point mStartTime;
|
||||
|
||||
Reference in New Issue
Block a user