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

Commit fc9c52f7 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Camera: Rework StreamSplitter for camera use cases"

parents 1cbdb417 bee0f0a5
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -507,6 +507,14 @@ binder::Status CameraDeviceClient::createStream(
            return res;

        if (!isStreamInfoValid) {
            // Streaming sharing is only supported for IMPLEMENTATION_DEFINED
            // formats.
            if (isShared && streamInfo.format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
                String8 msg = String8::format("Camera %s: Stream sharing is only supported for "
                        "IMPLEMENTATION_DEFINED format", mCameraIdStr.string());
                ALOGW("%s: %s", __FUNCTION__, msg.string());
                return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
            }
            isStreamInfoValid = true;
        }

+2 −8
Original line number Diff line number Diff line
@@ -3956,7 +3956,8 @@ status_t Camera3Device::RequestThread::prepareHalRequests() {
                }
            }

            res = outputStream->getBuffer(&outputBuffers->editItemAt(i));
            res = outputStream->getBuffer(&outputBuffers->editItemAt(i),
                    captureRequest->mOutputSurfaces[i]);
            if (res != OK) {
                // Can't get output buffer from gralloc queue - this could be due to
                // abandoned queue or other consumer misbehavior, so not a fatal
@@ -3968,13 +3969,6 @@ status_t Camera3Device::RequestThread::prepareHalRequests() {
            }
            halRequest->num_output_buffers++;

            res = outputStream->notifyRequestedSurfaces(halRequest->frame_number,
                    captureRequest->mOutputSurfaces[i]);
            if (res != OK) {
                ALOGE("RequestThread: Cannot register output surfaces: %s (%d)",
                      strerror(-res), res);
                return INVALID_OPERATION;
            }
        }
        totalNumBuffers += halRequest->num_output_buffers;

+2 −9
Original line number Diff line number Diff line
@@ -36,7 +36,8 @@ Camera3DummyStream::~Camera3DummyStream() {

}

