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

Commit 254446a8 authored by Eino-Ville Talvala's avatar Eino-Ville Talvala
Browse files

Camera2/3: Move recording frame processing to its own thread.

Due to new deadlock opportunities from HAL3 integration, recording
frame processing needs to move out of the new frame handler into its
own thread in StreamingProcessor.

Bug: 9282913
Change-Id: I8d2926f2de9d0d395eef3c328c65caebbdbd2827
parent 8f908c0c
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -102,6 +102,9 @@ status_t Camera2Client::initialize(camera_module_t *module)
    String8 threadName;

    mStreamingProcessor = new StreamingProcessor(this);
    threadName = String8::format("C2-%d-StreamProc",
            mCameraId);
    mStreamingProcessor->run(threadName.string());

    mFrameProcessor = new FrameProcessor(mDevice, this);
    threadName = String8::format("C2-%d-FrameProc",
@@ -411,6 +414,7 @@ void Camera2Client::disconnect() {
    mCallbackProcessor->deleteStream();
    mZslProcessor->deleteStream();

    mStreamingProcessor->requestExit();
    mFrameProcessor->requestExit();
    mCaptureSequencer->requestExit();
    mJpegProcessor->requestExit();
@@ -419,6 +423,7 @@ void Camera2Client::disconnect() {

    ALOGV("Camera %d: Waiting for threads", mCameraId);

    mStreamingProcessor->join();
    mFrameProcessor->join();
    mCaptureSequencer->join();
    mJpegProcessor->join();
+46 −11
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ StreamingProcessor::StreamingProcessor(sp<Camera2Client> client):
        mPreviewStreamId(NO_STREAM),
        mRecordingRequestId(Camera2Client::kRecordingRequestIdStart),
        mRecordingStreamId(NO_STREAM),
        mRecordingFrameAvailable(false),
        mRecordingHeapCount(kDefaultRecordingHeapCount)
{
}
@@ -535,6 +536,36 @@ status_t StreamingProcessor::incrementStreamingIds() {
}

void StreamingProcessor::onFrameAvailable() {
    ATRACE_CALL();
    Mutex::Autolock l(mMutex);
    if (!mRecordingFrameAvailable) {
        mRecordingFrameAvailable = true;
        mRecordingFrameAvailableSignal.signal();
    }

}

bool StreamingProcessor::threadLoop() {
    status_t res;

    {
        Mutex::Autolock l(mMutex);
        while (!mRecordingFrameAvailable) {
            res = mRecordingFrameAvailableSignal.waitRelative(
                mMutex, kWaitDuration);
            if (res == TIMED_OUT) return true;
        }
        mRecordingFrameAvailable = false;
    }

    do {
        res = processRecordingFrame();
    } while (res == OK);

    return true;
}

status_t StreamingProcessor::processRecordingFrame() {
    ATRACE_CALL();
    status_t res;
    sp<Camera2Heap> recordingHeap;
@@ -547,12 +578,14 @@ void StreamingProcessor::onFrameAvailable() {
        BufferItemConsumer::BufferItem imgBuffer;
        res = mRecordingConsumer->acquireBuffer(&imgBuffer);
        if (res != OK) {
            ALOGE("%s: Camera %d: Error receiving recording buffer: %s (%d)",
            if (res != BufferItemConsumer::NO_BUFFER_AVAILABLE) {
                ALOGE("%s: Camera %d: Can't acquire recording buffer: %s (%d)",
                        __FUNCTION__, mId, strerror(-res), res);
            return;
            }
            return res;
        }
        mRecordingConsumer->releaseBuffer(imgBuffer);
        return;
        return OK;
    }

    {
@@ -563,23 +596,24 @@ void StreamingProcessor::onFrameAvailable() {
        BufferItemConsumer::BufferItem imgBuffer;
        res = mRecordingConsumer->acquireBuffer(&imgBuffer);
        if (res != OK) {
            ALOGE("%s: Camera %d: Error receiving recording buffer: %s (%d)",
            if (res != BufferItemConsumer::NO_BUFFER_AVAILABLE) {
                ALOGE("%s: Camera %d: Can't acquire recording buffer: %s (%d)",
                        __FUNCTION__, mId, strerror(-res), res);
            return;
            }
            return res;
        }
        timestamp = imgBuffer.mTimestamp;

        mRecordingFrameCount++;
        ALOGV("OnRecordingFrame: Frame %d", mRecordingFrameCount);

        // TODO: Signal errors here upstream
        if (l.mParameters.state != Parameters::RECORD &&
                l.mParameters.state != Parameters::VIDEO_SNAPSHOT) {
            ALOGV("%s: Camera %d: Discarding recording image buffers "
                    "received after recording done", __FUNCTION__,
                    mId);
            mRecordingConsumer->releaseBuffer(imgBuffer);
            return;
            return INVALID_OPERATION;
        }

        if (mRecordingHeap == 0) {
@@ -594,7 +628,7 @@ void StreamingProcessor::onFrameAvailable() {
                ALOGE("%s: Camera %d: Unable to allocate memory for recording",
                        __FUNCTION__, mId);
                mRecordingConsumer->releaseBuffer(imgBuffer);
                return;
                return NO_MEMORY;
            }
            for (size_t i = 0; i < mRecordingBuffers.size(); i++) {
                if (mRecordingBuffers[i].mBuf !=
@@ -615,7 +649,7 @@ void StreamingProcessor::onFrameAvailable() {
            ALOGE("%s: Camera %d: No free recording buffers, dropping frame",
                    __FUNCTION__, mId);
            mRecordingConsumer->releaseBuffer(imgBuffer);
            return;
            return NO_MEMORY;
        }

        heapIdx = mRecordingHeapHead;
@@ -649,6 +683,7 @@ void StreamingProcessor::onFrameAvailable() {
                CAMERA_MSG_VIDEO_FRAME,
                recordingHeap->mBuffers[heapIdx]);
    }
    return OK;
}

void StreamingProcessor::releaseRecordingFrame(const sp<IMemory>& mem) {
+10 −1
Original line number Diff line number Diff line
@@ -37,7 +37,8 @@ class Camera2Heap;
/**
 * Management and processing for preview and recording streams
 */
class StreamingProcessor: public BufferItemConsumer::FrameAvailableListener {
class StreamingProcessor:
            public Thread, public BufferItemConsumer::FrameAvailableListener {
  public:
    StreamingProcessor(sp<Camera2Client> client);
    ~StreamingProcessor();
@@ -103,6 +104,8 @@ class StreamingProcessor: public BufferItemConsumer::FrameAvailableListener {
    sp<ANativeWindow> mPreviewWindow;

    // Recording-related members
    static const nsecs_t kWaitDuration = 50000000; // 50 ms

    int32_t mRecordingRequestId;
    int mRecordingStreamId;
    int mRecordingFrameCount;
@@ -111,11 +114,17 @@ class StreamingProcessor: public BufferItemConsumer::FrameAvailableListener {
    CameraMetadata mRecordingRequest;
    sp<camera2::Camera2Heap> mRecordingHeap;

    bool mRecordingFrameAvailable;
    Condition mRecordingFrameAvailableSignal;

    static const size_t kDefaultRecordingHeapCount = 8;
    size_t mRecordingHeapCount;
    Vector<BufferItemConsumer::BufferItem> mRecordingBuffers;
    size_t mRecordingHeapHead, mRecordingHeapFree;

    virtual bool threadLoop();

    status_t processRecordingFrame();
};