From 0ff9ae3ecbb421551d5de9701a349d8a3741f965 Mon Sep 17 00:00:00 2001 From: Shuzhen Wang Date: Wed, 5 Dec 2018 18:06:12 -0800 Subject: [PATCH] Camera: Enable logical multi-camera API in NDK The support inclues: - Physical camera specific stream support, - Physical camera result metadata, and Test: Newly added NDK CTS test pass Test: Newly added VNDK test pass Bug: 120566141 Bug: 115532726 Change-Id: I939b81522ca6c518c0e54ded5d3615f9973a6a65 --- camera/camera2/OutputConfiguration.cpp | 8 +- .../camera/camera2/OutputConfiguration.h | 4 +- camera/ndk/NdkCameraCaptureSession.cpp | 50 ++- camera/ndk/NdkCameraDevice.cpp | 14 + camera/ndk/NdkCameraMetadata.cpp | 17 + camera/ndk/impl/ACameraCaptureSession.cpp | 41 --- camera/ndk/impl/ACameraCaptureSession.h | 13 +- camera/ndk/impl/ACameraCaptureSession.inc | 68 ++++ camera/ndk/impl/ACameraDevice.cpp | 251 +++++++------- camera/ndk/impl/ACameraDevice.h | 63 +++- camera/ndk/impl/ACameraDevice.inc | 130 +++++++ camera/ndk/impl/ACameraMetadata.cpp | 52 +++ camera/ndk/impl/ACameraMetadata.h | 5 + .../include/camera/NdkCameraCaptureSession.h | 97 ++++++ camera/ndk/include/camera/NdkCameraDevice.h | 30 ++ camera/ndk/include/camera/NdkCameraMetadata.h | 22 ++ .../include/camera/NdkCameraMetadataTags.h | 19 + camera/ndk/libcamera2ndk.map.txt | 4 + .../impl/ACameraCaptureSessionVendor.h | 7 +- camera/ndk/ndk_vendor/impl/ACameraDevice.cpp | 325 +++++++++--------- camera/ndk/ndk_vendor/impl/ACameraDevice.h | 74 +++- .../ndk_vendor/impl/ACameraDeviceVendor.inc | 152 ++++++++ camera/tests/CameraBinderTests.cpp | 3 +- .../hidl/AidlCameraDeviceCallbacks.cpp | 8 +- .../camera/libcameraservice/hidl/Convert.cpp | 3 +- 25 files changed, 1094 insertions(+), 366 deletions(-) create mode 100644 camera/ndk/impl/ACameraCaptureSession.inc create mode 100644 camera/ndk/impl/ACameraDevice.inc create mode 100644 camera/ndk/ndk_vendor/impl/ACameraDeviceVendor.inc diff --git a/camera/camera2/OutputConfiguration.cpp b/camera/camera2/OutputConfiguration.cpp index 321eb08bea..4e9b27d50d 100644 --- a/camera/camera2/OutputConfiguration.cpp +++ b/camera/camera2/OutputConfiguration.cpp @@ -167,19 +167,23 @@ status_t OutputConfiguration::readFromParcel(const android::Parcel* parcel) { } OutputConfiguration::OutputConfiguration(sp& gbp, int rotation, + const String16& physicalId, int surfaceSetID, bool isShared) { mGbps.push_back(gbp); mRotation = rotation; mSurfaceSetID = surfaceSetID; mIsDeferred = false; mIsShared = isShared; + mPhysicalCameraId = physicalId; } OutputConfiguration::OutputConfiguration( const std::vector>& gbps, - int rotation, int surfaceSetID, int surfaceType, int width, int height, bool isShared) + int rotation, const String16& physicalCameraId, int surfaceSetID, int surfaceType, + int width, int height, bool isShared) : mGbps(gbps), mRotation(rotation), mSurfaceSetID(surfaceSetID), mSurfaceType(surfaceType), - mWidth(width), mHeight(height), mIsDeferred(false), mIsShared(isShared) { } + mWidth(width), mHeight(height), mIsDeferred(false), mIsShared(isShared), + mPhysicalCameraId(physicalCameraId) { } status_t OutputConfiguration::writeToParcel(android::Parcel* parcel) const { diff --git a/camera/include/camera/camera2/OutputConfiguration.h b/camera/include/camera/camera2/OutputConfiguration.h index 5b117fb14e..95c4f39d91 100644 --- a/camera/include/camera/camera2/OutputConfiguration.h +++ b/camera/include/camera/camera2/OutputConfiguration.h @@ -65,10 +65,12 @@ public: OutputConfiguration(const android::Parcel& parcel); OutputConfiguration(sp& gbp, int rotation, + const String16& physicalCameraId, int surfaceSetID = INVALID_SET_ID, bool isShared = false); OutputConfiguration(const std::vector>& gbps, - int rotation, int surfaceSetID = INVALID_SET_ID, + int rotation, const String16& physicalCameraId, + int surfaceSetID = INVALID_SET_ID, int surfaceType = OutputConfiguration::SURFACE_TYPE_UNKNOWN, int width = 0, int height = 0, bool isShared = false); diff --git a/camera/ndk/NdkCameraCaptureSession.cpp b/camera/ndk/NdkCameraCaptureSession.cpp index fd95296161..540d84e43b 100644 --- a/camera/ndk/NdkCameraCaptureSession.cpp +++ b/camera/ndk/NdkCameraCaptureSession.cpp @@ -28,6 +28,8 @@ #include #include "impl/ACameraCaptureSession.h" +#include "impl/ACameraCaptureSession.inc" + using namespace android; EXPORT @@ -82,7 +84,31 @@ camera_status_t ACameraCaptureSession_capture( return ACAMERA_ERROR_SESSION_CLOSED; } - return session->capture(cbs, numRequests, requests, captureSequenceId); + return session->capture( + cbs, numRequests, requests, captureSequenceId); +} + +EXPORT +camera_status_t ACameraCaptureSession_logicalCamera_capture( + ACameraCaptureSession* session, + /*optional*/ACameraCaptureSession_logicalCamera_captureCallbacks* lcbs, + int numRequests, ACaptureRequest** requests, + /*optional*/int* captureSequenceId) { + ATRACE_CALL(); + if (session == nullptr || requests == nullptr || numRequests < 1) { + ALOGE("%s: Error: invalid input: session %p, numRequest %d, requests %p", + __FUNCTION__, session, numRequests, requests); + return ACAMERA_ERROR_INVALID_PARAMETER; + } + + if (session->isClosed()) { + ALOGE("%s: session %p is already closed", __FUNCTION__, session); + *captureSequenceId = CAPTURE_SEQUENCE_ID_NONE; + return ACAMERA_ERROR_SESSION_CLOSED; + } + + return session->capture( + lcbs, numRequests, requests, captureSequenceId); } EXPORT @@ -106,6 +132,28 @@ camera_status_t ACameraCaptureSession_setRepeatingRequest( return session->setRepeatingRequest(cbs, numRequests, requests, captureSequenceId); } +EXPORT +camera_status_t ACameraCaptureSession_logicalCamera_setRepeatingRequest( + ACameraCaptureSession* session, + /*optional*/ACameraCaptureSession_logicalCamera_captureCallbacks* lcbs, + int numRequests, ACaptureRequest** requests, + /*optional*/int* captureSequenceId) { + ATRACE_CALL(); + if (session == nullptr || requests == nullptr || numRequests < 1) { + ALOGE("%s: Error: invalid input: session %p, numRequest %d, requests %p", + __FUNCTION__, session, numRequests, requests); + return ACAMERA_ERROR_INVALID_PARAMETER; + } + + if (session->isClosed()) { + ALOGE("%s: session %p is already closed", __FUNCTION__, session); + *captureSequenceId = CAPTURE_SEQUENCE_ID_NONE; + return ACAMERA_ERROR_SESSION_CLOSED; + } + + return session->setRepeatingRequest(lcbs, numRequests, requests, captureSequenceId); +} + EXPORT camera_status_t ACameraCaptureSession_stopRepeating(ACameraCaptureSession* session) { ATRACE_CALL(); diff --git a/camera/ndk/NdkCameraDevice.cpp b/camera/ndk/NdkCameraDevice.cpp index ef05e0b80f..98608da774 100644 --- a/camera/ndk/NdkCameraDevice.cpp +++ b/camera/ndk/NdkCameraDevice.cpp @@ -128,6 +128,20 @@ camera_status_t ACaptureSessionSharedOutput_create( return ACAMERA_OK; } +EXPORT +camera_status_t ACaptureSessionPhysicalOutput_create( + ACameraWindowType* window, const char* physicalId, + /*out*/ACaptureSessionOutput** out) { + ATRACE_CALL(); + if (window == nullptr || physicalId == nullptr || out == nullptr) { + ALOGE("%s: Error: bad argument. window %p, physicalId %p, out %p", + __FUNCTION__, window, physicalId, out); + return ACAMERA_ERROR_INVALID_PARAMETER; + } + *out = new ACaptureSessionOutput(window, false, physicalId); + return ACAMERA_OK; +} + EXPORT camera_status_t ACaptureSessionSharedOutput_add(ACaptureSessionOutput *out, ACameraWindowType* window) { diff --git a/camera/ndk/NdkCameraMetadata.cpp b/camera/ndk/NdkCameraMetadata.cpp index 34ec2da100..9a39ed872f 100644 --- a/camera/ndk/NdkCameraMetadata.cpp +++ b/camera/ndk/NdkCameraMetadata.cpp @@ -69,3 +69,20 @@ void ACameraMetadata_free(ACameraMetadata* metadata) { metadata->decStrong((void*) ACameraMetadata_free); } } + +EXPORT +bool ACameraMetadata_isLogicalMultiCamera(const ACameraMetadata* staticMetadata, + /*out*/size_t* numPhysicalCameras, /*out*/const char*const** physicalCameraIds) { + ATRACE_CALL(); + if (numPhysicalCameras == nullptr || physicalCameraIds == nullptr) { + ALOGE("%s: Invalid input: numPhysicalCameras %p, physicalCameraIds %p", + __FUNCTION__, numPhysicalCameras, physicalCameraIds); + return false; + } + if (staticMetadata == nullptr) { + ALOGE("%s: Invalid input: staticMetadata is null.", __FUNCTION__); + return false; + } + + return staticMetadata->isLogicalMultiCamera(numPhysicalCameras, physicalCameraIds); +} diff --git a/camera/ndk/impl/ACameraCaptureSession.cpp b/camera/ndk/impl/ACameraCaptureSession.cpp index fb72bdbb3c..d6f14122ea 100644 --- a/camera/ndk/impl/ACameraCaptureSession.cpp +++ b/camera/ndk/impl/ACameraCaptureSession.cpp @@ -107,47 +107,6 @@ ACameraCaptureSession::abortCaptures() { return ret; } -camera_status_t -ACameraCaptureSession::setRepeatingRequest( - /*optional*/ACameraCaptureSession_captureCallbacks* cbs, - int numRequests, ACaptureRequest** requests, - /*optional*/int* captureSequenceId) { - sp dev = getDeviceSp(); - if (dev == nullptr) { - ALOGE("Error: Device associated with session %p has been closed!", this); - return ACAMERA_ERROR_SESSION_CLOSED; - } - - camera_status_t ret; - dev->lockDeviceForSessionOps(); - { - Mutex::Autolock _l(mSessionLock); - ret = dev->setRepeatingRequestsLocked( - this, cbs, numRequests, requests, captureSequenceId); - } - dev->unlockDevice(); - return ret; -} - -camera_status_t ACameraCaptureSession::capture( - /*optional*/ACameraCaptureSession_captureCallbacks* cbs, - int numRequests, ACaptureRequest** requests, - /*optional*/int* captureSequenceId) { - sp dev = getDeviceSp(); - if (dev == nullptr) { - ALOGE("Error: Device associated with session %p has been closed!", this); - return ACAMERA_ERROR_SESSION_CLOSED; - } - camera_status_t ret; - dev->lockDeviceForSessionOps(); - { - Mutex::Autolock _l(mSessionLock); - ret = dev->captureLocked(this, cbs, numRequests, requests, captureSequenceId); - } - dev->unlockDevice(); - return ret; -} - camera_status_t ACameraCaptureSession::updateOutputConfiguration(ACaptureSessionOutput *output) { sp dev = getDeviceSp(); if (dev == nullptr) { diff --git a/camera/ndk/impl/ACameraCaptureSession.h b/camera/ndk/impl/ACameraCaptureSession.h index 133c2c8325..08a922634d 100644 --- a/camera/ndk/impl/ACameraCaptureSession.h +++ b/camera/ndk/impl/ACameraCaptureSession.h @@ -17,6 +17,7 @@ #define _ACAMERA_CAPTURE_SESSION_H #include +#include #include #include @@ -29,8 +30,9 @@ using namespace android; struct ACaptureSessionOutput { - explicit ACaptureSessionOutput(ACameraWindowType* window, bool isShared = false) : - mWindow(window), mIsShared(isShared) {}; + explicit ACaptureSessionOutput(ACameraWindowType* window, bool isShared = false, + const char* physicalCameraId = "") : + mWindow(window), mIsShared(isShared), mPhysicalCameraId(physicalCameraId) {}; bool operator == (const ACaptureSessionOutput& other) const { return mWindow == other.mWindow; @@ -49,6 +51,7 @@ struct ACaptureSessionOutput { std::set mSharedWindows; bool mIsShared; int mRotation = CAMERA3_STREAM_ROTATION_0; + std::string mPhysicalCameraId; }; #endif @@ -88,13 +91,15 @@ struct ACameraCaptureSession : public RefBase { camera_status_t abortCaptures(); + template camera_status_t setRepeatingRequest( - /*optional*/ACameraCaptureSession_captureCallbacks* cbs, + /*optional*/T* cbs, int numRequests, ACaptureRequest** requests, /*optional*/int* captureSequenceId); + template camera_status_t capture( - /*optional*/ACameraCaptureSession_captureCallbacks* cbs, + /*optional*/T* cbs, int numRequests, ACaptureRequest** requests, /*optional*/int* captureSequenceId); diff --git a/camera/ndk/impl/ACameraCaptureSession.inc b/camera/ndk/impl/ACameraCaptureSession.inc new file mode 100644 index 0000000000..86bf8a5d25 --- /dev/null +++ b/camera/ndk/impl/ACameraCaptureSession.inc @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ACameraCaptureSession.h" + +#ifdef __ANDROID_VNDK__ +#include "ndk_vendor/impl/ACameraDeviceVendor.inc" +#else +#include "ACameraDevice.inc" +#endif + +using namespace android; + +template +camera_status_t +ACameraCaptureSession::setRepeatingRequest( + /*optional*/T* cbs, + int numRequests, ACaptureRequest** requests, + /*optional*/int* captureSequenceId) { + sp dev = getDeviceSp(); + if (dev == nullptr) { + ALOGE("Error: Device associated with session %p has been closed!", this); + return ACAMERA_ERROR_SESSION_CLOSED; + } + + camera_status_t ret; + dev->lockDeviceForSessionOps(); + { + Mutex::Autolock _l(mSessionLock); + ret = dev->setRepeatingRequestsLocked( + this, cbs, numRequests, requests, captureSequenceId); + } + dev->unlockDevice(); + return ret; +} + +template +camera_status_t ACameraCaptureSession::capture( + /*optional*/T* cbs, + int numRequests, ACaptureRequest** requests, + /*optional*/int* captureSequenceId) { + sp dev = getDeviceSp(); + if (dev == nullptr) { + ALOGE("Error: Device associated with session %p has been closed!", this); + return ACAMERA_ERROR_SESSION_CLOSED; + } + camera_status_t ret; + dev->lockDeviceForSessionOps(); + { + Mutex::Autolock _l(mSessionLock); + ret = dev->captureLocked(this, cbs, numRequests, requests, captureSequenceId); + } + dev->unlockDevice(); + return ret; +} diff --git a/camera/ndk/impl/ACameraDevice.cpp b/camera/ndk/impl/ACameraDevice.cpp index 657d41fa4e..d8a57650c8 100644 --- a/camera/ndk/impl/ACameraDevice.cpp +++ b/camera/ndk/impl/ACameraDevice.cpp @@ -20,13 +20,14 @@ #include #include #include -#include #include #include "ACameraDevice.h" #include "ACameraMetadata.h" #include "ACaptureRequest.h" #include "ACameraCaptureSession.h" +#include "ACameraCaptureSession.inc" + namespace android { namespace acam { @@ -39,6 +40,7 @@ const char* CameraDevice::kSessionSpKey = "SessionSp"; const char* CameraDevice::kCaptureRequestKey = "CaptureRequest"; const char* CameraDevice::kTimeStampKey = "TimeStamp"; const char* CameraDevice::kCaptureResultKey = "CaptureResult"; +const char* CameraDevice::kPhysicalCaptureResultKey = "PhysicalCaptureResult"; const char* CameraDevice::kCaptureFailureKey = "CaptureFailure"; const char* CameraDevice::kSequenceIdKey = "SequenceId"; const char* CameraDevice::kFrameNumberKey = "FrameNumber"; @@ -190,106 +192,6 @@ CameraDevice::createCaptureSession( return ACAMERA_OK; } -camera_status_t -CameraDevice::captureLocked( - sp session, - /*optional*/ACameraCaptureSession_captureCallbacks* cbs, - int numRequests, ACaptureRequest** requests, - /*optional*/int* captureSequenceId) { - return submitRequestsLocked( - session, cbs, numRequests, requests, captureSequenceId, /*isRepeating*/false); -} - -camera_status_t -CameraDevice::setRepeatingRequestsLocked( - sp session, - /*optional*/ACameraCaptureSession_captureCallbacks* cbs, - int numRequests, ACaptureRequest** requests, - /*optional*/int* captureSequenceId) { - return submitRequestsLocked( - session, cbs, numRequests, requests, captureSequenceId, /*isRepeating*/true); -} - -camera_status_t -CameraDevice::submitRequestsLocked( - sp session, - /*optional*/ACameraCaptureSession_captureCallbacks* cbs, - int numRequests, ACaptureRequest** requests, - /*optional*/int* captureSequenceId, - bool isRepeating) { - camera_status_t ret = checkCameraClosedOrErrorLocked(); - if (ret != ACAMERA_OK) { - ALOGE("Camera %s submit capture request failed! ret %d", getId(), ret); - return ret; - } - - // Form two vectors of capture request, one for internal tracking - std::vector requestList; - Vector > requestsV; - requestsV.setCapacity(numRequests); - for (int i = 0; i < numRequests; i++) { - sp req; - ret = allocateCaptureRequest(requests[i], req); - if (ret != ACAMERA_OK) { - ALOGE("Convert capture request to internal format failure! ret %d", ret); - return ret; - } - if (req->mSurfaceList.empty()) { - ALOGE("Capture request without output target cannot be submitted!"); - return ACAMERA_ERROR_INVALID_PARAMETER; - } - requestList.push_back(*(req.get())); - requestsV.push_back(req); - } - - if (isRepeating) { - ret = stopRepeatingLocked(); - if (ret != ACAMERA_OK) { - ALOGE("Camera %s stop repeating failed! ret %d", getId(), ret); - return ret; - } - } - - binder::Status remoteRet; - hardware::camera2::utils::SubmitInfo info; - remoteRet = mRemote->submitRequestList(requestList, isRepeating, &info); - int sequenceId = info.mRequestId; - int64_t lastFrameNumber = info.mLastFrameNumber; - if (sequenceId < 0) { - ALOGE("Camera %s submit request remote failure: ret %d", getId(), sequenceId); - return ACAMERA_ERROR_UNKNOWN; - } - - CallbackHolder cbHolder(session, requestsV, isRepeating, cbs); - mSequenceCallbackMap.insert(std::make_pair(sequenceId, cbHolder)); - - if (isRepeating) { - // stopRepeating above should have cleanup repeating sequence id - if (mRepeatingSequenceId != REQUEST_ID_NONE) { - setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_DEVICE); - return ACAMERA_ERROR_CAMERA_DEVICE; - } - mRepeatingSequenceId = sequenceId; - } else { - mSequenceLastFrameNumberMap.insert(std::make_pair(sequenceId, lastFrameNumber)); - } - - if (mIdle) { - sp msg = new AMessage(kWhatSessionStateCb, mHandler); - msg->setPointer(kContextKey, session->mUserSessionCallback.context); - msg->setObject(kSessionSpKey, session); - msg->setPointer(kCallbackFpKey, (void*) session->mUserSessionCallback.onActive); - postSessionMsgAndCleanup(msg); - } - mIdle = false; - mBusySession = session; - - if (captureSequenceId) { - *captureSequenceId = sequenceId; - } - return ACAMERA_OK; -} - camera_status_t CameraDevice::updateOutputConfigurationLocked(ACaptureSessionOutput *output) { camera_status_t ret = checkCameraClosedOrErrorLocked(); if (ret != ACAMERA_OK) { @@ -325,8 +227,9 @@ camera_status_t CameraDevice::updateOutputConfigurationLocked(ACaptureSessionOut return ret; } - OutputConfiguration outConfig(iGBP, output->mRotation, OutputConfiguration::INVALID_SET_ID, - true); + String16 physicalId16(output->mPhysicalCameraId.c_str()); + OutputConfiguration outConfig(iGBP, output->mRotation, physicalId16, + OutputConfiguration::INVALID_SET_ID, true); for (auto& anw : output->mSharedWindows) { ret = getIGBPfromAnw(anw, iGBP); @@ -640,8 +543,9 @@ CameraDevice::configureStreamsLocked(const ACaptureSessionOutputContainer* outpu if (ret != ACAMERA_OK) { return ret; } + String16 physicalId16(outConfig.mPhysicalCameraId.c_str()); outputSet.insert(std::make_pair( - anw, OutputConfiguration(iGBP, outConfig.mRotation, + anw, OutputConfiguration(iGBP, outConfig.mRotation, physicalId16, OutputConfiguration::INVALID_SET_ID, outConfig.mIsShared))); } auto addSet = outputSet; @@ -829,7 +733,7 @@ CameraDevice::onCaptureErrorLocked( if (errorCode == hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_BUFFER) { int32_t streamId = resultExtras.errorStreamId; ACameraCaptureSession_captureCallback_bufferLost onBufferLost = - cbh.mCallbacks.onCaptureBufferLost; + cbh.mOnCaptureBufferLost; auto outputPairIt = mConfiguredOutputs.find(streamId); if (outputPairIt == mConfiguredOutputs.end()) { ALOGE("%s: Error: stream id %d does not exist", __FUNCTION__, streamId); @@ -846,7 +750,7 @@ CameraDevice::onCaptureErrorLocked( getId(), anw, frameNumber); sp msg = new AMessage(kWhatCaptureBufferLost, mHandler); - msg->setPointer(kContextKey, cbh.mCallbacks.context); + msg->setPointer(kContextKey, cbh.mContext); msg->setObject(kSessionSpKey, session); msg->setPointer(kCallbackFpKey, (void*) onBufferLost); msg->setObject(kCaptureRequestKey, request); @@ -858,7 +762,7 @@ CameraDevice::onCaptureErrorLocked( } } else { // Handle other capture failures // Fire capture failure callback if there is one registered - ACameraCaptureSession_captureCallback_failed onError = cbh.mCallbacks.onCaptureFailed; + ACameraCaptureSession_captureCallback_failed onError = cbh.mOnCaptureFailed; sp failure(new CameraCaptureFailure()); failure->frameNumber = frameNumber; // TODO: refine this when implementing flush @@ -868,7 +772,7 @@ CameraDevice::onCaptureErrorLocked( hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_RESULT); sp msg = new AMessage(kWhatCaptureFail, mHandler); - msg->setPointer(kContextKey, cbh.mCallbacks.context); + msg->setPointer(kContextKey, cbh.mContext); msg->setObject(kSessionSpKey, session); msg->setPointer(kCallbackFpKey, (void*) onError); msg->setObject(kCaptureRequestKey, request); @@ -890,6 +794,7 @@ void CameraDevice::CallbackHandler::onMessageReceived( case kWhatSessionStateCb: case kWhatCaptureStart: case kWhatCaptureResult: + case kWhatLogicalCaptureResult: case kWhatCaptureFail: case kWhatCaptureSeqEnd: case kWhatCaptureSeqAbort: @@ -960,6 +865,7 @@ void CameraDevice::CallbackHandler::onMessageReceived( case kWhatSessionStateCb: case kWhatCaptureStart: case kWhatCaptureResult: + case kWhatLogicalCaptureResult: case kWhatCaptureFail: case kWhatCaptureSeqEnd: case kWhatCaptureSeqAbort: @@ -977,6 +883,7 @@ void CameraDevice::CallbackHandler::onMessageReceived( switch (msg->what()) { case kWhatCaptureStart: case kWhatCaptureResult: + case kWhatLogicalCaptureResult: case kWhatCaptureFail: case kWhatCaptureBufferLost: found = msg->findObject(kCaptureRequestKey, &obj); @@ -1048,6 +955,64 @@ void CameraDevice::CallbackHandler::onMessageReceived( freeACaptureRequest(request); break; } + case kWhatLogicalCaptureResult: + { + ACameraCaptureSession_logicalCamera_captureCallback_result onResult; + found = msg->findPointer(kCallbackFpKey, (void**) &onResult); + if (!found) { + ALOGE("%s: Cannot find logicalCamera capture result callback!", + __FUNCTION__); + return; + } + if (onResult == nullptr) { + return; + } + + found = msg->findObject(kCaptureResultKey, &obj); + if (!found) { + ALOGE("%s: Cannot find capture result!", __FUNCTION__); + return; + } + sp result(static_cast(obj.get())); + + found = msg->findObject(kPhysicalCaptureResultKey, &obj); + if (!found) { + ALOGE("%s: Cannot find physical capture result!", __FUNCTION__); + return; + } + sp physicalResult( + static_cast(obj.get())); + std::vector& physicalResultInfo = + physicalResult->mPhysicalResultInfo; + + std::vector physicalCameraIds; + std::vector> physicalMetadataCopy; + for (size_t i = 0; i < physicalResultInfo.size(); i++) { + String8 physicalId8(physicalResultInfo[i].mPhysicalCameraId); + physicalCameraIds.push_back(physicalId8.c_str()); + + CameraMetadata clone = physicalResultInfo[i].mPhysicalCameraMetadata; + clone.update(ANDROID_SYNC_FRAME_NUMBER, + &physicalResult->mFrameNumber, /*data_count*/1); + sp metadata = + new ACameraMetadata(clone.release(), ACameraMetadata::ACM_RESULT); + physicalMetadataCopy.push_back(metadata); + } + + std::vector physicalCameraIdPtrs; + std::vector physicalMetadataCopyPtrs; + for (size_t i = 0; i < physicalResultInfo.size(); i++) { + physicalCameraIdPtrs.push_back(physicalCameraIds[i].c_str()); + physicalMetadataCopyPtrs.push_back(physicalMetadataCopy[i].get()); + } + + ACaptureRequest* request = allocateACaptureRequest(requestSp); + (*onResult)(context, session.get(), request, result.get(), + physicalResultInfo.size(), physicalCameraIdPtrs.data(), + physicalMetadataCopyPtrs.data()); + freeACaptureRequest(request); + break; + } case kWhatCaptureFail: { ACameraCaptureSession_captureCallback_failed onFail; @@ -1158,12 +1123,34 @@ void CameraDevice::CallbackHandler::onMessageReceived( } CameraDevice::CallbackHolder::CallbackHolder( - sp session, - const Vector >& requests, - bool isRepeating, - ACameraCaptureSession_captureCallbacks* cbs) : - mSession(session), mRequests(requests), - mIsRepeating(isRepeating), mCallbacks(fillCb(cbs)) {} + sp session, + const Vector >& requests, + bool isRepeating, + ACameraCaptureSession_captureCallbacks* cbs) : + mSession(session), mRequests(requests), + mIsRepeating(isRepeating), + mIsLogicalCameraCallback(false) { + initCaptureCallbacks(cbs); + + if (cbs != nullptr) { + mOnCaptureCompleted = cbs->onCaptureCompleted; + } +} + +CameraDevice::CallbackHolder::CallbackHolder( + sp session, + const Vector >& requests, + bool isRepeating, + ACameraCaptureSession_logicalCamera_captureCallbacks* lcbs) : + mSession(session), mRequests(requests), + mIsRepeating(isRepeating), + mIsLogicalCameraCallback(true) { + initCaptureCallbacks(lcbs); + + if (lcbs != nullptr) { + mOnLogicalCameraCaptureCompleted = lcbs->onLogicalCameraCaptureCompleted; + } +} void CameraDevice::checkRepeatingSequenceCompleteLocked( @@ -1180,9 +1167,9 @@ CameraDevice::checkRepeatingSequenceCompleteLocked( mSequenceCallbackMap.erase(cbIt); // send seq aborted callback sp msg = new AMessage(kWhatCaptureSeqAbort, mHandler); - msg->setPointer(kContextKey, cbh.mCallbacks.context); + msg->setPointer(kContextKey, cbh.mContext); msg->setObject(kSessionSpKey, cbh.mSession); - msg->setPointer(kCallbackFpKey, (void*) cbh.mCallbacks.onCaptureSequenceAborted); + msg->setPointer(kCallbackFpKey, (void*) cbh.mOnCaptureSequenceAborted); msg->setInt32(kSequenceIdKey, sequenceId); postSessionMsgAndCleanup(msg); } else { @@ -1230,9 +1217,9 @@ CameraDevice::checkAndFireSequenceCompleteLocked() { mSequenceCallbackMap.erase(cbIt); // send seq complete callback sp msg = new AMessage(kWhatCaptureSeqEnd, mHandler); - msg->setPointer(kContextKey, cbh.mCallbacks.context); + msg->setPointer(kContextKey, cbh.mContext); msg->setObject(kSessionSpKey, cbh.mSession); - msg->setPointer(kCallbackFpKey, (void*) cbh.mCallbacks.onCaptureSequenceCompleted); + msg->setPointer(kCallbackFpKey, (void*) cbh.mOnCaptureSequenceCompleted); msg->setInt32(kSequenceIdKey, sequenceId); msg->setInt64(kFrameNumberKey, lastFrameNumber); @@ -1389,7 +1376,7 @@ CameraDevice::ServiceCallback::onCaptureStarted( auto it = dev->mSequenceCallbackMap.find(sequenceId); if (it != dev->mSequenceCallbackMap.end()) { CallbackHolder cbh = (*it).second; - ACameraCaptureSession_captureCallback_start onStart = cbh.mCallbacks.onCaptureStarted; + ACameraCaptureSession_captureCallback_start onStart = cbh.mOnCaptureStarted; sp session = cbh.mSession; if ((size_t) burstId >= cbh.mRequests.size()) { ALOGE("%s: Error: request index %d out of bound (size %zu)", @@ -1398,7 +1385,7 @@ CameraDevice::ServiceCallback::onCaptureStarted( } sp request = cbh.mRequests[burstId]; sp msg = new AMessage(kWhatCaptureStart, dev->mHandler); - msg->setPointer(kContextKey, cbh.mCallbacks.context); + msg->setPointer(kContextKey, cbh.mContext); msg->setObject(kSessionSpKey, session); msg->setPointer(kCallbackFpKey, (void*) onStart); msg->setObject(kCaptureRequestKey, request); @@ -1413,7 +1400,6 @@ CameraDevice::ServiceCallback::onResultReceived( const CameraMetadata& metadata, const CaptureResultExtras& resultExtras, const std::vector& physicalResultInfos) { - (void) physicalResultInfos; binder::Status ret = binder::Status::ok(); sp dev = mDevice.promote(); @@ -1449,9 +1435,6 @@ CameraDevice::ServiceCallback::onResultReceived( auto it = dev->mSequenceCallbackMap.find(sequenceId); if (it != dev->mSequenceCallbackMap.end()) { CallbackHolder cbh = (*it).second; - ACameraCaptureSession_captureCallback_result onResult = isPartialResult ? - cbh.mCallbacks.onCaptureProgressed : - cbh.mCallbacks.onCaptureCompleted; sp session = cbh.mSession; if ((size_t) burstId >= cbh.mRequests.size()) { ALOGE("%s: Error: request index %d out of bound (size %zu)", @@ -1461,13 +1444,27 @@ CameraDevice::ServiceCallback::onResultReceived( sp request = cbh.mRequests[burstId]; sp result(new ACameraMetadata( metadataCopy.release(), ACameraMetadata::ACM_RESULT)); + sp physicalResult( + new ACameraPhysicalCaptureResultInfo(physicalResultInfos, frameNumber)); - sp msg = new AMessage(kWhatCaptureResult, dev->mHandler); - msg->setPointer(kContextKey, cbh.mCallbacks.context); + sp msg = new AMessage( + cbh.mIsLogicalCameraCallback ? kWhatLogicalCaptureResult : kWhatCaptureResult, + dev->mHandler); + msg->setPointer(kContextKey, cbh.mContext); msg->setObject(kSessionSpKey, session); - msg->setPointer(kCallbackFpKey, (void*) onResult); msg->setObject(kCaptureRequestKey, request); msg->setObject(kCaptureResultKey, result); + if (isPartialResult) { + msg->setPointer(kCallbackFpKey, + (void *)cbh.mOnCaptureProgressed); + } else if (cbh.mIsLogicalCameraCallback) { + msg->setPointer(kCallbackFpKey, + (void *)cbh.mOnLogicalCameraCaptureCompleted); + msg->setObject(kPhysicalCaptureResultKey, physicalResult); + } else { + msg->setPointer(kCallbackFpKey, + (void *)cbh.mOnCaptureCompleted); + } dev->postSessionMsgAndCleanup(msg); } diff --git a/camera/ndk/impl/ACameraDevice.h b/camera/ndk/impl/ACameraDevice.h index 8f56d3f2e2..d0f363bfbb 100644 --- a/camera/ndk/impl/ACameraDevice.h +++ b/camera/ndk/impl/ACameraDevice.h @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -46,6 +47,16 @@ namespace acam { // Wrap ACameraCaptureFailure so it can be ref-counted struct CameraCaptureFailure : public RefBase, public ACameraCaptureFailure {}; +// Wrap PhysicalCaptureResultInfo so that it can be ref-counted +struct ACameraPhysicalCaptureResultInfo: public RefBase { + ACameraPhysicalCaptureResultInfo(const std::vector& info, + int64_t frameNumber) : + mPhysicalResultInfo(info), mFrameNumber(frameNumber) {} + + std::vector mPhysicalResultInfo; + int64_t mFrameNumber; +}; + class CameraDevice final : public RefBase { public: CameraDevice(const char* id, ACameraDevice_StateCallbacks* cb, @@ -109,19 +120,22 @@ class CameraDevice final : public RefBase { camera_status_t waitUntilIdleLocked(); + template camera_status_t captureLocked(sp session, - /*optional*/ACameraCaptureSession_captureCallbacks* cbs, + /*optional*/T* cbs, int numRequests, ACaptureRequest** requests, /*optional*/int* captureSequenceId); + template camera_status_t setRepeatingRequestsLocked(sp session, - /*optional*/ACameraCaptureSession_captureCallbacks* cbs, + /*optional*/T* cbs, int numRequests, ACaptureRequest** requests, /*optional*/int* captureSequenceId); + template camera_status_t submitRequestsLocked( sp session, - /*optional*/ACameraCaptureSession_captureCallbacks* cbs, + /*optional*/T* cbs, int numRequests, ACaptureRequest** requests, /*out*/int* captureSequenceId, bool isRepeating); @@ -192,6 +206,7 @@ class CameraDevice final : public RefBase { // Capture callbacks kWhatCaptureStart, // onCaptureStarted kWhatCaptureResult, // onCaptureProgressed, onCaptureCompleted + kWhatLogicalCaptureResult, // onLogicalCameraCaptureCompleted kWhatCaptureFail, // onCaptureFailed kWhatCaptureSeqEnd, // onCaptureSequenceCompleted kWhatCaptureSeqAbort, // onCaptureSequenceAborted @@ -207,6 +222,7 @@ class CameraDevice final : public RefBase { static const char* kCaptureRequestKey; static const char* kTimeStampKey; static const char* kCaptureResultKey; + static const char* kPhysicalCaptureResultKey; static const char* kCaptureFailureKey; static const char* kSequenceIdKey; static const char* kFrameNumberKey; @@ -245,19 +261,46 @@ class CameraDevice final : public RefBase { const Vector >& requests, bool isRepeating, ACameraCaptureSession_captureCallbacks* cbs); - - static ACameraCaptureSession_captureCallbacks fillCb( - ACameraCaptureSession_captureCallbacks* cbs) { + CallbackHolder(sp session, + const Vector >& requests, + bool isRepeating, + ACameraCaptureSession_logicalCamera_captureCallbacks* lcbs); + + template + void initCaptureCallbacks(T* cbs) { + mContext = nullptr; + mOnCaptureStarted = nullptr; + mOnCaptureProgressed = nullptr; + mOnCaptureCompleted = nullptr; + mOnLogicalCameraCaptureCompleted = nullptr; + mOnCaptureFailed = nullptr; + mOnCaptureSequenceCompleted = nullptr; + mOnCaptureSequenceAborted = nullptr; + mOnCaptureBufferLost = nullptr; if (cbs != nullptr) { - return *cbs; + mContext = cbs->context; + mOnCaptureStarted = cbs->onCaptureStarted; + mOnCaptureProgressed = cbs->onCaptureProgressed; + mOnCaptureFailed = cbs->onCaptureFailed; + mOnCaptureSequenceCompleted = cbs->onCaptureSequenceCompleted; + mOnCaptureSequenceAborted = cbs->onCaptureSequenceAborted; + mOnCaptureBufferLost = cbs->onCaptureBufferLost; } - return { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr }; } - sp mSession; Vector > mRequests; const bool mIsRepeating; - ACameraCaptureSession_captureCallbacks mCallbacks; + const bool mIsLogicalCameraCallback; + + void* mContext; + ACameraCaptureSession_captureCallback_start mOnCaptureStarted; + ACameraCaptureSession_captureCallback_result mOnCaptureProgressed; + ACameraCaptureSession_captureCallback_result mOnCaptureCompleted; + ACameraCaptureSession_logicalCamera_captureCallback_result mOnLogicalCameraCaptureCompleted; + ACameraCaptureSession_captureCallback_failed mOnCaptureFailed; + ACameraCaptureSession_captureCallback_sequenceEnd mOnCaptureSequenceCompleted; + ACameraCaptureSession_captureCallback_sequenceAbort mOnCaptureSequenceAborted; + ACameraCaptureSession_captureCallback_bufferLost mOnCaptureBufferLost; }; // sequence id -> callbacks map std::map mSequenceCallbackMap; diff --git a/camera/ndk/impl/ACameraDevice.inc b/camera/ndk/impl/ACameraDevice.inc new file mode 100644 index 0000000000..1fc5352e85 --- /dev/null +++ b/camera/ndk/impl/ACameraDevice.inc @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include "ACameraDevice.h" +#include "ACameraMetadata.h" +#include "ACaptureRequest.h" +#include "ACameraCaptureSession.h" + +namespace android { +namespace acam { + +template +camera_status_t +CameraDevice::captureLocked( + sp session, + /*optional*/T* cbs, + int numRequests, ACaptureRequest** requests, + /*optional*/int* captureSequenceId) { + return submitRequestsLocked( + session, cbs, numRequests, requests, captureSequenceId, /*isRepeating*/false); +} + +template +camera_status_t +CameraDevice::setRepeatingRequestsLocked( + sp session, + /*optional*/T* cbs, + int numRequests, ACaptureRequest** requests, + /*optional*/int* captureSequenceId) { + return submitRequestsLocked( + session, cbs, numRequests, requests, captureSequenceId, /*isRepeating*/true); +} + +template +camera_status_t CameraDevice::submitRequestsLocked( + sp session, + /*optional*/T* cbs, + int numRequests, ACaptureRequest** requests, + /*optional*/int* captureSequenceId, + bool isRepeating) { + camera_status_t ret = checkCameraClosedOrErrorLocked(); + if (ret != ACAMERA_OK) { + ALOGE("Camera %s submit capture request failed! ret %d", getId(), ret); + return ret; + } + + // Form two vectors of capture request, one for internal tracking + std::vector requestList; + Vector > requestsV; + requestsV.setCapacity(numRequests); + for (int i = 0; i < numRequests; i++) { + sp req; + ret = allocateCaptureRequest(requests[i], req); + if (ret != ACAMERA_OK) { + ALOGE("Convert capture request to internal format failure! ret %d", ret); + return ret; + } + if (req->mSurfaceList.empty()) { + ALOGE("Capture request without output target cannot be submitted!"); + return ACAMERA_ERROR_INVALID_PARAMETER; + } + requestList.push_back(*(req.get())); + requestsV.push_back(req); + } + + if (isRepeating) { + ret = stopRepeatingLocked(); + if (ret != ACAMERA_OK) { + ALOGE("Camera %s stop repeating failed! ret %d", getId(), ret); + return ret; + } + } + + binder::Status remoteRet; + hardware::camera2::utils::SubmitInfo info; + remoteRet = mRemote->submitRequestList(requestList, isRepeating, &info); + int sequenceId = info.mRequestId; + int64_t lastFrameNumber = info.mLastFrameNumber; + if (sequenceId < 0) { + ALOGE("Camera %s submit request remote failure: ret %d", getId(), sequenceId); + return ACAMERA_ERROR_UNKNOWN; + } + + CallbackHolder cbHolder(session, requestsV, isRepeating, cbs); + mSequenceCallbackMap.insert(std::make_pair(sequenceId, cbHolder)); + + if (isRepeating) { + // stopRepeating above should have cleanup repeating sequence id + if (mRepeatingSequenceId != REQUEST_ID_NONE) { + setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_DEVICE); + return ACAMERA_ERROR_CAMERA_DEVICE; + } + mRepeatingSequenceId = sequenceId; + } else { + mSequenceLastFrameNumberMap.insert(std::make_pair(sequenceId, lastFrameNumber)); + } + + if (mIdle) { + sp msg = new AMessage(kWhatSessionStateCb, mHandler); + msg->setPointer(kContextKey, session->mUserSessionCallback.context); + msg->setObject(kSessionSpKey, session); + msg->setPointer(kCallbackFpKey, (void*) session->mUserSessionCallback.onActive); + postSessionMsgAndCleanup(msg); + } + mIdle = false; + mBusySession = session; + + if (captureSequenceId) { + *captureSequenceId = sequenceId; + } + return ACAMERA_OK; +} + +} // namespace acam +} // namespace android diff --git a/camera/ndk/impl/ACameraMetadata.cpp b/camera/ndk/impl/ACameraMetadata.cpp index 94b57132cb..c6612337ed 100644 --- a/camera/ndk/impl/ACameraMetadata.cpp +++ b/camera/ndk/impl/ACameraMetadata.cpp @@ -50,6 +50,7 @@ ACameraMetadata::isNdkSupportedCapability(int32_t capability) { case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_READ_SENSOR_SETTINGS: case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE: case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT: + case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA: return true; case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING: case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_PRIVATE_REPROCESSING: @@ -79,11 +80,41 @@ ACameraMetadata::filterUnsupportedFeatures() { uint8_t capability = entry.data.u8[i]; if (isNdkSupportedCapability(capability)) { capabilities.push(capability); + + if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA) { + derivePhysicalCameraIds(); + } } } mData.update(ANDROID_REQUEST_AVAILABLE_CAPABILITIES, capabilities); } +void +ACameraMetadata::derivePhysicalCameraIds() { + ACameraMetadata_const_entry entry; + auto ret = getConstEntry(ACAMERA_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS, &entry); + if (ret != ACAMERA_OK) { + ALOGE("%s: Get ACAMERA_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS key failed. ret %d", + __FUNCTION__, ret); + return; + } + + const uint8_t* ids = entry.data.u8; + size_t start = 0; + for (size_t i = 0; i < entry.count; ++i) { + if (ids[i] == '\0') { + if (start != i) { + mStaticPhysicalCameraIds.push_back((const char*)ids+start); + } + start = i+1; + } + } + + if (mStaticPhysicalCameraIds.size() < 2) { + ALOGW("%s: Logical multi-camera device only has %zu physical cameras", + __FUNCTION__, mStaticPhysicalCameraIds.size()); + } +} void ACameraMetadata::filterDurations(uint32_t tag) { @@ -309,6 +340,27 @@ ACameraMetadata::getInternalData() const { return mData; } +bool +ACameraMetadata::isLogicalMultiCamera(size_t* count, const char*const** physicalCameraIds) const { + if (mType != ACM_CHARACTERISTICS) { + ALOGE("%s must be called for a static metadata!", __FUNCTION__); + return false; + } + if (count == nullptr || physicalCameraIds == nullptr) { + ALOGE("%s: Invalid input count: %p, physicalCameraIds: %p", __FUNCTION__, + count, physicalCameraIds); + return false; + } + + if (mStaticPhysicalCameraIds.size() >= 2) { + *count = mStaticPhysicalCameraIds.size(); + *physicalCameraIds = mStaticPhysicalCameraIds.data(); + return true; + } + + return false; +} + // TODO: some of key below should be hidden from user // ex: ACAMERA_REQUEST_ID and ACAMERA_REPROCESS_EFFECTIVE_EXPOSURE_FACTOR /*@O~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~ diff --git a/camera/ndk/impl/ACameraMetadata.h b/camera/ndk/impl/ACameraMetadata.h index f21dbaf1ba..7049c4bab5 100644 --- a/camera/ndk/impl/ACameraMetadata.h +++ b/camera/ndk/impl/ACameraMetadata.h @@ -17,6 +17,7 @@ #define _ACAMERA_METADATA_H #include +#include #include #include @@ -65,6 +66,7 @@ struct ACameraMetadata : public RefBase { /*out*/const uint32_t** tags) const; const CameraMetadata& getInternalData() const; + bool isLogicalMultiCamera(size_t* count, const char* const** physicalCameraIds) const; private: @@ -74,6 +76,7 @@ struct ACameraMetadata : public RefBase { void filterUnsupportedFeatures(); // Hide features not yet supported by NDK void filterStreamConfigurations(); // Hide input streams, translate hal format to NDK formats void filterDurations(uint32_t tag); // translate hal format to NDK formats + void derivePhysicalCameraIds(); // Derive array of physical ids. template camera_status_t updateImpl(uint32_t tag, uint32_t count, const NDK_T* data) { @@ -112,6 +115,8 @@ struct ACameraMetadata : public RefBase { const ACAMERA_METADATA_TYPE mType; static std::unordered_set sSystemTags; + + std::vector mStaticPhysicalCameraIds; }; #endif // _ACAMERA_METADATA_H diff --git a/camera/ndk/include/camera/NdkCameraCaptureSession.h b/camera/ndk/include/camera/NdkCameraCaptureSession.h index 1244582364..d13a818648 100644 --- a/camera/ndk/include/camera/NdkCameraCaptureSession.h +++ b/camera/ndk/include/camera/NdkCameraCaptureSession.h @@ -643,6 +643,103 @@ camera_status_t ACameraCaptureSession_updateSharedOutput(ACameraCaptureSession* ACaptureSessionOutput* output) __INTRODUCED_IN(28); #endif /* __ANDROID_API__ >= 28 */ +#if __ANDROID_API__ >= 29 +/** + * The definition of final capture result callback with logical multi-camera support. + * + * This has the same functionality as final ACameraCaptureSession_captureCallback_result, with + * added ability to return physical camera result metadata within a logical multi-camera. + * + * For a logical multi-camera, this function will be called with the Id and result metadata + * of the underlying physical cameras, which the corresponding capture request contains targets for. + * If the capture request doesn't contain targets specific to any physical camera, or the current + * camera device isn't a logical multi-camera, physicalResultCount will be 0. + * + * @param context The optional application context provided by user in + * {@link ACameraCaptureSession_captureCallbacks}. + * @param session The camera capture session of interest. + * @param request The capture request of interest. Note that this pointer points to a copy of + * capture request sent by application, so the address is different to what + * application sent but the content will match. This request will be freed by + * framework immediately after this callback returns. + * @param result The capture result metadata reported by camera device. The memory is managed by + * camera framework. Do not access this pointer after this callback returns. + * @param physicalResultCount The number of physical camera result metadata + * @param physicalCameraIds The array of physical camera IDs on which the + * physical result metadata are reported. + * @param physicalResults The array of capture result metadata reported by the + * physical camera devices. + */ +typedef void (*ACameraCaptureSession_logicalCamera_captureCallback_result)( + void* context, ACameraCaptureSession* session, + ACaptureRequest* request, const ACameraMetadata* result, + size_t physicalResultCount, const char** physicalCameraIds, + const ACameraMetadata** physicalResults); + +/** + * This has the same functionality as ACameraCaptureSession_captureCallbacks, + * with the exception that an onLogicalCameraCaptureCompleted callback is + * used, instead of onCaptureCompleted, to support logical multi-camera. + */ +typedef struct ACameraCaptureSession_logicalCamera_captureCallbacks { + /** + * Same as ACameraCaptureSession_captureCallbacks + */ + void* context; + ACameraCaptureSession_captureCallback_start onCaptureStarted; + ACameraCaptureSession_captureCallback_result onCaptureProgressed; + + /** + * This callback is called when an image capture has fully completed and all the + * result metadata is available. For a logical multi-camera, this callback + * also returns the result metadata for all physical cameras being + * explicitly requested on. + * + *

This callback will always fire after the last {@link onCaptureProgressed}; + * in other words, no more partial results will be delivered once the completed result + * is available.

+ * + *

For performance-intensive use-cases where latency is a factor, consider + * using {@link onCaptureProgressed} instead.

+ * + *

Note that the ACaptureRequest pointer in the callback will not match what application has + * submitted, but the contents the ACaptureRequest will match what application submitted.

+ */ + ACameraCaptureSession_logicalCamera_captureCallback_result onLogicalCameraCaptureCompleted; + + /** + * Same as ACameraCaptureSession_captureCallbacks + */ + ACameraCaptureSession_captureCallback_failed onCaptureFailed; + ACameraCaptureSession_captureCallback_sequenceEnd onCaptureSequenceCompleted; + ACameraCaptureSession_captureCallback_sequenceAbort onCaptureSequenceAborted; + ACameraCaptureSession_captureCallback_bufferLost onCaptureBufferLost; +} ACameraCaptureSession_logicalCamera_captureCallbacks; + +/** + * This has the same functionality as ACameraCaptureSession_capture, with added + * support for logical multi-camera where the capture callbacks supports result metadata for + * physical cameras. + */ +camera_status_t ACameraCaptureSession_logicalCamera_capture( + ACameraCaptureSession* session, + /*optional*/ACameraCaptureSession_logicalCamera_captureCallbacks* callbacks, + int numRequests, ACaptureRequest** requests, + /*optional*/int* captureSequenceId) __INTRODUCED_IN(29); + +/** + * This has the same functionality as ACameraCaptureSession_setRepeatingRequest, with added + * support for logical multi-camera where the capture callbacks supports result metadata for + * physical cameras. + */ +camera_status_t ACameraCaptureSession_logicalCamera_setRepeatingRequest( + ACameraCaptureSession* session, + /*optional*/ACameraCaptureSession_logicalCamera_captureCallbacks* callbacks, + int numRequests, ACaptureRequest** requests, + /*optional*/int* captureSequenceId) __INTRODUCED_IN(29); + +#endif /* __ANDROID_API__ >= 29 */ + __END_DECLS #endif /* _NDK_CAMERA_CAPTURE_SESSION_H */ diff --git a/camera/ndk/include/camera/NdkCameraDevice.h b/camera/ndk/include/camera/NdkCameraDevice.h index 4fe43d5278..26af4f8787 100644 --- a/camera/ndk/include/camera/NdkCameraDevice.h +++ b/camera/ndk/include/camera/NdkCameraDevice.h @@ -765,6 +765,36 @@ camera_status_t ACameraDevice_createCaptureSessionWithSessionParameters( #endif /* __ANDROID_API__ >= 28 */ +#if __ANDROID_API__ >= 29 + +/** + * Create a ACaptureSessionOutput object used for streaming from a physical + * camera as part of a logical camera device. + * + *

