diff options
3 files changed, 61 insertions, 12 deletions
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<Camera2Client> 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<Camera2Heap> 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<IMemory>& 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<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(); }; |