camera: Add support for individual physical camera requests
Multi-camera devices should be able to accept and process
individual settings for all physical sensors backing the
logical camera. 'CaptureRequest' must be extended to hold
these additional physical camera settings.
Test: Manual using camera application,
camera_client_test,
run vts --skip-all-system-status-check --skip-preconditions
--primary-abi-only --module VtsHalCameraProviderV2_4Target -l INFO
Bug: 64691172
Change-Id: Ia38d1e7681a9385be7578c11e40f4e35e9101d75
diff --git a/camera/device/3.2/default/CameraDeviceSession.cpp b/camera/device/3.2/default/CameraDeviceSession.cpp
index 631404e..31b4739 100644
--- a/camera/device/3.2/default/CameraDeviceSession.cpp
+++ b/camera/device/3.2/default/CameraDeviceSession.cpp
@@ -333,11 +333,10 @@
mResultMetadataQueue = q;
}
-void CameraDeviceSession::ResultBatcher::registerBatch(
- const hidl_vec<CaptureRequest>& requests) {
+void CameraDeviceSession::ResultBatcher::registerBatch(uint32_t frameNumber, uint32_t batchSize) {
auto batch = std::make_shared<InflightBatch>();
- batch->mFirstFrame = requests[0].frameNumber;
- batch->mBatchSize = requests.size();
+ batch->mFirstFrame = frameNumber;
+ batch->mBatchSize = batchSize;
batch->mLastFrame = batch->mFirstFrame + batch->mBatchSize - 1;
batch->mNumPartialResults = mNumPartialResults;
for (int id : mStreamsToBatch) {
@@ -1010,7 +1009,7 @@
}
if (s == Status::OK && requests.size() > 1) {
- mResultBatcher.registerBatch(requests);
+ mResultBatcher.registerBatch(requests[0].frameNumber, requests.size());
}
_hidl_cb(s, numRequestProcessed);
@@ -1111,6 +1110,7 @@
halRequest.settings = settingsOverride.getAndLock();
}
}
+ halRequest.num_physcam_settings = 0;
ATRACE_ASYNC_BEGIN("frame capture", request.frameNumber);
ATRACE_BEGIN("camera3->process_capture_request");
diff --git a/camera/device/3.2/default/CameraDeviceSession.h b/camera/device/3.2/default/CameraDeviceSession.h
index c5a63c8..0048ef4 100644
--- a/camera/device/3.2/default/CameraDeviceSession.h
+++ b/camera/device/3.2/default/CameraDeviceSession.h
@@ -184,7 +184,7 @@
void setBatchedStreams(const std::vector<int>& streamsToBatch);
void setResultMetadataQueue(std::shared_ptr<ResultMetadataQueue> q);
- void registerBatch(const hidl_vec<CaptureRequest>& requests);
+ void registerBatch(uint32_t frameNumber, uint32_t batchSize);
void notify(NotifyMsg& msg);
void processCaptureResult(CaptureResult& result);
diff --git a/camera/device/3.4/ICameraDeviceSession.hal b/camera/device/3.4/ICameraDeviceSession.hal
index 71a4b34..4ce749d 100644
--- a/camera/device/3.4/ICameraDeviceSession.hal
+++ b/camera/device/3.4/ICameraDeviceSession.hal
@@ -20,7 +20,6 @@
import @3.3::ICameraDeviceSession;
import @3.3::HalStreamConfiguration;
import @3.2::BufferCache;
-import @3.2::CaptureRequest;
/**
* Camera device active session interface.
@@ -72,4 +71,38 @@
configureStreams_3_4(@3.4::StreamConfiguration requestedConfiguration)
generates (Status status,
@3.4::HalStreamConfiguration halConfiguration);
+
+ /**
+ * processCaptureRequest_3_4:
+ *
+ * Identical to @3.2::ICameraDeviceSession.processCaptureRequest, except that:
+ *
+ * - The capture request can include individual settings for physical camera devices
+ * backing a logical multi-camera.
+ *
+ * @return status Status code for the operation, one of:
+ * OK:
+ * On a successful start to processing the capture request
+ * ILLEGAL_ARGUMENT:
+ * If the input is malformed (the settings are empty when not
+ * allowed, the physical camera settings are invalid, there are 0
+ * output buffers, etc) and capture processing
+ * cannot start. Failures during request processing must be
+ * handled by calling ICameraDeviceCallback::notify(). In case of
+ * this error, the framework retains responsibility for the
+ * stream buffers' fences and the buffer handles; the HAL must not
+ * close the fences or return these buffers with
+ * ICameraDeviceCallback::processCaptureResult().
+ * INTERNAL_ERROR:
+ * If the camera device has encountered a serious error. After this
+ * error is returned, only the close() method can be successfully
+ * called by the framework.
+ * @return numRequestProcessed Number of requests successfully processed by
+ * camera HAL. When status is OK, this must be equal to the size of
+ * requests. When the call fails, this number is the number of requests
+ * that HAL processed successfully before HAL runs into an error.
+ *
+ */
+ processCaptureRequest_3_4(vec<CaptureRequest> requests, vec<BufferCache> cachesToRemove)
+ generates (Status status, uint32_t numRequestProcessed);
};
diff --git a/camera/device/3.4/default/CameraDeviceSession.cpp b/camera/device/3.4/default/CameraDeviceSession.cpp
index b74fd57..c8d33eb 100644
--- a/camera/device/3.4/default/CameraDeviceSession.cpp
+++ b/camera/device/3.4/default/CameraDeviceSession.cpp
@@ -201,9 +201,9 @@
}
Return<void> CameraDeviceSession::processCaptureRequest_3_4(
- const hidl_vec<CaptureRequest>& requests,
+ const hidl_vec<V3_4::CaptureRequest>& requests,
const hidl_vec<V3_2::BufferCache>& cachesToRemove,
- ICameraDeviceSession::processCaptureRequest_cb _hidl_cb) {
+ ICameraDeviceSession::processCaptureRequest_3_4_cb _hidl_cb) {
updateBufferCaches(cachesToRemove);
uint32_t numRequestProcessed = 0;
@@ -216,14 +216,14 @@
}
if (s == Status::OK && requests.size() > 1) {
- mResultBatcher.registerBatch(requests);
+ mResultBatcher.registerBatch(requests[0].v3_2.frameNumber, requests.size());
}
_hidl_cb(s, numRequestProcessed);
return Void();
}
-Status CameraDeviceSession::processOneCaptureRequest_3_4(const CaptureRequest& request) {
+Status CameraDeviceSession::processOneCaptureRequest_3_4(const V3_4::CaptureRequest& request) {
Status status = initStatus();
if (status != Status::OK) {
ALOGE("%s: camera init failed or disconnected", __FUNCTION__);
@@ -231,15 +231,15 @@
}
camera3_capture_request_t halRequest;
- halRequest.frame_number = request.frameNumber;
+ halRequest.frame_number = request.v3_2.frameNumber;
bool converted = true;
V3_2::CameraMetadata settingsFmq; // settings from FMQ
- if (request.fmqSettingsSize > 0) {
+ if (request.v3_2.fmqSettingsSize > 0) {
// non-blocking read; client must write metadata before calling
// processOneCaptureRequest
- settingsFmq.resize(request.fmqSettingsSize);
- bool read = mRequestMetadataQueue->read(settingsFmq.data(), request.fmqSettingsSize);
+ settingsFmq.resize(request.v3_2.fmqSettingsSize);
+ bool read = mRequestMetadataQueue->read(settingsFmq.data(), request.v3_2.fmqSettingsSize);
if (read) {
converted = V3_2::implementation::convertFromHidl(settingsFmq, &halRequest.settings);
} else {
@@ -247,7 +247,8 @@
converted = false;
}
} else {
- converted = V3_2::implementation::convertFromHidl(request.settings, &halRequest.settings);
+ converted = V3_2::implementation::convertFromHidl(request.v3_2.settings,
+ &halRequest.settings);
}
if (!converted) {
@@ -263,9 +264,9 @@
hidl_vec<buffer_handle_t*> allBufPtrs;
hidl_vec<int> allFences;
- bool hasInputBuf = (request.inputBuffer.streamId != -1 &&
- request.inputBuffer.bufferId != 0);
- size_t numOutputBufs = request.outputBuffers.size();
+ bool hasInputBuf = (request.v3_2.inputBuffer.streamId != -1 &&
+ request.v3_2.inputBuffer.bufferId != 0);
+ size_t numOutputBufs = request.v3_2.outputBuffers.size();
size_t numBufs = numOutputBufs + (hasInputBuf ? 1 : 0);
if (numOutputBufs == 0) {
@@ -273,7 +274,7 @@
return Status::ILLEGAL_ARGUMENT;
}
- status = importRequest(request, allBufPtrs, allFences);
+ status = importRequest(request.v3_2, allBufPtrs, allFences);
if (status != Status::OK) {
return status;
}
@@ -285,12 +286,12 @@
{
Mutex::Autolock _l(mInflightLock);
if (hasInputBuf) {
- auto streamId = request.inputBuffer.streamId;
- auto key = std::make_pair(request.inputBuffer.streamId, request.frameNumber);
+ auto streamId = request.v3_2.inputBuffer.streamId;
+ auto key = std::make_pair(request.v3_2.inputBuffer.streamId, request.v3_2.frameNumber);
auto& bufCache = mInflightBuffers[key] = camera3_stream_buffer_t{};
convertFromHidl(
- allBufPtrs[numOutputBufs], request.inputBuffer.status,
- &mStreamMap[request.inputBuffer.streamId], allFences[numOutputBufs],
+ allBufPtrs[numOutputBufs], request.v3_2.inputBuffer.status,
+ &mStreamMap[request.v3_2.inputBuffer.streamId], allFences[numOutputBufs],
&bufCache);
bufCache.stream->physical_camera_id = mPhysicalCameraIdMap[streamId].c_str();
halRequest.input_buffer = &bufCache;
@@ -300,11 +301,11 @@
halRequest.num_output_buffers = numOutputBufs;
for (size_t i = 0; i < numOutputBufs; i++) {
- auto streamId = request.outputBuffers[i].streamId;
- auto key = std::make_pair(streamId, request.frameNumber);
+ auto streamId = request.v3_2.outputBuffers[i].streamId;
+ auto key = std::make_pair(streamId, request.v3_2.frameNumber);
auto& bufCache = mInflightBuffers[key] = camera3_stream_buffer_t{};
convertFromHidl(
- allBufPtrs[i], request.outputBuffers[i].status,
+ allBufPtrs[i], request.v3_2.outputBuffers[i].status,
&mStreamMap[streamId], allFences[i],
&bufCache);
bufCache.stream->physical_camera_id = mPhysicalCameraIdMap[streamId].c_str();
@@ -322,7 +323,47 @@
}
}
- ATRACE_ASYNC_BEGIN("frame capture", request.frameNumber);
+ std::vector<const char *> physicalCameraIds;
+ std::vector<const camera_metadata_t *> physicalCameraSettings;
+ std::vector<V3_2::CameraMetadata> physicalFmq;
+ size_t settingsCount = request.physicalCameraSettings.size();
+ if (settingsCount > 0) {
+ physicalCameraIds.reserve(settingsCount);
+ physicalCameraSettings.reserve(settingsCount);
+ physicalFmq.reserve(settingsCount);
+
+ for (size_t i = 0; i < settingsCount; i++) {
+ uint64_t settingsSize = request.physicalCameraSettings[i].fmqSettingsSize;
+ const camera_metadata_t *settings;
+ if (settingsSize > 0) {
+ physicalFmq.push_back(V3_2::CameraMetadata(settingsSize));
+ bool read = mRequestMetadataQueue->read(physicalFmq[i].data(), settingsSize);
+ if (read) {
+ converted = V3_2::implementation::convertFromHidl(physicalFmq[i], &settings);
+ physicalCameraSettings.push_back(settings);
+ } else {
+ ALOGE("%s: physical camera settings metadata couldn't be read from fmq!",
+ __FUNCTION__);
+ converted = false;
+ }
+ } else {
+ converted = V3_2::implementation::convertFromHidl(
+ request.physicalCameraSettings[i].settings, &settings);
+ physicalCameraSettings.push_back(settings);
+ }
+
+ if (!converted) {
+ ALOGE("%s: physical camera settings metadata is corrupt!", __FUNCTION__);
+ return Status::ILLEGAL_ARGUMENT;
+ }
+ physicalCameraIds.push_back(request.physicalCameraSettings[i].physicalCameraId.c_str());
+ }
+ }
+ halRequest.num_physcam_settings = settingsCount;
+ halRequest.physcam_id = physicalCameraIds.data();
+ halRequest.physcam_settings = physicalCameraSettings.data();
+
+ ATRACE_ASYNC_BEGIN("frame capture", request.v3_2.frameNumber);
ATRACE_BEGIN("camera3->process_capture_request");
status_t ret = mDevice->ops->process_capture_request(mDevice, &halRequest);
ATRACE_END();
@@ -335,17 +376,23 @@
cleanupInflightFences(allFences, numBufs);
if (hasInputBuf) {
- auto key = std::make_pair(request.inputBuffer.streamId, request.frameNumber);
+ auto key = std::make_pair(request.v3_2.inputBuffer.streamId, request.v3_2.frameNumber);
mInflightBuffers.erase(key);
}
for (size_t i = 0; i < numOutputBufs; i++) {
- auto key = std::make_pair(request.outputBuffers[i].streamId, request.frameNumber);
+ auto key = std::make_pair(request.v3_2.outputBuffers[i].streamId,
+ request.v3_2.frameNumber);
mInflightBuffers.erase(key);
}
if (aeCancelTriggerNeeded) {
- mInflightAETriggerOverrides.erase(request.frameNumber);
+ mInflightAETriggerOverrides.erase(request.v3_2.frameNumber);
}
- return Status::INTERNAL_ERROR;
+
+ if (ret == BAD_VALUE) {
+ return Status::ILLEGAL_ARGUMENT;
+ } else {
+ return Status::INTERNAL_ERROR;
+ }
}
mFirstRequest = false;
diff --git a/camera/device/3.4/default/include/device_v3_4_impl/CameraDeviceSession.h b/camera/device/3.4/default/include/device_v3_4_impl/CameraDeviceSession.h
index 83b3afe..fbde083 100644
--- a/camera/device/3.4/default/include/device_v3_4_impl/CameraDeviceSession.h
+++ b/camera/device/3.4/default/include/device_v3_4_impl/CameraDeviceSession.h
@@ -85,10 +85,10 @@
void postProcessConfigurationLocked_3_4(const StreamConfiguration& requestedConfiguration);
Return<void> processCaptureRequest_3_4(
- const hidl_vec<CaptureRequest>& requests,
+ const hidl_vec<V3_4::CaptureRequest>& requests,
const hidl_vec<V3_2::BufferCache>& cachesToRemove,
- ICameraDeviceSession::processCaptureRequest_cb _hidl_cb);
- Status processOneCaptureRequest_3_4(const CaptureRequest& request);
+ ICameraDeviceSession::processCaptureRequest_3_4_cb _hidl_cb);
+ Status processOneCaptureRequest_3_4(const V3_4::CaptureRequest& request);
std::map<int, std::string> mPhysicalCameraIdMap;
private:
@@ -109,10 +109,16 @@
return mParent->configureStreams(requestedConfiguration, _hidl_cb);
}
+ virtual Return<void> processCaptureRequest_3_4(const hidl_vec<V3_4::CaptureRequest>& requests,
+ const hidl_vec<V3_2::BufferCache>& cachesToRemove,
+ ICameraDeviceSession::processCaptureRequest_3_4_cb _hidl_cb) override {
+ return mParent->processCaptureRequest_3_4(requests, cachesToRemove, _hidl_cb);
+ }
+
virtual Return<void> processCaptureRequest(const hidl_vec<V3_2::CaptureRequest>& requests,
const hidl_vec<V3_2::BufferCache>& cachesToRemove,
V3_3::ICameraDeviceSession::processCaptureRequest_cb _hidl_cb) override {
- return mParent->processCaptureRequest_3_4(requests, cachesToRemove, _hidl_cb);
+ return mParent->processCaptureRequest(requests, cachesToRemove, _hidl_cb);
}
virtual Return<void> getCaptureRequestMetadataQueue(
diff --git a/camera/device/3.4/types.hal b/camera/device/3.4/types.hal
index acad093..77e855f 100644
--- a/camera/device/3.4/types.hal
+++ b/camera/device/3.4/types.hal
@@ -21,6 +21,7 @@
import @3.2::Stream;
import @3.3::HalStream;
import @3.2::CameraMetadata;
+import @3.2::CaptureRequest;
/**
* Stream:
@@ -133,3 +134,65 @@
struct HalStreamConfiguration {
vec<HalStream> streams;
};
+
+/**
+ * PhysicalCameraSetting:
+ *
+ * Individual camera settings for logical camera backed by multiple physical devices.
+ * Clients are allowed to pass separate settings for each physical device.
+ */
+struct PhysicalCameraSetting {
+ /**
+ * If non-zero, read settings from request queue instead
+ * (see ICameraDeviceSession.getCaptureRequestMetadataQueue).
+ * If zero, read settings from .settings field.
+ */
+ uint64_t fmqSettingsSize;
+
+ /**
+ * Contains the physical device camera id. Any settings passed by client here
+ * should be applied for this physical device. In case the physical id is invalid
+ * Hal should fail the process request and return Status::ILLEGAL_ARGUMENT.
+ */
+ string physicalCameraId;
+
+ /**
+ * If fmqSettingsSize is zero, the settings buffer contains the capture and
+ * processing parameters for the physical device with id 'phyCamId'.
+ * In case the individual settings are empty or missing, Hal should fail the
+ * request and return Status::ILLEGAL_ARGUMENT.
+ */
+ CameraMetadata settings;
+};
+
+/**
+ * CaptureRequest:
+ *
+ * A single request for image capture/buffer reprocessing, sent to the Camera
+ * HAL device by the framework in processCaptureRequest().
+ *
+ * The request contains the settings to be used for this capture, and the set of
+ * output buffers to write the resulting image data in. It may optionally
+ * contain an input buffer, in which case the request is for reprocessing that
+ * input buffer instead of capturing a new image with the camera sensor. The
+ * capture is identified by the frameNumber.
+ *
+ * In response, the camera HAL device must send a CaptureResult
+ * structure asynchronously to the framework, using the processCaptureResult()
+ * callback.
+ *
+ * Identical to @3.2::CaptureRequest, except that it contains @3.4::physCamSettings vector.
+ *
+ */
+struct CaptureRequest {
+ /**
+ * The definition of CaptureRequest from prior version.
+ */
+ @3.2::CaptureRequest v3_2;
+
+ /**
+ * A vector containing individual camera settings for logical camera backed by multiple physical
+ * devices. In case the vector is empty, Hal should use the settings field in 'v3_2'.
+ */
+ vec<PhysicalCameraSetting> physicalCameraSettings;
+};