OSDN Git Service

Camera: add HAL1 recording batching support
authorYin-Chia Yeh <yinchiayeh@google.com>
Wed, 22 Mar 2017 00:47:02 +0000 (17:47 -0700)
committerYin-Chia Yeh <yinchiayeh@google.com>
Sat, 1 Apr 2017 20:12:49 +0000 (13:12 -0700)
Test: Angler HAL1 + set mBatchSize to 4 locally
Bug: 35997432
Change-Id: I6baf112f9da56534ae81008bad818fba1e76a294

camera/device/1.0/ICameraDevice.hal
camera/device/1.0/ICameraDeviceCallback.hal
camera/device/1.0/default/CameraDevice.cpp
camera/device/1.0/default/CameraDevice_1_0.h
camera/device/1.0/types.hal
camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp

index 52d6cf0..d4aa8cc 100644 (file)
@@ -328,6 +328,20 @@ interface ICameraDevice {
     releaseRecordingFrameHandle(MemoryId memId, uint32_t bufferIndex, handle frame);
 
     /**
+     * Release a batch of record frames previously returned by CAMERA_MSG_VIDEO_FRAME
+     * in handleCallbackTimestampBatch.
+     *
+     * It is camera HAL client's responsibility to release video recording
+     * frames sent out by the camera HAL before the camera HAL receives a call
+     * to disableMsgType(CAMERA_MSG_VIDEO_FRAME). After it receives the call to
+     * disableMsgType(CAMERA_MSG_VIDEO_FRAME), it is the camera HAL's
+     * responsibility to manage the life-cycle of the video recording frames.
+     *
+     * @param batch A batch of recording frames to be released by camera HAL.
+     */
+    releaseRecordingFrameHandleBatch(vec<VideoFrameMessage> batch);
+
+    /**
      * Start auto focus.
      *
      * The notification callback routine is called with
index 1b0db24..1dfcd80 100644 (file)
@@ -92,10 +92,24 @@ interface ICameraDeviceCallback {
      * @param timestamp The time this buffer was captured by the camera, in
      *     nanoseconds.
      *
-     * @return frameId a frame ID to be used with releaseRecordingFrameId later
-     *
      */
     handleCallbackTimestamp(DataCallbackMsg msgType, handle frameData, MemoryId data,
             uint32_t bufferIndex, int64_t timestamp);
 
+    /**
+     * Send a batch of image data buffer to the camera service, with timestamps
+     *
+     * This callback can be used to send multiple frames to camera framework in one callback, which
+     * reduce number of callbacks in performance intensive use cases, such as high speed video
+     * recording. The HAL must not mix use of this method with handleCallbackTimestamp in one
+     * recording session (between startRecording and stopRecording)
+     *
+     * @param msgType The kind of image buffer data this call represents.
+     * @param batch a vector messages. Each message contains a image buffer and a timestamp. The
+     *     messages must be ordered in time from lower index to higher index, so that timestamp of
+     *     i-th message is always smaller than i+1-th message.
+     *
+     */
+    handleCallbackTimestampBatch(DataCallbackMsg msgType, vec<HandleTimestampMessage> batch);
+
 };
index 819525b..6eeda1c 100644 (file)
@@ -420,6 +420,39 @@ void CameraDevice::sDataCb(int32_t msg_type, const camera_memory_t *data, unsign
     }
 }
 
