Phase 7 done
All checks were successful
CI / React UI Build (push) Successful in 10s
CI / Native Windows Build And Tests (push) Successful in 2m47s
CI / Windows Release Package (push) Successful in 3m2s

This commit is contained in:
Aiden
2026-05-11 21:15:51 +10:00
parent f288455709
commit 0a7954e879
12 changed files with 289 additions and 27 deletions

View File

@@ -146,9 +146,9 @@ bool VideoBackend::ScheduleOutputFrame(const VideoIOOutputFrame& frame)
return mVideoIODevice->ScheduleOutputFrame(frame);
}
void VideoBackend::AccountForCompletionResult(VideoIOCompletionResult result, uint64_t readyQueueDepth)
VideoPlayoutRecoveryDecision VideoBackend::AccountForCompletionResult(VideoIOCompletionResult result, uint64_t readyQueueDepth)
{
mVideoIODevice->AccountForCompletionResult(result, readyQueueDepth);
return mVideoIODevice->AccountForCompletionResult(result, readyQueueDepth);
}
bool VideoBackend::HasInputDevice() const
@@ -347,11 +347,38 @@ void VideoBackend::ProcessOutputFrameCompletion(const VideoIOCompletion& complet
{
RecordFramePacing(completion.result);
PublishOutputFrameCompleted(completion);
AccountForCompletionResult(completion.result, mReadyOutputQueue.GetMetrics().depth);
const VideoPlayoutRecoveryDecision recoveryDecision = AccountForCompletionResult(completion.result, mReadyOutputQueue.GetMetrics().depth);
FillReadyOutputQueue(completion);
if (!ScheduleReadyOutputFrame())
ScheduleBlackUnderrunFrame();
RecordBackendPlayoutHealth(completion.result, recoveryDecision);
}
void VideoBackend::RecordBackendPlayoutHealth(VideoIOCompletionResult result, const VideoPlayoutRecoveryDecision& recoveryDecision)
{
const RenderOutputQueueMetrics queueMetrics = mReadyOutputQueue.GetMetrics();
mHealthTelemetry.TryRecordBackendPlayoutHealth(
VideoBackendLifecycle::StateName(mLifecycle.State()),
CompletionResultName(result),
queueMetrics.depth,
queueMetrics.capacity,
queueMetrics.pushedCount,
queueMetrics.poppedCount,
queueMetrics.droppedCount,
queueMetrics.underrunCount,
recoveryDecision.completedFrameIndex,
recoveryDecision.scheduledFrameIndex,
recoveryDecision.scheduledLeadFrames,
recoveryDecision.measuredLagFrames,
recoveryDecision.catchUpFrames,
recoveryDecision.lateStreak,
recoveryDecision.dropStreak,
mLateFrameCount,
mDroppedFrameCount,
mFlushedFrameCount,
mLifecycle.State() == VideoBackendLifecycleState::Degraded,
StatusMessage());
}
bool VideoBackend::FillReadyOutputQueue(const VideoIOCompletion& completion)

View File

@@ -40,7 +40,8 @@ public:
bool BeginOutputFrame(VideoIOOutputFrame& frame);
void EndOutputFrame(VideoIOOutputFrame& frame);
bool ScheduleOutputFrame(const VideoIOOutputFrame& frame);
void AccountForCompletionResult(VideoIOCompletionResult result, uint64_t readyQueueDepth);
VideoPlayoutRecoveryDecision AccountForCompletionResult(VideoIOCompletionResult result, uint64_t readyQueueDepth);
void RecordBackendPlayoutHealth(VideoIOCompletionResult result, const VideoPlayoutRecoveryDecision& recoveryDecision);
bool HasInputDevice() const;
bool HasInputSource() const;

View File

@@ -86,6 +86,19 @@ struct VideoIOScheduleTime
uint64_t frameIndex = 0;
};
struct VideoPlayoutRecoveryDecision
{
VideoIOCompletionResult result = VideoIOCompletionResult::Completed;
uint64_t completedFrameIndex = 0;
uint64_t scheduledFrameIndex = 0;
uint64_t readyQueueDepth = 0;
uint64_t scheduledLeadFrames = 0;
uint64_t measuredLagFrames = 0;
uint64_t catchUpFrames = 0;
uint64_t lateStreak = 0;
uint64_t dropStreak = 0;
};
class VideoIODevice
{
public:
@@ -105,7 +118,7 @@ public:
virtual bool BeginOutputFrame(VideoIOOutputFrame& frame) = 0;
virtual void EndOutputFrame(VideoIOOutputFrame& frame) = 0;
virtual bool ScheduleOutputFrame(const VideoIOOutputFrame& frame) = 0;
virtual void AccountForCompletionResult(VideoIOCompletionResult result, uint64_t readyQueueDepth) = 0;
virtual VideoPlayoutRecoveryDecision AccountForCompletionResult(VideoIOCompletionResult result, uint64_t readyQueueDepth) = 0;
bool HasInputDevice() const { return State().hasInputDevice; }
bool HasInputSource() const { return State().hasInputSource; }

View File

@@ -5,19 +5,6 @@
#include <cstdint>
struct VideoPlayoutRecoveryDecision
{
VideoIOCompletionResult result = VideoIOCompletionResult::Completed;
uint64_t completedFrameIndex = 0;
uint64_t scheduledFrameIndex = 0;
uint64_t readyQueueDepth = 0;
uint64_t scheduledLeadFrames = 0;
uint64_t measuredLagFrames = 0;
uint64_t catchUpFrames = 0;
uint64_t lateStreak = 0;
uint64_t dropStreak = 0;
};
class VideoPlayoutScheduler
{
public:

View File

@@ -498,9 +498,9 @@ void DeckLinkSession::EndOutputFrame(VideoIOOutputFrame& frame)
frame.bytes = nullptr;
}
void DeckLinkSession::AccountForCompletionResult(VideoIOCompletionResult completionResult, uint64_t readyQueueDepth)
VideoPlayoutRecoveryDecision DeckLinkSession::AccountForCompletionResult(VideoIOCompletionResult completionResult, uint64_t readyQueueDepth)
{
mScheduler.AccountForCompletionResult(completionResult, readyQueueDepth);
return mScheduler.AccountForCompletionResult(completionResult, readyQueueDepth);
}
bool DeckLinkSession::ScheduleOutputFrame(const VideoIOOutputFrame& frame)

View File

@@ -59,7 +59,7 @@ public:
const VideoIOState& State() const override { return mState; }
VideoIOState& MutableState() override { return mState; }
double FrameBudgetMilliseconds() const;
void AccountForCompletionResult(VideoIOCompletionResult completionResult, uint64_t readyQueueDepth) override;
VideoPlayoutRecoveryDecision AccountForCompletionResult(VideoIOCompletionResult completionResult, uint64_t readyQueueDepth) override;
bool BeginOutputFrame(VideoIOOutputFrame& frame) override;
void EndOutputFrame(VideoIOOutputFrame& frame) override;
bool ScheduleOutputFrame(const VideoIOOutputFrame& frame) override;