blob: ee73195e41ffe114f868fd84f7934179a7aa2a99 [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-PipelineModelSessionStreaming"
//
#include <memory>
#include <string>
// for scenario control
#include <mtkcam/drv/IHalSensor.h>
//
#include <impl/ControlMetaBufferGenerator.h>
#include <impl/PipelineContextBuilder.h>
#include <impl/PipelineFrameBuilder.h>
//
#include "MyUtils.h"
//
#include <mtkcam/pipeline/model/session/PipelineModelSessionStreaming.h>
#include <mtkcam/pipeline/hwnode/NodeId.h>
#include <mtkcam/pipeline/hwnode/P1Node.h>
#include <mtkcam/pipeline/hwnode/P2StreamingNode.h>
#include <mtkcam/pipeline/hwnode/JpegNode.h>
#include <mtkcam/utils/hw/HwInfoHelper.h>
#include <mtkcam/utils/metadata/hal/mtk_platform_metadata_tag.h>
/******************************************************************************
*
******************************************************************************/
using NSCam::v3::pipeline::model::PipelineModelSessionStreaming;
/******************************************************************************
*
******************************************************************************/
auto PipelineModelSessionStreaming::makeInstance(std::string const& name,
CtorParams const& rCtorParams)
-> std::shared_ptr<IPipelineModelSession> {
std::shared_ptr<PipelineModelSessionStreaming> pSession =
std::make_shared<PipelineModelSessionStreaming>(name, rCtorParams);
if (CC_UNLIKELY(pSession == nullptr)) {
CAM_LOGE("[%s] Bad pSession", __FUNCTION__);
return nullptr;
}
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;
}
/******************************************************************************
*
******************************************************************************/
PipelineModelSessionStreaming::PipelineModelSessionStreaming(
std::string const& name, CtorParams const& rCtorParams)
: PipelineModelSessionDefault(
{name +
std::to_string(rCtorParams.staticInfo.pPipelineStaticInfo->openId)},
rCtorParams) {
mConfigInfo2 = nullptr;
}
/******************************************************************************
*
******************************************************************************/
PipelineModelSessionStreaming::~PipelineModelSessionStreaming() {}
/******************************************************************************
*
******************************************************************************/
auto PipelineModelSessionStreaming::processReconfiguration(
NSCam::v3::pipeline::policy::pipelinesetting::RequestOutputParams*
rcfOutputParam __unused,
std::shared_ptr<ConfigInfo2>* pConfigInfo2 __unused,
MUINT32 requestNo) -> int {
pthread_rwlock_wrlock(&mRWLock_PipelineContext);
auto ret = BAD_VALUE;
if (!rcfOutputParam->needReconfiguration) {
ret = OK;
} else if (rcfOutputParam->reconfigCategory ==
NSCam::v3::pipeline::policy::ReCfgCtg::STREAMING) {
// reconfigCategory is Stream
if (processReconfigStream(rcfOutputParam, pConfigInfo2, requestNo) != OK) {
MY_LOGE("reconfigCategory(%hhu): processReconfigStream Error",
rcfOutputParam->reconfigCategory);
ret = BAD_VALUE;
}
ret = OK;
} else if (rcfOutputParam->reconfigCategory ==
NSCam::v3::pipeline::policy::ReCfgCtg::CAPTURE) {
ret = OK;
}
pthread_rwlock_unlock(&mRWLock_PipelineContext);
return ret;
}
/******************************************************************************
*
******************************************************************************/
auto PipelineModelSessionStreaming::processReconfigStream(
NSCam::v3::pipeline::policy::pipelinesetting::RequestOutputParams*
rcfOutputParam __unused,
std::shared_ptr<ConfigInfo2>* pConfigInfo2 __unused,
MUINT32 requestNo) -> int {
MY_LOGD("requestNo(%d) processReconfigStream +", requestNo);
MBOOL ret = INVALID_OPERATION;
ret = waitUntilP1NodeDrainedAndFlush();
if (ret != OK) {
ALOGE("waitUntilP1NodeDrainedAndFlush Fail!");
return ret;
}
ret = waitUntilP2DrainedAndFlush();
if (ret != OK) {
ALOGE("waitUntilP2DrainedAndFlush Fail!");
return ret;
}
mCurrentPipelineContext = nullptr;
*pConfigInfo2 = std::make_shared<ConfigInfo2>();
RETURN_ERROR_IF_NULLPTR(*pConfigInfo2, -ENODEV,
"Fail on make_shared<ConfigInfo2>");
NSCam::v3::pipeline::policy::pipelinesetting::ConfigurationOutputParams
rcfOutParam{
.pStreamingFeatureSetting =
&(*pConfigInfo2)->mStreamingFeatureSetting,
.pCaptureFeatureSetting = &(*pConfigInfo2)->mCaptureFeatureSetting,
.pPipelineNodesNeed = &(*pConfigInfo2)->mPipelineNodesNeed,
.pSensorSetting = &(*pConfigInfo2)->mvSensorSetting,
.pP1HwSetting = &(*pConfigInfo2)->mvP1HwSetting,
.pP1DmaNeed = &(*pConfigInfo2)->mvP1DmaNeed,
.pParsedStreamInfo_P1 = &(*pConfigInfo2)->mvParsedStreamInfo_P1,
.pParsedStreamInfo_NonP1 = &(*pConfigInfo2)->mParsedStreamInfo_NonP1,
.pIsZSLMode = &(*pConfigInfo2)->mIsZSLMode,
};
RETURN_ERROR_IF_NOT_OK(
mPipelineSettingPolicy->evaluateConfiguration(&rcfOutParam, {}),
"Fail on Pipeline Reconfiguration");
// App Image Max. Buffer Number
RETURN_ERROR_IF_NOT_OK(
mPipelineSettingPolicy->decideConfiguredAppImageStreamMaxBufNum(
mStaticInfo.pUserConfiguration->pParsedAppImageStreamInfo.get(),
&(*pConfigInfo2)->mStreamingFeatureSetting,
&(*pConfigInfo2)->mCaptureFeatureSetting),
"Fail on decideConfiguredAppImageStreamMaxBufNum");
// create capture related instances, MUST be after FeatureSettingPolicy
configureCaptureInFlight(
(*pConfigInfo2)->mCaptureFeatureSetting.maxAppJpegStreamNum);
BuildPipelineContextInputParams const in{
.pipelineName = getSessionName(),
.pPipelineStaticInfo = mStaticInfo.pPipelineStaticInfo.get(),
.pPipelineUserConfiguration = mStaticInfo.pUserConfiguration.get(),
.pParsedStreamInfo_NonP1 = &(*pConfigInfo2)->mParsedStreamInfo_NonP1,
.pvParsedStreamInfo_P1 = &(*pConfigInfo2)->mvParsedStreamInfo_P1,
.pZSLProvider = nullptr,
.pvSensorSetting = &(*pConfigInfo2)->mvSensorSetting,
.pvP1HwSetting = &(*pConfigInfo2)->mvP1HwSetting,
.pPipelineNodesNeed = &(*pConfigInfo2)->mPipelineNodesNeed,
.pStreamingFeatureSetting = &(*pConfigInfo2)->mStreamingFeatureSetting,
.pCaptureFeatureSetting = &mConfigInfo2->mCaptureFeatureSetting,
.batchSize = 0,
.pOldPipelineContext = nullptr,
.pDataCallback = shared_from_this(),
.bUsingMultiThreadToBuildPipelineContext =
mbUsingMultiThreadToBuildPipelineContext,
.bIsReconfigure = true,
};
// Create New pipeline context for streaming.
RETURN_ERROR_IF_NOT_OK(buildPipelineContext(&mCurrentPipelineContext, in),
"Fail on buildPipelineContext");
MY_LOGD("requestNo(%d) processReconfigStream -", requestNo);
return OK;
}
/******************************************************************************
*
******************************************************************************/
auto PipelineModelSessionStreaming::waitUntilP1NodeDrainedAndFlush() -> MERROR {
MERROR err = OK;
std::shared_ptr<PipelineContext> pPipelineContext =
getCurrentPipelineContext();
if (!pPipelineContext.get()) {
MY_LOGW("get pPipelineContext fail");
return UNKNOWN_ERROR;
}
MY_LOGD("waitUntilP1nodeDrainedAndFlush");
// P1
{
std::shared_ptr<NSCam::v3::NSPipelineContext::NodeActor<NSCam::v3::P1Node>>
nodeActor = nullptr;
err = waitUntilNodeDrainedAndFlush(eNODEID_P1Node, &nodeActor);
if (err != OK) {
MY_LOGW("get wait until node(%d) drained and flush fail", eNODEID_P1Node);
return err;
}
}
return err;
}
/******************************************************************************
*
******************************************************************************/
auto PipelineModelSessionStreaming::waitUntilP2DrainedAndFlush() -> MERROR {
MERROR err = OK;
std::shared_ptr<PipelineContext> pPipelineContext =
getCurrentPipelineContext();
if (!pPipelineContext.get()) {
MY_LOGW("get pPipelineContext fail");
return UNKNOWN_ERROR;
}
MY_LOGD("waitUntilP2DrainedAndFlush");
// P2
{
std::shared_ptr<
NSCam::v3::NSPipelineContext::NodeActor<NSCam::v3::P2StreamingNode>>
nodeActor = nullptr;
err = waitUntilNodeDrainedAndFlush(eNODEID_P2StreamNode, &nodeActor);
if (err != OK) {
MY_LOGW("get wait until node(%d) drained and flush fail",
eNODEID_P2StreamNode);
return err;
}
}
return err;
}
/******************************************************************************
*
******************************************************************************/
template <typename _Node_>
MERROR PipelineModelSessionStreaming::waitUntilNodeDrainedAndFlush(
NodeId_T const nodeId,
std::shared_ptr<NSCam::v3::NSPipelineContext::NodeActor<_Node_>>*
pNodeActor) {
std::shared_ptr<PipelineContext> pPipelineContext =
getCurrentPipelineContext();
if (!pPipelineContext.get()) {
MY_LOGW("get pPipelineContext fail");
return UNKNOWN_ERROR;
}
MERROR err = pPipelineContext->queryNodeActor(nodeId, pNodeActor);
if (err != NAME_NOT_FOUND) {
if (err != OK || *pNodeActor == nullptr) {
MY_LOGW("get NodeActor(%" PRIdPTR ") fail", nodeId);
return err;
}
//
err = pPipelineContext->waitUntilNodeDrained(nodeId);
if (err != OK) {
MY_LOGW("wait until node(%" PRIdPTR ") drained fail", nodeId);
return err;
}
//
std::shared_ptr<IPipelineNode> node = (*pNodeActor)->getNode();
if (node == nullptr) {
MY_LOGW("get node(%" PRIdPTR ") fail", nodeId);
return UNKNOWN_ERROR;
}
//
err = node->flush();
if (err != OK) {
MY_LOGW("flush node(%" PRIdPTR ") fail", nodeId);
return err;
}
}
return OK;
}