telemetry and timing updates
All checks were successful
CI / React UI Build (push) Successful in 10s
CI / Native Windows Build And Tests (push) Successful in 2m58s
CI / Windows Release Package (push) Has been skipped

This commit is contained in:
Aiden
2026-05-13 00:21:28 +10:00
parent d411453f80
commit 5c1fc2a6cf
24 changed files with 260 additions and 38 deletions

View File

@@ -532,17 +532,13 @@ bool DeckLinkSession::ScheduleFrame(IDeckLinkMutableVideoFrame* outputVideoFrame
return false;
}
BMDTimeValue streamTime = 0;
double playbackSpeed = 0.0;
if (output->GetScheduledStreamTime(mScheduler.TimeScale(), &streamTime, &playbackSpeed) == S_OK && playbackSpeed > 0.0)
if (mScheduleRealignmentPending)
{
RefreshBufferedVideoFrameCount();
const uint64_t leadFrames = mState.actualDeckLinkBufferedFramesAvailable
? static_cast<uint64_t>(mState.actualDeckLinkBufferedFrames) + 1
: static_cast<uint64_t>(mPlayoutPolicy.targetPrerollFrames);
mScheduler.AlignNextScheduleTimeToPlayback(streamTime, leadFrames);
RealignScheduleCursorToPlayback();
mScheduleRealignmentPending = false;
}
UpdateScheduleLeadTelemetry();
const VideoIOScheduleTime scheduleTime = mScheduler.NextScheduleTime();
const auto scheduleStart = std::chrono::steady_clock::now();
const HRESULT result = output->ScheduleVideoFrame(outputVideoFrame, scheduleTime.streamTime, scheduleTime.duration, scheduleTime.timeScale);
@@ -554,6 +550,49 @@ bool DeckLinkSession::ScheduleFrame(IDeckLinkMutableVideoFrame* outputVideoFrame
return result == S_OK;
}
void DeckLinkSession::UpdateScheduleLeadTelemetry()
{
if (output == nullptr)
{
mState.deckLinkScheduleLeadAvailable = false;
return;
}
BMDTimeValue streamTime = 0;
double playbackSpeed = 0.0;
if (output->GetScheduledStreamTime(mScheduler.TimeScale(), &streamTime, &playbackSpeed) != S_OK || playbackSpeed <= 0.0)
{
mState.deckLinkScheduleLeadAvailable = false;
return;
}
const uint64_t playbackFrameIndex = streamTime >= 0 && mScheduler.FrameDuration() > 0
? static_cast<uint64_t>(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<int64_t>(nextScheduleFrameIndex) - static_cast<int64_t>(playbackFrameIndex);
}
void DeckLinkSession::RealignScheduleCursorToPlayback()
{
if (output == nullptr)
return;
BMDTimeValue streamTime = 0;
double playbackSpeed = 0.0;
if (output->GetScheduledStreamTime(mScheduler.TimeScale(), &streamTime, &playbackSpeed) != S_OK || playbackSpeed <= 0.0)
return;
const VideoPlayoutPolicy policy = NormalizeVideoPlayoutPolicy(mPlayoutPolicy);
mScheduler.AlignNextScheduleTimeToPlayback(streamTime, policy.targetPrerollFrames);
++mState.deckLinkScheduleRealignmentCount;
UpdateScheduleLeadTelemetry();
}
bool DeckLinkSession::ScheduleSystemMemoryFrame(const VideoIOOutputFrame& frame)
{
if (output == nullptr || frame.bytes == nullptr || frame.rowBytes <= 0 || frame.height == 0)
@@ -838,6 +877,18 @@ void DeckLinkSession::HandlePlayoutFrameCompleted(IDeckLinkVideoFrame* completed
VideoIOCompletion completion;
completion.result = TranslateCompletionResult(completionResult);
if (completion.result == VideoIOCompletionResult::DisplayedLate || completion.result == VideoIOCompletionResult::Dropped)
{
if (mScheduleRealignmentArmed)
{
mScheduleRealignmentPending = true;
mScheduleRealignmentArmed = false;
}
}
else if (completion.result == VideoIOCompletionResult::Completed)
{
mScheduleRealignmentArmed = true;
}
completion.outputFrameBuffer = completedSystemBuffer;
mOutputFrameCallback(completion);
}

View File

@@ -75,6 +75,8 @@ private:
bool AcquireNextOutputVideoFrame(CComPtr<IDeckLinkMutableVideoFrame>& outputVideoFrame);
bool PopulateOutputFrame(IDeckLinkMutableVideoFrame* outputVideoFrame, VideoIOOutputFrame& frame);
bool ScheduleFrame(IDeckLinkMutableVideoFrame* outputVideoFrame);
void UpdateScheduleLeadTelemetry();
void RealignScheduleCursorToPlayback();
bool ScheduleSystemMemoryFrame(const VideoIOOutputFrame& frame);
bool ScheduleBlackFrame(IDeckLinkMutableVideoFrame* outputVideoFrame);
void RefreshBufferedVideoFrameCount();
@@ -91,6 +93,8 @@ private:
VideoIOState mState;
VideoPlayoutPolicy mPlayoutPolicy;
VideoPlayoutScheduler mScheduler;
bool mScheduleRealignmentPending = false;
bool mScheduleRealignmentArmed = true;
InputFrameCallback mInputFrameCallback;
OutputFrameCallback mOutputFrameCallback;
};