Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
135 changes: 71 additions & 64 deletions nativelib/src/main/cpp/native_render.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ void NativeRender::SetVsyncEnabled(bool enable) {
bool wasEnabled = vsyncEnabled_.exchange(enable);
if (wasEnabled != enable) {
{
std::lock_guard<std::mutex> lock(presentationMutex_);
std::unique_lock<std::mutex> lock(presentationMutex_);
ResetPresentationClockLocked();
ResetPresentationStatsLocked();
}
Expand Down Expand Up @@ -438,6 +438,8 @@ void NativeRender::ResetPresentationStatsLocked() {
precisePhaseShiftCount_ = 0;
preciseRebufferCount_ = 0;
preciseResyncCount_ = 0;
preciseQueueFullCount_ = 0;
preciseWaitForDrainCount_ = 0;
preciseApiFailureCount_ = 0;
preciseMaxTargetLeadNs_ = 0;
presentationDiagnostics_.Reset();
Expand Down Expand Up @@ -551,69 +553,77 @@ NativeRender::FrameSubmitResult NativeRender::SubmitFrame(const DecodedFrame& fr
} else {
const int64_t decodedAtNs = GetMonotonicTimeNs();
RequestVSyncSample(decodedAtNs);
PresentationPlan plan;
{
std::lock_guard<std::mutex> lock(presentationMutex_);
plan = ptsScheduler_.PlanFrame(frame.ptsUs, decodedAtNs);
if (plan.action == PresentationAction::SCHEDULE) {
preciseScheduledCount_++;
} else {
preciseDroppedCount_++;
}
if (plan.latenessNs > 0) preciseLateCount_++;
if (plan.event == PresentationEvent::CATCH_UP) {
preciseCatchUpCount_++;
}
if (plan.event == PresentationEvent::PHASE_SHIFT) precisePhaseShiftCount_++;
if (plan.event == PresentationEvent::REBUFFER) preciseRebufferCount_++;
if (plan.event == PresentationEvent::DISCONTINUITY ||
plan.event == PresentationEvent::DUPLICATE_PTS) {
preciseResyncCount_++;
}
const int64_t observedVsyncNs =
g_observedVsyncTimestampNs.load(std::memory_order_acquire);
const int64_t observedVsyncPeriodNs =
g_observedVsyncPeriodNs.load(std::memory_order_acquire);
if (plan.action == PresentationAction::SCHEDULE) {
preciseMaxTargetLeadNs_ = std::max(
preciseMaxTargetLeadNs_, plan.targetTimeNs - decodedAtNs);
presentationDiagnostics_.Record(
plan.targetTimeNs, decodedAtNs,
observedVsyncNs, observedVsyncPeriodNs);
}
const int64_t observedVsyncNs =
g_observedVsyncTimestampNs.load(std::memory_order_acquire);
const int64_t observedVsyncPeriodNs =
g_observedVsyncPeriodNs.load(std::memory_order_acquire);
const PresentationVsyncTiming vsyncTiming = {
observedVsyncNs, observedVsyncPeriodNs};

// Keep planning and timed submission ordered even if a codec emits
// output callbacks concurrently.
std::unique_lock<std::mutex> lock(presentationMutex_);
const PresentationPlan plan = ptsScheduler_.PlanFrame(
frame.ptsUs, decodedAtNs, vsyncTiming);
if (plan.action == PresentationAction::SCHEDULE) {
preciseScheduledCount_++;
} else {
preciseDroppedCount_++;
}
if (plan.latenessNs > 0) preciseLateCount_++;
if (plan.event == PresentationEvent::CATCH_UP) preciseCatchUpCount_++;
if (plan.event == PresentationEvent::PHASE_SHIFT) precisePhaseShiftCount_++;
if (plan.event == PresentationEvent::REBUFFER) preciseRebufferCount_++;
if (plan.event == PresentationEvent::DISCONTINUITY ||
plan.event == PresentationEvent::DUPLICATE_PTS) {
preciseResyncCount_++;
}
if (plan.event == PresentationEvent::QUEUE_FULL) preciseQueueFullCount_++;
if (plan.event == PresentationEvent::WAIT_FOR_DRAIN) {
preciseWaitForDrainCount_++;
}
if (plan.action == PresentationAction::SCHEDULE) {
preciseMaxTargetLeadNs_ = std::max(
preciseMaxTargetLeadNs_, plan.targetTimeNs - decodedAtNs);
presentationDiagnostics_.Record(
plan.targetTimeNs, decodedAtNs,
observedVsyncNs, observedVsyncPeriodNs);
}

const int64_t totalFrames = preciseScheduledCount_ + preciseDroppedCount_;
if (totalFrames % kHostPacedStatsLogIntervalFrames == 0) {
const PresentationTimingStats& timing =
presentationDiagnostics_.GetStats();
OH_LOG_INFO(LOG_APP,
"Host-paced stats: frames=%{public}lld, scheduled=%{public}lld, dropped=%{public}lld, late=%{public}lld, catchUp=%{public}lld, phaseShift=%{public}lld, rebuffer=%{public}lld, resync=%{public}lld, apiFailure=%{public}lld, lead=%{public}lldus, maxLead=%{public}lldus, sameSlot=%{public}lld, slotRegression=%{public}lld, targetRegression=%{public}lld, maxRegression=%{public}lldus, maxQueueSlots=%{public}lld, vsyncPeriod=%{public}lldus, vsyncAge=%{public}lldus, vsyncSampleFailure=%{public}lld",
static_cast<long long>(totalFrames),
static_cast<long long>(preciseScheduledCount_),
static_cast<long long>(preciseDroppedCount_),
static_cast<long long>(preciseLateCount_),
static_cast<long long>(preciseCatchUpCount_),
static_cast<long long>(precisePhaseShiftCount_),
static_cast<long long>(preciseRebufferCount_),
static_cast<long long>(preciseResyncCount_),
static_cast<long long>(preciseApiFailureCount_),
static_cast<long long>(ptsScheduler_.GetInitialLeadNs() / 1000),
static_cast<long long>(preciseMaxTargetLeadNs_ / 1000),
static_cast<long long>(timing.sameVsyncSlotCount),
static_cast<long long>(timing.vsyncSlotRegressionCount),
static_cast<long long>(timing.targetRegressionCount),
static_cast<long long>(timing.maxTargetRegressionNs / 1000),
static_cast<long long>(timing.maxQueueDepthSlots),
static_cast<long long>(observedVsyncPeriodNs / 1000),
static_cast<long long>(observedVsyncNs > 0
? std::max<int64_t>(0, decodedAtNs - observedVsyncNs) / 1000
: 0),
static_cast<long long>(g_vsyncSampleRequestFailures.load(
std::memory_order_relaxed)));
}
const int64_t totalFrames = preciseScheduledCount_ + preciseDroppedCount_;
if (totalFrames % kHostPacedStatsLogIntervalFrames == 0) {
const PresentationTimingStats& timing =
presentationDiagnostics_.GetStats();
OH_LOG_INFO(LOG_APP,
"Host-paced stats: frames=%{public}lld, scheduled=%{public}lld, dropped=%{public}lld, late=%{public}lld, catchUp=%{public}lld, phaseShift=%{public}lld, rebuffer=%{public}lld, resync=%{public}lld, queueFull=%{public}lld, waitDrain=%{public}lld, apiFailure=%{public}lld, lead=%{public}lldus, maxLead=%{public}lldus, sameSlot=%{public}lld, slotRegression=%{public}lld, targetRegression=%{public}lld, maxRegression=%{public}lldus, maxQueueSlots=%{public}lld, vsyncPeriod=%{public}lldus, vsyncAge=%{public}lldus, vsyncSampleFailure=%{public}lld",
static_cast<long long>(totalFrames),
static_cast<long long>(preciseScheduledCount_),
static_cast<long long>(preciseDroppedCount_),
static_cast<long long>(preciseLateCount_),
static_cast<long long>(preciseCatchUpCount_),
static_cast<long long>(precisePhaseShiftCount_),
static_cast<long long>(preciseRebufferCount_),
static_cast<long long>(preciseResyncCount_),
static_cast<long long>(preciseQueueFullCount_),
static_cast<long long>(preciseWaitForDrainCount_),
static_cast<long long>(preciseApiFailureCount_),
static_cast<long long>(ptsScheduler_.GetInitialLeadNs() / 1000),
static_cast<long long>(preciseMaxTargetLeadNs_ / 1000),
static_cast<long long>(timing.sameVsyncSlotCount),
static_cast<long long>(timing.vsyncSlotRegressionCount),
static_cast<long long>(timing.targetRegressionCount),
static_cast<long long>(timing.maxTargetRegressionNs / 1000),
static_cast<long long>(timing.maxQueueDepthSlots),
static_cast<long long>(observedVsyncPeriodNs / 1000),
static_cast<long long>(observedVsyncNs > 0
? std::max<int64_t>(0, decodedAtNs - observedVsyncNs) / 1000
: 0),
static_cast<long long>(g_vsyncSampleRequestFailures.load(
std::memory_order_relaxed)));
}

if (plan.action == PresentationAction::DROP) {
lock.unlock();
renderResult = freeFrame();
} else {
renderResult = renderAtTime(
Expand All @@ -622,10 +632,7 @@ NativeRender::FrameSubmitResult NativeRender::SubmitFrame(const DecodedFrame& fr
bufferConsumed = true;
framePresented = true;
} else {
{
std::lock_guard<std::mutex> lock(presentationMutex_);
preciseApiFailureCount_++;
}
preciseApiFailureCount_++;
OH_LOG_WARN(LOG_APP,
"Host-paced render failed: %{public}d, pts=%{public}lld, targetNs=%{public}lld; falling back",
renderResult, static_cast<long long>(frame.ptsUs),
Expand Down
2 changes: 2 additions & 0 deletions nativelib/src/main/cpp/native_render.h
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,8 @@ class NativeRender {
int64_t precisePhaseShiftCount_ = 0;
int64_t preciseRebufferCount_ = 0;
int64_t preciseResyncCount_ = 0;
int64_t preciseQueueFullCount_ = 0;
int64_t preciseWaitForDrainCount_ = 0;
int64_t preciseApiFailureCount_ = 0;
int64_t preciseMaxTargetLeadNs_ = 0;

Expand Down
Loading
Loading