/*
 * Copyright (C) 2015-2020 Intel Corporation.
 *
 * 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 "PlatformData"

#include <sys/sysinfo.h>
#include <math.h>
#include <memory>

#include "iutils/CameraLog.h"

#include "PlatformData.h"
#include "CameraParser.h"
#include "PolicyParser.h"
#include "ParameterHelper.h"

#include "gc/GraphConfigManager.h"

using std::string;
using std::vector;

namespace icamera {
PlatformData *PlatformData::sInstance = nullptr;
Mutex  PlatformData::sLock;

PlatformData* PlatformData::getInstance()
{
    AutoMutex lock(sLock);
    if (sInstance == nullptr) {
        sInstance = new PlatformData();
    }

    return sInstance;
}

void PlatformData::releaseInstance()
{
    AutoMutex lock(sLock);
    LOG1("@%s", __func__);

    if (sInstance) {
        delete sInstance;
        sInstance = nullptr;
    }
}

PlatformData::PlatformData()
{
    LOG1("@%s", __func__);
    MediaControl *mc = MediaControl::getInstance();
    if (mc) {
        mc->initEntities();
    }

    CameraParser CameraParser(mc, &mStaticCfg);
    PolicyParser PolicyParser(&mStaticCfg);
}

PlatformData::~PlatformData() {
    LOG1("@%s", __func__);

    releaseGraphConfigNodes();

    MediaControl::getInstance()->clearEntities();
    MediaControl::releaseInstance();

    for (size_t i = 0; i < mAiqInitData.size(); i++) {
        delete mAiqInitData[i];
    }

    mAiqInitData.clear();
}

int PlatformData::init() {
    LOG2("@%s", __func__);

    getInstance()->parseGraphFromXmlFile();

    StaticCfg *staticCfg = &(getInstance()->mStaticCfg);
    for (size_t i = 0; i < staticCfg->mCameras.size(); i++) {
        std::string camModuleName;
        AiqInitData* aiqInitData =
            new AiqInitData(staticCfg->mCameras[i].sensorName,
                            getCameraCfgPath(),
                            staticCfg->mCameras[i].mSupportedTuningConfig,
                            staticCfg->mCameras[i].mLardTagsConfig,
                            staticCfg->mCameras[i].mNvmDirectory,
                            staticCfg->mCameras[i].mMaxNvmDataSize, &camModuleName,
                            staticCfg->mCameras[i].mCameraModuleToAiqbMap);
        getInstance()->mAiqInitData.push_back(aiqInitData);

        if (!camModuleName.empty() &&
            staticCfg->mCameras[i].mCameraModuleInfoMap.find(camModuleName) !=
            staticCfg->mCameras[i].mCameraModuleInfoMap.end()) {
            ParameterHelper::merge(staticCfg->mCameras[i].mCameraModuleInfoMap[camModuleName],
                                  &staticCfg->mCameras[i].mCapability);
        }
    }

    return OK;
}

/**
 * Read graph descriptor and settings from configuration files.
 *
 * The resulting graphs represend all possible graphs for given sensor, and
 * they are stored in capinfo structure.
 */
void PlatformData::parseGraphFromXmlFile() {
    std::shared_ptr<GraphConfig> graphConfig = std::make_shared<GraphConfig>();

    // Assuming that PSL section from profiles is already parsed, and number
    // of cameras is known.
    graphConfig->addCustomKeyMap();
    for (size_t i = 0; i < getInstance()->mStaticCfg.mCameras.size(); ++i) {
        const string &fileName = getInstance()->mStaticCfg.mCameras[i].mGraphSettingsFile;
        if (fileName.empty()) {
            continue;
        }

        LOGXML("Using graph setting file:%s for camera:%zu", fileName.c_str(), i);
        int ret  = graphConfig->parse(i, fileName.c_str());
        CheckError(ret != OK, VOID_VALUE, "Could not read graph config file for camera %zu", i);
    }
}

void PlatformData::releaseGraphConfigNodes()
{
    std::shared_ptr<GraphConfig> graphConfig = std::make_shared<GraphConfig>();
    graphConfig->releaseGraphNodes();
    for (uint8_t cameraId = 0; cameraId < mStaticCfg.mCameras.size(); cameraId++) {
        IGraphConfigManager::releaseInstance(cameraId);
    }
}

const char* PlatformData::getSensorName(int cameraId)
{
    return getInstance()->mStaticCfg.mCameras[cameraId].sensorName.c_str();
}

const char* PlatformData::getSensorDescription(int cameraId)
{
    return getInstance()->mStaticCfg.mCameras[cameraId].sensorDescription.c_str();
}

const char* PlatformData::getLensName(int cameraId)
{
    return getInstance()->mStaticCfg.mCameras[cameraId].mLensName.c_str();
}

int PlatformData::getLensHwType(int cameraId)
{
    return getInstance()->mStaticCfg.mCameras[cameraId].mLensHwType;
}

int PlatformData::getDVSType(int cameraId)
{
    return getInstance()->mStaticCfg.mCameras[cameraId].mDVSType;
}

bool PlatformData::getISYSCompression(int cameraId)
{
    return getInstance()->mStaticCfg.mCameras[cameraId].mISYSCompression;
}

bool PlatformData::getPSACompression(int cameraId)
{
    return getInstance()->mStaticCfg.mCameras[cameraId].mPSACompression;
}

bool PlatformData::getOFSCompression(int cameraId)
{
    return getInstance()->mStaticCfg.mCameras[cameraId].mOFSCompression;
}

int PlatformData::getCITMaxMargin(int cameraId)
{
    return getInstance()->mStaticCfg.mCameras[cameraId].mCITMaxMargin;
}

bool PlatformData::isEnableAIQ(int cameraId)
{
    return getInstance()->mStaticCfg.mCameras[cameraId].mEnableAIQ;
}

bool PlatformData::isEnableLtmThread(int cameraId)
{
    return getInstance()->mStaticCfg.mCameras[cameraId].mEnableLtmThread;
}

bool PlatformData::isFaceAeEnabled(int cameraId)
{
    return getInstance()->mStaticCfg.mCameras[cameraId].mFaceAeEnabled;
}

int PlatformData::faceEngineRunningInterval(int cameraId)
{
    return getInstance()->mStaticCfg.mCameras[cameraId].mFaceEngineRunningInterval;
}

