Camx MetaData的流程

 因为这段时间工作的时候老是看到各种metadata,真的时烦死了。对这个东西之前简单的了解了一下,对这个东西了解的还不是很系统,所以接下来的这段时间打算好好的整理一下这个metada。前期的时候我会把我整理的这些东西简单的整理成比较碎片的文档,等后面完全通的时候再把这些东西顺下来。

前期学习的时候真的是一件很痛苦的事情,但是学习就是这样的在痛苦中成长。我就不写学习计划了,我学到了什么就先写什么,比较碎片化。

把hal所有的metadata放在一起

主要就是这个AppendVendorTagInfo函数,代代表三类的meta。hw和core这两类是高通自己定义的,正常情况下我们是不会去改动这些的。我自己加的meta属于componentVendorTag这个类别里面。

//单例模式
VendorTagManager* VendorTagManager::GetInstance()
{
    static VendorTagManager s_VendorTagManagerSingleton;
    return &s_VendorTagManagerSingleton;
}

VendorTagManager::VendorTagManager()
{
    CamxResult result = InitializeVendorTagInfo();
}
CamxResult VendorTagManager::InitializeVendorTagInfo()
{
    VendorTagInfo            hwVendorTagInfo = { 0 };
    ComponentVendorTagsInfo  componentVendorTagsInfo = { 0 };
    VendorTagInfo            coreVendorTagInfo = { g_CamXVendorTagSections, CAMX_ARRAY_SIZE(g_CamXVendorTagSections) };

    // Query the vendor tag information from HW
    result = pHwEnvironment->GetHwStaticEntry()->QueryVendorTagsInfo(&hwVendorTagInfo);
    result = AppendVendorTagInfo(&hwVendorTagInfo);
    result = AppendVendorTagInfo(&coreVendorTagInfo);

    // Query the vendor tag information from External Component
    for (UINT32 i = 0; i < componentVendorTagsInfo.numVendorTagInfo ; i++)
    {
        result = AppendVendorTagInfo(&componentVendorTagsInfo.pVendorTagInfoArray[i]);
        
    }
    
}
1.hwVendorTagInfo

这是对应结构体的定义

struct VendorTagInfo
{
    VendorTagSectionData* pVendorTagDataArray;               ///< An array of vendor tag section
    UINT32                numSections;                       ///< The number of vendor tag section in pVendorTagDataArray
};

struct VendorTagSectionData
{
    const CHAR*          pVendorTagSectionName;              ///< The string representing the vendor tag section name
    VendorTag            firstVendorTag;                     ///< The first vendor tag in the vendor tag section
    UINT32               numTags;                            ///< The number of vendor tags in the section
    VendorTagData*       pVendorTagaData;                    ///< An array of vendor tag data arrays
    TagSectionVisibility visbility;                          ///< Visibility of this tag section
};

typedef UINT32 VendorTag;

struct VendorTagData
{
    const CHAR*     pVendorTagName; ///< The string representation of the vendor tag name
    VendorTagType   vendorTagType;  ///< The type of the vendor tag
    SIZE_T          numUnits;      ///< The number of units of vendorTagType needed to program this tag
};

enum class VendorTagType : UINT8
{
    Byte     = 0,   ///< Unsigned 8-bit integer
    Int32    = 1,   ///< Signed 32-bit integer
    Float    = 2,   ///< 32-bit float
    Int64    = 3,   ///< Signed 64-bit integer
    Double   = 4,   ///< 64-bit float
    Rational = 5,   ///< A 64-bit fraction
    Error    = 255, ///< Complies with COMMON API if an invalid vendor tag specified
}; 

enum TagSectionVisibility : UINT32
{
    TagSectionVisibleToOEM               = 0x1,              ///< VenderTag section visible to OEM
    TagSectionVisibleToFramework         = 0x2,              ///< VenderTag section visible to Android framework
    TagSectionVisibleToAll               = 0xFFFFFFFF,       ///< VenderTag section visible to All
};

 接下来看下hwVendorTagInfo是怎么获取到的

