blob: 38cb06115086d3a3af36e2bd29b5964c320b4185 [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.
*/
#undef LOG_TAG
#define LOG_TAG "mtkcam-PipelineModelSessionDefault"
// for scenario control
#include <mtkcam/drv/IHalSensor.h>
//
#include <impl/ControlMetaBufferGenerator.h>
#include <impl/PipelineContextBuilder.h>
#include <impl/PipelineFrameBuilder.h>
//
#include <memory>
#include <mtkcam/pipeline/hwnode/NodeId.h>
#include <mtkcam/pipeline/model/session/PipelineModelSessionDefault.h>
#include <mtkcam/pipeline/utils/streaminfo/IStreamInfoSetControl.h>
#include <string>
#include <vector>
#include "MyUtils.h"
/******************************************************************************
*
******************************************************************************/
using NSCam::v3::pipeline::model::PipelineModelSessionDefault;
/******************************************************************************
*
******************************************************************************/
auto PipelineModelSessionDefault::makeInstance(
std::string const& name, CtorParams const& rCtorParams __unused)
-> std::shared_ptr<IPipelineModelSession> {
auto pSession =
std::make_shared<PipelineModelSessionDefault>(name, rCtorParams);
int const err = pSession->configure();
if (CC_UNLIKELY(err != 0)) {
CAM_LOGE("[%s] err:%d(%s) - Fail on configure()", __FUNCTION__, err,
::strerror(-err));
return nullptr;
}
return pSession;
}
/******************************************************************************
*
******************************************************************************/
PipelineModelSessionDefault::PipelineModelSessionDefault(
std::string const& name, CtorParams const& rCtorParams)
: PipelineModelSessionBase(
{"Default/" +
std::to_string(rCtorParams.staticInfo.pPipelineStaticInfo->openId)},
rCtorParams) {
pthread_rwlock_init(&mRWLock_ConfigInfo2, NULL);
pthread_rwlock_init(&mRWLock_PipelineContext, NULL);
}
/******************************************************************************
*
******************************************************************************/
namespace local {
template <typename T>
static std::string toString(const std::vector<T>& o) {
std::string os;
for (size_t i = 0; i < o.size(); i++) {
if (o.size() > 1) {
os += base::StringPrintf(" [%zu] ", i);
}
os += toString(o[i]);
}
return os;
}
} // namespace local
auto PipelineModelSessionDefault::print(ConfigInfo2 const& o __unused) {
std::string os;
os += "{ empty ,need implement }";
return os;
}
/******************************************************************************
*
******************************************************************************/
auto PipelineModelSessionDefault::dumpState(
const std::vector<std::string>& options __unused) -> void {
PipelineModelSessionBase::dumpState(options);
// ConfigInfo2
std::shared_ptr<ConfigInfo2> pConfigInfo2;
{
pthread_rwlock_rdlock(&mRWLock_ConfigInfo2);
pConfigInfo2 = mConfigInfo2;
pthread_rwlock_unlock(&mRWLock_ConfigInfo2);
}
if (pConfigInfo2 != nullptr) {
print(*pConfigInfo2);
}
}
/******************************************************************************
*
******************************************************************************/
auto PipelineModelSessionDefault::getCurrentPipelineContext() const
-> std::shared_ptr<PipelineContext> {
pthread_rwlock_rdlock(&mRWLock_PipelineContext);
auto ret = mCurrentPipelineContext;
pthread_rwlock_unlock(&mRWLock_PipelineContext);
return ret;
}
/******************************************************************************
*
******************************************************************************/
auto PipelineModelSessionDefault::configure() -> int {
// Allocate mConfigInfo2
mConfigInfo2 = std::make_shared<ConfigInfo2>();
// Initialize mConfigInfo2
{
NSCam::v3::pipeline::policy::pipelinesetting::ConfigurationOutputParams out{
.pStreamingFeatureSetting = &mConfigInfo2->mStreamingFeatureSetting,
.pCaptureFeatureSetting = &mConfigInfo2->mCaptureFeatureSetting,
.pPipelineNodesNeed = &mConfigInfo2->mPipelineNodesNeed,
.pSensorSetting = &mConfigInfo2->mvSensorSetting,
.pP1HwSetting = &mConfigInfo2->mvP1HwSetting,
.pP1DmaNeed = &mConfigInfo2->mvP1DmaNeed,
.pParsedStreamInfo_P1 = &mConfigInfo2->mvParsedStreamInfo_P1,
.pParsedStreamInfo_NonP1 = &mConfigInfo2->mParsedStreamInfo_NonP1,
.pIsZSLMode = &mConfigInfo2->mIsZSLMode,
};
RETURN_ERROR_IF_NOT_OK(
mPipelineSettingPolicy->evaluateConfiguration(&out, {}),
"Fail on evaluateConfiguration");
}
// App Image Max. Buffer Number
RETURN_ERROR_IF_NOT_OK(
mPipelineSettingPolicy->decideConfiguredAppImageStreamMaxBufNum(
mStaticInfo.pUserConfiguration->pParsedAppImageStreamInfo.get(),
&mConfigInfo2->mStreamingFeatureSetting,
&mConfigInfo2->mCaptureFeatureSetting),
"Fail on decideConfiguredAppImageStreamMaxBufNum");
// some feature needs some information which get from config policy update.
// And, it has to do related before build pipeline context.
// This interface will help to do this.
RETURN_ERROR_IF_NOT_OK(updateBeforeBuildPipelineContext(),
"updateBeforeBuildPipelineContext faile");
// create capture related instances, MUST be after FeatureSettingPolicy
configureCaptureInFlight(
mConfigInfo2->mCaptureFeatureSetting.maxAppJpegStreamNum);
// build pipeline context
{
BuildPipelineContextInputParams const in{
.pipelineName = getSessionName(),
.pPipelineStaticInfo = mStaticInfo.pPipelineStaticInfo.get(),
.pPipelineUserConfiguration = mStaticInfo.pUserConfiguration.get(),
.pParsedStreamInfo_NonP1 = &mConfigInfo2->mParsedStreamInfo_NonP1,
.pvParsedStreamInfo_P1 = &mConfigInfo2->mvParsedStreamInfo_P1,
.pZSLProvider = nullptr,
.pvSensorSetting = &mConfigInfo2->mvSensorSetting,
.pvP1HwSetting = &mConfigInfo2->mvP1HwSetting,
.pPipelineNodesNeed = &mConfigInfo2->mPipelineNodesNeed,
.pStreamingFeatureSetting = &mConfigInfo2->mStreamingFeatureSetting,
.pCaptureFeatureSetting = &mConfigInfo2->mCaptureFeatureSetting,
.batchSize = 0,
.pOldPipelineContext = nullptr,
.pDataCallback = shared_from_this(),
.bUsingMultiThreadToBuildPipelineContext =
mbUsingMultiThreadToBuildPipelineContext,
.bIsReconfigure = false,
};
RETURN_ERROR_IF_NOT_OK(buildPipelineContext(&mCurrentPipelineContext, in),
"Fail on buildPipelineContext");
}
////////////////////////////////////////////////////////////////////////////
// Initialize the current sensor settings.
for (auto const& v : mConfigInfo2->mvSensorSetting) {
mSensorMode.push_back(v.sensorMode);
mSensorSize.push_back(v.sensorSize);
}
return OK;
}
/******************************************************************************
*
******************************************************************************/
auto PipelineModelSessionDefault::updateBeforeBuildPipelineContext() -> int {
return OK;
}
/******************************************************************************
*
******************************************************************************/
auto PipelineModelSessionDefault::submitOneRequest(
std::shared_ptr<ParsedAppRequest> const& request) -> int {
// On this function, use this local variable to serve the request.
std::shared_ptr<ConfigInfo2> pConfigInfo2;
{
pthread_rwlock_rdlock(&mRWLock_ConfigInfo2);
pConfigInfo2 = mConfigInfo2;
pthread_rwlock_unlock(&mRWLock_ConfigInfo2);
}
// Make a copy of the original App Meta Control
IMetadata appControl; // original app control
{
if (request == nullptr) {
MY_LOGD("request is NULL");
return -ENODEV;
}
auto pTempAppMetaControl =
request->pAppMetaControlStreamBuffer->tryReadLock(LOG_TAG);
if (CC_LIKELY(pTempAppMetaControl)) {
appControl = *pTempAppMetaControl;
request->pAppMetaControlStreamBuffer->unlock(LOG_TAG,
pTempAppMetaControl);
}
}
// Evaluate a result for a request.
NSCam::v3::pipeline::policy::pipelinesetting::RequestOutputParams out;
{
NSCam::v3::pipeline::policy::pipelinesetting::RequestInputParams const in{
.requestNo = request->requestNo,
.pRequest_AppImageStreamInfo = request->pParsedAppImageStreamInfo.get(),
.pRequest_AppControl = &appControl,
.pRequest_ParsedAppMetaControl = request->pParsedAppMetaControl.get(),
.pConfiguration_PipelineNodesNeed = &pConfigInfo2->mPipelineNodesNeed,
.pConfiguration_StreamInfo_NonP1 =
&pConfigInfo2->mParsedStreamInfo_NonP1,
.pConfiguration_StreamInfo_P1 = &pConfigInfo2->mvParsedStreamInfo_P1,
.pSensorMode = &mSensorMode,
.pSensorSize = &mSensorSize,
.isZSLMode = pConfigInfo2->mIsZSLMode,
};
RETURN_ERROR_IF_NOT_OK(mPipelineSettingPolicy->evaluateRequest(&out, in),
"Fail on evaluateRequest - requestNo:%d",
in.requestNo);
}
// Reconfiguration Flow
processReconfiguration(&out, &pConfigInfo2, request->requestNo);
// PipelineContext
auto pPipelineContext = getCurrentPipelineContext();
RETURN_ERROR_IF_NULLPTR(pPipelineContext, -ENODEV, "Bad PipelineContext");
////////////////////////////////////////////////////////////////////////////
// process each frame
MUINT32 lastFrameNo = 0;
auto processFrame = [&](NSCam::v3::pipeline::policy::pipelinesetting::
RequestResultParams const& result,
int frameType) -> int {
std::vector<std::shared_ptr<IMetaStreamBuffer>> vAppMeta;
generateControlAppMetaBuffer(
&vAppMeta,
(frameType == eFRAMETYPE_MAIN) ? request->pAppMetaControlStreamBuffer
: nullptr,
&appControl, result.additionalApp.get(),
pConfigInfo2->mParsedStreamInfo_NonP1.pAppMeta_Control);
std::vector<std::shared_ptr<HalMetaStreamBuffer>> vHalMeta;
for (size_t i = 0; i < pConfigInfo2->mvParsedStreamInfo_P1.size(); ++i) {
MY_LOGD("generate (%zu) in metadata", i);
generateControlHalMetaBuffer(
&vHalMeta, result.additionalHal[i].get(),
pConfigInfo2->mvParsedStreamInfo_P1[i].pHalMeta_Control);
}
std::shared_ptr<IPipelineFrame> pPipelineFrame;
BuildPipelineFrameInputParams const params = {
.requestNo = request->requestNo,
.pAppImageStreamBuffers =
(frameType == eFRAMETYPE_MAIN
? request->pParsedAppImageStreamBuffers.get()
: nullptr),
.pAppMetaStreamBuffers = (vAppMeta.empty() ? nullptr : &vAppMeta),
.pHalImageStreamBuffers = nullptr,
.pHalMetaStreamBuffers = (vHalMeta.empty() ? nullptr : &vHalMeta),
.pvUpdatedImageStreamInfo = &(result.vUpdatedImageStreamInfo),
.pnodeSet = &result.nodeSet,
.pnodeIOMapImage = &(result.nodeIOMapImage),
.pnodeIOMapMeta = &(result.nodeIOMapMeta),
.pRootNodes = &(result.roots),
.pEdges = &(result.edges),
.pCallback =
(frameType == eFRAMETYPE_MAIN ? shared_from_this() : nullptr),
.pPipelineContext = pPipelineContext};
MY_LOGD(
"process request (%u): frametype(%d), sub(%u), preDummy(%u), "
"postDummy(%u), enableZSL(%d)",
request->requestNo, frameType, out.subFrames.size(),
out.preDummyFrames.size(), out.postDummyFrames.size(), out.needZslFlow);
RETURN_ERROR_IF_NOT_OK(buildPipelineFrame(&pPipelineFrame, params),
"buildPipelineFrame fail - requestNo:%u",
request->requestNo);
lastFrameNo = pPipelineFrame->getFrameNo();
RETURN_ERROR_IF_NOT_OK(pPipelineContext->queue(pPipelineFrame),
"PipelineContext::queue fail - requestNo:%u",
request->requestNo);
return OK;
};
// pre-dummy frames
for (auto const& frame : out.preDummyFrames) {
RETURN_ERROR_IF_NOT_OK(processFrame(*frame, eFRAMETYPE_PREDUMMY),
"processFrame preDummyFrame fail");
}
// main frame
{
RETURN_ERROR_IF_NOT_OK(processFrame(*out.mainFrame, eFRAMETYPE_MAIN),
"processFrame mainFrame fail");
}
// sub frames
for (auto const& frame : out.subFrames) {
RETURN_ERROR_IF_NOT_OK(processFrame(*frame, eFRAMETYPE_SUB),
"processFrame subFrame fail");
}
// post-dummy frames
for (auto const& frame : out.postDummyFrames) {
RETURN_ERROR_IF_NOT_OK(processFrame(*frame, eFRAMETYPE_POSTDUMMY),
"processFrame postDummyFrame fail");
}
if (out.mainFrame->nodesNeed.needJpegNode) {
mpCaptureInFlightRequest->insertRequest(request->requestNo,
eMSG_INFLIGHT_NORMAL);
}
if (out.boostScenario != -1 &&
out.boostScenario != IScenarioControlV3::Scenario_None) {
mpScenarioCtrl->boostScenario(out.boostScenario, out.featureFlag,
lastFrameNo);
}
// End of Reconfiguration Flow
processEndSubmitOneRequest(&out);
return OK;
}
/******************************************************************************
*
******************************************************************************/
auto PipelineModelSessionDefault::beginFlush() -> int {
auto pPipelineContext = getCurrentPipelineContext();
RETURN_ERROR_IF_NULLPTR(pPipelineContext, OK, "No current pipeline context");
RETURN_ERROR_IF_NOT_OK(pPipelineContext->flush(), "PipelineContext::flush()");
return OK;
}
/******************************************************************************
*
******************************************************************************/
MVOID
PipelineModelSessionDefault::updateFrame(MUINT32 const requestNo,
MINTPTR const userId,
Result const& result) {
if (result.bFrameEnd) {
mpCaptureInFlightRequest->removeRequest(requestNo);
return;
}
StreamId_T streamId = -1L;
{
pthread_rwlock_rdlock(&mRWLock_ConfigInfo2);
streamId = mConfigInfo2->mvParsedStreamInfo_P1[0]
.pHalMeta_DynamicP1->getStreamId();
pthread_rwlock_unlock(&mRWLock_ConfigInfo2);
}
auto timestampStartOfFrame =
determineTimestampSOF(streamId, result.vHalOutMeta);
updateFrameTimestamp(requestNo, userId, result, timestampStartOfFrame);
}
/******************************************************************************
*
******************************************************************************/
auto PipelineModelSessionDefault::updateFrameTimestamp(
MUINT32 const requestNo,
MINTPTR const userId,
Result const& result,
int64_t timestampStartOfFrame) -> void {
PipelineModelSessionBase::updateFrameTimestamp(requestNo, userId, result,
timestampStartOfFrame);
}
/******************************************************************************
*
******************************************************************************/
auto PipelineModelSessionDefault::processReconfiguration(
NSCam::v3::pipeline::policy::pipelinesetting::RequestOutputParams*
rcfOutputParam,
std::shared_ptr<ConfigInfo2>* pConfigInfo2 __unused,
MUINT32 requestNo __unused) -> int {
if (!rcfOutputParam->needReconfiguration) {
return OK;
}
MY_LOGW("[TODO] needReconfiguration - Not Implement");
return BAD_VALUE;
}
/******************************************************************************
*
******************************************************************************/
auto PipelineModelSessionDefault::configureCaptureInFlight(const int maxJpegNum)
-> int {
mpCaptureInFlightRequest = ICaptureInFlightRequest::createInstance(
mStaticInfo.pPipelineStaticInfo->openId, mSessionName);
if (!mpCaptureInFlightRequest) {
MY_LOGE("fail to create CaptureInFlighRequest");
return BAD_VALUE;
}
INextCaptureListener::CtorParams ctorParams;
ctorParams.maxJpegNum = maxJpegNum;
ctorParams.pCallback = mPipelineModelCallback;
mpNextCaptureListener = INextCaptureListener::createInstance(
mStaticInfo.pPipelineStaticInfo->openId, mSessionName, ctorParams);
if (mpNextCaptureListener) {
mpCaptureInFlightRequest->registerListener(mpNextCaptureListener);
} else {
MY_LOGE("fail to create NextCaptureListener");
return BAD_VALUE;
}
return OK;
}
/******************************************************************************
*
******************************************************************************/
auto PipelineModelSessionDefault::processEndSubmitOneRequest(
NSCam::v3::pipeline::policy::pipelinesetting::RequestOutputParams*
rcfOutputParam __unused) -> int {
return OK;
}
/******************************************************************************
*
******************************************************************************/
MVOID
PipelineModelSessionDefault::onNextCaptureCallBack(MUINT32 requestNo,
MINTPTR nodeId __unused) {
mpNextCaptureListener->onNextCaptureCallBack(requestNo);
}