int PlatformData::faceEngineRunningIntervalNoFace(int cameraId)
{
    return getInstance()->mStaticCfg.mCameras[cameraId].mFaceEngineRunningIntervalNoFace;
}

bool PlatformData::isFaceEngineSyncRunning(int cameraId)
{
    return getInstance()->mStaticCfg.mCameras[cameraId].mFaceEngineRunningSync;
}

unsigned int PlatformData::getMaxFaceDetectionNumber(int cameraId)
{
    return getInstance()->mStaticCfg.mCameras[cameraId].mMaxFaceDetectionNumber;
}

bool PlatformData::isDvsSupported(int cameraId)
{
    camera_video_stabilization_list_t videoStabilizationList;
    Parameters* param = &getInstance()->mStaticCfg.mCameras[cameraId].mCapability;
    param->getSupportedVideoStabilizationMode(videoStabilizationList);

    bool supported = false;
    for (auto it : videoStabilizationList) {
        if (it == VIDEO_STABILIZATION_MODE_ON) {
            supported = true;
        }
    }

    LOG2("@%s, dvs supported:%d", __func__, supported);
    return supported;
}

bool PlatformData::psysAlignWithSof(int cameraId)
{
    return getInstance()->mStaticCfg.mCameras[cameraId].mPsysAlignWithSof;
}

bool PlatformData::psysBundleWithAic(int cameraId)
{
    return getInstance()->mStaticCfg.mCameras[cameraId].mPsysBundleWithAic;
}

bool PlatformData::swProcessingAlignWithIsp(int cameraId)
{
    return getInstance()->mStaticCfg.mCameras[cameraId].mSwProcessingAlignWithIsp;
}

bool PlatformData::isUsingSensorDigitalGain(int cameraId)
{
    return getInstance()->mStaticCfg.mCameras[cameraId].mUseSensorDigitalGain;
}

bool PlatformData::isUsingIspDigitalGain(int cameraId)
{
    return getInstance()->mStaticCfg.mCameras[cameraId].mUseIspDigitalGain;
}

bool PlatformData::isNeedToPreRegisterBuffer(int cameraId)
{
    return getInstance()->mStaticCfg.mCameras[cameraId].mNeedPreRegisterBuffers;
}

int PlatformData::getAutoSwitchType(int cameraId)
{
    return getInstance()->mStaticCfg.mCameras[cameraId].mAutoSwitchType;
}

bool PlatformData::isEnableFrameSyncCheck(int cameraId)
{
    return getInstance()->mStaticCfg.mCameras[cameraId].mFrameSyncCheckEnabled;
}

bool PlatformData::isEnableDefog(int cameraId)
{
    return getInstance()->mStaticCfg.mCameras[cameraId].mEnableLtmDefog;
}

int PlatformData::getExposureNum(int cameraId, bool multiExposure)
{
    if (multiExposure) {
        return getInstance()->mStaticCfg.mCameras[cameraId].mSensorExposureNum;
    }

    int exposureNum = 1;

    return exposureNum;
}

bool PlatformData::isLtmEnabled(int cameraId)
{

    return getInstance()->mStaticCfg.mCameras[cameraId].mLtmEnabled;
}

int PlatformData::getSensorExposureType(int cameraId)
{
    return getInstance()->mStaticCfg.mCameras[cameraId].mSensorExposureType;
}

int PlatformData::getSensorGainType(int cameraId)
{
    return getInstance()->mStaticCfg.mCameras[cameraId].mSensorGainType;
}

bool PlatformData::isSkipFrameOnSTR2MMIOErr(int cameraId)
{
    return getInstance()->mStaticCfg.mCameras[cameraId].mSkipFrameV4L2Error;
}

unsigned int PlatformData::getInitialSkipFrame(int cameraId)
{
    return getInstance()->mStaticCfg.mCameras[cameraId].mInitialSkipFrame;
}

unsigned int PlatformData::getMaxRawDataNum(int cameraId)
{
    return getInstance()->mStaticCfg.mCameras[cameraId].mMaxRawDataNum;
}

bool PlatformData::getTopBottomReverse(int cameraId)
{
    return getInstance()->mStaticCfg.mCameras[cameraId].mTopBottomReverse;
}

bool PlatformData::isPsysContinueStats(int cameraId)
{
    return getInstance()->mStaticCfg.mCameras[cameraId].mPsysContinueStats;
}

unsigned int PlatformData::getPreferredBufQSize(int cameraId)
{
    return getInstance()->mStaticCfg.mCameras[cameraId].mPreferredBufQSize;
}

unsigned int PlatformData::getPipeSwitchDelayFrame(int cameraId)
{
    return getInstance()->mStaticCfg.mCameras[cameraId].mPipeSwitchDelayFrame;
}

int PlatformData::getLtmGainLag(int cameraId)
{
    return getInstance()->mStaticCfg.mCameras[cameraId].mLtmGainLag;
}

int PlatformData::getMaxSensorDigitalGain(int cameraId)
{
    return getInstance()->mStaticCfg.mCameras[cameraId].mMaxSensorDigitalGain;
}

SensorDgType PlatformData::sensorDigitalGainType(int cameraId)
{
    return getInstance()->mStaticCfg.mCameras[cameraId].mSensorDgType;
}

int PlatformData::getDigitalGainLag(int cameraId)
{
    return getInstance()->mStaticCfg.mCameras[cameraId].mDigitalGainLag;
}

int PlatformData::getExposureLag(int cameraId)
{
    return getInstance()->mStaticCfg.mCameras[cameraId].mExposureLag;
}

int PlatformData::getAnalogGainLag(int cameraId)
{
    return getInstance()->mStaticCfg.mCameras[cameraId].mAnalogGainLag;
}

PolicyConfig* PlatformData::getExecutorPolicyConfig(int graphId)
{
    size_t i = 0;
    PlatformData::StaticCfg *cfg = &getInstance()->mStaticCfg;

    for (i = 0; i < cfg->mPolicyConfig.size(); i++) {
        if (graphId == cfg->mPolicyConfig[i].graphId) {
            return &(cfg->mPolicyConfig[i]);
        }
    }

    LOGW("Couldn't find the executor policy for graphId(%d), please check xml file", graphId);
    return nullptr;
}

int PlatformData::numberOfCameras()
{
    return getInstance()->mStaticCfg.mCameras.size();
}

int PlatformData::getXmlCameraNumber()
{
    return getInstance()->mStaticCfg.mCommonConfig.cameraNumber;
}

