From 254446a80cb13d5beb606bfc3e60a17473869478 Mon Sep 17 00:00:00 2001 From: Eino-Ville Talvala Date: Tue, 4 Jun 2013 16:34:35 -0700 Subject: 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(-) (limited to 'services') diff --git a/services/camera/libcameraservice/Camera2Client.cpp b/services/camera/libcameraservice/Camera2Client.cpp index 5fdec34..081fdec 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 f4a9217..fed05a6 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 281b344..9f71fa0 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(); }; -- cgit v1.1