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

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

Merge "Camera3: Use proper timestamp clock domain for different streams" into nyc-dev

parents 661c5953 c28dcccb
Loading
Loading
Loading
Loading
+33 −3
Original line number Diff line number Diff line
@@ -64,6 +64,7 @@ Camera3Device::Camera3Device(int id):
        mStatusWaiters(0),
        mUsePartialResult(false),
        mNumPartialResults(1),
        mTimestampOffset(0),
        mNextResultFrameNumber(0),
        mNextReprocessResultFrameNumber(0),
        mNextShutterFrameNumber(0),
@@ -204,6 +205,14 @@ status_t Camera3Device::initialize(CameraModule *module)
    mNeedConfig = true;
    mPauseStateNotify = false;

    // Measure the clock domain offset between camera and video/hw_composer
    camera_metadata_entry timestampSource =
            mDeviceInfo.find(ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE);
    if (timestampSource.count > 0 && timestampSource.data.u8[0] ==
            ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE_REALTIME) {
        mTimestampOffset = getMonoToBoottimeOffset();
    }

    // Will the HAL be sending in early partial result metadata?
    if (mDeviceVersion >= CAMERA_DEVICE_API_VERSION_3_2) {
        camera_metadata_entry partialResultsCount =
@@ -382,6 +391,24 @@ Camera3Device::Size Camera3Device::getMaxJpegResolution() const {
    return Size(maxJpegWidth, maxJpegHeight);
}

nsecs_t Camera3Device::getMonoToBoottimeOffset() {
    // try three times to get the clock offset, choose the one
    // with the minimum gap in measurements.
    const int tries = 3;
    nsecs_t bestGap, measured;
    for (int i = 0; i < tries; ++i) {
        const nsecs_t tmono = systemTime(SYSTEM_TIME_MONOTONIC);
        const nsecs_t tbase = systemTime(SYSTEM_TIME_BOOTTIME);
        const nsecs_t tmono2 = systemTime(SYSTEM_TIME_MONOTONIC);
        const nsecs_t gap = tmono2 - tmono;
        if (i == 0 || gap < bestGap) {
            bestGap = gap;
            measured = tbase - ((tmono + tmono2) >> 1);
        }
    }
    return measured;
}

ssize_t Camera3Device::getJpegBufferSize(uint32_t width, uint32_t height) const {
    // Get max jpeg size (area-wise).
    Size maxJpegResolution = getMaxJpegResolution();
@@ -992,7 +1019,8 @@ status_t Camera3Device::createStream(sp<Surface> consumer,
            }
        }
        newStream = new Camera3OutputStream(mNextStreamId, consumer,
                width, height, blobBufferSize, format, dataSpace, rotation, streamSetId);
                width, height, blobBufferSize, format, dataSpace, rotation,
                mTimestampOffset, streamSetId);
    } else if (format == HAL_PIXEL_FORMAT_RAW_OPAQUE) {
        ssize_t rawOpaqueBufferSize = getRawOpaqueBufferSize(width, height);
        if (rawOpaqueBufferSize <= 0) {
@@ -1000,10 +1028,12 @@ status_t Camera3Device::createStream(sp<Surface> consumer,
            return BAD_VALUE;
        }
        newStream = new Camera3OutputStream(mNextStreamId, consumer,
                width, height, rawOpaqueBufferSize, format, dataSpace, rotation, streamSetId);
                width, height, rawOpaqueBufferSize, format, dataSpace, rotation,
                mTimestampOffset, streamSetId);
    } else {
        newStream = new Camera3OutputStream(mNextStreamId, consumer,
                width, height, format, dataSpace, rotation, streamSetId);
                width, height, format, dataSpace, rotation,
                mTimestampOffset, streamSetId);
    }
    newStream->setStatusTracker(mStatusTracker);