The ACaptureSessionOutput is used in {@link ACaptureSessionOutputContainer_add} method to add + * an output {@link ANativeWindow} to ACaptureSessionOutputContainer. Use + * {@link ACaptureSessionOutput_free} to free the object and its memory after application no longer + * needs the {@link ACaptureSessionOutput}.

+ * + * @param anw the {@link ANativeWindow} to be associated with the {@link ACaptureSessionOutput} + * @param physicalId the Id of the physical camera this output is associated + * with. + * @param output the output {@link ACaptureSessionOutput} will be stored here if the + * method call succeeds. + * + * @return
    + *
  • {@link ACAMERA_OK} if the method call succeeds. The created container will be + * filled in the output argument.
  • + *
  • {@link ACAMERA_ERROR_INVALID_PARAMETER} if anw, physicalId or output is NULL.
+ * + * @see ACaptureSessionOutputContainer_add + */ +camera_status_t ACaptureSessionPhysicalOutput_create( + ACameraWindowType* anw, const char* physicalId, + /*out*/ACaptureSessionOutput** output) __INTRODUCED_IN(29); + +#endif /* __ANDROID_API__ >= 29 */ + __END_DECLS #endif /* _NDK_CAMERA_DEVICE_H */ diff --git a/camera/ndk/include/camera/NdkCameraMetadata.h b/camera/ndk/include/camera/NdkCameraMetadata.h index 611e270e56..9bbfb83fc8 100644 --- a/camera/ndk/include/camera/NdkCameraMetadata.h +++ b/camera/ndk/include/camera/NdkCameraMetadata.h @@ -233,6 +233,28 @@ void ACameraMetadata_free(ACameraMetadata* metadata) __INTRODUCED_IN(24); #endif /* __ANDROID_API__ >= 24 */ +#if __ANDROID_API__ >= 29 + +/** + * Helper function to check if a camera is logical multi-camera. + * + *

