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

Commit 6adc9ccb authored by Zhijun He's avatar Zhijun He
Browse files

Camera3: block until get an available buffer

Camera3Stream shouldn't error out when the max number of buffers are already
dequeued. It should block until next buffer returned from camera device.

Bug: 11595505
Change-Id: If65a70c29cb04219e14ded0744059c0ab783444b
parent cb010a3f
Loading
Loading
Loading
Loading
+31 −13
Original line number Diff line number Diff line
@@ -34,7 +34,8 @@ Camera3IOStreamBase::Camera3IOStreamBase(int id, camera3_stream_type_t type,
        Camera3Stream(id, type,
                width, height, maxSize, format),
        mTotalBufferCount(0),
        mDequeuedBufferCount(0),
        mHandoutTotalBufferCount(0),
        mHandoutOutputBufferCount(0),
        mFrameCount(0),
        mLastTimestamp(0) {

@@ -55,8 +56,8 @@ bool Camera3IOStreamBase::hasOutstandingBuffersLocked() const {
    nsecs_t signalTime = mCombinedFence->getSignalTime();
    ALOGV("%s: Stream %d: Has %zu outstanding buffers,"
            " buffer signal time is %" PRId64,
            __FUNCTION__, mId, mDequeuedBufferCount, signalTime);
    if (mDequeuedBufferCount > 0 || signalTime == INT64_MAX) {
            __FUNCTION__, mId, mHandoutTotalBufferCount, signalTime);
    if (mHandoutTotalBufferCount > 0 || signalTime == INT64_MAX) {
        return true;
    }
    return false;
@@ -75,7 +76,7 @@ void Camera3IOStreamBase::dump(int fd, const Vector<String16> &args) const {
    lines.appendFormat("      Frames produced: %d, last timestamp: %" PRId64 " ns\n",
            mFrameCount, mLastTimestamp);
    lines.appendFormat("      Total buffers: %zu, currently dequeued: %zu\n",
            mTotalBufferCount, mDequeuedBufferCount);
            mTotalBufferCount, mHandoutTotalBufferCount);
    write(fd, lines.string(), lines.size());
}

@@ -104,6 +105,14 @@ size_t Camera3IOStreamBase::getBufferCountLocked() {
    return mTotalBufferCount;
}

size_t Camera3IOStreamBase::getHandoutOutputBufferCountLocked() {
    return mHandoutOutputBufferCount;
}

size_t Camera3IOStreamBase::getHandoutInputBufferCountLocked() {
    return (mHandoutTotalBufferCount - mHandoutOutputBufferCount);
}

status_t Camera3IOStreamBase::disconnectLocked() {
    switch (mState) {
        case STATE_IN_RECONFIG:
@@ -117,9 +126,9 @@ status_t Camera3IOStreamBase::disconnectLocked() {
            return -ENOTCONN;
    }

    if (mDequeuedBufferCount > 0) {
    if (mHandoutTotalBufferCount > 0) {
        ALOGE("%s: Can't disconnect with %zu buffers still dequeued!",
                __FUNCTION__, mDequeuedBufferCount);
                __FUNCTION__, mHandoutTotalBufferCount);
        return INVALID_OPERATION;
    }

@@ -130,7 +139,8 @@ void Camera3IOStreamBase::handoutBufferLocked(camera3_stream_buffer &buffer,
                                              buffer_handle_t *handle,
                                              int acquireFence,
                                              int releaseFence,
                                              camera3_buffer_status_t status) {
                                              camera3_buffer_status_t status,
                                              bool output) {
    /**
     * Note that all fences are now owned by HAL.
     */
@@ -144,7 +154,7 @@ void Camera3IOStreamBase::handoutBufferLocked(camera3_stream_buffer &buffer,
    buffer.status = status;

    // Inform tracker about becoming busy
    if (mDequeuedBufferCount == 0 && mState != STATE_IN_CONFIG &&
    if (mHandoutTotalBufferCount == 0 && mState != STATE_IN_CONFIG &&
            mState != STATE_IN_RECONFIG) {
        /**
         * Avoid a spurious IDLE->ACTIVE->IDLE transition when using buffers
@@ -158,7 +168,11 @@ void Camera3IOStreamBase::handoutBufferLocked(camera3_stream_buffer &buffer,
            statusTracker->markComponentActive(mStatusId);
        }
    }
    mDequeuedBufferCount++;
    mHandoutTotalBufferCount++;

    if (output) {
        mHandoutOutputBufferCount++;
    }
}

status_t Camera3IOStreamBase::getBufferPreconditionCheckLocked() const {
@@ -172,7 +186,7 @@ status_t Camera3IOStreamBase::getBufferPreconditionCheckLocked() const {

    // Only limit dequeue amount when fully configured
    if (mState == STATE_CONFIGURED &&
            mDequeuedBufferCount == camera3_stream::max_buffers) {
            mHandoutTotalBufferCount == camera3_stream::max_buffers) {
        ALOGE("%s: Stream %d: Already dequeued maximum number of simultaneous"
                " buffers (%d)", __FUNCTION__, mId,
                camera3_stream::max_buffers);
@@ -190,7 +204,7 @@ status_t Camera3IOStreamBase::returnBufferPreconditionCheckLocked() const {
                __FUNCTION__, mId, mState);
        return INVALID_OPERATION;
    }
    if (mDequeuedBufferCount == 0) {
    if (mHandoutTotalBufferCount == 0) {
        ALOGE("%s: Stream %d: No buffers outstanding to return", __FUNCTION__,
                mId);
        return INVALID_OPERATION;
@@ -228,8 +242,12 @@ status_t Camera3IOStreamBase::returnAnyBufferLocked(
        mCombinedFence = Fence::merge(mName, mCombinedFence, releaseFence);
    }

    mDequeuedBufferCount--;
    if (mDequeuedBufferCount == 0 && mState != STATE_IN_CONFIG &&
    if (output) {
        mHandoutOutputBufferCount--;
    }

    mHandoutTotalBufferCount--;
    if (mHandoutTotalBufferCount == 0 && mState != STATE_IN_CONFIG &&
            mState != STATE_IN_RECONFIG) {
        /**
         * Avoid a spurious IDLE->ACTIVE->IDLE transition when using buffers
+10 −2
Original line number Diff line number Diff line
@@ -48,7 +48,10 @@ class Camera3IOStreamBase :
  protected:
    size_t            mTotalBufferCount;
    // sum of input and output buffers that are currently acquired by HAL
    size_t            mDequeuedBufferCount;
    size_t            mHandoutTotalBufferCount;
    // number of output buffers that are currently acquired by HAL. This will be
    // Redundant when camera3 streams are no longer bidirectional streams.
    size_t            mHandoutOutputBufferCount;
    Condition         mBufferReturnedSignal;
    uint32_t          mFrameCount;
    // Last received output buffer's timestamp
@@ -76,6 +79,10 @@ class Camera3IOStreamBase :

    virtual size_t   getBufferCountLocked();

    virtual size_t   getHandoutOutputBufferCountLocked();

    virtual size_t   getHandoutInputBufferCountLocked();

    virtual status_t getEndpointUsage(uint32_t *usage) = 0;

    status_t getBufferPreconditionCheckLocked() const;
@@ -92,7 +99,8 @@ class Camera3IOStreamBase :
                             buffer_handle_t *handle,
                             int acquire_fence,
                             int release_fence,
                             camera3_buffer_status_t status);
                             camera3_buffer_status_t status,
                             bool output);

}; // class Camera3IOStreamBase

+2 −2
Original line number Diff line number Diff line
@@ -81,7 +81,7 @@ status_t Camera3InputStream::getInputBufferLocked(
     * in which case we reassign it to acquire_fence
     */
    handoutBufferLocked(*buffer, &(anb->handle), /*acquireFence*/fenceFd,
                        /*releaseFence*/-1, CAMERA3_BUFFER_STATUS_OK);
                        /*releaseFence*/-1, CAMERA3_BUFFER_STATUS_OK, /*output*/false);
    mBuffersInFlight.push_back(bufferItem);

    return OK;
@@ -199,7 +199,7 @@ status_t Camera3InputStream::configureQueueLocked() {
    assert(mMaxSize == 0);
    assert(camera3_stream::format != HAL_PIXEL_FORMAT_BLOB);

    mDequeuedBufferCount = 0;
    mHandoutTotalBufferCount = 0;
    mFrameCount = 0;

    if (mConsumer.get() == 0) {
+2 −2
Original line number Diff line number Diff line
@@ -119,7 +119,7 @@ status_t Camera3OutputStream::getBufferLocked(camera3_stream_buffer *buffer) {
     * in which case we reassign it to acquire_fence
     */
    handoutBufferLocked(*buffer, &(anb->handle), /*acquireFence*/fenceFd,
                        /*releaseFence*/-1, CAMERA3_BUFFER_STATUS_OK);
                        /*releaseFence*/-1, CAMERA3_BUFFER_STATUS_OK, /*output*/true);

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

    mTotalBufferCount = maxConsumerBuffers + camera3_stream::max_buffers;
    mDequeuedBufferCount = 0;
    mHandoutTotalBufferCount = 0;
    mFrameCount = 0;
    mLastTimestamp = 0;

+48 −2
Original line number Diff line number Diff line
@@ -212,8 +212,30 @@ status_t Camera3Stream::finishConfiguration(camera3_device *hal3Device) {
status_t Camera3Stream::getBuffer(camera3_stream_buffer *buffer) {
    ATRACE_CALL();
    Mutex::Autolock l(mLock);
    status_t res = OK;

    status_t res = getBufferLocked(buffer);
    // This function should be only called when the stream is configured already.
    if (mState != STATE_CONFIGURED) {
        ALOGE("%s: Stream %d: Can't get buffers if stream is not in CONFIGURED state %d",
                __FUNCTION__, mId, mState);
        return INVALID_OPERATION;
    }

    // Wait for new buffer returned back if we are running into the limit.
    if (getHandoutOutputBufferCountLocked() == camera3_stream::max_buffers) {
        ALOGV("%s: Already dequeued max output buffers (%d), wait for next returned one.",
                __FUNCTION__, camera3_stream::max_buffers);
        res = mOutputBufferReturnedSignal.waitRelative(mLock, kWaitForBufferDuration);
        if (res != OK) {
            if (res == TIMED_OUT) {
                ALOGE("%s: wait for output buffer return timed out after %lldms", __FUNCTION__,
                        kWaitForBufferDuration / 1000000LL);
            }
            return res;
        }
    }

    res = getBufferLocked(buffer);
    if (res == OK) {
        fireBufferListenersLocked(*buffer, /*acquired*/true, /*output*/true);
    }
@@ -237,6 +259,7 @@ status_t Camera3Stream::returnBuffer(const camera3_stream_buffer &buffer,
    status_t res = returnBufferLocked(buffer, timestamp);
    if (res == OK) {
        fireBufferListenersLocked(buffer, /*acquired*/false, /*output*/true);
        mOutputBufferReturnedSignal.signal();
    }

    return res;
@@ -245,8 +268,30 @@ status_t Camera3Stream::returnBuffer(const camera3_stream_buffer &buffer,
status_t Camera3Stream::getInputBuffer(camera3_stream_buffer *buffer) {
    ATRACE_CALL();
    Mutex::Autolock l(mLock);
    status_t res = OK;

    // This function should be only called when the stream is configured already.
    if (mState != STATE_CONFIGURED) {
        ALOGE("%s: Stream %d: Can't get input buffers if stream is not in CONFIGURED state %d",
                __FUNCTION__, mId, mState);
        return INVALID_OPERATION;
    }

    // Wait for new buffer returned back if we are running into the limit.
    if (getHandoutInputBufferCountLocked() == camera3_stream::max_buffers) {
        ALOGV("%s: Already dequeued max input buffers (%d), wait for next returned one.",
                __FUNCTION__, camera3_stream::max_buffers);
        res = mInputBufferReturnedSignal.waitRelative(mLock, kWaitForBufferDuration);
        if (res != OK) {
            if (res == TIMED_OUT) {
                ALOGE("%s: wait for input buffer return timed out after %lldms", __FUNCTION__,
                        kWaitForBufferDuration / 1000000LL);
            }
            return res;
        }
    }

    status_t res = getInputBufferLocked(buffer);
    res = getInputBufferLocked(buffer);
    if (res == OK) {
        fireBufferListenersLocked(*buffer, /*acquired*/true, /*output*/false);
    }
@@ -261,6 +306,7 @@ status_t Camera3Stream::returnInputBuffer(const camera3_stream_buffer &buffer) {
    status_t res = returnInputBufferLocked(buffer);
    if (res == OK) {
        fireBufferListenersLocked(buffer, /*acquired*/false, /*output*/false);
        mInputBufferReturnedSignal.signal();
    }
    return res;
}
Loading