Camera: add HAL1 recording batching support

Test: Angler HAL1 + set mBatchSize to 4 locally
Bug: 35997432
Change-Id: I6baf112f9da56534ae81008bad818fba1e76a294
This commit is contained in:
Yin-Chia Yeh
2017-03-21 17:47:02 -07:00
parent 3368520bbc
commit 1ba83a9a28
6 changed files with 145 additions and 7 deletions

View File

@@ -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.
*

View 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);
};

View 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);

View 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);

View 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;
};

View 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) {