From 5c192e5d4fcec8aa2dd14be539ac28ffff4a12fa Mon Sep 17 00:00:00 2001 From: Eino-Ville Talvala Date: Tue, 4 Jun 2013 16:34:35 -0700 Subject: [PATCH] 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 --- services/camera/libcameraservice/Camera2Client.cpp | 5 ++ .../camera2/StreamingProcessor.cpp | 57 +++++++++++++++++----- .../libcameraservice/camera2/StreamingProcessor.h | 11 ++++- 3 files changed, 61 insertions(+), 12 deletions(-) diff --git a/services/camera/libcameraservice/Camera2Client.cpp b/services/camera/libcameraservice/Camera2Client.cpp index 5fdec34e7a..081fdec338 100644 --- a/services/camera/libcameraservice/Camera2Client.cpp +++ b/services/camera/libcameraservice/Camera2Client.cpp @@ -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(); diff --git a/services/camera/libcameraservice/camera2/StreamingProcessor.cpp b/services/camera/libcameraservice/camera2/StreamingProcessor.cpp index f4a92176b2..fed05a672f 100644 --- a/services/camera/libcameraservice/camera2/StreamingProcessor.cpp +++ b/services/camera/libcameraservice/camera2/StreamingProcessor.cpp @@ -41,6 +41,7 @@ StreamingProcessor::StreamingProcessor(sp client): mPreviewStreamId(NO_STREAM), mRecordingRequestId(Camera2Client::kRecordingRequestIdStart), mRecordingStreamId(NO_STREAM), + mRecordingFrameAvailable(false), mRecordingHeapCount(kDefaultRecordingHeapCount) { } @@ -536,6 +537,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 recordingHeap; size_t heapIdx = 0; @@ -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)", - __FUNCTION__, mId, strerror(-res), res); - return; + if (res != BufferItemConsumer::NO_BUFFER_AVAILABLE) { + ALOGE("%s: Camera %d: Can't acquire recording buffer: %s (%d)", + __FUNCTION__, mId, strerror(-res), res); + } + 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)", - __FUNCTION__, mId, strerror(-res), res); - return; + if (res != BufferItemConsumer::NO_BUFFER_AVAILABLE) { + ALOGE("%s: Camera %d: Can't acquire recording buffer: %s (%d)", + __FUNCTION__, mId, strerror(-res), res); + } + 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& mem) { diff --git a/services/camera/libcameraservice/camera2/StreamingProcessor.h b/services/camera/libcameraservice/camera2/StreamingProcessor.h index 281b34483e..9f71fa010c 100644 --- a/services/camera/libcameraservice/camera2/StreamingProcessor.h +++ b/services/camera/libcameraservice/camera2/StreamingProcessor.h @@ -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 client); ~StreamingProcessor(); @@ -103,6 +104,8 @@ class StreamingProcessor: public BufferItemConsumer::FrameAvailableListener { sp 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 mRecordingHeap; + bool mRecordingFrameAvailable; + Condition mRecordingFrameAvailableSignal; + static const size_t kDefaultRecordingHeapCount = 8; size_t mRecordingHeapCount; Vector mRecordingBuffers; size_t mRecordingHeapHead, mRecordingHeapFree; + virtual bool threadLoop(); + + status_t processRecordingFrame(); }; -- 2.11.0