| /* |
| * Copyright 2017 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 "QCamera3HdrPlusListenerThread.h" |
| |
| |
| using ::android::hardware::camera::common::V1_0::helper::CameraMetadata; |
| using namespace android; |
| |
| namespace qcamera { |
| |
| QCamera3HdrPlusListenerThread::QCamera3HdrPlusListenerThread( |
| HdrPlusClientListener *listener) : mListener(listener), mExitRequested(false), |
| mFatalError(false) |
| { |
| } |
| |
| QCamera3HdrPlusListenerThread::~QCamera3HdrPlusListenerThread() |
| { |
| requestExit(); |
| } |
| |
| void QCamera3HdrPlusListenerThread::onOpened(std::unique_ptr<HdrPlusClient> client) |
| { |
| std::unique_lock<std::mutex> l(mCallbackLock); |
| if (mClient != nullptr) { |
| ALOGW("%s: An old client exists and will be destroyed.", __FUNCTION__); |
| } |
| mClient = std::move(client); |
| mPendingCallbacks.push(CALLBACK_TYPE_OPENED); |
| mCallbackCond.notify_one(); |
| } |
| |
| void QCamera3HdrPlusListenerThread::onOpenFailed(status_t err) |
| { |
| std::unique_lock<std::mutex> l(mCallbackLock); |
| if (mOpenError != OK) { |
| ALOGW("%s: An old open failure exists and will be ignored: %s (%d)", __FUNCTION__, |
| strerror(-mOpenError), mOpenError); |
| } |
| mOpenError = err; |
| mPendingCallbacks.push(CALLBACK_TYPE_OPENFAILED); |
| mCallbackCond.notify_one(); |
| } |
| |
| void QCamera3HdrPlusListenerThread::onFatalError() |
| { |
| std::unique_lock<std::mutex> l(mCallbackLock); |
| if (mFatalError) { |
| ALOGW("%s: An old fatal failure exists.", __FUNCTION__); |
| } |
| mFatalError = true; |
| mPendingCallbacks.push(CALLBACK_TYPE_FATAL_ERROR); |
| mCallbackCond.notify_one(); |
| } |
| |
| void QCamera3HdrPlusListenerThread::onCaptureResult(pbcamera::CaptureResult *result, |
| const camera_metadata_t &resultMetadata) |
| { |
| std::unique_lock<std::mutex> l(mCallbackLock); |
| |
| PendingResult pendingResult = {}; |
| pendingResult.result = *result; |
| pendingResult.metadata = clone_camera_metadata(&resultMetadata); |
| pendingResult.isFailed = false; |
| mResults.push(pendingResult); |
| |
| mPendingCallbacks.push(CALLBACK_TYPE_CAPTURE_RESULT); |
| mCallbackCond.notify_one(); |
| } |
| |
| void QCamera3HdrPlusListenerThread::onFailedCaptureResult(pbcamera::CaptureResult *failedResult) |
| { |
| std::unique_lock<std::mutex> l(mCallbackLock); |
| |
| PendingResult result = {}; |
| result.result = *failedResult; |
| result.metadata = nullptr; |
| result.isFailed = true; |
| mResults.push(result); |
| |
| mPendingCallbacks.push(CALLBACK_TYPE_CAPTURE_RESULT); |
| mCallbackCond.notify_one(); |
| } |
| |
| void QCamera3HdrPlusListenerThread::onShutter(uint32_t requestId, int64_t apSensorTimestampNs) |
| { |
| std::unique_lock<std::mutex> l(mCallbackLock); |
| |
| std::pair<uint32_t, int64_t> shutter(requestId, apSensorTimestampNs); |
| mShutters.push(shutter); |
| |
| mPendingCallbacks.push(CALLBACK_TYPE_SHUTTER); |
| mCallbackCond.notify_one(); |
| } |
| |
| void QCamera3HdrPlusListenerThread::onNextCaptureReady(uint32_t requestId) |
| { |
| std::unique_lock<std::mutex> l(mCallbackLock); |
| mNextCaptureReadyIds.push(requestId); |
| |
| mPendingCallbacks.push(CALLBACK_TYPE_NEXT_CAPTURE_READY); |
| mCallbackCond.notify_one(); |
| |
| } |
| |
| void QCamera3HdrPlusListenerThread::onPostview(uint32_t requestId, |
| std::unique_ptr<std::vector<uint8_t>> postview, uint32_t width, uint32_t height, |
| uint32_t stride, int32_t format) |
| { |
| std::unique_lock<std::mutex> l(mCallbackLock); |
| |
| PendingPostview pendingPostview = {}; |
| pendingPostview.requestId = requestId; |
| pendingPostview.postview = std::move(postview); |
| pendingPostview.width = width; |
| pendingPostview.height = height; |
| pendingPostview.stride = stride; |
| pendingPostview.format = format; |
| mPostviews.push(std::move(pendingPostview)); |
| |
| mPendingCallbacks.push(CALLBACK_TYPE_POSTVIEW); |
| mCallbackCond.notify_one(); |
| |
| } |
| |
| void QCamera3HdrPlusListenerThread::requestExit() |
| { |
| std::unique_lock<std::mutex> l(mCallbackLock); |
| mExitRequested = true; |
| mCallbackCond.notify_one(); |
| } |
| |
| void QCamera3HdrPlusListenerThread::handleFatalError() |
| { |
| bool fatalError; |
| { |
| std::unique_lock<std::mutex> lock(mCallbackLock); |
| if (!mFatalError) { |
| ALOGW("%s: There is no fatal error.", __FUNCTION__); |
| return; |
| } |
| |
| fatalError = mFatalError; |
| } |
| |
| mListener->onFatalError(); |
| } |
| |
| void QCamera3HdrPlusListenerThread::handlePendingClient() |
| { |
| std::unique_ptr<HdrPlusClient> client; |
| { |
| std::unique_lock<std::mutex> lock(mCallbackLock); |
| if (mClient == nullptr) { |
| ALOGW("%s: There is no pending client.", __FUNCTION__); |
| return; |
| } |
| |
| client = std::move(mClient); |
| } |
| |
| mListener->onOpened(std::move(client)); |
| } |
| |
| void QCamera3HdrPlusListenerThread::handleOpenError() |
| { |
| status_t err = OK; |
| { |
| std::unique_lock<std::mutex> lock(mCallbackLock); |
| if (mOpenError == OK) { |
| ALOGW("%s: There is no pending open failure.", __FUNCTION__); |
| return; |
| } |
| |
| err = mOpenError; |
| mOpenError = OK; |
| } |
| |
| mListener->onOpenFailed(err); |
| } |
| |
| void QCamera3HdrPlusListenerThread::handleNextCaptureReady() |
| { |
| uint32_t requestId = 0; |
| { |
| std::unique_lock<std::mutex> l(mCallbackLock); |
| if (mNextCaptureReadyIds.size() == 0) { |
| ALOGW("%s: There is no NextCaptureReady.", __FUNCTION__); |
| return; |
| } |
| requestId = mNextCaptureReadyIds.front(); |
| mNextCaptureReadyIds.pop(); |
| } |
| mListener->onNextCaptureReady(requestId); |
| } |
| |
| void QCamera3HdrPlusListenerThread::handleCaptureResult() |
| { |
| PendingResult result = {}; |
| { |
| std::unique_lock<std::mutex> l(mCallbackLock); |
| if (mResults.size() == 0) { |
| ALOGW("%s: There is no capture result.", __FUNCTION__); |
| return; |
| } |
| result = mResults.front(); |
| mResults.pop(); |
| } |
| |
| if (result.isFailed) { |
| mListener->onFailedCaptureResult(&result.result); |
| } else { |
| mListener->onCaptureResult(&result.result, *result.metadata); |
| } |
| } |
| |
| void QCamera3HdrPlusListenerThread::handleShutter() |
| { |
| uint32_t requestId; |
| int64_t apSensorTimestampNs; |
| |
| { |
| std::unique_lock<std::mutex> l(mCallbackLock); |
| if (mShutters.size() == 0) { |
| ALOGW("%s: There is no shutter.", __FUNCTION__); |
| return;; |
| } |
| |
| auto shutter = mShutters.front(); |
| requestId = shutter.first; |
| apSensorTimestampNs = shutter.second; |
| mShutters.pop(); |
| } |
| |
| mListener->onShutter(requestId, apSensorTimestampNs); |
| } |
| |
| void QCamera3HdrPlusListenerThread::handlePostview() |
| { |
| PendingPostview postview = {}; |
| |
| { |
| std::unique_lock<std::mutex> l(mCallbackLock); |
| if (mPostviews.size() == 0) { |
| ALOGW("%s: There is no postview.", __FUNCTION__); |
| return;; |
| } |
| |
| postview = std::move(mPostviews.front()); |
| mPostviews.pop(); |
| } |
| |
| mListener->onPostview(postview.requestId, std::move(postview.postview), postview.width, |
| postview.height, postview.stride, postview.format); |
| } |
| |
| bool QCamera3HdrPlusListenerThread::threadLoop() |
| { |
| if (mListener == nullptr) { |
| ALOGE("%s: mListener is nullptr.", __FUNCTION__); |
| return false; |
| } |
| |
| while (1) { |
| CallbackType nextCallback; |
| |
| { |
| std::unique_lock<std::mutex> lock(mCallbackLock); |
| if (!mExitRequested && mPendingCallbacks.size() == 0) { |
| mCallbackCond.wait(lock, |
| [&] { return mExitRequested || mPendingCallbacks.size() > 0; }); |
| } |
| |
| if (mExitRequested) { |
| return false; |
| } else { |
| nextCallback = mPendingCallbacks.front(); |
| mPendingCallbacks.pop(); |
| } |
| } |
| |
| switch (nextCallback) { |
| case CALLBACK_TYPE_OPENED: |
| handlePendingClient(); |
| break; |
| case CALLBACK_TYPE_OPENFAILED: |
| handleOpenError(); |
| break; |
| case CALLBACK_TYPE_FATAL_ERROR: |
| handleFatalError(); |
| break; |
| case CALLBACK_TYPE_CAPTURE_RESULT: |
| handleCaptureResult(); |
| break; |
| case CALLBACK_TYPE_SHUTTER: |
| handleShutter(); |
| break; |
| case CALLBACK_TYPE_NEXT_CAPTURE_READY: |
| handleNextCaptureReady(); |
| break; |
| case CALLBACK_TYPE_POSTVIEW: |
| handlePostview(); |
| break; |
| default: |
| ALOGE("%s: Unknown callback type %d", __FUNCTION__, nextCallback); |
| break; |
| } |
| } |
| |
| return false; |
| } |
| |
| }; // namespace qcamera |