diff options
Diffstat (limited to 'camera/device')
-rw-r--r-- | camera/device/3.2/default/CameraDeviceSession.cpp | 99 | ||||
-rw-r--r-- | camera/device/3.2/default/CameraDeviceSession.h | 28 | ||||
-rw-r--r-- | camera/device/3.4/Android.bp | 6 | ||||
-rw-r--r-- | camera/device/3.4/ICameraDeviceCallback.hal | 43 | ||||
-rw-r--r-- | camera/device/3.4/ICameraDeviceSession.hal | 38 | ||||
-rw-r--r-- | camera/device/3.4/default/CameraDeviceSession.cpp | 272 | ||||
-rw-r--r-- | camera/device/3.4/default/ExternalCameraDevice.cpp | 3 | ||||
-rw-r--r-- | camera/device/3.4/default/ExternalCameraDeviceSession.cpp | 71 | ||||
-rw-r--r-- | camera/device/3.4/default/include/device_v3_4_impl/CameraDeviceSession.h | 30 | ||||
-rw-r--r-- | camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h | 19 | ||||
-rw-r--r-- | camera/device/3.4/types.hal | 96 |
11 files changed, 622 insertions, 83 deletions
diff --git a/camera/device/3.2/default/CameraDeviceSession.cpp b/camera/device/3.2/default/CameraDeviceSession.cpp index 31b47392e..975fb0134 100644 --- a/camera/device/3.2/default/CameraDeviceSession.cpp +++ b/camera/device/3.2/default/CameraDeviceSession.cpp @@ -738,8 +738,14 @@ void CameraDeviceSession::ResultBatcher::processCaptureResult(CaptureResult& res // Methods from ::android::hardware::camera::device::V3_2::ICameraDeviceSession follow. Return<void> CameraDeviceSession::constructDefaultRequestSettings( RequestTemplate type, ICameraDeviceSession::constructDefaultRequestSettings_cb _hidl_cb) { - Status status = initStatus(); CameraMetadata outMetadata; + Status status = constructDefaultRequestSettingsRaw( (int) type, &outMetadata); + _hidl_cb(status, outMetadata); + return Void(); +} + +Status CameraDeviceSession::constructDefaultRequestSettingsRaw(int type, CameraMetadata *outMetadata) { + Status status = initStatus(); const camera_metadata_t *rawRequest; if (status == Status::OK) { ATRACE_BEGIN("camera3->construct_default_request_settings"); @@ -761,15 +767,14 @@ Return<void> CameraDeviceSession::constructDefaultRequestSettings( defaultBoost, 1); const camera_metadata_t *metaBuffer = mOverridenRequest.getAndLock(); - convertToHidl(metaBuffer, &outMetadata); + convertToHidl(metaBuffer, outMetadata); mOverridenRequest.unlock(metaBuffer); } else { - convertToHidl(rawRequest, &outMetadata); + convertToHidl(rawRequest, outMetadata); } } } - _hidl_cb(status, outMetadata); - return Void(); + return status; } /** @@ -1193,26 +1198,19 @@ Return<void> CameraDeviceSession::close() { return Void(); } -/** - * Static callback forwarding methods from HAL to instance - */ -void CameraDeviceSession::sProcessCaptureResult( - const camera3_callback_ops *cb, - const camera3_capture_result *hal_result) { - CameraDeviceSession *d = - const_cast<CameraDeviceSession*>(static_cast<const CameraDeviceSession*>(cb)); - +void CameraDeviceSession::constructCaptureResult(CaptureResult& result, + const camera3_capture_result *hal_result) { uint32_t frameNumber = hal_result->frame_number; bool hasInputBuf = (hal_result->input_buffer != nullptr); size_t numOutputBufs = hal_result->num_output_buffers; size_t numBufs = numOutputBufs + (hasInputBuf ? 1 : 0); if (numBufs > 0) { - Mutex::Autolock _l(d->mInflightLock); + Mutex::Autolock _l(mInflightLock); if (hasInputBuf) { int streamId = static_cast<Camera3Stream*>(hal_result->input_buffer->stream)->mId; // validate if buffer is inflight auto key = std::make_pair(streamId, frameNumber); - if (d->mInflightBuffers.count(key) != 1) { + if (mInflightBuffers.count(key) != 1) { ALOGE("%s: input buffer for stream %d frame %d is not inflight!", __FUNCTION__, streamId, frameNumber); return; @@ -1223,7 +1221,7 @@ void CameraDeviceSession::sProcessCaptureResult( int streamId = static_cast<Camera3Stream*>(hal_result->output_buffers[i].stream)->mId; // validate if buffer is inflight auto key = std::make_pair(streamId, frameNumber); - if (d->mInflightBuffers.count(key) != 1) { + if (mInflightBuffers.count(key) != 1) { ALOGE("%s: output buffer for stream %d frame %d is not inflight!", __FUNCTION__, streamId, frameNumber); return; @@ -1232,64 +1230,63 @@ void CameraDeviceSession::sProcessCaptureResult( } // We don't need to validate/import fences here since we will be passing them to camera service // within the scope of this function - CaptureResult result; result.frameNumber = frameNumber; result.fmqResultSize = 0; result.partialResult = hal_result->partial_result; convertToHidl(hal_result->result, &result.result); if (nullptr != hal_result->result) { bool resultOverriden = false; - Mutex::Autolock _l(d->mInflightLock); + Mutex::Autolock _l(mInflightLock); // Derive some new keys for backward compatibility - if (d->mDerivePostRawSensKey) { + if (mDerivePostRawSensKey) { camera_metadata_ro_entry entry; if (find_camera_metadata_ro_entry(hal_result->result, ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST, &entry) == 0) { - d->mInflightRawBoostPresent[frameNumber] = true; + mInflightRawBoostPresent[frameNumber] = true; } else { - auto entry = d->mInflightRawBoostPresent.find(frameNumber); - if (d->mInflightRawBoostPresent.end() == entry) { - d->mInflightRawBoostPresent[frameNumber] = false; + auto entry = mInflightRawBoostPresent.find(frameNumber); + if (mInflightRawBoostPresent.end() == entry) { + mInflightRawBoostPresent[frameNumber] = false; } } - if ((hal_result->partial_result == d->mNumPartialResults)) { - if (!d->mInflightRawBoostPresent[frameNumber]) { + if ((hal_result->partial_result == mNumPartialResults)) { + if (!mInflightRawBoostPresent[frameNumber]) { if (!resultOverriden) { - d->mOverridenResult.clear(); - d->mOverridenResult.append(hal_result->result); + mOverridenResult.clear(); + mOverridenResult.append(hal_result->result); resultOverriden = true; } int32_t defaultBoost[1] = {100}; - d->mOverridenResult.update( + mOverridenResult.update( ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST, defaultBoost, 1); } - d->mInflightRawBoostPresent.erase(frameNumber); + mInflightRawBoostPresent.erase(frameNumber); } } - auto entry = d->mInflightAETriggerOverrides.find(frameNumber); - if (d->mInflightAETriggerOverrides.end() != entry) { + auto entry = mInflightAETriggerOverrides.find(frameNumber); + if (mInflightAETriggerOverrides.end() != entry) { if (!resultOverriden) { - d->mOverridenResult.clear(); - d->mOverridenResult.append(hal_result->result); + mOverridenResult.clear(); + mOverridenResult.append(hal_result->result); resultOverriden = true; } - d->overrideResultForPrecaptureCancelLocked(entry->second, - &d->mOverridenResult); - if (hal_result->partial_result == d->mNumPartialResults) { - d->mInflightAETriggerOverrides.erase(frameNumber); + overrideResultForPrecaptureCancelLocked(entry->second, + &mOverridenResult); + if (hal_result->partial_result == mNumPartialResults) { + mInflightAETriggerOverrides.erase(frameNumber); } } if (resultOverriden) { const camera_metadata_t *metaBuffer = - d->mOverridenResult.getAndLock(); + mOverridenResult.getAndLock(); convertToHidl(metaBuffer, &result.result); - d->mOverridenResult.unlock(metaBuffer); + mOverridenResult.unlock(metaBuffer); } } if (hasInputBuf) { @@ -1330,24 +1327,38 @@ void CameraDeviceSession::sProcessCaptureResult( // configure_streams right after the processCaptureResult call so we need to finish // updating inflight queues first if (numBufs > 0) { - Mutex::Autolock _l(d->mInflightLock); + Mutex::Autolock _l(mInflightLock); if (hasInputBuf) { int streamId = static_cast<Camera3Stream*>(hal_result->input_buffer->stream)->mId; auto key = std::make_pair(streamId, frameNumber); - d->mInflightBuffers.erase(key); + mInflightBuffers.erase(key); } for (size_t i = 0; i < numOutputBufs; i++) { int streamId = static_cast<Camera3Stream*>(hal_result->output_buffers[i].stream)->mId; auto key = std::make_pair(streamId, frameNumber); - d->mInflightBuffers.erase(key); + mInflightBuffers.erase(key); } - if (d->mInflightBuffers.empty()) { + if (mInflightBuffers.empty()) { ALOGV("%s: inflight buffer queue is now empty!", __FUNCTION__); } } +} + +/** + * Static callback forwarding methods from HAL to instance + */ +void CameraDeviceSession::sProcessCaptureResult( + const camera3_callback_ops *cb, + const camera3_capture_result *hal_result) { + CameraDeviceSession *d = + const_cast<CameraDeviceSession*>(static_cast<const CameraDeviceSession*>(cb)); + + CaptureResult result; + d->constructCaptureResult(result, hal_result); + d->mResultBatcher.processCaptureResult(result); } diff --git a/camera/device/3.2/default/CameraDeviceSession.h b/camera/device/3.2/default/CameraDeviceSession.h index 0048ef49b..61db67106 100644 --- a/camera/device/3.2/default/CameraDeviceSession.h +++ b/camera/device/3.2/default/CameraDeviceSession.h @@ -112,7 +112,9 @@ protected: Return<Status> flush(); Return<void> close(); - //Helper methods + // Helper methods + Status constructDefaultRequestSettingsRaw(int type, CameraMetadata *outMetadata); + bool preProcessConfigurationLocked(const StreamConfiguration& requestedConfiguration, camera3_stream_configuration_t *stream_list /*out*/, hidl_vec<camera3_stream_t*> *streams /*out*/); @@ -188,7 +190,7 @@ protected: void notify(NotifyMsg& msg); void processCaptureResult(CaptureResult& result); - private: + protected: struct InflightBatch { // Protect access to entire struct. Acquire this lock before read/write any data or // calling any methods. processCaptureResult and notify will compete for this lock @@ -233,7 +235,6 @@ protected: bool mRemoved = false; }; - static const int NOT_BATCHED = -1; // Get the batch index and pointer to InflightBatch (nullptrt if the frame is not batched) // Caller must acquire the InflightBatch::mLock before accessing the InflightBatch @@ -243,6 +244,16 @@ protected: // This method will hold ResultBatcher::mLock briefly std::pair<int, std::shared_ptr<InflightBatch>> getBatch(uint32_t frameNumber); + static const int NOT_BATCHED = -1; + + // move/push function avoids "hidl_handle& operator=(hidl_handle&)", which clones native + // handle + void moveStreamBuffer(StreamBuffer&& src, StreamBuffer& dst); + void pushStreamBuffer(StreamBuffer&& src, std::vector<StreamBuffer>& dst); + + void sendBatchMetadataLocked( + std::shared_ptr<InflightBatch> batch, uint32_t lastPartialResultIdx); + // Check if the first batch in mInflightBatches is ready to be removed, and remove it if so // This method will hold ResultBatcher::mLock briefly void checkAndRemoveFirstBatch(); @@ -255,9 +266,7 @@ protected: // send buffers for specified streams void sendBatchBuffersLocked( std::shared_ptr<InflightBatch> batch, const std::vector<int>& streams); - void sendBatchMetadataLocked( - std::shared_ptr<InflightBatch> batch, uint32_t lastPartialResultIdx); - // End of sendXXXX methods + // End of sendXXXX methods // helper methods void freeReleaseFences(hidl_vec<CaptureResult>&); @@ -265,11 +274,6 @@ protected: void processOneCaptureResult(CaptureResult& result); void invokeProcessCaptureResultCallback(hidl_vec<CaptureResult> &results, bool tryWriteFmq); - // move/push function avoids "hidl_handle& operator=(hidl_handle&)", which clones native - // handle - void moveStreamBuffer(StreamBuffer&& src, StreamBuffer& dst); - void pushStreamBuffer(StreamBuffer&& src, std::vector<StreamBuffer>& dst); - // Protect access to mInflightBatches, mNumPartialResults and mStreamsToBatch // processCaptureRequest, processCaptureResult, notify will compete for this lock // Do NOT issue HIDL IPCs while holding this lock (except when HAL reports error) @@ -323,6 +327,8 @@ protected: static callbacks_process_capture_result_t sProcessCaptureResult; static callbacks_notify_t sNotify; + void constructCaptureResult(CaptureResult& result, + const camera3_capture_result *hal_result); private: struct TrampolineSessionInterface_3_2 : public ICameraDeviceSession { diff --git a/camera/device/3.4/Android.bp b/camera/device/3.4/Android.bp index 67b79b987..87acd2556 100644 --- a/camera/device/3.4/Android.bp +++ b/camera/device/3.4/Android.bp @@ -8,6 +8,7 @@ hidl_interface { }, srcs: [ "types.hal", + "ICameraDeviceCallback.hal", "ICameraDeviceSession.hal", ], interfaces: [ @@ -18,8 +19,13 @@ hidl_interface { "android.hidl.base@1.0", ], types: [ + "CaptureRequest", + "CaptureResult", "HalStream", "HalStreamConfiguration", + "PhysicalCameraMetadata", + "PhysicalCameraSetting", + "RequestTemplate", "Stream", "StreamConfiguration", ], diff --git a/camera/device/3.4/ICameraDeviceCallback.hal b/camera/device/3.4/ICameraDeviceCallback.hal new file mode 100644 index 000000000..8ce8d4b74 --- /dev/null +++ b/camera/device/3.4/ICameraDeviceCallback.hal @@ -0,0 +1,43 @@ +/* + * 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. + */ + +package android.hardware.camera.device@3.4; + +import @3.2::ICameraDeviceCallback; + +/** + * + * Callback methods for the HAL to call into the framework. + * + * These methods are used to return metadata and image buffers for a completed + * or failed captures, and to notify the framework of asynchronous events such + * as errors. + * + * The framework must not call back into the HAL from within these callbacks, + * and these calls must not block for extended periods. + * + */ +interface ICameraDeviceCallback extends @3.2::ICameraDeviceCallback { + /** + * processCaptureResult_3_4: + * + * Identical to @3.2::ICameraDeviceCallback.processCaptureResult, except + * that it takes a list of @3.4::CaptureResult, which could contain + * physical camera metadata for logical multi-camera. + * + */ + processCaptureResult_3_4(vec<@3.4::CaptureResult> results); +}; diff --git a/camera/device/3.4/ICameraDeviceSession.hal b/camera/device/3.4/ICameraDeviceSession.hal index 4ce749d7a..7afcf94ee 100644 --- a/camera/device/3.4/ICameraDeviceSession.hal +++ b/camera/device/3.4/ICameraDeviceSession.hal @@ -17,6 +17,7 @@ package android.hardware.camera.device@3.4; import android.hardware.camera.common@1.0::Status; +import @3.2::CameraMetadata; import @3.3::ICameraDeviceSession; import @3.3::HalStreamConfiguration; import @3.2::BufferCache; @@ -30,6 +31,43 @@ import @3.2::BufferCache; interface ICameraDeviceSession extends @3.3::ICameraDeviceSession { /** + * constructDefaultRequestSettings_3_4: + * + * Create capture settings for standard camera use cases. Supports the + * new template enums added in @3.4. + * + * The device must return a settings buffer that is configured to meet the + * requested use case, which must be one of the CAMERA3_TEMPLATE_* + * enums. All request control fields must be included. + * + * Performance requirements: + * + * This must be a non-blocking call. The HAL should return from this call + * in 1ms, and must return from this call in 5ms. + * + * Return values: + * @return status Status code for the operation, one of: + * OK: + * On a successful construction of default settings. + * INTERNAL_ERROR: + * An unexpected internal error occurred, and the default settings + * are not available. + * ILLEGAL_ARGUMENT: + * The camera HAL does not support the input template type + * CAMERA_DISCONNECTED: + * An external camera device has been disconnected, and is no longer + * available. This camera device interface is now stale, and a new + * instance must be acquired if the device is reconnected. All + * subsequent calls on this interface must return + * CAMERA_DISCONNECTED. + * @return requestTemplate The default capture request settings for the requested + * use case, or an empty metadata structure if status is not OK. + * + */ + constructDefaultRequestSettings_3_4(RequestTemplate type) generates + (Status status, @3.2::CameraMetadata requestTemplate); + + /** * configureStreams_3_4: * * Identical to @3.3::ICameraDeviceSession.configureStreams, except that: diff --git a/camera/device/3.4/default/CameraDeviceSession.cpp b/camera/device/3.4/default/CameraDeviceSession.cpp index c8d33ebca..f6c6b2b0f 100644 --- a/camera/device/3.4/default/CameraDeviceSession.cpp +++ b/camera/device/3.4/default/CameraDeviceSession.cpp @@ -34,18 +34,54 @@ CameraDeviceSession::CameraDeviceSession( camera3_device_t* device, const camera_metadata_t* deviceInfo, const sp<V3_2::ICameraDeviceCallback>& callback) : - V3_3::implementation::CameraDeviceSession(device, deviceInfo, callback) { + V3_3::implementation::CameraDeviceSession(device, deviceInfo, callback), + mResultBatcher_3_4(callback) { + + mHasCallback_3_4 = false; + + auto castResult = ICameraDeviceCallback::castFrom(callback); + if (castResult.isOk()) { + sp<ICameraDeviceCallback> callback3_4 = castResult; + if (callback3_4 != nullptr) { + process_capture_result = sProcessCaptureResult_3_4; + notify = sNotify_3_4; + mHasCallback_3_4 = true; + if (!mInitFail) { + mResultBatcher_3_4.setResultMetadataQueue(mResultMetadataQueue); + } + } + } } CameraDeviceSession::~CameraDeviceSession() { } +Return<void> CameraDeviceSession::constructDefaultRequestSettings_3_4( + RequestTemplate type, ICameraDeviceSession::constructDefaultRequestSettings_cb _hidl_cb) { + V3_2::CameraMetadata outMetadata; + Status status = constructDefaultRequestSettingsRaw( (int) type, &outMetadata); + _hidl_cb(status, outMetadata); + return Void(); +} + Return<void> CameraDeviceSession::configureStreams_3_4( const StreamConfiguration& requestedConfiguration, ICameraDeviceSession::configureStreams_3_4_cb _hidl_cb) { Status status = initStatus(); HalStreamConfiguration outStreams; + // If callback is 3.2, make sure no physical stream is configured + if (!mHasCallback_3_4) { + for (size_t i = 0; i < requestedConfiguration.streams.size(); i++) { + if (requestedConfiguration.streams[i].physicalCameraId.size() > 0) { + ALOGE("%s: trying to configureStreams with physical camera id with V3.2 callback", + __FUNCTION__); + _hidl_cb(Status::INTERNAL_ERROR, outStreams); + return Void(); + } + } + } + // hold the inflight lock for entire configureStreams scope since there must not be any // inflight request/results during stream configuration. Mutex::Autolock _l(mInflightLock); @@ -197,7 +233,7 @@ void CameraDeviceSession::postProcessConfigurationLocked_3_4( mVideoStreamIds.push_back(stream.v3_2.id); } } - mResultBatcher.setBatchedStreams(mVideoStreamIds); + mResultBatcher_3_4.setBatchedStreams(mVideoStreamIds); } Return<void> CameraDeviceSession::processCaptureRequest_3_4( @@ -216,7 +252,7 @@ Return<void> CameraDeviceSession::processCaptureRequest_3_4( } if (s == Status::OK && requests.size() > 1) { - mResultBatcher.registerBatch(requests[0].v3_2.frameNumber, requests.size()); + mResultBatcher_3_4.registerBatch(requests[0].v3_2.frameNumber, requests.size()); } _hidl_cb(s, numRequestProcessed); @@ -229,6 +265,14 @@ Status CameraDeviceSession::processOneCaptureRequest_3_4(const V3_4::CaptureRequ ALOGE("%s: camera init failed or disconnected", __FUNCTION__); return status; } + // If callback is 3.2, make sure there are no physical settings. + if (!mHasCallback_3_4) { + if (request.physicalCameraSettings.size() > 0) { + ALOGE("%s: trying to call processCaptureRequest_3_4 with physical camera id " + "and V3.2 callback", __FUNCTION__); + return Status::INTERNAL_ERROR; + } + } camera3_capture_request_t halRequest; halRequest.frame_number = request.v3_2.frameNumber; @@ -399,6 +443,228 @@ Status CameraDeviceSession::processOneCaptureRequest_3_4(const V3_4::CaptureRequ return Status::OK; } +/** + * Static callback forwarding methods from HAL to instance + */ +void CameraDeviceSession::sProcessCaptureResult_3_4( + const camera3_callback_ops *cb, + const camera3_capture_result *hal_result) { + CameraDeviceSession *d = + const_cast<CameraDeviceSession*>(static_cast<const CameraDeviceSession*>(cb)); + + CaptureResult result; + d->constructCaptureResult(result.v3_2, hal_result); + result.physicalCameraMetadata.resize(hal_result->num_physcam_metadata); + for (uint32_t i = 0; i < hal_result->num_physcam_metadata; i++) { + std::string physicalId = hal_result->physcam_ids[i]; + V3_2::CameraMetadata physicalMetadata; + V3_2::implementation::convertToHidl(hal_result->physcam_metadata[i], &physicalMetadata); + PhysicalCameraMetadata physicalCameraMetadata = { + .fmqMetadataSize = 0, + .physicalCameraId = physicalId, + .metadata = physicalMetadata }; + result.physicalCameraMetadata[i] = physicalCameraMetadata; + } + d->mResultBatcher_3_4.processCaptureResult_3_4(result); +} + +void CameraDeviceSession::sNotify_3_4( + const camera3_callback_ops *cb, + const camera3_notify_msg *msg) { + CameraDeviceSession *d = + const_cast<CameraDeviceSession*>(static_cast<const CameraDeviceSession*>(cb)); + V3_2::NotifyMsg hidlMsg; + V3_2::implementation::convertToHidl(msg, &hidlMsg); + + if (hidlMsg.type == (V3_2::MsgType) CAMERA3_MSG_ERROR && + hidlMsg.msg.error.errorStreamId != -1) { + if (d->mStreamMap.count(hidlMsg.msg.error.errorStreamId) != 1) { + ALOGE("%s: unknown stream ID %d reports an error!", + __FUNCTION__, hidlMsg.msg.error.errorStreamId); + return; + } + } + + if (static_cast<camera3_msg_type_t>(hidlMsg.type) == CAMERA3_MSG_ERROR) { + switch (hidlMsg.msg.error.errorCode) { + case V3_2::ErrorCode::ERROR_DEVICE: + case V3_2::ErrorCode::ERROR_REQUEST: + case V3_2::ErrorCode::ERROR_RESULT: { + Mutex::Autolock _l(d->mInflightLock); + auto entry = d->mInflightAETriggerOverrides.find( + hidlMsg.msg.error.frameNumber); + if (d->mInflightAETriggerOverrides.end() != entry) { + d->mInflightAETriggerOverrides.erase( + hidlMsg.msg.error.frameNumber); + } + + auto boostEntry = d->mInflightRawBoostPresent.find( + hidlMsg.msg.error.frameNumber); + if (d->mInflightRawBoostPresent.end() != boostEntry) { + d->mInflightRawBoostPresent.erase( + hidlMsg.msg.error.frameNumber); + } + + } + break; + case V3_2::ErrorCode::ERROR_BUFFER: + default: + break; + } + + } + + d->mResultBatcher_3_4.notify(hidlMsg); +} + +CameraDeviceSession::ResultBatcher_3_4::ResultBatcher_3_4( + const sp<V3_2::ICameraDeviceCallback>& callback) : + V3_3::implementation::CameraDeviceSession::ResultBatcher(callback) { + auto castResult = ICameraDeviceCallback::castFrom(callback); + if (castResult.isOk()) { + mCallback_3_4 = castResult; + } +} + +void CameraDeviceSession::ResultBatcher_3_4::processCaptureResult_3_4(CaptureResult& result) { + auto pair = getBatch(result.v3_2.frameNumber); + int batchIdx = pair.first; + if (batchIdx == NOT_BATCHED) { + processOneCaptureResult_3_4(result); + return; + } + std::shared_ptr<InflightBatch> batch = pair.second; + { + Mutex::Autolock _l(batch->mLock); + // Check if the batch is removed (mostly by notify error) before lock was acquired + if (batch->mRemoved) { + // Fall back to non-batch path + processOneCaptureResult_3_4(result); + return; + } + + // queue metadata + if (result.v3_2.result.size() != 0) { + // Save a copy of metadata + batch->mResultMds[result.v3_2.partialResult].mMds.push_back( + std::make_pair(result.v3_2.frameNumber, result.v3_2.result)); + } + + // queue buffer + std::vector<int> filledStreams; + std::vector<V3_2::StreamBuffer> nonBatchedBuffers; + for (auto& buffer : result.v3_2.outputBuffers) { + auto it = batch->mBatchBufs.find(buffer.streamId); + if (it != batch->mBatchBufs.end()) { + InflightBatch::BufferBatch& bb = it->second; + pushStreamBuffer(std::move(buffer), bb.mBuffers); + filledStreams.push_back(buffer.streamId); + } else { + pushStreamBuffer(std::move(buffer), nonBatchedBuffers); + } + } + + // send non-batched buffers up + if (nonBatchedBuffers.size() > 0 || result.v3_2.inputBuffer.streamId != -1) { + CaptureResult nonBatchedResult; + nonBatchedResult.v3_2.frameNumber = result.v3_2.frameNumber; + nonBatchedResult.v3_2.fmqResultSize = 0; + nonBatchedResult.v3_2.outputBuffers.resize(nonBatchedBuffers.size()); + for (size_t i = 0; i < nonBatchedBuffers.size(); i++) { + moveStreamBuffer( + std::move(nonBatchedBuffers[i]), nonBatchedResult.v3_2.outputBuffers[i]); + } + moveStreamBuffer(std::move(result.v3_2.inputBuffer), nonBatchedResult.v3_2.inputBuffer); + nonBatchedResult.v3_2.partialResult = 0; // 0 for buffer only results + processOneCaptureResult_3_4(nonBatchedResult); + } + + if (result.v3_2.frameNumber == batch->mLastFrame) { + // Send data up + if (result.v3_2.partialResult > 0) { + sendBatchMetadataLocked(batch, result.v3_2.partialResult); + } + // send buffer up + if (filledStreams.size() > 0) { + sendBatchBuffersLocked(batch, filledStreams); + } + } + } // end of batch lock scope + + // see if the batch is complete + if (result.v3_2.frameNumber == batch->mLastFrame) { + checkAndRemoveFirstBatch(); + } +} + +void CameraDeviceSession::ResultBatcher_3_4::processOneCaptureResult_3_4(CaptureResult& result) { + hidl_vec<CaptureResult> results; + results.resize(1); + results[0] = std::move(result); + invokeProcessCaptureResultCallback_3_4(results, /* tryWriteFmq */true); + freeReleaseFences_3_4(results); + return; +} + +void CameraDeviceSession::ResultBatcher_3_4::invokeProcessCaptureResultCallback_3_4( + hidl_vec<CaptureResult> &results, bool tryWriteFmq) { + if (mProcessCaptureResultLock.tryLock() != OK) { + ALOGV("%s: previous call is not finished! waiting 1s...", __FUNCTION__); + if (mProcessCaptureResultLock.timedLock(1000000000 /* 1s */) != OK) { + ALOGE("%s: cannot acquire lock in 1s, cannot proceed", + __FUNCTION__); + return; + } + } + if (tryWriteFmq && mResultMetadataQueue->availableToWrite() > 0) { + for (CaptureResult &result : results) { + if (result.v3_2.result.size() > 0) { + if (mResultMetadataQueue->write(result.v3_2.result.data(), + result.v3_2.result.size())) { + result.v3_2.fmqResultSize = result.v3_2.result.size(); + result.v3_2.result.resize(0); + } else { + ALOGW("%s: couldn't utilize fmq, fall back to hwbinder", __FUNCTION__); + result.v3_2.fmqResultSize = 0; + } + } + + for (auto& onePhysMetadata : result.physicalCameraMetadata) { + if (mResultMetadataQueue->write(onePhysMetadata.metadata.data(), + onePhysMetadata.metadata.size())) { + onePhysMetadata.fmqMetadataSize = onePhysMetadata.metadata.size(); + onePhysMetadata.metadata.resize(0); + } else { + ALOGW("%s: couldn't utilize fmq, fall back to hwbinder", __FUNCTION__); + onePhysMetadata.fmqMetadataSize = 0; + } + } + } + } + mCallback_3_4->processCaptureResult_3_4(results); + mProcessCaptureResultLock.unlock(); +} + +void CameraDeviceSession::ResultBatcher_3_4::freeReleaseFences_3_4(hidl_vec<CaptureResult>& results) { + for (auto& result : results) { + if (result.v3_2.inputBuffer.releaseFence.getNativeHandle() != nullptr) { + native_handle_t* handle = const_cast<native_handle_t*>( + result.v3_2.inputBuffer.releaseFence.getNativeHandle()); + native_handle_close(handle); + native_handle_delete(handle); + } + for (auto& buf : result.v3_2.outputBuffers) { + if (buf.releaseFence.getNativeHandle() != nullptr) { + native_handle_t* handle = const_cast<native_handle_t*>( + buf.releaseFence.getNativeHandle()); + native_handle_close(handle); + native_handle_delete(handle); + } + } + } + return; +} + } // namespace implementation } // namespace V3_4 } // namespace device diff --git a/camera/device/3.4/default/ExternalCameraDevice.cpp b/camera/device/3.4/default/ExternalCameraDevice.cpp index d6c31f33c..e6e0ae3ef 100644 --- a/camera/device/3.4/default/ExternalCameraDevice.cpp +++ b/camera/device/3.4/default/ExternalCameraDevice.cpp @@ -227,8 +227,7 @@ do { \ status_t ExternalCameraDevice::initDefaultCharsKeys( ::android::hardware::camera::common::V1_0::helper::CameraMetadata* metadata) { - // TODO: changed to HARDWARELEVEL_EXTERNAL later - const uint8_t hardware_level = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED; + const uint8_t hardware_level = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL; UPDATE(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL, &hardware_level, 1); // android.colorCorrection diff --git a/camera/device/3.4/default/ExternalCameraDeviceSession.cpp b/camera/device/3.4/default/ExternalCameraDeviceSession.cpp index c869ad7e4..0714ee2be 100644 --- a/camera/device/3.4/default/ExternalCameraDeviceSession.cpp +++ b/camera/device/3.4/default/ExternalCameraDeviceSession.cpp @@ -57,8 +57,9 @@ const float kMinAspectRatio = 1.f; HandleImporter ExternalCameraDeviceSession::sHandleImporter; bool isAspectRatioClose(float ar1, float ar2) { - const float kAspectRatioMatchThres = 0.01f; // This threshold is good enough to distinguish + const float kAspectRatioMatchThres = 0.025f; // This threshold is good enough to distinguish // 4:3/16:9/20:9 + // 1.33 / 1.78 / 2 return (std::abs(ar1 - ar2) < kAspectRatioMatchThres); } @@ -93,8 +94,8 @@ CroppingType ExternalCameraDeviceSession::initCroppingType( const std::vector<SupportedV4L2Format>& sortedFmts) { const auto& maxSize = sortedFmts[sortedFmts.size() - 1]; float maxSizeAr = ASPECT_RATIO(maxSize); - float minAr = kMinAspectRatio; - float maxAr = kMaxAspectRatio; + float minAr = kMaxAspectRatio; + float maxAr = kMinAspectRatio; for (const auto& fmt : sortedFmts) { float ar = ASPECT_RATIO(fmt); if (ar < minAr) { @@ -178,33 +179,53 @@ void ExternalCameraDeviceSession::dumpState(const native_handle_t*) { } Return<void> ExternalCameraDeviceSession::constructDefaultRequestSettings( + V3_2::RequestTemplate type, + V3_2::ICameraDeviceSession::constructDefaultRequestSettings_cb _hidl_cb) { + V3_2::CameraMetadata outMetadata; + Status status = constructDefaultRequestSettingsRaw( + static_cast<RequestTemplate>(type), &outMetadata); + _hidl_cb(status, outMetadata); + return Void(); +} + +Return<void> ExternalCameraDeviceSession::constructDefaultRequestSettings_3_4( RequestTemplate type, - ICameraDeviceSession::constructDefaultRequestSettings_cb _hidl_cb) { + ICameraDeviceSession::constructDefaultRequestSettings_cb _hidl_cb) { + V3_2::CameraMetadata outMetadata; + Status status = constructDefaultRequestSettingsRaw(type, &outMetadata); + _hidl_cb(status, outMetadata); + return Void(); +} + +Status ExternalCameraDeviceSession::constructDefaultRequestSettingsRaw(RequestTemplate type, + V3_2::CameraMetadata *outMetadata) { CameraMetadata emptyMd; Status status = initStatus(); if (status != Status::OK) { - _hidl_cb(status, emptyMd); - return Void(); + return status; } switch (type) { case RequestTemplate::PREVIEW: case RequestTemplate::STILL_CAPTURE: case RequestTemplate::VIDEO_RECORD: - case RequestTemplate::VIDEO_SNAPSHOT: - _hidl_cb(Status::OK, mDefaultRequests[static_cast<int>(type)]); + case RequestTemplate::VIDEO_SNAPSHOT: { + *outMetadata = mDefaultRequests[type]; break; + } case RequestTemplate::MANUAL: case RequestTemplate::ZERO_SHUTTER_LAG: - // Don't support MANUAL or ZSL template - _hidl_cb(Status::ILLEGAL_ARGUMENT, emptyMd); + case RequestTemplate::MOTION_TRACKING_PREVIEW: + case RequestTemplate::MOTION_TRACKING_BEST: + // Don't support MANUAL, ZSL, MOTION_TRACKING_* templates + status = Status::ILLEGAL_ARGUMENT; break; default: ALOGE("%s: unknown request template type %d", __FUNCTION__, static_cast<int>(type)); - _hidl_cb(Status::ILLEGAL_ARGUMENT, emptyMd); + status = Status::ILLEGAL_ARGUMENT; break; } - return Void(); + return status; } Return<void> ExternalCameraDeviceSession::configureStreams( @@ -704,11 +725,24 @@ int ExternalCameraDeviceSession::OutputThread::getCropRect( ALOGE("%s: out is null", __FUNCTION__); return -1; } + uint32_t inW = inSize.width; uint32_t inH = inSize.height; uint32_t outW = outSize.width; uint32_t outH = outSize.height; + // Handle special case where aspect ratio is close to input but scaled + // dimension is slightly larger than input + float arIn = ASPECT_RATIO(inSize); + float arOut = ASPECT_RATIO(outSize); + if (isAspectRatioClose(arIn, arOut)) { + out->left = 0; + out->top = 0; + out->width = inW; + out->height = inH; + return 0; + } + if (ct == VERTICAL) { uint64_t scaledOutH = static_cast<uint64_t>(outH) * inW / outW; if (scaledOutH > inH) { @@ -1768,21 +1802,21 @@ status_t ExternalCameraDeviceSession::initDefaultRequests() { const uint8_t controlMode = ANDROID_CONTROL_MODE_AUTO; UPDATE(md, ANDROID_CONTROL_MODE, &controlMode, 1); - for (int type = static_cast<int>(RequestTemplate::PREVIEW); - type <= static_cast<int>(RequestTemplate::VIDEO_SNAPSHOT); type++) { + auto requestTemplates = hidl_enum_iterator<RequestTemplate>(); + for (RequestTemplate type : requestTemplates) { ::android::hardware::camera::common::V1_0::helper::CameraMetadata mdCopy = md; uint8_t intent = ANDROID_CONTROL_CAPTURE_INTENT_PREVIEW; switch (type) { - case static_cast<int>(RequestTemplate::PREVIEW): + case RequestTemplate::PREVIEW: intent = ANDROID_CONTROL_CAPTURE_INTENT_PREVIEW; break; - case static_cast<int>(RequestTemplate::STILL_CAPTURE): + case RequestTemplate::STILL_CAPTURE: intent = ANDROID_CONTROL_CAPTURE_INTENT_STILL_CAPTURE; break; - case static_cast<int>(RequestTemplate::VIDEO_RECORD): + case RequestTemplate::VIDEO_RECORD: intent = ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_RECORD; break; - case static_cast<int>(RequestTemplate::VIDEO_SNAPSHOT): + case RequestTemplate::VIDEO_SNAPSHOT: intent = ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT; break; default: @@ -1990,4 +2024,3 @@ int AllocatedFrame::getCroppedLayout(const IMapper::Rect& rect, YCbCrLayout* out } // namespace camera } // namespace hardware } // namespace android - diff --git a/camera/device/3.4/default/include/device_v3_4_impl/CameraDeviceSession.h b/camera/device/3.4/default/include/device_v3_4_impl/CameraDeviceSession.h index fbde083fd..9cd7da7ba 100644 --- a/camera/device/3.4/default/include/device_v3_4_impl/CameraDeviceSession.h +++ b/camera/device/3.4/default/include/device_v3_4_impl/CameraDeviceSession.h @@ -19,6 +19,7 @@ #include <android/hardware/camera/device/3.2/ICameraDevice.h> #include <android/hardware/camera/device/3.4/ICameraDeviceSession.h> +#include <android/hardware/camera/device/3.4/ICameraDeviceCallback.h> #include <../../3.3/default/CameraDeviceSession.h> #include <../../3.3/default/include/convert.h> #include <fmq/MessageQueue.h> @@ -46,6 +47,7 @@ using ::android::hardware::camera::device::V3_2::StreamType; using ::android::hardware::camera::device::V3_4::StreamConfiguration; using ::android::hardware::camera::device::V3_4::HalStreamConfiguration; using ::android::hardware::camera::device::V3_4::ICameraDeviceSession; +using ::android::hardware::camera::device::V3_4::ICameraDeviceCallback; using ::android::hardware::camera::common::V1_0::Status; using ::android::hardware::camera::common::V1_0::helper::HandleImporter; using ::android::hardware::kSynchronizedReadWrite; @@ -73,6 +75,9 @@ protected: // Methods from v3.3 and earlier will trampoline to inherited implementation // New methods for v3.4 + Return<void> constructDefaultRequestSettings_3_4( + RequestTemplate type, + ICameraDeviceSession::constructDefaultRequestSettings_cb _hidl_cb); Return<void> configureStreams_3_4( const StreamConfiguration& requestedConfiguration, @@ -91,6 +96,25 @@ protected: Status processOneCaptureRequest_3_4(const V3_4::CaptureRequest& request); std::map<int, std::string> mPhysicalCameraIdMap; + + static V3_2::implementation::callbacks_process_capture_result_t sProcessCaptureResult_3_4; + static V3_2::implementation::callbacks_notify_t sNotify_3_4; + + class ResultBatcher_3_4 : public V3_3::implementation::CameraDeviceSession::ResultBatcher { + public: + ResultBatcher_3_4(const sp<V3_2::ICameraDeviceCallback>& callback); + void processCaptureResult_3_4(CaptureResult& result); + private: + void freeReleaseFences_3_4(hidl_vec<CaptureResult>&); + void processOneCaptureResult_3_4(CaptureResult& result); + void invokeProcessCaptureResultCallback_3_4(hidl_vec<CaptureResult> &results, + bool tryWriteFmq); + + sp<ICameraDeviceCallback> mCallback_3_4; + } mResultBatcher_3_4; + + // Whether this camera device session is created with version 3.4 callback. + bool mHasCallback_3_4; private: struct TrampolineSessionInterface_3_4 : public ICameraDeviceSession { @@ -139,6 +163,12 @@ private: return mParent->close(); } + virtual Return<void> constructDefaultRequestSettings_3_4( + RequestTemplate type, + ICameraDeviceSession::constructDefaultRequestSettings_cb _hidl_cb) override { + return mParent->constructDefaultRequestSettings_3_4(type, _hidl_cb); + } + virtual Return<void> configureStreams_3_3( const V3_2::StreamConfiguration& requestedConfiguration, configureStreams_3_3_cb _hidl_cb) override { diff --git a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h index ba49ebec2..7d7f52c97 100644 --- a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h +++ b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h @@ -51,7 +51,7 @@ using ::android::hardware::camera::device::V3_2::ErrorCode; using ::android::hardware::camera::device::V3_2::ICameraDeviceCallback; using ::android::hardware::camera::device::V3_2::MsgType; using ::android::hardware::camera::device::V3_2::NotifyMsg; -using ::android::hardware::camera::device::V3_2::RequestTemplate; +using ::android::hardware::camera::device::V3_4::RequestTemplate; using ::android::hardware::camera::device::V3_2::Stream; using ::android::hardware::camera::device::V3_4::StreamConfiguration; using ::android::hardware::camera::device::V3_2::StreamConfigurationMode; @@ -172,7 +172,11 @@ protected: // Methods from ::android::hardware::camera::device::V3_2::ICameraDeviceSession follow Return<void> constructDefaultRequestSettings( - RequestTemplate, + V3_2::RequestTemplate, + ICameraDeviceSession::constructDefaultRequestSettings_cb _hidl_cb); + + Return<void> constructDefaultRequestSettings_3_4( + RequestTemplate type, ICameraDeviceSession::constructDefaultRequestSettings_cb _hidl_cb); Return<void> configureStreams( @@ -227,6 +231,9 @@ protected: std::vector<HalStreamBuffer> buffers; }; + Status constructDefaultRequestSettingsRaw(RequestTemplate type, + V3_2::CameraMetadata *outMetadata); + static std::vector<SupportedV4L2Format> sortFormats( const std::vector<SupportedV4L2Format>&); static CroppingType initCroppingType(const std::vector<SupportedV4L2Format>&); @@ -365,7 +372,7 @@ protected: // Protect against invokeProcessCaptureResultCallback() Mutex mProcessCaptureResultLock; - std::unordered_map<int, CameraMetadata> mDefaultRequests; + std::unordered_map<RequestTemplate, CameraMetadata> mDefaultRequests; /* End of members not changed after initialize() */ private: @@ -410,6 +417,12 @@ private: return mParent->close(); } + virtual Return<void> constructDefaultRequestSettings_3_4( + RequestTemplate type, + ICameraDeviceSession::constructDefaultRequestSettings_cb _hidl_cb) override { + return mParent->constructDefaultRequestSettings_3_4(type, _hidl_cb); + } + virtual Return<void> configureStreams_3_3( const V3_2::StreamConfiguration& requestedConfiguration, configureStreams_3_3_cb _hidl_cb) override { diff --git a/camera/device/3.4/types.hal b/camera/device/3.4/types.hal index 77e855f12..5ab6b8818 100644 --- a/camera/device/3.4/types.hal +++ b/camera/device/3.4/types.hal @@ -16,12 +16,13 @@ package android.hardware.camera.device@3.4; -import @3.2::types; +import @3.2::RequestTemplate; import @3.2::StreamConfigurationMode; import @3.2::Stream; import @3.3::HalStream; import @3.2::CameraMetadata; import @3.2::CaptureRequest; +import @3.2::CaptureResult; /** * Stream: @@ -62,6 +63,36 @@ struct Stream { }; /** + * New request templates, extending the @3.2 RequestTemplate + */ +enum RequestTemplate : @3.2::RequestTemplate { + /** + * A template for selecting camera parameters that match TEMPLATE_PREVIEW as closely as + * possible while improving the camera output for motion tracking use cases. + * + * This template is best used by applications that are frequently switching between motion + * tracking use cases and regular still capture use cases, to minimize the IQ changes + * when swapping use cases. + * + * This template is guaranteed to be supported on camera devices that support the + * REQUEST_AVAILABLE_CAPABILITIES_MOTION_TRACKING capability. + */ + MOTION_TRACKING_PREVIEW = 7, + + /** + * A template for selecting camera parameters that maximize the quality of camera output for + * motion tracking use cases. + * + * This template is best used by applications dedicated to motion tracking applications, + * which aren't concerned about fast switches between motion tracking and other use cases. + * + * This template is guaranteed to be supported on camera devices that support the + * REQUEST_AVAILABLE_CAPABILITIES_MOTION_TRACKING capability. + */ + MOTION_TRACKING_BEST = 8, +}; + +/** * StreamConfiguration: * * Identical to @3.2::StreamConfiguration, except that it contains session @@ -196,3 +227,66 @@ struct CaptureRequest { */ vec<PhysicalCameraSetting> physicalCameraSettings; }; + +/** + * PhysicalCameraMetadata: + * + * Individual camera metadata for a physical camera as part of a logical + * multi-camera. Camera HAL should return one such metadata for each physical + * camera being requested on. + */ +struct PhysicalCameraMetadata { + /** + * If non-zero, read metadata from result metadata queue instead + * (see ICameraDeviceSession.getCaptureResultMetadataQueue). + * If zero, read metadata from .metadata field. + */ + uint64_t fmqMetadataSize; + + /** + * Contains the physical device camera id. As long as the corresponding + * processCaptureRequest requests on a particular physical camera stream, + * the metadata for that physical camera should be generated for the capture + * result. */ + string physicalCameraId; + + /** + * If fmqMetadataSize is zero, the metadata buffer contains the metadata + * for the physical device with physicalCameraId. + * + * The v3_2 CaptureResult metadata is read first from the FMQ, followed by + * the physical cameras' metadata starting from index 0. + */ + CameraMetadata metadata; +}; + +/** + * CaptureResult: + * + * Identical to @3.2::CaptureResult, except that it contains a list of + * physical camera metadata. + * + * Physical camera metadata needs to be generated if and only if a + * request is pending on a stream from that physical camera. For example, + * if the processCaptureRequest call doesn't request on physical camera + * streams, the physicalCameraMetadata field of the CaptureResult being returned + * should be an 0-size vector. If the processCaptureRequest call requests on + * streams from one of the physical camera, the physicalCameraMetadata field + * should contain one metadata describing the capture from that physical camera. + * + * For a CaptureResult that contains physical camera metadata, its + * partialResult field must be android.request.partialResultCount. In other + * words, the physicalCameraMetadata must only be contained in a final capture + * result. + */ +struct CaptureResult { + /** + * The definition of CaptureResult from the prior version. + */ + @3.2::CaptureResult v3_2; + + /** + * The physical metadata for logical multi-camera. + */ + vec<PhysicalCameraMetadata> physicalCameraMetadata; +}; |