blob: 7e27b304a39c486777887f008164233cdef759bc [file] [log] [blame]
/*
* Copyright (C) 2019 MediaTek Inc.
*
* 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 "camera/hal/mediatek/mtkcam/pipeline/hwnode/p2/P2_BasicProcessor.h"
#include "P2_Util.h"
#include <src/pass2/NormalStream.h>
#include <memory>
#include <vector>
#define LOG_TAG "P2_BasicProcessor"
#define P2_BASIC_THREAD_NAME "p2_basic"
#define FORCE_BURST 0
namespace P2 {
#include <mtkcam/utils/debug/P2_DebugControl.h>
#define P2_CLASS_TAG BasicProcessor
#define P2_TRACE TRACE_BASIC_PROCESSOR
#include "P2_LogHeader.h"
BasicProcessor::BasicProcessor() : Processor(P2_BASIC_THREAD_NAME) {
MY_LOG_FUNC_ENTER();
MY_LOG_FUNC_EXIT();
}
BasicProcessor::~BasicProcessor() {
MY_LOG_S_FUNC_ENTER(mLog);
this->uninit();
MY_LOG_S_FUNC_EXIT(mLog);
}
MBOOL BasicProcessor::onInit(const P2InitParam& param) {
ILog log = param.mP2Info.mLog;
MY_LOG_S_FUNC_ENTER(log);
P2_CAM_TRACE_NAME(TRACE_ADVANCED, "P2_Basic:init()");
MBOOL ret = MFALSE;
mP2Info = param.mP2Info;
mLog = mP2Info.mLog;
ret = initNormalStream() && init3A();
if (!ret) {
MY_S_LOGE(mLog, "P2_Basic:init fail");
uninitNormalStream();
uninit3A();
}
MY_LOG_S_FUNC_EXIT(log);
return ret;
}
MVOID BasicProcessor::onUninit() {
MY_LOG_S_FUNC_ENTER(mLog);
P2_CAM_TRACE_NAME(TRACE_ADVANCED, "P2_Basic:uninit()");
uninitNormalStream();
uninit3A();
MY_LOG_S_FUNC_EXIT(mLog);
}
MVOID BasicProcessor::onThreadStart() {
MY_LOG_S_FUNC_ENTER(mLog);
P2_CAM_TRACE_NAME(TRACE_ADVANCED, "P2_Basic:threadStart()");
MY_LOG_S_FUNC_EXIT(mLog);
}
MVOID BasicProcessor::onThreadStop() {
MY_LOG_S_FUNC_ENTER(mLog);
P2_CAM_TRACE_NAME(TRACE_ADVANCED, "P2_Basic:threadStop()");
MY_LOG_S_FUNC_EXIT(mLog);
}
MBOOL BasicProcessor::onConfig(const P2ConfigParam& param) {
MY_LOG_S_FUNC_ENTER(mLog);
P2_CAM_TRACE_NAME(TRACE_ADVANCED, "P2_Basic:config()");
mP2Info = param.mP2Info;
MY_LOG_S_FUNC_EXIT(mLog);
return MTRUE;
}
MBOOL BasicProcessor::onEnque(const std::shared_ptr<P2Request>& request) {
ILog log = spToILog(request);
TRACE_S_FUNC_ENTER(log);
P2_CAM_TRACE_NAME(TRACE_ADVANCED, "P2_Basic:enque()");
MBOOL ret = MFALSE;
processVenc(request);
if (request != nullptr && request->hasInput() && request->hasOutput()) {
std::shared_ptr<P2Payload> payload = std::make_shared<P2Payload>(request);
MUINT32 portFlag = mEnableVencStream ? P2Util::USE_VENC : 0;
payload->mIO = P2Util::extractSimpleIO(request, portFlag);
payload->mIO.setUseLMV(MFALSE);
if (payload->mIO.hasInput() && payload->mIO.hasOutput()) {
P2MetaSet metaSet = request->getMetaSet();
/*add for tuning flow*/
int size = mTuningBuffers.size();
payload->mIO.mTuningBuffer = mTuningBuffers[size - 1];
payload->mTuning =
P2Util::xmakeTuning(request->mP2Pack, payload->mIO, mHal3A, &metaSet);
request->updateMetaSet(metaSet);
payload->mQParams =
P2Util::xmakeQParams(request->mP2Pack, payload->mIO, payload->mTuning,
payload->mP2Obj.toPtrTable());
mTuningBuffers.pop_back();
payload->mRequest->releaseResource(P2Request::RES_IN_IMG);
ret = processBurst(payload) || processP2(payload);
} else {
checkBurst();
}
}
TRACE_S_FUNC_EXIT(log);
return ret;
}
MVOID BasicProcessor::onNotifyFlush() {
MY_LOG_S_FUNC_ENTER(mLog);
P2_CAM_TRACE_NAME(TRACE_ADVANCED, "P2_Basic:notifyFlush()");
if (mBurstQueue.size()) {
updateResult(mBurstQueue, MFALSE);
mBurstQueue.clear();
}
MY_LOG_S_FUNC_EXIT(mLog);
}
MVOID BasicProcessor::onWaitFlush() {
MY_LOG_S_FUNC_ENTER(mLog);
P2_CAM_TRACE_NAME(TRACE_ADVANCED, "P2_Basic:waitFlush()");
waitP2CBDone();
MY_LOG_S_FUNC_EXIT(mLog);
}
MBOOL BasicProcessor::initNormalStream() {
TRACE_S_FUNC_ENTER(mLog);
MBOOL ret = MFALSE;
P2_CAM_TRACE_BEGIN(TRACE_ADVANCED, "P2_Basic:NormalStream create");
mNormalStream = std::make_shared<NSCam::v4l2::NormalStream>(
mP2Info.getConfigInfo().mMainSensorID);
P2_CAM_TRACE_END(TRACE_ADVANCED);
if (mNormalStream == nullptr) {
MY_S_LOGE(mLog, "OOM: cannot create NormalStream");
} else {
P2_CAM_TRACE_BEGIN(TRACE_ADVANCED, "P2_Basic:NormalStream init");
ret = mNormalStream->init(getName());
P2_CAM_TRACE_END(TRACE_ADVANCED);
if (!ret) {
MY_S_LOGE(mLog, "NormalStream init failed");
return MFALSE;
}
ret = mNormalStream->requestBuffers(
NSImageio::NSIspio::EPortIndex_TUNING,
NSCam::IImageBufferAllocator::ImgParam(0, 0), &mTuningBuffers);
if (!ret) {
MY_S_LOGE(mLog, "NormalStream requestBuffers failed");
}
}
TRACE_S_FUNC_EXIT(mLog);
return ret;
}
MVOID BasicProcessor::uninitNormalStream() {
TRACE_S_FUNC_ENTER(mLog);
if (mNormalStream) {
configVencStream(MFALSE);
for (auto& it : mTuningBuffers) {
it->unlockBuf("V4L2");
}
mNormalStream->uninit(getName());
}
TRACE_S_FUNC_EXIT(mLog);
}
MBOOL BasicProcessor::init3A() {
TRACE_S_FUNC_ENTER(mLog);
MBOOL ret = MTRUE;
P2_CAM_TRACE_BEGIN(TRACE_ADVANCED, "P2_Basic:3A create");
MAKE_Hal3A(
mHal3A, [](IHal3A* p) { p->destroyInstance(LOG_TAG); },
mP2Info.getConfigInfo().mMainSensorID, LOG_TAG);
P2_CAM_TRACE_END(TRACE_ADVANCED);
if (mHal3A == nullptr) {
MY_S_LOGE(mLog, "OOM: cannot create Hal3A");
ret = MFALSE;
}
TRACE_S_FUNC_EXIT(mLog);
return ret;
}
MVOID BasicProcessor::uninit3A() {
TRACE_S_FUNC_ENTER(mLog);
TRACE_S_FUNC_EXIT(mLog);
}
MVOID BasicProcessor::onP2CB(const QParams& qparams,
std::shared_ptr<P2Payload> const& payload) {
TRACE_S_FUNC_ENTER(payload->mRequest->mLog);
P2_CAM_TRACE_NAME(TRACE_ADVANCED, "P2_Basic:onP2CB()");
std::shared_ptr<IImageBuffer> tuningBuffer = payload->mIO.mTuningBuffer;
mTuningBuffers.push_back(tuningBuffer);
payload->mIO.updateResult(qparams.mDequeSuccess);
}
MBOOL BasicProcessor::processVenc(const std::shared_ptr<P2Request>& request) {
TRACE_S_FUNC_ENTER(request->mLog);
MBOOL ret = MTRUE;
if (request != nullptr) {
MINT32 fps = 0;
MSize size;
std::shared_ptr<P2Meta> meta = request->getMeta(IN_P1_HAL);
if (tryGet<MINT32>(meta, MTK_P2NODE_HIGH_SPEED_VDO_FPS, &fps) &&
tryGet<MSize>(meta, MTK_P2NODE_HIGH_SPEED_VDO_SIZE, &size)) {
MBOOL enable = fps && size.w && size.h;
ret = configVencStream(enable, fps, size);
}
}
TRACE_S_FUNC_EXIT(request->mLog);
return ret;
}
MBOOL BasicProcessor::configVencStream(MBOOL enable, MINT32 fps, MSize size) {
TRACE_S_FUNC_ENTER(mLog);
MBOOL ret = MTRUE;
if (enable != mEnableVencStream) {
ret = enable ? mNormalStream->sendCommand(ESDCmd_CONFIG_VENC_DIRLK, fps,
size.w, size.h)
: mNormalStream->sendCommand(ESDCmd_RELEASE_VENC_DIRLK);
if (!ret) {
MY_S_LOGW(mLog,
"Config venc stream failed: enable(%d) fps(%d) size(%dx%d)",
enable, fps, size.w, size.h);
} else {
mEnableVencStream = enable;
}
}
TRACE_S_FUNC_EXIT(mLog);
return ret;
}
BasicProcessor::P2Payload::P2Payload() {}
BasicProcessor::P2Payload::P2Payload(const std::shared_ptr<P2Request>& request)
: mRequest(request) {}
BasicProcessor::P2Payload::~P2Payload() {
P2Util::releaseTuning(&mTuning);
}
BasicProcessor::P2Cookie::P2Cookie(BasicProcessor* parent,
const std::shared_ptr<P2Payload>& payload)
: mParent(parent) {
mPayloads.push_back(payload);
}
BasicProcessor::P2Cookie::P2Cookie(
BasicProcessor* parent,
const std::vector<std::shared_ptr<P2Payload>>& payloads)
: mParent(parent), mPayloads(payloads) {}
ILog BasicProcessor::P2Cookie::getILog() {
ILog log;
if (mPayloads.size() && mPayloads[0]->mRequest != nullptr) {
log = mPayloads[0]->mRequest->mLog;
}
return log;
}
ILog BasicProcessor::getILog(const std::shared_ptr<P2Payload>& payload) {
return payload->mRequest->mLog;
}
ILog BasicProcessor::getILog(
const std::vector<std::shared_ptr<P2Payload>>& payloads) {
return payloads[0]->mRequest->mLog;
}
template <typename T>
MBOOL BasicProcessor::processP2(T payload) {
ILog log = getILog(payload);
TRACE_S_FUNC_ENTER(log);
MBOOL ret = MFALSE;
P2Cookie* cookie = createCookie(log, payload);
if (cookie != nullptr) {
P2_CAM_TRACE_NAME(TRACE_ADVANCED, "P2_Basic:drv enq");
QParams qparams = prepareEnqueQParams(payload);
qparams.mpCookie = reinterpret_cast<void*>(cookie);
qparams.mpfnCallback = BasicProcessor::p2CB;
ret = mNormalStream->enque(&qparams);
if (!ret) {
MY_S_LOGW(log, "enque failed");
updateResult(payload, MFALSE);
freeCookie(cookie, NO_CHECK_ORDER);
}
}
TRACE_S_FUNC_EXIT(log);
return ret;
}
QParams BasicProcessor::prepareEnqueQParams(
std::shared_ptr<P2Payload> payload) {
TRACE_S_FUNC_ENTER(payload->mRequest->mLog);
NSCam::Feature::P2Util::printQParams(getILog(payload), payload->mQParams);
TRACE_S_FUNC_EXIT(payload->mRequest->mLog);
return payload->mQParams;
}
QParams BasicProcessor::prepareEnqueQParams(
std::vector<std::shared_ptr<P2Payload>> payloads) {
TRACE_S_FUNC_ENTER(payloads[0]->mRequest->mLog);
QParams qparams;
for (std::shared_ptr<P2Payload> payload : payloads) {
qparams.mvFrameParams.insert(qparams.mvFrameParams.end(),
payload->mQParams.mvFrameParams.begin(),
payload->mQParams.mvFrameParams.end());
}
TRACE_S_FUNC_EXIT(payloads[0]->mRequest->mLog);
return qparams;
}
MVOID BasicProcessor::updateResult(std::shared_ptr<P2Payload> payload,
MBOOL result) {
TRACE_S_FUNC_ENTER(payload->mRequest->mLog);
payload->mQParams.mDequeSuccess = result;
payload->mRequest->updateResult(result);
TRACE_S_FUNC_EXIT(payload->mRequest->mLog);
}
MVOID BasicProcessor::updateResult(
std::vector<std::shared_ptr<P2Payload>> payloads, MBOOL result) {
TRACE_S_FUNC_ENTER(payloads[0]->mRequest->mLog);
for (std::shared_ptr<P2Payload> payload : payloads) {
payload->mQParams.mDequeSuccess = result;
payload->mRequest->updateResult(result);
}
TRACE_S_FUNC_EXIT(payloads[0]->mRequest->mLog);
}
MVOID BasicProcessor::processP2CB(const QParams& qparams, P2Cookie* cookie) {
TRACE_S_FUNC_ENTER(mLog);
if (cookie) {
for (std::shared_ptr<P2Payload> payload : cookie->mPayloads) {
payload->mQParams.mDequeSuccess = qparams.mDequeSuccess;
onP2CB(payload->mQParams, payload);
}
freeCookie(cookie, CHECK_ORDER);
cookie = nullptr;
}
TRACE_S_FUNC_EXIT(mLog);
}
template <typename T>
BasicProcessor::P2Cookie* BasicProcessor::createCookie(const ILog& log,
const T& payload) {
TRACE_S_FUNC_ENTER(log);
P2Cookie* cookie = nullptr;
cookie = new P2Cookie(this, payload);
if (cookie == nullptr) {
MY_S_LOGE(log, "OOM: cannot create P2Cookie");
} else {
std::lock_guard<std::mutex> _lock(mP2CookieMutex);
mP2CookieList.push_back(cookie);
}
TRACE_S_FUNC_EXIT(log);
return cookie;
}
MBOOL BasicProcessor::freeCookie(P2Cookie* cookie, MBOOL checkOrder) {
TRACE_S_FUNC_ENTER(mLog);
MBOOL ret = MFALSE;
if (cookie == nullptr) {
MY_S_LOGW(mLog, "invalid cookie = nullptr");
} else {
std::lock_guard<std::mutex> _lock(mP2CookieMutex);
auto it = find(mP2CookieList.begin(), mP2CookieList.end(), cookie);
if (it != mP2CookieList.end()) {
if (checkOrder && it != mP2CookieList.begin()) {
MY_S_LOGW(cookie->getILog(), "callback out of order");
}
delete cookie;
cookie = nullptr;
mP2CookieList.erase(it);
mP2Condition.notify_all();
ret = MTRUE;
} else {
MY_S_LOGE(mLog, "Cookie not freed: invalid data=%p", cookie);
}
}
TRACE_S_FUNC_EXIT(mLog);
return ret;
}
MVOID BasicProcessor::p2CB(QParams* pQparams) {
TRACE_FUNC_ENTER();
P2Cookie* cookie = reinterpret_cast<P2Cookie*>(pQparams->mpCookie);
if (cookie && cookie->mParent) {
cookie->mParent->processP2CB(*pQparams, cookie);
}
TRACE_FUNC_EXIT();
}
MVOID BasicProcessor::waitP2CBDone() {
TRACE_S_FUNC_ENTER(mLog);
std::unique_lock<std::mutex> _lock(mP2CookieMutex);
while (mP2CookieList.size()) {
mP2Condition.wait(_lock);
}
TRACE_S_FUNC_EXIT(mLog);
}
MBOOL BasicProcessor::processBurst(const std::shared_ptr<P2Payload>& payload) {
TRACE_S_FUNC_ENTER(payload->mRequest->mLog);
MUINT32 burst = payload->mRequest->mP2Pack.getConfigInfo().mBurstNum;
burst = FORCE_BURST ? 4 : burst;
burst = payload->mRequest->isResized() ? burst : 0;
MUINT8 reqtSmvrFps = (MUINT8)MTK_SMVR_FPS_30;
if (payload->mRequest != nullptr) {
std::shared_ptr<P2Meta> spHalMeta = payload->mRequest->getMeta(IN_P1_HAL);
if (tryGet<MUINT8>(spHalMeta, MTK_HAL_REQUEST_SMVR_FPS, &reqtSmvrFps)) {
MY_LOGE("!!err: tryGet IN_P1_HAL error");
}
}
if (reqtSmvrFps != (MUINT8)MTK_SMVR_FPS_30) {
if (burst > 1) {
mBurstQueue.push_back(payload);
}
if (mBurstQueue.size() && mBurstQueue.size() >= burst) {
processP2(mBurstQueue);
mBurstQueue.clear();
}
}
TRACE_S_FUNC_EXIT(payload->mRequest->mLog,
"reqtSmvrFps=%d, burst(%d) queueSize(%d)", reqtSmvrFps,
burst, mBurstQueue.size());
return (burst > 1 && reqtSmvrFps != MTK_SMVR_FPS_30);
}
MBOOL BasicProcessor::checkBurst() {
TRACE_S_FUNC_ENTER(mLog);
MBOOL ret = MFALSE;
if (mBurstQueue.size()) {
processP2(mBurstQueue);
mBurstQueue.clear();
ret = MTRUE;
}
TRACE_S_FUNC_EXIT(mLog);
return ret;
}
} // namespace P2