MediaCtlConf *PlatformData::getMediaCtlConf(int cameraId)
{
    return getInstance()->mStaticCfg.mCameras[cameraId].mCurrentMcConf;
}

int PlatformData::getCameraInfo(int cameraId, camera_info_t& info)
{
    // TODO correct the version info
    info.device_version = 1;
    info.facing = getInstance()->mStaticCfg.mCameras[cameraId].mFacing;
    info.orientation= getInstance()->mStaticCfg.mCameras[cameraId].mOrientation;
    info.name = getSensorName(cameraId);
    info.description = getSensorDescription(cameraId);
    info.capability = &getInstance()->mStaticCfg.mCameras[cameraId].mCapability;
    return OK;
}

bool PlatformData::isFeatureSupported(int cameraId, camera_features feature)
{
    camera_features_list_t features;
    getInstance()->mStaticCfg.mCameras[cameraId].mCapability.getSupportedFeatures(features);

    if (features.empty()) {
        return false;
    }
    for (auto& item : features) {
        if (item == feature) {
            return true;
        }
    }
    return false;
}

bool PlatformData::isSupportedStream(int cameraId, const stream_t& conf)
{
    int width = conf.width;
    int height = conf.height;
    int format = conf.format;
    int field = conf.field;

    stream_array_t availableConfigs;
    getInstance()->mStaticCfg.mCameras[cameraId].mCapability.getSupportedStreamConfig(availableConfigs);
    bool sameConfigFound = false;
    for (auto const& config : availableConfigs) {
        if (config.format == format && config.field == field
                && config.width == width && config.height == height) {
            sameConfigFound = true;
            break;
        }
    }

    return sameConfigFound;
}

void PlatformData::getSupportedISysSizes(int cameraId, vector <camera_resolution_t>& resolutions)
{
    resolutions = getInstance()->mStaticCfg.mCameras[cameraId].mSupportedISysSizes;
}

bool PlatformData::getSupportedISysFormats(int cameraId, vector <int>& formats)
{
    formats = getInstance()->mStaticCfg.mCameras[cameraId].mSupportedISysFormat;

    return true;
}

int PlatformData::getISysFormat(int cameraId)
{
    return getInstance()->mStaticCfg.mCameras[cameraId].mISysFourcc;
}

/**
 * The ISYS format is determined by the steps below:
 * 1. Try to use the specified format in media control config if it exists.
 * 2. If the given format is supported by ISYS, then use it.
 * 3. Use the first supported format if still could not find an appropriate one.
 */
void PlatformData::selectISysFormat(int cameraId, int format)
{
    MediaCtlConf *mc = getMediaCtlConf(cameraId);
    if (mc != nullptr && mc->format != -1) {
        getInstance()->mStaticCfg.mCameras[cameraId].mISysFourcc = mc->format;
    } else if (isISysSupportedFormat(cameraId, format)) {
        getInstance()->mStaticCfg.mCameras[cameraId].mISysFourcc = format;
    } else {
        // Set the first one in support list to default Isys output.
        vector <int> supportedFormat =
            getInstance()->mStaticCfg.mCameras[cameraId].mSupportedISysFormat;
        getInstance()->mStaticCfg.mCameras[cameraId].mISysFourcc = supportedFormat[0];
    }
}

/**
 * The media control config is determined by the steps below:
 * 1. Check if can get one from the given MC ID.
 * 2. And then, try to use ConfigMode to find matched one.
 * 3. Use stream config to get a corresponding mc id, and then get the config by id.
 * 4. Return nullptr if still could not find an appropriate one.
 */
void PlatformData::selectMcConf(int cameraId, stream_t stream, ConfigMode mode, int mcId)
{
    if (!isIsysEnabled(cameraId)) return;

    const StaticCfg::CameraInfo& pCam = getInstance()->mStaticCfg.mCameras[cameraId];

    MediaCtlConf* mcConfig = getMcConfByMcId(pCam, mcId);
    if (!mcConfig) {
        mcConfig = getMcConfByConfigMode(pCam, stream, mode);
    }

    if (!mcConfig) {
        mcConfig = getMcConfByStream(pCam, stream);
    }

    getInstance()->mStaticCfg.mCameras[cameraId].mCurrentMcConf = mcConfig;

    if (!mcConfig) {
        LOGE("No matching McConf: cameraId %d, configMode %d, mcId %d", cameraId, mode, mcId);
    }
}

/*
 * Find the MediaCtlConf based on the given MC id.
 */
MediaCtlConf* PlatformData::getMcConfByMcId(const StaticCfg::CameraInfo& cameraInfo, int mcId)
{
    if (mcId == -1) {
        return nullptr;
    }

    for (auto& mc : cameraInfo.mMediaCtlConfs) {
        if (mcId == mc.mcId) {
            return (MediaCtlConf*)&mc;
        }
    }

    return nullptr;
}

/*
 * Find the MediaCtlConf based on MC id in mStreamToMcMap.
 */
MediaCtlConf* PlatformData::getMcConfByStream(const StaticCfg::CameraInfo& cameraInfo,
                                              const stream_t& stream)
{
    int mcId = -1;
    for (auto& table : cameraInfo.mStreamToMcMap) {
        for(auto& config : table.second) {
            if (config.format == stream.format && config.field == stream.field
                    && config.width == stream.width && config.height == stream.height) {
                mcId = table.first;
                break;
            }
        }
        if (mcId != -1) {
            break;
        }
    }

    return getMcConfByMcId(cameraInfo, mcId);
}

/*
 * Find the MediaCtlConf based on operation mode and stream info.
 */
MediaCtlConf* PlatformData::getMcConfByConfigMode(const StaticCfg::CameraInfo& cameraInfo,
                                                  const stream_t& stream, ConfigMode mode)
{
    for (auto& mc : cameraInfo.mMediaCtlConfs) {
        for (auto& cfgMode : mc.configMode) {
            if (mode != cfgMode) continue;

            int outputWidth = mc.outputWidth;
            int outputHeight = mc.outputHeight;
            int stride = CameraUtils::getStride(mc.format, mc.outputWidth);
            bool sameStride = (stride == CameraUtils::getStride(mc.format, stream.width));
            /*
             * outputWidth and outputHeight is 0 means the ISYS output size
             * is dynamic, we don't need to check if it matches with stream config.
             */
            if ((outputWidth == 0 && outputHeight == 0 ) ||
                ((stream.width == outputWidth || sameStride)
                && stream.height == outputHeight)) {
                return (MediaCtlConf*)&mc;
            }
        }
    }

    return nullptr;
}

