Loading services/camera/libcameraservice/device3/Camera3OutputStream.cpp +48 −4 Original line number Diff line number Diff line Loading @@ -486,7 +486,7 @@ status_t Camera3OutputStream::returnBufferCheckedLocked( bufferDeferred = true; } else { nsecs_t presentTime = mSyncToDisplay ? syncTimestampToDisplayLocked(captureTime) : captureTime; syncTimestampToDisplayLocked(captureTime, releaseFence->dup()) : captureTime; setTransform(transform, true/*mayChangeMirror*/); res = native_window_set_buffers_timestamp(mConsumer.get(), presentTime); Loading Loading @@ -1410,7 +1410,7 @@ void Camera3OutputStream::returnPrefetchedBuffersLocked() { } } nsecs_t Camera3OutputStream::syncTimestampToDisplayLocked(nsecs_t t) { nsecs_t Camera3OutputStream::syncTimestampToDisplayLocked(nsecs_t t, int releaseFence) { nsecs_t currentTime = systemTime(); if (!mFixedFps) { mLastCaptureTime = t; Loading Loading @@ -1453,6 +1453,17 @@ nsecs_t Camera3OutputStream::syncTimestampToDisplayLocked(nsecs_t t) { mLastCaptureTime = t; mLastPresentTime = presentT; // If releaseFence is available, store the fence to check signal // time later. mRefVsyncData = vsyncEventData; mReferenceCaptureTime = t; mReferenceArrivalTime = currentTime; if (releaseFence != -1) { mReferenceFrameFence = new Fence(releaseFence); } else { mFenceSignalOffset = 0; } // Move the expected presentation time back by 1/3 of frame interval to // mitigate the time drift. Due to time drift, if we directly use the // expected presentation time, often times 2 expected presentation time Loading @@ -1462,6 +1473,36 @@ nsecs_t Camera3OutputStream::syncTimestampToDisplayLocked(nsecs_t t) { } } // If there is a reference frame release fence, get the signal time and // update the captureToPresentOffset. if (mReferenceFrameFence != nullptr) { mFenceSignalOffset = 0; nsecs_t signalTime = mReferenceFrameFence->getSignalTime(); // Now that the fence has signaled, recalculate the offsets based on // the timeline which was actually latched if (signalTime != INT64_MAX) { for (size_t i = 0; i < mRefVsyncData.frameTimelinesLength; i++) { const auto& timeline = mRefVsyncData.frameTimelines[i]; if (timeline.deadlineTimestamp >= signalTime) { nsecs_t originalOffset = mCaptureToPresentOffset; mCaptureToPresentOffset = timeline.expectedPresentationTime - mReferenceCaptureTime; mLastPresentTime = timeline.expectedPresentationTime; mFenceSignalOffset = signalTime > mReferenceArrivalTime ? signalTime - mReferenceArrivalTime : 0; ALOGV("%s: Last deadline %" PRId64 " signalTime %" PRId64 " original offset %" PRId64 " new offset %" PRId64 " fencesignal offset %" PRId64, __FUNCTION__, timeline.deadlineTimestamp, signalTime, originalOffset, mCaptureToPresentOffset, mFenceSignalOffset); break; } } mReferenceFrameFence.clear(); } } nsecs_t idealPresentT = t + mCaptureToPresentOffset; nsecs_t expectedPresentT = mLastPresentTime; nsecs_t minDiff = INT64_MAX; Loading Loading @@ -1505,6 +1546,7 @@ nsecs_t Camera3OutputStream::syncTimestampToDisplayLocked(nsecs_t t) { // Find best timestamp in the vsync timelines: // - Only use at most kMaxTimelines timelines to avoid long latency // - Add an extra timeline if display fence is used // - closest to the ideal presentation time, // - deadline timestamp is greater than the current time, and // - For fixed FPS, if the capture interval doesn't deviate too much from refresh interval, Loading @@ -1513,7 +1555,9 @@ nsecs_t Camera3OutputStream::syncTimestampToDisplayLocked(nsecs_t t) { // - For variable FPS, or if the capture interval deviates from refresh // interval for more than 5%, find a presentation time closest to the // (lastPresentationTime + captureToPresentOffset) instead. int maxTimelines = std::min(kMaxTimelines, (int)vsyncEventData.frameTimelinesLength); int fenceAdjustment = (mFenceSignalOffset > 0) ? 1 : 0; int maxTimelines = std::min(kMaxTimelines + fenceAdjustment, (int)vsyncEventData.frameTimelinesLength); float biasForShortDelay = 1.0f; for (int i = 0; i < maxTimelines; i ++) { const auto& vsyncTime = vsyncEventData.frameTimelines[i]; Loading @@ -1524,7 +1568,7 @@ nsecs_t Camera3OutputStream::syncTimestampToDisplayLocked(nsecs_t t) { biasForShortDelay = 1.0 - 2.0 * i / (maxTimelines - 1); } if (std::abs(vsyncTime.expectedPresentationTime - idealPresentT) < minDiff && vsyncTime.deadlineTimestamp >= currentTime && vsyncTime.deadlineTimestamp >= currentTime + mFenceSignalOffset && ((!cameraDisplayInSync && vsyncTime.expectedPresentationTime > minPresentT) || (cameraDisplayInSync && vsyncTime.expectedPresentationTime > mLastPresentTime + minInterval + Loading services/camera/libcameraservice/device3/Camera3OutputStream.h +8 −1 Original line number Diff line number Diff line Loading @@ -446,7 +446,14 @@ class Camera3OutputStream : static constexpr nsecs_t kTimelineThresholdNs = 1000000LL; // 1 millisecond static constexpr float kMaxIntervalRatioDeviation = 0.05f; static constexpr int kMaxTimelines = 2; nsecs_t syncTimestampToDisplayLocked(nsecs_t t); nsecs_t syncTimestampToDisplayLocked(nsecs_t t, int releaseFence); // In case of fence being used sp<Fence> mReferenceFrameFence; nsecs_t mReferenceCaptureTime = 0; nsecs_t mReferenceArrivalTime = 0; nsecs_t mFenceSignalOffset = 0; VsyncEventData mRefVsyncData; // Re-space frames by delaying queueBuffer so that frame delivery has // the same cadence as capture. Default is on for SurfaceTexture bound Loading Loading
services/camera/libcameraservice/device3/Camera3OutputStream.cpp +48 −4 Original line number Diff line number Diff line Loading @@ -486,7 +486,7 @@ status_t Camera3OutputStream::returnBufferCheckedLocked( bufferDeferred = true; } else { nsecs_t presentTime = mSyncToDisplay ? syncTimestampToDisplayLocked(captureTime) : captureTime; syncTimestampToDisplayLocked(captureTime, releaseFence->dup()) : captureTime; setTransform(transform, true/*mayChangeMirror*/); res = native_window_set_buffers_timestamp(mConsumer.get(), presentTime); Loading Loading @@ -1410,7 +1410,7 @@ void Camera3OutputStream::returnPrefetchedBuffersLocked() { } } nsecs_t Camera3OutputStream::syncTimestampToDisplayLocked(nsecs_t t) { nsecs_t Camera3OutputStream::syncTimestampToDisplayLocked(nsecs_t t, int releaseFence) { nsecs_t currentTime = systemTime(); if (!mFixedFps) { mLastCaptureTime = t; Loading Loading @@ -1453,6 +1453,17 @@ nsecs_t Camera3OutputStream::syncTimestampToDisplayLocked(nsecs_t t) { mLastCaptureTime = t; mLastPresentTime = presentT; // If releaseFence is available, store the fence to check signal // time later. mRefVsyncData = vsyncEventData; mReferenceCaptureTime = t; mReferenceArrivalTime = currentTime; if (releaseFence != -1) { mReferenceFrameFence = new Fence(releaseFence); } else { mFenceSignalOffset = 0; } // Move the expected presentation time back by 1/3 of frame interval to // mitigate the time drift. Due to time drift, if we directly use the // expected presentation time, often times 2 expected presentation time Loading @@ -1462,6 +1473,36 @@ nsecs_t Camera3OutputStream::syncTimestampToDisplayLocked(nsecs_t t) { } } // If there is a reference frame release fence, get the signal time and // update the captureToPresentOffset. if (mReferenceFrameFence != nullptr) { mFenceSignalOffset = 0; nsecs_t signalTime = mReferenceFrameFence->getSignalTime(); // Now that the fence has signaled, recalculate the offsets based on // the timeline which was actually latched if (signalTime != INT64_MAX) { for (size_t i = 0; i < mRefVsyncData.frameTimelinesLength; i++) { const auto& timeline = mRefVsyncData.frameTimelines[i]; if (timeline.deadlineTimestamp >= signalTime) { nsecs_t originalOffset = mCaptureToPresentOffset; mCaptureToPresentOffset = timeline.expectedPresentationTime - mReferenceCaptureTime; mLastPresentTime = timeline.expectedPresentationTime; mFenceSignalOffset = signalTime > mReferenceArrivalTime ? signalTime - mReferenceArrivalTime : 0; ALOGV("%s: Last deadline %" PRId64 " signalTime %" PRId64 " original offset %" PRId64 " new offset %" PRId64 " fencesignal offset %" PRId64, __FUNCTION__, timeline.deadlineTimestamp, signalTime, originalOffset, mCaptureToPresentOffset, mFenceSignalOffset); break; } } mReferenceFrameFence.clear(); } } nsecs_t idealPresentT = t + mCaptureToPresentOffset; nsecs_t expectedPresentT = mLastPresentTime; nsecs_t minDiff = INT64_MAX; Loading Loading @@ -1505,6 +1546,7 @@ nsecs_t Camera3OutputStream::syncTimestampToDisplayLocked(nsecs_t t) { // Find best timestamp in the vsync timelines: // - Only use at most kMaxTimelines timelines to avoid long latency // - Add an extra timeline if display fence is used // - closest to the ideal presentation time, // - deadline timestamp is greater than the current time, and // - For fixed FPS, if the capture interval doesn't deviate too much from refresh interval, Loading @@ -1513,7 +1555,9 @@ nsecs_t Camera3OutputStream::syncTimestampToDisplayLocked(nsecs_t t) { // - For variable FPS, or if the capture interval deviates from refresh // interval for more than 5%, find a presentation time closest to the // (lastPresentationTime + captureToPresentOffset) instead. int maxTimelines = std::min(kMaxTimelines, (int)vsyncEventData.frameTimelinesLength); int fenceAdjustment = (mFenceSignalOffset > 0) ? 1 : 0; int maxTimelines = std::min(kMaxTimelines + fenceAdjustment, (int)vsyncEventData.frameTimelinesLength); float biasForShortDelay = 1.0f; for (int i = 0; i < maxTimelines; i ++) { const auto& vsyncTime = vsyncEventData.frameTimelines[i]; Loading @@ -1524,7 +1568,7 @@ nsecs_t Camera3OutputStream::syncTimestampToDisplayLocked(nsecs_t t) { biasForShortDelay = 1.0 - 2.0 * i / (maxTimelines - 1); } if (std::abs(vsyncTime.expectedPresentationTime - idealPresentT) < minDiff && vsyncTime.deadlineTimestamp >= currentTime && vsyncTime.deadlineTimestamp >= currentTime + mFenceSignalOffset && ((!cameraDisplayInSync && vsyncTime.expectedPresentationTime > minPresentT) || (cameraDisplayInSync && vsyncTime.expectedPresentationTime > mLastPresentTime + minInterval + Loading
services/camera/libcameraservice/device3/Camera3OutputStream.h +8 −1 Original line number Diff line number Diff line Loading @@ -446,7 +446,14 @@ class Camera3OutputStream : static constexpr nsecs_t kTimelineThresholdNs = 1000000LL; // 1 millisecond static constexpr float kMaxIntervalRatioDeviation = 0.05f; static constexpr int kMaxTimelines = 2; nsecs_t syncTimestampToDisplayLocked(nsecs_t t); nsecs_t syncTimestampToDisplayLocked(nsecs_t t, int releaseFence); // In case of fence being used sp<Fence> mReferenceFrameFence; nsecs_t mReferenceCaptureTime = 0; nsecs_t mReferenceArrivalTime = 0; nsecs_t mFenceSignalOffset = 0; VsyncEventData mRefVsyncData; // Re-space frames by delaying queueBuffer so that frame delivery has // the same cadence as capture. Default is on for SurfaceTexture bound Loading