From 2058f94193f7bf9f3aae73632a5b42630548456b Mon Sep 17 00:00:00 2001 From: Aiden Date: Fri, 22 May 2026 15:53:56 +1000 Subject: [PATCH] generic telemetry --- src/video/core/VideoIOTypes.h | 10 ------- src/video/decklink/DeckLinkOutput.cpp | 22 ++++++++-------- src/video/decklink/DeckLinkSession.cpp | 36 +++++++++++++------------- src/video/decklink/DeckLinkSession.h | 16 ++++++++++++ 4 files changed, 45 insertions(+), 39 deletions(-) diff --git a/src/video/core/VideoIOTypes.h b/src/video/core/VideoIOTypes.h index 88d472c..2dcab06 100644 --- a/src/video/core/VideoIOTypes.h +++ b/src/video/core/VideoIOTypes.h @@ -42,16 +42,6 @@ struct VideoIOState bool keyerInterfaceAvailable = false; bool externalKeyingActive = false; double frameBudgetMilliseconds = 0.0; - bool actualDeckLinkBufferedFramesAvailable = false; - uint64_t actualDeckLinkBufferedFrames = 0; - double deckLinkScheduleCallMilliseconds = 0.0; - uint64_t deckLinkScheduleFailureCount = 0; - bool deckLinkScheduleLeadAvailable = false; - int64_t deckLinkPlaybackStreamTime = 0; - uint64_t deckLinkPlaybackFrameIndex = 0; - uint64_t deckLinkNextScheduleFrameIndex = 0; - int64_t deckLinkScheduleLeadFrames = 0; - uint64_t deckLinkScheduleRealignmentCount = 0; }; struct VideoIOFrame diff --git a/src/video/decklink/DeckLinkOutput.cpp b/src/video/decklink/DeckLinkOutput.cpp index 53dafeb..7909f0f 100644 --- a/src/video/decklink/DeckLinkOutput.cpp +++ b/src/video/decklink/DeckLinkOutput.cpp @@ -72,17 +72,17 @@ DeckLinkOutputMetrics DeckLinkOutput::Metrics() const metrics.dropped = mDropped.load(); metrics.flushed = mFlushed.load(); - const VideoIOState& state = mSession.State(); - metrics.scheduleFailures = state.deckLinkScheduleFailureCount; - metrics.actualBufferedFramesAvailable = state.actualDeckLinkBufferedFramesAvailable; - metrics.actualBufferedFrames = state.actualDeckLinkBufferedFrames; - metrics.scheduleCallMilliseconds = state.deckLinkScheduleCallMilliseconds; - metrics.scheduleLeadAvailable = state.deckLinkScheduleLeadAvailable; - metrics.playbackStreamTime = state.deckLinkPlaybackStreamTime; - metrics.playbackFrameIndex = state.deckLinkPlaybackFrameIndex; - metrics.nextScheduleFrameIndex = state.deckLinkNextScheduleFrameIndex; - metrics.scheduleLeadFrames = state.deckLinkScheduleLeadFrames; - metrics.scheduleRealignmentCount = state.deckLinkScheduleRealignmentCount; + const DeckLinkSessionTelemetry& telemetry = mSession.Telemetry(); + metrics.scheduleFailures = telemetry.scheduleFailureCount; + metrics.actualBufferedFramesAvailable = telemetry.actualBufferedFramesAvailable; + metrics.actualBufferedFrames = telemetry.actualBufferedFrames; + metrics.scheduleCallMilliseconds = telemetry.scheduleCallMilliseconds; + metrics.scheduleLeadAvailable = telemetry.scheduleLeadAvailable; + metrics.playbackStreamTime = telemetry.playbackStreamTime; + metrics.playbackFrameIndex = telemetry.playbackFrameIndex; + metrics.nextScheduleFrameIndex = telemetry.nextScheduleFrameIndex; + metrics.scheduleLeadFrames = telemetry.scheduleLeadFrames; + metrics.scheduleRealignmentCount = telemetry.scheduleRealignmentCount; return metrics; } diff --git a/src/video/decklink/DeckLinkSession.cpp b/src/video/decklink/DeckLinkSession.cpp index 63cae9d..22aac1b 100644 --- a/src/video/decklink/DeckLinkSession.cpp +++ b/src/video/decklink/DeckLinkSession.cpp @@ -443,7 +443,7 @@ bool DeckLinkSession::ScheduleFrame(IDeckLinkMutableVideoFrame* outputVideoFrame { if (outputVideoFrame == nullptr || output == nullptr) { - ++mState.deckLinkScheduleFailureCount; + ++mTelemetry.scheduleFailureCount; return false; } @@ -459,9 +459,9 @@ bool DeckLinkSession::ScheduleFrame(IDeckLinkMutableVideoFrame* outputVideoFrame const auto scheduleStart = std::chrono::steady_clock::now(); const HRESULT result = output->ScheduleVideoFrame(outputVideoFrame, scheduleTime.streamTime, scheduleTime.duration, scheduleTime.timeScale); const auto scheduleEnd = std::chrono::steady_clock::now(); - mState.deckLinkScheduleCallMilliseconds = std::chrono::duration_cast>(scheduleEnd - scheduleStart).count(); + mTelemetry.scheduleCallMilliseconds = std::chrono::duration_cast>(scheduleEnd - scheduleStart).count(); if (result != S_OK) - ++mState.deckLinkScheduleFailureCount; + ++mTelemetry.scheduleFailureCount; RefreshBufferedVideoFrameCount(); return result == S_OK; } @@ -470,7 +470,7 @@ void DeckLinkSession::UpdateScheduleLeadTelemetry() { if (output == nullptr) { - mState.deckLinkScheduleLeadAvailable = false; + mTelemetry.scheduleLeadAvailable = false; return; } @@ -478,7 +478,7 @@ void DeckLinkSession::UpdateScheduleLeadTelemetry() double playbackSpeed = 0.0; if (output->GetScheduledStreamTime(mScheduler.TimeScale(), &streamTime, &playbackSpeed) != S_OK || playbackSpeed <= 0.0) { - mState.deckLinkScheduleLeadAvailable = false; + mTelemetry.scheduleLeadAvailable = false; return; } @@ -486,25 +486,25 @@ void DeckLinkSession::UpdateScheduleLeadTelemetry() ? static_cast(streamTime / mScheduler.FrameDuration()) : 0; const uint64_t nextScheduleFrameIndex = mScheduler.ScheduledFrameIndex(); - mState.deckLinkScheduleLeadAvailable = true; - mState.deckLinkPlaybackStreamTime = streamTime; - mState.deckLinkPlaybackFrameIndex = playbackFrameIndex; - mState.deckLinkNextScheduleFrameIndex = nextScheduleFrameIndex; - mState.deckLinkScheduleLeadFrames = static_cast(nextScheduleFrameIndex) - static_cast(playbackFrameIndex); + mTelemetry.scheduleLeadAvailable = true; + mTelemetry.playbackStreamTime = streamTime; + mTelemetry.playbackFrameIndex = playbackFrameIndex; + mTelemetry.nextScheduleFrameIndex = nextScheduleFrameIndex; + mTelemetry.scheduleLeadFrames = static_cast(nextScheduleFrameIndex) - static_cast(playbackFrameIndex); } void DeckLinkSession::MaybeRealignScheduleCursorForLowLead() { - if (!mState.deckLinkScheduleLeadAvailable) + if (!mTelemetry.scheduleLeadAvailable) return; - if (mState.deckLinkScheduleLeadFrames >= kMinimumHealthyScheduleLeadFrames) + if (mTelemetry.scheduleLeadFrames >= kMinimumHealthyScheduleLeadFrames) { mProactiveScheduleRealignmentArmed = true; return; } - if (!mProactiveScheduleRealignmentArmed || mState.deckLinkScheduleLeadFrames > kProactiveScheduleLeadFloorFrames) + if (!mProactiveScheduleRealignmentArmed || mTelemetry.scheduleLeadFrames > kProactiveScheduleLeadFloorFrames) return; RealignScheduleCursorToPlayback(); @@ -523,7 +523,7 @@ void DeckLinkSession::RealignScheduleCursorToPlayback() const VideoPlayoutPolicy policy = NormalizeVideoPlayoutPolicy(mPlayoutPolicy); mScheduler.AlignNextScheduleTimeToPlayback(streamTime, policy.targetPrerollFrames); - ++mState.deckLinkScheduleRealignmentCount; + ++mTelemetry.scheduleRealignmentCount; UpdateScheduleLeadTelemetry(); } @@ -593,19 +593,19 @@ void DeckLinkSession::RefreshBufferedVideoFrameCount() { if (output == nullptr) { - mState.actualDeckLinkBufferedFramesAvailable = false; + mTelemetry.actualBufferedFramesAvailable = false; return; } unsigned int bufferedFrameCount = 0; if (output->GetBufferedVideoFrameCount(&bufferedFrameCount) == S_OK) { - mState.actualDeckLinkBufferedFrames = bufferedFrameCount; - mState.actualDeckLinkBufferedFramesAvailable = true; + mTelemetry.actualBufferedFrames = bufferedFrameCount; + mTelemetry.actualBufferedFramesAvailable = true; } else { - mState.actualDeckLinkBufferedFramesAvailable = false; + mTelemetry.actualBufferedFramesAvailable = false; } } diff --git a/src/video/decklink/DeckLinkSession.h b/src/video/decklink/DeckLinkSession.h index 7a82ba2..49d8f28 100644 --- a/src/video/decklink/DeckLinkSession.h +++ b/src/video/decklink/DeckLinkSession.h @@ -18,6 +18,20 @@ class OpenGLComposite; +struct DeckLinkSessionTelemetry +{ + bool actualBufferedFramesAvailable = false; + uint64_t actualBufferedFrames = 0; + double scheduleCallMilliseconds = 0.0; + uint64_t scheduleFailureCount = 0; + bool scheduleLeadAvailable = false; + int64_t playbackStreamTime = 0; + uint64_t playbackFrameIndex = 0; + uint64_t nextScheduleFrameIndex = 0; + int64_t scheduleLeadFrames = 0; + uint64_t scheduleRealignmentCount = 0; +}; + class DeckLinkSession { public: @@ -63,6 +77,7 @@ public: void SetStatusMessage(const std::string& message) { mState.statusMessage = message; } const VideoIOState& State() const { return mState; } VideoIOState& MutableState() { return mState; } + const DeckLinkSessionTelemetry& Telemetry() const { return mTelemetry; } double FrameBudgetMilliseconds() const; VideoPlayoutRecoveryDecision AccountForCompletionResult(VideoIOCompletionResult completionResult, uint64_t readyQueueDepth); bool BeginOutputFrame(VideoIOOutputFrame& frame); @@ -89,6 +104,7 @@ private: std::mutex mScheduledSystemFrameMutex; std::unordered_map mScheduledSystemFrameBuffers; VideoIOState mState; + DeckLinkSessionTelemetry mTelemetry; VideoPlayoutPolicy mPlayoutPolicy; VideoPlayoutScheduler mScheduler; bool mScheduleRealignmentPending = false;