/*
 * Check if video node is enabled via camera Id and video node type.
 */
bool PlatformData::isVideoNodeEnabled(int cameraId, VideoNodeType type) {
    MediaCtlConf *mc = getMediaCtlConf(cameraId);
    if (!mc) return false;

    for(auto const& nd : mc->videoNodes) {
        if (type == nd.videoNodeType) {
            return true;
        }
    }
    return false;
}

bool PlatformData::isISysSupportedFormat(int cameraId, int format)
{
    vector <int> supportedFormat;
    getSupportedISysFormats(cameraId, supportedFormat);

    for (auto const fmt : supportedFormat) {
        if (format == fmt)
            return true;
    }
    return false;
}

bool PlatformData::isISysSupportedResolution(int cameraId, camera_resolution_t resolution)
{
    vector <camera_resolution_t> res;
    getSupportedISysSizes(cameraId, res);

    for (auto const& size : res) {
        if (resolution.width == size.width && resolution.height== size.height)
            return true;
    }

    return false;
}

int PlatformData::getISysRawFormat(int cameraId)
{
    return getInstance()->mStaticCfg.mCameras[cameraId].mISysRawFormat;
}

stream_t PlatformData::getISysOutputByPort(int cameraId, Port port)
{
    stream_t config;
    CLEAR(config);

    MediaCtlConf *mc = PlatformData::getMediaCtlConf(cameraId);
    CheckError(!mc, config, "Invalid media control config.");

    for (const auto& output : mc->outputs) {
        if (output.port == port) {
            config.format  = output.v4l2Format;
            config.width   = output.width;
            config.height  = output.height;
            break;
        }
    }

    return config;
}

bool PlatformData::isAiqdEnabled(int cameraId)
{
    return getInstance()->mStaticCfg.mCameras[cameraId].mEnableAiqd;
}

int PlatformData::getFormatByDevName(int cameraId, const string& devName, McFormat& format)
{
    MediaCtlConf *mc = getMediaCtlConf(cameraId);
    CheckError(!mc, BAD_VALUE, "getMediaCtlConf returns nullptr, cameraId:%d", cameraId);

    for (auto &fmt : mc->formats) {
        if (fmt.formatType == FC_FORMAT && devName == fmt.entityName) {
            format = fmt;
            return OK;
        }
    }

    LOGE("Failed to find DevName for cameraId: %d, devname: %s", cameraId, devName.c_str());
    return BAD_VALUE;
}

int PlatformData::getVideoNodeNameByType(int cameraId, VideoNodeType videoNodeType, string& videoNodeName)
{
    MediaCtlConf *mc = getMediaCtlConf(cameraId);
    CheckError(!mc, BAD_VALUE, "getMediaCtlConf returns nullptr, cameraId:%d", cameraId);

    for(auto const& nd : mc->videoNodes) {
        if (videoNodeType == nd.videoNodeType) {
            videoNodeName = nd.name;
            return OK;
        }
    }

    LOGE("failed to find video note name for cameraId: %d", cameraId);
    return BAD_VALUE;
}

int PlatformData::getDevNameByType(int cameraId, VideoNodeType videoNodeType, string& devName)
{
    if (!isIsysEnabled(cameraId)) return OK;

    MediaCtlConf *mc = getMediaCtlConf(cameraId);
    bool isSubDev = false;

    switch (videoNodeType) {
        case VIDEO_PIXEL_ARRAY:
        case VIDEO_PIXEL_BINNER:
        case VIDEO_PIXEL_SCALER:
        {
            isSubDev = true;
            // For sensor subdevices are fixed and sensor HW may be initialized before configure,
            // the first MediaCtlConf is used to find sensor subdevice name.
            PlatformData::StaticCfg::CameraInfo *pCam = &getInstance()->mStaticCfg.mCameras[cameraId];
            mc = &pCam->mMediaCtlConfs[0];
            break;
        }
        case VIDEO_ISYS_RECEIVER_BACKEND:
        case VIDEO_ISYS_RECEIVER:
        {
            isSubDev = true;
            break;
        }
        default:
            break;
    }

    CheckError(!mc, NAME_NOT_FOUND, "failed to get MediaCtlConf, videoNodeType %d", videoNodeType);

    for(auto& nd : mc->videoNodes) {
        if (videoNodeType == nd.videoNodeType) {
            string tmpDevName;
            CameraUtils::getDeviceName(nd.name.c_str(), tmpDevName, isSubDev);
            if (!tmpDevName.empty()) {
                devName = tmpDevName;
                LOG2("@%s, Found DevName. cameraId: %d, get video node: %s, devname: %s",
                      __func__, cameraId, nd.name.c_str(), devName.c_str());
                return OK;
            } else {
                // Use default device name if cannot find it
                if (isSubDev)
                    devName = "/dev/v4l-subdev1";
                else
                    devName = "/dev/video5";
                LOGE("Failed to find DevName for cameraId: %d, get video node: %s, devname: %s",
                      cameraId, nd.name.c_str(), devName.c_str());
                return NAME_NOT_FOUND;
            }
        }
    }

    LOG1("Failed to find devname for cameraId: %d, use default setting instead", cameraId);
    return NAME_NOT_FOUND;
}

/**
 * The ISYS best resolution is determined by the steps below:
 * 1. If the resolution is specified in MediaCtlConf, then use it.
 * 2. Try to find the exact matched one in ISYS supported resolutions.
 * 3. Try to find the same ratio resolution.
 * 4. If still couldn't get one, then use the biggest one.
 */
