501 lines
24 KiB
C++
501 lines
24 KiB
C++
#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;
|
|
}
|
|
|
|
void HealthTelemetry::RecordRuntimeEventQueueMetrics(const std::string& queueName, std::size_t depth, std::size_t capacity,
|
|
uint64_t droppedCount, double oldestEventAgeMilliseconds)
|
|
{
|
|
std::lock_guard<std::mutex> lock(mMutex);
|
|
mRuntimeEvents.queue.queueName = queueName;
|
|
mRuntimeEvents.queue.depth = depth;
|
|
mRuntimeEvents.queue.capacity = capacity;
|
|
mRuntimeEvents.queue.droppedCount = droppedCount;
|
|
mRuntimeEvents.queue.oldestEventAgeMilliseconds = std::max(oldestEventAgeMilliseconds, 0.0);
|
|
}
|
|
|
|
bool HealthTelemetry::TryRecordRuntimeEventQueueMetrics(const std::string& queueName, std::size_t depth, std::size_t capacity,
|
|
uint64_t droppedCount, double oldestEventAgeMilliseconds)
|
|
{
|
|
std::unique_lock<std::mutex> lock(mMutex, std::try_to_lock);
|
|
if (!lock.owns_lock())
|
|
return false;
|
|
|
|
mRuntimeEvents.queue.queueName = queueName;
|
|
mRuntimeEvents.queue.depth = depth;
|
|
mRuntimeEvents.queue.capacity = capacity;
|
|
mRuntimeEvents.queue.droppedCount = droppedCount;
|
|
mRuntimeEvents.queue.oldestEventAgeMilliseconds = std::max(oldestEventAgeMilliseconds, 0.0);
|
|
return true;
|
|
}
|
|
|
|
void HealthTelemetry::RecordRuntimeEventDispatchStats(std::size_t dispatchedEvents, std::size_t handlerInvocations,
|
|
std::size_t handlerFailures, double dispatchDurationMilliseconds)
|
|
{
|
|
std::lock_guard<std::mutex> lock(mMutex);
|
|
++mRuntimeEvents.dispatch.dispatchCallCount;
|
|
mRuntimeEvents.dispatch.dispatchedEventCount += static_cast<uint64_t>(dispatchedEvents);
|
|
mRuntimeEvents.dispatch.handlerInvocationCount += static_cast<uint64_t>(handlerInvocations);
|
|
mRuntimeEvents.dispatch.handlerFailureCount += static_cast<uint64_t>(handlerFailures);
|
|
mRuntimeEvents.dispatch.lastDispatchDurationMilliseconds = std::max(dispatchDurationMilliseconds, 0.0);
|
|
mRuntimeEvents.dispatch.maxDispatchDurationMilliseconds = std::max(
|
|
mRuntimeEvents.dispatch.maxDispatchDurationMilliseconds,
|
|
mRuntimeEvents.dispatch.lastDispatchDurationMilliseconds);
|
|
}
|
|
|
|
bool HealthTelemetry::TryRecordRuntimeEventDispatchStats(std::size_t dispatchedEvents, std::size_t handlerInvocations,
|
|
std::size_t handlerFailures, double dispatchDurationMilliseconds)
|
|
{
|
|
std::unique_lock<std::mutex> lock(mMutex, std::try_to_lock);
|
|
if (!lock.owns_lock())
|
|
return false;
|
|
|
|
++mRuntimeEvents.dispatch.dispatchCallCount;
|
|
mRuntimeEvents.dispatch.dispatchedEventCount += static_cast<uint64_t>(dispatchedEvents);
|
|
mRuntimeEvents.dispatch.handlerInvocationCount += static_cast<uint64_t>(handlerInvocations);
|
|
mRuntimeEvents.dispatch.handlerFailureCount += static_cast<uint64_t>(handlerFailures);
|
|
mRuntimeEvents.dispatch.lastDispatchDurationMilliseconds = std::max(dispatchDurationMilliseconds, 0.0);
|
|
mRuntimeEvents.dispatch.maxDispatchDurationMilliseconds = std::max(
|
|
mRuntimeEvents.dispatch.maxDispatchDurationMilliseconds,
|
|
mRuntimeEvents.dispatch.lastDispatchDurationMilliseconds);
|
|
return true;
|
|
}
|
|
|
|
void HealthTelemetry::RecordPersistenceWriteResult(bool succeeded, const std::string& targetKind, const std::string& targetPath,
|
|
const std::string& reason, const std::string& errorMessage, bool newerRequestPending)
|
|
{
|
|
std::lock_guard<std::mutex> lock(mMutex);
|
|
if (succeeded)
|
|
++mPersistence.writeSuccessCount;
|
|
else
|
|
++mPersistence.writeFailureCount;
|
|
mPersistence.lastWriteSucceeded = succeeded;
|
|
mPersistence.unsavedChanges = !succeeded || newerRequestPending;
|
|
mPersistence.newerRequestPending = newerRequestPending;
|
|
mPersistence.lastTargetKind = targetKind;
|
|
mPersistence.lastTargetPath = targetPath;
|
|
mPersistence.lastReason = reason;
|
|
mPersistence.lastErrorMessage = errorMessage;
|
|
}
|
|
|
|
bool HealthTelemetry::TryRecordPersistenceWriteResult(bool succeeded, const std::string& targetKind, const std::string& targetPath,
|
|
const std::string& reason, const std::string& errorMessage, bool newerRequestPending)
|
|
{
|
|
std::unique_lock<std::mutex> lock(mMutex, std::try_to_lock);
|
|
if (!lock.owns_lock())
|
|
return false;
|
|
|
|
if (succeeded)
|
|
++mPersistence.writeSuccessCount;
|
|
else
|
|
++mPersistence.writeFailureCount;
|
|
mPersistence.lastWriteSucceeded = succeeded;
|
|
mPersistence.unsavedChanges = !succeeded || newerRequestPending;
|
|
mPersistence.newerRequestPending = newerRequestPending;
|
|
mPersistence.lastTargetKind = targetKind;
|
|
mPersistence.lastTargetPath = targetPath;
|
|
mPersistence.lastReason = reason;
|
|
mPersistence.lastErrorMessage = errorMessage;
|
|
return true;
|
|
}
|
|
|
|
void HealthTelemetry::RecordBackendPlayoutHealth(const std::string& lifecycleState, const std::string& completionResult,
|
|
std::size_t readyQueueDepth, std::size_t readyQueueCapacity, uint64_t readyQueuePushedCount,
|
|
std::size_t minReadyQueueDepth, std::size_t maxReadyQueueDepth, uint64_t readyQueueZeroDepthCount,
|
|
uint64_t readyQueuePoppedCount, uint64_t readyQueueDroppedCount, uint64_t readyQueueUnderrunCount,
|
|
double outputRenderMilliseconds, double smoothedOutputRenderMilliseconds, double maxOutputRenderMilliseconds,
|
|
double outputFrameAcquireMilliseconds, double outputFrameRenderRequestMilliseconds, double outputFrameEndAccessMilliseconds,
|
|
uint64_t completedFrameIndex, uint64_t scheduledFrameIndex, uint64_t scheduledLeadFrames,
|
|
uint64_t measuredLagFrames, uint64_t catchUpFrames, uint64_t lateStreak, uint64_t dropStreak,
|
|
uint64_t lateFrameCount, uint64_t droppedFrameCount, uint64_t flushedFrameCount,
|
|
bool degraded, const std::string& statusMessage)
|
|
{
|
|
std::lock_guard<std::mutex> lock(mMutex);
|
|
mBackendPlayout.lifecycleState = lifecycleState;
|
|
mBackendPlayout.completionResult = completionResult;
|
|
mBackendPlayout.readyQueueDepth = readyQueueDepth;
|
|
mBackendPlayout.readyQueueCapacity = readyQueueCapacity;
|
|
mBackendPlayout.minReadyQueueDepth = minReadyQueueDepth;
|
|
mBackendPlayout.maxReadyQueueDepth = maxReadyQueueDepth;
|
|
mBackendPlayout.readyQueueZeroDepthCount = readyQueueZeroDepthCount;
|
|
mBackendPlayout.readyQueuePushedCount = readyQueuePushedCount;
|
|
mBackendPlayout.readyQueuePoppedCount = readyQueuePoppedCount;
|
|
mBackendPlayout.readyQueueDroppedCount = readyQueueDroppedCount;
|
|
mBackendPlayout.readyQueueUnderrunCount = readyQueueUnderrunCount;
|
|
mBackendPlayout.outputRenderMilliseconds = std::max(outputRenderMilliseconds, 0.0);
|
|
mBackendPlayout.smoothedOutputRenderMilliseconds = std::max(smoothedOutputRenderMilliseconds, 0.0);
|
|
mBackendPlayout.maxOutputRenderMilliseconds = std::max(maxOutputRenderMilliseconds, 0.0);
|
|
mBackendPlayout.outputFrameAcquireMilliseconds = std::max(outputFrameAcquireMilliseconds, 0.0);
|
|
mBackendPlayout.outputFrameRenderRequestMilliseconds = std::max(outputFrameRenderRequestMilliseconds, 0.0);
|
|
mBackendPlayout.outputFrameEndAccessMilliseconds = std::max(outputFrameEndAccessMilliseconds, 0.0);
|
|
mBackendPlayout.completedFrameIndex = completedFrameIndex;
|
|
mBackendPlayout.scheduledFrameIndex = scheduledFrameIndex;
|
|
mBackendPlayout.scheduledLeadFrames = scheduledLeadFrames;
|
|
mBackendPlayout.measuredLagFrames = measuredLagFrames;
|
|
mBackendPlayout.catchUpFrames = catchUpFrames;
|
|
mBackendPlayout.lateStreak = lateStreak;
|
|
mBackendPlayout.dropStreak = dropStreak;
|
|
mBackendPlayout.lateFrameCount = lateFrameCount;
|
|
mBackendPlayout.droppedFrameCount = droppedFrameCount;
|
|
mBackendPlayout.flushedFrameCount = flushedFrameCount;
|
|
mBackendPlayout.degraded = degraded;
|
|
mBackendPlayout.statusMessage = statusMessage;
|
|
}
|
|
|
|
bool HealthTelemetry::TryRecordBackendPlayoutHealth(const std::string& lifecycleState, const std::string& completionResult,
|
|
std::size_t readyQueueDepth, std::size_t readyQueueCapacity, uint64_t readyQueuePushedCount,
|
|
std::size_t minReadyQueueDepth, std::size_t maxReadyQueueDepth, uint64_t readyQueueZeroDepthCount,
|
|
uint64_t readyQueuePoppedCount, uint64_t readyQueueDroppedCount, uint64_t readyQueueUnderrunCount,
|
|
double outputRenderMilliseconds, double smoothedOutputRenderMilliseconds, double maxOutputRenderMilliseconds,
|
|
double outputFrameAcquireMilliseconds, double outputFrameRenderRequestMilliseconds, double outputFrameEndAccessMilliseconds,
|
|
uint64_t completedFrameIndex, uint64_t scheduledFrameIndex, uint64_t scheduledLeadFrames,
|
|
uint64_t measuredLagFrames, uint64_t catchUpFrames, uint64_t lateStreak, uint64_t dropStreak,
|
|
uint64_t lateFrameCount, uint64_t droppedFrameCount, uint64_t flushedFrameCount,
|
|
bool degraded, const std::string& statusMessage)
|
|
{
|
|
std::unique_lock<std::mutex> lock(mMutex, std::try_to_lock);
|
|
if (!lock.owns_lock())
|
|
return false;
|
|
|
|
mBackendPlayout.lifecycleState = lifecycleState;
|
|
mBackendPlayout.completionResult = completionResult;
|
|
mBackendPlayout.readyQueueDepth = readyQueueDepth;
|
|
mBackendPlayout.readyQueueCapacity = readyQueueCapacity;
|
|
mBackendPlayout.minReadyQueueDepth = minReadyQueueDepth;
|
|
mBackendPlayout.maxReadyQueueDepth = maxReadyQueueDepth;
|
|
mBackendPlayout.readyQueueZeroDepthCount = readyQueueZeroDepthCount;
|
|
mBackendPlayout.readyQueuePushedCount = readyQueuePushedCount;
|
|
mBackendPlayout.readyQueuePoppedCount = readyQueuePoppedCount;
|
|
mBackendPlayout.readyQueueDroppedCount = readyQueueDroppedCount;
|
|
mBackendPlayout.readyQueueUnderrunCount = readyQueueUnderrunCount;
|
|
mBackendPlayout.outputRenderMilliseconds = std::max(outputRenderMilliseconds, 0.0);
|
|
mBackendPlayout.smoothedOutputRenderMilliseconds = std::max(smoothedOutputRenderMilliseconds, 0.0);
|
|
mBackendPlayout.maxOutputRenderMilliseconds = std::max(maxOutputRenderMilliseconds, 0.0);
|
|
mBackendPlayout.outputFrameAcquireMilliseconds = std::max(outputFrameAcquireMilliseconds, 0.0);
|
|
mBackendPlayout.outputFrameRenderRequestMilliseconds = std::max(outputFrameRenderRequestMilliseconds, 0.0);
|
|
mBackendPlayout.outputFrameEndAccessMilliseconds = std::max(outputFrameEndAccessMilliseconds, 0.0);
|
|
mBackendPlayout.completedFrameIndex = completedFrameIndex;
|
|
mBackendPlayout.scheduledFrameIndex = scheduledFrameIndex;
|
|
mBackendPlayout.scheduledLeadFrames = scheduledLeadFrames;
|
|
mBackendPlayout.measuredLagFrames = measuredLagFrames;
|
|
mBackendPlayout.catchUpFrames = catchUpFrames;
|
|
mBackendPlayout.lateStreak = lateStreak;
|
|
mBackendPlayout.dropStreak = dropStreak;
|
|
mBackendPlayout.lateFrameCount = lateFrameCount;
|
|
mBackendPlayout.droppedFrameCount = droppedFrameCount;
|
|
mBackendPlayout.flushedFrameCount = flushedFrameCount;
|
|
mBackendPlayout.degraded = degraded;
|
|
mBackendPlayout.statusMessage = statusMessage;
|
|
return true;
|
|
}
|
|
|
|
void HealthTelemetry::RecordOutputRenderQueueWait(double queueWaitMilliseconds)
|
|
{
|
|
std::lock_guard<std::mutex> lock(mMutex);
|
|
mBackendPlayout.outputRenderQueueWaitMilliseconds = std::max(queueWaitMilliseconds, 0.0);
|
|
}
|
|
|
|
bool HealthTelemetry::TryRecordOutputRenderQueueWait(double queueWaitMilliseconds)
|
|
{
|
|
std::unique_lock<std::mutex> lock(mMutex, std::try_to_lock);
|
|
if (!lock.owns_lock())
|
|
return false;
|
|
|
|
mBackendPlayout.outputRenderQueueWaitMilliseconds = std::max(queueWaitMilliseconds, 0.0);
|
|
return true;
|
|
}
|
|
|
|
void HealthTelemetry::RecordSystemMemoryPlayoutStats(std::size_t freeFrameCount, std::size_t readyFrameCount,
|
|
std::size_t scheduledFrameCount, uint64_t underrunCount, uint64_t repeatCount, uint64_t dropCount,
|
|
double frameAgeAtScheduleMilliseconds, double frameAgeAtCompletionMilliseconds)
|
|
{
|
|
std::lock_guard<std::mutex> lock(mMutex);
|
|
mBackendPlayout.systemFramePoolFree = freeFrameCount;
|
|
mBackendPlayout.systemFramePoolReady = readyFrameCount;
|
|
mBackendPlayout.systemFramePoolScheduled = scheduledFrameCount;
|
|
mBackendPlayout.systemFrameUnderrunCount = underrunCount;
|
|
mBackendPlayout.systemFrameRepeatCount = repeatCount;
|
|
mBackendPlayout.systemFrameDropCount = dropCount;
|
|
mBackendPlayout.systemFrameAgeAtScheduleMilliseconds = std::max(frameAgeAtScheduleMilliseconds, 0.0);
|
|
mBackendPlayout.systemFrameAgeAtCompletionMilliseconds = std::max(frameAgeAtCompletionMilliseconds, 0.0);
|
|
}
|
|
|
|
bool HealthTelemetry::TryRecordSystemMemoryPlayoutStats(std::size_t freeFrameCount, std::size_t readyFrameCount,
|
|
std::size_t scheduledFrameCount, uint64_t underrunCount, uint64_t repeatCount, uint64_t dropCount,
|
|
double frameAgeAtScheduleMilliseconds, double frameAgeAtCompletionMilliseconds)
|
|
{
|
|
std::unique_lock<std::mutex> lock(mMutex, std::try_to_lock);
|
|
if (!lock.owns_lock())
|
|
return false;
|
|
|
|
mBackendPlayout.systemFramePoolFree = freeFrameCount;
|
|
mBackendPlayout.systemFramePoolReady = readyFrameCount;
|
|
mBackendPlayout.systemFramePoolScheduled = scheduledFrameCount;
|
|
mBackendPlayout.systemFrameUnderrunCount = underrunCount;
|
|
mBackendPlayout.systemFrameRepeatCount = repeatCount;
|
|
mBackendPlayout.systemFrameDropCount = dropCount;
|
|
mBackendPlayout.systemFrameAgeAtScheduleMilliseconds = std::max(frameAgeAtScheduleMilliseconds, 0.0);
|
|
mBackendPlayout.systemFrameAgeAtCompletionMilliseconds = std::max(frameAgeAtCompletionMilliseconds, 0.0);
|
|
return true;
|
|
}
|
|
|
|
void HealthTelemetry::RecordDeckLinkBufferTelemetry(bool actualBufferedFramesAvailable, uint64_t actualBufferedFrames,
|
|
std::size_t targetBufferedFrames, double scheduleCallMilliseconds, uint64_t scheduleFailureCount)
|
|
{
|
|
std::lock_guard<std::mutex> lock(mMutex);
|
|
mBackendPlayout.actualDeckLinkBufferedFramesAvailable = actualBufferedFramesAvailable;
|
|
mBackendPlayout.actualDeckLinkBufferedFrames = actualBufferedFramesAvailable ? actualBufferedFrames : 0;
|
|
mBackendPlayout.targetDeckLinkBufferedFrames = targetBufferedFrames;
|
|
mBackendPlayout.deckLinkScheduleCallMilliseconds = std::max(scheduleCallMilliseconds, 0.0);
|
|
mBackendPlayout.deckLinkScheduleFailureCount = scheduleFailureCount;
|
|
}
|
|
|
|
bool HealthTelemetry::TryRecordDeckLinkBufferTelemetry(bool actualBufferedFramesAvailable, uint64_t actualBufferedFrames,
|
|
std::size_t targetBufferedFrames, double scheduleCallMilliseconds, uint64_t scheduleFailureCount)
|
|
{
|
|
std::unique_lock<std::mutex> lock(mMutex, std::try_to_lock);
|
|
if (!lock.owns_lock())
|
|
return false;
|
|
|
|
mBackendPlayout.actualDeckLinkBufferedFramesAvailable = actualBufferedFramesAvailable;
|
|
mBackendPlayout.actualDeckLinkBufferedFrames = actualBufferedFramesAvailable ? actualBufferedFrames : 0;
|
|
mBackendPlayout.targetDeckLinkBufferedFrames = targetBufferedFrames;
|
|
mBackendPlayout.deckLinkScheduleCallMilliseconds = std::max(scheduleCallMilliseconds, 0.0);
|
|
mBackendPlayout.deckLinkScheduleFailureCount = scheduleFailureCount;
|
|
return true;
|
|
}
|
|
|
|
void HealthTelemetry::RecordOutputRenderPipelineTiming(
|
|
double drawMilliseconds,
|
|
double fenceWaitMilliseconds,
|
|
double mapMilliseconds,
|
|
double readbackCopyMilliseconds,
|
|
double cachedCopyMilliseconds,
|
|
double asyncQueueMilliseconds,
|
|
double asyncQueueBufferMilliseconds,
|
|
double asyncQueueSetupMilliseconds,
|
|
double asyncQueueReadPixelsMilliseconds,
|
|
double asyncQueueFenceMilliseconds,
|
|
double syncReadMilliseconds,
|
|
bool asyncReadbackMissed,
|
|
bool cachedFallbackUsed,
|
|
bool syncFallbackUsed)
|
|
{
|
|
std::lock_guard<std::mutex> lock(mMutex);
|
|
mBackendPlayout.outputRenderDrawMilliseconds = std::max(drawMilliseconds, 0.0);
|
|
mBackendPlayout.outputReadbackFenceWaitMilliseconds = std::max(fenceWaitMilliseconds, 0.0);
|
|
mBackendPlayout.outputReadbackMapMilliseconds = std::max(mapMilliseconds, 0.0);
|
|
mBackendPlayout.outputReadbackCopyMilliseconds = std::max(readbackCopyMilliseconds, 0.0);
|
|
mBackendPlayout.outputCachedCopyMilliseconds = std::max(cachedCopyMilliseconds, 0.0);
|
|
mBackendPlayout.outputAsyncQueueMilliseconds = std::max(asyncQueueMilliseconds, 0.0);
|
|
mBackendPlayout.outputAsyncQueueBufferMilliseconds = std::max(asyncQueueBufferMilliseconds, 0.0);
|
|
mBackendPlayout.outputAsyncQueueSetupMilliseconds = std::max(asyncQueueSetupMilliseconds, 0.0);
|
|
mBackendPlayout.outputAsyncQueueReadPixelsMilliseconds = std::max(asyncQueueReadPixelsMilliseconds, 0.0);
|
|
mBackendPlayout.outputAsyncQueueFenceMilliseconds = std::max(asyncQueueFenceMilliseconds, 0.0);
|
|
mBackendPlayout.outputSyncReadMilliseconds = std::max(syncReadMilliseconds, 0.0);
|
|
if (asyncReadbackMissed)
|
|
++mBackendPlayout.outputAsyncReadbackMissCount;
|
|
if (cachedFallbackUsed)
|
|
++mBackendPlayout.outputCachedFallbackCount;
|
|
if (syncFallbackUsed)
|
|
++mBackendPlayout.outputSyncFallbackCount;
|
|
}
|
|
|
|
bool HealthTelemetry::TryRecordOutputRenderPipelineTiming(
|
|
double drawMilliseconds,
|
|
double fenceWaitMilliseconds,
|
|
double mapMilliseconds,
|
|
double readbackCopyMilliseconds,
|
|
double cachedCopyMilliseconds,
|
|
double asyncQueueMilliseconds,
|
|
double asyncQueueBufferMilliseconds,
|
|
double asyncQueueSetupMilliseconds,
|
|
double asyncQueueReadPixelsMilliseconds,
|
|
double asyncQueueFenceMilliseconds,
|
|
double syncReadMilliseconds,
|
|
bool asyncReadbackMissed,
|
|
bool cachedFallbackUsed,
|
|
bool syncFallbackUsed)
|
|
{
|
|
std::unique_lock<std::mutex> lock(mMutex, std::try_to_lock);
|
|
if (!lock.owns_lock())
|
|
return false;
|
|
|
|
mBackendPlayout.outputRenderDrawMilliseconds = std::max(drawMilliseconds, 0.0);
|
|
mBackendPlayout.outputReadbackFenceWaitMilliseconds = std::max(fenceWaitMilliseconds, 0.0);
|
|
mBackendPlayout.outputReadbackMapMilliseconds = std::max(mapMilliseconds, 0.0);
|
|
mBackendPlayout.outputReadbackCopyMilliseconds = std::max(readbackCopyMilliseconds, 0.0);
|
|
mBackendPlayout.outputCachedCopyMilliseconds = std::max(cachedCopyMilliseconds, 0.0);
|
|
mBackendPlayout.outputAsyncQueueMilliseconds = std::max(asyncQueueMilliseconds, 0.0);
|
|
mBackendPlayout.outputAsyncQueueBufferMilliseconds = std::max(asyncQueueBufferMilliseconds, 0.0);
|
|
mBackendPlayout.outputAsyncQueueSetupMilliseconds = std::max(asyncQueueSetupMilliseconds, 0.0);
|
|
mBackendPlayout.outputAsyncQueueReadPixelsMilliseconds = std::max(asyncQueueReadPixelsMilliseconds, 0.0);
|
|
mBackendPlayout.outputAsyncQueueFenceMilliseconds = std::max(asyncQueueFenceMilliseconds, 0.0);
|
|
mBackendPlayout.outputSyncReadMilliseconds = std::max(syncReadMilliseconds, 0.0);
|
|
if (asyncReadbackMissed)
|
|
++mBackendPlayout.outputAsyncReadbackMissCount;
|
|
if (cachedFallbackUsed)
|
|
++mBackendPlayout.outputCachedFallbackCount;
|
|
if (syncFallbackUsed)
|
|
++mBackendPlayout.outputSyncFallbackCount;
|
|
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::RuntimeEventMetricsSnapshot HealthTelemetry::GetRuntimeEventMetricsSnapshot() const
|
|
{
|
|
std::lock_guard<std::mutex> lock(mMutex);
|
|
return mRuntimeEvents;
|
|
}
|
|
|
|
HealthTelemetry::PersistenceSnapshot HealthTelemetry::GetPersistenceSnapshot() const
|
|
{
|
|
std::lock_guard<std::mutex> lock(mMutex);
|
|
return mPersistence;
|
|
}
|
|
|
|
HealthTelemetry::BackendPlayoutSnapshot HealthTelemetry::GetBackendPlayoutSnapshot() const
|
|
{
|
|
std::lock_guard<std::mutex> lock(mMutex);
|
|
return mBackendPlayout;
|
|
}
|
|
|
|
HealthTelemetry::Snapshot HealthTelemetry::GetSnapshot() const
|
|
{
|
|
std::lock_guard<std::mutex> lock(mMutex);
|
|
|
|
Snapshot snapshot;
|
|
snapshot.signal = mSignalStatus;
|
|
snapshot.videoIO = mVideoIOStatus;
|
|
snapshot.performance = mPerformance;
|
|
snapshot.runtimeEvents = mRuntimeEvents;
|
|
snapshot.persistence = mPersistence;
|
|
snapshot.backendPlayout = mBackendPlayout;
|
|
return snapshot;
|
|
}
|