+13 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
#include <utils/Mutex.h>
#include <utils/Thread.h>
#include <utils/KeyedVector.h>
#include <utils/Timers.h>
#include <hardware/camera3.h>
#include <camera/CaptureResult.h>
#include <camera/camera2/ICameraDeviceUser.h>
@@ -251,6 +252,12 @@ class Camera3Device :

    /**** End scope for mLock ****/

    // The offset converting from clock domain of other subsystem
    // (video/hardware composer) to that of camera. Assumption is that this
    // offset won't change during the life cycle of the camera device. In other
    // words, camera device shouldn't be open during CPU suspend.
    nsecs_t                    mTimestampOffset;

    typedef struct AeTriggerCancelOverride {
        bool applyAeLock;
        uint8_t aeLock;
@@ -392,6 +399,12 @@ class Camera3Device :
     */
    Size getMaxJpegResolution() const;

    /**
     * Helper function to get the offset between MONOTONIC and BOOTTIME
     * timestamp.
     */
    static nsecs_t getMonoToBoottimeOffset();

    struct RequestTrigger {
        // Metadata tag number, e.g. android.control.aePrecaptureTrigger
        uint32_t metadataTag;
+18 −16
Original line number Diff line number Diff line
@@ -34,14 +34,15 @@ namespace camera3 {
Camera3OutputStream::Camera3OutputStream(int id,
        sp<Surface> consumer,
        uint32_t width, uint32_t height, int format,
        android_dataspace dataSpace, camera3_stream_rotation_t rotation, int setId) :
        android_dataspace dataSpace, camera3_stream_rotation_t rotation,
        nsecs_t timestampOffset, int setId) :
        Camera3IOStreamBase(id, CAMERA3_STREAM_OUTPUT, width, height,
                            /*maxSize*/0, format, dataSpace, rotation, setId),
        mConsumer(consumer),
        mTransform(0),
        mTraceFirstBuffer(true),
        mTimestampBuffer(true),
        mUseBufferManager(false) {
        mUseBufferManager(false),
        mTimestampOffset(timestampOffset) {

    if (mConsumer == NULL) {
        ALOGE("%s: Consumer is NULL!", __FUNCTION__);
@@ -56,14 +57,16 @@ Camera3OutputStream::Camera3OutputStream(int id,
Camera3OutputStream::Camera3OutputStream(int id,
        sp<Surface> consumer,
        uint32_t width, uint32_t height, size_t maxSize, int format,
        android_dataspace dataSpace, camera3_stream_rotation_t rotation, int setId) :
        android_dataspace dataSpace, camera3_stream_rotation_t rotation,
        nsecs_t timestampOffset, int setId) :
        Camera3IOStreamBase(id, CAMERA3_STREAM_OUTPUT, width, height, maxSize,
                            format, dataSpace, rotation, setId),
        mConsumer(consumer),
        mTransform(0),
        mTraceFirstBuffer(true),
        mTimestampBuffer(true),
        mUseBufferManager(false) {
        mUseMonoTimestamp(false),
        mUseBufferManager(false),
        mTimestampOffset(timestampOffset) {

    if (format != HAL_PIXEL_FORMAT_BLOB && format != HAL_PIXEL_FORMAT_RAW_OPAQUE) {
        ALOGE("%s: Bad format for size-only stream: %d", __FUNCTION__,
@@ -92,6 +95,7 @@ Camera3OutputStream::Camera3OutputStream(int id, camera3_stream_type_t type,
                            format, dataSpace, rotation, setId),
        mTransform(0),
        mTraceFirstBuffer(true),
        mUseMonoTimestamp(false),
        mUseBufferManager(false) {

    if (setId > CAMERA3_STREAM_SET_ID_INVALID) {
@@ -237,16 +241,14 @@ status_t Camera3OutputStream::returnBufferCheckedLocked(

        /* Certain consumers (such as AudioSource or HardwareComposer) use
         * MONOTONIC time, causing time misalignment if camera timestamp is
         * in BOOTTIME. Avoid setting timestamp, and let BufferQueue generate it
         * instead. */
        if (mTimestampBuffer) {
            res = native_window_set_buffers_timestamp(mConsumer.get(), timestamp);
         * in BOOTTIME. Do the conversion if necessary. */
        res = native_window_set_buffers_timestamp(mConsumer.get(),
                mUseMonoTimestamp ? timestamp - mTimestampOffset : timestamp);
        if (res != OK) {
            ALOGE("%s: Stream %d: Error setting timestamp: %s (%d)",
                  __FUNCTION__, mId, strerror(-res), res);
            return res;
        }
        }

        res = currentConsumer->queueBuffer(currentConsumer.get(),
                container_of(buffer.buffer, ANativeWindowBuffer, handle),
@@ -398,7 +400,7 @@ status_t Camera3OutputStream::configureQueueLocked() {
    mHandoutTotalBufferCount = 0;
    mFrameCount = 0;
    mLastTimestamp = 0;
    mTimestampBuffer = !(isConsumedByHWComposer() | isVideoStream());
    mUseMonoTimestamp = (isConsumedByHWComposer() | isVideoStream());

    res = native_window_set_buffer_count(mConsumer.get(),
            mTotalBufferCount);
+10 −4
Original line number Diff line number Diff line
@@ -81,7 +81,7 @@ class Camera3OutputStream :
    Camera3OutputStream(int id, sp<Surface> consumer,
            uint32_t width, uint32_t height, int format,
            android_dataspace dataSpace, camera3_stream_rotation_t rotation,
            int setId = CAMERA3_STREAM_SET_ID_INVALID);
            nsecs_t timestampOffset, int setId = CAMERA3_STREAM_SET_ID_INVALID);

    /**
     * Set up a stream for formats that have a variable buffer size for the same
@@ -92,7 +92,7 @@ class Camera3OutputStream :
    Camera3OutputStream(int id, sp<Surface> consumer,
            uint32_t width, uint32_t height, size_t maxSize, int format,
            android_dataspace dataSpace, camera3_stream_rotation_t rotation,
            int setId = CAMERA3_STREAM_SET_ID_INVALID);
            nsecs_t timestampOffset, int setId = CAMERA3_STREAM_SET_ID_INVALID);

    virtual ~Camera3OutputStream();

@@ -167,8 +167,8 @@ class Camera3OutputStream :
    // Name of Surface consumer
    String8           mConsumerName;

    // Whether to timestamp the output buffer
    bool mTimestampBuffer;
    // Whether consumer assumes MONOTONIC timestamp
    bool mUseMonoTimestamp;

    /**
     * GraphicBuffer manager this stream is registered to. Used to replace the buffer
@@ -186,6 +186,12 @@ class Camera3OutputStream :
     * Flag indicating if the buffer manager is used to allocate the stream buffers
     */
    bool mUseBufferManager;

    /**
     * Timestamp offset for video and hardware composer consumed streams
     */
    nsecs_t mTimestampOffset;

    /**
     * Internal Camera3Stream interface
     */