Phase 7 done
This commit is contained in:
@@ -80,6 +80,35 @@ JsonValue RuntimeStatePresenter::BuildRuntimeStateValue(const RuntimeStore& runt
|
||||
performance.set("flushedFrameCount", JsonValue(static_cast<double>(telemetrySnapshot.performance.flushedFrameCount)));
|
||||
root.set("performance", performance);
|
||||
|
||||
JsonValue readyQueue = JsonValue::MakeObject();
|
||||
readyQueue.set("depth", JsonValue(static_cast<double>(telemetrySnapshot.backendPlayout.readyQueueDepth)));
|
||||
readyQueue.set("capacity", JsonValue(static_cast<double>(telemetrySnapshot.backendPlayout.readyQueueCapacity)));
|
||||
readyQueue.set("pushedCount", JsonValue(static_cast<double>(telemetrySnapshot.backendPlayout.readyQueuePushedCount)));
|
||||
readyQueue.set("poppedCount", JsonValue(static_cast<double>(telemetrySnapshot.backendPlayout.readyQueuePoppedCount)));
|
||||
readyQueue.set("droppedCount", JsonValue(static_cast<double>(telemetrySnapshot.backendPlayout.readyQueueDroppedCount)));
|
||||
readyQueue.set("underrunCount", JsonValue(static_cast<double>(telemetrySnapshot.backendPlayout.readyQueueUnderrunCount)));
|
||||
|
||||
JsonValue recovery = JsonValue::MakeObject();
|
||||
recovery.set("completionResult", JsonValue(telemetrySnapshot.backendPlayout.completionResult));
|
||||
recovery.set("completedFrameIndex", JsonValue(static_cast<double>(telemetrySnapshot.backendPlayout.completedFrameIndex)));
|
||||
recovery.set("scheduledFrameIndex", JsonValue(static_cast<double>(telemetrySnapshot.backendPlayout.scheduledFrameIndex)));
|
||||
recovery.set("scheduledLeadFrames", JsonValue(static_cast<double>(telemetrySnapshot.backendPlayout.scheduledLeadFrames)));
|
||||
recovery.set("measuredLagFrames", JsonValue(static_cast<double>(telemetrySnapshot.backendPlayout.measuredLagFrames)));
|
||||
recovery.set("catchUpFrames", JsonValue(static_cast<double>(telemetrySnapshot.backendPlayout.catchUpFrames)));
|
||||
recovery.set("lateStreak", JsonValue(static_cast<double>(telemetrySnapshot.backendPlayout.lateStreak)));
|
||||
recovery.set("dropStreak", JsonValue(static_cast<double>(telemetrySnapshot.backendPlayout.dropStreak)));
|
||||
|
||||
JsonValue backendPlayout = JsonValue::MakeObject();
|
||||
backendPlayout.set("lifecycleState", JsonValue(telemetrySnapshot.backendPlayout.lifecycleState));
|
||||
backendPlayout.set("degraded", JsonValue(telemetrySnapshot.backendPlayout.degraded));
|
||||
backendPlayout.set("statusMessage", JsonValue(telemetrySnapshot.backendPlayout.statusMessage));
|
||||
backendPlayout.set("lateFrameCount", JsonValue(static_cast<double>(telemetrySnapshot.backendPlayout.lateFrameCount)));
|
||||
backendPlayout.set("droppedFrameCount", JsonValue(static_cast<double>(telemetrySnapshot.backendPlayout.droppedFrameCount)));
|
||||
backendPlayout.set("flushedFrameCount", JsonValue(static_cast<double>(telemetrySnapshot.backendPlayout.flushedFrameCount)));
|
||||
backendPlayout.set("readyQueue", readyQueue);
|
||||
backendPlayout.set("recovery", recovery);
|
||||
root.set("backendPlayout", backendPlayout);
|
||||
|
||||
JsonValue eventQueue = JsonValue::MakeObject();
|
||||
eventQueue.set("name", JsonValue(telemetrySnapshot.runtimeEvents.queue.queueName));
|
||||
eventQueue.set("depth", JsonValue(static_cast<double>(telemetrySnapshot.runtimeEvents.queue.depth)));
|
||||
|
||||
@@ -207,6 +207,72 @@ bool HealthTelemetry::TryRecordPersistenceWriteResult(bool succeeded, const std:
|
||||
return true;
|
||||
}
|
||||
|
||||
void HealthTelemetry::RecordBackendPlayoutHealth(const std::string& lifecycleState, const std::string& completionResult,
|
||||
std::size_t readyQueueDepth, std::size_t readyQueueCapacity, uint64_t readyQueuePushedCount,
|
||||
uint64_t readyQueuePoppedCount, uint64_t readyQueueDroppedCount, uint64_t readyQueueUnderrunCount,
|
||||
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.readyQueuePushedCount = readyQueuePushedCount;
|
||||
mBackendPlayout.readyQueuePoppedCount = readyQueuePoppedCount;
|
||||
mBackendPlayout.readyQueueDroppedCount = readyQueueDroppedCount;
|
||||
mBackendPlayout.readyQueueUnderrunCount = readyQueueUnderrunCount;
|
||||
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,
|
||||
uint64_t readyQueuePoppedCount, uint64_t readyQueueDroppedCount, uint64_t readyQueueUnderrunCount,
|
||||
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.readyQueuePushedCount = readyQueuePushedCount;
|
||||
mBackendPlayout.readyQueuePoppedCount = readyQueuePoppedCount;
|
||||
mBackendPlayout.readyQueueDroppedCount = readyQueueDroppedCount;
|
||||
mBackendPlayout.readyQueueUnderrunCount = readyQueueUnderrunCount;
|
||||
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;
|
||||
}
|
||||
|
||||
HealthTelemetry::SignalStatusSnapshot HealthTelemetry::GetSignalStatusSnapshot() const
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mMutex);
|
||||
@@ -237,6 +303,12 @@ HealthTelemetry::PersistenceSnapshot HealthTelemetry::GetPersistenceSnapshot() c
|
||||
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);
|
||||
@@ -247,5 +319,6 @@ HealthTelemetry::Snapshot HealthTelemetry::GetSnapshot() const
|
||||
snapshot.performance = mPerformance;
|
||||
snapshot.runtimeEvents = mRuntimeEvents;
|
||||
snapshot.persistence = mPersistence;
|
||||
snapshot.backendPlayout = mBackendPlayout;
|
||||
return snapshot;
|
||||
}
|
||||
|
||||
@@ -81,6 +81,30 @@ public:
|
||||
std::string lastErrorMessage;
|
||||
};
|
||||
|
||||
struct BackendPlayoutSnapshot
|
||||
{
|
||||
std::string lifecycleState = "NotStarted";
|
||||
std::string completionResult = "Unknown";
|
||||
std::size_t readyQueueDepth = 0;
|
||||
std::size_t readyQueueCapacity = 0;
|
||||
uint64_t readyQueuePushedCount = 0;
|
||||
uint64_t readyQueuePoppedCount = 0;
|
||||
uint64_t readyQueueDroppedCount = 0;
|
||||
uint64_t readyQueueUnderrunCount = 0;
|
||||
uint64_t completedFrameIndex = 0;
|
||||
uint64_t scheduledFrameIndex = 0;
|
||||
uint64_t scheduledLeadFrames = 0;
|
||||
uint64_t measuredLagFrames = 0;
|
||||
uint64_t catchUpFrames = 0;
|
||||
uint64_t lateStreak = 0;
|
||||
uint64_t dropStreak = 0;
|
||||
uint64_t lateFrameCount = 0;
|
||||
uint64_t droppedFrameCount = 0;
|
||||
uint64_t flushedFrameCount = 0;
|
||||
bool degraded = false;
|
||||
std::string statusMessage;
|
||||
};
|
||||
|
||||
struct Snapshot
|
||||
{
|
||||
SignalStatusSnapshot signal;
|
||||
@@ -88,6 +112,7 @@ public:
|
||||
PerformanceSnapshot performance;
|
||||
RuntimeEventMetricsSnapshot runtimeEvents;
|
||||
PersistenceSnapshot persistence;
|
||||
BackendPlayoutSnapshot backendPlayout;
|
||||
};
|
||||
|
||||
HealthTelemetry() = default;
|
||||
@@ -125,11 +150,27 @@ public:
|
||||
bool TryRecordPersistenceWriteResult(bool succeeded, const std::string& targetKind, const std::string& targetPath,
|
||||
const std::string& reason, const std::string& errorMessage, bool newerRequestPending);
|
||||
|
||||
void RecordBackendPlayoutHealth(const std::string& lifecycleState, const std::string& completionResult,
|
||||
std::size_t readyQueueDepth, std::size_t readyQueueCapacity, uint64_t readyQueuePushedCount,
|
||||
uint64_t readyQueuePoppedCount, uint64_t readyQueueDroppedCount, uint64_t readyQueueUnderrunCount,
|
||||
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);
|
||||
bool TryRecordBackendPlayoutHealth(const std::string& lifecycleState, const std::string& completionResult,
|
||||
std::size_t readyQueueDepth, std::size_t readyQueueCapacity, uint64_t readyQueuePushedCount,
|
||||
uint64_t readyQueuePoppedCount, uint64_t readyQueueDroppedCount, uint64_t readyQueueUnderrunCount,
|
||||
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);
|
||||
|
||||
SignalStatusSnapshot GetSignalStatusSnapshot() const;
|
||||
VideoIOStatusSnapshot GetVideoIOStatusSnapshot() const;
|
||||
PerformanceSnapshot GetPerformanceSnapshot() const;
|
||||
RuntimeEventMetricsSnapshot GetRuntimeEventMetricsSnapshot() const;
|
||||
PersistenceSnapshot GetPersistenceSnapshot() const;
|
||||
BackendPlayoutSnapshot GetBackendPlayoutSnapshot() const;
|
||||
Snapshot GetSnapshot() const;
|
||||
|
||||
private:
|
||||
@@ -139,4 +180,5 @@ private:
|
||||
PerformanceSnapshot mPerformance;
|
||||
RuntimeEventMetricsSnapshot mRuntimeEvents;
|
||||
PersistenceSnapshot mPersistence;
|
||||
BackendPlayoutSnapshot mBackendPlayout;
|
||||
};
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user