Check whether a camera device is a logical multi-camera based on its + * static metadata. If it is, also returns its physical sub camera Ids.

+ * + * @param staticMetadata the static metadata of the camera being checked. + * @param numPhysicalCameras returns the number of physical cameras. + * @param physicalCameraIds returns the array of physical camera Ids backing this logical + * camera device. Note that this pointer is only valid + * during the lifetime of the staticMetadata object. + * + * @return true if this is a logical multi-camera, false otherwise. + */ +bool ACameraMetadata_isLogicalMultiCamera(const ACameraMetadata* staticMetadata, + /*out*/size_t* numPhysicalCameras, /*out*/const char* const** physicalCameraIds) + __INTRODUCED_IN(29); + +#endif /* __ANDROID_API__ >= 29 */ + __END_DECLS #endif /* _NDK_CAMERA_METADATA_H */ diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h index cb474f442f..4bb74cbf6d 100644 --- a/camera/ndk/include/camera/NdkCameraMetadataTags.h +++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h @@ -5551,6 +5551,25 @@ typedef enum acamera_metadata_tag { ACAMERA_DEPTH_START + 5, ACAMERA_DEPTH_END, + /** + *

String containing the ids of the underlying physical cameras.

+ * + *

Type: byte[n]

+ * + *

This tag may appear in: + *

    + *
  • ACameraMetadata from ACameraManager_getCameraCharacteristics
  • + *