result = pHwEnvironment->GetHwStaticEntry()->QueryVendorTagsInfo(&hwVendorTagInfo);

 CamxResult Titan17xContext::QueryVendorTagsInfo(VendorTagInfo* pVendorTagInfo)
{
    pVendorTagInfo->pVendorTagDataArray = g_HwVendorTagSections;
    pVendorTagInfo->numSections         = CAMX_ARRAY_SIZE(g_HwVendorTagSections);
}

可以说只要找到g_HwVendorTagSections 是怎么来的就找到了hwVendorTagInfo,这个正好是高通定义的一个数组。

static VendorTagSectionData g_HwVendorTagSections[] =
{
    ......
    {
        "xxx.xxx.xxx", //pVendorTagSectionName
        0,             //firstVendorTag
        CAMX_ARRAY_SIZE(g_VendorTagSectionSharpness), //numTags
        g_VendorTagSectionSharpness,                  //pVendorTagaData
        TagSectionVisibility::TagSectionVisibleToAll  //visbility
    }
    ......
}

static VendorTagData g_VendorTagSectionSharpness[] =
{
    { 
        "strength",            //pVendorTagName
        VendorTagType::Int32,  //vendorTagType
        1                      //numUnits
    }
}
2.coreVendorTagInfo

这个类型跟g_HwVendorTagSections差不多,我就随便找一个例子分析下,因为有些还是有差异的

static VendorTagSectionData g_CamXVendorTagSections[] =
{
         {
             "org.codeaurora.qcamera3.internal_private",
              VendorTagPrivate,
             CAMX_ARRAY_SIZE(g_VendorTagSectionInernalPrivate),             
             g_VendorTagSectionInernalPrivate,
             TagSectionVisibility::TagSectionVisibleToOEM
     }, 
}

static const UINT32 NumOfVendorTagOffsetBit   = 16;
MetadataSectionVendorSection = 0x8000
VendorTagSectionPrivate                   = MetadataSectionVendorSection

static const VendorTag VendorTagPrivate = static_cast<VendorTag>(VendorTagSectionPrivate << NumOfVendorTagOffsetBit);

static VendorTagData g_VendorTagSectionInernalPrivate[] =
{
    {
        "private_property", 
        VendorTagType::Byte, 
        PropertyBlobSize 
} // tagId + value + number of tags
}

static const UINT PropertyBlobSize = sizeof(MainPropertyBlob) + sizeof(MainPropertyLinearLUT) + sizeof(UINT32);

这两个是个数组,几乎把所有的tagid否枚举出来了到时候研究一下
3. componentVendorTagsInfo

可以看到这个是对hwVendorTagInfo的进一步封装

struct ComponentVendorTagsInfo
{
    VendorTagInfo*        pVendorTagInfoArray;               ///< An array of vendor tag info
    UINT32                numVendorTagInfo;                  ///< The number of vendortag info section in pVendorTagInfoArray
};
pHwEnvironment->GetHwStaticEntry()->QueryExternalComponentVendorTagsInfo(&componentVendorTagsInfo);

CamxResult Titan17xContext::QueryExternalComponentVendorTagsInfo(ComponentVendorTagsInfo* pComponentVendorTagsInfo)
{
    pComponentVendorTagsInfo->pVendorTagInfoArray   = g_componentVendorTagsInfo.pVendorTagInfoArray;
    pComponentVendorTagsInfo->numVendorTagInfo      = g_componentVendorTagsInfo.numVendorTagInfo;
}

 这个主要是找到g_componentVendorTagsInfo被赋值的地方就可以找到这一类是怎么来的了。

这里就要从开启动的流程开始说起了

//这是一个典型的单例模式实现方式可以学习一下
HwEnvironment* HwEnvironment::GetInstance()
{
    static HwEnvironment s_HwEnvironmentSingleton;
    if (InitCapsInitialize == s_HwEnvironmentSingleton.m_initCapsStatus)
    {
        s_HwEnvironmentSingleton.InitCaps();
    }
    
    return &s_HwEnvironmentSingleton;
}

//开机启动的时候会调用这个函数
 HwEnvironment::HwEnvironment()                                                                                                                                                     
    : m_initCapsStatus(InitCapsInvalid)                                                                                                                      
    , m_pNCSObject(NULL)                                                                                                                                              {                                                                                                                                                                         
    Initialize();                                                                                                                                                     } 

