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

Commit b3a0fb55 authored by Shuzhen Wang's avatar Shuzhen Wang
Browse files

Camera: Fix high speed recording failure due to prepare()

In case application sends 2 consecutive setRepeatingBurst, the first
request may be preparing the video stream, whiel the second request
fails the isPreparing check.

Fix this by distinguishing between internal and external prepare. For
internal prepare, allow new requests to come through to the request
thread.

Bug: 114422231
Bug: 109830370
Test: Camera CTS
Change-Id: I55a7271e3924f2cb8cf9c452e934b070a82bc4ca
parent daba8f4f
Loading
Loading
Loading
Loading
+8 −7
Original line number Diff line number Diff line
@@ -2261,8 +2261,8 @@ sp<Camera3Device::CaptureRequest> Camera3Device::createCaptureRequest(
                return NULL;
            }
        }
        // Check if stream is being prepared
        if (mInputStream->isPreparing()) {
        // Check if stream prepare is blocking requests.
        if (mInputStream->isBlockedByPrepare()) {
            CLOGE("Request references an input stream that's being prepared!");
            return NULL;
        }
@@ -2312,8 +2312,8 @@ sp<Camera3Device::CaptureRequest> Camera3Device::createCaptureRequest(
                return NULL;
            }
        }
        // Check if stream is being prepared
        if (stream->isPreparing()) {
        // Check if stream prepare is blocking requests.
        if (stream->isBlockedByPrepare()) {
            CLOGE("Request references an output stream that's being prepared!");
            return NULL;
        }
@@ -4871,7 +4871,8 @@ status_t Camera3Device::RequestThread::prepareHalRequests() {
                // Only try to prepare video stream on the first video request.
                mPrepareVideoStream = false;

                res = outputStream->startPrepare(Camera3StreamInterface::ALLOCATE_PIPELINE_MAX);
                res = outputStream->startPrepare(Camera3StreamInterface::ALLOCATE_PIPELINE_MAX,
                        false /*blockRequest*/);
                while (res == NOT_ENOUGH_DATA) {
                    res = outputStream->prepareNextBuffer();
                }
@@ -5536,7 +5537,7 @@ status_t Camera3Device::PreparerThread::prepare(int maxCount, sp<Camera3StreamIn
    Mutex::Autolock l(mLock);
    sp<NotificationListener> listener = mListener.promote();

    res = stream->startPrepare(maxCount);
    res = stream->startPrepare(maxCount, true /*blockRequest*/);
    if (res == OK) {
        // No preparation needed, fire listener right off
        ALOGV("%s: Stream %d already prepared", __FUNCTION__, stream->getId());
@@ -5624,7 +5625,7 @@ status_t Camera3Device::PreparerThread::resume() {

    auto it = mPendingStreams.begin();
    for (; it != mPendingStreams.end();) {
        res = it->second->startPrepare(it->first);
        res = it->second->startPrepare(it->first, true /*blockRequest*/);
        if (res == OK) {
            if (listener != NULL) {
                listener->notifyPrepared(it->second->getId());
+6 −5
Original line number Diff line number Diff line
@@ -61,6 +61,7 @@ Camera3Stream::Camera3Stream(int id,
    mOldUsage(0),
    mOldMaxBuffers(0),
    mPrepared(false),
    mPrepareBlockRequest(true),
    mPreparedBufferIdx(0),
    mLastMaxCount(Camera3StreamInterface::ALLOCATE_PIPELINE_MAX),
    mBufferLimitLatency(kBufferLimitLatencyBinSize),
@@ -327,6 +328,7 @@ status_t Camera3Stream::finishConfiguration() {
    // Reset prepared state, since buffer config has changed, and existing
    // allocations are no longer valid
    mPrepared = false;
    mPrepareBlockRequest = true;
    mStreamUnpreparable = false;

    status_t res;
@@ -381,7 +383,7 @@ bool Camera3Stream::isUnpreparable() {
    return mStreamUnpreparable;
}

status_t Camera3Stream::startPrepare(int maxCount) {
status_t Camera3Stream::startPrepare(int maxCount, bool blockRequest) {
    ATRACE_CALL();

    Mutex::Autolock l(mLock);
@@ -413,8 +415,6 @@ status_t Camera3Stream::startPrepare(int maxCount) {
        return INVALID_OPERATION;
    }



    size_t pipelineMax = getBufferCountLocked();
    size_t clampedCount = (pipelineMax < static_cast<size_t>(maxCount)) ?
            pipelineMax : static_cast<size_t>(maxCount);
@@ -422,6 +422,7 @@ status_t Camera3Stream::startPrepare(int maxCount) {
            pipelineMax : clampedCount;

    mPrepared = bufferCount <= mLastMaxCount;
    mPrepareBlockRequest = blockRequest;

    if (mPrepared) return OK;

@@ -435,9 +436,9 @@ status_t Camera3Stream::startPrepare(int maxCount) {
    return NOT_ENOUGH_DATA;
}

bool Camera3Stream::isPreparing() const {
bool Camera3Stream::isBlockedByPrepare() const {
    Mutex::Autolock l(mLock);
    return mState == STATE_PREPARING;
    return mState == STATE_PREPARING && mPrepareBlockRequest;
}

bool Camera3Stream::isAbandoned() const {
+9 −3
Original line number Diff line number Diff line
@@ -232,6 +232,11 @@ class Camera3Stream :
     *
     * This call performs no allocation, so is quick to call.
     *
     * blockRequest specifies whether prepare will block upcoming capture
     * request. This flag should only be set to false if the caller guarantees
     * the whole buffer preparation process is done before capture request
     * comes in.
     *
     * Returns:
     *    OK if no more buffers need to be preallocated
     *    NOT_ENOUGH_DATA if calls to prepareNextBuffer are needed to finish
@@ -240,12 +245,12 @@ class Camera3Stream :
     *    INVALID_OPERATION if called when not in CONFIGURED state, or a
     *        valid buffer has already been returned to this stream.
     */
    status_t         startPrepare(int maxCount);
    status_t         startPrepare(int maxCount, bool blockRequest);

    /**
     * Check if the stream is mid-preparing.
     * Check if the request on a stream is blocked by prepare.
     */
    bool             isPreparing() const;
    bool             isBlockedByPrepare() const;

    /**
     * Continue stream buffer preparation by allocating the next
@@ -534,6 +539,7 @@ class Camera3Stream :
    // has been called sufficient number of times, or stream configuration
    // had to register buffers with the HAL
    bool mPrepared;
    bool mPrepareBlockRequest;

    Vector<camera3_stream_buffer_t> mPreparedBuffers;
    size_t mPreparedBufferIdx;
+8 −3
Original line number Diff line number Diff line
@@ -160,6 +160,11 @@ class Camera3StreamInterface : public virtual RefBase {
     * PREPARING state. Otherwise, returns NOT_ENOUGH_DATA and transitions
     * to PREPARING.
     *
     * blockRequest specifies whether prepare will block upcoming capture
     * request. This flag should only be set to false if the caller guarantees
     * the whole buffer preparation process is done before capture request
     * comes in.
     *
     * Returns:
     *    OK if no more buffers need to be preallocated
     *    NOT_ENOUGH_DATA if calls to prepareNextBuffer are needed to finish
@@ -168,12 +173,12 @@ class Camera3StreamInterface : public virtual RefBase {
     *    INVALID_OPERATION if called when not in CONFIGURED state, or a
     *        valid buffer has already been returned to this stream.
     */
    virtual status_t startPrepare(int maxCount) = 0;
    virtual status_t startPrepare(int maxCount, bool blockRequest) = 0;

    /**
     * Check if the stream is mid-preparing.
     * Check if the request on a stream is blocked by prepare.
     */
    virtual bool     isPreparing() const = 0;
    virtual bool     isBlockedByPrepare() const = 0;

    /**
     * Continue stream buffer preparation by allocating the next