camera_resolution_t PlatformData::getISysBestResolution(int cameraId, int width,
                                                        int height, int field)
{
    LOG1("@%s, width:%d, height:%d", __func__, width, height);

    // Skip for interlace, we only support by-pass in interlaced mode
    if (field == V4L2_FIELD_ALTERNATE) {
        return {width, height};
    }

    MediaCtlConf *mc = getMediaCtlConf(cameraId);
    // The isys output size is fixed if outputWidth/outputHeight != 0
    // So we use it to as the ISYS resolution.
    if (mc != nullptr && mc->outputWidth != 0 && mc->outputHeight != 0) {
        return {mc->outputWidth, mc->outputHeight};
    }

    const float RATIO_TOLERANCE = 0.05f; // Supported aspect ratios that are within RATIO_TOLERANCE
    const float kTargetRatio = (float)width / height;

    vector <camera_resolution_t> res;
    // The supported resolutions are saved in res with ascending order(small -> bigger)
    getSupportedISysSizes(cameraId, res);

    // Try to find out the same resolution in the supported isys resolution list
    // if it couldn't find out the same one, then use the bigger one which is the same ratio
    for (auto const& size : res) {
        if (width <= size.width && height <= size.height &&
            fabs((float)size.width/size.height - kTargetRatio) < RATIO_TOLERANCE) {
            LOG1("@%s: Found the best ISYS resoltoution (%d)x(%d)", __func__,
                 size.width, size.height);
            return {size.width, size.height};
        }
    }

    // If it still couldn't find one, then use the biggest one in the supported list.
    LOG1("@%s: ISYS resolution not found, used the biggest one: (%d)x(%d)",
         __func__, res.back().width, res.back().height);
    return {res.back().width, res.back().height};
}

bool PlatformData::isIsysEnabled(int cameraId)
{
    if (getInstance()->mStaticCfg.mCameras[cameraId].mMediaCtlConfs.empty()) {
        return false;
    }
    return true;
}

int PlatformData::calculateFrameParams(int cameraId, SensorFrameParams& sensorFrameParams)
{
    if (!isIsysEnabled(cameraId)) {
        LOG2("%s, no mc, just use default from xml", __func__);
        vector <camera_resolution_t> res;
        getSupportedISysSizes(cameraId, res);

        CheckError(res.empty(), BAD_VALUE, "Supported ISYS resolutions are not configured.");
        sensorFrameParams = {0, 0, static_cast<uint32_t>(res[0].width),
                             static_cast<uint32_t>(res[0].height), 1, 1, 1, 1};

        return OK;
    }

    CLEAR(sensorFrameParams);

    uint32_t width = 0;
    uint32_t horizontalOffset = 0;
    uint32_t horizontalBinNum = 1;
    uint32_t horizontalBinDenom = 1;
    uint32_t horizontalBin = 1;

    uint32_t height = 0;
    uint32_t verticalOffset = 0;
    uint32_t verticalBinNum = 1;
    uint32_t verticalBinDenom = 1;
    uint32_t verticalBin = 1;

    /**
     * For this function, it may be called without configuring stream
     * in some UT cases, the mc is nullptr at this moment. So we need to
     * get one default mc to calculate frame params.
     */
    MediaCtlConf *mc = PlatformData::getMediaCtlConf(cameraId);
    if (mc == nullptr) {
        PlatformData::StaticCfg::CameraInfo *pCam = &getInstance()->mStaticCfg.mCameras[cameraId];
        mc = &pCam->mMediaCtlConfs[0];
    }

    bool pixArraySizeFound = false;
    for (auto const& current : mc->formats) {
        if (!pixArraySizeFound && current.width > 0 && current.height > 0) {
            width = current.width;
            height = current.height;
            pixArraySizeFound = true;
            LOG2("%s: active pixel array H=%d, W=%d", __func__, height, width);
            //Setup initial sensor frame params.
            sensorFrameParams.horizontal_crop_offset += horizontalOffset;
            sensorFrameParams.vertical_crop_offset += verticalOffset;
            sensorFrameParams.cropped_image_width = width;
            sensorFrameParams.cropped_image_height = height;
            sensorFrameParams.horizontal_scaling_numerator = horizontalBinNum;
            sensorFrameParams.horizontal_scaling_denominator = horizontalBinDenom;
            sensorFrameParams.vertical_scaling_numerator = verticalBinNum;
            sensorFrameParams.vertical_scaling_denominator = verticalBinDenom;
        }

        if (current.formatType != FC_SELECTION) {
            continue;
        }

        if (current.selCmd == V4L2_SEL_TGT_CROP) {

            width = current.width * horizontalBin;
            horizontalOffset = current.left * horizontalBin;
            height = current.height * verticalBin;
            verticalOffset = current.top * verticalBin;

            LOG2("%s: crop (binning factor: hor/vert:%d,%d)"
                  , __func__, horizontalBin, verticalBin);

            LOG2("%s: crop left = %d, top = %d, width = %d height = %d",
                  __func__, horizontalOffset, verticalOffset, width, height);

        } else if (current.selCmd == V4L2_SEL_TGT_COMPOSE) {
            if (width == 0 || height == 0) {
                LOGE("Invalid XML configuration, no pixel array width/height when handling compose, skip.");
                return BAD_VALUE;
            }
            if (current.width == 0 || current.height == 0) {
                LOGW("%s: Invalid XML configuration for TGT_COMPOSE,"
                     "0 value detected in width or height", __func__);
                return BAD_VALUE;
            } else {
                LOG2("%s: Compose width %d/%d, height %d/%d", __func__, width, current.width,
                    height, current.height);
                // the scale factor should be float, so multiple numerator and denominator
                // with coefficient to indicate float factor
                const int SCALE_FACTOR_COEF = 10;
                horizontalBin = width / current.width;
                horizontalBinNum = width * SCALE_FACTOR_COEF / current.width;
                horizontalBinDenom = SCALE_FACTOR_COEF;
                verticalBin = height / current.height;
                verticalBinNum = height * SCALE_FACTOR_COEF / current.height;
                verticalBinDenom = SCALE_FACTOR_COEF;
            }

            LOG2("%s: COMPOSE horizontal bin factor=%d, (%d/%d)",
                  __func__, horizontalBin, horizontalBinNum, horizontalBinDenom);
            LOG2("%s: COMPOSE vertical bin factor=%d, (%d/%d)",
                  __func__, verticalBin, verticalBinNum, verticalBinDenom);
        } else {
            LOGW("%s: Target for selection is not CROP neither COMPOSE!", __func__);
            continue;
        }

        sensorFrameParams.horizontal_crop_offset += horizontalOffset;
        sensorFrameParams.vertical_crop_offset += verticalOffset;
        sensorFrameParams.cropped_image_width = width;
        sensorFrameParams.cropped_image_height = height;
        sensorFrameParams.horizontal_scaling_numerator = horizontalBinNum;
        sensorFrameParams.horizontal_scaling_denominator = horizontalBinDenom;
        sensorFrameParams.vertical_scaling_numerator = verticalBinNum;
        sensorFrameParams.vertical_scaling_denominator = verticalBinDenom;
    }

    return OK;

}

