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
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 @@
     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 @@
     mCallbackProcessor->deleteStream();
     mZslProcessor->deleteStream();
 
+    mStreamingProcessor->requestExit();
     mFrameProcessor->requestExit();
     mCaptureSequencer->requestExit();
     mJpegProcessor->requestExit();
@@ -419,6 +423,7 @@
 
     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 @@
         mPreviewStreamId(NO_STREAM),
         mRecordingRequestId(Camera2Client::kRecordingRequestIdStart),
         mRecordingStreamId(NO_STREAM),
+        mRecordingFrameAvailable(false),
         mRecordingHeapCount(kDefaultRecordingHeapCount)
 {
 }
@@ -536,6 +537,36 @@
 
 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 @@
         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 @@
         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 @@
                 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 @@
             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 @@
                 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 @@
 /**
  * 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 @@
     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 @@
     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();
 };