第三章 CHI架构详解:从CamX到客制化的桥梁

好,咱们今天聊聊CHI。说实话,这个架构刚出来的时候,我也懵了一阵子。毕竟从传统的HAL架构切过来,思维方式得变一变。但搞懂了之后,你会发现它其实挺优雅的。

3.1 CHI的由来:为什么要有它?

先说说背景。高通在骁龙845之前,用的是旧版HAL。那时候各家OEM要改相机逻辑,得直接改CamX的代码。你想想看,这有多痛苦?

  • 耦合太深:OEM的客制化代码和芯片底层代码混在一起
  • 升级困难:高通一升级底层,OEM就得重新适配
  • 维护成本高:每个项目都要重新解bug,重复劳动

所以,CHI(Camera HAL Interface)就诞生了。它的核心思想很简单:把客制化逻辑从CamX中抽离出来。说白了,就是给OEM留了一个“插件接口”,你只需要写自己的override逻辑,不用动底层。

核心概念:CHI不是一个新的HAL,而是CamX之上的一个抽象层。它定义了OEM如何注入自己的配置和行为。

3.2 CHI与CamX的关系:谁是谁的爸爸?

这个问题我经常被问到。其实它们的关系是这样的:

层次 角色 谁在维护
CamX 底层驱动框架,处理硬件交互 高通
CHI 上层配置层,提供客制化接口 高通定义接口,OEM实现
OEM客制化 基于CHI的override配置 OEM自己

嗯,这里要注意:CamX是执行者,CHI是配置者。CamX负责调度硬件、处理buffer、管理pipeline。而CHI负责告诉CamX:“嘿,这个场景下,你要用这个参数。”

我在项目中遇到过一种情况:有个同事想直接在CamX里改曝光参数,被我拦住了。我说:“兄弟,你改CHI的override文件就行,别动底层。” 后来他试了试,果然简单多了。

3.3 CHI Override机制:客制化的灵魂

好,重点来了。CHI Override机制,说白了就是一套配置覆盖系统。它允许OEM在不修改CamX源码的情况下,改变相机的行为。

3.4.1 Override的三种方式

根据我的经验,Override主要有三种方式:

  1. XML配置覆盖:最常用,改配置文件就行
  2. Usecase覆盖:针对特定场景(如夜景、人像)
  3. Sensor覆盖:针对特定sensor的调优

举个例子,你想修改夜景模式的曝光时间。传统做法是改CamX的算法代码。但在CHI架构下,你只需要这样:

// 在override XML中配置
<Usecase name="NightMode">
    <SensorConfig>
        <ExposureTime>200000000</ExposureTime>  // 200ms
        <Gain>4.0</Gain>
    </SensorConfig>
</Usecase>

你看,就这么简单。不需要动一行C++代码。

我的习惯:每次做新项目,我会先建一个override目录,把所有客制化配置放进去。这样升级CamX时,只需要重新编译override部分,省时省力。

3.4.2 Override的加载顺序

这里有个坑,我踩过。Override是有优先级的:

  • 最高优先级:运行时动态override(通过属性设置)
  • 中等优先级:Usecase级别的override
  • 最低优先级:全局默认配置

我曾经遇到过一个bug:明明改了XML,但效果没出来。查了半天,发现是运行时有个属性把配置覆盖了。嗯,从那以后,我每次调试都会先检查属性值。

3.5 实战:如何实现一个简单的Override

咱们来点实际的。假设你要客制化一个“美颜模式”,让它在特定sensor上生效。

第一步,创建override文件:

// vendor/qcom/proprietary/chi-cdk/override/beauty_mode.xml
<?xml version="1.0" encoding="utf-8"?>
<CameraSettings>
    <Usecase name="BeautyMode">
        <SensorName>imx586</SensorName>
        <Pipeline>
            <Node name="beauty_node">
                <Parameter name="strength">0.8</Parameter>
            </Node>
        </Pipeline>
    </Usecase>
</CameraSettings>

第二步,在CHI配置中注册这个usecase:

// chi-cdk/core/default/chiusecase.cpp
static ChiUsecase g_beautyUsecase = {
    .pUsecaseName = "BeautyMode",
    .pOverrideXml = "beauty_mode.xml",
    .sensorId = SENSOR_IMX586
};

第三步,编译并验证。我个人习惯用adb push到设备上测试:

adb push beauty_mode.xml /vendor/etc/camera/
adb shell setprop persist.camera.override.beauty 1
adb reboot

注意:Override文件的名字和路径必须和CHI配置中一致。我曾经因为文件名大小写问题,浪费了半天时间。记住,Linux是区分大小写的。

3.6 避坑指南:我踩过的那些坑

最后,分享几个实战经验:

  • XML格式一定要严格:多一个空格都可能解析失败。我建议用xmllint验证一下。
  • 不要覆盖所有配置:只覆盖你需要改的部分。其他保持默认,这样升级时兼容性更好。
  • 调试时加日志:在override代码里加CHI_LOG,能帮你快速定位问题。
  • 注意版本兼容:不同版本的CHI,override的语法可能有差异。升级前先看release notes。

我曾经接手过一个项目,前任工程师把整个CHI配置都改了一遍。结果高通一升级,全废了。后来我花了三周才把配置重新整理好。所以,尽量少改,改精不改多

好了,CHI架构的核心内容就这些。下一章咱们聊聊具体的pipeline配置,到时候会用到今天讲的override知识。有什么问题,欢迎随时交流。