void PlatformData::getSupportedTuningConfig(int cameraId, vector <TuningConfig> &configs)
{
    configs = getInstance()->mStaticCfg.mCameras[cameraId].mSupportedTuningConfig;
}

bool PlatformData::usePsys(int cameraId, int format)
{
    if (getInstance()->mStaticCfg.mCameras[cameraId].mSupportedTuningConfig.empty()) {
        LOG1("@%s, the tuning config in xml does not exist", __func__);
        return false;
    }

    if (getInstance()->mStaticCfg.mCameras[cameraId].mPSysFormat.empty()) {
        LOG1("@%s, the psys supported format does not exist", __func__);
        return false;
    }

    for (auto &psys_fmt : getInstance()->mStaticCfg.mCameras[cameraId].mPSysFormat) {
        if (format == psys_fmt)
            return true;
    }

    LOGW("%s, No matched format found, but expected format:%s", __func__,
        CameraUtils::pixelCode2String(format));

    return false;
}

int PlatformData::getConfigModesByOperationMode(int cameraId, uint32_t operationMode, vector <ConfigMode> &configModes)
{
    if (operationMode == CAMERA_STREAM_CONFIGURATION_MODE_END) {
        LOG2("%s: operationMode was invalid operation mode", __func__);
        return INVALID_OPERATION;
    }

    CheckError(getInstance()->mStaticCfg.mCameras[cameraId].mSupportedTuningConfig.empty(), INVALID_OPERATION,
          "@%s, the tuning config in xml does not exist", __func__);

    if (operationMode == CAMERA_STREAM_CONFIGURATION_MODE_AUTO) {
        if (getInstance()->mStaticCfg.mCameras[cameraId].mConfigModesForAuto.empty()) {
            // Use the first config mode as default for auto
            configModes.push_back(getInstance()->mStaticCfg.mCameras[cameraId].mSupportedTuningConfig[0].configMode);
            LOG2("%s: add config mode %d for operation mode %d", __func__, configModes[0], operationMode);
        } else {
            configModes = getInstance()->mStaticCfg.mCameras[cameraId].mConfigModesForAuto;
        }
    } else {
        for (auto &cfg : getInstance()->mStaticCfg.mCameras[cameraId].mSupportedTuningConfig) {
            if (operationMode == (uint32_t)cfg.configMode) {
                configModes.push_back(cfg.configMode);
                LOG2("%s: add config mode %d for operation mode %d", __func__, cfg.configMode, operationMode);
            }
        }
    }

    if (configModes.size() > 0) return OK;
    LOGW("%s, configure number %zu, operationMode %x, cameraId %d", __func__,
            configModes.size(), operationMode, cameraId);
    return INVALID_OPERATION;
}

int PlatformData::getTuningModeByConfigMode(int cameraId, ConfigMode configMode,
                                            TuningMode& tuningMode)
{
    CheckError(getInstance()->mStaticCfg.mCameras[cameraId].mSupportedTuningConfig.empty(),
          INVALID_OPERATION, "the tuning config in xml does not exist");

    for (auto &cfg : getInstance()->mStaticCfg.mCameras[cameraId].mSupportedTuningConfig) {
        LOG2("%s, tuningMode %d, configMode %x", __func__, cfg.tuningMode, cfg.configMode);
        if (cfg.configMode == configMode) {
            tuningMode = cfg.tuningMode;
            return OK;
        }
    }

    LOGW("%s, configMode %x, cameraId %d, no tuningModes", __func__, configMode, cameraId);
    return INVALID_OPERATION;
}

int PlatformData::getTuningConfigByConfigMode(int cameraId, ConfigMode mode, TuningConfig &config)
{
    CheckError(getInstance()->mStaticCfg.mCameras[cameraId].mSupportedTuningConfig.empty(), INVALID_OPERATION,
          "@%s, the tuning config in xml does not exist.", __func__);

    for (auto &cfg : getInstance()->mStaticCfg.mCameras[cameraId].mSupportedTuningConfig) {
        if (cfg.configMode == mode) {
            config = cfg;
            return OK;
        }
    }

    LOGW("%s, configMode %x, cameraId %d, no TuningConfig", __func__, mode, cameraId);
    return INVALID_OPERATION;
}

int PlatformData::getStreamIdByConfigMode(int cameraId, ConfigMode configMode)
{
    std::map<int, int> modeMap = getInstance()->mStaticCfg.mCameras[cameraId].mConfigModeToStreamId;
    return modeMap.find(configMode) == modeMap.end() ? -1 : modeMap[configMode];
}

int PlatformData::getMaxRequestsInflight(int cameraId)
{
    int inflight = getInstance()->mStaticCfg.mCameras[cameraId].mMaxRequestsInflight;
    if (inflight <= 0) {
        inflight = isEnableAIQ(cameraId) ? 4 : MAX_BUFFER_COUNT;
    }

    return inflight;
}

bool PlatformData::getGraphConfigNodes(int cameraId)
{
    return !(getInstance()->mStaticCfg.mCameras[cameraId].mGraphSettingsFile.empty());
}

GraphSettingType PlatformData::getGraphSettingsType(int cameraId)
{
    return getInstance()->mStaticCfg.mCameras[cameraId].mGraphSettingsType;
}

camera_yuv_color_range_mode_t PlatformData::getYuvColorRangeMode(int cameraId)
{
    return getInstance()->mStaticCfg.mCameras[cameraId].mYuvColorRangeMode;
}

ia_binary_data* PlatformData::getAiqd(int cameraId, TuningMode mode)
{
    CheckError(cameraId >= static_cast<int>(getInstance()->mAiqInitData.size()), nullptr,
               "@%s, bad cameraId:%d", __func__, cameraId);

    AiqInitData* aiqInitData = getInstance()->mAiqInitData[cameraId];
    return aiqInitData->getAiqd(mode);
}

void PlatformData::saveAiqd(int cameraId, TuningMode tuningMode, const ia_binary_data& data)
{
    CheckError(cameraId >= static_cast<int>(getInstance()->mAiqInitData.size()), VOID_VALUE,
               "@%s, bad cameraId:%d", __func__, cameraId);

    AiqInitData* aiqInitData = getInstance()->mAiqInitData[cameraId];
    aiqInitData->saveAiqd(tuningMode, data);
}

