尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

高通CamX Chi-CDK源码开发指南:掌控相机HAL层的底层控制台

高通CamX Chi-CDK源码开发指南:掌控相机HAL层的底层控制台 简介本资源为高通Camera Camx架构chi-cdk仓库全套开源源码面向Android相机驱动开发、图像处理算法工程师及嵌入式视觉系统开发者旨在支撑基于高通平台的高性能相机功能定制与底层优化。资源共2000个文件以1604个XML配置文件定义Camx节点拓扑与pipeline流程、331个TXT文档含接口说明与构建指南、38个H头文件如chiaecinterface.h、chiawbinterface.h等核心模块接口定义为主辅以Python脚本自动化构建与测试、YAML配置及Markdown说明整体压缩包仅5.38MB轻量但结构完整。已有656人学习下载适合深入理解Camx架构设计思想、调试Chi节点交互逻辑、复现ISP/3A算法集成路径的中高级开发者。源码覆盖从图像捕获、统计分析chistatsinterfacedefs.h、自动对焦chiafcommon.h到ISP参数配置chiispstatsdefs.h的全链路模块是研究高通影像技术栈不可多得的一手工程参考。1. 高通Camera Camx架构chi-cdk仓库全套源码不是“下载即用”的SDK包而是你掌控相机HAL层的底层控制台如果你在高通平台比如骁龙8 Gen2/Gen3、QCM6490、SM8550等上做过相机驱动开发、ISP tuning、自定义metadata注入或者被Camx日志里满屏的CHI_NODE,PIPELINE,SessionManager绕晕过——那你迟早会撞上chi-cdk这个目录。它不是官方文档里轻描淡写的“可选工具包”而是高通Camera HAL层真正可编译、可调试、可patch的源码级开发套件。它把原本黑盒化的CamX-CDACamera Daemon Architecture拆解成C模块、XML配置、JSON pipeline描述、以及可hook的Chi节点接口。你用它才能绕过vendor blob限制在hal3层做真正的定制比如把自定义AI模型输出的depth map塞进android.depth域让上层App直接读或者把多摄同步触发逻辑从firmware下移到Chi pipeline里重写。这不是给App开发者看的API文档而是给能编译kernel、刷bootimage、抓logcat -b camera、看/sys/kernel/debug/camss节点的固件工程师准备的作战地图。新手别硬啃但如果你正卡在“为什么setParameters不生效”“为什么CaptureRequest被丢弃”“为什么VendorTag写进去却读不到”那chi-cdk就是你该打开的第一扇门。2. chi-cdk到底是什么从高通Camera HAL分层模型讲清它的定位与不可替代性2.1 高通Camera HAL的三层真相Vendor Blob不是终点chi-cdk才是入口高通Camera HAL不是Android标准HAL的简单实现而是一个三明治结构最底层CamX-CDACamera Daemon Architecture由高通闭源binary提供负责硬件调度、时序控制、中断处理中间层ChiCamera Hardware Interface是chi-cdk暴露的可编译C框架它定义了ChiNode,ChiPipeline,ChiSession等核心抽象并通过chi_override.xml和chi_override.json允许你替换/插入节点最上层CamX HAL即libcamx.so它调用Chi接口再封装成Android HAL3标准接口ICameraDevice,ICameraProvider。关键点在于libcamx.so本身是vendor blob但chi-cdk提供了它的构建依赖、头文件、示例pipeline和override机制。没有chi-cdk你连ChiNode::ProcessRequest()的函数签名都看不到有了它你才能在chi_override.xml里声明一个自定义MyAISNode并在chi_override.json中把它插入到PreviewPipeline的PostProc阶段——这才是高通AISAI Scene功能可二次开发的物理基础。网络热词里常提的“高通ais”其底层正是运行在Chi节点上的独立AI inference模块而chi-cdk就是你把它替换成自己模型的唯一合法通道。2.2 chi-cdk仓库结构解析6个核心目录决定你能改什么、不能改什么chi-cdk不是单个zip包而是一个完整构建树。以高通公开发布的chi-cdk-4.10适配Snapdragon Camera Framework v4.10为例关键目录如下目录作用是否可修改典型用途chi/Chi核心框架ChiNode.h,ChiPipeline.h,ChiSession.h等头文件与stub实现❌ vendor受控仅头文件开放查接口定义、继承ChiNode写新节点chx/CamX HAL wrapperChxSession.cpp,ChxCaptureRequest.cpp等✅ 可修改需重新编译libcamx.so修改request分发逻辑、metadata注入点common/公共工具CamXUtils.h,CamXTrace.h,CamXMutex.h✅ 可修改加日志、改锁策略、注入调试信息nodes/官方Chi节点实现AECNode.cpp,AWBNode.cpp,HDRNode.cpp⚠️ 部分可patch如AECNode的ProcessRequest调整曝光算法参数、hook ISP寄存器读写overrides/override入口chi_override.xml,chi_override.json,chi_override.cpp✅ 必改声明自定义节点、重排pipeline、绑定vendor tagsamples/示例工程sample_aec_node,sample_metadata_node✅ 可复用快速验证自定义节点是否加载成功提示chi-cdk本身不包含libcamx.so源码它只提供构建libcamx.so所需的头文件、链接库libchi.so,libchx.so和构建脚本。你必须配合高通提供的camxbinary blob通常随BSP包下发一起编译。这意味着你无法修改CamXDaemon主循环但可以完全控制Chi层所有节点的输入/输出行为。2.3 为什么必须用chi-cdk对比传统HAL开发的三个致命短板传统HAL patch方式直接改libcamera_device.so只能动Android HAL层无法干预CaptureRequest到ISP hardware之间的pipeline调度对multi-frame sync,burst capture latency,vendor metadata传递无能为力仅用camxbinary vendorconfig你只能调参如aec_config.xml无法添加新节点、无法拦截ProcessRequest、无法在ChiSession::CreatePipeline()阶段动态构造pipelinechi-cdk的不可替代性它让你在不触碰vendor blob的前提下获得Chi层的完全控制权。例如你想在PreviewPipeline末尾插入一个CustomLUTNode把YUV转成带风格化色调的YUV只需在nodes/下新建custom_lut_node.cpp继承ChiNode在overrides/chi_override.xml中声明该node在overrides/chi_override.json中指定它插入位置编译libcamx.so并刷入target。整个过程无需高通授权且不影响其他pipeline如VideoPipeline。3. 搭建chi-cdk编译环境从Linux主机到刷机验证的7步闭环3.1 硬件与软件前提不是所有Linux都能跑通chi-cdkchi-cdk对构建环境有硬性要求OSUbuntu 20.04 LTS官方唯一支持Ubuntu 22.04已知glibc版本冲突导致libcamx.sodlopen失败GCC必须使用gcc-9sudo apt install gcc-9 g-9gcc-11会导致std::shared_ptrABI不兼容NDKAndroid NDK r21endk-bundle-r21e-linux-x86_64.zip更高版本因c_shared库路径变更报undefined reference to __cxa_guard_acquirePythonPython 3.8python3.8-devpython3.10会因distutils.sysconfig移除导致build.sh失败目标平台BSP必须配套高通CamXbinary blob通常为camx-version.tar.gz含libcamx.so,libchi.so,libchx.so及include/头文件。注意chi-cdk不支持Windows WSL或Docker容器编译。build.sh脚本内嵌大量/proc/sys/kernel/shmmax、/dev/kmsg等Linux kernel特性检查WSL2的/dev挂载不全会导致camxdaemon启动失败。必须用物理机或VMware虚拟机启用3D Acceleration和Large Pages。3.2 下载与解压chi-cdk避开高通官网的三个隐藏陷阱高通官网需要NDA账号下载的chi-cdk-ver.tar.gz存在三个常见陷阱陷阱1版本错配——chi-cdk-4.10必须搭配camx-4.10blob若混用camx-4.9编译通过但运行时报ChiNode::Initialize() failed: Invalid version陷阱2缺失overrides/模板—— 官方包有时漏掉chi_override.xml.example需从samples/复制sample_override.xml重命名陷阱3build.sh权限丢失—— 解压后chmod x build.sh否则报/bin/bash^M: bad interpreterWindows换行符残留。正确解压命令tar -xzf chi-cdk-4.10.tar.gz cd chi-cdk-4.10 chmod x build.sh # 检查BSP blob是否就位 ls -l camx-blob/libcamx.so camx-blob/include/chi/ # 必须存在3.3 执行编译build.sh背后的5个关键参数与它们的真实含义chi-cdk的build.sh不是一键式脚本它通过环境变量控制构建行为。以下是生产环境必设的5个参数环境变量示例值作用不设后果CAMX_BLOB_PATH/home/user/camx-blob指向BSP blob根目录编译失败fatal error: chi/chi.h: No such file or directoryANDROID_NDK_ROOT/home/user/android-ndk-r21eNDK路径clang: command not foundTARGET_ARCHarm64目标CPU架构arm64/arm生成libcamx.so无法在target上dlopenBUILD_TYPEuserdebug构建类型user/userdebug/enguser版禁用adb shell setprop debug.camx.log 3无法抓Chi日志ENABLE_DEBUG_LOGtrue启用CAMX_LOG_DBG级别日志默认只输出CAMX_LOG_WARN无法定位ProcessRequest卡点执行编译命令建议加-j$(nproc)加速export CAMX_BLOB_PATH/home/user/camx-blob export ANDROID_NDK_ROOT/home/user/android-ndk-r21e export TARGET_ARCHarm64 export BUILD_TYPEuserdebug export ENABLE_DEBUG_LOGtrue ./build.sh -j$(nproc)编译成功后产物位于out/target/product/platform/libcamx.so重编译后的HAL库libchi.so,libchx.soChi框架库camxoverrides.sooverride节点动态库3.4 刷机与验证如何确认chi-cdk真的生效了编译只是第一步刷机后必须验证override是否加载Push文件到target假设target为/system/vendor/lib64/adb root adb remount adb push out/target/product/platform/libcamx.so /system/vendor/lib64/ adb push out/target/product/platform/camxoverrides.so /system/vendor/lib64/ adb reboot抓取CamX日志确认override加载adb logcat -b camera | grep -i override\|chi_node # 正常应看到 # [CHI] ChiOverrideManager::LoadOverrides: Loaded 3 override nodes # [CHI] ChiNodeFactory::CreateNode: Created node CustomLUTNode (ID: 0x1234)验证自定义节点是否参与pipelineadb shell setprop debug.camx.log 3 # 开启Chi debug日志 adb shell am start -a android.intent.action.MAIN -n com.android.camera2/com.android.camera.CameraLauncher adb logcat -b camera | grep -A5 -B5 CustomLUTNode # 应看到类似 # [CHI] CustomLUTNode::ProcessRequest: Input buffer fd123, formatNV12 # [CHI] CustomLUTNode::ProcessRequest: LUT applied, output buffer fd124若无此日志说明chi_override.xml未被CamXDaemon读取需检查/vendor/etc/camera/chi_override.xml路径及权限chmod 644。4. chi-cdk核心开发实战从零写一个Vendor Metadata注入节点4.1 Vendor Tag注册在chi-cdk中定义你的私有metadata字段Android HAL3的VendorTag是跨层传递自定义数据的唯一标准方式。chi-cdk要求你在overrides/下创建vendor_tag_descriptor.xml?xml version1.0 encodingutf-8? vendor_tag_descriptor version2.0 tag_group namecom.mycompany.camera tag nameai_score typefloat descriptionAI confidence score (0.0~1.0)/ tag nameface_rect typeint32 count4 descriptionFace bounding box [x,y,w,h]/ /tag_group /vendor_tag_descriptor然后在chx/ChxSession.cpp的Initialize()函数中注册关键代码// chx/ChxSession.cpp #include vendor_tag_descriptor.h // 自定义头文件由xml生成 ... CamxResult ChxSession::Initialize() { // ...原有初始化代码 // 注册Vendor Tag Descriptor VendorTagDescriptor* pVendorTagDescriptor VendorTagDescriptor::GetInstance(); if (NULL ! pVendorTagDescriptor) { pVendorTagDescriptor-RegisterVendorTagDescriptor( g_VendorTagDescriptor); // g_VendorTagDescriptor由xml生成的全局变量 } return CamxResultSuccess; }参数说明typefloat对应HAL3的TYPE_FLOATcount4表示数组长度description会被dumpsys media.camera显示。注册后上层App可通过CaptureRequest.Builder.setEntry()写入CaptureResult中读取。4.2 创建CustomMetadataNode继承ChiNode并拦截CaptureRequest在nodes/下新建custom_metadata_node.cpp#include chi_custom_metadata_node.h #include chihal.h #include camx.h CustomMetadataNode::CustomMetadataNode() : ChiNode() {} CustomMetadataNode::~CustomMetadataNode() {} CamxResult CustomMetadataNode::Initialize(ChiNodeCreateInput* pCreateInput) { CAMX_LOG_INFO(CAMX_LOG_MODULE_CHI, CustomMetadataNode::Initialize); return CamxResultSuccess; } CamxResult CustomMetadataNode::ProcessRequest(ChiRequest* pChiRequest) { // 获取CaptureRequest中的VendorTag CHINodeRequest* pNodeRequest static_castCHINodeRequest*(pChiRequest); if (NULL pNodeRequest-pCaptureRequest) { return CamxResultEFailed; } // 写入AI Score此处模拟AI结果 float aiScore 0.87f; pNodeRequest-pCaptureRequest-SetFloatEntry( g_vendorTagDescriptor.ai_score, aiScore, 1); // 写入Face Rect模拟检测结果 INT32 faceRect[4] {120, 80, 200, 250}; pNodeRequest-pCaptureRequest-SetInt32Entry( g_vendorTagDescriptor.face_rect, faceRect, 4); CAMX_LOG_INFO(CAMX_LOG_MODULE_CHI, CustomMetadataNode::ProcessRequest: AI Score%.2f, Face[%d,%d,%d,%d], aiScore, faceRect[0], faceRect[1], faceRect[2], faceRect[3]); return CamxResultSuccess; }关键点pNodeRequest-pCaptureRequest是CamX::CaptureRequest对象SetFloatEntry/SetInt32Entry是HAL3标准接口确保上层可读。4.3 在override中声明并插入节点chi_override.xml与chi_override.json联动overrides/chi_override.xml?xml version1.0 encodingutf-8? chi_override node nameCustomMetadataNode librarylibcamxoverrides.so classCustomMetadataNode/ /chi_overrideoverrides/chi_override.json插入到PreviewPipeline的PostProc后{ pipelines: [ { name: PreviewPipeline, nodes: [ { name: CustomMetadataNode, position: after, reference: PostProcNode } ] } ] }逻辑说明position: after表示插入到PostProcNode之后这是preview流最后的图像处理节点此时CaptureResult尚未提交是注入metadata的最佳时机。library指向编译出的camxoverrides.soclass是节点类名。4.4 上层App验证用Camera2 API读取VendorTag在App中// Java端读取VendorTag CaptureResult result ...; // 从CaptureCallback.onCaptureCompleted获取 Float aiScore result.get(g_vendorTagDescriptor.ai_score); // 返回0.87f int[] faceRect result.get(g_vendorTagDescriptor.face_rect); // 返回[120,80,200,250] Log.d(CAMERA, AI Score: aiScore , Face: Arrays.toString(faceRect));若能正确打印证明chi-cdk的VendorTag注入链路App → HAL → Chi Node → ISP → App已全线贯通。5. chi-cdk避坑指南5个血泪经验总结每个都曾让我重启三次设备5.1 现象CamXDaemon启动失败logcat报dlopen failed: library libcamx.so not found原因libcamx.so依赖libchi.so和libchx.so但/vendor/lib64/下只有libcamx.so缺少另外两个库。解决adb push时必须三者一起pushadb push out/target/product/platform/libcamx.so /system/vendor/lib64/ adb push out/target/product/platform/libchi.so /system/vendor/lib64/ adb push out/target/product/platform/libchx.so /system/vendor/lib64/玄学提示libchi.so和libchx.so必须与libcamx.so同版本混用会导致undefined symbol: ChiNode::Initialize。5.2 现象chi_override.xml被忽略logcat无Loaded override nodes日志原因高通CamXDaemon只读取/vendor/etc/camera/chi_override.xml且要求文件权限为644owner为root:root。解决adb shell mkdir -p /vendor/etc/camera adb push overrides/chi_override.xml /vendor/etc/camera/ adb shell chmod 644 /vendor/etc/camera/chi_override.xml adb shell chown root:root /vendor/etc/camera/chi_override.xml翻车现场曾因adb push后ls -l看到-rw-rw-rw-666CamXDaemon拒绝加载必须644。5.3 现象自定义节点ProcessRequest被调用但SetFloatEntry无效App读到null原因VendorTag未在CaptureRequest.Builder中显式setEntry()HAL层不会自动创建该entry。解决App端必须先写再读// App必须主动设置否则HAL层无该entry CaptureRequest.Builder builder mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); builder.setEntry(g_vendorTagDescriptor.ai_score, new Float[]{0.0f}); // 初始化占位后悔药chi-cdk不提供default value机制所有VendorTag必须由App显式初始化。5.4 现象libcamx.so编译成功但target上dlopen报undefined symbol: __cxa_guard_acquire原因NDK版本过高r23c_shared库ABI变更与chi-cdk的gcc-9不兼容。解决严格使用android-ndk-r21e并在build.sh开头强制指定export NDK_HOME/home/user/android-ndk-r21e export PATH$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin:$PATH黑匣子__cxa_guard_acquire是C11静态局部变量初始化的符号r21e用gcc-9生成r23用clang-12生成二者不兼容。5.5 现象CustomMetadataNode被加载但ProcessRequest从未被调用原因节点未被正确插入pipeline或插入位置无数据流经过如插在RawDumpNode后但当前场景未启用Raw Dump。解决adb logcat -b camera | grep Pipeline.*Preview确认PreviewPipeline实际加载的节点列表检查chi_override.json中name是否与chi_override.xml中name完全一致大小写敏感在CustomMetadataNode::Initialize()中加CAMX_LOG_INFO确认节点实例化成功若仍不调用尝试将position改为before或first排除pipeline拓扑问题。6. 进阶技巧用chi-cdk做ISP寄存器实时dump与AI模型热替换6.1 实时dump ISP寄存器在Chi节点中调用CamX::HAL::WriteReg32chi-cdk虽不开放ISP driver源码但提供了CamX::HAL::WriteReg32/ReadReg32接口需在chx/中启用CAMX_HAL_ENABLE_REG_ACCESS宏。在CustomMetadataNode::ProcessRequest()中// 读取AE状态寄存器假设地址0x1234 UINT32 aeStatus 0; CamX::HAL::ReadReg32(0x1234, aeStatus); CAMX_LOG_INFO(CAMX_LOG_MODULE_CHI, AE Status Reg0x%x, aeStatus); // 写入自定义LUT表假设LUT基址0x5678 UINT32 lutData[256]; for (int i 0; i 256; i) { lutData[i] i * 2; // 线性映射 } CamX::HAL::WriteReg32Array(0x5678, lutData, 256);边界说明ReadReg32/WriteReg32只能访问CamX HAL白名单内的寄存器范围见camx-hal.h越界会返回CamxResultEAccessDenied。实际可用寄存器需参考高通ISP Register Map文档BSP包内。6.2 AI模型热替换用dlopen加载.so模型避免重编译libcamx.so将AI模型封装为独立libai_model.so导出C接口// ai_model.h extern C { void* ai_init(const char* modelPath); float ai_infer(void* ctx, UINT8* input, int width, int height); void ai_deinit(void* ctx); }在CustomMetadataNode中动态加载#include dlfcn.h ... CamxResult CustomMetadataNode::ProcessRequest(ChiRequest* pChiRequest) { static void* s_pAIHandle NULL; static void* s_pAIContext NULL; if (NULL s_pAIHandle) { s_pAIHandle dlopen(/vendor/lib64/libai_model.so, RTLD_NOW); if (NULL s_pAIHandle) { CAMX_LOG_ERROR(CAMX_LOG_MODULE_CHI, dlopen libai_model.so failed); return CamxResultEFailed; } typedef void* (*AIInitFunc)(const char*); AIInitFunc ai_init (AIInitFunc)dlsym(s_pAIHandle, ai_init); s_pAIContext ai_init(/vendor/etc/camera/model.bin); } // 调用AI推理 float score ai_infer(s_pAIContext, pInputBuffer, width, height); ... }技巧价值模型更新只需adb push libai_model.soadb shell killall CamXDaemon无需重刷整个libcamx.so大幅缩短AI tuning迭代周期。我团队用此法将AIS模型迭代从2小时压缩到3分钟。6.3 性能监控用CamXTrace打点统计节点耗时chi-cdk内置CamXTrace可在任意节点加耗时统计CamXResult CustomMetadataNode::ProcessRequest(ChiRequest* pChiRequest) { CAMX_TRACE_SYNC_BEGIN(CAMX_TRACE_LEVEL_HIGH, CustomMetadataNode::ProcessRequest); // ... your code ... CAMX_TRACE_SYNC_END(CAMX_TRACE_LEVEL_HIGH, CustomMetadataNode::ProcessRequest); // 或更细粒度 CAMX_TRACE_ASYNC_BEGIN(CAMX_TRACE_LEVEL_HIGH, AI_Inference); float score ai_infer(...); CAMX_TRACE_ASYNC_END(CAMX_TRACE_LEVEL_HIGH, AI_Inference); return CamxResultSuccess; }然后用adb shell setprop debug.camx.trace 1开启traceadb shell atrace --async_start camera抓取systrace.py生成HTML报告。你会看到CustomMetadataNode::ProcessRequest在timeline上的精确耗时轻松定位AI推理是否成为瓶颈。我做高通相机开发这七年chi-cdk是唯一一个让我敢说“改完代码烧进去五分钟后就知道对不对”的工具链。它不承诺易用但绝对诚实——每一个编译错误、每一次dlopen失败、每一行CamXTrace日志都在告诉你硬件真实的边界在哪里。与其花时间猜vendor blob怎么工作不如把chi-cdk当成你的硬件探针一层层捅开CamX的黑盒。希望帮到你。本文还有配套的精品资源点击获取
返回列表