SA8650 camx pipeline node xml 配置信息

目录

usecases

pipeline

node

UsecaseAuto::Initialize

[1. Initialize metadata Manager and initialize input client](#1. Initialize metadata Manager and initialize input client)

[2. Get the default matching usecase for the stream combination](#2. Get the default matching usecase for the stream combination)

[3. Create pipeline and assign all pipeline parameters](#3. Create pipeline and assign all pipeline parameters)

[4. Create session](#4. Create session)

[5. Register metadata clients](#5. Register metadata clients)

[6. get extension module instance for pipeline activation pExtensionModuleInstance->ActivatePipeline](#6. get extension module instance for pipeline activation pExtensionModuleInstance->ActivatePipeline)

[UsecaseSelector::DefaultMatchingUsecaseSelection 获取对应 Usecaseid 对应的usecase数组](#UsecaseSelector::DefaultMatchingUsecaseSelection 获取对应 Usecaseid 对应的usecase数组)

1、对分辨率进行判断

[1)、获取 Usecase 的streamConfigMode](#1)、获取 Usecase 的streamConfigMode)

[2)、获取Usecase 的 pChiUsecases 对数组UsecaseAuto_Targets中的 UsecaseAuto_TARGET_BUFFER_RAW1_target 的 ChiTarget BufferDimension 中的分辨进行判断 ,再根据 ChiStreamFormat UsecaseAuto_TARGET_BUFFER_RAW1_formats 与 pStreamConfig比较判断使用哪一个格式](#2)、获取Usecase 的 pChiUsecases 对数组UsecaseAuto_Targets中的 UsecaseAuto_TARGET_BUFFER_RAW1_target 的 ChiTarget BufferDimension 中的分辨进行判断 ,再根据 ChiStreamFormat UsecaseAuto_TARGET_BUFFER_RAW1_formats 与 pStreamConfig比较判断使用哪一个格式)

[2、如果有rawStream enable PruneRawTargetStrings](#2、如果有rawStream enable PruneRawTargetStrings)

[3、如果是YUV的stream enable PruneYUVTargetStrings](#3、如果是YUV的stream enable PruneYUVTargetStrings)

[4、如果是PruneUBWCTp10的数据流 enble PruneUBWCTp10TargetStrings](#4、如果是PruneUBWCTp10的数据流 enble PruneUBWCTp10TargetStrings)

[5、如果是PreviewStreams enable PrunePreviewTargetStrings](#5、如果是PreviewStreams enable PrunePreviewTargetStrings)

6、确认m_enableAutoNoIPE是否配置

7、确认缩放裁剪是否enable

8、UsecaseMatches(g_UsecaseNameToUsecaseInstanceMap.at("g_pUsecaseAuto"))))

解析g_SocIdNameToFunctionPointerMap获取pSelectedUsecase数组

[pipeline 创建成功,Node:BPS\IPE\JPEG\JPEG AGRREGATOR\Links](#pipeline 创建成功,Node:BPS\IPE\JPEG\JPEG AGRREGATOR\Links)

Pipeline::CreateDescriptor

[1、初始化m_pipelineDescriptor pipelineCreateData](#1、初始化m_pipelineDescriptor pipelineCreateData)

[2、解析ChiNode 中的node info 信息](#2、解析ChiNode 中的node info 信息)

[1、pNodeProperties[i].pValues中保存的是支持的node 节点支持的算法信息com.qti.stats.pdlibwrapper com.qti.hvx.addconstant](#1、pNodeProperties[i].pValues中保存的是支持的node 节点支持的算法信息com.qti.stats.pdlibwrapper com.qti.hvx.addconstant)

[2、获取HDR 模式信息 m_HDRInfo[logicalCameraId]](#2、获取HDR 模式信息 m_HDRInfo[logicalCameraId])

[3、如果usecases(torch widget, AON),那么 IsNoBufferUsecase=true](#3、如果usecases(torch widget, AON),那么 IsNoBufferUsecase=true)

[4、当前场景中没使用torch widget, AON, auto usecase的 IsNoBufferUsecase = FALSE](#4、当前场景中没使用torch widget, AON, auto usecase的 IsNoBufferUsecase = FALSE)

[5、获取帧率,判断是否支持HDR 模式](#5、获取帧率,判断是否支持HDR 模式)

[6、获取pLogicalCameraInfo 的m_cameraCaps.numSensorModes pSensorModeInfo](#6、获取pLogicalCameraInfo 的m_cameraCaps.numSensorModes pSensorModeInfo)

7、根据pLogicalCameraInfo判断支持那种模式的HDR

[8、判断是否支持裁剪 根据设置传感器模式 设置分辨率](#8、判断是否支持裁剪 根据设置传感器模式 设置分辨率)


usecases

apps/qnx_ap/AMSS/multimedia/qcamera/camera_qcx/cdk_qcx/oem/qcom/topology/titan/sa8650/

sa8650_usecase.xml

pipeline

apps/qnx_ap/AMSS/multimedia/qcamera/camera_qcx/cdk_qcx/oem/qcom/topology/titan/usecase-components/usecases/UsecaseAuto/pipelines

camxAutoYUV.xml

引用RealTimeBaseAuto &StatsSegmentAuto node算法

node

segments/sa8650/

RealTimeBaseAuto.xml

com.qti.hvx.addconstant &com.qti.stats.pdlibwrapper 算法

在camx中ExtensionModule加载时初始化获取m_platformID

++ExtensionModule++ ::ExtensionModule()

m_platformID = SocUtils::++GetSocId++();

 ChiPopulatePipelineData pFuncPopulatePipelineData =
        reinterpret_cast<ChiPopulatePipelineData>(ChxUtils::LibGetAddr(m_chiUsecaseHandle, "PopulatePipelineData"));

    if (NULL != pFuncPopulatePipelineData)
   {
       pFuncPopulatePipelineData(m_platformID);
    }
    else
    {
       CHX_LOG_ERROR("Failed to load PopulatePipelineData lib");
    }


/// PopulatePipelineData
///
/// @brief  Populate the global map variable with correct data from usecase xml generated file based on socId
///
/// @param  socID             [IN]  SocId for current target
///
/// @return None

VOID UsecaseSelector::PopulatePipelineData(SocId socId)
{
    OSLIBRARYHANDLE handle = ExtensionModule::GetInstance()->GetChiUsecaseSelectorHandle();
    ChiPopulatePipelineData pFuncPopulatePipelineData =
        reinterpret_cast<ChiPopulatePipelineData>(ChxUtils::LibGetAddr(handle, "PopulatePipelineData"));

    if (NULL != pFuncPopulatePipelineData)
    {
        pFuncPopulatePipelineData(socId);
    }
    else
    {
        CHX_LOG_ERROR("Failed to load pFuncPopulatePipelineData lib");
    }
}

获取对应平台的g_SocIdNameToFunctionPointerMap 配置

// PopulatePipelineData

extern "C" CAMX_VISIBILITY_PUBLIC  VOID PopulatePipelineData(
    SocId socId)
{
    pFunc pPopulateUseCaseInfo = NULL;
    FillMapdata();

    switch (socId)
    {
        case SocId::SM8450:
            pPopulateUseCaseInfo = g_SocIdNameToFunctionPointerMap.at("sm8450");
            break;
        case SocId::SA8650P:
            pPopulateUseCaseInfo = g_SocIdNameToFunctionPointerMap.at("sa8650");
            break;
        case SocId::SA8630P:
            pPopulateUseCaseInfo = g_SocIdNameToFunctionPointerMap.at("sa8630");
            break;
        default:
            break;
    }
    if (NULL != pPopulateUseCaseInfo)
    {
        pPopulateUseCaseInfo();
    }
    else
    {
        CHX_LOG_ERROR("Error Failed to populate pipleine data");
    }
}

cdk_qcx/oem/qcom/chiusecase/common/g_pipelines.cpp

void FillMapssa8650()
{
   g_EnumNameToEnumValueMap["InvalidVariantGroup"] = sa8650::InvalidVariantGroup;
   g_EnumNameToEnumValueMap["PruneGroupAEC"] = sa8650::PruneGroupAEC;
   g_EnumNameToEnumValueMap["PruneGroupAWB"] = sa8650::PruneGroupAWB;
   g_EnumNameToEnumValueMap["PruneGroupNoIPE"] = sa8650::PruneGroupNoIPE;
   g_EnumNameToEnumValueMap["PruneGroupP010Format"] = sa8650::PruneGroupP010Format;
   g_EnumNameToEnumValueMap["PruneGroupP010LSBFormat"] = sa8650::PruneGroupP010LSBFormat;
   g_EnumNameToEnumValueMap["PruneGroupP01208Format"] = sa8650::PruneGroupP01208Format;
   g_EnumNameToEnumValueMap["PruneGroupP01208LSBFormat"] = sa8650::PruneGroupP01208LSBFormat;
   g_EnumNameToEnumValueMap["PruneGroupP01210Format"] = sa8650::PruneGroupP01210Format;
   g_EnumNameToEnumValueMap["PruneGroupP01210LSBFormat"] = sa8650::PruneGroupP01210LSBFormat;
   g_EnumNameToEnumValueMap["PruneGroupPlain16_12"] = sa8650::PruneGroupPlain16_12;
   g_EnumNameToEnumValueMap["PruneGroupPreview"] = sa8650::PruneGroupPreview;
   g_EnumNameToEnumValueMap["PruneGroupPreview2"] = sa8650::PruneGroupPreview2;
   g_EnumNameToEnumValueMap["PruneGroupPreview3"] = sa8650::PruneGroupPreview3;
   g_EnumNameToEnumValueMap["PruneGroupRGBIFormat"] = sa8650::PruneGroupRGBIFormat;
   g_EnumNameToEnumValueMap["PruneGroupRGBPFormat"] = sa8650::PruneGroupRGBPFormat;
   g_EnumNameToEnumValueMap["PruneGroupRaw1"] = sa8650::PruneGroupRaw1;
   g_EnumNameToEnumValueMap["PruneGroupRaw16"] = sa8650::PruneGroupRaw16;
   g_EnumNameToEnumValueMap["PruneGroupRaw2"] = sa8650::PruneGroupRaw2;
   g_EnumNameToEnumValueMap["PruneGroupRaw3"] = sa8650::PruneGroupRaw3;
   g_EnumNameToEnumValueMap["PruneGroupRaw4"] = sa8650::PruneGroupRaw4;
   g_EnumNameToEnumValueMap["PruneGroupVideo"] = sa8650::PruneGroupVideo;
   g_EnumNameToEnumValueMap["PruneGroupYuv"] = sa8650::PruneGroupYuv;
   g_EnumNameToEnumValueMap["PruneGroupYuv2"] = sa8650::PruneGroupYuv2;
   g_EnumNameToEnumValueMap["PruneGroupYuv3"] = sa8650::PruneGroupYuv3;
   g_StringArrayNameToStringArray["g_stringMapVariantGroup"] = sa8650::g_stringMapVariantGroup;
   g_EnumNameToEnumValueMap["g_stringMapVariantGroupSize"] = sizeof(sa8650::g_stringMapVariantGroup) / sizeof(sa8650::g_stringMapVariantGroup[0]);
   g_EnumNameToEnumValueMap["InvalidVariantType"] = sa8650::InvalidVariantType;
   g_EnumNameToEnumValueMap["PruneTypeDisabled"] = sa8650::PruneTypeDisabled;
   g_EnumNameToEnumValueMap["PruneTypeEnabled"] = sa8650::PruneTypeEnabled;
   g_StringArrayNameToStringArray["g_stringMapVariantType"] = sa8650::g_stringMapVariantType;
   g_EnumNameToEnumValueMap["g_stringMapVariantTypeSize"] = sizeof(sa8650::g_stringMapVariantType) / sizeof(sa8650::g_stringMapVariantType[0]);
   g_EnumNameToEnumValueMap["ICMSMono"] = sa8650::ICMSMono;
   g_EnumNameToEnumValueMap["RawAuto"] = sa8650::RawAuto;
   g_EnumNameToEnumValueMap["AutoNoIPE"] = sa8650::AutoNoIPE;
   g_EnumNameToEnumValueMap["AutoICMS3"] = sa8650::AutoICMS3;
   g_EnumNameToEnumValueMap["AutoICMS4"] = sa8650::AutoICMS4;
   g_EnumNameToEnumValueMap["AutoICMS"] = sa8650::AutoICMS;
   g_EnumNameToEnumValueMap["AutoICMS2"] = sa8650::AutoICMS2;
   g_EnumNameToEnumValueMap["AutoFFCChiNode"] = sa8650::AutoFFCChiNode;
   g_EnumNameToEnumValueMap["AutoFFCCVSOC"] = sa8650::AutoFFCCVSOC;
   g_EnumNameToEnumValueMap["AutoSRV"] = sa8650::AutoSRV;
   g_EnumNameToEnumValueMap["AutoFFC"] = sa8650::AutoFFC;
   g_EnumNameToEnumValueMap["AutoFFCMeta"] = sa8650::AutoFFCMeta;
   g_EnumNameToEnumValueMap["AutoOfflineIFE"] = sa8650::AutoOfflineIFE;
   g_EnumNameToEnumValueMap["AutoYUVROI"] = sa8650::AutoYUVROI;
   g_EnumNameToEnumValueMap["Auto"] = sa8650::Auto;
   g_EnumNameToEnumValueMap["AutoYUV"] = sa8650::AutoYUV;
   g_UsecaseCollectionNameToUsecaseCollectionMap["PerNumTargetUsecases"] =sa8650::PerNumTargetUsecases;
   g_EnumNameToEnumValueMap["PerNumTargetUsecasesSize"]             = sizeof(sa8650::PerNumTargetUsecases) / sizeof(sa8650::PerNumTargetUsecases[0]);
   g_EnumNameToEnumValueMap["UsecaseICMSMonoId"] = sa8650::UsecaseICMSMonoId;
   g_UsecaseNameToUsecaseInstanceMap["g_pUsecaseICMSMono"] = &(sa8650::Usecases1Target[sa8650::UsecaseICMSMonoId]);
   g_UsecaseNameToUsecaseInstanceMap["Usecases1Target"] = sa8650::Usecases1Target;
   g_EnumNameToEnumValueMap["UsecaseRawAutoId"] = sa8650::UsecaseRawAutoId;
   g_UsecaseNameToUsecaseInstanceMap["g_pUsecaseRawAuto"] = &(sa8650::Usecases5Target[sa8650::UsecaseRawAutoId]);
   g_UsecaseNameToUsecaseInstanceMap["Usecases5Target"] = sa8650::Usecases5Target;
   g_EnumNameToEnumValueMap["UsecaseICMSId"] = sa8650::UsecaseICMSId;
   g_UsecaseNameToUsecaseInstanceMap["g_pUsecaseICMS"] = &(sa8650::Usecases6Target[sa8650::UsecaseICMSId]);
   g_UsecaseNameToUsecaseInstanceMap["Usecases6Target"] = sa8650::Usecases6Target;
   g_EnumNameToEnumValueMap["UsecaseFFCChiNodeId"] = sa8650::UsecaseFFCChiNodeId;
   g_UsecaseNameToUsecaseInstanceMap["g_pUsecaseFFCChiNode"] = &(sa8650::Usecases6Target[sa8650::UsecaseFFCChiNodeId]);
   g_UsecaseNameToUsecaseInstanceMap["Usecases6Target"] = sa8650::Usecases6Target;
   g_EnumNameToEnumValueMap["UsecaseFFCCVSOCId"] = sa8650::UsecaseFFCCVSOCId;
   g_UsecaseNameToUsecaseInstanceMap["g_pUsecaseFFCCVSOC"] = &(sa8650::Usecases6Target[sa8650::UsecaseFFCCVSOCId]);
   g_UsecaseNameToUsecaseInstanceMap["Usecases6Target"] = sa8650::Usecases6Target;
   g_EnumNameToEnumValueMap["UsecaseSRVId"] = sa8650::UsecaseSRVId;
   g_UsecaseNameToUsecaseInstanceMap["g_pUsecaseSRV"] = &(sa8650::Usecases7Target[sa8650::UsecaseSRVId]);
   g_UsecaseNameToUsecaseInstanceMap["Usecases7Target"] = sa8650::Usecases7Target;
   g_EnumNameToEnumValueMap["UsecaseFFCId"] = sa8650::UsecaseFFCId;
   g_UsecaseNameToUsecaseInstanceMap["g_pUsecaseFFC"] = &(sa8650::Usecases8Target[sa8650::UsecaseFFCId]);
   g_UsecaseNameToUsecaseInstanceMap["Usecases8Target"] = sa8650::Usecases8Target;
   g_EnumNameToEnumValueMap["UsecaseAutoId"] = sa8650::UsecaseAutoId;
   //UsecaseAutoId=0 UsecaseAuto 初始化usecase name  pUsecaseName;
   g_UsecaseNameToUsecaseInstanceMap["g_pUsecaseAuto"] = &(sa8650::Usecases18Target[sa8650::UsecaseAutoId]);
   g_UsecaseNameToUsecaseInstanceMap["Usecases18Target"] = sa8650::Usecases18Target;
   g_EnumNameToEnumValueMap["ChiMaxNumTargets"] =18;

}

apps/qnx_ap/AMSS/multimedia/qcamera/camera_qcx/cdk_qcx/oem/qcom/chiusecase/auto/chxusecaseselector.cpp

chxusecaseselector.cpp:

解析pStreamConfig 判断pipeline 的配置情况 && 解析g_SocIdNameToFunctionPointerMap 参数

UsecaseAuto::Initialize

1. Initialize metadata Manager and initialize input client

2. Get the default matching usecase for the stream combination

3. Create pipeline and assign all pipeline parameters

Pipeline::Create m_pPipelines[index]->GetDescriptorMetadata

result = m_pPipelines[index]->CreateDescriptor =Pipeline::CreateDescriptor

4. Create session

Session::Create

5. Register metadata clients

pPipeline->SetMetadataClientId(m_metadataClients[index])

6. get extension module instance for pipeline activation

pExtensionModuleInstance->ActivatePipeline

UsecaseSelector::DefaultMatchingUsecase(pStreamConfigPerPipeline, 0);调用各类平台的cdk_qcx/oem/qcom/chiusecase/(platform)/chxusecaseselector.cpp

GetDefaultMatchingUsecase获取usecase信息最终会调用到DefaultMatchingUsecaseSelection

DefaultMatchingUsecaseSelection根据pStreamConfig的分辨率 、格式 operation_mode选择对应支持的usecase

Pipeline::Create 创建pipe

// UsecaseSelector::DefaultMatchingUsecase

ChiUsecase* UsecaseSelector::DefaultMatchingUsecase(
    camera3_stream_configuration_t* pStreamConfig,
    UINT32                          bpp)
{
    ChiUsecase*        pSelectedUsecase   = NULL;

    OSLIBRARYHANDLE handle =  ExtensionModule::GetInstance()->GetChiUsecaseSelectorHandle();
    if (NULL == handle)
    {
        CHX_LOG_ERROR("Failed to load ChiusecaseSelector lib");
    }
    else
    {
        CHX_LOG_INFO("ChiusecaseSelector able to load handle lib %p", handle);
    }
    ChiUsecaseSelector pFuncChiUsecaseSelector =
                 reinterpret_cast<ChiUsecaseSelector>(ChxUtils::LibGetAddr(handle, "GetDefaultMatchingUsecase"));
    if (NULL == pFuncChiUsecaseSelector)
    {
        CHX_LOG_ERROR("Failed to load pFuncChiUsecaseSelector lib");
    }
    else
    {
        pSelectedUsecase = pFuncChiUsecaseSelector(pStreamConfig, bpp);
    }
    return pSelectedUsecase;
}

UsecaseSelector::DefaultMatchingUsecaseSelection 获取对应 Usecaseid 对应的usecase数组

1、对分辨率进行判断

1)、获取 Usecase 的streamConfigMode

2)、获取Usecase 的 pChiUsecases 对数组UsecaseAuto_Targets中的 UsecaseAuto_TARGET_BUFFER_RAW1_target 的 ChiTarget BufferDimension 中的分辨进行判断 ,再根据 ChiStreamFormat UsecaseAuto_TARGET_BUFFER_RAW1_formats 与 pStreamConfig比较判断使用哪一个格式

2、如果有rawStream enable PruneRawTargetStrings

3、如果是YUV的stream enable PruneYUVTargetStrings

4、如果是PruneUBWCTp10的数据流 enble PruneUBWCTp10TargetStrings

5、如果是PreviewStreams enable PrunePreviewTargetStrings

6、确认m_enableAutoNoIPE是否配置

7、确认缩放裁剪是否enable

8、UsecaseMatches(g_UsecaseNameToUsecaseInstanceMap.at("g_pUsecaseAuto")))

解析g_SocIdNameToFunctionPointerMap获取pSelectedUsecase数组

//    UsecaseSelector::DefaultMatchingUsecaseSelection

extern "C" CAMX_VISIBILITY_PUBLIC ChiUsecase* UsecaseSelector::DefaultMatchingUsecaseSelection(
    camera3_stream_configuration_t* pStreamConfig,
    UINT32                          bpp)
{
    ChiUsecase* pSelectedUsecase = NULL;
    CDKResult   result               = CDKResultSuccess;
    UINT32      numRawStreams        = 0;
    UINT32      numYUVStreams        = 0;
    UINT32      numUBWCStreams       = 0;
    UINT32      numPreviewStreams    = 0;
    BOOL        isRaw16Stream        = FALSE;
    BOOL        isRawPlain1612Stream = FALSE;
    BOOL        isNoIPEEnabled       = FALSE;
    BOOL        isP01208Stream       = FALSE;
    BOOL        isP01210Stream       = FALSE;
    BOOL        isP01208LSBStream    = FALSE;
    BOOL        isP01210LSBStream    = FALSE;
    BOOL        isRGBIStream         = FALSE;
    BOOL        isRGBPStream         = FALSE;
    BOOL        isCropEnabled        = FALSE;
    BOOL        isP010Stream         = FALSE;
    BOOL        isP010LSBStream      = FALSE;
    UINT32      numMetaStreams       = 0;

    PruneSettings pruneSettings;
    PruneVariant  variants[MaxPruneTargetStrings];   // update MaxOtherStreamsPerPipeline when adding more pruneVariants
    pruneSettings.numSettings = 0;
    pruneSettings.pVariants   = variants;

    if (NULL == pStreamConfig)
    {
        CHX_LOG_ERROR("Failed to match usecase. pStreamConfig is NULL");
    }
    else
    {
        for (UINT32 streamIdx = 0; streamIdx < pStreamConfig->num_streams; streamIdx++)
        {
            camera3_stream_t* pFwkStream = pStreamConfig->streams[streamIdx];

            if (pFwkStream->height > MaxMetaHeight)
            {
                if (UsecaseSelector::IsRawStream(pFwkStream))
                {
                    numRawStreams++;
                }
                 //pStream->format
                if (UsecaseSelector::IsRaw16Stream(pFwkStream))
                {
                    // decrement the number of raw stream when using Raw 16
                    // it is also raw stream, but has different pruning
                    // so when numRawStream will decrement as much raw 16 Streams
                    // enabled.
                    numRawStreams--;
                    isRaw16Stream = TRUE;
                }
                //pStream->stream_type & pStream->format
                if (UsecaseSelector::IsYUVOutStream(pFwkStream))
                {
                    numYUVStreams++;
                }
                if (UsecaseSelector::IsPreviewStream(pFwkStream))
                {
                    numPreviewStreams++;
                }
                if (UsecaseSelector::IsUBWCTP10Stream(pFwkStream))
                {
                    numUBWCStreams++;
                }
                if (UsecaseSelector::IsP01208Stream(pFwkStream))
                {
                    isP01208Stream = TRUE;
                }
                if (UsecaseSelector::IsP01210Stream(pFwkStream))
                {
                    isP01210Stream = TRUE;
                }
                if (UsecaseSelector::IsP010Stream(pFwkStream))
                {
                    isP010Stream = TRUE;
                }
                if (UsecaseSelector::IsP01208LSBStream(pFwkStream))
                {
                    isP01208LSBStream = TRUE;
                }
                if (UsecaseSelector::IsP01210LSBStream(pFwkStream))
                {
                    isP01210LSBStream = TRUE;
                }
                if (UsecaseSelector::IsP010LSBStream(pFwkStream))
                {
                    isP010LSBStream = TRUE;
                }
                if (UsecaseSelector::IsRGBIStream(pFwkStream))
                {
                    isRGBIStream = TRUE;
                }
                if (UsecaseSelector::IsRGBPStream(pFwkStream))
                {
                    isRGBPStream = TRUE;
                }
                if (UsecaseSelector::IsRawPlain1612Stream(pFwkStream))
                {
                    isRawPlain1612Stream++;
                }
            }
            else
            {
                numMetaStreams++;
            }
        }

        auto AddSetting = [&pruneSettings, &variants](const CHAR* pGroup, const CHAR* pType) -> VOID
        {
            VariantGroup group = GetVariantGroup(pGroup);
            VariantType  type  = GetVariantType(pType);
            if ((g_EnumNameToEnumValueMap.at("InvalidVariantGroup") != group) &&
                (g_EnumNameToEnumValueMap.at("InvalidVariantType") != type))
            {
                if (pruneSettings.numSettings < MaxPruneTargetStrings)
                {
                    CHX_LOG_INFO("Adding prune setting #%u - %s = %s", pruneSettings.numSettings, pGroup, pType);
                    PruneVariant* pVariant = &variants[pruneSettings.numSettings++];
                    pVariant->group        = group;
                    pVariant->type         = type;
                }
                else
                {
                    CHX_LOG_ERROR("prunSettings added exceeds allowed max pruneSettings: %d", MaxPruneTargetStrings);
                }
            }
            else
            {
                CHX_LOG_WARN("Invalid Prune Setting - Group: %s(%u) Setting: %s(%u)", pGroup, group, pType, type);
            }
        };

        auto UsecaseMatches = [&](const ChiUsecase* const pUsecase) -> BOOL
        { //对分辨率进行判断
          //获取 Usecase 的streamConfigMode 
          // 获取Usecase 的 pChiUsecases 对数组UsecaseAuto_Targets中的
           //UsecaseAuto_TARGET_BUFFER_RAW1_target 的 ChiTarget  BufferDimension 中的分辨进行判断
           //再根据 ChiStreamFormat UsecaseAuto_TARGET_BUFFER_RAW1_formats  与 pStreamConfig比较判断使用哪一个格式
            return IsMatchingUsecase(pStreamConfig, pUsecase, &pruneSettings);
        };

        // Pruning raw streams
        for (UINT32 i = 0; i < MaxRawStreamsPerPipeline; i++)
        { //如果有rawStream enable  PruneRawTargetStrings
            AddSetting(PruneRawTargetStrings[i], (i < numRawStreams) ? "Enabled" : "Disabled");
        }
        // Pruning for auto YUV targets
        for (UINT32 i = 0; i < MaxYuvStreamsPerPipeline; i++)
        {//如果是YUV的stream enable PruneYUVTargetStrings 
            AddSetting(PruneYUVTargetStrings[i], (i < numYUVStreams) ? "Enabled" : "Disabled");
        }

        for (UINT32 i = 0; i < MaxUBWCStreamsPerPipeline; i++)
        {  //如果是PruneUBWCTp10的数据流 enble PruneUBWCTp10TargetStrings
            AddSetting(PruneUBWCTp10TargetStrings[i], (i < numUBWCStreams) ? "Enabled" : "Disabled");
        }

        // Pruning Preview Streams
        for (UINT32 i = 0; i < MaxPreviewStreamsPerPipeline; i++)
        {   //如果是PreviewStreams enable  PrunePreviewTargetStrings
            AddSetting(PrunePreviewTargetStrings[i], (i < numPreviewStreams) ? "Enabled" : "Disabled");
        }

        // get override settings
        //确认m_enableAutoNoIPE是否配置
        isNoIPEEnabled = ExtensionModule::GetInstance()->EnableAutoNoIPEpipeline();

        CHX_LOG_INFO("numPreviewStreams %d, numUBWCStreams %d, numYUVStreams %d, numRawStreams %d",
            numPreviewStreams, numUBWCStreams, numYUVStreams, numRawStreams);

        AddSetting("Raw16",   (TRUE == isRaw16Stream)   ? "Enabled" : "Disabled");
        AddSetting("Plain16_12",   (TRUE == isRawPlain1612Stream)   ? "Enabled" : "Disabled");
        AddSetting("NoIPE",   (TRUE == isNoIPEEnabled)  ? "Enabled" : "Disabled");
        AddSetting("AWB",     (TRUE == ExtensionModule::GetInstance()->EnableAutoAWB()) ? "Enabled" : "Disabled");
        AddSetting("AEC",     (TRUE == ExtensionModule::GetInstance()->EnableAutoAEC()) ? "Enabled" : "Disabled");
        AddSetting("P01208Format", (TRUE == isP01208Stream)  ? "Enabled" : "Disabled");
        AddSetting("P01210Format", (TRUE == isP01210Stream)  ? "Enabled" : "Disabled");
        AddSetting("P010Format",   (TRUE == isP010Stream)    ? "Enabled" : "Disabled");
        AddSetting("P01208LSBFormat", (TRUE == isP01208LSBStream)  ? "Enabled" : "Disabled");
        AddSetting("P01210LSBFormat", (TRUE == isP01210LSBStream)  ? "Enabled" : "Disabled");
        AddSetting("P010LSBFormat",   (TRUE == isP010LSBStream)    ? "Enabled" : "Disabled");
        AddSetting("RGBIFormat",    (TRUE == isRGBIStream)     ? "Enabled" : "Disabled");
        AddSetting("RGBPFormat",    (TRUE == isRGBPStream)     ? "Enabled" : "Disabled");

        for (UINT32 i = 0; i < MaxRawStreamsPerPipeline; i++)
        {
            AddSetting(PruneRawTargetStrings[i], (i < numMetaStreams) ? "Enabled" : "Disabled"); // to match usecase
            AddSetting(PruneMetaTargetStrings[i], (i < numMetaStreams) ? "Enabled" : "Disabled");
        }

        //check Vendortag
        // 1 for bayer, 2 for mono
        camera_metadata_entry_t entry = {};

        UINT32 enableICMS = ChxUtils::QuerySessionParam(pStreamConfig, "EnableICMS", entry);
        UINT32 enableSRV  = ChxUtils::QuerySessionParam(pStreamConfig, "EnableSRV",  entry);
        UINT32 enableFFC  = ChxUtils::QuerySessionParam(pStreamConfig, "EnableFFC",  entry);


        ChxUtils::QuerySessionParam(pStreamConfig, "ScalerCropRegion", entry);
        if (NULL != entry.data.i32)
        {
            if ((0 != entry.data.i32[0]) || (0 != entry.data.i32[1]))
            {  //缩放裁剪enable
                isCropEnabled = TRUE;
            }
        }

        CHX_LOG_INFO("enableICMS %d, enableSRV %d, enableFFC %d", enableICMS, enableSRV, enableFFC);
        //解析g_SocIdNameToFunctionPointerMap获取pSelectedUsecase
        // assign the logical camera usecase and pipelines accordingly
        // bayer ICMS usecase
        if ((1 == enableICMS) && (TRUE == UsecaseMatches(g_UsecaseNameToUsecaseInstanceMap.at("g_pUsecaseICMS"))))
        {
            pSelectedUsecase = g_UsecaseNameToUsecaseInstanceMap.at("g_pUsecaseICMS");
        }

        // mono usecase
        if ((2 == enableICMS) && (TRUE == UsecaseMatches(g_UsecaseNameToUsecaseInstanceMap.at("g_pUsecaseICMSMono"))))
        {
            pSelectedUsecase = g_UsecaseNameToUsecaseInstanceMap.at("g_pUsecaseICMSMono");
        }

        // SRV usecase
        if ((1 == enableSRV) && (TRUE == UsecaseMatches(g_UsecaseNameToUsecaseInstanceMap.at("g_pUsecaseSRV"))))
        {
            pSelectedUsecase = g_UsecaseNameToUsecaseInstanceMap.at("g_pUsecaseSRV");
        }

        // FFC usecase
        if ((1 == enableFFC))
        {

            if ((1 == ExtensionModule::GetInstance()->getCurrentSoc()) &&
                    TRUE == UsecaseMatches(g_UsecaseNameToUsecaseInstanceMap.at("g_pUsecaseFFCChiNode")))
            {
                CHX_LOG_INFO("Selected FFC: ISOC chinode usecase");
                pSelectedUsecase = g_UsecaseNameToUsecaseInstanceMap.at("g_pUsecaseFFCChiNode");
            }
            else if ((2 == ExtensionModule::GetInstance()->getCurrentSoc()) &&
                    TRUE == UsecaseMatches(g_UsecaseNameToUsecaseInstanceMap.at("g_pUsecaseFFCCVSOC")))
            {
                CHX_LOG_INFO("Selected FFC: CVSOC usecase");
                pSelectedUsecase = g_UsecaseNameToUsecaseInstanceMap.at("g_pUsecaseFFCCVSOC");
            }
            else
            {
                // Select ISOC usecase by default
                if ( TRUE == UsecaseMatches(g_UsecaseNameToUsecaseInstanceMap.at("g_pUsecaseFFC")))
                {
                    CHX_LOG_INFO("Selected FFC usecase, FFC sensor %d",
                        ExtensionModule::GetInstance()->IsFFCSensor());
                    pSelectedUsecase = g_UsecaseNameToUsecaseInstanceMap.at("g_pUsecaseFFC");
                }
            }
        }

        if (NULL == pSelectedUsecase)
        {
            if ((numYUVStreams > 0)    || (numPreviewStreams > 0) || (TRUE == isRGBPStream) ||
                (TRUE == isP01208Stream) || (TRUE == isP01210Stream)  || (TRUE == isRGBIStream) ||
                (numUBWCStreams> 0) || (TRUE == isRaw16Stream) || (TRUE == isP010Stream) ||
                (TRUE == isP01208LSBStream) || (TRUE == isP01210LSBStream) || (TRUE == isP010LSBStream))
            {
                if (TRUE == UsecaseMatches(g_UsecaseNameToUsecaseInstanceMap.at("g_pUsecaseAuto")))
                {
                    pSelectedUsecase = g_UsecaseNameToUsecaseInstanceMap.at("g_pUsecaseAuto");
                }
            }
            else
            {
                if (TRUE == UsecaseMatches(g_UsecaseNameToUsecaseInstanceMap.at("g_pUsecaseRawAuto")))
                {
                    pSelectedUsecase = g_UsecaseNameToUsecaseInstanceMap.at("g_pUsecaseRawAuto");
                }
            }
        }

        if (NULL == pSelectedUsecase)
        {
            CHX_LOG_ERROR("Fatal: no Usecase Selected or Usecase Matching Failed");
        }
        else
        {
            // Handle more usecases, currently handling only RAW usecase.
            UINT32      totalPipelineIdx = DefaultPipelineIdx;
            UINT32      pipelineDescIdx[5] = {0};
            ChiUsecase* pClonedUsecase     = NULL;

            // Select the right pipeline index based on override setting
            if ((2 != enableICMS) || (1 != enableSRV))
            {
                totalPipelineIdx = DefaultPipelineIdx;

                for (UINT32 i = 0; i < pSelectedUsecase->numPipelines; i++)
                {
                    if (1 == enableICMS)
                    {
                        if (0 == CdkUtils::StrCmp(pSelectedUsecase->pPipelineTargetCreateDesc[i].pPipelineName,
                                                     PruneICMSPipelineStrings[numPreviewStreams + numYUVStreams - 1]))
                        {
                            pipelineDescIdx[0] = i;
                        }
                    }
                    else if (1 == enableFFC)
                    {
                        if (TRUE == ExtensionModule::GetInstance()->IsFFCSensor())
                        {
                            CHX_LOG_INFO("Selected FFC usecase, FFC sensor, pipeline %s, i %d",
                                pSelectedUsecase->pPipelineTargetCreateDesc[i].pPipelineName, i);
                            if (0 == CdkUtils::StrCmp(pSelectedUsecase->pPipelineTargetCreateDesc[i].pPipelineName, "AutoFFCMeta"))
                            {
                                pipelineDescIdx[0] = i;
                            }
                        }
                        else if ((1 == ExtensionModule::GetInstance()->getCurrentSoc()) &&
                                 (2 == ExtensionModule::GetInstance()->getCurrentSoc()))
                        {
                            if ((0 == CdkUtils::StrCmp(pSelectedUsecase->pPipelineTargetCreateDesc[i].pPipelineName, "AutoFFCChiNode")) ||
                                (0 == CdkUtils::StrCmp(pSelectedUsecase->pPipelineTargetCreateDesc[i].pPipelineName, "AutoFFCCVSOC")))
                            {
                                pipelineDescIdx[0] = i;
                            }
                        }
                        else
                        {
                            if (0 == CdkUtils::StrCmp(pSelectedUsecase->pPipelineTargetCreateDesc[i].pPipelineName, "AutoFFC"))
                            {
                                pipelineDescIdx[0] = i;
                            }
                        }
                    }
                    else if (TRUE == ExtensionModule::GetInstance()->EnableAutoNoIPEpipeline())
                    {
                        if ((TRUE == isCropEnabled) &&
                            (0 == CdkUtils::StrCmp(
                                pSelectedUsecase->pPipelineTargetCreateDesc[i].pPipelineName , "AutoYUVROI")))
                        {
                            pipelineDescIdx[0] = i;
                            break;
                        }

                        if ((0 == CdkUtils::StrCmp(
                                pSelectedUsecase->pPipelineTargetCreateDesc[i].pPipelineName, "AutoNoIPE")) ||
                            (0 == CdkUtils::StrCmp(
                                pSelectedUsecase->pPipelineTargetCreateDesc[i].pPipelineName , "AutoYUV")))
                        {
                            pipelineDescIdx[0] = i;
                            break;
                        }
                    }
                    else if (TRUE == ExtensionModule::GetInstance()->IsOfflineIFEEnabled())
                    {
                        if (0 == CdkUtils::StrCmp(
                            pSelectedUsecase->pPipelineTargetCreateDesc[i].pPipelineName, "AutoOfflineIFE"))
                        {
                            pipelineDescIdx[0] = i;
                            break;
                        }
                    }
                    else
                    {
                        if (0 == CdkUtils::StrCmp(pSelectedUsecase->pPipelineTargetCreateDesc[i].pPipelineName, "Auto"))
                        {
                            pipelineDescIdx[0] = i;
                            break;
                        }
                    }
                }
            }

            // Prune
            pClonedUsecase = UsecaseSelector::CloneUsecase(pSelectedUsecase, totalPipelineIdx, pipelineDescIdx);

            result = UsecaseSelector::PruneUsecaseDescriptor(pClonedUsecase,
                                                    pruneSettings.numSettings,
                                                    pruneSettings.pVariants,
                                                    &pSelectedUsecase);

            if (NULL != pClonedUsecase)
            {
                UsecaseSelector::DestroyUsecase(pClonedUsecase);
                pClonedUsecase = NULL;
            }

            if (NULL != pSelectedUsecase)
            {
                // showing which pipelines are being selected for the usecase
                for (UINT i = 0; i < totalPipelineIdx; i++)
                {
                    CHX_LOG_INFO("SelectedUsecase %s, PipelineName %s %p",
                        pSelectedUsecase->pUsecaseName,
                        pSelectedUsecase->pPipelineTargetCreateDesc[i].pPipelineName,
                        &pSelectedUsecase->pPipelineTargetCreateDesc[i]);
                }
            }
            else
            {
                CHX_LOG_ERROR("Failed to match usecase. pSelectedUsecase is NULL");
            }
        }
    }

    return pSelectedUsecase;
}

Pipeline::Create

1)、CHX_NEW Pipeline pPipeline->Initialize

2)、初始化pPipeline->m_pPipelineName = pName;

// Pipeline::Create

Pipeline* Pipeline::Create(
    UINT32       cameraId,
    PipelineType type,
    const CHAR*  pName)
{
    Pipeline* pPipeline = CHX_NEW Pipeline;

    if (NULL != pPipeline)
    {
        const UINT32 logicalCameraId = ExtensionModule::GetInstance()->GetLogicalCameraId(cameraId);
        if (CDKResultSuccess != pPipeline->Initialize(cameraId, logicalCameraId, type))
        {
            CHX_LOG_ERROR("Failed to initialize %s", pName ? pName : "NULL");
            CHX_DELETE pPipeline;
            pPipeline = NULL;
        }
        else
        {
            pPipeline->m_pPipelineName = pName;
        }
    }

    return pPipeline;
}


// Pipeline::Initialize

CDKResult Pipeline::Initialize(
    UINT32       cameraId,
    UINT32       logicalCameraId,
    PipelineType type)
{
    CDKResult result = CDKResultSuccess;

    CHX_LOG_INFO("Initializing Pipeline with cameraId %u logicalCameraId %u, type:%d", cameraId, logicalCameraId, type);

    m_cameraId              = cameraId;
    m_logicalCameraId       = logicalCameraId;
    m_type                  = type;
    m_pipelineActivated     = FALSE;
    m_isDeferFinalizeNeeded = FALSE;
    m_SensorModePickhint    = {};
    m_isNameAllocated       = FALSE;
    m_isSensorModeHintSet   = FALSE;
    m_numInputBuffers       = 0;

    m_pPipelineDescriptorMetadata = ChiMetadata::Create();
    if (NULL == m_pPipelineDescriptorMetadata)
    {
        result = CDKResultENoMemory;
        CHX_LOG_ERROR("Failed to allocate memory for Pipeline Metadata");
    }

    if (m_type == PipelineType::OfflinePreview)
    {
        m_numInputBuffers  = 1; // Sensor - so no input buffer
        m_numOutputBuffers = 1; // Preview
        SetupRealtimePreviewPipelineDescriptor();
    }

    return result;
}

m_pipelineDescriptor.pNodes nodeId = 65538

m_nodes[nodeIndex].nodeAllPorts.pInputPorts portId=8

m_nodes[nodeIndex].nodeAllPorts.pOutputPorts portId=0

m_pipelineDescriptor.pLinks

srcNode.nodeId = 65538

m_links[0].numDestNodes = 1;

m_linkNodeDescriptors[0].nodeId = 2

/// Pipeline::SetupRealtimePreviewPipelineDescriptor

VOID Pipeline::SetupRealtimePreviewPipelineDescriptor()
{
    m_pipelineDescriptor.size       = sizeof(CHIPIPELINECREATEDESCRIPTOR);
    m_pipelineDescriptor.numNodes   = 1;
    m_pipelineDescriptor.pNodes     = &m_nodes[0];
    m_pipelineDescriptor.numLinks   = 1;
    m_pipelineDescriptor.pLinks     = &m_links[0];
    m_pipelineDescriptor.isRealTime = FALSE;

    // Nodes
    UINT32 nodeIndex = 0;
#if 0
    // ---------------------------------------------------------------------------
    // ---------------------------------- BPS ------------------------------------
    // ---------------------------------------------------------------------------
    m_nodes[nodeIndex].nodeId                      = 65539;
    m_nodes[nodeIndex].nodeInstanceId              = 0;
    m_nodes[nodeIndex].nodeAllPorts.numInputPorts  = 1;
    m_nodes[nodeIndex].nodeAllPorts.pInputPorts    = &m_inputPorts[BPSNode];
    m_nodes[nodeIndex].nodeAllPorts.numOutputPorts = 1;
    m_nodes[nodeIndex].nodeAllPorts.pOutputPorts   = &m_outputPorts[BPSNode];

    // BPS output port
    m_outputPorts[BPSNode].portId                  = 1;
    m_outputPorts[BPSNode].isSinkPort              = FALSE;
    m_outputPorts[BPSNode].isOutputStreamBuffer    = FALSE;
    // BPS input port
    m_inputPorts[BPSNode].portId                   = 0;
    m_inputPorts[BPSNode].isInputStreamBuffer      = TRUE;

    // ---------------------------------------------------------------------------
    // ---------------------------------- IPE ------------------------------------
    // ---------------------------------------------------------------------------
    nodeIndex++;
#endif

    m_nodes[nodeIndex].nodeId                      = 65538;
    m_nodes[nodeIndex].nodeInstanceId              = 0;
    m_nodes[nodeIndex].nodeAllPorts.numInputPorts  = 1;
    m_nodes[nodeIndex].nodeAllPorts.pInputPorts    = &m_inputPorts[IPENode];
    m_nodes[nodeIndex].nodeAllPorts.numOutputPorts = 1;
    m_nodes[nodeIndex].nodeAllPorts.pOutputPorts   = &m_outputPorts[IPENode];

    // IPE output port
    m_outputPorts[IPENode].portId                  = 8;
    m_outputPorts[IPENode].isSinkPort              = TRUE;
    m_outputPorts[IPENode].isOutputStreamBuffer    = TRUE;
    // IPE input port
    m_inputPorts[IPENode].portId                   = 0;
    m_inputPorts[IPENode].isInputStreamBuffer      = TRUE;

#if 0
    // ---------------------------------------------------------------------------
    // ---------------------------------- JPEG -----------------------------------
    // ---------------------------------------------------------------------------
    nodeIndex++;

    m_nodes[nodeIndex].nodeId                        = 65537;
    m_nodes[nodeIndex].nodeInstanceId                = 0;
    m_nodes[nodeIndex].nodeAllPorts.numInputPorts    = 1;
    m_nodes[nodeIndex].nodeAllPorts.pInputPorts      = &m_inputPorts[JPEGNode];
    m_nodes[nodeIndex].nodeAllPorts.numOutputPorts   = 1;
    m_nodes[nodeIndex].nodeAllPorts.pOutputPorts     = &m_outputPorts[JPEGNode];

    // JPEG output port
    m_outputPorts[JPEGNode].portId                   = 1;
    m_outputPorts[JPEGNode].isSinkPort               = FALSE;
    m_outputPorts[JPEGNode].isOutputStreamBuffer     = FALSE;
    // JPEG input port
    m_inputPorts[JPEGNode].portId                    = 0;
    m_inputPorts[JPEGNode].isInputStreamBuffer       = FALSE;

    // ---------------------------------------------------------------------------
    // ---------------------------------- JPEG AGRREGATOR ------------------------
    // ---------------------------------------------------------------------------
    nodeIndex++;

    m_nodes[nodeIndex].nodeId                        = 6;
    m_nodes[nodeIndex].nodeInstanceId                = 0;
    m_nodes[nodeIndex].nodeAllPorts.numInputPorts    = 1;
    m_nodes[nodeIndex].nodeAllPorts.pInputPorts      = &m_inputPorts[JPEGAgrregatorNode];
    m_nodes[nodeIndex].nodeAllPorts.numOutputPorts   = 1;
    m_nodes[nodeIndex].nodeAllPorts.pOutputPorts     = &m_outputPorts[JPEGAgrregatorNode];

    // JPEG output port
    m_outputPorts[JPEGAgrregatorNode].portId                = 1;
    m_outputPorts[JPEGAgrregatorNode].isSinkPort            = TRUE;
    m_outputPorts[JPEGAgrregatorNode].isOutputStreamBuffer  = TRUE;
    // JPEG input port
    m_inputPorts[JPEGAgrregatorNode].portId                 = 0;
    m_inputPorts[JPEGAgrregatorNode].isInputStreamBuffer    = FALSE;
#endif
    // ---------------------------------------------------------------------------
    // --------------------------------- Links -----------------------------------
    // ---------------------------------------------------------------------------

#if 0
    // BPS --> IPE
    m_links[0].srcNode.nodeId                     = 65539;
    m_links[0].srcNode.nodeInstanceId             = 0;
    m_links[0].srcNode.nodePortId                 = 1;
    m_links[0].numDestNodes                       = 1;
    m_links[0].pDestNodes                         = &m_linkNodeDescriptors[0];

    m_linkNodeDescriptors[0].nodeId               = 65538;
    m_linkNodeDescriptors[0].nodeInstanceId       = 0;
    m_linkNodeDescriptors[0].nodePortId           = 0;

    m_links[0].bufferProperties.bufferFlags       = BufferMemFlagHw;
    m_links[0].bufferProperties.bufferFormat      = ChiFormatUBWCTP10;
    m_links[0].bufferProperties.bufferHeap        = BufferHeapIon;
    m_links[0].bufferProperties.bufferQueueDepth  = 8;

    // IPE --> JPEG
    m_links[1].srcNode.nodeId                     = 65538;
    m_links[1].srcNode.nodeInstanceId             = 0;
    m_links[1].srcNode.nodePortId                 = 8;
    m_links[1].numDestNodes                       = 1;
    m_links[1].pDestNodes                         = &m_linkNodeDescriptors[1];

    m_linkNodeDescriptors[1].nodeId               = 65537;
    m_linkNodeDescriptors[1].nodeInstanceId       = 0;
    m_linkNodeDescriptors[1].nodePortId           = 0;

    m_links[1].bufferProperties.bufferFlags       = (BufferMemFlagHw | BufferMemFlagLockable);
    m_links[1].bufferProperties.bufferFormat      = ChiFormatYUV420NV12;
    m_links[1].bufferProperties.bufferHeap        = BufferHeapIon;
    m_links[1].bufferProperties.bufferQueueDepth  = 8;

    // JPEG --> JPEG Agrregator
    m_links[2].srcNode.nodeId                     = 65537;
    m_links[2].srcNode.nodeInstanceId             = 0;
    m_links[2].srcNode.nodePortId                 = 1;
    m_links[2].numDestNodes                       = 1;
    m_links[2].pDestNodes                         = &m_linkNodeDescriptors[2];

    m_linkNodeDescriptors[2].nodeId               = 6;
    m_linkNodeDescriptors[2].nodeInstanceId       = 0;
    m_linkNodeDescriptors[2].nodePortId           = 0;

    m_links[2].bufferProperties.bufferFlags       = (BufferMemFlagHw | BufferMemFlagLockable);
    m_links[2].bufferProperties.bufferFormat      = ChiFormatYUV420NV12;
    m_links[2].bufferProperties.bufferHeap        = BufferHeapIon;
    m_links[2].bufferProperties.bufferQueueDepth  = 8;

    // JPEG Aggregator --> Sink Buffer
    m_links[3].srcNode.nodeId                     = 6;
    m_links[3].srcNode.nodeInstanceId             = 0;
    m_links[3].srcNode.nodePortId                 = 1;
    m_links[3].numDestNodes                       = 1;
    m_links[3].pDestNodes                         = &m_linkNodeDescriptors[3];

    m_linkNodeDescriptors[3].nodeId               = 2;
    m_linkNodeDescriptors[3].nodeInstanceId       = 0;
    m_linkNodeDescriptors[3].nodePortId           = 0;
#endif

    m_links[0].srcNode.nodeId                     = 65538;
    m_links[0].srcNode.nodeInstanceId             = 0;
    m_links[0].srcNode.nodePortId                 = 8;
    m_links[0].numDestNodes                       = 1;
    m_links[0].pDestNodes                         = &m_linkNodeDescriptors[0];

    m_linkNodeDescriptors[0].nodeId               = 2;
    m_linkNodeDescriptors[0].nodeInstanceId       = 0;
    m_linkNodeDescriptors[0].nodePortId           = 0;
}

Pipeline::CreateDescriptor

1、初始化m_pipelineDescriptor pipelineCreateData

在UsecaseAuto::Initialize 解析UsecaseAuto_pipelines是初始化获取的

pipelineOutputBuffer[streamIdx].pStream = pSinkTargetDesc->pTarget->pChiStream;

pipelineOutputBuffer[streamIdx].pNodePort = pSinkTargetDesc->pNodePort;

pipelineOutputBuffer[streamIdx].numNodePorts = pSinkTargetDesc->numNodePorts;

2、解析ChiNode 中的node info 信息

1、pNodeProperties[i].pValues中保存的是支持的node 节点支持的算法信息com.qti.stats.pdlibwrapper com.qti.hvx.addconstant

2、获取HDR 模式信息 m_HDRInfo[logicalCameraId]

3、如果usecases(torch widget, AON),那么 IsNoBufferUsecase=true

4、当前场景中没使用torch widget, AON, auto usecase的 IsNoBufferUsecase = FALSE

5、获取帧率,判断是否支持HDR 模式

6、获取pLogicalCameraInfo 的m_cameraCaps.numSensorModes pSensorModeInfo

modeCount:

pLogicalCameraInfo->m_cameraCaps.numSensorModes

pAllModes:

pLogicalCameraInfo->pSensorModeInfo

7、根据pLogicalCameraInfo判断支持那种模式的HDR

1)、采用三曝光实现实时HDR预览

2)、Staggered HDR 行交织 HD

3)、MFHDR 多帧 HDR

4)、QHDR(Quad HDR,四像素HDR)

8、判断是否支持裁剪 根据设置传感器模式 设置分辨率

// Pipeline::CreateDescriptor

CDKResult Pipeline::CreateDescriptor()
{
    CDKResult          result                    = CDKResultSuccess;
    PipelineCreateData pipelineCreateData        = {};

    m_pipelineDescriptor.isRealTime              = HasSensorNode(&m_pipelineDescriptor);

    // m_cameraId from usecase side must be correct, even for pipelines without sensor Node
    m_pipelineDescriptor.cameraId                = m_cameraId;
    m_pipelineDescriptor.logicalCameraId         = m_logicalCameraId;
    m_pipelineDescriptor.context                 = m_context;

    pipelineCreateData.pPipelineName             = m_pPipelineName;
    pipelineCreateData.numOutputs                = m_numOutputBuffers;
    pipelineCreateData.pOutputDescriptors        = &m_pipelineOutputBuffer[0];
    pipelineCreateData.numInputs                 = m_numInputBuffers;
    pipelineCreateData.pInputOptions             = &m_pipelineInputOptions[0];
    pipelineCreateData.pPipelineCreateDescriptor = &m_pipelineDescriptor;

    CHIPIPELINECREATEDESCRIPTOR* pCreateDesc = pipelineCreateData.pPipelineCreateDescriptor;

    pCreateDesc->numBatchedFrames        = ExtensionModule::GetInstance()->GetNumBatchedFrames(m_logicalCameraId);
    pCreateDesc->HALOutputBufferCombined = ExtensionModule::GetInstance()->GetHALOutputBufferCombined();
    pCreateDesc->maxFPSValue             = ExtensionModule::GetInstance()->GetUsecaseMaxFPS(m_logicalCameraId);

    const CHAR* pClientName = "Chi::Pipeline::CreateDescriptor";
    SetTuningUsecase();

    m_pPipelineDescriptorMetadata->AddReference(pClientName);
    m_pipelineDescriptor.hPipelineMetadata = m_pPipelineDescriptorMetadata->GetHandle();

    CHX_LOG_CORE_CFG("Pipeline[%s] pipeline pointer %p numInputs=%d, numOutputs=%d stream w x h: %d x %d "
        "format: %d, numBatchedFrames: %d, HALOutputBufferCombined: %d maxFPSValue: %d cameraId: %d logicalCameraId:%d",
        m_pPipelineName,
        this,
        pipelineCreateData.numInputs,
        pipelineCreateData.numOutputs,
        (NULL != pipelineCreateData.pOutputDescriptors->pStream) ? pipelineCreateData.pOutputDescriptors->pStream->width : 0,
        (NULL != pipelineCreateData.pOutputDescriptors->pStream) ? pipelineCreateData.pOutputDescriptors->pStream->height : 0,
        (NULL != pipelineCreateData.pOutputDescriptors->pStream) ? pipelineCreateData.pOutputDescriptors->pStream->format : 0,
        pCreateDesc->numBatchedFrames,
        pCreateDesc->HALOutputBufferCombined,
        pCreateDesc->maxFPSValue,
        pipelineCreateData.pPipelineCreateDescriptor->cameraId,
        pipelineCreateData.pPipelineCreateDescriptor->logicalCameraId);

    UINT32 enableSWMCTFwithReferenceFrame = ExtensionModule::GetInstance()->GetMCTFwithReferenceFrameStatus(m_logicalCameraId);
    ChxUtils::SetVendorTagValue(m_pPipelineDescriptorMetadata,
        VendorTag::SWMCTFEnableWithRef,
        1,
        &enableSWMCTFwithReferenceFrame);

    UINT32 facialContourVersion = ExtensionModule::GetInstance()->GetFacialContourVersion(m_logicalCameraId);
    ChxUtils::SetVendorTagValue(m_pPipelineDescriptorMetadata,
        VendorTag::FacialContourVersion,
        1,
        &facialContourVersion);

    // Update stats skip pattern in node property with value from override
    //m_pipelineDescriptor.numNodes=3
    for (UINT node = 0; node < m_pipelineDescriptor.numNodes; node++)
    {
       //pNodes[node]=UsecaseAuto_AutoOfflineIFENodes[node]
        const ChiNode* const pChiNode = &m_pipelineDescriptor.pNodes[node];
        
       //pChiNode->numProperties=1 2 4
       //pChiNode->pNodeProperties=UsecaseAuto_AutoOfflineIFE_node0_0_properties
       //                            UsecaseAuto_AutoOfflineIFE_node65536_1_properties
       //                            UsecaseAuto_AutoOfflineIFE_node65536_0_properties
        for (UINT i = 0; i < pChiNode->numProperties; i++)
        {
           //pChiNode->pNodeProperties[i].id=1
            switch(pChiNode->pNodeProperties[i].id)
            { //解析node的算法
            //pNodeProperties[i].pValues = com.qti.stats.pdlibwrapper  com.qti.hvx.addconstant
                case NodePropertyStatsSkipPattern://6
                    m_statsSkipPattern = ExtensionModule::GetInstance()->GetStatsSkipPattern();
                    pChiNode->pNodeProperties[i].pValue = &m_statsSkipPattern;
                    break;
                case NodePropertyEnableFOVC://16
                    m_enableFOVC = ExtensionModule::GetInstance()->EnableFOVCUseCase();
                    pChiNode->pNodeProperties[i].pValue = &m_enableFOVC;
                    break;
                case NodePropertyNISInternalTrigger://21 
                    m_isNISInternalTrigger = ExtensionModule::GetInstance()->IsInternalTriggered(m_logicalCameraId);
                    pChiNode->pNodeProperties[i].pValue = &m_isNISInternalTrigger;
                    break;
                default:
                    break;
            }
        }
    }
    //初始化pCreatePipelineDescriptor m_hPipelineHandle
    m_hPipelineHandle = ExtensionModule::GetInstance()->CreatePipelineDescriptor(&pipelineCreateData);

    m_pPipelineDescriptorMetadata->ReleaseReference(pClientName);

    if (NULL == m_hPipelineHandle)
    {
        result = CDKResultEFailed;
        CHX_LOG_ERROR("Fail due to NULL pipeline handle");
    }
    else
    {//获取HDR 模式信息  m_HDRInfo[logicalCameraId]
        const HDRInfo&    rHDRInfo              = ExtensionModule::GetInstance()->GetHDRInfo(m_logicalCameraId);
        HDRDeviceInfo*    pLogicalHDRDeviceInfo = rHDRInfo.pLogicalHDRDeviceInfo;
        ChiHDRModeInfo    physicalHDRModeInfo   =
                ExtensionModule::GetInstance()->GetPhysicalDeviceHDRModeInfo(m_logicalCameraId, m_cameraId);
        ChiHDRFeatureMode physicalHDRMode       = physicalHDRModeInfo.HDRMode;
        //usecases(torch widget, AON). IsNoBufferUsecase=true
        //auto usecase  IsNoBufferUsecase = FALSE
        if ((FALSE == ExtensionModule::GetInstance()->IsNoBufferUsecase()))
        {
            // sensor mode selection not required for no buffer usecases(torch widget, AON).
            DesiredSensorMode desiredSensorMode = {};
            //获取帧率
            desiredSensorMode.frameRate = ExtensionModule::GetInstance()->GetUsecaseMaxFPS(m_logicalCameraId);
            //判断是否支持HDR 模式
            if (ExtensionModule::GetInstance()->IsVideoHDRMode())
            {
                const auto sensorModes = [&]() -> ChiPtrView<CHISENSORMODEINFO>
                {
                    UINT32             modeCount = 0;
                    CHISENSORMODEINFO* pAllModes = NULL;
                    //获取pLogicalCameraInfo  modeCount pAllModes
                    //pLogicalCameraInfo->m_cameraCaps.numSensorModes
                    //pLogicalCameraInfo->pSensorModeInfo;
                    if (CDKResultSuccess == ExtensionModule::GetInstance()->GetPhysicalCameraSensorModes(m_cameraId,
                                                                                                         &modeCount,
                                                                                                         &pAllModes))
                    {
                        return ChiPtrView{static_cast<SIZE_T>(modeCount), pAllModes};
                    }
                    return ChiPtrView<CHISENSORMODEINFO>(static_cast<SIZE_T>(0), NULL);
                }();

                auto SupportsZZHDR = [&](const ChiSensorModeInfo& rSensorModeInfo)
                {
                    return rSensorModeInfo.sensorModeCaps.u.ZZHDR;
                };
                desiredSensorMode.sensorModeCaps.u.ZZHDR = std::any_of(sensorModes.begin(), sensorModes.end(), SupportsZZHDR);
            }//采用三曝光实现实时HDR预览
            else if (SelectInSensorHDR3ExpUsecase::InSensorHDR3ExpPreview ==
                     ExtensionModule::GetInstance()->SelectInSensorHDR3ExpUsecase())
            {
                desiredSensorMode.sensorModeCaps.u.IHDR = 1;
            }//Staggered HDR 行交织 HDR
            else if (HDRFeatureModeSHDR == physicalHDRMode)
            {
                desiredSensorMode.sensorModeCaps.u.SHDR = 1;
                desiredSensorMode.sensorHDRExposureType = ChiHDRExposureType::TwoExposure;
                if (FALSE == rHDRInfo.isAutoHDREnabled)
                {
                    switch (rHDRInfo.appReqNumHDRExposure)
                    {
                        case SingleHDRExposure:
                            desiredSensorMode.sensorHDRExposureType = ChiHDRExposureType::OneExposure;
                            break;
                        case TwoHDRExposure:
                            desiredSensorMode.sensorHDRExposureType = ChiHDRExposureType::TwoExposure;
                            break;
                        case ThreeHDRExposure:
                            desiredSensorMode.sensorHDRExposureType = ChiHDRExposureType::ThreeExposure;
                            break;
                        default:
                            desiredSensorMode.sensorHDRExposureType = ChiHDRExposureType::TwoExposure;
                            break;
                    }
                }
            }//MFHDR 多帧 HDR
            else if (HDRFeatureModeMFHDR == physicalHDRMode)
            {
                desiredSensorMode.sensorModeCaps.u.Normal = TRUE;
                // For MFHDR case, we will run sensor @ twice the desired output framerate
                desiredSensorMode.frameRate *= 2;
            }//QHDR(Quad HDR,四像素HDR)
            else if (HDRFeatureModeQHDR == physicalHDRMode)
            {
                if (TRUE == rHDRInfo.appEnabledQHDR)
                {
                    desiredSensorMode.sensorModeCaps.u.QHDR = 1;
                    desiredSensorMode.sensorHDRExposureType = ChiHDRExposureType::ThreeExposure;
                }
            }

            UINT index = FindHighestWidthInputIndex(m_pipelineInputOptions, m_numInputOptions);
            // @todo Select the highest width/height from all the input buffer requirements
            desiredSensorMode.optimalWidth  = m_pipelineInputOptions[index].bufferOptions.optimalDimension.width;
            desiredSensorMode.optimalHeight = m_pipelineInputOptions[index].bufferOptions.optimalDimension.height;
            desiredSensorMode.maxWidth      = m_pipelineInputOptions[index].bufferOptions.maxDimension.width;
            desiredSensorMode.maxHeight     = m_pipelineInputOptions[index].bufferOptions.maxDimension.height;
            desiredSensorMode.minWidth      = m_pipelineInputOptions[index].bufferOptions.minDimension.width;
            desiredSensorMode.minHeight     = m_pipelineInputOptions[index].bufferOptions.minDimension.height;
            desiredSensorMode.forceMode     = ExtensionModule::GetInstance()->GetForceSensorMode(m_cameraId);

            if (TRUE == m_isSensorModeHintSet)
            {
                CHX_LOG("input option:%dx%d, upscale:%d, override optimal size:%dx%d, sensor mode caps:%x",
                    desiredSensorMode.optimalWidth, desiredSensorMode.optimalHeight,
                    m_SensorModePickhint.postSensorUpscale,
                    m_SensorModePickhint.sensorOutputSize.width,
                    m_SensorModePickhint.sensorOutputSize.height,
                    m_SensorModePickhint.sensorModeCaps.value);
                
                 //判断是否支持裁剪 根据设置传感器模式 设置分辨率
                if ((TRUE == m_SensorModePickhint.postSensorUpscale) &&
                    (m_SensorModePickhint.sensorOutputSize.width  < desiredSensorMode.optimalWidth) &&
                    (m_SensorModePickhint.sensorOutputSize.height < desiredSensorMode.optimalHeight))
                {
                    desiredSensorMode.optimalWidth  = m_SensorModePickhint.sensorOutputSize.width;
                    desiredSensorMode.optimalHeight = m_SensorModePickhint.sensorOutputSize.height;
                    desiredSensorMode.maxWidth      = desiredSensorMode.optimalWidth;
                    desiredSensorMode.maxHeight     = desiredSensorMode.optimalHeight;
                    desiredSensorMode.minWidth      = desiredSensorMode.optimalWidth;
                    desiredSensorMode.minHeight     = desiredSensorMode.optimalHeight;
                }

                if (0 != m_SensorModePickhint.sensorModeCaps.value)
                {
                    desiredSensorMode.sensorModeCaps.value = m_SensorModePickhint.sensorModeCaps.value;
                }
                if (0 != m_SensorModePickhint.frameRateMultiplier)
                {
                    desiredSensorMode.frameRate *= m_SensorModePickhint.frameRateMultiplier;
                }

                if (TRUE == m_SensorModePickhint.sensorModeCaps.u.QuadCFA)
                {
                    desiredSensorMode.sensorRemosaicType = ExtensionModule::GetInstance()->GetRemosaicType();
                }
            }
            if (StreamConfigModeFastShutter == ExtensionModule::GetInstance()->GetOpMode(m_cameraId))
            {
                desiredSensorMode.sensorModeCaps.u.FS = 1;
            }

            if (HDRFeatureModeQHDR == physicalHDRMode)
            {
                // QCFA binning mode
                if (FALSE == rHDRInfo.appEnabledQHDR)
                {
                    desiredSensorMode.optimalWidth  = m_pipelineInputOptions[index].bufferOptions.optimalDimension.width >> 1;
                    desiredSensorMode.optimalHeight = m_pipelineInputOptions[index].bufferOptions.optimalDimension.height >> 1;
                }
            }

            m_pSelectedSensorMode                   = ChxSensorModeSelect::FindBestSensorMode(m_cameraId, &desiredSensorMode);
            m_pSelectedSensorMode->batchedFrames    = ExtensionModule::GetInstance()->GetNumBatchedFrames(m_logicalCameraId);
            m_pSelectedSensorMode->HALOutputBufferCombined = ExtensionModule::GetInstance()->GetHALOutputBufferCombined();
        }


        if (TRUE == m_pipelineDescriptor.isRealTime)
        {
            if ((NULL               != pLogicalHDRDeviceInfo) &&
                (HDRFeatureModeSHDR == pLogicalHDRDeviceInfo->HDRModeInfo.HDRMode) &&
                (InvalidMode        != ExtensionModule::GetInstance()->GetForceSensorMode(m_cameraId)))
            {
                // This is to handle the case wherre overridesensor mode is used
                pLogicalHDRDeviceInfo->numHDRExposure = static_cast<UINT>(m_pSelectedSensorMode->HDRExposureType) + 1;
            }

            m_pipelineInfo.pipelineInputInfo.isInputSensor              = TRUE;
            m_pipelineInfo.pipelineInputInfo.sensorInfo.cameraId        = m_cameraId;
            m_pipelineInfo.pipelineInputInfo.sensorInfo.pSensorModeInfo = m_pSelectedSensorMode;
            CHX_LOG_CORE_CFG("Pipeline[%s] Pipeline pointer %p Selected sensor Mode W=%d, H=%d Mode=%d",
                m_pPipelineName,
                this,
                m_pipelineInfo.pipelineInputInfo.sensorInfo.pSensorModeInfo->frameDimension.width,
                m_pipelineInfo.pipelineInputInfo.sensorInfo.pSensorModeInfo->frameDimension.height,
                m_pipelineInfo.pipelineInputInfo.sensorInfo.pSensorModeInfo->modeIndex);

                std::vector transition_modes = {1, 2, 3};
                std::copy(transition_modes.begin(), transition_modes.end(), std::back_inserter(m_transitionModesList));
            // add changes to get the list of seamless mode transitions possible for this sensor mode
        }
        else
        {
            m_pipelineInfo.pipelineInputInfo.isInputSensor                           = FALSE;
            m_pipelineInfo.pipelineInputInfo.inputBufferInfo.numInputBuffers         = m_numInputBuffers;
            m_pipelineInfo.pipelineInputInfo.inputBufferInfo.pInputBufferDescriptors = GetInputBufferDescriptors();

            if ((FALSE == ExtensionModule::GetInstance()->IsNoBufferUsecase()))
            {
                CHIBUFFERDIMENSION sensorOutDim = {};
                sensorOutDim.width              = m_pSelectedSensorMode->frameDimension.width;
                sensorOutDim.height             = m_pSelectedSensorMode->frameDimension.height;

                for (UINT32 i = 0; i < m_numInputOptions; i++)
                {
                    CHIBUFFEROPTIONS& rBufferOptions = m_pipelineInputOptions[i].bufferOptions;

                    if ((rBufferOptions.minDimension.width  > sensorOutDim.width) ||
                        (rBufferOptions.minDimension.height > sensorOutDim.height))
                    {
                        CHX_LOG_INFO("override min requirement to sensor output size. %dx%d -> %dx%d",
                            rBufferOptions.minDimension.width, rBufferOptions.minDimension.height,
                            sensorOutDim.width, sensorOutDim.height);

                        rBufferOptions.minDimension = sensorOutDim;
                    }

                    if ((rBufferOptions.minDimension.width  > rBufferOptions.optimalDimension.width) ||
                        (rBufferOptions.minDimension.height > rBufferOptions.optimalDimension.height))
                    {
                        rBufferOptions.optimalDimension = rBufferOptions.minDimension;
                    }
                }
            }
        }

        m_pipelineInfo.hPipelineDescriptor                = reinterpret_cast<CHIPIPELINEDESCRIPTOR>(m_hPipelineHandle);
        m_pipelineInfo.pipelineOutputInfo.hPipelineHandle = NULL;
        m_pipelineInfo.pipelineResourcePolicy             = m_resourcePolicy;
        m_pipelineInfo.isDeferFinalizeNeeded              = m_isDeferFinalizeNeeded;
    }

    return result;
}
相关推荐
Chandler2416 分钟前
C++11 多线程 锁与条件变量:mutex、lock_guard、unique_lock 和 condition_variable
c++
h^hh1 小时前
堆的模拟实现(详解)c++
数据结构·c++·算法
被AI抢饭碗的人2 小时前
c++:list
开发语言·c++
亦梦亦醒乐逍遥3 小时前
【C++基础】字符串/字符读取函数解析
java·c++·算法
CHANG_THE_WORLD4 小时前
C++泛型编程指南08 auto decltype
java·jvm·c++
利刃大大5 小时前
【数据结构与算法】九大排序算法实现详解
c语言·数据结构·c++·算法·排序算法
qystca6 小时前
【16届蓝桥杯寒假刷题营】第2期DAY2
数据结构·c++·算法·深度优先·二分·爆搜
我命由我123457 小时前
游戏引擎 Unity - Unity 设置为简体中文、Unity 创建项目
c语言·开发语言·c++·unity·visualstudio·c#·游戏引擎
和风化雨7 小时前
排序算法--插入排序
c语言·c++·算法·排序算法
暮色初上_8 小时前
700. 二叉搜索树中的搜索
c++·leetcode·回归算法