OSDN Git Service

Use fmq for camera capture result.
authorYifan Hong <elsk@google.com>
Wed, 12 Apr 2017 23:31:23 +0000 (16:31 -0700)
committerYin-Chia Yeh <yinchiayeh@google.com>
Fri, 14 Apr 2017 21:28:48 +0000 (14:28 -0700)
Test: camera works.

Bug: 35788245 [Treble] Pass camera metadata using shared memory

Change-Id: Ia8ba8ac4c8f7d1a89035f549c0281a30190554bb

camera/device/3.2/ICameraDeviceCallback.hal
camera/device/3.2/ICameraDeviceSession.hal
camera/device/3.2/default/CameraDeviceSession.cpp
camera/device/3.2/default/CameraDeviceSession.h
camera/device/3.2/types.hal

index bf51da2..69715de 100644 (file)
@@ -42,7 +42,9 @@ interface ICameraDeviceCallback {
      * metadata and low-resolution buffers to be returned in one call, and
      * post-processed JPEG buffers in a later call, once it is available. Each
      * call must include the frame number of the request it is returning
-     * metadata or buffers for.
+     * metadata or buffers for. Only one call to processCaptureResult
+     * may be made at a time by the HAL although the calls may come from
+     * different threads in the HAL.
      *
      * A component (buffer or metadata) of the complete result may only be
      * included in one process_capture_result call. A buffer for each stream,
index bf56881..477a3cc 100644 (file)
@@ -263,6 +263,24 @@ interface ICameraDeviceSession {
     getCaptureRequestMetadataQueue() generates (fmq_sync<uint8_t> queue);
 
     /**
+     * getCaptureResultMetadataQueue:
+     *
+     * Retrieves the queue used along with
+     * ICameraDeviceCallback.processCaptureResult.
+     *
+     * Clients to ICameraDeviceSession must:
+     * - Call getCaptureRequestMetadataQueue to retrieve the fast message queue;
+     * - In implementation of ICameraDeviceCallback, test whether
+     *   .fmqResultSize field is zero.
+     *     - If .fmqResultSize != 0, read result metadata from the fast message
+     *       queue;
+     *     - otherwise, read result metadata in CaptureResult.result.
+     *
+     * @return queue the queue that implementation writes result metadata to.
+     */
+    getCaptureResultMetadataQueue() generates (fmq_sync<uint8_t> queue);
+
+    /**
      * flush:
      *
      * Flush all currently in-process captures and all buffers in the pipeline
index ebb8fcb..2499b1a 100644 (file)
@@ -32,6 +32,8 @@ namespace implementation {
 
 // Size of request metadata fast message queue. Change to 0 to always use hwbinder buffer.
 static constexpr size_t CAMERA_REQUEST_METADATA_QUEUE_SIZE = 1 << 20 /* 1MB */;
+// Size of result metadata fast message queue. Change to 0 to always use hwbinder buffer.
+static constexpr size_t CAMERA_RESULT_METADATA_QUEUE_SIZE  = 1 << 20 /* 1MB */;
 
 HandleImporter& CameraDeviceSession::sHandleImporter = HandleImporter::getInstance();
 const int CameraDeviceSession::ResultBatcher::NOT_BATCHED;
@@ -73,9 +75,16 @@ bool CameraDeviceSession::initialize() {
     mRequestMetadataQueue = std::make_unique<RequestMetadataQueue>(
             CAMERA_REQUEST_METADATA_QUEUE_SIZE, false /* non blocking */);
     if (!mRequestMetadataQueue->isValid()) {
-        ALOGE("%s: invalid fmq", __FUNCTION__);
+        ALOGE("%s: invalid request fmq", __FUNCTION__);
         return true;
     }
+    mResultMetadataQueue = std::make_shared<RequestMetadataQueue>(
+            CAMERA_RESULT_METADATA_QUEUE_SIZE, false /* non blocking */);
+    if (!mResultMetadataQueue->isValid()) {
+        ALOGE("%s: invalid result fmq", __FUNCTION__);
+        return true;
+    }
+    mResultBatcher.setResultMetadataQueue(mResultMetadataQueue);
 
     return false;
 }
@@ -231,6 +240,11 @@ void CameraDeviceSession::ResultBatcher::setBatchedStreams(
     mStreamsToBatch = streamsToBatch;
 }
 
+void CameraDeviceSession::ResultBatcher::setResultMetadataQueue(std::shared_ptr<ResultMetadataQueue> q) {
+    Mutex::Autolock _l(mLock);
+    mResultMetadataQueue = q;
+}
+
 void CameraDeviceSession::ResultBatcher::registerBatch(
         const hidl_vec<CaptureRequest>& requests) {
     auto batch = std::make_shared<InflightBatch>();
@@ -350,6 +364,7 @@ void CameraDeviceSession::ResultBatcher::sendBatchBuffersLocked(
     results.resize(batchSize);
     for (size_t i = 0; i < batchSize; i++) {
         results[i].frameNumber = batch->mFirstFrame + i;
+        results[i].fmqResultSize = 0;
         results[i].partialResult = 0; // 0 for buffer only results
         results[i].inputBuffer.streamId = -1;
         results[i].inputBuffer.bufferId = 0;
@@ -366,7 +381,7 @@ void CameraDeviceSession::ResultBatcher::sendBatchBuffersLocked(
         }
         results[i].outputBuffers = outBufs;
     }
-    mCallback->processCaptureResult(results);
+    invokeProcessCaptureResultCallback(results, /* tryWriteFmq */false);
     freeReleaseFences(results);
     for (int streamId : streams) {
         InflightBatch::BufferBatch& bb = batch->mBatchBufs[streamId];
@@ -396,6 +411,7 @@ void CameraDeviceSession::ResultBatcher::sendBatchMetadataLocked(
             CaptureResult result;
             result.frameNumber = p.first;
             result.result = std::move(p.second);
+            result.fmqResultSize = 0;
             result.inputBuffer.streamId = -1;
             result.inputBuffer.bufferId = 0;
             result.inputBuffer.buffer = nullptr;
@@ -404,7 +420,9 @@ void CameraDeviceSession::ResultBatcher::sendBatchMetadataLocked(
         }
         mb.mMds.clear();
     }
-    mCallback->processCaptureResult(results);
+    hidl_vec<CaptureResult> hResults;
+    hResults.setToExternal(results.data(), results.size());
+    invokeProcessCaptureResultCallback(hResults, /* tryWriteFmq */true);
     batch->mPartialResultProgress = lastPartialResultIdx;
     for (uint32_t partialIdx : toBeRemovedIdxes) {
         batch->mResultMds.erase(partialIdx);
@@ -477,9 +495,37 @@ void CameraDeviceSession::ResultBatcher::notify(NotifyMsg& msg) {
     }
 }
 
+void CameraDeviceSession::ResultBatcher::invokeProcessCaptureResultCallback(
+        hidl_vec<CaptureResult> &results, bool tryWriteFmq) {
+    if (mProcessCaptureResultLock.tryLock() != OK) {
+        ALOGW("%s: previous call is not finished! waiting 1s...",
+                __FUNCTION__);
+        if (mProcessCaptureResultLock.timedLock(1000000000 /* 1s */) != OK) {
+            ALOGE("%s: cannot acquire lock in 1s, cannot proceed",
+                    __FUNCTION__);
+            return;
+        }
+    }
+    if (tryWriteFmq && mResultMetadataQueue->availableToWrite() > 0) {
+        for (CaptureResult &result : results) {
+            if (result.result.size() > 0) {
+                if (mResultMetadataQueue->write(result.result.data(), result.result.size())) {
+                    result.fmqResultSize = result.result.size();
+                    result.result.resize(0);
+                } else {
+                    ALOGW("%s: couldn't utilize fmq, fall back to hwbinder", __FUNCTION__);
+                    result.fmqResultSize = 0;
+                }
+            }
+        }
+    }
+    mCallback->processCaptureResult(results);
+    mProcessCaptureResultLock.unlock();
+}
+
 void CameraDeviceSession::ResultBatcher::processOneCaptureResult(CaptureResult& result) {
     hidl_vec<CaptureResult> results = {result};
-    mCallback->processCaptureResult(results);
+    invokeProcessCaptureResultCallback(results, /* tryWriteFmq */true);
     freeReleaseFences(results);
     return;
 }
@@ -526,6 +572,7 @@ void CameraDeviceSession::ResultBatcher::processCaptureResult(CaptureResult& res
         if (nonBatchedBuffers.size() > 0 || result.inputBuffer.streamId != -1) {
             CaptureResult nonBatchedResult;
             nonBatchedResult.frameNumber = result.frameNumber;
+            nonBatchedResult.fmqResultSize = 0;
             nonBatchedResult.outputBuffers = nonBatchedBuffers;
             nonBatchedResult.inputBuffer = result.inputBuffer;
             nonBatchedResult.partialResult = 0; // 0 for buffer only results
@@ -716,6 +763,12 @@ Return<void> CameraDeviceSession::getCaptureRequestMetadataQueue(
     return Void();
 }
 
+Return<void> CameraDeviceSession::getCaptureResultMetadataQueue(
+    getCaptureResultMetadataQueue_cb _hidl_cb) {
+    _hidl_cb(*mResultMetadataQueue->getDesc());
+    return Void();
+}
+
 Return<void> CameraDeviceSession::processCaptureRequest(
         const hidl_vec<CaptureRequest>& requests,
         const hidl_vec<BufferCache>& cachesToRemove,
@@ -915,6 +968,7 @@ void CameraDeviceSession::sProcessCaptureResult(
     // within the scope of this function
     CaptureResult result;
     result.frameNumber = frameNumber;
+    result.fmqResultSize = 0;
     result.partialResult = hal_result->partial_result;
     convertToHidl(hal_result->result, &result.result);
     if (hasInputBuf) {
index f59f503..7682165 100644 (file)
@@ -90,6 +90,8 @@ struct CameraDeviceSession : public ICameraDeviceSession, private camera3_callba
             const StreamConfiguration& requestedConfiguration, configureStreams_cb _hidl_cb) override;
     Return<void> getCaptureRequestMetadataQueue(
         getCaptureRequestMetadataQueue_cb _hidl_cb) override;
+    Return<void> getCaptureResultMetadataQueue(
+        getCaptureResultMetadataQueue_cb _hidl_cb) override;
     Return<void> processCaptureRequest(
             const hidl_vec<CaptureRequest>& requests,
             const hidl_vec<BufferCache>& cachesToRemove,
@@ -134,12 +136,15 @@ private:
 
     using RequestMetadataQueue = MessageQueue<uint8_t, kSynchronizedReadWrite>;
     std::unique_ptr<RequestMetadataQueue> mRequestMetadataQueue;
+    using ResultMetadataQueue = MessageQueue<uint8_t, kSynchronizedReadWrite>;
+    std::shared_ptr<ResultMetadataQueue> mResultMetadataQueue;
 
     class ResultBatcher {
     public:
         ResultBatcher(const sp<ICameraDeviceCallback>& callback);
         void setNumPartialResults(uint32_t n);
         void setBatchedStreams(const std::vector<int>& streamsToBatch);
+        void setResultMetadataQueue(std::shared_ptr<ResultMetadataQueue> q);
 
         void registerBatch(const hidl_vec<CaptureRequest>& requests);
         void notify(NotifyMsg& msg);
@@ -217,6 +222,7 @@ private:
         void freeReleaseFences(hidl_vec<CaptureResult>&);
         void notifySingleMsg(NotifyMsg& msg);
         void processOneCaptureResult(CaptureResult& result);
+        void invokeProcessCaptureResultCallback(hidl_vec<CaptureResult> &results, bool tryWriteFmq);
 
         // Protect access to mInflightBatches, mNumPartialResults and mStreamsToBatch
         // processCaptureRequest, processCaptureResult, notify will compete for this lock
@@ -226,6 +232,11 @@ private:
         uint32_t mNumPartialResults;
         std::vector<int> mStreamsToBatch;
         const sp<ICameraDeviceCallback> mCallback;
+        std::shared_ptr<ResultMetadataQueue> mResultMetadataQueue;
+
+        // Protect against invokeProcessCaptureResultCallback()
+        Mutex mProcessCaptureResultLock;
+
     } mResultBatcher;
 
     std::vector<int> mVideoStreamIds;
index 8e433f6..276e92a 100644 (file)
@@ -853,6 +853,13 @@ struct CaptureResult {
     uint32_t frameNumber;
 
     /**
+     * If non-zero, read result from result queue instead
+     * (see ICameraDeviceSession.getCaptureResultMetadataQueue).
+     * If zero, read result from .result field.
+     */
+    uint64_t fmqResultSize;
+
+    /**
      * The result metadata for this capture. This contains information about the
      * final capture parameters, the state of the capture and post-processing
      * hardware, the state of the 3A algorithms, if enabled, and the output of