mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-01 11:36:00 +00:00
Camera: add HAL1 recording batching support
Test: Angler HAL1 + set mBatchSize to 4 locally Bug: 35997432 Change-Id: I6baf112f9da56534ae81008bad818fba1e76a294
This commit is contained in:
@@ -327,6 +327,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.
|
||||
*
|
||||
|
||||
@@ -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);
|
||||
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user