Improvement
This commit is contained in:
@@ -34,6 +34,7 @@ void VideoBackend::ReleaseResources()
|
||||
mReadyOutputQueue.Clear();
|
||||
if (mVideoIODevice)
|
||||
mVideoIODevice->ReleaseResources();
|
||||
mSystemOutputFramePool.Clear();
|
||||
if (!VideoBackendLifecycle::CanTransition(mLifecycle.State(), VideoBackendLifecycleState::Stopped))
|
||||
ApplyLifecycleFailure("Video backend resources released before lifecycle completed.");
|
||||
ApplyLifecycleTransition(VideoBackendLifecycleState::Stopped, "Video backend resources released.");
|
||||
@@ -95,6 +96,14 @@ bool VideoBackend::ConfigureOutput(const VideoFormat& outputVideoMode, bool exte
|
||||
ApplyLifecycleFailure(error.empty() ? "Video backend output configuration failed." : error);
|
||||
return false;
|
||||
}
|
||||
SystemOutputFramePoolConfig poolConfig;
|
||||
poolConfig.width = mVideoIODevice->OutputFrameWidth();
|
||||
poolConfig.height = mVideoIODevice->OutputFrameHeight();
|
||||
poolConfig.pixelFormat = mVideoIODevice->OutputPixelFormat();
|
||||
poolConfig.rowBytes = mVideoIODevice->OutputFrameRowBytes();
|
||||
poolConfig.capacity = mPlayoutPolicy.outputFramePoolSize;
|
||||
mSystemOutputFramePool.Configure(poolConfig);
|
||||
RecordSystemMemoryPlayoutStats();
|
||||
return ApplyLifecycleTransition(VideoBackendLifecycleState::Configured, "Video backend configured.");
|
||||
}
|
||||
|
||||
@@ -460,6 +469,8 @@ std::chrono::milliseconds VideoBackend::OutputProducerWakeInterval() const
|
||||
|
||||
void VideoBackend::ProcessOutputFrameCompletion(const VideoIOCompletion& completion)
|
||||
{
|
||||
if (completion.outputFrameBuffer != nullptr)
|
||||
mSystemOutputFramePool.ReleaseSlotByBuffer(completion.outputFrameBuffer);
|
||||
RecordFramePacing(completion.result);
|
||||
PublishOutputFrameCompleted(completion);
|
||||
const RenderOutputQueueMetrics initialQueueMetrics = mReadyOutputQueue.GetMetrics();
|
||||
@@ -483,6 +494,7 @@ void VideoBackend::ProcessOutputFrameCompletion(const VideoIOCompletion& complet
|
||||
}
|
||||
NotifyOutputProducer();
|
||||
RecordBackendPlayoutHealth(completion.result, recoveryDecision);
|
||||
RecordSystemMemoryPlayoutStats();
|
||||
}
|
||||
|
||||
void VideoBackend::RecordBackendPlayoutHealth(VideoIOCompletionResult result, const VideoPlayoutRecoveryDecision& recoveryDecision)
|
||||
@@ -582,10 +594,12 @@ OutputProductionPressure VideoBackend::BuildOutputProductionPressure(const Rende
|
||||
bool VideoBackend::RenderReadyOutputFrame(const VideoIOState& state, const VideoIOCompletion& completion)
|
||||
{
|
||||
const auto renderStart = std::chrono::steady_clock::now();
|
||||
OutputFrameSlot outputSlot;
|
||||
VideoIOOutputFrame outputFrame;
|
||||
const auto acquireStart = std::chrono::steady_clock::now();
|
||||
if (!BeginOutputFrame(outputFrame))
|
||||
if (!mSystemOutputFramePool.AcquireFreeSlot(outputSlot))
|
||||
return false;
|
||||
outputFrame = outputSlot.frame;
|
||||
const auto acquireEnd = std::chrono::steady_clock::now();
|
||||
|
||||
bool rendered = true;
|
||||
@@ -595,7 +609,7 @@ bool VideoBackend::RenderReadyOutputFrame(const VideoIOState& state, const Video
|
||||
const auto renderRequestEnd = std::chrono::steady_clock::now();
|
||||
|
||||
const auto endAccessStart = std::chrono::steady_clock::now();
|
||||
EndOutputFrame(outputFrame);
|
||||
const bool publishedReady = mSystemOutputFramePool.PublishReadySlot(outputSlot);
|
||||
const auto endAccessEnd = std::chrono::steady_clock::now();
|
||||
const double acquireMilliseconds = std::chrono::duration_cast<std::chrono::duration<double, std::milli>>(acquireEnd - acquireStart).count();
|
||||
const double renderRequestMilliseconds = std::chrono::duration_cast<std::chrono::duration<double, std::milli>>(renderRequestEnd - renderRequestStart).count();
|
||||
@@ -603,15 +617,17 @@ bool VideoBackend::RenderReadyOutputFrame(const VideoIOState& state, const Video
|
||||
|
||||
if (!rendered)
|
||||
{
|
||||
mSystemOutputFramePool.ReleaseSlot(outputSlot);
|
||||
ApplyLifecycleTransition(VideoBackendLifecycleState::Degraded, "Output frame render request failed; skipping schedule for this frame.");
|
||||
const double renderMilliseconds = std::chrono::duration_cast<std::chrono::duration<double, std::milli>>(
|
||||
std::chrono::steady_clock::now() - renderStart).count();
|
||||
RecordOutputRenderDuration(renderMilliseconds, acquireMilliseconds, renderRequestMilliseconds, endAccessMilliseconds);
|
||||
if (outputFrame.nativeFrame != nullptr)
|
||||
{
|
||||
static_cast<IUnknown*>(outputFrame.nativeFrame)->Release();
|
||||
outputFrame.nativeFrame = nullptr;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!publishedReady)
|
||||
{
|
||||
mSystemOutputFramePool.ReleaseSlot(outputSlot);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -622,12 +638,13 @@ bool VideoBackend::RenderReadyOutputFrame(const VideoIOState& state, const Video
|
||||
RenderOutputFrame readyFrame;
|
||||
readyFrame.frame = outputFrame;
|
||||
readyFrame.frameIndex = ++mNextReadyOutputFrameIndex;
|
||||
readyFrame.releaseFrame = [this](VideoIOOutputFrame& frame) {
|
||||
mSystemOutputFramePool.ReleaseSlotByBuffer(frame.bytes);
|
||||
};
|
||||
const bool pushed = mReadyOutputQueue.Push(readyFrame);
|
||||
if (!pushed && outputFrame.nativeFrame != nullptr)
|
||||
{
|
||||
static_cast<IUnknown*>(outputFrame.nativeFrame)->Release();
|
||||
outputFrame.nativeFrame = nullptr;
|
||||
}
|
||||
if (!pushed)
|
||||
mSystemOutputFramePool.ReleaseSlot(outputSlot);
|
||||
RecordSystemMemoryPlayoutStats();
|
||||
return pushed;
|
||||
}
|
||||
|
||||
@@ -638,10 +655,21 @@ bool VideoBackend::ScheduleReadyOutputFrame()
|
||||
return false;
|
||||
RecordReadyQueueDepthSample(mReadyOutputQueue.GetMetrics());
|
||||
|
||||
if (!ScheduleOutputFrame(readyFrame.frame))
|
||||
if (!mSystemOutputFramePool.MarkScheduledByBuffer(readyFrame.frame.bytes))
|
||||
{
|
||||
if (readyFrame.releaseFrame)
|
||||
readyFrame.releaseFrame(readyFrame.frame);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ScheduleOutputFrame(readyFrame.frame))
|
||||
{
|
||||
mSystemOutputFramePool.ReleaseSlotByBuffer(readyFrame.frame.bytes);
|
||||
return false;
|
||||
}
|
||||
|
||||
PublishOutputFrameScheduled(readyFrame.frame);
|
||||
RecordSystemMemoryPlayoutStats();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -721,6 +749,21 @@ void VideoBackend::RecordReadyQueueDepthSample(const RenderOutputQueueMetrics& m
|
||||
++mReadyQueueZeroDepthCount;
|
||||
}
|
||||
|
||||
void VideoBackend::RecordSystemMemoryPlayoutStats()
|
||||
{
|
||||
const SystemOutputFramePoolMetrics poolMetrics = mSystemOutputFramePool.GetMetrics();
|
||||
const RenderOutputQueueMetrics queueMetrics = mReadyOutputQueue.GetMetrics();
|
||||
mHealthTelemetry.TryRecordSystemMemoryPlayoutStats(
|
||||
poolMetrics.freeCount,
|
||||
poolMetrics.readyCount,
|
||||
poolMetrics.scheduledCount,
|
||||
poolMetrics.readyUnderrunCount,
|
||||
0,
|
||||
queueMetrics.droppedCount,
|
||||
0.0,
|
||||
0.0);
|
||||
}
|
||||
|
||||
void VideoBackend::RecordOutputRenderDuration(double renderMilliseconds, double acquireMilliseconds, double renderRequestMilliseconds, double endAccessMilliseconds)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mOutputMetricsMutex);
|
||||
|
||||
Reference in New Issue
Block a user