+void CameraDevice::handleCallbackTimestamp(
+        nsecs_t timestamp, int32_t msg_type,
+        MemoryId memId , unsigned index, native_handle_t* handle) {
+    uint32_t batchSize = 0;
+    {
+        Mutex::Autolock _l(mBatchLock);
+        batchSize = mBatchSize;
+    }
+
+    if (batchSize == 0) { // non-batch mode
+        mDeviceCallback->handleCallbackTimestamp(
+                (DataCallbackMsg) msg_type, handle, memId, index, timestamp);
+    } else { // batch mode
+        Mutex::Autolock _l(mBatchLock);
+        size_t inflightSize = mInflightBatch.size();
+        if (inflightSize == 0) {
+            mBatchMsgType = msg_type;
+        } else if (mBatchMsgType != msg_type) {
+            ALOGE("%s: msg_type change (from %d to %d) is not supported!",
+                    __FUNCTION__, mBatchMsgType, msg_type);
+            return;
+        }
+        mInflightBatch.push_back({handle, memId, index, timestamp});
+
+        // Send batched frames to camera framework
+        if (mInflightBatch.size() >= batchSize) {
+            mDeviceCallback->handleCallbackTimestampBatch(
+                    (DataCallbackMsg) mBatchMsgType, mInflightBatch);
+            mInflightBatch.clear();
+        }
+    }
+}
+
 void CameraDevice::sDataCbTimestamp(nsecs_t timestamp, int32_t msg_type,
         const camera_memory_t *data, unsigned index, void *user) {
     ALOGV("%s", __FUNCTION__);
@@ -450,8 +483,7 @@ void CameraDevice::sDataCbTimestamp(nsecs_t timestamp, int32_t msg_type,
             object->mDeviceCallback->dataCallbackTimestamp(
                     (DataCallbackMsg) msg_type, mem->handle.mId, index, timestamp);
         } else {
-            object->mDeviceCallback->handleCallbackTimestamp(
-                    (DataCallbackMsg) msg_type, handle, mem->handle.mId, index, timestamp);
+            object->handleCallbackTimestamp(timestamp, msg_type, mem->handle.mId, index, handle);
         }
     }
 }
@@ -827,6 +859,17 @@ Return<void> CameraDevice::releaseRecordingFrameHandle(
     return Void();
 }
 
+Return<void> CameraDevice::releaseRecordingFrameHandleBatch(
+        const hidl_vec<VideoFrameMessage>& msgs) {
+    ALOGV("%s(%s)", __FUNCTION__, mCameraId.c_str());
+    Mutex::Autolock _l(mLock);
+    for (auto& msg : msgs) {
+        releaseRecordingFrameLocked(
+                msg.data, msg.bufferIndex, msg.frameData.getNativeHandle());
+    }
+    return Void();
+}
+
 Return<Status> CameraDevice::autoFocus() {
     ALOGV("%s(%s)", __FUNCTION__, mCameraId.c_str());
     Mutex::Autolock _l(mLock);
index 2568f86..ad5f582 100644 (file)
@@ -93,6 +93,8 @@ struct CameraDevice : public ICameraDevice {
     Return<void> releaseRecordingFrame(uint32_t memId, uint32_t bufferIndex) override;
     Return<void> releaseRecordingFrameHandle(
             uint32_t memId, uint32_t bufferIndex, const hidl_handle& frame) override;
+    Return<void> releaseRecordingFrameHandleBatch(
+            const hidl_vec<VideoFrameMessage>&) override;
     Return<Status> autoFocus() override;
     Return<Status> cancelAutoFocus() override;
     Return<Status> takePicture() override;
@@ -169,6 +171,16 @@ private:
 
     bool mMetadataMode = false;
 
+    mutable Mutex mBatchLock;
+    // Start of protection scope for mBatchLock
+    uint32_t mBatchSize = 0; // 0 for non-batch mode, set to other value to start batching
+    int32_t mBatchMsgType;   // Maybe only allow DataCallbackMsg::VIDEO_FRAME?
+    std::vector<HandleTimestampMessage> mInflightBatch;
+    // End of protection scope for mBatchLock
+
+    void handleCallbackTimestamp(
+            nsecs_t timestamp, int32_t msg_type,
+            MemoryId memId , unsigned index, native_handle_t* handle);
     void releaseRecordingFrameLocked(uint32_t memId, uint32_t bufferIndex, const native_handle_t*);
 
     // shared memory methods
@@ -178,13 +190,13 @@ private:
     // Device callback forwarding methods
     static void sNotifyCb(int32_t msg_type, int32_t ext1, int32_t ext2, void *user);
     static void sDataCb(int32_t msg_type, const camera_memory_t *data, unsigned int index,
-                          camera_frame_metadata_t *metadata, void *user);
+                        camera_frame_metadata_t *metadata, void *user);
     static void sDataCbTimestamp(nsecs_t timestamp, int32_t msg_type,
                                     const camera_memory_t *data, unsigned index, void *user);
 
     // Preview window callback forwarding methods
     static int sDequeueBuffer(struct preview_stream_ops* w,
-                                buffer_handle_t** buffer, int *stride);
+                              buffer_handle_t** buffer, int *stride);
 
     static int sLockBuffer(struct preview_stream_ops* w, buffer_handle_t* buffer);
 
