blob: 586322af0ccc78762ac81d69cb3d152f40510323 [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.
*/
#define LOG_TAG "MtkCam/ppl_context"
//
#include <memory>
#include "MyUtils.h"
#include "PipelineContextImpl.h"
#include <property_lib.h>
#include <string>
#include <vector>
//
using NSCam::v3::NSPipelineContext::ContextNode;
using NSCam::v3::NSPipelineContext::DispatcherBase;
using NSCam::v3::NSPipelineContext::HalImageStreamBufferPoolT;
using NSCam::v3::NSPipelineContext::INodeActor;
using NSCam::v3::NSPipelineContext::IOMapSet;
using NSCam::v3::NSPipelineContext::PipelineContext;
/******************************************************************************
*
******************************************************************************/
const IOMapSet& IOMapSet::buildEmptyIOMap() {
static IOMapSet o;
return o;
}
/******************************************************************************
*
******************************************************************************/
std::shared_ptr<PipelineContext> PipelineContext::create(char const* name) {
return std::make_shared<PipelineContext>(name);
}
/******************************************************************************
*
******************************************************************************/
PipelineContext::PipelineContext(char const* name)
: mpImpl(std::make_shared<PipelineContextImpl>(name)) {}
/******************************************************************************
*
******************************************************************************/
PipelineContext::~PipelineContext() {
MY_LOGD("deconstruction");
onLastStrongRef(nullptr);
}
/******************************************************************************
*
******************************************************************************/
void PipelineContext::onLastStrongRef(const void* /*id*/) {
std::string name(mpImpl->getName());
MY_LOGD("name: %s(%p) +", name.c_str(), this);
mpImpl = nullptr;
MY_LOGD("name: %s -", name.c_str());
}
/******************************************************************************
*
******************************************************************************/
char const* PipelineContext::getName() const {
return mpImpl->getName();
}
/******************************************************************************
*
******************************************************************************/
MERROR
PipelineContext::beginConfigure(std::shared_ptr<PipelineContext> oldContext) {
FUNC_START;
// if old == current
if (oldContext.get() == this) {
MY_LOGW("context: old == this");
return INVALID_OPERATION;
}
waitUntilDrained();
mpOldContext = oldContext;
FUNC_END;
return OK;
}
/******************************************************************************
*
******************************************************************************/
MERROR
PipelineContext::endConfigure(MBOOL const parallelConfig) {
MERROR err;
// DEBUG
int Enable_Dump = property_get_int32("vendor.pipeline.state.dump", 0);
if (Enable_Dump) {
dump();
}
//
if (OK !=
(err = getImpl()->config(mpOldContext ? mpOldContext->getImpl() : nullptr,
parallelConfig))) {
MY_LOGE("config fail");
return err;
}
// release old context
mpOldContext = nullptr;
return OK;
}
/******************************************************************************
*
******************************************************************************/
MERROR
PipelineContext::queue(std::shared_ptr<IPipelineFrame> const& pFrame) {
return getImpl()->queue(pFrame);
}
/******************************************************************************
*
******************************************************************************/
MERROR
PipelineContext::kick(std::shared_ptr<IPipelineFrame> const& pFrame) {
return getImpl()->kick(pFrame);
}
/******************************************************************************
*
******************************************************************************/
MERROR
PipelineContext::flush() {
FUNC_START;
// begin flush
getImpl()->beginFlush();
//
// wait until drained
getImpl()->waitUntilDrained();
//
// end flush
getImpl()->endFlush();
//
FUNC_END;
return OK;
}
/******************************************************************************
*
******************************************************************************/
MERROR
PipelineContext::waitUntilDrained() {
FUNC_START;
//
getImpl()->waitUntilDrained();
//
FUNC_END;
return OK;
}
/******************************************************************************
*
******************************************************************************/
MERROR
PipelineContext::waitUntilNodeDrained(NodeId_T const nodeId) {
FUNC_START;
//
getImpl()->waitUntilNodeDrained(nodeId);
//
FUNC_END;
return OK;
}
/******************************************************************************
*
******************************************************************************/
MERROR
PipelineContext::setScenarioControl(
std::shared_ptr<NSCam::IScenarioControl> pControl) {
return getImpl()->setScenarioControl(pControl);
}
/******************************************************************************
*
******************************************************************************/
std::shared_ptr<NSCam::IScenarioControl> PipelineContext::getScenarioControl()
const {
return getImpl()->getScenarioControl();
}
/******************************************************************************
*
******************************************************************************/
MERROR
PipelineContext::setDispatcher(std::weak_ptr<IDispatcher> pDispatcher) {
return getImpl()->setDispatcher(pDispatcher);
}
/******************************************************************************
*
******************************************************************************/
MERROR
PipelineContext::setDataCallback(std::weak_ptr<IDataCallback> pCallback) {
return getImpl()->setDataCallback(pCallback);
}
/******************************************************************************
*
******************************************************************************/
std::shared_ptr<HalImageStreamBufferPoolT>
PipelineContext::queryImageStreamPool(StreamId_T const streamId) const {
return getImpl()->queryImageStreamPool(streamId);
}
/******************************************************************************
*
******************************************************************************/
std::shared_ptr<INodeActor> PipelineContext::queryINodeActor(
NodeId_T const nodeId) const {
return getImpl()->queryNode(nodeId);
}
/******************************************************************************
*
******************************************************************************/
MERROR
PipelineContext::queryStream(StreamId_T const streamId,
std::shared_ptr<IImageStreamInfo>* pStreamInfo) {
std::shared_ptr<PipelineContextImpl> pImpl;
pImpl.reset(this->getImpl());
if (!pImpl.get()) {
MY_LOGE("null contextimpl");
return NAME_NOT_FOUND;
}
//
std::shared_ptr<StreamConfig::ItemImageStream> pItem =
pImpl->queryImage(streamId);
if (!pItem.get() || !pItem->pInfo.get()) {
MY_LOGD("no previous image stream");
// this might success if both previous & new-coming pipeline have no this
// stream.
*pStreamInfo = nullptr;
return OK;
}
//
*pStreamInfo = pItem->pInfo;
return OK;
}
/******************************************************************************
*
******************************************************************************/
MERROR
PipelineContext::reuseStream(std::shared_ptr<IImageStreamInfo>* pStreamInfo) {
if (!pStreamInfo->get() || !queryOldContext().get() ||
!queryOldContext()->getImpl()) {
return NAME_NOT_FOUND;
}
//
MERROR err;
PipelineContextImpl* pOldImpl = queryOldContext()->getImpl();
StreamId_T const streamId = (*pStreamInfo)->getStreamId();
std::shared_ptr<StreamConfig::ItemImageStream> pItem =
pOldImpl->queryImage(streamId);
if (!pItem.get()) {
MY_LOGD("no previous stream");
return BAD_VALUE;
}
if (OK != (err = getImpl()->reuseStream(pItem))) {
return err;
}
*pStreamInfo = pItem->pInfo;
return OK;
}
/******************************************************************************
*
******************************************************************************/
MERROR
PipelineContext::reuseNode(NodeId_T const nodeId) {
if (!queryOldContext().get() || !queryOldContext()->getImpl()) {
return NAME_NOT_FOUND;
}
//
MERROR err;
PipelineContextImpl* const pOldImpl = queryOldContext()->getImpl();
//
std::shared_ptr<NodeConfig> pOldNodeCfg = pOldImpl->getNodeConfig();
if (!pOldNodeCfg.get()) {
MY_LOGD("no previous node config");
return BAD_VALUE;
}
std::shared_ptr<ContextNode> pNode = pOldNodeCfg->queryNode(nodeId);
if (!pNode.get()) {
MY_LOGD("no previous node context");
return BAD_VALUE;
}
//
StreamUsageMap const& usgMap = pOldNodeCfg->getImageStreamUsage(nodeId);
if (OK != (err = getImpl()->reuseNode(nodeId, pNode, usgMap))) {
return err;
}
return OK;
}
/******************************************************************************
*
******************************************************************************/
auto PipelineContext::dumpState(
const std::vector<std::string>& options __unused) -> void {
mpImpl->dumpState(options);
}
/******************************************************************************
*
******************************************************************************/
MVOID
PipelineContext::dump() {
mpImpl->dumpState({});
}
/******************************************************************************
*
******************************************************************************/
uint32_t PipelineContext::getFrameNo() {
return getImpl()->getFrameNo();
}
/******************************************************************************
*
******************************************************************************/
MVOID
PipelineContext::setMultiCamSyncHelper(
std::shared_ptr<MultiCamSyncHelper> const& helper) {
MY_LOGD("set sync helper (%p)", helper.get());
mpSyncHelper = helper;
}
/******************************************************************************
*
******************************************************************************/
auto PipelineContext::getMultiCamSyncHelper()
-> std::shared_ptr<MultiCamSyncHelper> {
return mpSyncHelper;
}
/******************************************************************************
*
******************************************************************************/
PipelineContext::PipelineContextImpl* PipelineContext::getImpl() const {
return mpImpl.get();
}
/******************************************************************************
*
******************************************************************************/
MUINT32
INodeActor::getStatus() const {
std::lock_guard<std::mutex> _l(mLock);
return muStatus;
}
/******************************************************************************
*
******************************************************************************/
#define PRECHECK_STATUS(_status_, _skip_st_, _expected_) \
do { \
if (_status_ >= _skip_st_) { \
MY_LOGD("%s already in state %d", getNode()->getNodeName(), _status_); \
return OK; \
} else if (_status_ != _expected_) { \
MY_LOGE("%s wrong status %d, expected %d", getNode()->getNodeName(), \
_status_, _expected_); \
return INVALID_OPERATION; \
} \
} while (0)
#define UPDATE_STATUS_IF_OK(_ret_, _status_var_, _newstatus_) \
do { \
if (_ret_ == OK) { \
_status_var_ = _newstatus_; \
} else { \
MY_LOGE("%s ret = %d", getNode()->getNodeName(), _ret_); \
} \
} while (0)
/******************************************************************************
*
******************************************************************************/
MERROR
INodeActor::init() {
std::lock_guard<std::mutex> _l(mLock);
PRECHECK_STATUS(muStatus, eNodeState_Init, eNodeState_Create);
MERROR const ret = onInit();
UPDATE_STATUS_IF_OK(ret, muStatus, eNodeState_Init);
return ret;
}
/******************************************************************************
*
******************************************************************************/
MERROR
INodeActor::config() {
std::lock_guard<std::mutex> _l(mLock);
PRECHECK_STATUS(muStatus, eNodeState_Config, eNodeState_Init);
MERROR const ret = onConfig();
UPDATE_STATUS_IF_OK(ret, muStatus, eNodeState_Config);
return ret;
}
/******************************************************************************
*
******************************************************************************/
MERROR
INodeActor::uninit() {
std::lock_guard<std::mutex> _l(mLock);
if (muStatus < eNodeState_Init) {
MY_LOGD("already uninit or not init");
return OK;
}
//
MERROR const ret = onUninit();
if (ret != OK) {
MY_LOGE("uninit failed");
}
// always update
muStatus = eNodeState_Create;
return ret;
}
/******************************************************************************
*
******************************************************************************/
ContextNode::ContextNode(NodeId_T const nodeId,
std::shared_ptr<INodeActor> pNode)
: mNodeId(nodeId),
mpNode(pNode)
//
,
mpInStreams(nullptr),
mpOutStreams(nullptr) {}
/******************************************************************************
*
******************************************************************************/
ContextNode::~ContextNode() {}
/******************************************************************************
*
******************************************************************************/
MVOID
DispatcherBase::onEarlyCallback(MUINT32 requestNo,
Pipeline_NodeId_T nodeId,
StreamId_T streamId,
IMetadata const& rMetaData,
MBOOL errorResult) {
std::shared_ptr<IDataCallback> pDataCallback = mpDataCallback.lock();
if (pDataCallback.get()) {
pDataCallback->onMetaCallback(requestNo, nodeId, streamId, rMetaData,
errorResult);
}
}
/******************************************************************************
*
******************************************************************************/
MVOID
DispatcherBase::onCtrlSetting(MUINT32 requestNo,
Pipeline_NodeId_T nodeId,
StreamId_T const metaAppStreamId,
IMetadata const& rAppMetaData,
StreamId_T const metaHalStreamId,
IMetadata const& rHalMetaData,
MBOOL const& rIsChanged) {
std::shared_ptr<IDataCallback> pDataCallback = mpDataCallback.lock();
if (pDataCallback.get()) {
if (pDataCallback->isCtrlSetting())
pDataCallback->onCtrlSetting(requestNo, nodeId, metaAppStreamId,
rAppMetaData, metaHalStreamId, rHalMetaData,
rIsChanged);
else
MY_LOGD("NOT Support ControlCallback - Setting");
}
}
/******************************************************************************
*
******************************************************************************/
MVOID
DispatcherBase::onCtrlSync(MUINT32 requestNo,
Pipeline_NodeId_T nodeId,
MUINT32 index,
MUINT32 type,
MINT64 duration) {
std::shared_ptr<IDataCallback> pDataCallback = mpDataCallback.lock();
if (pDataCallback.get()) {
if (pDataCallback->isCtrlSync())
pDataCallback->onCtrlSync(requestNo, nodeId, index, type, duration);
else
MY_LOGD("NOT Support ControlCallback - Sync");
}
}
/******************************************************************************
*
******************************************************************************/
MVOID
DispatcherBase::onCtrlResize(MUINT32 requestNo,
Pipeline_NodeId_T nodeId,
StreamId_T const metaAppStreamId,
IMetadata const& rAppMetaData,
StreamId_T const metaHalStreamId,
IMetadata const& rHalMetaData,
MBOOL const& rIsChanged) {
std::shared_ptr<IDataCallback> pDataCallback = mpDataCallback.lock();
if (pDataCallback.get()) {
if (pDataCallback->isCtrlResize())
pDataCallback->onCtrlResize(requestNo, nodeId, metaAppStreamId,
rAppMetaData, metaHalStreamId, rHalMetaData,
rIsChanged);
else
MY_LOGD("NOT Support ControlCallback - Resize");
}
}
/******************************************************************************
*
******************************************************************************/
MVOID
DispatcherBase::onCtrlReadout(MUINT32 requestNo,
Pipeline_NodeId_T nodeId,
StreamId_T const metaAppStreamId,
IMetadata const& rAppMetaData,
StreamId_T const metaHalStreamId,
IMetadata const& rHalMetaData,
MBOOL const& rIsChanged) {
std::shared_ptr<IDataCallback> pDataCallback = mpDataCallback.lock();
if (pDataCallback.get()) {
if (pDataCallback->isCtrlSetting())
pDataCallback->onCtrlSetting(requestNo, nodeId, metaAppStreamId,
rAppMetaData, metaHalStreamId, rHalMetaData,
rIsChanged);
else
MY_LOGD("NOT Support ControlCallback - Readout");
}
}
/******************************************************************************
*
******************************************************************************/
MBOOL
DispatcherBase::needCtrlCb(eCtrlType eType) {
std::shared_ptr<IDataCallback> pDataCallback = mpDataCallback.lock();
MBOOL res = MFALSE;
if (pDataCallback.get()) {
switch (eType) {
case eCtrl_Setting:
res = pDataCallback->isCtrlSetting();
break;
case eCtrl_Sync:
res = pDataCallback->isCtrlSync();
break;
case eCtrl_Resize:
res = pDataCallback->isCtrlResize();
break;
case eCtrl_Readout:
res = pDataCallback->isCtrlReadout();
break;
default:
break;
}
}
return res;
}
/******************************************************************************
*
******************************************************************************/
MVOID
DispatcherBase::onNextCaptureCallBack(MUINT32 requestNo,
Pipeline_NodeId_T nodeId) {
std::shared_ptr<IDataCallback> pDataCallback = mpDataCallback.lock();
if (pDataCallback.get()) {
pDataCallback->onNextCaptureCallBack(requestNo, nodeId);
}
}