blob: 355d970918191f8ebc9b08a0ed3d077a685c700c [file] [log] [blame]
/*
* 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