@@ -195,7 +207,7 @@ private:
     static int sSetBufferCount(struct preview_stream_ops* w, int count);
 
     static int sSetBuffersGeometry(struct preview_stream_ops* w,
-                                     int width, int height, int format);
+                                   int width, int height, int format);
 
     static int sSetCrop(struct preview_stream_ops *w, int left, int top, int right, int bottom);
 
index bf632d1..ce5205e 100644 (file)
@@ -254,3 +254,36 @@ struct CameraFrameMetadata {
  * between the HAL and the framework.
  */
 typedef uint32_t MemoryId;
+
+/*
+ * Struct containing arguments of ICameraDeviceCallback::handleCallbackTimestamp.
+ * Used to send a batch of messages in ICameraDeviceCallback::handleCallbackTimestampBatch.
+ */
+struct HandleTimestampMessage {
+    // The handle of image buffer data.
+    handle frameData;
+
+    // A memory handle to the buffer containing the data
+    MemoryId data;
+
+    // The offset into the memory handle where the buffer starts.
+    uint32_t bufferIndex;
+
+    // The time this buffer was captured by the camera, in nanoseconds
+    int64_t timestamp;
+};
+
+/*
+ * Struct containing arguments of ICameraDevice::releaseRecordingFrameHandle.
+ * Used by camera framework to send a batch of recording frames back to camera HAL.
+ */
+struct VideoFrameMessage {
+    // The handle of image buffer data.
+    handle frameData;
+
+    // A memory handle to the buffer containing the data
+    MemoryId data;
+
+    // The offset into the memory handle where the buffer starts.
+    uint32_t bufferIndex;
+};
index a79c9fa..25ffdc6 100644 (file)
@@ -86,6 +86,7 @@ using ::android::hardware::camera::device::V1_0::DataCallbackMsg;
 using ::android::hardware::camera::device::V1_0::CameraFrameMetadata;
 using ::android::hardware::camera::device::V1_0::ICameraDevicePreviewCallback;
 using ::android::hardware::camera::device::V1_0::FrameCallbackFlag;
+using ::android::hardware::camera::device::V1_0::HandleTimestampMessage;
 
 const char kCameraPassthroughServiceName[] = "legacy/0";
 const uint32_t kMaxPreviewWidth = 1920;
@@ -510,6 +511,10 @@ public:
                 const hidl_handle& frameData,uint32_t data,
                 uint32_t bufferIndex, int64_t timestamp) override;
 
+        Return<void> handleCallbackTimestampBatch(DataCallbackMsg msgType,
+                const ::android::hardware::hidl_vec<HandleTimestampMessage>& batch) override;
+
+
      private:
         CameraHidlTest *mParent;               // Parent object
     };
@@ -666,6 +671,23 @@ Return<void> CameraHidlTest::Camera1DeviceCb::handleCallbackTimestamp(
     return Void();
 }
 
+Return<void> CameraHidlTest::Camera1DeviceCb::handleCallbackTimestampBatch(
+        DataCallbackMsg msgType,
+        const hidl_vec<HandleTimestampMessage>& batch) {
+    std::unique_lock<std::mutex> l(mParent->mLock);
+    for (auto& msg : batch) {
+        mParent->mDataMessageTypeReceived = msgType;
+        mParent->mVideoBufferIndex = msg.bufferIndex;
+        if (mParent->mMemoryPool.count(msg.data) == 0) {
+            ADD_FAILURE() << "memory pool ID " << msg.data << " not found";
+        }
+        mParent->mVideoData = msg.data;
+        mParent->mVideoNativeHandle = msg.frameData;
+        mParent->mResultCondition.notify_one();
+    }
+    return Void();
+}
+
 Return<void> CameraHidlTest::DeviceCb::processCaptureResult(
         const hidl_vec<CaptureResult>& results) {
     if (nullptr == mParent) {