Frame timing
This commit is contained in:
@@ -359,6 +359,12 @@ void VideoBackend::StartOutputProducerWorker()
|
||||
if (mOutputProducerWorkerRunning)
|
||||
return;
|
||||
|
||||
const double frameBudgetMilliseconds = State().frameBudgetMilliseconds;
|
||||
const auto frameDuration = frameBudgetMilliseconds > 0.0
|
||||
? std::chrono::duration_cast<RenderCadenceController::Duration>(
|
||||
std::chrono::duration<double, std::milli>(frameBudgetMilliseconds))
|
||||
: std::chrono::milliseconds(16);
|
||||
mRenderCadenceController.Configure(frameDuration, std::chrono::steady_clock::now());
|
||||
mLastOutputProductionCompletion = VideoIOCompletion();
|
||||
mLastOutputProductionTime = std::chrono::steady_clock::time_point();
|
||||
mOutputProducerWorkerStopping = false;
|
||||
@@ -433,11 +439,16 @@ void VideoBackend::OutputProducerWorkerMain()
|
||||
|
||||
const RenderOutputQueueMetrics metrics = mReadyOutputQueue.GetMetrics();
|
||||
RecordReadyQueueDepthSample(metrics);
|
||||
const OutputProductionDecision decision = mOutputProductionController.Decide(BuildOutputProductionPressure(metrics));
|
||||
if (decision.action != OutputProductionAction::Produce || decision.requestedFrames == 0)
|
||||
|
||||
const auto now = std::chrono::steady_clock::now();
|
||||
RenderCadenceDecision cadenceDecision = mRenderCadenceController.Tick(now);
|
||||
if (cadenceDecision.action == RenderCadenceAction::Wait)
|
||||
{
|
||||
const auto waitDuration = (std::min)(
|
||||
std::chrono::duration_cast<std::chrono::milliseconds>(cadenceDecision.waitDuration),
|
||||
OutputProducerWakeInterval());
|
||||
std::unique_lock<std::mutex> lock(mOutputProducerMutex);
|
||||
mOutputProducerCondition.wait_for(lock, OutputProducerWakeInterval());
|
||||
mOutputProducerCondition.wait_for(lock, waitDuration);
|
||||
if (mOutputProducerWorkerStopping)
|
||||
{
|
||||
mOutputProducerWorkerRunning = false;
|
||||
@@ -454,16 +465,7 @@ void VideoBackend::OutputProducerWorkerMain()
|
||||
completion = mLastOutputProductionCompletion;
|
||||
}
|
||||
|
||||
const bool belowTargetDepth = metrics.depth < decision.targetReadyFrames;
|
||||
const auto now = std::chrono::steady_clock::now();
|
||||
if (!belowTargetDepth &&
|
||||
mLastOutputProductionTime != std::chrono::steady_clock::time_point() &&
|
||||
now - mLastOutputProductionTime < OutputProducerWakeInterval())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const std::size_t producedFrames = ProduceReadyOutputFrames(completion, decision.requestedFrames);
|
||||
const std::size_t producedFrames = ProduceReadyOutputFrames(completion, 1);
|
||||
if (producedFrames > 0)
|
||||
{
|
||||
mLastOutputProductionTime = std::chrono::steady_clock::now();
|
||||
@@ -600,10 +602,6 @@ std::size_t VideoBackend::ProduceReadyOutputFrames(const VideoIOCompletion& comp
|
||||
std::size_t producedFrames = 0;
|
||||
while (producedFrames < maxFrames)
|
||||
{
|
||||
const OutputProductionDecision decision = mOutputProductionController.Decide(BuildOutputProductionPressure(metrics));
|
||||
if (decision.action != OutputProductionAction::Produce)
|
||||
break;
|
||||
|
||||
if (!RenderReadyOutputFrame(mVideoIODevice->State(), completion))
|
||||
break;
|
||||
++producedFrames;
|
||||
@@ -634,7 +632,10 @@ bool VideoBackend::RenderReadyOutputFrame(const VideoIOState& state, const Video
|
||||
VideoIOOutputFrame outputFrame;
|
||||
const auto acquireStart = std::chrono::steady_clock::now();
|
||||
if (!mSystemOutputFramePool.AcquireFreeSlot(outputSlot))
|
||||
return false;
|
||||
{
|
||||
if (!mReadyOutputQueue.DropOldestFrame() || !mSystemOutputFramePool.AcquireFreeSlot(outputSlot))
|
||||
return false;
|
||||
}
|
||||
outputFrame = outputSlot.frame;
|
||||
const auto acquireEnd = std::chrono::steady_clock::now();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user