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

Commit 2604c061 authored by Shuzhen Wang's avatar Shuzhen Wang Committed by Automerger Merge Worker
Browse files

Merge "Camera: re-space camera output for hardware texture target" into tm-dev am: 3bd124eb

parents 21a95f54 3bd124eb
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -81,6 +81,7 @@ cc_library_shared {
        "device3/Camera3OutputUtils.cpp",
        "device3/Camera3OutputUtils.cpp",
        "device3/Camera3DeviceInjectionMethods.cpp",
        "device3/Camera3DeviceInjectionMethods.cpp",
        "device3/UHRCropAndMeteringRegionMapper.cpp",
        "device3/UHRCropAndMeteringRegionMapper.cpp",
        "device3/PreviewFrameSpacer.cpp",
        "device3/hidl/HidlCamera3Device.cpp",
        "device3/hidl/HidlCamera3Device.cpp",
        "device3/hidl/HidlCamera3OfflineSession.cpp",
        "device3/hidl/HidlCamera3OfflineSession.cpp",
        "device3/hidl/HidlCamera3OutputUtils.cpp",
        "device3/hidl/HidlCamera3OutputUtils.cpp",
+44 −23
Original line number Original line Diff line number Diff line
@@ -376,7 +376,17 @@ status_t Camera3OutputStream::returnBufferCheckedLocked(
            dumpImageToDisk(timestamp, anwBuffer, anwReleaseFence);
            dumpImageToDisk(timestamp, anwBuffer, anwReleaseFence);
        }
        }


        nsecs_t captureTime = (mSyncToDisplay ? readoutTimestamp : timestamp) - mTimestampOffset;
        if (mPreviewFrameSpacer != nullptr) {
            res = mPreviewFrameSpacer->queuePreviewBuffer(timestamp - mTimestampOffset, transform,
                    anwBuffer, anwReleaseFence);
            if (res != OK) {
                ALOGE("%s: Stream %d: Error queuing buffer to preview buffer spacer: %s (%d)",
                        __FUNCTION__, mId, strerror(-res), res);
                return res;
            }
        } else {
            nsecs_t captureTime = (mSyncToDisplay ? readoutTimestamp : timestamp)
                    - mTimestampOffset;
            nsecs_t presentTime = mSyncToDisplay ?
            nsecs_t presentTime = mSyncToDisplay ?
                    syncTimestampToDisplayLocked(captureTime) : captureTime;
                    syncTimestampToDisplayLocked(captureTime) : captureTime;


@@ -396,6 +406,7 @@ status_t Camera3OutputStream::returnBufferCheckedLocked(
                      " %s (%d)", __FUNCTION__, mId, strerror(-res), res);
                      " %s (%d)", __FUNCTION__, mId, strerror(-res), res);
            }
            }
        }
        }
    }
    mLock.lock();
    mLock.lock();


    // Once a valid buffer has been returned to the queue, can no longer
    // Once a valid buffer has been returned to the queue, can no longer
@@ -468,7 +479,7 @@ status_t Camera3OutputStream::configureQueueLocked() {
        return res;
        return res;
    }
    }


    if ((res = configureConsumerQueueLocked(true /*allowDisplaySync*/)) != OK) {
    if ((res = configureConsumerQueueLocked(true /*allowPreviewRespace*/)) != OK) {
        return res;
        return res;
    }
    }


@@ -492,7 +503,7 @@ status_t Camera3OutputStream::configureQueueLocked() {
    return OK;
    return OK;
}
}