status_t Camera3DummyStream::getBufferLocked(camera3_stream_buffer *) {
status_t Camera3DummyStream::getBufferLocked(camera3_stream_buffer *,
        const std::vector<size_t>&) {
    ATRACE_CALL();
    ALOGE("%s: Stream %d: Dummy stream cannot produce buffers!", __FUNCTION__, mId);
    return INVALID_OPERATION;
@@ -83,14 +84,6 @@ status_t Camera3DummyStream::detachBuffer(sp<GraphicBuffer>* buffer, int* fenceF
    return OK;
}

status_t Camera3DummyStream::notifyRequestedSurfaces(uint32_t frame_number,
        const std::vector<size_t>& surface_ids) {
    (void) frame_number;
    (void) surface_ids;
    // Do nothing
    return OK;
}

status_t Camera3DummyStream::configureQueueLocked() {
    // Do nothing
    return OK;
+2 −4
Original line number Diff line number Diff line
@@ -56,9 +56,6 @@ class Camera3DummyStream :

    virtual status_t detachBuffer(sp<GraphicBuffer>* buffer, int* fenceFd);

    virtual status_t notifyRequestedSurfaces(uint32_t frame_number,
            const std::vector<size_t>& surface_ids);

    /**
     * Return if this output stream is for video encoding.
     */
@@ -102,7 +99,8 @@ class Camera3DummyStream :
    /**
     * Internal Camera3Stream interface
     */
    virtual status_t getBufferLocked(camera3_stream_buffer *buffer);
    virtual status_t getBufferLocked(camera3_stream_buffer *buffer,
            const std::vector<size_t>& surface_ids = std::vector<size_t>());
    virtual status_t returnBufferLocked(
            const camera3_stream_buffer &buffer,
            nsecs_t timestamp);
+87 −68
Original line number Diff line number Diff line
@@ -148,74 +148,18 @@ Camera3OutputStream::~Camera3OutputStream() {
    disconnectLocked();
}

status_t Camera3OutputStream::getBufferLocked(camera3_stream_buffer *buffer) {
status_t Camera3OutputStream::getBufferLocked(camera3_stream_buffer *buffer,
        const std::vector<size_t>&) {
    ATRACE_CALL();
    status_t res;

    if ((res = getBufferPreconditionCheckLocked()) != OK) {
        return res;
    }

    ANativeWindowBuffer* anb;
    int fenceFd = -1;
    bool gotBufferFromManager = false;

    if (mUseBufferManager) {
        sp<GraphicBuffer> gb;
        res = mBufferManager->getBufferForStream(getId(), getStreamSetId(), &gb, &fenceFd);
        if (res == OK) {
            // Attach this buffer to the bufferQueue: the buffer will be in dequeue state after a
            // successful return.
            anb = gb.get();
            res = mConsumer->attachBuffer(anb);
            if (res != OK) {
                ALOGE("%s: Stream %d: Can't attach the output buffer to this surface: %s (%d)",
                        __FUNCTION__, mId, strerror(-res), res);
                return res;
            }
            gotBufferFromManager = true;
            ALOGV("Stream %d: Attached new buffer", getId());
        } else if (res == ALREADY_EXISTS) {
            // Have sufficient free buffers already attached, can just
            // dequeue from buffer queue
            ALOGV("Stream %d: Reusing attached buffer", getId());
            gotBufferFromManager = false;
        } else if (res != OK) {
            ALOGE("%s: Stream %d: Can't get next output buffer from buffer manager: %s (%d)",
                    __FUNCTION__, mId, strerror(-res), res);
            return res;
        }
    }
    if (!gotBufferFromManager) {
        /**
         * Release the lock briefly to avoid deadlock for below scenario:
         * Thread 1: StreamingProcessor::startStream -> Camera3Stream::isConfiguring().
         * This thread acquired StreamingProcessor lock and try to lock Camera3Stream lock.
         * Thread 2: Camera3Stream::returnBuffer->StreamingProcessor::onFrameAvailable().
         * This thread acquired Camera3Stream lock and bufferQueue lock, and try to lock
         * StreamingProcessor lock.
         * Thread 3: Camera3Stream::getBuffer(). This thread acquired Camera3Stream lock
         * and try to lock bufferQueue lock.
         * Then there is circular locking dependency.
         */
        sp<ANativeWindow> currentConsumer = mConsumer;
        mLock.unlock();

        res = currentConsumer->dequeueBuffer(currentConsumer.get(), &anb, &fenceFd);
        mLock.lock();
    status_t res;
    res = getBufferLockedCommon(&anb, &fenceFd);
    if (res != OK) {
            ALOGE("%s: Stream %d: Can't dequeue next output buffer: %s (%d)",
                    __FUNCTION__, mId, strerror(-res), res);

            // Only transition to STATE_ABANDONED from STATE_CONFIGURED. (If it is STATE_PREPARING,
            // let prepareNextBuffer handle the error.)
            if (res == NO_INIT && mState == STATE_CONFIGURED) {
                mState = STATE_ABANDONED;
            }

        return res;
    }
    }

    /**
     * FenceFD now owned by HAL except in case of error,
@@ -227,6 +171,11 @@ status_t Camera3OutputStream::getBufferLocked(camera3_stream_buffer *buffer) {
    return OK;
}

status_t Camera3OutputStream::queueBufferToConsumer(sp<ANativeWindow>& consumer,
            ANativeWindowBuffer* buffer, int anwReleaseFence) {
    return consumer->queueBuffer(consumer.get(), buffer, anwReleaseFence);
}

status_t Camera3OutputStream::returnBufferLocked(
        const camera3_stream_buffer &buffer,
        nsecs_t timestamp) {
@@ -269,6 +218,7 @@ status_t Camera3OutputStream::returnBufferCheckedLocked(
    sp<ANativeWindow> currentConsumer = mConsumer;
    mLock.unlock();

    ANativeWindowBuffer *anwBuffer = container_of(buffer.buffer, ANativeWindowBuffer, handle);
    /**
     * Return buffer back to ANativeWindow
     */
@@ -276,13 +226,14 @@ status_t Camera3OutputStream::returnBufferCheckedLocked(
        // Cancel buffer
        ALOGW("A frame is dropped for stream %d", mId);
        res = currentConsumer->cancelBuffer(currentConsumer.get(),
                container_of(buffer.buffer, ANativeWindowBuffer, handle),
                anwBuffer,
                anwReleaseFence);
        if (res != OK) {
            ALOGE("%s: Stream %d: Error cancelling buffer to native window:"
                  " %s (%d)", __FUNCTION__, mId, strerror(-res), res);
        }

        notifyBufferReleased(anwBuffer);
        if (mUseBufferManager) {
            // Return this buffer back to buffer manager.
            mBufferReleasedListener->onBufferReleased();
@@ -308,9 +259,7 @@ status_t Camera3OutputStream::returnBufferCheckedLocked(
            return res;
        }

        res = currentConsumer->queueBuffer(currentConsumer.get(),
                container_of(buffer.buffer, ANativeWindowBuffer, handle),
                anwReleaseFence);
        res = queueBufferToConsumer(currentConsumer, anwBuffer, anwReleaseFence);
        if (res != OK) {
            ALOGE("%s: Stream %d: Error queueing buffer to native window: "
                  "%s (%d)", __FUNCTION__, mId, strerror(-res), res);
@@ -527,6 +476,76 @@ status_t Camera3OutputStream::configureConsumerQueueLocked() {
    return OK;
}

status_t Camera3OutputStream::getBufferLockedCommon(ANativeWindowBuffer** anb, int* fenceFd) {
    ATRACE_CALL();
    status_t res;

    if ((res = getBufferPreconditionCheckLocked()) != OK) {
        return res;
    }

    bool gotBufferFromManager = false;

    if (mUseBufferManager) {
        sp<GraphicBuffer> gb;
        res = mBufferManager->getBufferForStream(getId(), getStreamSetId(), &gb, fenceFd);
        if (res == OK) {
            // Attach this buffer to the bufferQueue: the buffer will be in dequeue state after a
            // successful return.
            *anb = gb.get();
            res = mConsumer->attachBuffer(*anb);
            if (res != OK) {
                ALOGE("%s: Stream %d: Can't attach the output buffer to this surface: %s (%d)",
                        __FUNCTION__, mId, strerror(-res), res);
                return res;
            }
            gotBufferFromManager = true;
            ALOGV("Stream %d: Attached new buffer", getId());
        } else if (res == ALREADY_EXISTS) {
            // Have sufficient free buffers already attached, can just
            // dequeue from buffer queue
            ALOGV("Stream %d: Reusing attached buffer", getId());
            gotBufferFromManager = false;
        } else if (res != OK) {
            ALOGE("%s: Stream %d: Can't get next output buffer from buffer manager: %s (%d)",
                    __FUNCTION__, mId, strerror(-res), res);
            return res;
        }
    }
    if (!gotBufferFromManager) {
        /**
         * Release the lock briefly to avoid deadlock for below scenario:
         * Thread 1: StreamingProcessor::startStream -> Camera3Stream::isConfiguring().
         * This thread acquired StreamingProcessor lock and try to lock Camera3Stream lock.
         * Thread 2: Camera3Stream::returnBuffer->StreamingProcessor::onFrameAvailable().
         * This thread acquired Camera3Stream lock and bufferQueue lock, and try to lock
         * StreamingProcessor lock.
         * Thread 3: Camera3Stream::getBuffer(). This thread acquired Camera3Stream lock
         * and try to lock bufferQueue lock.
         * Then there is circular locking dependency.
         */
        sp<ANativeWindow> currentConsumer = mConsumer;
        mLock.unlock();

        res = currentConsumer->dequeueBuffer(currentConsumer.get(), anb, fenceFd);
        mLock.lock();
        if (res != OK) {
            ALOGE("%s: Stream %d: Can't dequeue next output buffer: %s (%d)",
                    __FUNCTION__, mId, strerror(-res), res);

            // Only transition to STATE_ABANDONED from STATE_CONFIGURED. (If it is STATE_PREPARING,
            // let prepareNextBuffer handle the error.)
            if (res == NO_INIT && mState == STATE_CONFIGURED) {
                mState = STATE_ABANDONED;
            }

            return res;
        }
    }

    return res;
}

status_t Camera3OutputStream::disconnectLocked() {
    status_t res;

@@ -702,8 +721,7 @@ status_t Camera3OutputStream::detachBuffer(sp<GraphicBuffer>* buffer, int* fence
    return OK;
}

status_t Camera3OutputStream::notifyRequestedSurfaces(uint32_t /*frame_number*/,
        const std::vector<size_t>& /*surface_ids*/) {
status_t Camera3OutputStream::notifyBufferReleased(ANativeWindowBuffer* /*anwBuffer*/) {
    return OK;
}

@@ -717,6 +735,7 @@ bool Camera3OutputStream::isConsumerConfigurationDeferred(size_t surface_id) con
}

status_t Camera3OutputStream::setConsumers(const std::vector<sp<Surface>>& consumers) {
    Mutex::Autolock l(mLock);
    if (consumers.size() != 1) {
        ALOGE("%s: it's illegal to set %zu consumer surfaces!",
                  __FUNCTION__, consumers.size());
Loading