// load cpf when tuning file (.aiqb) is available
int PlatformData::getCpfAndCmc(int cameraId,
                               ia_binary_data* ispData,
                               ia_binary_data* aiqData,
                               ia_binary_data* otherData,
                               uintptr_t* cmcHandle,
                               TuningMode mode,
                               ia_cmc_t** cmcData)
{
    CheckError(cameraId >= static_cast<int>(getInstance()->mAiqInitData.size()) ||
               cameraId >= MAX_CAMERA_NUMBER, BAD_VALUE, "@%s, bad cameraId:%d",
               __func__, cameraId);
    CheckError(getInstance()->mStaticCfg.mCameras[cameraId].mSupportedTuningConfig.empty(),
               INVALID_OPERATION, "@%s, the tuning config in xml does not exist", __func__);

    AiqInitData* aiqInitData = getInstance()->mAiqInitData[cameraId];
    return aiqInitData->getCpfAndCmc(ispData, aiqData, otherData, cmcHandle, mode, cmcData);
}

bool PlatformData::isCSIBackEndCapture(int cameraId)
{
    bool isCsiBECapture = false;
    MediaCtlConf *mc = getMediaCtlConf(cameraId);
    CheckError(!mc, false, "getMediaCtlConf returns nullptr, cameraId:%d", cameraId);

    for(const auto& node : mc->videoNodes) {
        if (node.videoNodeType == VIDEO_GENERIC &&
                (node.name.find("BE capture") != string::npos ||
                 node.name.find("BE SOC capture") != string::npos)) {
            isCsiBECapture = true;
            break;
        }
    }

    return isCsiBECapture;
}

bool PlatformData::isCSIFrontEndCapture(int cameraId)
{
    bool isCsiFeCapture = false;
    MediaCtlConf *mc = getMediaCtlConf(cameraId);
    CheckError(!mc, false, "getMediaCtlConf returns nullptr, cameraId:%d", cameraId);

    for(const auto& node : mc->videoNodes) {
        if (node.videoNodeType == VIDEO_GENERIC &&
                (node.name.find("CSI-2") != string::npos ||
                 node.name.find("TPG") != string::npos)) {
            isCsiFeCapture = true;
            break;
        }
    }
    return isCsiFeCapture;
}

bool PlatformData::isTPGReceiver(int cameraId)
{
    bool isTPGCapture = false;
    MediaCtlConf *mc = getMediaCtlConf(cameraId);
    CheckError(!mc, false, "getMediaCtlConf returns nullptr, cameraId:%d", cameraId);

    for(const auto& node : mc->videoNodes) {
        if (node.videoNodeType == VIDEO_ISYS_RECEIVER &&
                (node.name.find("TPG") != string::npos)) {
            isTPGCapture = true;
            break;
        }
    }
    return isTPGCapture;
}

int PlatformData::getSupportAeExposureTimeRange(int cameraId, camera_scene_mode_t sceneMode,
                                                camera_range_t& etRange)
{
    vector<camera_ae_exposure_time_range_t> ranges;
    getInstance()->mStaticCfg.mCameras[cameraId].mCapability.getSupportedAeExposureTimeRange(ranges);

    if (ranges.empty())
        return NAME_NOT_FOUND;

    for (auto& item : ranges) {
        if (item.scene_mode == sceneMode) {
            etRange = item.et_range;
            return OK;
        }
    }
    return NAME_NOT_FOUND;
}

int PlatformData::getSupportAeGainRange(int cameraId, camera_scene_mode_t sceneMode,
                                        camera_range_t& gainRange)
{
    vector<camera_ae_gain_range_t> ranges;
    getInstance()->mStaticCfg.mCameras[cameraId].mCapability.getSupportedAeGainRange(ranges);

    if(ranges.empty()) {
        return NAME_NOT_FOUND;
    }

    for (auto& item : ranges) {
        if (item.scene_mode == sceneMode) {
            gainRange = item.gain_range;
            return OK;
        }
    }
    return NAME_NOT_FOUND;
}

bool PlatformData::isUsingCrlModule(int cameraId)
{
    return getInstance()->mStaticCfg.mCameras[cameraId].mUseCrlModule;
}

vector<MultiExpRange> PlatformData::getMultiExpRanges(int cameraId)
{
    return getInstance()->mStaticCfg.mCameras[cameraId].mMultiExpRanges;
}

camera_resolution_t *PlatformData::getPslOutputForRotation(int width, int height, int cameraId)
{
    CheckError(getInstance()->mStaticCfg.mCameras[cameraId].mOutputMap.empty(), nullptr,
          "@%s, cameraId: %d, there isn't pslOutputMapForRotation field in xml.", __func__, cameraId);

    vector<UserToPslOutputMap> &outputMap = getInstance()->mStaticCfg.mCameras[cameraId].mOutputMap;
    for (auto & map : outputMap) {
        if (width == map.User.width && height == map.User.height) {
            LOG2("cameraId: %d, find the psl output resoltion(%d, %d) for %dx%d",
                  cameraId, map.Psl.width, map.Psl.height, map.User.width, map.User.height);
            return &map.Psl;
        }
    }

    return nullptr;
}

bool PlatformData::isTestPatternSupported(int cameraId)
{
    return !getInstance()->mStaticCfg.mCameras[cameraId].mTestPatternMap.empty();
}

int32_t PlatformData::getSensorTestPattern(int cameraId, int32_t mode)
{
    CheckError(getInstance()->mStaticCfg.mCameras[cameraId].mTestPatternMap.empty(), -1,
          "@%s, cameraId: %d, mTestPatternMap is empty!", __func__, cameraId);
    auto testPatternMap = getInstance()->mStaticCfg.mCameras[cameraId].mTestPatternMap;

    if (testPatternMap.find(mode) == testPatternMap.end()) {
        LOGW("Test pattern %d wasn't found in configuration file, return -1", mode);
        return -1;
    }
    return testPatternMap[mode];
}

ia_binary_data *PlatformData::getNvm(int cameraId)
{
    CheckError(cameraId >= static_cast<int>(getInstance()->mAiqInitData.size()), nullptr,
               "@%s, bad cameraId:%d", __func__, cameraId);

    return getInstance()->mAiqInitData[cameraId]->getNvm();
}

camera_coordinate_system_t PlatformData::getActivePixelArray(int cameraId)
{
    camera_coordinate_system_t arraySize;
    CLEAR(arraySize);

    Parameters* param = &getInstance()->mStaticCfg.mCameras[cameraId].mCapability;
    if (param->getSensorActiveArraySize(arraySize) != OK) {
        return { 0, 0, 0, 0 };
    }

    return {arraySize.left, arraySize.top, arraySize.right, arraySize.bottom};
}

