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

Commit 26abaf46 authored by Shuzhen Wang's avatar Shuzhen Wang
Browse files

Camera: Make sure timestamp is increasing

Guard against case where timestamp of stream buffers doesn't increase.

Timestamp source is either monotonic or boottime, both of which are
guaranteed to increase.

There are 2 exceptions where timestamp may go back in time:
- For requests where HAL ZSL is enabled, and
- For reprocessing requests

Test: Camera CTS
Bug: 113340974
Change-Id: I0ae9290696d651168150fa5ed7aa13c140a0294f
parent 10caf0e2
Loading
Loading
Loading
Loading
+17 −7
Original line number Diff line number Diff line
@@ -2742,13 +2742,14 @@ void Camera3Device::setErrorStateLockedV(const char *fmt, va_list args) {
status_t Camera3Device::registerInFlight(uint32_t frameNumber,
        int32_t numBuffers, CaptureResultExtras resultExtras, bool hasInput,
        bool hasAppCallback, nsecs_t maxExpectedDuration,
        std::set<String8>& physicalCameraIds, bool isStillCapture) {
        std::set<String8>& physicalCameraIds, bool isStillCapture,
        bool isZslCapture) {
    ATRACE_CALL();
    Mutex::Autolock l(mInFlightLock);

    ssize_t res;
    res = mInFlightMap.add(frameNumber, InFlightRequest(numBuffers, resultExtras, hasInput,
            hasAppCallback, maxExpectedDuration, physicalCameraIds, isStillCapture));
            hasAppCallback, maxExpectedDuration, physicalCameraIds, isStillCapture, isZslCapture));
    if (res < 0) return res;

    if (mInFlightMap.size() == 1) {
@@ -2766,11 +2767,12 @@ status_t Camera3Device::registerInFlight(uint32_t frameNumber,

void Camera3Device::returnOutputBuffers(
        const camera3_stream_buffer_t *outputBuffers, size_t numBuffers,
        nsecs_t timestamp) {
        nsecs_t timestamp, bool timestampIncreasing) {

    for (size_t i = 0; i < numBuffers; i++)
    {
        Camera3Stream *stream = Camera3Stream::cast(outputBuffers[i].stream);
        status_t res = stream->returnBuffer(outputBuffers[i], timestamp);
        status_t res = stream->returnBuffer(outputBuffers[i], timestamp, timestampIncreasing);
        // Note: stream may be deallocated at this point, if this buffer was
        // the last reference to it.
        if (res != OK) {
@@ -3214,8 +3216,9 @@ void Camera3Device::processCaptureResult(const camera3_capture_result *result) {
            request.pendingOutputBuffers.appendArray(result->output_buffers,
                result->num_output_buffers);
        } else {
            bool timestampIncreasing = !(request.zslCapture || request.hasInputBuffer);
            returnOutputBuffers(result->output_buffers,
                result->num_output_buffers, shutterTimestamp);
                result->num_output_buffers, shutterTimestamp, timestampIncreasing);
        }

        if (result->result != NULL && !isPartialResult) {
@@ -3421,8 +3424,9 @@ void Camera3Device::notifyShutter(const camera3_shutter_msg_t &msg,
                    r.collectedPartialResult, msg.frame_number,
                    r.hasInputBuffer, r.physicalMetadatas);
            }
            bool timestampIncreasing = !(r.zslCapture || r.hasInputBuffer);
            returnOutputBuffers(r.pendingOutputBuffers.array(),
                r.pendingOutputBuffers.size(), r.shutterTimestamp);
                r.pendingOutputBuffers.size(), r.shutterTimestamp, timestampIncreasing);
            r.pendingOutputBuffers.clear();

            removeInFlightRequestIfReadyLocked(idx);
@@ -4948,6 +4952,7 @@ status_t Camera3Device::RequestThread::prepareHalRequests() {
            hasCallback = false;
        }
        bool isStillCapture = false;
        bool isZslCapture = false;
        if (!mNextRequests[0].captureRequest->mSettingsList.begin()->metadata.isEmpty()) {
            camera_metadata_ro_entry_t e = camera_metadata_ro_entry_t();
            find_camera_metadata_ro_entry(halRequest->settings, ANDROID_CONTROL_CAPTURE_INTENT, &e);
@@ -4955,13 +4960,18 @@ status_t Camera3Device::RequestThread::prepareHalRequests() {
                isStillCapture = true;
                ATRACE_ASYNC_BEGIN("still capture", mNextRequests[i].halRequest.frame_number);
            }

            find_camera_metadata_ro_entry(halRequest->settings, ANDROID_CONTROL_ENABLE_ZSL, &e);
            if ((e.count > 0) && (e.data.u8[0] == ANDROID_CONTROL_ENABLE_ZSL_TRUE)) {
                isZslCapture = true;
            }
        }
        res = parent->registerInFlight(halRequest->frame_number,
                totalNumBuffers, captureRequest->mResultExtras,
                /*hasInput*/halRequest->input_buffer != NULL,
                hasCallback,
                calculateMaxExpectedDuration(halRequest->settings),
                requestedPhysicalCameras, isStillCapture);
                requestedPhysicalCameras, isStillCapture, isZslCapture);
        ALOGVV("%s: registered in flight requestId = %" PRId32 ", frameNumber = %" PRId64
               ", burstId = %" PRId32 ".",
                __FUNCTION__,
+11 −5
Original line number Diff line number Diff line
@@ -999,6 +999,9 @@ class Camera3Device :
        // Indicates a still capture request.
        bool stillCapture;

        // Indicates a ZSL capture request
        bool zslCapture;

        // Default constructor needed by KeyedVector
        InFlightRequest() :
                shutterTimestamp(0),
@@ -1010,12 +1013,14 @@ class Camera3Device :
                hasCallback(true),
                maxExpectedDuration(kDefaultExpectedDuration),
                skipResultMetadata(false),
                stillCapture(false) {
                stillCapture(false),
                zslCapture(false) {
        }

        InFlightRequest(int numBuffers, CaptureResultExtras extras, bool hasInput,
                bool hasAppCallback, nsecs_t maxDuration,
                const std::set<String8>& physicalCameraIdSet, bool isStillCapture) :
                const std::set<String8>& physicalCameraIdSet, bool isStillCapture, 
                bool isZslCapture) :
                shutterTimestamp(0),
                sensorTimestamp(0),
                requestStatus(OK),
@@ -1027,7 +1032,8 @@ class Camera3Device :
                maxExpectedDuration(maxDuration),
                skipResultMetadata(false),
                physicalCameraIds(physicalCameraIdSet),
                stillCapture(isStillCapture) {
                stillCapture(isStillCapture),
                zslCapture(isZslCapture) {
        }
    };

@@ -1044,7 +1050,7 @@ class Camera3Device :
    status_t registerInFlight(uint32_t frameNumber,
            int32_t numBuffers, CaptureResultExtras resultExtras, bool hasInput,
            bool callback, nsecs_t maxExpectedDuration, std::set<String8>& physicalCameraIds,
            bool isStillCapture);
            bool isStillCapture, bool isZslCapture);

    /**
     * Returns the maximum expected time it'll take for all currently in-flight
@@ -1154,7 +1160,7 @@ class Camera3Device :

    // helper function to return the output buffers to the streams.
    void returnOutputBuffers(const camera3_stream_buffer_t *outputBuffers,
            size_t numBuffers, nsecs_t timestamp);
            size_t numBuffers, nsecs_t timestamp, bool timestampIncreasing = true);

    // Send a partial capture result.
    void sendPartialCaptureResult(const camera_metadata_t * partialResult,
+5 −0
Original line number Diff line number Diff line
@@ -268,6 +268,11 @@ status_t Camera3OutputStream::returnBufferCheckedLocked(
            mTraceFirstBuffer = false;
        }

        if (timestamp == 0) {
            ALOGE("%s: Stream %d: timestamp shouldn't be 0", __FUNCTION__, mId);
            return BAD_VALUE;
        }

        /* Certain consumers (such as AudioSource or HardwareComposer) use
         * MONOTONIC time, causing time misalignment if camera timestamp is
         * in BOOTTIME. Do the conversion if necessary. */
+10 −2
Original line number Diff line number Diff line
@@ -66,7 +66,8 @@ Camera3Stream::Camera3Stream(int id,
    mBufferLimitLatency(kBufferLimitLatencyBinSize),
    mFormatOverridden(false),
    mOriginalFormat(-1),
    mPhysicalCameraId(physicalCameraId) {
    mPhysicalCameraId(physicalCameraId),
    mLastTimestamp(0) {

    camera3_stream::stream_type = type;
    camera3_stream::width = width;
@@ -649,7 +650,7 @@ void Camera3Stream::removeOutstandingBuffer(const camera3_stream_buffer &buffer)
}

status_t Camera3Stream::returnBuffer(const camera3_stream_buffer &buffer,
        nsecs_t timestamp) {
        nsecs_t timestamp, bool timestampIncreasing) {
    ATRACE_CALL();
    Mutex::Autolock l(mLock);

@@ -661,6 +662,13 @@ status_t Camera3Stream::returnBuffer(const camera3_stream_buffer &buffer,

    removeOutstandingBuffer(buffer);

    if (timestampIncreasing && timestamp != 0 && timestamp <= mLastTimestamp) {
        ALOGE("%s: Stream %d: timestamp %" PRId64 " is not increasing. Prev timestamp %" PRId64,
                __FUNCTION__, mId, timestamp, mLastTimestamp);
        return BAD_VALUE;
    }
    mLastTimestamp = timestamp;

    /**
     * TODO: Check that the state is valid first.
     *
+2 −1
Original line number Diff line number Diff line
@@ -320,7 +320,7 @@ class Camera3Stream :
     * For bidirectional streams, this method applies to the output-side buffers
     */
    status_t         returnBuffer(const camera3_stream_buffer &buffer,
            nsecs_t timestamp);
            nsecs_t timestamp, bool timestampIncreasing);

    /**
     * Fill in the camera3_stream_buffer with the next valid buffer for this
@@ -559,6 +559,7 @@ class Camera3Stream :
    android_dataspace mOriginalDataSpace;

    String8 mPhysicalCameraId;
    nsecs_t mLastTimestamp;
}; // class Camera3Stream

}; // namespace camera3
Loading