+ * + *

For a logical camera, this is concatenation of all underlying physical camera ids. + * The null terminator for physical camera id must be preserved so that the whole string + * can be tokenized using '\0' to generate list of physical camera ids.

+ *

For example, if the physical camera ids of the logical camera are "2" and "3", the + * value of this tag will be ['2', '\0', '3', '\0'].

+ *

The number of physical camera ids must be no less than 2.

+ */ + ACAMERA_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS = // byte[n] + ACAMERA_LOGICAL_MULTI_CAMERA_START, /** *

The accuracy of frame timestamp synchronization between physical cameras

* diff --git a/camera/ndk/libcamera2ndk.map.txt b/camera/ndk/libcamera2ndk.map.txt index a29e96df34..5a0002290a 100644 --- a/camera/ndk/libcamera2ndk.map.txt +++ b/camera/ndk/libcamera2ndk.map.txt @@ -2,9 +2,11 @@ LIBCAMERA2NDK { global: ACameraCaptureSession_abortCaptures; ACameraCaptureSession_capture; + ACameraCaptureSession_logicalCamera_capture; # introduced=29 ACameraCaptureSession_close; ACameraCaptureSession_getDevice; ACameraCaptureSession_setRepeatingRequest; + ACameraCaptureSession_logicalCamera_setRepeatingRequest; # introduced=29 ACameraCaptureSession_stopRepeating; ACameraCaptureSession_updateSharedOutput; # introduced=28 ACameraDevice_close; @@ -24,6 +26,7 @@ LIBCAMERA2NDK { ACameraMetadata_free; ACameraMetadata_getAllTags; ACameraMetadata_getConstEntry; + ACameraMetadata_isLogicalMultiCamera; # introduced=29 ACameraOutputTarget_create; ACameraOutputTarget_free; ACaptureRequest_addTarget; @@ -48,6 +51,7 @@ LIBCAMERA2NDK { ACaptureSessionSharedOutput_create; # introduced=28 ACaptureSessionSharedOutput_add; # introduced=28 ACaptureSessionSharedOutput_remove; # introduced=28 + ACaptureSessionPhysicalOutput_create; # introduced=29 ACaptureSessionOutput_free; local: *; diff --git a/camera/ndk/ndk_vendor/impl/ACameraCaptureSessionVendor.h b/camera/ndk/ndk_vendor/impl/ACameraCaptureSessionVendor.h index 8d9e90cac5..e1af8c1421 100644 --- a/camera/ndk/ndk_vendor/impl/ACameraCaptureSessionVendor.h +++ b/camera/ndk/ndk_vendor/impl/ACameraCaptureSessionVendor.h @@ -14,11 +14,13 @@ * limitations under the License. */ +#include #include "utils.h" struct ACaptureSessionOutput { - explicit ACaptureSessionOutput(native_handle_t* window, bool isShared = false) : - mWindow(window), mIsShared(isShared) {}; + explicit ACaptureSessionOutput(native_handle_t* window, bool isShared = false, + const char* physicalCameraId = "") : + mWindow(window), mIsShared(isShared), mPhysicalCameraId(physicalCameraId) {}; bool operator == (const ACaptureSessionOutput& other) const { return (mWindow == other.mWindow); @@ -40,6 +42,7 @@ struct ACaptureSessionOutput { std::set mSharedWindows; bool mIsShared; int mRotation = CAMERA3_STREAM_ROTATION_0; + std::string mPhysicalCameraId; }; diff --git a/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp b/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp index 26e6b3c50f..f7863a5eb6 100644 --- a/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp +++ b/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp @@ -29,6 +29,8 @@ #include "ACaptureRequest.h" #include "utils.h" +#include "ACameraCaptureSession.inc" + using namespace android; namespace android { @@ -47,6 +49,7 @@ const char* CameraDevice::kSessionSpKey = "SessionSp"; const char* CameraDevice::kCaptureRequestKey = "CaptureRequest"; const char* CameraDevice::kTimeStampKey = "TimeStamp"; const char* CameraDevice::kCaptureResultKey = "CaptureResult"; +const char* CameraDevice::kPhysicalCaptureResultKey = "PhysicalCaptureResult"; const char* CameraDevice::kCaptureFailureKey = "CaptureFailure"; const char* CameraDevice::kSequenceIdKey = "SequenceId"; const char* CameraDevice::kFrameNumberKey = "FrameNumber"; @@ -206,28 +209,8 @@ CameraDevice::createCaptureSession( return ACAMERA_OK; } -camera_status_t -CameraDevice::captureLocked( - sp session, - /*optional*/ACameraCaptureSession_captureCallbacks* cbs, - int numRequests, ACaptureRequest** requests, - /*optional*/int* captureSequenceId) { - return submitRequestsLocked( - session, cbs, numRequests, requests, captureSequenceId, /*isRepeating*/false); -} - -camera_status_t -CameraDevice::setRepeatingRequestsLocked( - sp session, - /*optional*/ACameraCaptureSession_captureCallbacks* cbs, - int numRequests, ACaptureRequest** requests, - /*optional*/int* captureSequenceId) { - return submitRequestsLocked( - session, cbs, numRequests, requests, captureSequenceId, /*isRepeating*/true); -} - -void addRequestSettingsMetadata(ACaptureRequest *aCaptureRequest, - sp &req) { +void CameraDevice::addRequestSettingsMetadata(ACaptureRequest *aCaptureRequest, + sp &req) { CameraMetadata metadataCopy = aCaptureRequest->settings->getInternalData(); const camera_metadata_t *camera_metadata = metadataCopy.getAndLock(); HCameraMetadata hCameraMetadata; @@ -237,101 +220,6 @@ void addRequestSettingsMetadata(ACaptureRequest *aCaptureRequest, req->mPhysicalCameraSettings[0].settings.metadata(std::move(hCameraMetadata)); } -camera_status_t -CameraDevice::submitRequestsLocked( - sp session, - /*optional*/ACameraCaptureSession_captureCallbacks* cbs, - int numRequests, ACaptureRequest** requests, - /*optional*/int* captureSequenceId, - bool isRepeating) { - camera_status_t ret = checkCameraClosedOrErrorLocked(); - if (ret != ACAMERA_OK) { - ALOGE("Camera %s submit capture request failed! ret %d", getId(), ret); - return ret; - } - - // Form two vectors of capture request, one for internal tracking - std::vector requestList; - Vector> requestsV; - requestsV.setCapacity(numRequests); - for (int i = 0; i < numRequests; i++) { - sp req; - ret = allocateCaptureRequest(requests[i], req); - // We need to call this method since after submitRequestList is called, - // the request metadata queue might have removed the capture request - // metadata. Therefore we simply add the metadata to its wrapper class, - // so that it can be retrived later. - addRequestSettingsMetadata(requests[i], req); - if (ret != ACAMERA_OK) { - ALOGE("Convert capture request to internal format failure! ret %d", ret); - return ret; - } - if (req->mCaptureRequest.streamAndWindowIds.size() == 0) { - ALOGE("Capture request without output target cannot be submitted!"); - return ACAMERA_ERROR_INVALID_PARAMETER; - } - requestList.push_back(utils::convertToHidl(req.get())); - requestsV.push_back(req); - } - if (isRepeating) { - ret = stopRepeatingLocked(); - if (ret != ACAMERA_OK) { - ALOGE("Camera %s stop repeating failed! ret %d", getId(), ret); - return ret; - } - } - - SubmitInfo info; - Status status; - auto remoteRet = mRemote->submitRequestList(requestList, isRepeating, - [&status, &info](auto s, auto &submitInfo) { - status = s; - info = submitInfo; - }); - if (!remoteRet.isOk()) { - ALOGE("%s: Transaction error for submitRequestList call: %s", __FUNCTION__, - remoteRet.description().c_str()); - } - if (status != Status::NO_ERROR) { - return utils::convertFromHidl(status); - } - int32_t sequenceId = info.requestId; - int64_t lastFrameNumber = info.lastFrameNumber; - if (sequenceId < 0) { - ALOGE("Camera %s submit request remote failure: ret %d", getId(), sequenceId); - return ACAMERA_ERROR_UNKNOWN; - } - - CallbackHolder cbHolder(session, requestsV, isRepeating, cbs); - mSequenceCallbackMap.insert(std::make_pair(sequenceId, cbHolder)); - - if (isRepeating) { - // stopRepeating above should have cleanup repeating sequence id - if (mRepeatingSequenceId != REQUEST_ID_NONE) { - setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_DEVICE); - return ACAMERA_ERROR_CAMERA_DEVICE; - } - mRepeatingSequenceId = sequenceId; - } else { - mSequenceLastFrameNumberMap.insert(std::make_pair(sequenceId, lastFrameNumber)); - } - - if (mIdle) { - sp msg = new AMessage(kWhatSessionStateCb, mHandler); - msg->setPointer(kContextKey, session->mUserSessionCallback.context); - msg->setObject(kSessionSpKey, session); - msg->setPointer(kCallbackFpKey, (void*) session->mUserSessionCallback.onActive); - postSessionMsgAndCleanup(msg); - } - mIdle = false; - mBusySession = session; - - if (captureSequenceId) { - *captureSequenceId = sequenceId; - } - return ACAMERA_OK; -} - camera_status_t CameraDevice::updateOutputConfigurationLocked(ACaptureSessionOutput *output) { camera_status_t ret = checkCameraClosedOrErrorLocked(); if (ret != ACAMERA_OK) { @@ -365,6 +253,7 @@ camera_status_t CameraDevice::updateOutputConfigurationLocked(ACaptureSessionOut outConfig.windowGroupId = -1; // ndk doesn't support inter OutputConfiguration buffer sharing. outConfig.windowHandles.resize(output->mSharedWindows.size() + 1); outConfig.windowHandles[0] = output->mWindow; + outConfig.physicalCameraId = output->mPhysicalCameraId; int i = 1; for (auto& anw : output->mSharedWindows) { outConfig.windowHandles[i++] = anw; @@ -668,6 +557,7 @@ CameraDevice::configureStreamsLocked(const ACaptureSessionOutputContainer* outpu outConfigInsert.windowGroupId = -1; outConfigInsert.windowHandles.resize(outConfig.mSharedWindows.size() + 1); outConfigInsert.windowHandles[0] = anw; + outConfigInsert.physicalCameraId = outConfig.mPhysicalCameraId; native_handle_ptr_wrapper wrap(anw); outputSet.insert(std::make_pair(anw, outConfigInsertW)); } @@ -894,7 +784,7 @@ CameraDevice::onCaptureErrorLocked( if (errorCode == ErrorCode::CAMERA_BUFFER) { int32_t streamId = resultExtras.errorStreamId; ACameraCaptureSession_captureCallback_bufferLost onBufferLost = - cbh.mCallbacks.onCaptureBufferLost; + cbh.mOnCaptureBufferLost; auto outputPairIt = mConfiguredOutputs.find(streamId); if (outputPairIt == mConfiguredOutputs.end()) { ALOGE("%s: Error: stream id %d does not exist", __FUNCTION__, streamId); @@ -913,7 +803,7 @@ CameraDevice::onCaptureErrorLocked( getId(), anw, frameNumber); sp msg = new AMessage(kWhatCaptureBufferLost, mHandler); - msg->setPointer(kContextKey, cbh.mCallbacks.context); + msg->setPointer(kContextKey, cbh.mContext); msg->setObject(kSessionSpKey, session); msg->setPointer(kCallbackFpKey, (void*) onBufferLost); msg->setObject(kCaptureRequestKey, request); @@ -925,7 +815,7 @@ CameraDevice::onCaptureErrorLocked( } } else { // Handle other capture failures // Fire capture failure callback if there is one registered - ACameraCaptureSession_captureCallback_failed onError = cbh.mCallbacks.onCaptureFailed; + ACameraCaptureSession_captureCallback_failed onError = cbh.mOnCaptureFailed; sp failure(new CameraCaptureFailure()); failure->frameNumber = frameNumber; // TODO: refine this when implementing flush @@ -934,7 +824,7 @@ CameraDevice::onCaptureErrorLocked( failure->wasImageCaptured = (errorCode == ErrorCode::CAMERA_RESULT); sp msg = new AMessage(kWhatCaptureFail, mHandler); - msg->setPointer(kContextKey, cbh.mCallbacks.context); + msg->setPointer(kContextKey, cbh.mContext); msg->setObject(kSessionSpKey, session); msg->setPointer(kCallbackFpKey, (void*) onError); msg->setObject(kCaptureRequestKey, request); @@ -956,6 +846,7 @@ void CameraDevice::CallbackHandler::onMessageReceived( case kWhatSessionStateCb: case kWhatCaptureStart: case kWhatCaptureResult: + case kWhatLogicalCaptureResult: case kWhatCaptureFail: case kWhatCaptureSeqEnd: case kWhatCaptureSeqAbort: @@ -1026,6 +917,7 @@ void CameraDevice::CallbackHandler::onMessageReceived( case kWhatSessionStateCb: case kWhatCaptureStart: case kWhatCaptureResult: + case kWhatLogicalCaptureResult: case kWhatCaptureFail: case kWhatCaptureSeqEnd: case kWhatCaptureSeqAbort: @@ -1043,6 +935,7 @@ void CameraDevice::CallbackHandler::onMessageReceived( switch (msg->what()) { case kWhatCaptureStart: case kWhatCaptureResult: + case kWhatLogicalCaptureResult: case kWhatCaptureFail: case kWhatCaptureBufferLost: found = msg->findObject(kCaptureRequestKey, &obj); @@ -1114,6 +1007,62 @@ void CameraDevice::CallbackHandler::onMessageReceived( freeACaptureRequest(request); break; } + case kWhatLogicalCaptureResult: + { + ACameraCaptureSession_logicalCamera_captureCallback_result onResult; + found = msg->findPointer(kCallbackFpKey, (void**) &onResult); + if (!found) { + ALOGE("%s: Cannot find capture result callback!", __FUNCTION__); + return; + } + if (onResult == nullptr) { + return; + } + + found = msg->findObject(kCaptureResultKey, &obj); + if (!found) { + ALOGE("%s: Cannot find capture result!", __FUNCTION__); + return; + } + sp result(static_cast(obj.get())); + + found = msg->findObject(kPhysicalCaptureResultKey, &obj); + if (!found) { + ALOGE("%s: Cannot find physical capture result!", __FUNCTION__); + return; + } + sp physicalResult( + static_cast(obj.get())); + std::vector& physicalResultInfo = + physicalResult->mPhysicalResultInfo; + + std::vector physicalCameraIds; + std::vector> physicalMetadataCopy; + for (size_t i = 0; i < physicalResultInfo.size(); i++) { + physicalCameraIds.push_back(physicalResultInfo[i].physicalCameraId); + + CameraMetadata clone = physicalResultInfo[i].physicalMetadata; + clone.update(ANDROID_SYNC_FRAME_NUMBER, + &physicalResult->mFrameNumber, /*data_count*/1); + sp metadata = + new ACameraMetadata(clone.release(), ACameraMetadata::ACM_RESULT); + physicalMetadataCopy.push_back(metadata); + } + std::vector physicalCameraIdPtrs; + std::vector physicalMetadataCopyPtrs; + for (size_t i = 0; i < physicalResultInfo.size(); i++) { + physicalCameraIdPtrs.push_back(physicalCameraIds[i].c_str()); + physicalMetadataCopyPtrs.push_back(physicalMetadataCopy[i].get()); + } + + ACaptureRequest* request = allocateACaptureRequest(requestSp); + (*onResult)(context, session.get(), request, result.get(), + physicalResultInfo.size(), physicalCameraIdPtrs.data(), + physicalMetadataCopyPtrs.data()); + freeACaptureRequest(request); + break; + } + case kWhatCaptureFail: { ACameraCaptureSession_captureCallback_failed onFail; @@ -1224,12 +1173,34 @@ void CameraDevice::CallbackHandler::onMessageReceived( } CameraDevice::CallbackHolder::CallbackHolder( - sp session, - const Vector >& requests, - bool isRepeating, - ACameraCaptureSession_captureCallbacks* cbs) : - mSession(session), mRequests(requests), - mIsRepeating(isRepeating), mCallbacks(fillCb(cbs)) {} + sp session, + const Vector >& requests, + bool isRepeating, + ACameraCaptureSession_captureCallbacks* cbs) : + mSession(session), mRequests(requests), + mIsRepeating(isRepeating), + mIsLogicalCameraCallback(false) { + initCaptureCallbacks(cbs); + + if (cbs != nullptr) { + mOnCaptureCompleted = cbs->onCaptureCompleted; + } +} + +CameraDevice::CallbackHolder::CallbackHolder( + sp session, + const Vector >& requests, + bool isRepeating, + ACameraCaptureSession_logicalCamera_captureCallbacks* lcbs) : + mSession(session), mRequests(requests), + mIsRepeating(isRepeating), + mIsLogicalCameraCallback(true) { + initCaptureCallbacks(lcbs); + + if (lcbs != nullptr) { + mOnLogicalCameraCaptureCompleted = lcbs->onLogicalCameraCaptureCompleted; + } +} void CameraDevice::checkRepeatingSequenceCompleteLocked( @@ -1246,9 +1217,9 @@ CameraDevice::checkRepeatingSequenceCompleteLocked( mSequenceCallbackMap.erase(cbIt); // send seq aborted callback sp msg = new AMessage(kWhatCaptureSeqAbort, mHandler); - msg->setPointer(kContextKey, cbh.mCallbacks.context); + msg->setPointer(kContextKey, cbh.mContext); msg->setObject(kSessionSpKey, cbh.mSession); - msg->setPointer(kCallbackFpKey, (void*) cbh.mCallbacks.onCaptureSequenceAborted); + msg->setPointer(kCallbackFpKey, (void*) cbh.mOnCaptureSequenceAborted); msg->setInt32(kSequenceIdKey, sequenceId); postSessionMsgAndCleanup(msg); } else { @@ -1295,9 +1266,9 @@ CameraDevice::checkAndFireSequenceCompleteLocked() { mSequenceCallbackMap.erase(cbIt); // send seq complete callback sp msg = new AMessage(kWhatCaptureSeqEnd, mHandler); - msg->setPointer(kContextKey, cbh.mCallbacks.context); + msg->setPointer(kContextKey, cbh.mContext); msg->setObject(kSessionSpKey, cbh.mSession); - msg->setPointer(kCallbackFpKey, (void*) cbh.mCallbacks.onCaptureSequenceCompleted); + msg->setPointer(kCallbackFpKey, (void*) cbh.mOnCaptureSequenceCompleted); msg->setInt32(kSequenceIdKey, sequenceId); msg->setInt64(kFrameNumberKey, lastFrameNumber); @@ -1454,7 +1425,7 @@ CameraDevice::ServiceCallback::onCaptureStarted( auto it = dev->mSequenceCallbackMap.find(sequenceId); if (it != dev->mSequenceCallbackMap.end()) { CallbackHolder cbh = (*it).second; - ACameraCaptureSession_captureCallback_start onStart = cbh.mCallbacks.onCaptureStarted; + ACameraCaptureSession_captureCallback_start onStart = cbh.mOnCaptureStarted; sp session = cbh.mSession; if ((size_t) burstId >= cbh.mRequests.size()) { ALOGE("%s: Error: request index %d out of bound (size %zu)", @@ -1463,7 +1434,7 @@ CameraDevice::ServiceCallback::onCaptureStarted( } sp request = cbh.mRequests[burstId]; sp msg = new AMessage(kWhatCaptureStart, dev->mHandler); - msg->setPointer(kContextKey, cbh.mCallbacks.context); + msg->setPointer(kContextKey, cbh.mContext); msg->setObject(kSessionSpKey, session); msg->setPointer(kCallbackFpKey, (void*) onStart); msg->setObject(kCaptureRequestKey, request); @@ -1478,7 +1449,6 @@ CameraDevice::ServiceCallback::onResultReceived( const FmqSizeOrMetadata& resultMetadata, const CaptureResultExtras& resultExtras, const hidl_vec& physicalResultInfos) { - (void) physicalResultInfos; auto ret = Void(); sp dev = mDevice.promote(); @@ -1508,27 +1478,10 @@ CameraDevice::ServiceCallback::onResultReceived( } CameraMetadata metadataCopy; - HCameraMetadata hCameraMetadata; - bool converted = false; - if (resultMetadata.getDiscriminator() == - FmqSizeOrMetadata::hidl_discriminator::fmqMetadataSize) { - hCameraMetadata.resize(resultMetadata.fmqMetadataSize()); - bool read = dev->mCaptureResultMetadataQueue->read(hCameraMetadata.data(), - resultMetadata.fmqMetadataSize()); - if (!read) { - ALOGE("%s capture request settings could't be read from fmq", - __FUNCTION__); - return ret; - } - // TODO: Do we actually need to clone here ? - converted = utils::convertFromHidlCloned(hCameraMetadata, &metadataCopy); - - } else { - converted = utils::convertFromHidlCloned(resultMetadata.metadata(), &metadataCopy); - } - - if (!converted) { - ALOGE("%s result metadata couldn't be converted", __FUNCTION__); + camera_status_t status = readOneResultMetadata(resultMetadata, + dev->mCaptureResultMetadataQueue.get(), &metadataCopy); + if (status != ACAMERA_OK) { + ALOGE("%s: result metadata couldn't be converted", __FUNCTION__); return ret; } @@ -1538,9 +1491,6 @@ CameraDevice::ServiceCallback::onResultReceived( auto it = dev->mSequenceCallbackMap.find(sequenceId); if (it != dev->mSequenceCallbackMap.end()) { CallbackHolder cbh = (*it).second; - ACameraCaptureSession_captureCallback_result onResult = isPartialResult ? - cbh.mCallbacks.onCaptureProgressed : - cbh.mCallbacks.onCaptureCompleted; sp session = cbh.mSession; if ((size_t) burstId >= cbh.mRequests.size()) { ALOGE("%s: Error: request index %d out of bound (size %zu)", @@ -1551,12 +1501,39 @@ CameraDevice::ServiceCallback::onResultReceived( sp result(new ACameraMetadata( metadataCopy.release(), ACameraMetadata::ACM_RESULT)); - sp msg = new AMessage(kWhatCaptureResult, dev->mHandler); - msg->setPointer(kContextKey, cbh.mCallbacks.context); + std::vector localPhysicalResult; + localPhysicalResult.resize(physicalResultInfos.size()); + for (size_t i = 0; i < physicalResultInfos.size(); i++) { + localPhysicalResult[i].physicalCameraId = physicalResultInfos[i].physicalCameraId; + status = readOneResultMetadata(physicalResultInfos[i].physicalCameraMetadata, + dev->mCaptureResultMetadataQueue.get(), + &localPhysicalResult[i].physicalMetadata); + if (status != ACAMERA_OK) { + ALOGE("%s: physical camera result metadata couldn't be converted", __FUNCTION__); + return ret; + } + } + sp physicalResult( + new ACameraPhysicalCaptureResultInfo(localPhysicalResult, frameNumber)); + + sp msg = new AMessage( + cbh.mIsLogicalCameraCallback ? kWhatLogicalCaptureResult : kWhatCaptureResult, + dev->mHandler); + msg->setPointer(kContextKey, cbh.mContext); msg->setObject(kSessionSpKey, session); - msg->setPointer(kCallbackFpKey, (void*) onResult); msg->setObject(kCaptureRequestKey, request); msg->setObject(kCaptureResultKey, result); + if (isPartialResult) { + msg->setPointer(kCallbackFpKey, + (void *)cbh.mOnCaptureProgressed); + } else if (cbh.mIsLogicalCameraCallback) { + msg->setPointer(kCallbackFpKey, + (void *)cbh.mOnLogicalCameraCaptureCompleted); + msg->setObject(kPhysicalCaptureResultKey, physicalResult); + } else { + msg->setPointer(kCallbackFpKey, + (void *)cbh.mOnCaptureCompleted); + } dev->postSessionMsgAndCleanup(msg); } @@ -1590,5 +1567,31 @@ CameraDevice::ServiceCallback::onRepeatingRequestError( return ret; } +camera_status_t CameraDevice::ServiceCallback::readOneResultMetadata( + const FmqSizeOrMetadata& fmqSizeOrMetadata, ResultMetadataQueue* metadataQueue, + CameraMetadata* metadata) { + if (metadataQueue == nullptr || metadata == nullptr) { + return ACAMERA_ERROR_INVALID_PARAMETER; + } + bool converted; + HCameraMetadata hCameraMetadata; + if (fmqSizeOrMetadata.getDiscriminator() == + FmqSizeOrMetadata::hidl_discriminator::fmqMetadataSize) { + hCameraMetadata.resize(fmqSizeOrMetadata.fmqMetadataSize()); + bool read = metadataQueue->read( + hCameraMetadata.data(), fmqSizeOrMetadata.fmqMetadataSize()); + if (!read) { + ALOGE("%s capture request settings could't be read from fmq", __FUNCTION__); + return ACAMERA_ERROR_UNKNOWN; + } + // TODO: Do we actually need to clone here ? + converted = utils::convertFromHidlCloned(hCameraMetadata, metadata); + } else { + converted = utils::convertFromHidlCloned(fmqSizeOrMetadata.metadata(), metadata); + } + + return converted ? ACAMERA_OK : ACAMERA_ERROR_UNKNOWN; +} + } // namespace acam } // namespace android diff --git a/camera/ndk/ndk_vendor/impl/ACameraDevice.h b/camera/ndk/ndk_vendor/impl/ACameraDevice.h index 01a219f01a..c63b97fc0c 100644 --- a/camera/ndk/ndk_vendor/impl/ACameraDevice.h +++ b/camera/ndk/ndk_vendor/impl/ACameraDevice.h @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -65,6 +66,21 @@ using utils::OutputConfigurationWrapper; // Wrap ACameraCaptureFailure so it can be ref-counted struct CameraCaptureFailure : public RefBase, public ACameraCaptureFailure { }; +// Wrap PhysicalCaptureResultInfo so that it can be ref-counted +struct PhysicalCaptureResultInfoLocal { + std::string physicalCameraId; + CameraMetadata physicalMetadata; +}; + +struct ACameraPhysicalCaptureResultInfo: public RefBase { + ACameraPhysicalCaptureResultInfo(const std::vector& info, + int64_t frameNumber) : + mPhysicalResultInfo(info), mFrameNumber(frameNumber) {} + + std::vector mPhysicalResultInfo; + int64_t mFrameNumber; +}; + class CameraDevice final : public RefBase { public: CameraDevice(const char* id, ACameraDevice_StateCallbacks* cb, @@ -99,6 +115,8 @@ class CameraDevice final : public RefBase { android::hardware::Return onRepeatingRequestError(uint64_t lastFrameNumber, int32_t stoppedSequenceId) override; private: + camera_status_t readOneResultMetadata(const FmqSizeOrMetadata& fmqSizeOrMetadata, + ResultMetadataQueue* metadataQueue, CameraMetadata* metadata); const wp mDevice; }; inline sp getServiceCallback() { @@ -127,24 +145,28 @@ class CameraDevice final : public RefBase { camera_status_t waitUntilIdleLocked(); - + template camera_status_t captureLocked(sp session, - /*optional*/ACameraCaptureSession_captureCallbacks* cbs, + /*optional*/T* cbs, int numRequests, ACaptureRequest** requests, /*optional*/int* captureSequenceId); + template camera_status_t setRepeatingRequestsLocked(sp session, - /*optional*/ACameraCaptureSession_captureCallbacks* cbs, + /*optional*/T* cbs, int numRequests, ACaptureRequest** requests, /*optional*/int* captureSequenceId); + template camera_status_t submitRequestsLocked( sp session, - /*optional*/ACameraCaptureSession_captureCallbacks* cbs, + /*optional*/T* cbs, int numRequests, ACaptureRequest** requests, /*out*/int* captureSequenceId, bool isRepeating); + void addRequestSettingsMetadata(ACaptureRequest *aCaptureRequest, sp &req); + camera_status_t updateOutputConfigurationLocked(ACaptureSessionOutput *output); camera_status_t allocateCaptureRequest( @@ -206,6 +228,7 @@ class CameraDevice final : public RefBase { // Capture callbacks kWhatCaptureStart, // onCaptureStarted kWhatCaptureResult, // onCaptureProgressed, onCaptureCompleted + kWhatLogicalCaptureResult, // onLogicalCameraCaptureCompleted kWhatCaptureFail, // onCaptureFailed kWhatCaptureSeqEnd, // onCaptureSequenceCompleted kWhatCaptureSeqAbort, // onCaptureSequenceAborted @@ -221,6 +244,7 @@ class CameraDevice final : public RefBase { static const char* kCaptureRequestKey; static const char* kTimeStampKey; static const char* kCaptureResultKey; + static const char* kPhysicalCaptureResultKey; static const char* kCaptureFailureKey; static const char* kSequenceIdKey; static const char* kFrameNumberKey; @@ -259,19 +283,47 @@ class CameraDevice final : public RefBase { const Vector>& requests, bool isRepeating, ACameraCaptureSession_captureCallbacks* cbs); - - static ACameraCaptureSession_captureCallbacks fillCb( - ACameraCaptureSession_captureCallbacks* cbs) { + CallbackHolder(sp session, + const Vector>& requests, + bool isRepeating, + ACameraCaptureSession_logicalCamera_captureCallbacks* lcbs); + + template + void initCaptureCallbacks(T* cbs) { + mContext = nullptr; + mOnCaptureStarted = nullptr; + mOnCaptureProgressed = nullptr; + mOnCaptureCompleted = nullptr; + mOnLogicalCameraCaptureCompleted = nullptr; + mOnCaptureFailed = nullptr; + mOnCaptureSequenceCompleted = nullptr; + mOnCaptureSequenceAborted = nullptr; + mOnCaptureBufferLost = nullptr; if (cbs != nullptr) { - return *cbs; + mContext = cbs->context; + mOnCaptureStarted = cbs->onCaptureStarted; + mOnCaptureProgressed = cbs->onCaptureProgressed; + mOnCaptureFailed = cbs->onCaptureFailed; + mOnCaptureSequenceCompleted = cbs->onCaptureSequenceCompleted; + mOnCaptureSequenceAborted = cbs->onCaptureSequenceAborted; + mOnCaptureBufferLost = cbs->onCaptureBufferLost; } - return { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr }; } sp mSession; - Vector> mRequests; + Vector> mRequests; const bool mIsRepeating; - ACameraCaptureSession_captureCallbacks mCallbacks; + const bool mIsLogicalCameraCallback; + + void* mContext; + ACameraCaptureSession_captureCallback_start mOnCaptureStarted; + ACameraCaptureSession_captureCallback_result mOnCaptureProgressed; + ACameraCaptureSession_captureCallback_result mOnCaptureCompleted; + ACameraCaptureSession_logicalCamera_captureCallback_result mOnLogicalCameraCaptureCompleted; + ACameraCaptureSession_captureCallback_failed mOnCaptureFailed; + ACameraCaptureSession_captureCallback_sequenceEnd mOnCaptureSequenceCompleted; + ACameraCaptureSession_captureCallback_sequenceAbort mOnCaptureSequenceAborted; + ACameraCaptureSession_captureCallback_bufferLost mOnCaptureBufferLost; }; // sequence id -> callbacks map std::map mSequenceCallbackMap; diff --git a/camera/ndk/ndk_vendor/impl/ACameraDeviceVendor.inc b/camera/ndk/ndk_vendor/impl/ACameraDeviceVendor.inc new file mode 100644 index 0000000000..7d2304e63e --- /dev/null +++ b/camera/ndk/ndk_vendor/impl/ACameraDeviceVendor.inc @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include + +#include "ndk_vendor/impl/ACameraDevice.h" +#include "ACameraCaptureSession.h" +#include "ACameraMetadata.h" +#include "ACaptureRequest.h" +#include "utils.h" + +using namespace android; + +namespace android { +namespace acam { + +template +camera_status_t +CameraDevice::captureLocked( + sp session, + /*optional*/T* cbs, + int numRequests, ACaptureRequest** requests, + /*optional*/int* captureSequenceId) { + return submitRequestsLocked( + session, cbs, numRequests, requests, captureSequenceId, /*isRepeating*/false); +} + +template +camera_status_t +CameraDevice::setRepeatingRequestsLocked( + sp session, + /*optional*/T* cbs, + int numRequests, ACaptureRequest** requests, + /*optional*/int* captureSequenceId) { + return submitRequestsLocked( + session, cbs, numRequests, requests, captureSequenceId, /*isRepeating*/true); +} + +template +camera_status_t CameraDevice::submitRequestsLocked( + sp session, + /*optional*/T* cbs, + int numRequests, ACaptureRequest** requests, + /*out*/int* captureSequenceId, + bool isRepeating) +{ + camera_status_t ret = checkCameraClosedOrErrorLocked(); + if (ret != ACAMERA_OK) { + ALOGE("Camera %s submit capture request failed! ret %d", getId(), ret); + return ret; + } + + // Form two vectors of capture request, one for internal tracking + std::vector requestList; + Vector> requestsV; + requestsV.setCapacity(numRequests); + for (int i = 0; i < numRequests; i++) { + sp req; + ret = allocateCaptureRequest(requests[i], req); + // We need to call this method since after submitRequestList is called, + // the request metadata queue might have removed the capture request + // metadata. Therefore we simply add the metadata to its wrapper class, + // so that it can be retrieved later. + addRequestSettingsMetadata(requests[i], req); + if (ret != ACAMERA_OK) { + ALOGE("Convert capture request to internal format failure! ret %d", ret); + return ret; + } + if (req->mCaptureRequest.streamAndWindowIds.size() == 0) { + ALOGE("Capture request without output target cannot be submitted!"); + return ACAMERA_ERROR_INVALID_PARAMETER; + } + requestList.push_back(utils::convertToHidl(req.get())); + requestsV.push_back(req); + } + if (isRepeating) { + ret = stopRepeatingLocked(); + if (ret != ACAMERA_OK) { + ALOGE("Camera %s stop repeating failed! ret %d", getId(), ret); + return ret; + } + } + + SubmitInfo info; + Status status; + auto remoteRet = mRemote->submitRequestList(requestList, isRepeating, + [&status, &info](auto s, auto &submitInfo) { + status = s; + info = submitInfo; + }); + if (!remoteRet.isOk()) { + ALOGE("%s: Transaction error for submitRequestList call: %s", __FUNCTION__, + remoteRet.description().c_str()); + } + if (status != Status::NO_ERROR) { + return utils::convertFromHidl(status); + } + int32_t sequenceId = info.requestId; + int64_t lastFrameNumber = info.lastFrameNumber; + if (sequenceId < 0) { + ALOGE("Camera %s submit request remote failure: ret %d", getId(), sequenceId); + return ACAMERA_ERROR_UNKNOWN; + } + + CallbackHolder cbHolder(session, requestsV, isRepeating, cbs); + mSequenceCallbackMap.insert(std::make_pair(sequenceId, cbHolder)); + if (isRepeating) { + // stopRepeating above should have cleanup repeating sequence id + if (mRepeatingSequenceId != REQUEST_ID_NONE) { + setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_DEVICE); + return ACAMERA_ERROR_CAMERA_DEVICE; + } + mRepeatingSequenceId = sequenceId; + } else { + mSequenceLastFrameNumberMap.insert(std::make_pair(sequenceId, lastFrameNumber)); + } + + if (mIdle) { + sp msg = new AMessage(kWhatSessionStateCb, mHandler); + msg->setPointer(kContextKey, session->mUserSessionCallback.context); + msg->setObject(kSessionSpKey, session); + msg->setPointer(kCallbackFpKey, (void*) session->mUserSessionCallback.onActive); + postSessionMsgAndCleanup(msg); + } + mIdle = false; + mBusySession = session; + + if (captureSequenceId) { + *captureSequenceId = sequenceId; + } + return ACAMERA_OK; +} + +} // namespace acam +} // namespace android diff --git a/camera/tests/CameraBinderTests.cpp b/camera/tests/CameraBinderTests.cpp index fa8a7a360a..8534b289ea 100644 --- a/camera/tests/CameraBinderTests.cpp +++ b/camera/tests/CameraBinderTests.cpp @@ -480,7 +480,8 @@ TEST_F(CameraClientBinderTest, CheckBinderCameraDeviceUser) { sp surface(new Surface(gbProducer, /*controlledByApp*/false)); - OutputConfiguration output(gbProducer, /*rotation*/0); + String16 noPhysicalId; + OutputConfiguration output(gbProducer, /*rotation*/0, noPhysicalId); // Can we configure? res = device->beginConfigure(); diff --git a/services/camera/libcameraservice/hidl/AidlCameraDeviceCallbacks.cpp b/services/camera/libcameraservice/hidl/AidlCameraDeviceCallbacks.cpp index e5e5024204..f063506d4b 100644 --- a/services/camera/libcameraservice/hidl/AidlCameraDeviceCallbacks.cpp +++ b/services/camera/libcameraservice/hidl/AidlCameraDeviceCallbacks.cpp @@ -139,18 +139,18 @@ void H2BCameraDeviceCallbacks::CallbackHandler::processResultMessage( } CameraMetadataNative &result = resultWrapper->mResult; auto resultExtras = resultWrapper->mResultExtras; - auto &physicalCaptureResultInfos = resultWrapper->mPhysicalCaptureResultInfos; HCaptureResultExtras hResultExtras = hardware::cameraservice::utils::conversion::convertToHidl(resultExtras); - hidl_vec hPhysicalCaptureResultInfos = - hardware::cameraservice::utils::conversion::convertToHidl( - physicalCaptureResultInfos, converter->mCaptureResultMetadataQueue); // Convert Metadata into HCameraMetadata; FmqSizeOrMetadata hResult; const camera_metadata_t *rawMetadata = result.getAndLock(); converter->convertResultMetadataToHidl(rawMetadata, &hResult); result.unlock(rawMetadata); + auto &physicalCaptureResultInfos = resultWrapper->mPhysicalCaptureResultInfos; + hidl_vec hPhysicalCaptureResultInfos = + hardware::cameraservice::utils::conversion::convertToHidl( + physicalCaptureResultInfos, converter->mCaptureResultMetadataQueue); auto ret = converter->mBase->onResultReceived(hResult, hResultExtras, hPhysicalCaptureResultInfos); if (!ret.isOk()) { diff --git a/services/camera/libcameraservice/hidl/Convert.cpp b/services/camera/libcameraservice/hidl/Convert.cpp index 582ce347f9..a87812b6b4 100644 --- a/services/camera/libcameraservice/hidl/Convert.cpp +++ b/services/camera/libcameraservice/hidl/Convert.cpp @@ -89,8 +89,9 @@ hardware::camera2::params::OutputConfiguration convertFromHidl( for (auto &handle : windowHandles) { iGBPs.push_back(new H2BGraphicBufferProducer(AImageReader_getHGBPFromHandle(handle))); } + String16 physicalCameraId16(hOutputConfiguration.physicalCameraId.c_str()); hardware::camera2::params::OutputConfiguration outputConfiguration( - iGBPs, convertFromHidl(hOutputConfiguration.rotation), + iGBPs, convertFromHidl(hOutputConfiguration.rotation), physicalCameraId16, hOutputConfiguration.windowGroupId, OutputConfiguration::SURFACE_TYPE_UNKNOWN, 0, 0, (windowHandles.size() > 1)); return outputConfiguration;