status_t Camera3OutputStream::configureConsumerQueueLocked(bool allowDisplaySync) {
status_t Camera3OutputStream::configureConsumerQueueLocked(bool allowPreviewRespace) {
    status_t res;
    status_t res;


    mTraceFirstBuffer = true;
    mTraceFirstBuffer = true;
@@ -582,20 +593,25 @@ status_t Camera3OutputStream::configureConsumerQueueLocked(bool allowDisplaySync
    int timestampBase = getTimestampBase();
    int timestampBase = getTimestampBase();
    bool isDefaultTimeBase = (timestampBase ==
    bool isDefaultTimeBase = (timestampBase ==
            OutputConfiguration::TIMESTAMP_BASE_DEFAULT);
            OutputConfiguration::TIMESTAMP_BASE_DEFAULT);
    if (allowDisplaySync)  {
    if (allowPreviewRespace)  {
        // We cannot distinguish between a SurfaceView and an ImageReader of
        // preview buffer format. Frames are synchronized to display in both
        // cases.
        bool forceChoreographer = (timestampBase ==
        bool forceChoreographer = (timestampBase ==
                OutputConfiguration::TIMESTAMP_BASE_CHOREOGRAPHER_SYNCED);
                OutputConfiguration::TIMESTAMP_BASE_CHOREOGRAPHER_SYNCED);
        bool defaultToChoreographer = (isDefaultTimeBase && isConsumedByHWComposer() &&
        bool defaultToChoreographer = (isDefaultTimeBase &&
                isConsumedByHWComposer() &&
                !property_get_bool("camera.disable_preview_scheduler", false));
                !property_get_bool("camera.disable_preview_scheduler", false));
        if (forceChoreographer || defaultToChoreographer) {
        if (forceChoreographer || defaultToChoreographer) {
            mSyncToDisplay = true;
            mSyncToDisplay = true;
            mTotalBufferCount += kDisplaySyncExtraBuffer;
            mTotalBufferCount += kDisplaySyncExtraBuffer;
        } else if (isConsumedByHWTexture() && !isVideoStream()) {
            mPreviewFrameSpacer = new PreviewFrameSpacer(*this, mConsumer);
            mTotalBufferCount ++;
            res = mPreviewFrameSpacer->run(String8::format("PreviewSpacer-%d", mId).string());
            if (res != OK) {
                ALOGE("%s: Unable to start preview spacer", __FUNCTION__);
                return res;
            }
        }
        }
    }
    }

    mHandoutTotalBufferCount = 0;
    mHandoutTotalBufferCount = 0;
    mFrameCount = 0;
    mFrameCount = 0;
    mLastTimestamp = 0;
    mLastTimestamp = 0;
@@ -1316,6 +1332,11 @@ nsecs_t Camera3OutputStream::syncTimestampToDisplayLocked(nsecs_t t) {
    return expectedPresentT - vsyncEventData.frameInterval/3;
    return expectedPresentT - vsyncEventData.frameInterval/3;
}
}


bool Camera3OutputStream::shouldLogError(status_t res) {
    Mutex::Autolock l(mLock);
    return shouldLogError(res, mState);
}

}; // namespace camera3
}; // namespace camera3


}; // namespace android
}; // namespace android
+11 −4
Original line number Original line Diff line number Diff line
@@ -28,6 +28,7 @@
#include "Camera3IOStreamBase.h"
#include "Camera3IOStreamBase.h"
#include "Camera3OutputStreamInterface.h"
#include "Camera3OutputStreamInterface.h"
#include "Camera3BufferManager.h"
#include "Camera3BufferManager.h"
#include "PreviewFrameSpacer.h"


namespace android {
namespace android {


@@ -250,6 +251,7 @@ class Camera3OutputStream :
    static void applyZSLUsageQuirk(int format, uint64_t *consumerUsage /*inout*/);
    static void applyZSLUsageQuirk(int format, uint64_t *consumerUsage /*inout*/);


    void setImageDumpMask(int mask) { mImageDumpMask = mask; }
    void setImageDumpMask(int mask) { mImageDumpMask = mask; }
    bool shouldLogError(status_t res);


