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
gugelfrei
Shuzhen Wang 5 years ago
parent a073d2ec84
commit 6c17e2107b

@ -78,7 +78,34 @@ camera_status_t ACameraDevice_createCaptureRequest(
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

@ -97,6 +97,27 @@ camera_status_t ACaptureRequest_getConstEntry(
return req->settings->getConstEntry(tag, entry);
}
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) {
@ -131,6 +152,34 @@ SET_ENTRY(rational,ACameraMetadata_rational)
#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 @@ void ACaptureRequest_free(ACaptureRequest* request) {
return;
}
request->settings.clear();
request->physicalSettings.clear();
delete request->targets;
delete request;
return;
@ -174,6 +224,9 @@ ACaptureRequest* ACaptureRequest_copy(const ACaptureRequest* src) {
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;

@ -76,7 +76,7 @@ CameraDevice::CameraDevice(
__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 @@ CameraDevice::CameraDevice(
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 @@ CameraDevice::postSessionMsgAndCleanup(sp<AMessage>& msg) {
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 @@ CameraDevice::createCaptureRequest(
}
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 @@ CameraDevice::allocateCaptureRequest(
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 @@ CameraDevice::allocateCaptureRequest(
}
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 @@ CameraDevice::freeACaptureRequest(ACaptureRequest* req) {
return;
}
req->settings.clear();
req->physicalSettings.clear();
delete req->targets;
delete req;
}
@ -786,6 +833,9 @@ CameraDevice::onCaptureErrorLocked(
return;
}
CameraDevice::CallbackHandler::CallbackHandler(const char* id) : mId(id) {
}
void CameraDevice::CallbackHandler::onMessageReceived(
const sp<AMessage> &msg) {
switch (msg->what()) {
@ -927,7 +977,7 @@ void CameraDevice::CallbackHandler::onMessageReceived(
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 @@ void CameraDevice::CallbackHandler::onMessageReceived(
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 @@ void CameraDevice::CallbackHandler::onMessageReceived(
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 @@ void CameraDevice::CallbackHandler::onMessageReceived(
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 @@ void CameraDevice::CallbackHandler::onMessageReceived(
return;
}
ACaptureRequest* request = allocateACaptureRequest(requestSp);
ACaptureRequest* request = allocateACaptureRequest(requestSp, mId);
(*onBufferLost)(context, session.get(), request, anw, frameNumber);
freeACaptureRequest(request);
break;

@ -68,6 +68,7 @@ class CameraDevice final : public RefBase {
camera_status_t createCaptureRequest(
ACameraDevice_request_template templateId,
const ACameraIdList* physicalIdList,
ACaptureRequest** request) const;
camera_status_t createCaptureSession(
@ -145,7 +146,8 @@ class CameraDevice final : public RefBase {
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 CameraDevice final : public RefBase {
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 @@ class CameraDevice final : public RefBase {
// 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 @@ struct ACameraDevice {
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(

@ -18,6 +18,7 @@
#include <camera/NdkCaptureRequest.h>
#include <set>
#include <unordered_map>
using namespace android;
@ -59,7 +60,8 @@ struct ACaptureRequest {
return ACAMERA_OK;
}
sp<ACameraMetadata> settings;
sp<ACameraMetadata> settings;
std::unordered_map<std::string, sp<ACameraMetadata>> physicalSettings;
ACameraOutputTargets* targets;
void* context;
};

@ -53,6 +53,17 @@ __BEGIN_DECLS
*/
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 @@ camera_status_t ACaptureSessionPhysicalOutput_create(
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

@ -74,12 +74,6 @@ ACameraManager* ACameraManager_create() __INTRODUCED_IN(24);
*/
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.

@ -3046,6 +3046,28 @@ typedef enum acamera_metadata_tag {
*/
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,
/**

@ -358,6 +358,219 @@ ACaptureRequest* ACaptureRequest_copy(const ACaptureRequest* src) __INTRODUCED_I
#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 */

@ -11,6 +11,7 @@ LIBCAMERA2NDK {
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 @@ LIBCAMERA2NDK {
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;

@ -138,6 +138,7 @@ CameraDevice::postSessionMsgAndCleanup(sp<AMessage>& msg) {
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 @@ CameraDevice::createCaptureRequest(
}
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 @@ camera_status_t
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 @@ CameraDevice::allocateCaptureRequestLocked(
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 @@ void CameraDevice::CallbackHandler::onMessageReceived(
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 @@ void CameraDevice::CallbackHandler::onMessageReceived(
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 @@ void CameraDevice::CallbackHandler::onMessageReceived(
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 @@ void CameraDevice::CallbackHandler::onMessageReceived(
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 @@ void CameraDevice::CallbackHandler::onMessageReceived(
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 @@ void CameraDevice::CallbackHandler::onMessageReceived(
return;
}
ACaptureRequest* request = allocateACaptureRequest(requestSp);
ACaptureRequest* request = allocateACaptureRequest(requestSp, device->getId());
(*onBufferLost)(context, session.get(), request, anw, frameNumber);
freeACaptureRequest(request);
break;

@ -92,6 +92,7 @@ class CameraDevice final : public RefBase {
camera_status_t createCaptureRequest(
ACameraDevice_request_template templateId,
const ACameraIdList* physicalCameraIdList,
ACaptureRequest** request) const;
camera_status_t createCaptureSession(
@ -176,8 +177,11 @@ class CameraDevice final : public RefBase {
// 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 @@ struct ACameraDevice {
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(

@ -61,7 +61,8 @@ class CameraHelper {
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 @@ class CameraHelper {
return ret;
}
std::vector<const char*> idPointerList;
for (auto& physicalStream : physicalImgReaders) {
ACaptureSessionOutput* sessionOutput = nullptr;
ret = ACaptureSessionPhysicalOutput_create(physicalStream.anw,
@ -113,7 +115,11 @@ class CameraHelper {
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 @@ class CameraHelper {
}
// 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 @@ class AImageReaderVendorTest : public ::testing::Test {
}
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 @@ class AImageReaderVendorTest : public ::testing::Test {
*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, CreateWindowNativeHandle) {
}
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

Loading…
Cancel
Save