CamxResult HwEnvironment::Initialize()
{
    ExternalComponentInfo*  pExternalComponent      = GetExternalComponent();
    CAMX_ASSERT(NULL != pExternalComponent);
    
    if ((CamxResultSuccess == result) && (NULL != pExternalComponent))
    {
        result = ProbeChiComponents(pExternalComponent, &m_numExternalComponent);//主要是这个函数比较重要
    }
}


CAMX_INLINE ExternalComponentInfo* GetExternalComponent() const
{
    return (ExternalComponentInfo*)&m_externalComponent[0];//感觉这里就是单纯的传递一个地址
}

从下面开始就是重头戏了,这个看明白就知道为什么我们客制化要在node或者chi里面定义tag的原因了。

这是传入的参数的数据结构

struct ExternalComponentInfo
{
    CHAR*                          pComponentName;     ///< External Component name

    union
    {
        CHINODEINTERFACE           nodeInterface;      ///< node Interface for custom node to call into Chi.
        CHIALGORITHMINTERFACE      algoInterface;      ///< algo Interface for custom node to call into Chi.
    };

    union
    {
        CHINODECALLBACKS                nodeCallbacks;          ///< Node Callback Interface for Chi to call into custom node.
        CHIHISTALGORITHMCALLBACKS       histAlgoCallbacks;      ///< Algo Callback Interface for Chi to call into custom node.
        CHIAECALGORITHMCALLBACKS        AECAlgoCallbacks;       ///< Algo Callback Interface for Chi to call into custom node.
        CHIAFALGORITHMCALLBACKS         AFAlgoCallbacks;        ///< Algo Callback Interface for Chi to call into custom node.
        CHIAWBALGORITHMCALLBACKS        AWBAlgoCallbacks;       ///< Algo Callback Interface for Chi to call into custom node.
        CHIAFDALGORITHMCALLBACKS        AFDAlgoCallbacks;       ///< Algo Callback Interface for Chi to call into custom node.
        CHIASDALGORITHMCALLBACKS        ASDAlgoCallbacks;       ///< Algo Callback Interface for Chi to call into custom node.
        CHIPDLIBRARYCALLBACKS           PDLibCallbacks;         ///< Algo Callback Interface for Chi to call into custom node.
        CHIISPHVXALGORITHMCALLBACKS     HVXAlgoCallbacks;       ///< Algo Callback Interface for Chi to call into custom node.
        CHITRACKERALGORITHMCALLBACKS    trackerAlgoCallbacks;   ///< Algo Callback Interface for chi to call into custom code.
    };

