703 lines
23 KiB
C++
703 lines
23 KiB
C++
/*
|
|
* Copyright (C) 2014-2017 Intel Corporation
|
|
* Copyright (c) 2017, Fuzhou Rockchip Electronics Co., Ltd
|
|
*
|
|
* 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 "ResultProcessor"
|
|
|
|
#include "ResultProcessor.h"
|
|
#include "Camera3Request.h"
|
|
#include "RequestThread.h"
|
|
#include "PlatformData.h"
|
|
#include "PerformanceTraces.h"
|
|
|
|
NAMESPACE_DECLARATION {
|
|
|
|
ResultProcessor::ResultProcessor(RequestThread * aReqThread,
|
|
const camera3_callback_ops_t * cbOps) :
|
|
mRequestThread(aReqThread),
|
|
mMessageQueue("ResultProcessor", MESSAGE_ID_MAX),
|
|
mMessageThread(new MessageThread(this,"ResultProcessor")),
|
|
mCallbackOps(cbOps),
|
|
mThreadRunning(true),
|
|
mPartialResultCount(0),
|
|
mNextRequestId(0),
|
|
mDevError(false)
|
|
{
|
|
HAL_TRACE_CALL(CAM_GLBL_DBG_HIGH);
|
|
mReqStatePool.init(MAX_REQUEST_IN_TRANSIT);
|
|
mMessageThread->run();
|
|
}
|
|
|
|
ResultProcessor::~ResultProcessor()
|
|
{
|
|
HAL_TRACE_CALL(CAM_GLBL_DBG_HIGH);
|
|
if (mMessageThread != nullptr) {
|
|
mMessageThread.reset();
|
|
mMessageThread = nullptr;
|
|
}
|
|
mRequestsPendingMetaReturn.clear();
|
|
mRequestsInTransit.clear();
|
|
}
|
|
|
|
/**********************************************************************
|
|
* Public methods
|
|
*/
|
|
/**********************************************************************
|
|
* Thread methods
|
|
*/
|
|
status_t ResultProcessor::requestExitAndWait(void)
|
|
{
|
|
HAL_TRACE_CALL(CAM_GLBL_DBG_HIGH);
|
|
Message msg;
|
|
msg.id = MESSAGE_ID_EXIT;
|
|
status_t status = mMessageQueue.send(&msg, MESSAGE_ID_EXIT);
|
|
status |= mMessageThread->requestExitAndWait();
|
|
return status;
|
|
}
|
|
status_t ResultProcessor::handleMessageExit(void)
|
|
{
|
|
HAL_TRACE_CALL(CAM_GLBL_DBG_HIGH);
|
|
while ((mRequestsInTransit.size()) != 0) {
|
|
recycleRequest((mRequestsInTransit.begin()->second)->request);
|
|
}
|
|
mThreadRunning = false;
|
|
mMessageQueue.reply(MESSAGE_ID_EXIT, OK);
|
|
return NO_ERROR;
|
|
}
|
|
|
|
/**
|
|
* registerRequest
|
|
*
|
|
* Present a request to the ResultProcessor.
|
|
* This call is used to inform the result processor that a new request
|
|
* has been sent to the PSL. RequestThread uses this method
|
|
* ResultProcessor will store its state in an internal vector to track
|
|
* the different events during the lifetime of the request.
|
|
*
|
|
* Once the request has been completed ResultProcessor returns the request
|
|
* to the RequestThread for recycling, using the method:
|
|
* RequestThread::returnRequest();
|
|
*
|
|
* \param request [IN] item to register
|
|
* \return NO_ERROR
|
|
*/
|
|
status_t ResultProcessor::registerRequest(Camera3Request *request)
|
|
{
|
|
HAL_TRACE_CALL(CAM_GLBL_DBG_HIGH);
|
|
Message msg;
|
|
msg.id = MESSAGE_ID_REGISTER_REQUEST;
|
|
msg.request = request;
|
|
return mMessageQueue.send(&msg, MESSAGE_ID_REGISTER_REQUEST);
|
|
}
|
|
|
|
status_t ResultProcessor::handleRegisterRequest(Message &msg)
|
|
{
|
|
status_t status = NO_ERROR;
|
|
RequestState_t* reqState;
|
|
int reqId = msg.request->getId();
|
|
/**
|
|
* check if the request was not already register. we may receive registration
|
|
* request duplicated in case of request that are held by the PSL
|
|
*/
|
|
if (getRequestsInTransit(&reqState, reqId) == NO_ERROR) {
|
|
return NO_ERROR;
|
|
}
|
|
|
|
status = mReqStatePool.acquireItem(&reqState);
|
|
if (status != NO_ERROR) {
|
|
LOGE("Could not acquire an empty reqState from the pool");
|
|
return status;
|
|
}
|
|
|
|
reqState->init(msg.request);
|
|
mRequestsInTransit.insert(RequestsInTransitPair(reqState->reqId, reqState));
|
|
LOGD("<request %d> camera id %d registered @ ResultProcessor", reqState->reqId, msg.request->getCameraId());
|
|
/**
|
|
* get the number of partial results the request may return, this is not
|
|
* going to change once the camera is open, so do it only once.
|
|
* We initialize the value to 0, the minimum value should be 1
|
|
*/
|
|
if (CC_UNLIKELY(mPartialResultCount == 0)) {
|
|
mPartialResultCount = msg.request->getpartialResultCount();
|
|
}
|
|
return status;
|
|
}
|
|
|
|
void ResultProcessor::messageThreadLoop(void)
|
|
{
|
|
HAL_TRACE_CALL(CAM_GLBL_DBG_HIGH);
|
|
|
|
mThreadRunning = true;
|
|
while (mThreadRunning) {
|
|
status_t status = NO_ERROR;
|
|
Message msg;
|
|
mMessageQueue.receive(&msg);
|
|
PERFORMANCE_HAL_ATRACE_PARAM1("msg", msg.id);
|
|
switch (msg.id) {
|
|
case MESSAGE_ID_EXIT:
|
|
status = handleMessageExit();
|
|
break;
|
|
case MESSAGE_ID_SHUTTER_DONE:
|
|
status = handleShutterDone(msg);
|
|
break;
|
|
case MESSAGE_ID_METADATA_DONE:
|
|
status = handleMetadataDone(msg);
|
|
break;
|
|
case MESSAGE_ID_BUFFER_DONE:
|
|
status = handleBufferDone(msg);
|
|
break;
|
|
case MESSAGE_ID_REGISTER_REQUEST:
|
|
status = handleRegisterRequest(msg);
|
|
break;
|
|
case MESSAGE_ID_DEVICE_ERROR:
|
|
handleDeviceError();
|
|
break;
|
|
default:
|
|
LOGE("Wrong message id %d", msg.id);
|
|
status = BAD_VALUE;
|
|
break;
|
|
}
|
|
mMessageQueue.reply(msg.id, status);
|
|
}
|
|
}
|
|
|
|
status_t ResultProcessor::shutterDone(Camera3Request* request,
|
|
int64_t timestamp)
|
|
{
|
|
HAL_TRACE_CALL(CAM_GLBL_DBG_HIGH);
|
|
Message msg;
|
|
msg.id = MESSAGE_ID_SHUTTER_DONE;
|
|
msg.request = request;
|
|
msg.data.shutter.time = timestamp;
|
|
|
|
return mMessageQueue.send(&msg);
|
|
}
|
|
|
|
status_t ResultProcessor::handleShutterDone(Message &msg)
|
|
{
|
|
HAL_TRACE_CALL(CAM_GLBL_DBG_HIGH);
|
|
status_t status = NO_ERROR;
|
|
int reqId = 0;
|
|
Camera3Request* request = msg.request;
|
|
|
|
reqId = request->getId();
|
|
LOGD("%s for <Request : %d", __FUNCTION__, reqId);
|
|
PERFORMANCE_HAL_ATRACE_PARAM1("reqId", reqId);
|
|
PERFORMANCE_ATRACE_NAME_SNPRINTF("handleShutterDone - %d", reqId);
|
|
PERFORMANCE_ATRACE_ASYNC_BEGIN("Shutter2Alldone", reqId);
|
|
|
|
RequestState_t *reqState = nullptr;
|
|
if (getRequestsInTransit(&reqState, reqId) == BAD_VALUE) {
|
|
LOGE("Request %d was not registered find the bug", reqId);
|
|
return BAD_VALUE;
|
|
}
|
|
|
|
reqState->shutterTime = msg.data.shutter.time;
|
|
if (mNextRequestId != reqId) {
|
|
LOGW("shutter done received ahead of time, expecting %d got %d Or discontinuities requests received.",
|
|
mNextRequestId, reqId);
|
|
reqState->shutterReceived = true;
|
|
}
|
|
|
|
returnShutterDone(reqState);
|
|
|
|
if (!reqState->pendingBuffers.empty()) {
|
|
returnPendingBuffers(reqState);
|
|
}
|
|
|
|
unsigned int resultsReceived = reqState->pendingPartialResults.size();
|
|
bool allMetaReceived = (resultsReceived == mPartialResultCount);
|
|
|
|
if (allMetaReceived) {
|
|
returnPendingPartials(reqState);
|
|
}
|
|
|
|
bool allMetaDone = (reqState->partialResultReturned == mPartialResultCount);
|
|
bool allBuffersDone = (reqState->buffersReturned == reqState->buffersToReturn);
|
|
if (allBuffersDone && allMetaDone) {
|
|
status = recycleRequest(request);
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
/**
|
|
* returnShutterDone
|
|
* Signal to the client that shutter event was received
|
|
* \param reqState [IN/OUT] state of the request
|
|
*/
|
|
void ResultProcessor::returnShutterDone(RequestState_t* reqState)
|
|
{
|
|
if (reqState->isShutterDone)
|
|
return;
|
|
|
|
camera3_notify_msg shutter;
|
|
shutter.type = CAMERA3_MSG_SHUTTER;
|
|
shutter.message.shutter.frame_number = reqState->reqId;
|
|
shutter.message.shutter.timestamp =reqState->shutterTime;
|
|
mCallbackOps->notify(mCallbackOps, &shutter);
|
|
reqState->isShutterDone = true;
|
|
mNextRequestId = reqState->nextReqId;
|
|
LOGD("<Request %d> camera id %d shutter done", reqState->reqId, reqState->request->getCameraId());
|
|
}
|
|
|
|
status_t ResultProcessor::metadataDone(Camera3Request* request,
|
|
int resultIndex)
|
|
{
|
|
HAL_TRACE_CALL(CAM_GLBL_DBG_HIGH);
|
|
Message msg;
|
|
msg.id = MESSAGE_ID_METADATA_DONE;
|
|
msg.request = request;
|
|
msg.data.meta.resultIndex = resultIndex;
|
|
|
|
return mMessageQueue.send(&msg);
|
|
}
|
|
|
|
status_t ResultProcessor::handleMetadataDone(Message &msg)
|
|
{
|
|
HAL_TRACE_CALL(CAM_GLBL_DBG_HIGH);
|
|
status_t status = NO_ERROR;
|
|
Camera3Request* request = msg.request;
|
|
int reqId = request->getId();
|
|
LOGD("%s for <Request %d>", __FUNCTION__, reqId);
|
|
PERFORMANCE_HAL_ATRACE_PARAM1("reqId", reqId);
|
|
PERFORMANCE_ATRACE_NAME_SNPRINTF("handleMetadataDone - %d", reqId);
|
|
|
|
RequestState_t *reqState = nullptr;
|
|
if (getRequestsInTransit(&reqState, reqId) == BAD_VALUE) {
|
|
LOGE("Request %d was not registered:find the bug", reqId);
|
|
return BAD_VALUE;
|
|
}
|
|
|
|
if (!reqState->pendingBuffers.empty())
|
|
returnPendingBuffers(reqState);
|
|
|
|
if (msg.data.meta.resultIndex >= 0) {
|
|
/**
|
|
* New Partial metadata result path. The result buffer is not the
|
|
* settings but a separate buffer stored in the request.
|
|
* The resultIndex indicates which one.
|
|
* This can be returned straight away now that we have declared 3.2
|
|
* device version. No need to enforce the order between shutter events
|
|
* result and buffers. We do not need to store the partials either.
|
|
* we can return them directly
|
|
*/
|
|
status = returnResult(reqState, msg.data.meta.resultIndex);
|
|
|
|
bool allMetadataDone = (reqState->partialResultReturned == mPartialResultCount);
|
|
bool allBuffersDone = (reqState->buffersReturned == reqState->buffersToReturn);
|
|
if (allBuffersDone && allMetadataDone) {
|
|
status = recycleRequest(request);
|
|
}
|
|
return status;
|
|
}
|
|
|
|
reqState->pendingPartialResults.emplace_back(request->getSettings());
|
|
LOGD(" <Request %d> camera id %d Metadata arrived %zu/%d", reqId, reqState->request->getCameraId(),
|
|
reqState->pendingPartialResults.size(),mPartialResultCount);
|
|
|
|
if (!reqState->isShutterDone) {
|
|
LOGD("metadata arrived before shutter, storing");
|
|
return NO_ERROR;
|
|
}
|
|
|
|
unsigned int resultsReceived = reqState->pendingPartialResults.size();
|
|
bool allMetaReceived = (resultsReceived == mPartialResultCount);
|
|
|
|
if (allMetaReceived) {
|
|
returnPendingPartials(reqState);
|
|
}
|
|
|
|
bool allMetadataDone = (reqState->partialResultReturned == mPartialResultCount);
|
|
bool allBuffersDone = (reqState->buffersReturned == reqState->buffersToReturn);
|
|
if (allBuffersDone && allMetadataDone) {
|
|
status = recycleRequest(request);
|
|
}
|
|
|
|
/**
|
|
* if the metadata done for the next request is available then send it.
|
|
*
|
|
*/
|
|
if (allMetadataDone) {
|
|
returnStoredPartials();
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
/**
|
|
* returnStoredPartials
|
|
* return the all stored pending metadata
|
|
*/
|
|
status_t ResultProcessor::returnStoredPartials()
|
|
{
|
|
status_t status = NO_ERROR;
|
|
|
|
while (mRequestsPendingMetaReturn.size() > 0) {
|
|
int reqId = mRequestsPendingMetaReturn.front();
|
|
LOGD("stored metadata req size:%zu, first reqid:%d", mRequestsPendingMetaReturn.size(), reqId);
|
|
RequestState_t *reqState = nullptr;
|
|
|
|
if (getRequestsInTransit(&reqState, reqId) == BAD_VALUE) {
|
|
LOGE("Request %d was not registered:find the bug", reqId);
|
|
mRequestsPendingMetaReturn.pop_front();
|
|
return BAD_VALUE;
|
|
}
|
|
|
|
returnPendingPartials(reqState);
|
|
bool allMetadataDone = (reqState->partialResultReturned == mPartialResultCount);
|
|
bool allBuffersDone = (reqState->buffersReturned == reqState->buffersToReturn);
|
|
if (allBuffersDone && allMetadataDone) {
|
|
status = recycleRequest(reqState->request);
|
|
}
|
|
|
|
mRequestsPendingMetaReturn.pop_front();
|
|
}
|
|
return status;
|
|
}
|
|
|
|
|
|
status_t ResultProcessor::bufferDone(Camera3Request* request,
|
|
std::shared_ptr<CameraBuffer> buffer)
|
|
{
|
|
HAL_TRACE_CALL(CAM_GLBL_DBG_HIGH);
|
|
Message msg;
|
|
msg.id = MESSAGE_ID_BUFFER_DONE;
|
|
msg.request = request;
|
|
msg.buffer = buffer;
|
|
|
|
return mMessageQueue.send(&msg);
|
|
}
|
|
|
|
/**
|
|
* handleBufferDone
|
|
*
|
|
* Try to return the buffer provided by PSL to client
|
|
* This method checks whether we can return the buffer straight to client or
|
|
* we need to hold it until shutter event has been received.
|
|
* \param msg [IN] Contains the buffer produced by PSL
|
|
*/
|
|
status_t ResultProcessor::handleBufferDone(Message &msg)
|
|
{
|
|
HAL_TRACE_CALL(CAM_GLBL_DBG_HIGH);
|
|
status_t status = NO_ERROR;
|
|
Camera3Request* request = msg.request;
|
|
std::shared_ptr<CameraBuffer> buffer = msg.buffer;
|
|
|
|
int reqId = request->getId();
|
|
if (buffer.get() && buffer->getOwner()) {
|
|
PERFORMANCE_HAL_ATRACE_PARAM1(
|
|
"streamAndReqId", reqId | (buffer->getOwner()->seqNo() << 28));
|
|
} else {
|
|
PERFORMANCE_HAL_ATRACE_PARAM1("reqId", reqId);
|
|
}
|
|
PERFORMANCE_ATRACE_NAME_SNPRINTF("handleBufferDone - %d", reqId);
|
|
|
|
RequestState_t *reqState = nullptr;
|
|
if (getRequestsInTransit(&reqState, reqId) == BAD_VALUE) {
|
|
LOGE("Request %d was not registered find the bug", reqId);
|
|
return BAD_VALUE;
|
|
}
|
|
|
|
LOGD("<Request %d> camera id %d buffer received from PSL",
|
|
reqId, reqState->request->getCameraId());
|
|
reqState->pendingBuffers.emplace_back(buffer);
|
|
if (!reqState->isShutterDone) {
|
|
LOGD("Buffer arrived before shutter req %d, queue it",reqId);
|
|
return NO_ERROR;
|
|
}
|
|
|
|
returnPendingBuffers(reqState);
|
|
|
|
if (!reqState->pendingPartialResults.empty()) {
|
|
returnPendingPartials(reqState);
|
|
}
|
|
|
|
bool allMetaDone = (reqState->partialResultReturned == mPartialResultCount);
|
|
bool allBuffersDone = (reqState->buffersReturned == reqState->buffersToReturn);
|
|
if (allBuffersDone && allMetaDone) {
|
|
status = recycleRequest(request);
|
|
}
|
|
return status;
|
|
}
|
|
|
|
void ResultProcessor::returnPendingBuffers(RequestState_t* reqState)
|
|
{
|
|
LOGD("@%s - req-%d %zu buffs", __FUNCTION__, reqState->reqId,
|
|
reqState->pendingBuffers.size());
|
|
unsigned int i;
|
|
camera3_capture_result_t result;
|
|
camera3_stream_buffer_t buf;
|
|
std::shared_ptr<CameraBuffer> pendingBuf;
|
|
Camera3Request* request = reqState->request;
|
|
|
|
/**
|
|
* protection against duplicated calls when all buffers have been returned
|
|
*/
|
|
if(reqState->buffersReturned == reqState->buffersToReturn) {
|
|
LOGW("trying to return buffers twice. Check PSL implementation");
|
|
return;
|
|
}
|
|
|
|
for (i = 0; i < reqState->pendingBuffers.size(); i++) {
|
|
CLEAR(buf);
|
|
CLEAR(result);
|
|
|
|
pendingBuf = reqState->pendingBuffers[i];
|
|
if (!request->isInputBuffer(pendingBuf)) {
|
|
result.num_output_buffers = 1;
|
|
}
|
|
result.frame_number = reqState->reqId;
|
|
// Force drop buffers when request error
|
|
buf.status = request->getError() ? CAMERA3_BUFFER_STATUS_ERROR :
|
|
pendingBuf->status();
|
|
buf.stream = pendingBuf->getOwner()->getStream();
|
|
/* framework check the handle point other than handle */
|
|
/* buf.buffer = pendingBuf->getBufferHandle(); */
|
|
buf.buffer = pendingBuf->getBufferHandlePtr();
|
|
pendingBuf->getFence(&buf);
|
|
result.result = nullptr;
|
|
if (request->isInputBuffer(pendingBuf)) {
|
|
result.input_buffer = &buf;
|
|
LOGD(" <Request %d> return an input buffer", reqState->reqId);
|
|
} else {
|
|
result.output_buffers = &buf;
|
|
}
|
|
|
|
processCaptureResult(reqState, &result);
|
|
pendingBuf->getOwner()->decOutBuffersInHal();
|
|
reqState->buffersReturned += 1;
|
|
LOGD(" <Request %d> camera id %d buffer done %d/%d ", reqState->reqId,
|
|
reqState->request->getCameraId(), reqState->buffersReturned, reqState->buffersToReturn);
|
|
}
|
|
|
|
reqState->pendingBuffers.clear();
|
|
}
|
|
|
|
/**
|
|
* Returns the single partial result stored in the vector.
|
|
* In the future we will have more than one.
|
|
*/
|
|
void ResultProcessor::returnPendingPartials(RequestState_t* reqState)
|
|
{
|
|
camera3_capture_result result;
|
|
CLEAR(result);
|
|
|
|
// it must be 1 for >= CAMERA_DEVICE_API_VERSION_3_2 if we don't support partial metadata
|
|
result.partial_result = mPartialResultCount;
|
|
|
|
//TODO: combine them all in one metadata buffer and return
|
|
result.frame_number = reqState->reqId;
|
|
|
|
// check if metadata result of the previous request is returned
|
|
int pre_reqId = reqState->reqId - 1;
|
|
RequestState_t *pre_reqState = nullptr;
|
|
|
|
if (getRequestsInTransit(&pre_reqState, pre_reqId) == NO_ERROR) {
|
|
if (pre_reqState->partialResultReturned == 0) {
|
|
LOGD("wait the metadata of the previous request return");
|
|
LOGD("%s add reqId %d in to pending list\n", __FUNCTION__, reqState->reqId);
|
|
std::list<int>::iterator it;
|
|
for (it = mRequestsPendingMetaReturn.begin();
|
|
(it != mRequestsPendingMetaReturn.end()) && (*it < reqState->reqId);
|
|
it++);
|
|
mRequestsPendingMetaReturn.insert(it, reqState->reqId);
|
|
return;
|
|
}
|
|
}
|
|
|
|
const CameraMetadata * settings = reqState->pendingPartialResults[0];
|
|
|
|
result.result = settings->getAndLock();
|
|
result.num_output_buffers = 0;
|
|
|
|
mCallbackOps->process_capture_result(mCallbackOps, &result);
|
|
|
|
settings->unlock(result.result);
|
|
|
|
reqState->partialResultReturned += 1;
|
|
LOGD("<Request %d> camera id %d result cb done",reqState->reqId, reqState->request->getCameraId());
|
|
reqState->pendingPartialResults.clear();
|
|
}
|
|
|
|
/**
|
|
* returnResult
|
|
*
|
|
* Returns a partial result metadata buffer, just one.
|
|
*
|
|
* \param reqState[IN]: Request State control structure
|
|
* \param returnIndex[IN]: index of the result buffer in the array of result
|
|
* buffers stored in the request
|
|
* -1 means null metadata
|
|
*/
|
|
status_t ResultProcessor::returnResult(RequestState_t* reqState, int returnIndex)
|
|
{
|
|
status_t status = NO_ERROR;
|
|
camera3_capture_result result;
|
|
CameraMetadata *resultMetadata;
|
|
CLEAR(result);
|
|
if (returnIndex >= 0)
|
|
resultMetadata = reqState->request->getPartialResultBuffer(returnIndex);
|
|
else
|
|
resultMetadata = nullptr;
|
|
reqState->request->dumpResults();
|
|
// This value should be between 1 and android.request.partialResultCount
|
|
// The index goes between 0-partialResultCount -1
|
|
result.partial_result = returnIndex + 1;
|
|
result.frame_number = reqState->reqId;
|
|
result.result = resultMetadata ? resultMetadata->getAndLock() : nullptr;
|
|
result.num_output_buffers = 0;
|
|
|
|
mCallbackOps->process_capture_result(mCallbackOps, &result);
|
|
|
|
if (resultMetadata)
|
|
resultMetadata->unlock(result.result);
|
|
|
|
reqState->partialResultReturned += 1;
|
|
LOGD("<Request %d> camera id %d result cb done", reqState->reqId, reqState->request->getCameraId());
|
|
return status;
|
|
}
|
|
|
|
/**
|
|
* getRequestsInTransit
|
|
*
|
|
* Returns a RequestState in the map at index.
|
|
*
|
|
* \param reqState[OUT]: Request State control structure
|
|
* \param index[IN]: index of the result state, it's request Id mapped to the state
|
|
*/
|
|
status_t ResultProcessor::getRequestsInTransit(RequestState_t** reqState, int index)
|
|
{
|
|
status_t state = NO_ERROR;
|
|
std::map<int, RequestState_t*>::const_iterator it;
|
|
|
|
it = mRequestsInTransit.find(index);
|
|
if (it == mRequestsInTransit.cend()) {
|
|
LOGI("%s, Result State not found for id %d", __FUNCTION__, index);
|
|
state = BAD_VALUE;
|
|
} else {
|
|
state = NO_ERROR;
|
|
*reqState = it->second;
|
|
}
|
|
|
|
return state;
|
|
}
|
|
|
|
void ResultProcessor::processCaptureResult(RequestState_t* reqState, camera3_capture_result* result)
|
|
{
|
|
int numMetaLeft = mPartialResultCount - reqState->partialResultReturned;
|
|
int numBufLeft = reqState->buffersToReturn - reqState->buffersReturned;
|
|
|
|
// Report request error when it's the last result
|
|
if (numMetaLeft + numBufLeft == 1) {
|
|
Camera3Request* request = reqState->request;
|
|
if (request->getError())
|
|
returnRequestError(request->getId());
|
|
}
|
|
|
|
mCallbackOps->process_capture_result(mCallbackOps, result);
|
|
}
|
|
|
|
/**
|
|
* Request is fully processed
|
|
* send the request object back to RequestThread for recycling
|
|
* return the request-state struct to the pool
|
|
*/
|
|
status_t ResultProcessor::recycleRequest(Camera3Request *req)
|
|
{
|
|
status_t status = NO_ERROR;
|
|
int id = req->getId();
|
|
PERFORMANCE_ATRACE_ASYNC_END("Shutter2Alldone", id);
|
|
RequestState_t *reqState = mRequestsInTransit.at(id);
|
|
status = mReqStatePool.releaseItem(reqState);
|
|
if (status != NO_ERROR) {
|
|
LOGE("Request State pool failure[%d] , recycling is broken!!", status);
|
|
}
|
|
|
|
mRequestsInTransit.erase(id);
|
|
mRequestThread->returnRequest(req);
|
|
LOGD("<Request %d> camera id %d OUT from ResultProcessor",id, reqState->request->getCameraId());
|
|
return status;
|
|
}
|
|
|
|
/**
|
|
* The android camera framework will remove the request when receiving the
|
|
* first result after request error. So the request error should be reported
|
|
* right before sending the last result.
|
|
*/
|
|
void ResultProcessor::returnRequestError(int reqId)
|
|
{
|
|
HAL_TRACE_CALL(CAM_GLBL_DBG_ERR);
|
|
LOGE("%s for <Request : %d", __FUNCTION__, reqId);
|
|
|
|
camera3_notify_msg msg;
|
|
CLEAR(msg);
|
|
msg.type = CAMERA3_MSG_ERROR;
|
|
msg.message.error.frame_number = reqId;
|
|
msg.message.error.error_stream = nullptr;
|
|
msg.message.error.error_code = CAMERA3_MSG_ERROR_REQUEST;
|
|
mCallbackOps->notify(mCallbackOps, &msg);
|
|
}
|
|
|
|
/**
|
|
* A serious failure occured. No further frames or buffer streams will
|
|
* be produced by the device. Device should be treated as closed. The
|
|
* client must reopen the device to use it again. The frame_number field
|
|
* is unused.
|
|
*/
|
|
void ResultProcessor::returnDeviceError(int reqId)
|
|
{
|
|
HAL_TRACE_CALL(CAM_GLBL_DBG_ERR);
|
|
LOGE("%s for <Request : %d", __FUNCTION__, reqId);
|
|
camera3_notify_msg msg;
|
|
CLEAR(msg);
|
|
msg.type = CAMERA3_MSG_ERROR;
|
|
msg.message.error.frame_number = reqId;
|
|
msg.message.error.error_stream = nullptr;
|
|
msg.message.error.error_code = CAMERA3_MSG_ERROR_DEVICE;
|
|
mCallbackOps->notify(mCallbackOps, &msg);
|
|
}
|
|
|
|
status_t ResultProcessor::deviceError(void)
|
|
{
|
|
HAL_TRACE_CALL(CAM_GLBL_DBG_ERR);
|
|
Message msg;
|
|
msg.id = MESSAGE_ID_DEVICE_ERROR;
|
|
|
|
return mMessageQueue.send(&msg);
|
|
}
|
|
|
|
void ResultProcessor::handleDeviceError(void)
|
|
{
|
|
HAL_TRACE_CALL(CAM_GLBL_DBG_ERR);
|
|
Camera3Request* request = NULL;
|
|
camera3_capture_result_t result;
|
|
RequestState_t* reqState = nullptr;
|
|
|
|
while ((mRequestsInTransit.size()) > 0) {
|
|
reqState = mRequestsInTransit.begin()->second;
|
|
request = reqState->request;
|
|
returnDeviceError(request->getId());
|
|
recycleRequest(request);
|
|
LOGD("@%s: mRequestsInTransit.size()(%d)", __FUNCTION__, mRequestsInTransit.size());
|
|
}
|
|
|
|
LOGD("@%s done", __FUNCTION__);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
} NAMESPACE_DECLARATION_END
|