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

Commit 730a7916 authored by Shuzhen Wang's avatar Shuzhen Wang
Browse files

Camera: Add lastCompletedFrameNumber in CaptureResultExtras

The new fields in CaptureResultExtras notify the application the last
completed frame numbers. A frame number is completed if:
- All buffers are returned
- Final capture result is returned, or CAPTURE_ERROR is called,
- For buffers that are cancelled, all notifyError() is called.

This makes sure client doesn't ignore BUFFER_ERROR after capture
result metadata callback.

Public API and NDK logic are fixed. VNDK is yet to be done.

Test: Camera CTS
Bug: 155353799
Change-Id: I43f0f5ea18a670dfa00872ebc581567e2df76ad4
parent 4e48c247
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -49,6 +49,9 @@ status_t CaptureResultExtras::readFromParcel(const android::Parcel *parcel) {
        }
        errorPhysicalCameraId = cameraId;
    }
    parcel->readInt64(&lastCompletedRegularFrameNumber);
    parcel->readInt64(&lastCompletedReprocessFrameNumber);
    parcel->readInt64(&lastCompletedZslFrameNumber);

    return OK;
}
@@ -76,6 +79,9 @@ status_t CaptureResultExtras::writeToParcel(android::Parcel *parcel) const {
    } else {
        parcel->writeBool(false);
    }
    parcel->writeInt64(lastCompletedRegularFrameNumber);
    parcel->writeInt64(lastCompletedReprocessFrameNumber);
    parcel->writeInt64(lastCompletedZslFrameNumber);

    return OK;
}
+32 −1
Original line number Diff line number Diff line
@@ -76,6 +76,34 @@ struct CaptureResultExtras : public android::Parcelable {
     */
    String16  errorPhysicalCameraId;

    // The last completed frame numbers shouldn't be checked in onResultReceived() and notifyError()
    // because the output buffers could be arriving after onResultReceived() and
    // notifyError(). Given this constraint, we check it for each
    // onCaptureStarted, and if there is no further onCaptureStarted(),
    // check for onDeviceIdle() to clear out all pending frame numbers.

    /**
     * The latest regular request frameNumber for which all buffers and capture result have been
     * returned or notified as an BUFFER_ERROR/RESULT_ERROR/REQUEST_ERROR. -1 if
     * none has completed.
     */
    int64_t lastCompletedRegularFrameNumber;

    /**
     * The latest reprocess request frameNumber for which all buffers and capture result have been
     * returned or notified as an BUFFER_ERROR/RESULT_ERROR/REQUEST_ERROR. -1 if
     * none has completed.
     */
    int64_t lastCompletedReprocessFrameNumber;

    /**
     * The latest Zsl request frameNumber for which all buffers and capture result have been
     * returned or notified as an BUFFER_ERROR/RESULT_ERROR/REQUEST_ERROR. -1 if
     * none has completed.
     */
    int64_t lastCompletedZslFrameNumber;


    /**
     * Constructor initializes object as invalid by setting requestId to be -1.
     */
@@ -87,7 +115,10 @@ struct CaptureResultExtras : public android::Parcelable {
          frameNumber(0),
          partialResultCount(0),
          errorStreamId(-1),
          errorPhysicalCameraId() {
          errorPhysicalCameraId(),
          lastCompletedRegularFrameNumber(-1),
          lastCompletedReprocessFrameNumber(-1),
          lastCompletedZslFrameNumber(-1) {
    }

    /**
+82 −35
Original line number Diff line number Diff line
@@ -1336,19 +1336,19 @@ CameraDevice::checkRepeatingSequenceCompleteLocked(
void
CameraDevice::checkAndFireSequenceCompleteLocked() {
    int64_t completedFrameNumber = mFrameNumberTracker.getCompletedFrameNumber();
    //std::map<int, int64_t> mSequenceLastFrameNumberMap;
    auto it = mSequenceLastFrameNumberMap.begin();
    while (it != mSequenceLastFrameNumberMap.end()) {
        int sequenceId = it->first;
        int64_t lastFrameNumber = it->second;
        bool seqCompleted = false;
        int64_t lastFrameNumber = it->second.lastFrameNumber;
        bool hasCallback = true;

        if (mRemote == nullptr) {
            ALOGW("Camera %s closed while checking sequence complete", getId());
            return;
        }

        ALOGV("%s: seq %d's last frame number %" PRId64 ", completed %" PRId64,
                __FUNCTION__, sequenceId, lastFrameNumber, completedFrameNumber);
        if (!it->second.isSequenceCompleted) {
            // Check if there is callback for this sequence
            // This should not happen because we always register callback (with nullptr inside)
            if (mSequenceCallbackMap.count(sequenceId) == 0) {
@@ -1357,16 +1357,14 @@ CameraDevice::checkAndFireSequenceCompleteLocked() {
            }

            if (lastFrameNumber <= completedFrameNumber) {
            ALOGV("seq %d reached last frame %" PRId64 ", completed %" PRId64,
                    sequenceId, lastFrameNumber, completedFrameNumber);
            seqCompleted = true;
                ALOGV("Mark sequenceId %d as sequence completed", sequenceId);
                it->second.isSequenceCompleted = true;
            }

        if (seqCompleted && hasCallback) {
            // remove callback holder from callback map
            if (it->second.isSequenceCompleted && hasCallback) {
                auto cbIt = mSequenceCallbackMap.find(sequenceId);
                CallbackHolder cbh = cbIt->second;
            mSequenceCallbackMap.erase(cbIt);

                // send seq complete callback
                sp<AMessage> msg = new AMessage(kWhatCaptureSeqEnd, mHandler);
                msg->setPointer(kContextKey, cbh.mContext);
@@ -1382,10 +1380,53 @@ CameraDevice::checkAndFireSequenceCompleteLocked() {
                cbh.mSession.clear();
                postSessionMsgAndCleanup(msg);
            }
        }

        // No need to track sequence complete if there is no callback registered
        if (seqCompleted || !hasCallback) {
        if (it->second.isSequenceCompleted && it->second.isInflightCompleted) {
            if (mSequenceCallbackMap.find(sequenceId) != mSequenceCallbackMap.end()) {
                mSequenceCallbackMap.erase(sequenceId);
            }
            it = mSequenceLastFrameNumberMap.erase(it);
            ALOGV("%s: Remove holder for sequenceId %d", __FUNCTION__, sequenceId);
        } else {
            ++it;
        }
    }
}

void
CameraDevice::removeCompletedCallbackHolderLocked(int64_t lastCompletedRegularFrameNumber) {
    auto it = mSequenceLastFrameNumberMap.begin();
    while (it != mSequenceLastFrameNumberMap.end()) {
        int sequenceId = it->first;
        int64_t lastFrameNumber = it->second.lastFrameNumber;

        if (mRemote == nullptr) {
            ALOGW("Camera %s closed while checking sequence complete", getId());
            return;
        }

        ALOGV("%s: seq %d's last frame number %" PRId64
                ", completed inflight frame number %" PRId64,
                __FUNCTION__, sequenceId, lastFrameNumber,
                lastCompletedRegularFrameNumber);
        if (lastFrameNumber <= lastCompletedRegularFrameNumber) {
            if (it->second.isSequenceCompleted) {
                // Check if there is callback for this sequence
                // This should not happen because we always register callback (with nullptr inside)
                if (mSequenceCallbackMap.count(sequenceId) == 0) {
                    ALOGW("No callback found for sequenceId %d", sequenceId);
                } else {
                    mSequenceCallbackMap.erase(sequenceId);
                }

                it = mSequenceLastFrameNumberMap.erase(it);
                ALOGV("%s: Remove holder for sequenceId %d", __FUNCTION__, sequenceId);
            } else {
                ALOGV("Mark sequenceId %d as inflight completed", sequenceId);
                it->second.isInflightCompleted = true;
                ++it;
            }
        } else {
            ++it;
        }
@@ -1480,6 +1521,9 @@ CameraDevice::ServiceCallback::onDeviceIdle() {
        return ret;
    }

    dev->removeCompletedCallbackHolderLocked(
             std::numeric_limits<int64_t>::max()/*lastCompletedRegularFrameNumber*/);

    if (dev->mIdle) {
        // Already in idle state. Possibly other thread did waitUntilIdle
        return ret;
@@ -1522,6 +1566,9 @@ CameraDevice::ServiceCallback::onCaptureStarted(
        return ret;
    }

    dev->removeCompletedCallbackHolderLocked(
            resultExtras.lastCompletedRegularFrameNumber);

    int sequenceId = resultExtras.requestId;
    int32_t burstId = resultExtras.burstId;

+10 −2
Original line number Diff line number Diff line
@@ -267,8 +267,15 @@ class CameraDevice final : public RefBase {
    static const int REQUEST_ID_NONE = -1;
    int mRepeatingSequenceId = REQUEST_ID_NONE;

    // sequence id -> last frame number map
    std::map<int, int64_t> mSequenceLastFrameNumberMap;
    // sequence id -> last frame number holder map
    struct RequestLastFrameNumberHolder {
        int64_t lastFrameNumber;
        bool isSequenceCompleted = false;
        bool isInflightCompleted = false;
        RequestLastFrameNumberHolder(int64_t lastFN) :
                lastFrameNumber(lastFN) {}
    };
    std::map<int, RequestLastFrameNumberHolder> mSequenceLastFrameNumberMap;

    struct CallbackHolder {
        CallbackHolder(sp<ACameraCaptureSession>          session,
@@ -338,6 +345,7 @@ class CameraDevice final : public RefBase {

    void checkRepeatingSequenceCompleteLocked(const int sequenceId, const int64_t lastFrameNumber);
    void checkAndFireSequenceCompleteLocked();
    void removeCompletedCallbackHolderLocked(int64_t lastCompletedRegularFrameNumber);

    // Misc variables
    int32_t mShadingMapSize[2];   // const after constructor
+19 −13
Original line number Diff line number Diff line
@@ -756,9 +756,10 @@ status_t Camera3Device::dump(int fd, const Vector<String16> &args) {
        for (size_t i = 0; i < mInFlightMap.size(); i++) {
            InFlightRequest r = mInFlightMap.valueAt(i);
            lines.appendFormat("      Frame %d |  Timestamp: %" PRId64 ", metadata"
                    " arrived: %s, buffers left: %d\n", mInFlightMap.keyAt(i),
                    " arrived: %s, buffers left: %d, buffers returned with STATUS_ERROR: %d, "
                    " buffers notified with error: %d\n", mInFlightMap.keyAt(i),
                    r.shutterTimestamp, r.haveResultMetadata ? "true" : "false",
                    r.numBuffersLeft);
                    r.numBuffersLeft, r.numErrorBuffersReturned, r.numErrorBuffersNotified);
        }
    }
    write(fd, lines.string(), lines.size());
@@ -1043,8 +1044,9 @@ hardware::Return<void> Camera3Device::processCaptureResult_3_4(
    }
    CaptureOutputStates states {
        mId,
        mInFlightLock, mInFlightMap,
        mOutputLock,  mResultQueue, mResultSignal,
        mInFlightLock, mLastCompletedRegularFrameNumber,
        mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
        mInFlightMap, mOutputLock,  mResultQueue, mResultSignal,
        mNextShutterFrameNumber,
        mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
        mNextResultFrameNumber,
@@ -1100,8 +1102,9 @@ hardware::Return<void> Camera3Device::processCaptureResult(

    CaptureOutputStates states {
        mId,
        mInFlightLock, mInFlightMap,
        mOutputLock,  mResultQueue, mResultSignal,
        mInFlightLock, mLastCompletedRegularFrameNumber,
        mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
        mInFlightMap, mOutputLock,  mResultQueue, mResultSignal,
        mNextShutterFrameNumber,
        mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
        mNextResultFrameNumber,
@@ -1139,8 +1142,9 @@ hardware::Return<void> Camera3Device::notify(

    CaptureOutputStates states {
        mId,
        mInFlightLock, mInFlightMap,
        mOutputLock,  mResultQueue, mResultSignal,
        mInFlightLock, mLastCompletedRegularFrameNumber,
        mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
        mInFlightMap, mOutputLock,  mResultQueue, mResultSignal,
        mNextShutterFrameNumber,
        mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
        mNextResultFrameNumber,
@@ -5906,11 +5910,13 @@ status_t Camera3Device::switchToOffline(
    //       though technically no other thread should be talking to Camera3Device at this point
    Camera3OfflineStates offlineStates(
            mTagMonitor, mVendorTagId, mUseHalBufManager, mNeedFixupMonochromeTags,
            mUsePartialResult, mNumPartialResults, mNextResultFrameNumber,
            mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
            mNextShutterFrameNumber, mNextReprocessShutterFrameNumber,
            mNextZslStillShutterFrameNumber, mDeviceInfo, mPhysicalDeviceInfoMap,
            mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers);
            mUsePartialResult, mNumPartialResults, mLastCompletedRegularFrameNumber,
            mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
            mNextResultFrameNumber, mNextReprocessResultFrameNumber,
            mNextZslStillResultFrameNumber, mNextShutterFrameNumber,
            mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
            mDeviceInfo, mPhysicalDeviceInfoMap, mDistortionMappers,
            mZoomRatioMappers, mRotateAndCropMappers);

    *session = new Camera3OfflineSession(mId, inputStream, offlineStreamSet,
            std::move(bufferRecords), offlineReqs, offlineStates, offlineSession);
Loading