    ExternalComponentNodeAlgo      nodeAlgoType;       ///< 0 for node and 1 for algo
    BOOL                           inUse;              ///< 1 for inUse and 0 for free
    ExternalComponentStatsAlgo     statsAlgo;          ///< stats algo type
}; 

 enum class ExternalComponentNodeAlgo                                                                                                                                  {                                                                                                                                                                                 
    COMPONENTNODE      = 0,   ///< Node                                                                                                                                       
    COMPONENTALGORITHM = 1,   ///< Algorithm                                                                                                                              
    COMPONENTHVX       = 2,   ///< Hvx                                                                                                                                };  

enum class ExternalComponentStatsAlgo
{
	ALGOAEC  = 0,       ///< AEC
	ALGOAF,             ///< AF
	ALGOAWB,            ///< AWB
	ALGOAFD,            ///< AFD
	ALGOASD,            ///< ASD
	ALGOPD,             ///< PD
	ALGOHIST = 7,       ///< Histogram Algo
	ALGOTRACK,          ///< Track
};

 这是对应的处理流程

CamxResult ProbeChiComponents(
    ExternalComponentInfo* pExternalComponentInfo,
    UINT*                  pNumExternalComponent)
{
    UINT16               fileCountTypeNode  = 0;
    UINT16               fileCountTypeStats = 0;
    UINT16               fileCountTypeOverride = 0;
    UINT16               fileCountTypeHvx   = 0;

    //这是在用通配符计算对应的so的数量
    fileCountTypeOverride = OsUtils::GetFilesFromPath(CHIOverrideModulePath,
                                                      FILENAME_MAX,                         
                                                      &chiOverrideSoFileName[0],
                                                      "*",
                                                      "chi",
                                                      "*",
                                                      "*",                                                                   
                                                      &SharedLibraryExtension[0]);
     fileCountTypeNode  = OsUtils::GetFilesFromPath(ExtCompPath,
                                                    FILENAME_MAX,
                                                    &soFilesName[0][0],
                                                    "*",
                                                    "node",
                                                    "*",
                                                    "*",
                                                    &SharedLibraryExtension[0]);
     fileCountTypeStats = OsUtils::GetFilesFromPath(ExtCompPath,
                                                    FILENAME_MAX,
                                                    &soFilesName[fileCountTypeNode][0],
                                                    "*",
                                                    "stats",
                                                    "*",
                                                    "*",
                                                    &SharedLibraryExtension[0]);
     fileCountTypeHvx   = OsUtils::GetFilesFromPath(ExtCompPath,
                                                    FILENAME_MAX,
                                                    &soFilesName[fileCountTypeNode+fileCountTypeStats][0],
                                                    "*",
                                                    "hvx",
                                                    "*",
                                                    "*",
                                                    &SharedLibraryExtension[0]);
    //这就是我们传过来的第二个参数在这里被赋值的  
    *pNumExternalComponent = fileCountTypeNode + fileCountTypeStats + fileCountTypeHvx;
    
    while (index < fileCountTypeNode + fileCountTypeStats + fileCountTypeHvx)
    {
        if (index < fileCountTypeNode)
        {
            CamX::OSLIBRARYHANDLE handle = CamX::OsUtils::LibMap(&soFilesName[index][0]);
            pNodeEntry = reinterpret_cast<PFCHINODEENTRY>(CamX::OsUtils::LibGetAddr(handle, "ChiNodeEntry"));
            pNodeEntry(&pExternalComponentInfo[index].nodeCallbacks);
            if (NULL != pExternalComponentInfo[index].nodeCallbacks.pQueryVendorTag)
            {              
                //这一句很重要
                GetComponentTag(pExternalComponentInfo[index].nodeCallbacks.pQueryVendorTag);
            }
        }
        else if (index < (fileCountTypeNode+fileCountTypeStats))
        {
            pExternalComponentInfo[index].nodeAlgoType = ExternalComponentNodeAlgo::COMPONENTALGORITHM;
            if (OsUtils::GetFileNameToken(&soFilesName[index][0], 4, outTokenString, FILENAME_MAX) == TRUE)
            {
                if (0 == OsUtils::StrNICmp(outTokenString, AECToken, OsUtils::StrLen(AECToken)))
                {
                    ......
                    //这一句很重要
                    GetAECAlgorithmCallback(&soFilesName[index][0], pExternalComponentInfo, index);
                    pExternalComponentInfo[index].statsAlgo = ExternalComponentStatsAlgo::ALGOAEC;
                }
                ......
            }
        }
        else
        {
            pExternalComponentInfo[index].nodeAlgoType = ExternalComponentNodeAlgo::COMPONENTHVX;
            GetHVXAlgorithmCallback(&soFilesName[index][0], pExternalComponentInfo, index); 
        }
    }
    if (0 < fileCountTypeOverride)
    {
        PFNCHIQUERYVENDORTAG pQueryVendorTag;
        pQueryVendorTag = reinterpret_cast<PFNCHIQUERYVENDORTAG>(CamX::OsUtils::LibGetAddr(CamX::OsUtils::LibMap(&chiOverrideSoFileName[fileIndex]), "chi_hal_query_vendertag"));
    GetComponentTag(pQueryVendorTag);
    }
}    

上面的逻辑主要分成两个,一个是while循环里面,另外一个是fileCountTypeOverride

首先分析while循环里面的内容

pNodeEntry = reinterpret_cast<PFCHINODEENTRY>(CamX::OsUtils::LibGetAddr(handle, "ChiNodeEntry"));

VOID* OsUtils::LibGetAddr(
    OSLIBRARYHANDLE hLibrary,
    const CHAR*     pProcName)
{
    VOID* pProcAddr = NULL;

    if (hLibrary != NULL)
    {
        pProcAddr = dlsym(hLibrary, pProcName);
    }
    return pProcAddr;
} 

//dlsym是一个计算机函数,功能是根据动态链接库操作句柄与符号,返回符号对应的地址,不但可以获取函数地址,也可以获取变量地址
//所以上面就相当于拿到了node的这个函数的句柄

pNodeEntry(&pExternalComponentInfo[index].nodeCallbacks);
//在每个node中都会有一个ChiNodeEntry函数,里面会定义所有的函数接口
//这里就相当于拿到了node的所有的函数。

CDK_VISIBILITY_PUBLIC VOID ChiNodeEntry(
    CHINODECALLBACKS* pNodeCallbacks)
{
    pNodeCallbacks->majorVersion             = ChiNodeMajorVersion;
    pNodeCallbacks->minorVersion             = ChiNodeMinorVersion;
    pNodeCallbacks->pGetCapabilities         = MemCpyNodeGetCaps;
    pNodeCallbacks->pQueryVendorTag          = MemCpyNodeQueryVendorTag;
    pNodeCallbacks->pCreate                  = MemCpyNodeCreate;
    pNodeCallbacks->pDestroy                 = MemCpyNodeDestroy;
    pNodeCallbacks->pQueryBufferInfo         = MemCpyNodeQueryBufferInfo;
    pNodeCallbacks->pSetBufferInfo           = MemCpyNodeSetBufferInfo;
    pNodeCallbacks->pProcessRequest          = MemCpyNodeProcRequest;
    pNodeCallbacks->pChiNodeSetNodeInterface = MemCpyNodeSetNodeInterface;
    pNodeCallbacks->pFlushRequest            = MemCpyNodeFlushRequest;
    pNodeCallbacks->pGetFlushResponse        = MemCpyNodeGetFlushResponseTime;
}
可以看到这是这个node所有的函数接口,pNodeCallbacks->pQueryVendorTag          = MemCpyNodeQueryVendorTag;只要拿到对应的callback就可以调用到对应的接口。

CDKResult MemCpyNodeQueryVendorTag(
    CHIQUERYVENDORTAG* pQueryVendorTag)
{
    CDKResult result = CDKResultSuccess;
    result = ChiNodeUtils::QueryVendorTag(pQueryVendorTag, g_VendorTagInfoMemCpy);

    return result;
}

g_VendorTagInfoMemCpy这个变量定义的就是这个node相关的tag
GetComponentTag(pExternalComponentInfo[index].nodeCallbacks.pQueryVendorTag);

pExternalComponentInfo[index].nodeCallbacks.pQueryVendorTag这里就可以调用到上面看的那个node对应的接口。

接下来看GetComponentTag()这个接口。

void GetComponentTag(
    PFNCHIQUERYVENDORTAG pfnQueryVendorTag)
{
   CHIQUERYVENDORTAG queryVendorTag = {0};

   queryVendorTag.size = sizeof(CHIQUERYVENDORTAG);
   pfnQueryVendorTag(&queryVendorTag);//这就是node中的接口

    AddComponentTag(&queryVendorTag); //这里把node获取到的tag传进去
}

CamxResult AddComponentTag(
    CHIQUERYVENDORTAG*   pQueryVendorTag)
{
    // Append to the global vendor tag info list
    UINT32 index = g_componentVendorTagsInfo.numVendorTagInfo;
    g_componentVendorTagsInfo.pVendorTagInfoArray[index].numSections =
        pQueryVendorTag->pVendorTagInfo->numSections;
    g_componentVendorTagsInfo.pVendorTagInfoArray[index].pVendorTagDataArray =
        reinterpret_cast<VendorTagSectionData *>(pQueryVendorTag->pVendorTagInfo->pVendorTagDataArray);
    g_componentVendorTagsInfo.numVendorTagInfo = g_componentVendorTagsInfo.numVendorTagInfo + 1;
}

g_componentVendorTagsInfo  //这个是不是很眼熟,我们最开始的目的就是为了找这个变量赋值的地方。现在终于找到咯

后面还有相关的AEC、AF、HVX这些地方去获取meta。跟这个获取node都是类似的可以追一下流程都是这种通过获取到对应的接口,然后获取到对应的tag。

到这里也可以明白为什么我们这些第三方加tag要加在chi和对应的nde里面了,这里也对高通说chi是开放给第三方的做客制化流程的节点有进一步的理解了。

  • 8
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值