From: Yin-Chia Yeh Date: Wed, 22 Mar 2017 00:47:02 +0000 (-0700) Subject: Camera: add HAL1 recording batching support X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=1ba83a9a282afa086ac2431942a4814633438ffc;p=android-x86%2Fhardware-interfaces.git Camera: add HAL1 recording batching support Test: Angler HAL1 + set mBatchSize to 4 locally Bug: 35997432 Change-Id: I6baf112f9da56534ae81008bad818fba1e76a294 --- diff --git a/camera/device/1.0/ICameraDevice.hal b/camera/device/1.0/ICameraDevice.hal index 52d6cf05..d4aa8cc6 100644 --- a/camera/device/1.0/ICameraDevice.hal +++ b/camera/device/1.0/ICameraDevice.hal @@ -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 batch); + + /** * Start auto focus. * * The notification callback routine is called with diff --git a/camera/device/1.0/ICameraDeviceCallback.hal b/camera/device/1.0/ICameraDeviceCallback.hal index 1b0db244..1dfcd805 100644 --- a/camera/device/1.0/ICameraDeviceCallback.hal +++ b/camera/device/1.0/ICameraDeviceCallback.hal @@ -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 batch); + }; diff --git a/camera/device/1.0/default/CameraDevice.cpp b/camera/device/1.0/default/CameraDevice.cpp index 819525be..6eeda1ca 100644 --- a/camera/device/1.0/default/CameraDevice.cpp +++ b/camera/device/1.0/default/CameraDevice.cpp @@ -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 CameraDevice::releaseRecordingFrameHandle( return Void(); } +Return CameraDevice::releaseRecordingFrameHandleBatch( + const hidl_vec& 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 CameraDevice::autoFocus() { ALOGV("%s(%s)", __FUNCTION__, mCameraId.c_str()); Mutex::Autolock _l(mLock); diff --git a/camera/device/1.0/default/CameraDevice_1_0.h b/camera/device/1.0/default/CameraDevice_1_0.h index 2568f866..ad5f5820 100644 --- a/camera/device/1.0/default/CameraDevice_1_0.h +++ b/camera/device/1.0/default/CameraDevice_1_0.h @@ -93,6 +93,8 @@ struct CameraDevice : public ICameraDevice { Return releaseRecordingFrame(uint32_t memId, uint32_t bufferIndex) override; Return releaseRecordingFrameHandle( uint32_t memId, uint32_t bufferIndex, const hidl_handle& frame) override; + Return releaseRecordingFrameHandleBatch( + const hidl_vec&) override; Return autoFocus() override; Return cancelAutoFocus() override; Return 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 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); diff --git a/camera/device/1.0/types.hal b/camera/device/1.0/types.hal index bf632d15..ce5205ea 100644 --- a/camera/device/1.0/types.hal +++ b/camera/device/1.0/types.hal @@ -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; +}; diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp index a79c9faf..25ffdc62 100644 --- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp +++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp @@ -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 handleCallbackTimestampBatch(DataCallbackMsg msgType, + const ::android::hardware::hidl_vec& batch) override; + + private: CameraHidlTest *mParent; // Parent object }; @@ -666,6 +671,23 @@ Return CameraHidlTest::Camera1DeviceCb::handleCallbackTimestamp( return Void(); } +Return CameraHidlTest::Camera1DeviceCb::handleCallbackTimestampBatch( + DataCallbackMsg msgType, + const hidl_vec& batch) { + std::unique_lock 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 CameraHidlTest::DeviceCb::processCaptureResult( const hidl_vec& results) { if (nullptr == mParent) {