| /* |
| * 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. |
| */ |
| |
| #define LOG_TAG "Camera3-CompositeStream" |
| #define ATRACE_TAG ATRACE_TAG_CAMERA |
| //#define LOG_NDEBUG 0 |
| |
| #include <utils/Log.h> |
| #include <utils/Trace.h> |
| |
| #include "common/CameraDeviceBase.h" |
| #include "CameraDeviceClient.h" |
| #include "CompositeStream.h" |
| |
| namespace android { |
| namespace camera3 { |
| |
| CompositeStream::CompositeStream(sp<CameraDeviceBase> device, |
| wp<hardware::camera2::ICameraDeviceCallbacks> cb) : |
| mDevice(device), |
| mRemoteCallback(cb), |
| mNumPartialResults(1), |
| mErrorState(false) { |
| if (device != nullptr) { |
| CameraMetadata staticInfo = device->info(); |
| camera_metadata_entry_t entry = staticInfo.find(ANDROID_REQUEST_PARTIAL_RESULT_COUNT); |
| if (entry.count > 0) { |
| mNumPartialResults = entry.data.i32[0]; |
| } |
| mStatusTracker = device->getStatusTracker(); |
| } |
| } |
| |
| status_t CompositeStream::createStream(const std::vector<sp<Surface>>& consumers, |
| bool hasDeferredConsumer, uint32_t width, uint32_t height, int format, |
| camera_stream_rotation_t rotation, int * id, const std::string& physicalCameraId, |
| const std::unordered_set<int32_t> &sensorPixelModesUsed, |
| std::vector<int> * surfaceIds, |
| int streamSetId, bool isShared, bool isMultiResolution, int32_t colorSpace, |
| int64_t dynamicProfile, int64_t streamUseCase, bool useReadoutTimestamp) { |
| if (hasDeferredConsumer) { |
| ALOGE("%s: Deferred consumers not supported in case of composite streams!", |
| __FUNCTION__); |
| return BAD_VALUE; |
| } |
| |
| if (streamSetId != camera3::CAMERA3_STREAM_ID_INVALID) { |
| ALOGE("%s: Surface groups not supported in case of composite streams!", |
| __FUNCTION__); |
| return BAD_VALUE; |
| } |
| |
| if (isShared) { |
| ALOGE("%s: Shared surfaces not supported in case of composite streams!", |
| __FUNCTION__); |
| return BAD_VALUE; |
| } |
| |
| if (isMultiResolution) { |
| ALOGE("%s: Multi-resolution output not supported in case of composite streams!", |
| __FUNCTION__); |
| return BAD_VALUE; |
| } |
| |
| return createInternalStreams(consumers, hasDeferredConsumer, width, height, format, rotation, |
| id, physicalCameraId, sensorPixelModesUsed, surfaceIds, streamSetId, isShared, |
| colorSpace, dynamicProfile, streamUseCase, useReadoutTimestamp); |
| } |
| |
| status_t CompositeStream::deleteStream() { |
| { |
| Mutex::Autolock l(mMutex); |
| mPendingCaptureResults.clear(); |
| mCaptureResults.clear(); |
| mFrameNumberMap.clear(); |
| mErrorFrameNumbers.clear(); |
| mRequestTimeMap.clear(); |
| } |
| |
| return deleteInternalStreams(); |
| } |
| |
| void CompositeStream::onBufferRequestForFrameNumber(uint64_t frameNumber, int streamId, |
| const CameraMetadata& /*settings*/) { |
| Mutex::Autolock l(mMutex); |
| if (!mErrorState && (streamId == getStreamId())) { |
| mPendingCaptureResults.emplace(frameNumber, CameraMetadata()); |
| auto ts = systemTime(); |
| mRequestTimeMap.emplace(frameNumber, ts); |
| } |
| } |
| |
| void CompositeStream::onBufferReleased(const BufferInfo& bufferInfo) { |
| Mutex::Autolock l(mMutex); |
| if (!mErrorState && !bufferInfo.mError) { |
| mFrameNumberMap.emplace(bufferInfo.mFrameNumber, bufferInfo.mTimestamp); |
| mInputReadyCondition.signal(); |
| } |
| } |
| |
| void CompositeStream::eraseResult(int64_t frameNumber) { |
| Mutex::Autolock l(mMutex); |
| |
| auto requestTimeIt = mRequestTimeMap.find(frameNumber); |
| if (requestTimeIt != mRequestTimeMap.end()) { |
| mRequestTimeMap.erase(requestTimeIt); |
| } |
| |
| auto it = mPendingCaptureResults.find(frameNumber); |
| if (it == mPendingCaptureResults.end()) { |
| return; |
| } |
| |
| it = mPendingCaptureResults.erase(it); |
| } |
| |
| void CompositeStream::onResultAvailable(const CaptureResult& result) { |
| bool resultError = false; |
| { |
| Mutex::Autolock l(mMutex); |
| |
| uint64_t frameNumber = result.mResultExtras.frameNumber; |
| bool resultReady = false; |
| auto it = mPendingCaptureResults.find(frameNumber); |
| if (it != mPendingCaptureResults.end()) { |
| it->second.append(result.mMetadata); |
| if (result.mResultExtras.partialResultCount >= mNumPartialResults) { |
| auto entry = it->second.find(ANDROID_SENSOR_TIMESTAMP); |
| if (entry.count == 1) { |
| auto ts = entry.data.i64[0]; |
| mCaptureResults.emplace(ts, std::make_tuple(frameNumber, it->second)); |
| resultReady = true; |
| } else { |
| ALOGE("%s: Timestamp metadata entry missing for frameNumber: %" PRIu64, |
| __FUNCTION__, frameNumber); |
| resultError = true; |
| } |
| mPendingCaptureResults.erase(it); |
| } |
| } |
| |
| if (resultReady) { |
| mInputReadyCondition.signal(); |
| } |
| } |
| |
| if (resultError) { |
| onResultError(result.mResultExtras); |
| } |
| } |
| |
| void CompositeStream::flagAnErrorFrameNumber(int64_t frameNumber) { |
| Mutex::Autolock l(mMutex); |
| mErrorFrameNumbers.emplace(frameNumber); |
| mInputReadyCondition.signal(); |
| } |
| |
| status_t CompositeStream::registerCompositeStreamListener(int32_t streamId) { |
| sp<CameraDeviceBase> device = mDevice.promote(); |
| if (device.get() == nullptr) { |
| return NO_INIT; |
| } |
| |
| auto ret = device->addBufferListenerForStream(streamId, this); |
| if (ret != OK) { |
| ALOGE("%s: Failed to register composite stream listener!", __FUNCTION__); |
| } |
| |
| return ret; |
| } |
| |
| bool CompositeStream::onError(int32_t errorCode, const CaptureResultExtras& resultExtras) { |
| auto ret = false; |
| switch (errorCode) { |
| case hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_RESULT: |
| onResultError(resultExtras); |
| break; |
| case hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_BUFFER: |
| ret = onStreamBufferError(resultExtras); |
| break; |
| case hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_REQUEST: |
| onRequestError(resultExtras); |
| break; |
| default: |
| ALOGE("%s: Unrecoverable error: %d detected!", __FUNCTION__, errorCode); |
| Mutex::Autolock l(mMutex); |
| mErrorState = true; |
| break; |
| } |
| |
| return ret; |
| } |
| |
| void CompositeStream::notifyError(int64_t frameNumber, int32_t requestId) { |
| sp<hardware::camera2::ICameraDeviceCallbacks> remoteCb = |
| mRemoteCallback.promote(); |
| |
| if ((frameNumber >= 0) && (remoteCb.get() != nullptr)) { |
| CaptureResultExtras extras; |
| extras.errorStreamId = getStreamId(); |
| extras.frameNumber = frameNumber; |
| extras.requestId = requestId; |
| remoteCb->onDeviceError( |
| hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_BUFFER, |
| extras); |
| } |
| } |
| |
| void CompositeStream::switchToOffline() { |
| Mutex::Autolock l(mMutex); |
| mDevice.clear(); |
| } |
| |
| }; // namespace camera3 |
| }; // namespace android |