  protected:
  protected:
    Camera3OutputStream(int id, camera_stream_type_t type,
    Camera3OutputStream(int id, camera_stream_type_t type,
@@ -282,7 +284,7 @@ class Camera3OutputStream :


    status_t getEndpointUsageForSurface(uint64_t *usage,
    status_t getEndpointUsageForSurface(uint64_t *usage,
            const sp<Surface>& surface) const;
            const sp<Surface>& surface) const;
    status_t configureConsumerQueueLocked(bool allowDisplaySync);
    status_t configureConsumerQueueLocked(bool allowPreviewRespace);


    // Consumer as the output of camera HAL
    // Consumer as the output of camera HAL
    sp<Surface> mConsumer;
    sp<Surface> mConsumer;
@@ -396,15 +398,14 @@ class Camera3OutputStream :


    void returnPrefetchedBuffersLocked();
    void returnPrefetchedBuffersLocked();


    // Synchronize camera timestamp to display, and the return value
    // can be used as presentation timestamp
    nsecs_t syncTimestampToDisplayLocked(nsecs_t t);


    static const int32_t kDequeueLatencyBinSize = 5; // in ms
    static const int32_t kDequeueLatencyBinSize = 5; // in ms
    CameraLatencyHistogram mDequeueBufferLatency;
    CameraLatencyHistogram mDequeueBufferLatency;


    int mImageDumpMask = 0;
    int mImageDumpMask = 0;


    // Re-space frames by overriding timestamp to align with display Vsync.
    // Default is on for SurfaceView bound streams.
    nsecs_t mMinExpectedDuration = 0;
    nsecs_t mMinExpectedDuration = 0;
    bool mSyncToDisplay = false;
    bool mSyncToDisplay = false;
    DisplayEventReceiver mDisplayEventReceiver;
    DisplayEventReceiver mDisplayEventReceiver;
@@ -414,6 +415,12 @@ class Camera3OutputStream :
    static constexpr size_t kDisplaySyncExtraBuffer = 2;
    static constexpr size_t kDisplaySyncExtraBuffer = 2;
    static constexpr nsecs_t kSpacingResetIntervalNs = 1000000000LL; // 1 second
    static constexpr nsecs_t kSpacingResetIntervalNs = 1000000000LL; // 1 second
    static constexpr nsecs_t kTimelineThresholdNs = 1000000LL; // 1 millisecond
    static constexpr nsecs_t kTimelineThresholdNs = 1000000LL; // 1 millisecond
    nsecs_t syncTimestampToDisplayLocked(nsecs_t t);

    // Re-space frames by delaying queueBuffer so that frame delivery has
    // the same cadence as capture. Default is on for SurfaceTexture bound
    // streams.
    sp<PreviewFrameSpacer> mPreviewFrameSpacer;
}; // class Camera3OutputStream
}; // class Camera3OutputStream


} // namespace camera3
} // namespace camera3
+1 −1
Original line number Original line Diff line number Diff line
@@ -251,7 +251,7 @@ status_t Camera3SharedOutputStream::configureQueueLocked() {
        return res;
        return res;
    }
    }


    res = configureConsumerQueueLocked(false/*allowDisplaySync*/);
    res = configureConsumerQueueLocked(false/*allowPreviewRespace*/);
    if (res != OK) {
    if (res != OK) {
        ALOGE("Failed to configureConsumerQueueLocked: %s(%d)", strerror(-res), res);
        ALOGE("Failed to configureConsumerQueueLocked: %s(%d)", strerror(-res), res);
        return res;
        return res;
+122 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2022 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define LOG_TAG "Camera3-PreviewFrameSpacer"
#define ATRACE_TAG ATRACE_TAG_CAMERA
//#define LOG_NDEBUG 0

#include <utils/Log.h>

#include "PreviewFrameSpacer.h"
#include "Camera3OutputStream.h"

namespace android {

namespace camera3 {

PreviewFrameSpacer::PreviewFrameSpacer(Camera3OutputStream& parent, sp<Surface> consumer) :
        mParent(parent),
        mConsumer(consumer) {
}

PreviewFrameSpacer::~PreviewFrameSpacer() {
    Thread::requestExitAndWait();
}

status_t PreviewFrameSpacer::queuePreviewBuffer(nsecs_t timestamp, int32_t transform,
        ANativeWindowBuffer* anwBuffer, int releaseFence) {
    Mutex::Autolock l(mLock);
    mPendingBuffers.emplace(timestamp, transform, anwBuffer, releaseFence);
    ALOGV("%s: mPendingBuffers size %zu, timestamp %" PRId64, __FUNCTION__,
            mPendingBuffers.size(), timestamp);

    mBufferCond.signal();
    return OK;
}

bool PreviewFrameSpacer::threadLoop() {
    Mutex::Autolock l(mLock);
    if (mPendingBuffers.size() == 0) {
        mBufferCond.waitRelative(mLock, kWaitDuration);
        return true;
    }

    nsecs_t currentTime = systemTime();
    auto buffer = mPendingBuffers.front();
    nsecs_t captureInterval = buffer.timestamp - mLastCameraCaptureTime;
    // If the capture interval exceeds threshold, directly queue
    // cached buffer.
    if (captureInterval >= kFrameIntervalThreshold) {
        mPendingBuffers.pop();
        queueBufferToClientLocked(buffer, currentTime);
        return true;
    }

    // Cache the frame to match capture time interval, for up to 33ms
    nsecs_t expectedQueueTime = mLastCameraPresentTime + captureInterval;
    nsecs_t frameWaitTime = std::min(kMaxFrameWaitTime, expectedQueueTime - currentTime);
    if (frameWaitTime > 0 && mPendingBuffers.size() < 2) {
        mBufferCond.waitRelative(mLock, frameWaitTime);
        if (exitPending()) {
            return true;
        }
        currentTime = systemTime();
    }
    ALOGV("%s: captureInterval %" PRId64 ", queueInterval %" PRId64 ", waited for %" PRId64
            ", timestamp %" PRId64, __FUNCTION__, captureInterval,
            currentTime - mLastCameraPresentTime, frameWaitTime, buffer.timestamp);
    mPendingBuffers.pop();
    queueBufferToClientLocked(buffer, currentTime);
    return true;
}

void PreviewFrameSpacer::requestExit() {
    // Call parent to set up shutdown
    Thread::requestExit();
    // Exit from other possible wait
    mBufferCond.signal();
}

void PreviewFrameSpacer::queueBufferToClientLocked(
        const BufferHolder& bufferHolder, nsecs_t currentTime) {
    mParent.setTransform(bufferHolder.transform, true/*mayChangeMirror*/);

    status_t res = native_window_set_buffers_timestamp(mConsumer.get(), bufferHolder.timestamp);
    if (res != OK) {
        ALOGE("%s: Preview Stream: Error setting timestamp: %s (%d)",
                __FUNCTION__, strerror(-res), res);
    }

    Camera3Stream::queueHDRMetadata(bufferHolder.anwBuffer.get()->handle, mConsumer,
            mParent.getDynamicRangeProfile());

    res = mConsumer->queueBuffer(mConsumer.get(), bufferHolder.anwBuffer.get(),
            bufferHolder.releaseFence);
    if (res != OK) {
        close(bufferHolder.releaseFence);
        if (mParent.shouldLogError(res)) {
            ALOGE("%s: Failed to queue buffer to client: %s(%d)", __FUNCTION__,
                    strerror(-res), res);
        }
    }

    mLastCameraPresentTime = currentTime;
    mLastCameraCaptureTime = bufferHolder.timestamp;
}

}; // namespace camera3

}; // namespace android
Loading