OSDN Git Service

Camera2/3: Move recording frame processing to its own thread.
authorEino-Ville Talvala <etalvala@google.com>
Tue, 4 Jun 2013 23:34:35 +0000 (16:34 -0700)
committerThe Android Automerger <android-build@android.com>
Wed, 5 Jun 2013 22:38:18 +0000 (15:38 -0700)
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
services/camera/libcameraservice/camera2/StreamingProcessor.cpp
services/camera/libcameraservice/camera2/StreamingProcessor.h

index 5fdec34..081fdec 100644 (file)
@@ -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();
index f4a9217..fed05a6 100644 (file)
@@ -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) {
index 281b344..9f71fa0 100644 (file)
@@ -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();
 };