Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c36537d8 authored by Shuzhen Wang's avatar Shuzhen Wang Committed by Android (Google) Code Review
Browse files

Merge "Camera: Handle release fence when syncing preview to display" into udc-dev

parents 6afa26c7 0897d598
Loading
Loading
Loading
Loading
+48 −4
Original line number Diff line number Diff line
@@ -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);
@@ -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;
@@ -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
@@ -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;
@@ -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,
@@ -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];
@@ -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 +
+8 −1
Original line number Diff line number Diff line
@@ -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