string PlatformData::getCameraCfgPath()
{
    char* p = getenv("CAMERA_CFG_PATH");

    return p? string(p) : string(CAMERA_DEFAULT_CFG_PATH);
}

string PlatformData::getGraphDescFilePath()
{
    return PlatformData::getCameraCfgPath() + string(CAMERA_GRAPH_DESCRIPTOR_FILE);
}

string PlatformData::getGraphSettingFilePath()
{
    return PlatformData::getCameraCfgPath() + string(CAMERA_GRAPH_SETTINGS_DIR);
}

int PlatformData::getSensorDigitalGain(int cameraId, float realDigitalGain)
{
    int sensorDg = 0;
    int maxSensorDg = PlatformData::getMaxSensorDigitalGain(cameraId);

    if (PlatformData::sensorDigitalGainType(cameraId) == SENSOR_DG_TYPE_2_X) {
        int index = 0;
        while (pow(2, index) <= realDigitalGain) {
            sensorDg = index;
            index++;
        }
        sensorDg = CLIP(sensorDg, maxSensorDg, 0);
    } else {
        LOGE("%s, don't support the sensor digital gain type: %d",
                __func__, PlatformData::sensorDigitalGainType(cameraId));
    }

    return sensorDg;
}

float PlatformData::getIspDigitalGain(int cameraId, float realDigitalGain)
{
    float ispDg = 1.0f;
    int sensorDg = getSensorDigitalGain(cameraId, realDigitalGain);

    if (PlatformData::sensorDigitalGainType(cameraId) == SENSOR_DG_TYPE_2_X) {
        ispDg = realDigitalGain / pow(2, sensorDg);
        ispDg = CLIP(ispDg, ispDg, 1.0);
    } else {
        LOGE("%s, don't support the sensor digital gain type: %d",
                __func__, PlatformData::sensorDigitalGainType(cameraId));
    }

    return ispDg;
}

int PlatformData::saveMakernoteData(int cameraId, camera_makernote_mode_t makernoteMode,
                                    int64_t sequence)
{
    CheckError(cameraId >= static_cast<int>(getInstance()->mAiqInitData.size()), BAD_VALUE,
               "@%s, bad cameraId:%d", __func__, cameraId);

    return getInstance()->mAiqInitData[cameraId]->saveMakernoteData(makernoteMode, sequence);
}

void* PlatformData::getMknHandle(int cameraId)
{
    CheckError(cameraId >= static_cast<int>(getInstance()->mAiqInitData.size()), nullptr,
               "@%s, bad cameraId:%d", __func__, cameraId);

    return getInstance()->mAiqInitData[cameraId]->getMknHandle();
}

void PlatformData::updateMakernoteTimeStamp(int cameraId, int64_t sequence, uint64_t timestamp)
{
    CheckError(cameraId >= static_cast<int>(getInstance()->mAiqInitData.size()), VOID_VALUE,
               "@%s, bad cameraId:%d", __func__, cameraId);

    getInstance()->mAiqInitData[cameraId]->updateMakernoteTimeStamp(sequence, timestamp);
}

void PlatformData::acquireMakernoteData(int cameraId, uint64_t timestamp, Parameters *param)
{
    CheckError(cameraId >= static_cast<int>(getInstance()->mAiqInitData.size()), VOID_VALUE,
               "@%s, bad cameraId:%d", __func__, cameraId);

    getInstance()->mAiqInitData[cameraId]->acquireMakernoteData(timestamp, param);
}

int PlatformData::getScalerInfo(int cameraId, int32_t streamId,
                                float *scalerWidth, float *scalerHeight)
{
    if (getInstance()->mStaticCfg.mCameras[cameraId].mScalerInfo.empty()) {
        *scalerWidth = 1.0;
        *scalerHeight = 1.0;
        return OK;
    }

    for (auto &scalerInfo : getInstance()->mStaticCfg.mCameras[cameraId].mScalerInfo) {
        LOG2("%s, streamId %d, scalerWidth %f, scalerHeight %f", __func__, scalerInfo.streamId,
             scalerInfo.scalerWidth, scalerInfo.scalerHeight);
        if (scalerInfo.streamId == streamId) {
            *scalerWidth = scalerInfo.scalerWidth;
            *scalerHeight = scalerInfo.scalerHeight;
            break;
        }
    }

    return OK;
}

void  PlatformData::setScalerInfo(int cameraId, std::vector<IGraphType::ScalerInfo> scalerInfo)
{
    for (auto &scalerInfoInput : scalerInfo) {
        bool flag = false;
        for (auto &scalerInfoTmp : getInstance()->mStaticCfg.mCameras[cameraId].mScalerInfo) {
            if (scalerInfoInput.streamId == scalerInfoTmp.streamId) {
                scalerInfoTmp.scalerWidth = scalerInfoInput.scalerWidth;
                scalerInfoTmp.scalerHeight = scalerInfoInput.scalerHeight;
                flag = true;
                break;
            }
        }
        if (!flag) {
            getInstance()->mStaticCfg.mCameras[cameraId].mScalerInfo.push_back(scalerInfoInput);
        }
    }
}

bool PlatformData::isGpuTnrEnabled()
{
    return getInstance()->mStaticCfg.mCommonConfig.isGpuTnrEnabled;
}

int PlatformData::getVideoStreamNum(int cameraId)
{
    return getInstance()->mStaticCfg.mCameras[cameraId].mVideoStreamNum;
}

bool PlatformData::isUsingGpuAlgo()
{
    bool enabled = false;
    enabled |= isGpuTnrEnabled();
    return enabled;
}

bool PlatformData::isStillTnrPrior()
{
    return getInstance()->mStaticCfg.mCommonConfig.isStillTnrPrior;
}

bool PlatformData::isTnrParamForceUpdate()
{
    return getInstance()->mStaticCfg.mCommonConfig.isTnrParamForceUpdate;
}

int PlatformData::getTnrExtraFrameCount(int cameraId)
{
    return getInstance()->mStaticCfg.mCameras[cameraId].mTnrExtraFrameNum;
}

float PlatformData::getManualSaturationFactor(int cameraId)
{
    return getInstance()->mStaticCfg.mCameras[cameraId].mSaturationFactor;
}
} // namespace icamera
