Use fmq for camera capture result.
Test: camera works.
Bug: 35788245 [Treble] Pass camera metadata using shared memory
Change-Id: Ia8ba8ac4c8f7d1a89035f549c0281a30190554bb
diff --git a/camera/device/3.2/ICameraDeviceCallback.hal b/camera/device/3.2/ICameraDeviceCallback.hal
index bf51da2..69715de 100644
--- a/camera/device/3.2/ICameraDeviceCallback.hal
+++ b/camera/device/3.2/ICameraDeviceCallback.hal
@@ -42,7 +42,9 @@
* 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,
diff --git a/camera/device/3.2/ICameraDeviceSession.hal b/camera/device/3.2/ICameraDeviceSession.hal
index bf56881..477a3cc 100644
--- a/camera/device/3.2/ICameraDeviceSession.hal
+++ b/camera/device/3.2/ICameraDeviceSession.hal
@@ -263,6 +263,24 @@
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
diff --git a/camera/device/3.2/default/CameraDeviceSession.cpp b/camera/device/3.2/default/CameraDeviceSession.cpp
index ebb8fcb..2499b1a 100644
--- a/camera/device/3.2/default/CameraDeviceSession.cpp
+++ b/camera/device/3.2/default/CameraDeviceSession.cpp
@@ -32,6 +32,8 @@
// 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 @@
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 @@
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 @@
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 @@
}
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 @@
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 @@
}
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::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 @@
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();
}
+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 @@
// 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) {
diff --git a/camera/device/3.2/default/CameraDeviceSession.h b/camera/device/3.2/default/CameraDeviceSession.h
index f59f503..7682165 100644
--- a/camera/device/3.2/default/CameraDeviceSession.h
+++ b/camera/device/3.2/default/CameraDeviceSession.h
@@ -90,6 +90,8 @@
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 @@
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 @@
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 @@
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;
diff --git a/camera/device/3.2/types.hal b/camera/device/3.2/types.hal
index 8e433f6..276e92a 100644
--- a/camera/device/3.2/types.hal
+++ b/camera/device/3.2/types.hal
@@ -853,6 +853,13 @@
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