re organisation
This commit is contained in:
@@ -0,0 +1,141 @@
|
||||
#include "stdafx.h"
|
||||
#include "HealthTelemetry.h"
|
||||
|
||||
void HealthTelemetry::ReportSignalStatus(bool hasSignal, unsigned width, unsigned height, const std::string& 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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
#pragma once
|
||||
|
||||
#include <mutex>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
// 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:
|
||||
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);
|
||||
|
||||
void RecordFramePacingStats(double completionIntervalMilliseconds, double smoothedCompletionIntervalMilliseconds,
|
||||
double maxCompletionIntervalMilliseconds, uint64_t lateFrameCount, uint64_t droppedFrameCount, uint64_t flushedFrameCount);
|
||||
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:
|
||||
mutable std::mutex mMutex;
|
||||
SignalStatusSnapshot mSignalStatus;
|
||||
VideoIOStatusSnapshot mVideoIOStatus;
|
||||
PerformanceSnapshot mPerformance;
|
||||
};
|
||||
@@ -0,0 +1,45 @@
|
||||
#include "RuntimeClock.h"
|
||||
|
||||
#include <chrono>
|
||||
|
||||
namespace
|
||||
{
|
||||
bool ToUtcTime(std::time_t time, std::tm& utcTime)
|
||||
{
|
||||
return gmtime_s(&utcTime, &time) == 0;
|
||||
}
|
||||
|
||||
bool ToLocalTime(std::time_t time, std::tm& localTime)
|
||||
{
|
||||
return localtime_s(&localTime, &time) == 0;
|
||||
}
|
||||
}
|
||||
|
||||
RuntimeClockSnapshot GetRuntimeClockSnapshot()
|
||||
{
|
||||
return MakeRuntimeClockSnapshot(std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()));
|
||||
}
|
||||
|
||||
RuntimeClockSnapshot MakeRuntimeClockSnapshot(std::time_t now)
|
||||
{
|
||||
RuntimeClockSnapshot snapshot;
|
||||
|
||||
std::tm utcTime = {};
|
||||
if (!ToUtcTime(now, utcTime))
|
||||
return snapshot;
|
||||
|
||||
snapshot.utcTimeSeconds =
|
||||
static_cast<double>(utcTime.tm_hour * 3600 + utcTime.tm_min * 60 + utcTime.tm_sec);
|
||||
|
||||
std::tm localTime = {};
|
||||
if (!ToLocalTime(now, localTime))
|
||||
return snapshot;
|
||||
|
||||
utcTime.tm_isdst = localTime.tm_isdst;
|
||||
const std::time_t localAsTime = std::mktime(&localTime);
|
||||
const std::time_t utcAsLocalTime = std::mktime(&utcTime);
|
||||
if (localAsTime != static_cast<std::time_t>(-1) && utcAsLocalTime != static_cast<std::time_t>(-1))
|
||||
snapshot.utcOffsetSeconds = std::difftime(localAsTime, utcAsLocalTime);
|
||||
|
||||
return snapshot;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <ctime>
|
||||
|
||||
struct RuntimeClockSnapshot
|
||||
{
|
||||
double utcTimeSeconds = 0.0;
|
||||
double utcOffsetSeconds = 0.0;
|
||||
};
|
||||
|
||||
RuntimeClockSnapshot GetRuntimeClockSnapshot();
|
||||
RuntimeClockSnapshot MakeRuntimeClockSnapshot(std::time_t now);
|
||||
Reference in New Issue
Block a user