HAL3对camera的控制是通过metadata进行控制的。在相机初始化的时候会获取一个默认设置,然后在请求每一帧的时候,把需要设置的参数在metadata中更新,再参数也下发下去。
那么带来了两个问题:
如何对接上层,告诉它我有相应的接口,如果你想要实现某个功能,就设置metadata就行了。
其次如何在CHI节点中又获取到上层设置的接口呢?CHI之间的3A,人脸识别等统计信息也是通过metadata传递的,在CHI之间如何获取呢?
本文从这两个方面去解答。
设置和获取上层的metadata
元数据标签可以是预定义的Android标签,也可以是定制的供应商标签。供应商标签在HAL中定义,以支持Camx和Chi所需的附加元数据。供应商标签信息有三种类型:hwVendorTagInfo、componentVendorTagsInfo和coreVendorTagInfo。我们需要添加相应的vendor标签。
hwVendorTagInfo: 在camxtitan17xcontext.cpp中定义,被Core、HWL、SWL等使用。这些厂商标签大多不属于HWL,它们是HW独立的。
componentVendorTagsInfo:这些厂商标签依赖于CHI节点,并在每个CHI组件中相应地定义。
coreVendorTagInfo:在核心层(camxvendortag .cpp)中定义,并由核心层或其他层使用。
接下来详细讲解操作步骤:
在hwVendorTagInfo增加厂商标签信息
//Path: vendor/qcom/proprietary/camx/src/hwl/titan17x/camxtitan17xcontext.cpp
static VendorTagData g_VendorTagSectionDemo[] =
{
{ "demoTag", VendorTagType::Byte, 1 },
};
static VendorTagSectionData g_HwVendorTagSections[] =
{
......
{
"org.quic.camera.DemoSection", 0,
CAMX_ARRAY_SIZE(g_VendorTagSectionDemo), g_VendorTagSectionDemo,
TagSectionVisibility::TagSectionVisibleToAll
},
};在骁龙相机中设置metadata标签
路径:packages/apps/SnapdragonCamera/src/com/android/camera/CaptureModule.java
定义key
public static final CaptureRequest.Key
demoKey =
new CaptureRequest.Key<>("org.quic.camera.DemoSection.demoTag", byte.class);定义默认值
private boolean mDemoKeyValue = true;
private void applyDemoKey(CaptureRequest.Builder request) {
try {
request.set(CaptureModule.demoKey, (byte) (mDemoKeyValue? 0xFF : 0x00));
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
}应用key到每帧请求
private void applyCommonSettings(CaptureRequest.Builder builder, int id) {
……
applyDemoKey(builder);
……
}
获取metadata
camx session
//Path: vendor/qcom/proprietary/camx/src/core/camxsession.cpp
CamxResult Session::ProcessCaptureRequest(
const ChiPipelineRequest* pPipelineRequests)
{
……..
MetadataSlot* pMetadataSlot =
pPerFrameInputPool->GetSlot(m_requestBatchId[pipelinIndex]);
if (pMetadataSlot != NULL) {
UINT32 metaTag = 0;
result = VendorTagManager::QueryVendorTagLocation("org.quic.camera.DemoSection", "demoTag", &metaTag);
if (CamxResultSuccess == result)
{
UINT8* demoData = static_cast(pMetadataSlot->GetMetadataByTag(metaTag));
}
}camx pipeline
//Path: vendor/qcom/proprietary/camx/src/core/camxpipeline.cpp
CamxResult Pipeline::ProcessRequest(
PipelineProcessRequestData* pPipelineRequestData)
{
……
UINT32 metaTag = 0;
result = VendorTagManager::QueryVendorTagLocation("org.quic.camera.DemoSection", "demoTag", &metaTag);
if (CamxResultSuccess == result)
{
UINT8* demoData = static_cast(pInputSlot->GetMetadataByTag(metaTag));
}
……SWL/HWL
//Path: vendor/qcom/proprietary/camx/src/swl/sensor/camxsensornode.cpp
CamxResult SensorNode::ExecuteProcessRequest(
ExecuteProcessRequestData* pExecuteProcessRequestData)
{
……
UINT32 metaTag[1] = { 0 };
UINT8* demoData[1] = { 0 };
UINT length = CAMX_ARRAY_SIZE(metaTag);
UINT64 configDataOffset[1] = { 0 };
result = VendorTagManager::QueryVendorTagLocation("org.quic.camera.DemoSection", "demoTag", &metaTag[0]);
metaTag[0] |= InputMetadataSectionMask;
GetDataList(metaTag, reinterpret_cast(demoData), configDataOffset, length);
……CHI 节点
//Path: vendor/qcom/proprietary/chi-cdk/vendor/node/memcpy/camxchinodememcpy.cpp
CDKResult ChiMemCpyNode::ProcessRequest(
CHINODEPROCESSREQUESTINFO* pProcessRequestInfo)
{
……
CHIVENDORTAGBASEINFO vendorTagBase = {0};
vendorTagBase.size = sizeof(CHIVENDORTAGBASEINFO);
vendorTagBase.pComponentName = "org.quic.camera.DemoSection";
vendorTagBase.pTagName = "demoTag";
g_ChiNodeInterface.pGetVendorTagBase(&vendorTagBase);
UINT8* demoData = static_cast(ChiNodeUtils::GetMetaData(
pProcessRequestInfo->frameNum, vendorTagBase.vendorTagBase
|InputMetadataSectionMask, ChiMetadataDynamic, &g_ChiNodeInterface,
m_hChiSession));
……
CHI节点之间获取metadata
我们在CHI节点之间需要获取metadata,那么如何获取呢,就以获取人脸检测配置为例
找到你需要获取的vendor tag
vendor\qcom\proprietary\chi-cdk\cdk\fd\chifdproperty.h
static const CHAR* VendorTagSectionOEMFDConfig = "org.quic.camera2.oemfdconfig"; ///< OEM FD config vendor tag section
static const CHAR* VendorTagNameOEMFDConfig = "OEMFDConfig"; ///< OEM FD config vendor tag name找到相关的数据结构体
vendor\qcom\proprietary\chi-cdk\cdk\common\chistatspropertydefines.h
/// @brief Structure describing the rectangle coordinates
typedef struct
{
UINT32 left; ///< x coordinate of the ROI
UINT32 top; ///< y coordinate of the ROI
UINT32 width; ///< Width of the ROI
UINT32 height; ///< Height of the ROI
} RectangleCoordinate;
/// @brief Describes Face ROI
typedef struct
{
UINT32 id; ///< Id used to track a face in the scene
UINT32 confidence; ///< Confidence of this face
RectangleCoordinate faceRect; ///< Detected Face rectangle
} FaceROIData;
/// @brief Structure describing Face ROI data
typedef struct
{
UINT64 requestId; ///< Request ID corresponding to this results
UINT32 ROICount; ///< Number of ROIs
FaceROIData unstabilizedROI[MaxFaceROIs]; ///< Unstabilized Face ROI data
FaceROIData stabilizedROI[MaxFaceROIs]; ///< Stabilized Face ROI data
} FaceROIInformation;检查需要读取的供应商标记的依赖。如果尚未发布,则增加依赖项计数。
如果Chi节点的处理依赖于其他标签并且标签尚未发布,则Chi节点可以在pProcessRequestInfo中设置依赖关系并立即返回。 一旦满足依赖关系,框架将再次调用ExecuteProcessRequest。
+ // Check OEMFDResults dependency
+ CHIVENDORTAGBASEINFO vendorTagBase = {0};
+ vendorTagBase.size = sizeof(CHIVENDORTAGBASEINFO);
+ vendorTagBase.pComponentName = VendorTagSectionOEMFDResults;
+ vendorTagBase.pTagName = VendorTagNameOEMFDResults;
+ g_ChiNodeInterface.pGetVendorTagBase(&vendorTagBase);
+
+ tag = vendorTagBase.vendorTagBase;
+
+ pData = ChiNodeUtils::GetMetaData(pProcessRequestInfo->frameNum, tag,
ChiMetadataDynamic,
+ &g_ChiNodeInterface, m_hChiSession);
+ if (NULL == pData)
+ {
+ pDependencyInfo->properties[dependencyCount] = tag;
+ pDependencyInfo->offsets[dependencyCount] = 0;
+ dependencyCount++;
+ }
+
if (dependencyCount > 0)
{
pDependencyInfo->count = dependencyCount;在处理请求的函数中获取厂商标签
+VOID ChiMemCpyNode::GetFDResults(UINT64 requestId)
+{
+ VOID* pData = NULL;
+ UINT32 tag;
+ CHIVENDORTAGBASEINFO vendorTagBase = {0};
+ vendorTagBase.size = sizeof(CHIVENDORTAGBASEINFO);
+ vendorTagBase.pComponentName = VendorTagSectionOEMFDResults;
+ vendorTagBase.pTagName = VendorTagNameOEMFDResults;
+ g_ChiNodeInterface.pGetVendorTagBase(&vendorTagBase);
+
+ tag = vendorTagBase.vendorTagBase;
+
+ pData = ChiNodeUtils::GetMetaData(requestId, tag, ChiMetadataDynamic,
+ &g_ChiNodeInterface, m_hChiSession);
+ if(pData){
+ LOG_ERROR(CamxLogGroupChi, "pData %p tag 0x%x",pData,tag);
+ FaceROIInformation* pFaceROIInfo = (FaceROIInformation *)pData;
+ LOG_ERROR(CamxLogGroupChi, "ROICount %d", pFaceROIInfo->ROICount);
+ for (UINT32 i = 0; i < pFaceROIInfo->ROICount; i++){
+ LOG_ERROR(CamxLogGroupChi,"faceID=%d, confidence=%d, top-left(%d, %d), width=%d, height=%d",
+ pFaceROIInfo->unstabilizedROI[i].id, pFaceROIInfo->unstabilizedROI[i].confidence,
+ pFaceROIInfo->unstabilizedROI[i].faceRect.left, pFaceROIInfo->unstabilizedROI[i].faceRect.top,
+ pFaceROIInfo->unstabilizedROI[i].faceRect.width, pFaceROIInfo->unstabilizedROI[i].faceRect.height);
+ }
+ for (UINT32 i = 0; i < pFaceROIInfo->ROICount; i++){
+ LOG_ERROR(CamxLogGroupChi,"faceID=%d, confidence=%d, top-left(%d, %d), width=%d, height=%d",
+ pFaceROIInfo->stabilizedROI[i].id, pFaceROIInfo->stabilizedROI[i].confidence,
+ pFaceROIInfo->stabilizedROI[i].faceRect.left, pFaceROIInfo->stabilizedROI[i].faceRect.top,
+ pFaceROIInfo->stabilizedROI[i].faceRect.width, pFaceROIInfo->stabilizedROI[i].faceRect.height);
+ }
+ }else{
+ LOG_ERROR(CamxLogGroupChi, "OEMFDResults pData is NULL!");
+ }
+}
+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// ChiMemCpyNode::ProcessRequest
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -550,6 +603,7 @@ CDKResult ChiMemCpyNode::ProcessRequest(
if (TRUE == satisfied)
{
+ GetFDResults(pProcessRequestInfo->frameNum);
for (UINT32 i = 0; i < pProcessRequestInfo->outputNum; i++)
{
// This is memcpy dummy RTB node最后打开人脸检测的打印进行检查
adb root
adb remount
adb shell "echo logVerboseMask=0x100000 >> /vendor/etc/camera/camxoverridesettings.txt"
adb reboot