Camera: Enable physical camera setting in camera ndk/vndk
Port physical camera settings support to ndk/vndk.
Test: Related camera VTS and NDK/VNDK tests pass
Bug: 115532726
Change-Id: Ie2d46b4ec041d2cec3c02145fbf06cf70eec5ac3
diff --git a/camera/ndk/NdkCameraDevice.cpp b/camera/ndk/NdkCameraDevice.cpp
index 98608da..09b85d5 100644
--- a/camera/ndk/NdkCameraDevice.cpp
+++ b/camera/ndk/NdkCameraDevice.cpp
@@ -78,7 +78,34 @@
ALOGE("%s: unknown template ID %d", __FUNCTION__, templateId);
return ACAMERA_ERROR_INVALID_PARAMETER;
}
- return device->createCaptureRequest(templateId, request);
+ return device->createCaptureRequest(templateId, nullptr /*physicalIdList*/, request);
+}
+
+EXPORT
+camera_status_t ACameraDevice_createCaptureRequest_withPhysicalIds(
+ const ACameraDevice* device,
+ ACameraDevice_request_template templateId,
+ const ACameraIdList* physicalCameraIdList,
+ ACaptureRequest** request) {
+ ATRACE_CALL();
+ if (device == nullptr || request == nullptr || physicalCameraIdList == nullptr) {
+ ALOGE("%s: invalid argument! device %p request %p, physicalCameraIdList %p",
+ __FUNCTION__, device, request, physicalCameraIdList);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ switch (templateId) {
+ case TEMPLATE_PREVIEW:
+ case TEMPLATE_STILL_CAPTURE:
+ case TEMPLATE_RECORD:
+ case TEMPLATE_VIDEO_SNAPSHOT:
+ case TEMPLATE_ZERO_SHUTTER_LAG:
+ case TEMPLATE_MANUAL:
+ break;
+ default:
+ ALOGE("%s: unknown template ID %d", __FUNCTION__, templateId);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ return device->createCaptureRequest(templateId, physicalCameraIdList, request);
}
EXPORT
diff --git a/camera/ndk/NdkCaptureRequest.cpp b/camera/ndk/NdkCaptureRequest.cpp
index c64de3e..87de4a9 100644
--- a/camera/ndk/NdkCaptureRequest.cpp
+++ b/camera/ndk/NdkCaptureRequest.cpp
@@ -98,6 +98,27 @@
}
EXPORT
+camera_status_t ACaptureRequest_getConstEntry_physicalCamera(
+ const ACaptureRequest* req, const char* physicalId,
+ uint32_t tag, ACameraMetadata_const_entry* entry) {
+ ATRACE_CALL();
+ if (req == nullptr || entry == nullptr || physicalId == nullptr) {
+ ALOGE("%s: invalid argument! req %p, tag 0x%x, entry %p, physicalId %p",
+ __FUNCTION__, req, tag, entry, physicalId);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+
+ const auto& physicalSettings = req->physicalSettings.find(physicalId);
+ if (physicalSettings == req->physicalSettings.end()) {
+ ALOGE("%s: Failed to find metadata for physical camera id %s",
+ __FUNCTION__, physicalId);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+
+ return physicalSettings->second->getConstEntry(tag, entry);
+}
+
+EXPORT
camera_status_t ACaptureRequest_getAllTags(
const ACaptureRequest* req, /*out*/int32_t* numTags, /*out*/const uint32_t** tags) {
ATRACE_CALL();
@@ -131,6 +152,34 @@
#undef SET_ENTRY
+#define SET_PHYSICAL_ENTRY(NAME,NDK_TYPE) \
+EXPORT \
+camera_status_t ACaptureRequest_setEntry_physicalCamera_##NAME( \
+ ACaptureRequest* req, const char* physicalId, uint32_t tag, \
+ uint32_t count, const NDK_TYPE* data) { \
+ ATRACE_CALL(); \
+ if (req == nullptr || (count > 0 && data == nullptr) || physicalId == nullptr) { \
+ ALOGE("%s: invalid argument! req %p, tag 0x%x, count %d, data 0x%p, physicalId %p", \
+ __FUNCTION__, req, tag, count, data, physicalId); \
+ return ACAMERA_ERROR_INVALID_PARAMETER; \
+ } \
+ if (req->physicalSettings.find(physicalId) == req->physicalSettings.end()) { \
+ ALOGE("%s: Failed to find metadata for physical camera id %s", \
+ __FUNCTION__, physicalId); \
+ return ACAMERA_ERROR_INVALID_PARAMETER; \
+ } \
+ return req->physicalSettings[physicalId]->update(tag, count, data); \
+}
+
+SET_PHYSICAL_ENTRY(u8,uint8_t)
+SET_PHYSICAL_ENTRY(i32,int32_t)
+SET_PHYSICAL_ENTRY(float,float)
+SET_PHYSICAL_ENTRY(double,double)
+SET_PHYSICAL_ENTRY(i64,int64_t)
+SET_PHYSICAL_ENTRY(rational,ACameraMetadata_rational)
+
+#undef SET_PHYSICAL_ENTRY
+
EXPORT
void ACaptureRequest_free(ACaptureRequest* request) {
ATRACE_CALL();
@@ -138,6 +187,7 @@
return;
}
request->settings.clear();
+ request->physicalSettings.clear();
delete request->targets;
delete request;
return;
@@ -174,6 +224,9 @@
ACaptureRequest* pRequest = new ACaptureRequest();
pRequest->settings = new ACameraMetadata(*(src->settings));
+ for (const auto& entry : src->physicalSettings) {
+ pRequest->physicalSettings[entry.first] = new ACameraMetadata(*(entry.second));
+ }
pRequest->targets = new ACameraOutputTargets();
*(pRequest->targets) = *(src->targets);
pRequest->context = src->context;
diff --git a/camera/ndk/impl/ACameraDevice.cpp b/camera/ndk/impl/ACameraDevice.cpp
index d8a5765..5e4fcd0 100644
--- a/camera/ndk/impl/ACameraDevice.cpp
+++ b/camera/ndk/impl/ACameraDevice.cpp
@@ -76,7 +76,7 @@
__FUNCTION__, strerror(-err), err);
setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_DEVICE);
}
- mHandler = new CallbackHandler();
+ mHandler = new CallbackHandler(id);
mCbLooper->registerHandler(mHandler);
const CameraMetadata& metadata = mChars->getInternalData();
@@ -97,6 +97,14 @@
mShadingMapSize[0] = entry.data.i32[0];
mShadingMapSize[1] = entry.data.i32[1];
}
+
+ size_t physicalIdCnt = 0;
+ const char*const* physicalCameraIds;
+ if (mChars->isLogicalMultiCamera(&physicalIdCnt, &physicalCameraIds)) {
+ for (size_t i = 0; i < physicalIdCnt; i++) {
+ mPhysicalIds.push_back(physicalCameraIds[i]);
+ }
+ }
}
// Device close implementaiton
@@ -129,8 +137,29 @@
camera_status_t
CameraDevice::createCaptureRequest(
ACameraDevice_request_template templateId,
+ const ACameraIdList* physicalIdList,
ACaptureRequest** request) const {
Mutex::Autolock _l(mDeviceLock);
+
+ if (physicalIdList != nullptr) {
+ if (physicalIdList->numCameras > static_cast<int>(mPhysicalIds.size())) {
+ ALOGE("%s: physicalIdList size %d exceeds number of available physical cameras %zu",
+ __FUNCTION__, physicalIdList->numCameras, mPhysicalIds.size());
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ for (auto i = 0; i < physicalIdList->numCameras; i++) {
+ if (physicalIdList->cameraIds[i] == nullptr) {
+ ALOGE("%s: physicalId is null!", __FUNCTION__);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ if (mPhysicalIds.end() == std::find(
+ mPhysicalIds.begin(), mPhysicalIds.end(), physicalIdList->cameraIds[i])) {
+ ALOGE("%s: Invalid physicalId %s!", __FUNCTION__, physicalIdList->cameraIds[i]);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ }
+ }
+
camera_status_t ret = checkCameraClosedOrErrorLocked();
if (ret != ACAMERA_OK) {
return ret;
@@ -151,6 +180,12 @@
}
ACaptureRequest* outReq = new ACaptureRequest();
outReq->settings = new ACameraMetadata(rawRequest.release(), ACameraMetadata::ACM_REQUEST);
+ if (physicalIdList != nullptr) {
+ for (auto i = 0; i < physicalIdList->numCameras; i++) {
+ outReq->physicalSettings.emplace(physicalIdList->cameraIds[i],
+ new ACameraMetadata(*(outReq->settings)));
+ }
+ }
outReq->targets = new ACameraOutputTargets();
*request = outReq;
return ACAMERA_OK;
@@ -275,8 +310,12 @@
const ACaptureRequest* request, /*out*/sp<CaptureRequest>& outReq) {
camera_status_t ret;
sp<CaptureRequest> req(new CaptureRequest());
- req->mPhysicalCameraSettings.push_back({std::string(mCameraId.string()),
+ req->mPhysicalCameraSettings.push_back({getId(),
request->settings->getInternalData()});
+ for (auto& entry : request->physicalSettings) {
+ req->mPhysicalCameraSettings.push_back({entry.first,
+ entry.second->getInternalData()});
+ }
req->mIsReprocess = false; // NDK does not support reprocessing yet
req->mContext = request->context;
req->mSurfaceConverted = true; // set to true, and fill in stream/surface idx to speed up IPC
@@ -320,10 +359,17 @@
}
ACaptureRequest*
-CameraDevice::allocateACaptureRequest(sp<CaptureRequest>& req) {
+CameraDevice::allocateACaptureRequest(sp<CaptureRequest>& req, const std::string& deviceId) {
ACaptureRequest* pRequest = new ACaptureRequest();
- CameraMetadata clone = req->mPhysicalCameraSettings.begin()->settings;
- pRequest->settings = new ACameraMetadata(clone.release(), ACameraMetadata::ACM_REQUEST);
+ for (auto& entry : req->mPhysicalCameraSettings) {
+ CameraMetadata clone = entry.settings;
+ if (entry.id == deviceId) {
+ pRequest->settings = new ACameraMetadata(clone.release(), ACameraMetadata::ACM_REQUEST);
+ } else {
+ pRequest->physicalSettings.emplace(entry.id,
+ new ACameraMetadata(clone.release(), ACameraMetadata::ACM_REQUEST));
+ }
+ }
pRequest->targets = new ACameraOutputTargets();
for (size_t i = 0; i < req->mSurfaceList.size(); i++) {
ANativeWindow* anw = static_cast<ANativeWindow*>(req->mSurfaceList[i].get());
@@ -340,6 +386,7 @@
return;
}
req->settings.clear();
+ req->physicalSettings.clear();
delete req->targets;
delete req;
}
@@ -786,6 +833,9 @@
return;
}
+CameraDevice::CallbackHandler::CallbackHandler(const char* id) : mId(id) {
+}
+
void CameraDevice::CallbackHandler::onMessageReceived(
const sp<AMessage> &msg) {
switch (msg->what()) {
@@ -927,7 +977,7 @@
ALOGE("%s: Cannot find timestamp!", __FUNCTION__);
return;
}
- ACaptureRequest* request = allocateACaptureRequest(requestSp);
+ ACaptureRequest* request = allocateACaptureRequest(requestSp, mId);
(*onStart)(context, session.get(), request, timestamp);
freeACaptureRequest(request);
break;
@@ -950,7 +1000,7 @@
return;
}
sp<ACameraMetadata> result(static_cast<ACameraMetadata*>(obj.get()));
- ACaptureRequest* request = allocateACaptureRequest(requestSp);
+ ACaptureRequest* request = allocateACaptureRequest(requestSp, mId);
(*onResult)(context, session.get(), request, result.get());
freeACaptureRequest(request);
break;
@@ -1006,7 +1056,7 @@
physicalMetadataCopyPtrs.push_back(physicalMetadataCopy[i].get());
}
- ACaptureRequest* request = allocateACaptureRequest(requestSp);
+ ACaptureRequest* request = allocateACaptureRequest(requestSp, mId);
(*onResult)(context, session.get(), request, result.get(),
physicalResultInfo.size(), physicalCameraIdPtrs.data(),
physicalMetadataCopyPtrs.data());
@@ -1034,7 +1084,7 @@
static_cast<CameraCaptureFailure*>(obj.get()));
ACameraCaptureFailure* failure =
static_cast<ACameraCaptureFailure*>(failureSp.get());
- ACaptureRequest* request = allocateACaptureRequest(requestSp);
+ ACaptureRequest* request = allocateACaptureRequest(requestSp, mId);
(*onFail)(context, session.get(), request, failure);
freeACaptureRequest(request);
break;
@@ -1111,7 +1161,7 @@
return;
}
- ACaptureRequest* request = allocateACaptureRequest(requestSp);
+ ACaptureRequest* request = allocateACaptureRequest(requestSp, mId);
(*onBufferLost)(context, session.get(), request, anw, frameNumber);
freeACaptureRequest(request);
break;
diff --git a/camera/ndk/impl/ACameraDevice.h b/camera/ndk/impl/ACameraDevice.h
index d0f363b..103efd5 100644
--- a/camera/ndk/impl/ACameraDevice.h
+++ b/camera/ndk/impl/ACameraDevice.h
@@ -68,6 +68,7 @@
camera_status_t createCaptureRequest(
ACameraDevice_request_template templateId,
+ const ACameraIdList* physicalIdList,
ACaptureRequest** request) const;
camera_status_t createCaptureSession(
@@ -145,7 +146,8 @@
camera_status_t allocateCaptureRequest(
const ACaptureRequest* request, sp<CaptureRequest>& outReq);
- static ACaptureRequest* allocateACaptureRequest(sp<CaptureRequest>& req);
+ static ACaptureRequest* allocateACaptureRequest(sp<CaptureRequest>& req,
+ const std::string& deviceId);
static void freeACaptureRequest(ACaptureRequest*);
// only For session to hold device lock
@@ -230,9 +232,11 @@
class CallbackHandler : public AHandler {
public:
+ explicit CallbackHandler(const char* id);
void onMessageReceived(const sp<AMessage> &msg) override;
private:
+ std::string mId;
// This handler will cache all capture session sp until kWhatCleanUpSessions
// is processed. This is used to guarantee the last session reference is always
// being removed in callback thread without holding camera device lock
@@ -327,6 +331,7 @@
// Misc variables
int32_t mShadingMapSize[2]; // const after constructor
int32_t mPartialResultCount; // const after constructor
+ std::vector<std::string> mPhysicalIds; // const after constructor
};
@@ -351,8 +356,9 @@
camera_status_t createCaptureRequest(
ACameraDevice_request_template templateId,
+ const ACameraIdList* physicalCameraIdList,
ACaptureRequest** request) const {
- return mDevice->createCaptureRequest(templateId, request);
+ return mDevice->createCaptureRequest(templateId, physicalCameraIdList, request);
}
camera_status_t createCaptureSession(
diff --git a/camera/ndk/impl/ACaptureRequest.h b/camera/ndk/impl/ACaptureRequest.h
index 5c82ab7..2ffcafe 100644
--- a/camera/ndk/impl/ACaptureRequest.h
+++ b/camera/ndk/impl/ACaptureRequest.h
@@ -18,6 +18,7 @@
#include <camera/NdkCaptureRequest.h>
#include <set>
+#include <unordered_map>
using namespace android;
@@ -59,7 +60,8 @@
return ACAMERA_OK;
}
- sp<ACameraMetadata> settings;
+ sp<ACameraMetadata> settings;
+ std::unordered_map<std::string, sp<ACameraMetadata>> physicalSettings;
ACameraOutputTargets* targets;
void* context;
};
diff --git a/camera/ndk/include/camera/NdkCameraDevice.h b/camera/ndk/include/camera/NdkCameraDevice.h
index 26af4f8..cedf83a 100644
--- a/camera/ndk/include/camera/NdkCameraDevice.h
+++ b/camera/ndk/include/camera/NdkCameraDevice.h
@@ -53,6 +53,17 @@
*/
typedef struct ACameraDevice ACameraDevice;
+/**
+ * Struct to hold list of camera device Ids. This can refer to either the Ids
+ * of connected camera devices returned from {@link ACameraManager_getCameraIdList},
+ * or the physical camera Ids passed into
+ * {@link ACameraDevice_createCaptureRequest_withPhysicalIds}.
+ */
+typedef struct ACameraIdList {
+ int numCameras; ///< Number of camera device Ids
+ const char** cameraIds; ///< list of camera device Ids
+} ACameraIdList;
+
/// Enum for ACameraDevice_ErrorStateCallback error code
enum {
/**
@@ -793,6 +804,47 @@
ACameraWindowType* anw, const char* physicalId,
/*out*/ACaptureSessionOutput** output) __INTRODUCED_IN(29);
+/**
+ * Create a logical multi-camera ACaptureRequest for capturing images, initialized with template
+ * for a target use case, with the ability to specify physical camera settings.
+ *
+ * <p>The settings are chosen to be the best options for this camera device,
+ * so it is not recommended to reuse the same request for a different camera device.</p>
+ *
+ * <p>Note that for all keys in physical camera settings, only the keys
+ * advertised in ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS are
+ * applicable. All other keys are ignored by the camera device.</p>
+ *
+ * @param device the camera device of interest
+ * @param templateId the type of capture request to be created.
+ * See {@link ACameraDevice_request_template}.
+ * @param physicalIdList The list of physical camera Ids that can be used to
+ * customize the request for a specific physical camera.
+ * @param request the output request will be stored here if the method call succeeds.
+ *
+ * @return <ul>
+ * <li>{@link ACAMERA_OK} if the method call succeeds. The created capture request will be
+ * filled in request argument.</li>
+ * <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if device, physicalIdList, or request is
+ * NULL, templateId is undefined or camera device does not support
+ * requested template, or if some Ids in physicalIdList isn't a
+ * valid physical camera backing the current camera device.</li>
+ * <li>{@link ACAMERA_ERROR_CAMERA_DISCONNECTED} if the camera device is closed.</li>
+ * <li>{@link ACAMERA_ERROR_CAMERA_DEVICE} if the camera device encounters fatal error.</li>
+ * <li>{@link ACAMERA_ERROR_CAMERA_SERVICE} if the camera service encounters fatal error.</li>
+ * <li>{@link ACAMERA_ERROR_UNKNOWN} if the method fails for some other reasons.</li></ul>
+ *
+ * @see TEMPLATE_PREVIEW
+ * @see TEMPLATE_RECORD
+ * @see TEMPLATE_STILL_CAPTURE
+ * @see TEMPLATE_VIDEO_SNAPSHOT
+ * @see TEMPLATE_MANUAL
+ */
+camera_status_t ACameraDevice_createCaptureRequest_withPhysicalIds(
+ const ACameraDevice* device, ACameraDevice_request_template templateId,
+ const ACameraIdList* physicalIdList,
+ /*out*/ACaptureRequest** request) __INTRODUCED_IN(29);
+
#endif /* __ANDROID_API__ >= 29 */
__END_DECLS
diff --git a/camera/ndk/include/camera/NdkCameraManager.h b/camera/ndk/include/camera/NdkCameraManager.h
index ea76738..8d05ddb 100644
--- a/camera/ndk/include/camera/NdkCameraManager.h
+++ b/camera/ndk/include/camera/NdkCameraManager.h
@@ -74,12 +74,6 @@
*/
void ACameraManager_delete(ACameraManager* manager) __INTRODUCED_IN(24);
-/// Struct to hold list of camera devices
-typedef struct ACameraIdList {
- int numCameras; ///< Number of connected camera devices
- const char** cameraIds; ///< list of identifier of connected camera devices
-} ACameraIdList;
-
/**
* Create a list of currently connected camera devices, including
* cameras that may be in use by other camera API clients.
diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h
index b200abf..c26ca69 100644
--- a/camera/ndk/include/camera/NdkCameraMetadataTags.h
+++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h
@@ -3046,6 +3046,28 @@
*/
ACAMERA_REQUEST_AVAILABLE_SESSION_KEYS = // int32[n]
ACAMERA_REQUEST_START + 16,
+ /**
+ * <p>A subset of the available request keys that can be overridden for
+ * physical devices backing a logical multi-camera.</p>
+ *
+ * <p>Type: int32[n]</p>
+ *
+ * <p>This tag may appear in:
+ * <ul>
+ * <li>ACameraMetadata from ACameraManager_getCameraCharacteristics</li>
+ * </ul></p>
+ *
+ * <p>This is a subset of ACAMERA_REQUEST_AVAILABLE_REQUEST_KEYS which contains a list
+ * of keys that can be overridden using <a href="https://developer.android.com/reference/CaptureRequest/Builder.html#setPhysicalCameraKey">Builder#setPhysicalCameraKey</a>.
+ * The respective value of such request key can be obtained by calling
+ * <a href="https://developer.android.com/reference/CaptureRequest/Builder.html#getPhysicalCameraKey">Builder#getPhysicalCameraKey</a>. Capture requests that contain
+ * individual physical device requests must be built via
+ * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraDevice.html#createCaptureRequest(int,">Set)</a>.</p>
+ *
+ * @see ACAMERA_REQUEST_AVAILABLE_REQUEST_KEYS
+ */
+ ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS = // int32[n]
+ ACAMERA_REQUEST_START + 17,
ACAMERA_REQUEST_END,
/**
diff --git a/camera/ndk/include/camera/NdkCaptureRequest.h b/camera/ndk/include/camera/NdkCaptureRequest.h
index 136989a..d3f8826 100644
--- a/camera/ndk/include/camera/NdkCaptureRequest.h
+++ b/camera/ndk/include/camera/NdkCaptureRequest.h
@@ -358,6 +358,219 @@
#endif /* __ANDROID_API__ >= 28 */
+#if __ANDROID_API__ >= 29
+
+/**
+ * Get a metadata entry from input {@link ACaptureRequest} for
+ * a physical camera backing a logical multi-camera device.
+ *
+ * <p>Same as ACaptureRequest_getConstEntry, except that if the key is contained
+ * in {@link ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS}, this function
+ * returns the entry set by ACaptureRequest_setEntry_physicalCamera_* class of
+ * functions on the particular physical camera.</p>
+ *
+ * @param request the {@link ACaptureRequest} of interest created by
+ * {@link ACameraDevice_createCaptureRequest_withPhysicalIds}.
+ * @param physicalId one of the physical Ids used when request is created with
+ * {@link ACameraDevice_createCaptureRequest_withPhysicalIds}.
+ * @param tag the capture request metadata tag in
+ * {@link ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS}
+ * that is set by ACaptureRequest_setEntry_physicalCamera_* class of functions.
+ *
+ * @return <ul>
+ * <li>{@link ACAMERA_OK} if the method call succeeds.</li>
+ * <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if metadata, physicalId, or entry is NULL,
+ * physicalId is not one of the Ids used in creating the request, or if the capture
+ * request is a regular request with no physical Ids at all.</li>
+ * <li>{@link ACAMERA_ERROR_METADATA_NOT_FOUND} if the capture request does not contain an
+ * entry of input tag value.</li></ul>
+ */
+camera_status_t ACaptureRequest_getConstEntry_physicalCamera(
+ const ACaptureRequest* request, const char* physicalId, uint32_t tag,
+ ACameraMetadata_const_entry* entry) __INTRODUCED_IN(29);
+
+/**
+ * Set/change a camera capture control entry with unsigned 8 bits data type for
+ * a physical camera backing a logical multi-camera device.
+ *
+ * <p>Same as ACaptureRequest_setEntry_u8, except that if {@link tag} is contained
+ * in {@link ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS}, this function
+ * sets the entry for a particular physical sub-camera backing the logical multi-camera.
+ * If {@link tag} is not contained in
+ * {@link ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS}, the key will be ignored
+ * by the camera device.</p>
+ *
+ * @param request the {@link ACaptureRequest} of interest created by
+ * {@link ACameraDevice_createCaptureRequest_withPhysicalIds}.
+ * @param physicalId one of the physical Ids used when request is created with
+ * {@link ACameraDevice_createCaptureRequest_withPhysicalIds}.
+ * @param tag one of the capture request metadata tags in
+ * {@link ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS}.
+ *
+ * @return <ul>
+ * <li>{@link ACAMERA_OK} if the method call succeeds.</li>
+ * <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if request or physicalId is NULL, count is
+ * larger than zero while data is NULL, the data type of the tag is not unsigned 8 bits,
+ * the tag is not controllable by application, physicalId is not one of the Ids used
+ * in creating the request, or if the capture request is a regular request with no
+ * physical Ids at all.</li></ul>
+ */
+camera_status_t ACaptureRequest_setEntry_physicalCamera_u8(
+ ACaptureRequest* request, const char* physicalId, uint32_t tag,
+ uint32_t count, const uint8_t* data) __INTRODUCED_IN(29);
+
+/**
+ * Set/change a camera capture control entry with signed 32 bits data type for
+ * a physical camera of a logical multi-camera device.
+ *
+ * <p>Same as ACaptureRequest_setEntry_i32, except that if {@link tag} is contained
+ * in {@link ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS}, this function
+ * sets the entry for a particular physical sub-camera backing the logical multi-camera.
+ * If {@link tag} is not contained in
+ * {@link ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS}, the key will be ignored
+ * by the camera device.</p>
+ *
+ * @param request the {@link ACaptureRequest} of interest created by
+ * {@link ACameraDevice_createCaptureRequest_withPhysicalIds}.
+ * @param physicalId one of the physical Ids used when request is created with
+ * {@link ACameraDevice_createCaptureRequest_withPhysicalIds}.
+ * @param tag one of the capture request metadata tags in
+ * {@link ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS}.
+ *
+ * @return <ul>
+ * <li>{@link ACAMERA_OK} if the method call succeeds.</li>
+ * <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if request or physicalId is NULL, count is
+ * larger than zero while data is NULL, the data type of the tag is not signed 32 bits,
+ * the tag is not controllable by application, physicalId is not one of the Ids used
+ * in creating the request, or if the capture request is a regular request with no
+ * physical Ids at all.</li></ul>
+ */
+camera_status_t ACaptureRequest_setEntry_physicalCamera_i32(
+ ACaptureRequest* request, const char* physicalId, uint32_t tag,
+ uint32_t count, const int32_t* data) __INTRODUCED_IN(29);
+
+/**
+ * Set/change a camera capture control entry with float data type for
+ * a physical camera of a logical multi-camera device.
+ *
+ * <p>Same as ACaptureRequest_setEntry_float, except that if {@link tag} is contained
+ * in {@link ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS}, this function
+ * sets the entry for a particular physical sub-camera backing the logical multi-camera.
+ * If {@link tag} is not contained in
+ * {@link ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS}, the key will be ignored
+ * by the camera device.</p>
+ *
+ * @param request the {@link ACaptureRequest} of interest created by
+ * {@link ACameraDevice_createCaptureRequest_withPhysicalIds}.
+ * @param physicalId one of the physical Ids used when request is created with
+ * {@link ACameraDevice_createCaptureRequest_withPhysicalIds}.
+ * @param tag one of the capture request metadata tags in
+ * {@link ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS}.
+ *
+ * @return <ul>
+ * <li>{@link ACAMERA_OK} if the method call succeeds.</li>
+ * <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if request or physicalId is NULL, count is
+ * larger than zero while data is NULL, the data type of the tag is not float,
+ * the tag is not controllable by application, physicalId is not one of the Ids used
+ * in creating the request, or if the capture request is a regular request with no
+ * physical Ids at all.</li></ul>
+ */
+camera_status_t ACaptureRequest_setEntry_physicalCamera_float(
+ ACaptureRequest* request, const char* physicalId, uint32_t tag,
+ uint32_t count, const float* data) __INTRODUCED_IN(29);
+
+/**
+ * Set/change a camera capture control entry with signed 64 bits data type for
+ * a physical camera of a logical multi-camera device.
+ *
+ * <p>Same as ACaptureRequest_setEntry_i64, except that if {@link tag} is contained
+ * in {@link ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS}, this function
+ * sets the entry for a particular physical sub-camera backing the logical multi-camera.
+ * If {@link tag} is not contained in
+ * {@link ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS}, the key will be ignored
+ * by the camera device.</p>
+ *
+ * @param request the {@link ACaptureRequest} of interest created by
+ * {@link ACameraDevice_createCaptureRequest_withPhysicalIds}.
+ * @param physicalId one of the physical Ids used when request is created with
+ * {@link ACameraDevice_createCaptureRequest_withPhysicalIds}.
+ * @param tag one of the capture request metadata tags in
+ * {@link ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS}.
+ *
+ * @return <ul>
+ * <li>{@link ACAMERA_OK} if the method call succeeds.</li>
+ * <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if request or physicalId is NULL, count is
+ * larger than zero while data is NULL, the data type of the tag is not signed 64 bits,
+ * the tag is not controllable by application, physicalId is not one of the Ids used
+ * in creating the request, or if the capture request is a regular request with no
+ * physical Ids at all.</li></ul>
+ */
+camera_status_t ACaptureRequest_setEntry_physicalCamera_i64(
+ ACaptureRequest* request, const char* physicalId, uint32_t tag,
+ uint32_t count, const int64_t* data) __INTRODUCED_IN(29);
+
+/**
+ * Set/change a camera capture control entry with double data type for
+ * a physical camera of a logical multi-camera device.
+ *
+ * <p>Same as ACaptureRequest_setEntry_double, except that if {@link tag} is contained
+ * in {@link ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS}, this function
+ * sets the entry for a particular physical sub-camera backing the logical multi-camera.
+ * If {@link tag} is not contained in
+ * {@link ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS}, the key will be ignored
+ * by the camera device.</p>
+ *
+ * @param request the {@link ACaptureRequest} of interest created by
+ * {@link ACameraDevice_createCaptureRequest_withPhysicalIds}.
+ * @param physicalId one of the physical Ids used when request is created with
+ * {@link ACameraDevice_createCaptureRequest_withPhysicalIds}.
+ * @param tag one of the capture request metadata tags in
+ * {@link ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS}.
+ *
+ * @return <ul>
+ * <li>{@link ACAMERA_OK} if the method call succeeds.</li>
+ * <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if request or physicalId is NULL, count is
+ * larger than zero while data is NULL, the data type of the tag is not double,
+ * the tag is not controllable by application, physicalId is not one of the Ids used
+ * in creating the request, or if the capture request is a regular request with no
+ * physical Ids at all.</li></ul>
+ */
+camera_status_t ACaptureRequest_setEntry_physicalCamera_double(
+ ACaptureRequest* request, const char* physicalId, uint32_t tag,
+ uint32_t count, const double* data) __INTRODUCED_IN(29);
+
+/**
+ * Set/change a camera capture control entry with rational data type for
+ * a physical camera of a logical multi-camera device.
+ *
+ * <p>Same as ACaptureRequest_setEntry_rational, except that if {@link tag} is contained
+ * in {@link ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS}, this function
+ * sets the entry for a particular physical sub-camera backing the logical multi-camera.
+ * If {@link tag} is not contained in
+ * {@link ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS}, the key will be ignored
+ * by the camera device.</p>
+ *
+ * @param request the {@link ACaptureRequest} of interest created by
+ * {@link ACameraDevice_createCaptureRequest_withPhysicalIds}.
+ * @param physicalId one of the physical Ids used when request is created with
+ * {@link ACameraDevice_createCaptureRequest_withPhysicalIds}.
+ * @param tag one of the capture request metadata tags in
+ * {@link ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS}.
+ *
+ * @return <ul>
+ * <li>{@link ACAMERA_OK} if the method call succeeds.</li>
+ * <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if request or physicalId is NULL, count is
+ * larger than zero while data is NULL, the data type of the tag is not rational,
+ * the tag is not controllable by application, physicalId is not one of the Ids used
+ * in creating the request, or if the capture request is a regular request with no
+ * physical Ids at all.</li></ul>
+ */
+camera_status_t ACaptureRequest_setEntry_physicalCamera_rational(
+ ACaptureRequest* request, const char* physicalId, uint32_t tag,
+ uint32_t count, const ACameraMetadata_rational* data) __INTRODUCED_IN(29);
+
+#endif /* __ANDROID_API__ >= 29 */
+
__END_DECLS
#endif /* _NDK_CAPTURE_REQUEST_H */
diff --git a/camera/ndk/libcamera2ndk.map.txt b/camera/ndk/libcamera2ndk.map.txt
index 5a00022..2441830 100644
--- a/camera/ndk/libcamera2ndk.map.txt
+++ b/camera/ndk/libcamera2ndk.map.txt
@@ -11,6 +11,7 @@
ACameraCaptureSession_updateSharedOutput; # introduced=28
ACameraDevice_close;
ACameraDevice_createCaptureRequest;
+ ACameraDevice_createCaptureRequest_withPhysicalIds; # introduced=29
ACameraDevice_createCaptureSession;
ACameraDevice_createCaptureSessionWithSessionParameters; # introduced=28
ACameraDevice_getId;
@@ -34,14 +35,21 @@
ACaptureRequest_free;
ACaptureRequest_getAllTags;
ACaptureRequest_getConstEntry;
+ ACaptureRequest_getConstEntry_physicalCamera; # introduced=29
ACaptureRequest_getUserContext; # introduced=28
ACaptureRequest_removeTarget;
ACaptureRequest_setEntry_double;
+ ACaptureRequest_setEntry_physicalCamera_double; # introduced=29
ACaptureRequest_setEntry_float;
+ ACaptureRequest_setEntry_physicalCamera_float; # introduced=29
ACaptureRequest_setEntry_i32;
+ ACaptureRequest_setEntry_physicalCamera_i32; # introduced=29
ACaptureRequest_setEntry_i64;
+ ACaptureRequest_setEntry_physicalCamera_i64; # introduced=29
ACaptureRequest_setEntry_rational;
+ ACaptureRequest_setEntry_physicalCamera_rational; # introduced=29
ACaptureRequest_setEntry_u8;
+ ACaptureRequest_setEntry_physicalCamera_u8; # introduced=29
ACaptureRequest_setUserContext; # introduced=28
ACaptureSessionOutputContainer_add;
ACaptureSessionOutputContainer_create;
diff --git a/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp b/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp
index 9aafcd3..a38a31e 100644
--- a/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp
+++ b/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp
@@ -138,6 +138,7 @@
camera_status_t
CameraDevice::createCaptureRequest(
ACameraDevice_request_template templateId,
+ const ACameraIdList* physicalCameraIdList,
ACaptureRequest** request) const {
Mutex::Autolock _l(mDeviceLock);
camera_status_t ret = checkCameraClosedOrErrorLocked();
@@ -168,6 +169,12 @@
}
ACaptureRequest* outReq = new ACaptureRequest();
outReq->settings = new ACameraMetadata(rawRequest.release(), ACameraMetadata::ACM_REQUEST);
+ if (physicalCameraIdList != nullptr) {
+ for (auto i = 0; i < physicalCameraIdList->numCameras; i++) {
+ outReq->physicalSettings.emplace(physicalCameraIdList->cameraIds[i],
+ new ACameraMetadata(*(outReq->settings)));
+ }
+ }
outReq->targets = new ACameraOutputTargets();
*request = outReq;
return ACAMERA_OK;
@@ -292,29 +299,16 @@
CameraDevice::allocateCaptureRequestLocked(
const ACaptureRequest* request, /*out*/sp<CaptureRequest> &outReq) {
sp<CaptureRequest> req(new CaptureRequest());
- req->mCaptureRequest.physicalCameraSettings.resize(1);
- req->mCaptureRequest.physicalCameraSettings[0].id = mCameraId;
- // TODO: Do we really need to copy the metadata here ?
- CameraMetadata metadataCopy = request->settings->getInternalData();
- const camera_metadata_t *cameraMetadata = metadataCopy.getAndLock();
- HCameraMetadata hCameraMetadata;
- utils::convertToHidl(cameraMetadata, &hCameraMetadata);
- metadataCopy.unlock(cameraMetadata);
- if (request->settings != nullptr) {
- if (hCameraMetadata.data() != nullptr &&
- mCaptureRequestMetadataQueue != nullptr &&
- mCaptureRequestMetadataQueue->write(
- reinterpret_cast<const uint8_t *>(hCameraMetadata.data()),
- hCameraMetadata.size())) {
- // The metadata field of the union would've been destructued, so no need
- // to re-size it.
- req->mCaptureRequest.physicalCameraSettings[0].settings.fmqMetadataSize(
- hCameraMetadata.size());
- } else {
- ALOGE("Fmq write capture result failed, falling back to hwbinder");
- req->mCaptureRequest.physicalCameraSettings[0].settings.metadata(
- std::move(hCameraMetadata));
- }
+ req->mCaptureRequest.physicalCameraSettings.resize(1 + request->physicalSettings.size());
+
+ size_t index = 0;
+ allocateOneCaptureRequestMetadata(
+ req->mCaptureRequest.physicalCameraSettings[index++], mCameraId, request->settings);
+
+ for (auto& physicalEntry : request->physicalSettings) {
+ allocateOneCaptureRequestMetadata(
+ req->mCaptureRequest.physicalCameraSettings[index++],
+ physicalEntry.first, physicalEntry.second);
}
std::vector<int32_t> requestStreamIdxList;
@@ -356,13 +350,48 @@
return ACAMERA_OK;
}
+void CameraDevice::allocateOneCaptureRequestMetadata(
+ PhysicalCameraSettings& cameraSettings,
+ const std::string& id, const sp<ACameraMetadata>& metadata) {
+ cameraSettings.id = id;
+ // TODO: Do we really need to copy the metadata here ?
+ CameraMetadata metadataCopy = metadata->getInternalData();
+ const camera_metadata_t *cameraMetadata = metadataCopy.getAndLock();
+ HCameraMetadata hCameraMetadata;
+ utils::convertToHidl(cameraMetadata, &hCameraMetadata);
+ metadataCopy.unlock(cameraMetadata);
+ if (metadata != nullptr) {
+ if (hCameraMetadata.data() != nullptr &&
+ mCaptureRequestMetadataQueue != nullptr &&
+ mCaptureRequestMetadataQueue->write(
+ reinterpret_cast<const uint8_t *>(hCameraMetadata.data()),
+ hCameraMetadata.size())) {
+ // The metadata field of the union would've been destructued, so no need
+ // to re-size it.
+ cameraSettings.settings.fmqMetadataSize(hCameraMetadata.size());
+ } else {
+ ALOGE("Fmq write capture result failed, falling back to hwbinder");
+ cameraSettings.settings.metadata(std::move(hCameraMetadata));
+ }
+ }
+}
+
+
ACaptureRequest*
-CameraDevice::allocateACaptureRequest(sp<CaptureRequest>& req) {
+CameraDevice::allocateACaptureRequest(sp<CaptureRequest>& req, const char* deviceId) {
ACaptureRequest* pRequest = new ACaptureRequest();
- CameraMetadata clone;
- utils::convertFromHidlCloned(req->mPhysicalCameraSettings[0].settings.metadata(), &clone);
- pRequest->settings = new ACameraMetadata(clone.release(), ACameraMetadata::ACM_REQUEST);
- pRequest->targets = new ACameraOutputTargets();
+ for (size_t i = 0; i < req->mPhysicalCameraSettings.size(); i++) {
+ const std::string& id = req->mPhysicalCameraSettings[i].id;
+ CameraMetadata clone;
+ utils::convertFromHidlCloned(req->mPhysicalCameraSettings[i].settings.metadata(), &clone);
+ if (id == deviceId) {
+ pRequest->settings = new ACameraMetadata(clone.release(), ACameraMetadata::ACM_REQUEST);
+ } else {
+ pRequest->physicalSettings[req->mPhysicalCameraSettings[i].id] =
+ new ACameraMetadata(clone.release(), ACameraMetadata::ACM_REQUEST);
+ }
+ }
+ pRequest->targets = new ACameraOutputTargets();
for (size_t i = 0; i < req->mSurfaceList.size(); i++) {
native_handle_t* anw = req->mSurfaceList[i];
ACameraOutputTarget outputTarget(anw);
@@ -930,6 +959,7 @@
return;
}
sp<ACameraCaptureSession> session(static_cast<ACameraCaptureSession*>(obj.get()));
+ ACameraDevice* device = session->getDevice();
mCachedSessions.push(session);
sp<CaptureRequest> requestSp = nullptr;
switch (msg->what()) {
@@ -979,7 +1009,7 @@
ALOGE("%s: Cannot find timestamp!", __FUNCTION__);
return;
}
- ACaptureRequest* request = allocateACaptureRequest(requestSp);
+ ACaptureRequest* request = allocateACaptureRequest(requestSp, device->getId());
(*onStart)(context, session.get(), request, timestamp);
freeACaptureRequest(request);
break;
@@ -1002,7 +1032,7 @@
return;
}
sp<ACameraMetadata> result(static_cast<ACameraMetadata*>(obj.get()));
- ACaptureRequest* request = allocateACaptureRequest(requestSp);
+ ACaptureRequest* request = allocateACaptureRequest(requestSp, device->getId());
(*onResult)(context, session.get(), request, result.get());
freeACaptureRequest(request);
break;
@@ -1055,7 +1085,7 @@
physicalMetadataCopyPtrs.push_back(physicalMetadataCopy[i].get());
}
- ACaptureRequest* request = allocateACaptureRequest(requestSp);
+ ACaptureRequest* request = allocateACaptureRequest(requestSp, device->getId());
(*onResult)(context, session.get(), request, result.get(),
physicalResultInfo.size(), physicalCameraIdPtrs.data(),
physicalMetadataCopyPtrs.data());
@@ -1084,7 +1114,7 @@
static_cast<CameraCaptureFailure*>(obj.get()));
ACameraCaptureFailure* failure =
static_cast<ACameraCaptureFailure*>(failureSp.get());
- ACaptureRequest* request = allocateACaptureRequest(requestSp);
+ ACaptureRequest* request = allocateACaptureRequest(requestSp, device->getId());
(*onFail)(context, session.get(), request, failure);
freeACaptureRequest(request);
break;
@@ -1161,7 +1191,7 @@
return;
}
- ACaptureRequest* request = allocateACaptureRequest(requestSp);
+ ACaptureRequest* request = allocateACaptureRequest(requestSp, device->getId());
(*onBufferLost)(context, session.get(), request, anw, frameNumber);
freeACaptureRequest(request);
break;
diff --git a/camera/ndk/ndk_vendor/impl/ACameraDevice.h b/camera/ndk/ndk_vendor/impl/ACameraDevice.h
index d571585..28092fd 100644
--- a/camera/ndk/ndk_vendor/impl/ACameraDevice.h
+++ b/camera/ndk/ndk_vendor/impl/ACameraDevice.h
@@ -92,6 +92,7 @@
camera_status_t createCaptureRequest(
ACameraDevice_request_template templateId,
+ const ACameraIdList* physicalCameraIdList,
ACaptureRequest** request) const;
camera_status_t createCaptureSession(
@@ -176,8 +177,11 @@
// metadata associated with it.
camera_status_t allocateCaptureRequestLocked(
const ACaptureRequest* request, sp<CaptureRequest>& outReq);
+ void allocateOneCaptureRequestMetadata(
+ PhysicalCameraSettings& cameraSettings,
+ const std::string& id, const sp<ACameraMetadata>& metadata);
- static ACaptureRequest* allocateACaptureRequest(sp<CaptureRequest>& req);
+ static ACaptureRequest* allocateACaptureRequest(sp<CaptureRequest>& req, const char* deviceId);
static void freeACaptureRequest(ACaptureRequest*);
// only For session to hold device lock
@@ -380,8 +384,9 @@
camera_status_t createCaptureRequest(
ACameraDevice_request_template templateId,
+ const ACameraIdList* physicalCameraIdList,
ACaptureRequest** request) const {
- return mDevice->createCaptureRequest(templateId, request);
+ return mDevice->createCaptureRequest(templateId, physicalCameraIdList, request);
}
camera_status_t createCaptureSession(
diff --git a/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp b/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp
index 93108b0..2398922 100644
--- a/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp
+++ b/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp
@@ -61,7 +61,8 @@
native_handle_t* anw;
};
int initCamera(native_handle_t* imgReaderAnw,
- const std::vector<PhysicalImgReaderInfo>& physicalImgReaders) {
+ const std::vector<PhysicalImgReaderInfo>& physicalImgReaders,
+ bool usePhysicalSettings) {
if (imgReaderAnw == nullptr) {
ALOGE("Cannot initialize camera before image reader get initialized.");
return -1;
@@ -97,6 +98,7 @@
return ret;
}
+ std::vector<const char*> idPointerList;
for (auto& physicalStream : physicalImgReaders) {
ACaptureSessionOutput* sessionOutput = nullptr;
ret = ACaptureSessionPhysicalOutput_create(physicalStream.anw,
@@ -113,7 +115,11 @@
mExtraOutputs.push_back(sessionOutput);
// Assume that at most one physical stream per physical camera.
mPhysicalCameraIds.push_back(physicalStream.physicalCameraId);
+ idPointerList.push_back(physicalStream.physicalCameraId);
}
+ ACameraIdList cameraIdList;
+ cameraIdList.numCameras = idPointerList.size();
+ cameraIdList.cameraIds = idPointerList.data();
ret = ACameraDevice_createCaptureSession(mDevice, mOutputs, &mSessionCb, &mSession);
if (ret != AMEDIA_OK) {
@@ -122,7 +128,13 @@
}
// Create capture request
- ret = ACameraDevice_createCaptureRequest(mDevice, TEMPLATE_STILL_CAPTURE, &mStillRequest);
+ if (usePhysicalSettings) {
+ ret = ACameraDevice_createCaptureRequest_withPhysicalIds(mDevice,
+ TEMPLATE_STILL_CAPTURE, &cameraIdList, &mStillRequest);
+ } else {
+ ret = ACameraDevice_createCaptureRequest(mDevice,
+ TEMPLATE_STILL_CAPTURE, &mStillRequest);
+ }
if (ret != AMEDIA_OK) {
ALOGE("ACameraDevice_createCaptureRequest failed, ret=%d", ret);
return ret;
@@ -557,7 +569,8 @@
}
CameraHelper cameraHelper(id, mCameraManager);
- ret = cameraHelper.initCamera(testCase.getNativeWindow(), {});
+ ret = cameraHelper.initCamera(testCase.getNativeWindow(),
+ {}/*physicalImageReaders*/, false/*usePhysicalSettings*/);
if (ret < 0) {
ALOGE("Unable to initialize camera helper");
return false;
@@ -695,6 +708,69 @@
*cameraId = nullptr;
return;
}
+
+ void testLogicalCameraPhysicalStream(bool usePhysicalSettings) {
+ const char* cameraId = nullptr;
+ ACameraMetadata* staticMetadata = nullptr;
+ std::vector<const char*> physicalCameraIds;
+
+ findCandidateLogicalCamera(&cameraId, &staticMetadata, &physicalCameraIds);
+ if (cameraId == nullptr) {
+ // Couldn't find logical camera to test
+ return;
+ }
+
+ // Test streaming the logical multi-camera
+ uint64_t readerUsage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN;
+ int32_t readerMaxImages = 8;
+ bool readerAsync = false;
+ const int pictureCount = 6;
+ std::vector<ImageReaderTestCase*> testCases;
+ for (size_t i = 0; i < 3; i++) {
+ ImageReaderTestCase* testCase = new ImageReaderTestCase(
+ kTestImageWidth, kTestImageHeight, kTestImageFormat, readerUsage,
+ readerMaxImages, readerAsync);
+ ASSERT_EQ(testCase->initImageReader(), 0);
+ testCases.push_back(testCase);
+ }
+
+ CameraHelper cameraHelper(cameraId, mCameraManager);
+ std::vector<CameraHelper::PhysicalImgReaderInfo> physicalImgReaderInfo;
+ physicalImgReaderInfo.push_back({physicalCameraIds[0], testCases[1]->getNativeWindow()});
+ physicalImgReaderInfo.push_back({physicalCameraIds[1], testCases[2]->getNativeWindow()});
+
+ int ret = cameraHelper.initCamera(testCases[0]->getNativeWindow(),
+ physicalImgReaderInfo, usePhysicalSettings);
+ ASSERT_EQ(ret, 0);
+
+ if (!cameraHelper.isCameraReady()) {
+ ALOGW("Camera is not ready after successful initialization. It's either due to camera "
+ "on board lacks BACKWARDS_COMPATIBLE capability or the device does not have "
+ "camera on board.");
+ return;
+ }
+
+ for (int i = 0; i < pictureCount; i++) {
+ ret = cameraHelper.takeLogicalCameraPicture();
+ ASSERT_EQ(ret, 0);
+ }
+
+ // Sleep until all capture finished
+ for (int i = 0; i < kCaptureWaitRetry * pictureCount; i++) {
+ usleep(kCaptureWaitUs);
+ if (testCases[0]->getAcquiredImageCount() == pictureCount) {
+ ALOGI("Session take ~%d ms to capture %d images", i * kCaptureWaitUs / 1000,
+ pictureCount);
+ break;
+ }
+ }
+ ASSERT_EQ(testCases[0]->getAcquiredImageCount(), pictureCount);
+ ASSERT_EQ(testCases[1]->getAcquiredImageCount(), pictureCount);
+ ASSERT_EQ(testCases[2]->getAcquiredImageCount(), pictureCount);
+ ASSERT_TRUE(cameraHelper.checkCallbacks(pictureCount));
+
+ ACameraMetadata_free(staticMetadata);
+ }
};
TEST_F(AImageReaderVendorTest, CreateWindowNativeHandle) {
@@ -722,65 +798,8 @@
}
TEST_F(AImageReaderVendorTest, LogicalCameraPhysicalStream) {
- const char* cameraId = nullptr;
- ACameraMetadata* staticMetadata = nullptr;
- std::vector<const char*> physicalCameraIds;
-
- findCandidateLogicalCamera(&cameraId, &staticMetadata, &physicalCameraIds);
- if (cameraId == nullptr) {
- // Couldn't find logical camera to test
- return;
- }
-
- // Test streaming the logical multi-camera
- uint64_t readerUsage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN;
- int32_t readerMaxImages = 8;
- bool readerAsync = false;
- const int pictureCount = 6;
- std::vector<ImageReaderTestCase*> testCases;
- for (size_t i = 0; i < 3; i++) {
- ImageReaderTestCase* testCase = new ImageReaderTestCase(
- kTestImageWidth, kTestImageHeight, kTestImageFormat, readerUsage, readerMaxImages,
- readerAsync);
- ASSERT_EQ(testCase->initImageReader(), 0);
- testCases.push_back(testCase);
- }
-
- CameraHelper cameraHelper(cameraId, mCameraManager);
- std::vector<CameraHelper::PhysicalImgReaderInfo> physicalImgReaderInfo;
- physicalImgReaderInfo.push_back({physicalCameraIds[0], testCases[1]->getNativeWindow()});
- physicalImgReaderInfo.push_back({physicalCameraIds[1], testCases[2]->getNativeWindow()});
-
- int ret = cameraHelper.initCamera(testCases[0]->getNativeWindow(), physicalImgReaderInfo);
- ASSERT_EQ(ret, 0);
-
- if (!cameraHelper.isCameraReady()) {
- ALOGW("Camera is not ready after successful initialization. It's either due to camera on "
- "board lacks BACKWARDS_COMPATIBLE capability or the device does not have camera on "
- "board.");
- return;
- }
-
- for (int i = 0; i < pictureCount; i++) {
- ret = cameraHelper.takeLogicalCameraPicture();
- ASSERT_EQ(ret, 0);
- }
-
- // Sleep until all capture finished
- for (int i = 0; i < kCaptureWaitRetry * pictureCount; i++) {
- usleep(kCaptureWaitUs);
- if (testCases[0]->getAcquiredImageCount() == pictureCount) {
- ALOGI("Session take ~%d ms to capture %d images", i * kCaptureWaitUs / 1000,
- pictureCount);
- break;
- }
- }
- ASSERT_EQ(testCases[0]->getAcquiredImageCount(), pictureCount);
- ASSERT_EQ(testCases[1]->getAcquiredImageCount(), pictureCount);
- ASSERT_EQ(testCases[2]->getAcquiredImageCount(), pictureCount);
- ASSERT_TRUE(cameraHelper.checkCallbacks(pictureCount));
-
- ACameraMetadata_free(staticMetadata);
+ testLogicalCameraPhysicalStream(false/*usePhysicalSettings*/);
+ testLogicalCameraPhysicalStream(true/*usePhysicalSettings*/);
}
} // namespace