夜雨聆风学习资料网

ARTICLE · 959835

车载Camera·软件栈·第5篇 | 高通相机两条路:Camera2/CamX-CHI 与 QCarCam/AIS

车载Camera·软件栈·第5篇 | 高通相机两条路:Camera2/CamX-CHI 与 QCarCam/AIS

导读:你在车机上用 Camera2 打开一路相机——背后就是高通的 CamX-CHI 吗?在车载上,**答案是"不一定"**。手机相机只有一条路,车载有两条:座舱应用相机走 Camera2 → CamX-CHI,而倒车 / 环视 / DMS 这些车规相机走的是另一套 QCarCam / AIS。这一篇讲透 A 线的 HAL 实现 CamX-CHI(CHI 出图纸、core 造流水线),并把两条路的边界、以及"走 Camera2 ≠ 走 CamX-CHI"这个最容易搞错的点讲清——它也是整个系列的枢纽。


阅读前提

  • 系列内:承接第4篇《CameraService 深入》——第4篇讲到 CameraService 把请求交给 Camera Provider、再往下就是"厂商各自的 HAL 实现"便停住了。本篇从这条 HAL 边界往下走,看高通怎么实现(CamX-CHI);同时,它是整个系列的枢纽——把前面几篇讲的"Android 相机栈"放回车载的正确位置,并引出车载真正的另一条路。
  • 系列外:需要一点 HAL(硬件抽象层)、Camera2(Android 应用侧相机 API)、GMSL(车载长距离串行相机接口)、以及"进程内动态库 .so"的概念——不熟悉时按字面理解即可。

开篇:一个容易搞错的定位问题

你在车机上用 Android 的 Camera2 API 打开一路相机——它背后就是高通的 CamX-CHI 吗?

多数人会答"是"。但在车载上,**答案是"不一定"**。这个"不一定",正是本系列前几篇一直没讲清、而车载行业的人一眼就会质疑的地方。要讲清它,得先承认一件事:

手机相机只有一条路,车载相机有两条。


一、全局:高通平台上,相机有两条路

先看全局。在高通车载平台上,一路相机画面到达应用,可能走两条完全不同的软件栈:

路径 A —— Android 相机栈(座舱应用相机)

Android 应用(Camera2 / CameraX)
   → CameraService(第4篇)
   → Camera Provider(AIDL)
   → 厂商 HAL = CamX-CHI   ← 本篇主体
   → 内核驱动 → Spectra ISP

这就是手机上的那一套,AAOS(车载版 Android)沿用并做了车载扩展。它面向座舱里"像手机一样"的相机应用——视频通话、乘客自拍、拍照录像、扫码。

路径 B —— 车载专用相机栈(安全 / 环视 / 监测相机)

应用 / 中间件(QCarCam API 或 EVS)
   → AIS(Automotive Imaging System:ais_server + ais_client)
   → 内核驱动 → ISP

这是高通(QCarCam/AIS)和 Google(EVS)专门为"车"做的一套,独立于 Android 应用框架。它服务的是 RVC 倒车、AVM 环视、DMS 驾驶员监测、OMS 乘员监测、ADAS 感知——这些安全、早启动、多路常开的车载核心相机。

车载多出 B 这条路的原因

Android 这套(A)无法满足车载相机的几个硬性需求,于是有了 B:

  • 早启动:法规要求挂挡后极短时间内出倒车影像(AAOS 官方目标是开机 2 秒内),而车机从上电到 Android 完整框架起来、相机可用,动辄十几秒甚至更久,远够不上 2 秒——A 这条路来不及。B 必须能独立于、早于 Android 出图。
  • 功能安全:倒车、ADAS 是安全件,不能只依赖"可能崩溃重启"的 Android 应用栈。
  • 跨 OS / 双域:车载常是 QNX(安全域)+ Android(座舱) 双系统跑在 Hypervisor 上,安全相机要能跨域,不能受限于 Android。
  • GMSL 长线束、多路常开:车上摄像头分布全车、经 GMSL 串行解串长线束接入、多路同时开——需要专门的采集与资源仲裁框架(ais_server)。

关键纠偏:走 Camera2 ≠ 走 CamX-CHI

这是车载开发者最容易混淆的一处,也是本系列前几篇欠读者的一句话:

Camera2 只是 Android 应用能用的"标准 API 表面"。 在车载上,一个 app 调 Camera2,它背后可能是:

  • 真 CamX-CHI——当相机是"手机式" MIPI 直连时;
  • 一层"把 AIS 相机桥接成 Camera2"的 HAL 垫片——GMSL 相机的常见做法,app 用着 Camera2,后端其实是 AIS,不是 CamX-CHI。

所以判断一颗车载相机走哪条,**最准的维度不是"app 用了什么 API",而是"相机怎么接进来、要满足什么需求"**:

  • 要早启动 / 功能安全 / GMSL 多路 → B(QCarCam/AIS/EVS)
  • 座舱里像手机一样的应用相机 / MIPI 直连 → A(Camera2/CamX-CHI)

手机相机只有 A 这一条;车载 A、B 都有。本篇讲透 A 这条的 HAL 实现——CamX-CHI(也就是第4篇停下的那个"厂商 HAL");B 这条(QCarCam/AIS/EVS)是车载真正的主路径,留给后面几篇。

关于深度与依据:CamX-CHI 的核心(camera.qcom.so / com.qti.chi.override.so)是闭源的,高通以预编译库交付,源码级实现拿不到。本篇讲它的架构与设计——依据高通公开文档、一份高通专利(US10613870B2)与 AOSP,落到接口/组件/数据流这一级;不涉及函数实现,也不碰任何厂商私有的 sensor 连法、tuning、自研节点。B 路径的结论则区分了官方/二手来源,链接见文末。


二、CamX-CHI 是什么:Google 定接口,高通做实现

顺着路径 A 往下走,过了 Camera Provider 这道 HAL 边界,就进了 CamX-CHI。先厘清一个常被搞错的定位——也回答"CamX-CHI 是不是 Google 的相机框架":不是。HAL 边界上的接口是 Google 定的,实现是各家厂商自己做的。

  • Google 定义 Camera HAL3 接口(camera3_device_ops:configure_streams、process_capture_request、process_capture_result 等)——一份规范,规定 framework 怎么调 HAL、传什么、回什么,但不管 HAL 内部怎么实现。
  • 高通对这个接口的实现,就是 CamX-CHI。换个 SoC 厂商是另一套:联发科有 MTK 的实现,三星 Exynos 有自己的——它们都插在同一个 HAL3 插槽上。

一个反常识的细节:在高通平台上查看 cameraserver 加载的库,会发现相机 HAL 不是一个 .so,而是两个:camera.qcom.so(CamX core)与 com.qti.chi.override.so(CHI override)。而且 OEM 做相机定制时,往往只替换后面那个,前面那个原封不动。为什么拆两个、为什么只换一个——这正是下一节要讲的核心。先看 CamX-CHI 在路径 A 里的内部构成:

一个常见误解:Android 13 起 Camera HAL 接口 AIDL 化,容易让人以为"高通换了新 HAL 架构、CamX 被取代了"。其实 AIDL 化只发生在 Camera Provider 那一层(framework ↔ provider 的 IPC 由 HIDL 换成 AIDL);Provider 之下,高通实现的仍是传统 HAL3 device 接口,仍是 CamX-CHI。变的是外面那层 IPC 形态,没变的是里面这套实现。

CamX-CHI 是高通对 Google Camera HAL3 的实现,分 camera.qcom.so(CamX core)和 com.qti.chi.override.so(CHI override)两个库。它是路径 A 的最后一层。


三、CHI 与 core:设计与实现的切分

CamX-CHI 内部这两层,是理解它的钥匙。分工可以一句话概括:CHI 负责"设计",core 负责"实现"。

  • CHI override(策略层,com.qti.chi.override.so):决定这次用哪套 usecase、这条流水线由哪些处理单元(node)组成、怎么连(topology)——出图纸。
  • CamX core(执行层,camera.qcom.so):提供 node/pipeline 的真实代码和执行引擎,按图纸把流水线构建起来、驱动运行、经驱动下到硬件——照图纸落地执行。

三方角色:Google、高通、OEM

这里有个极易混淆的点:CHI 和 core 都是高通写的,不是谁的定制。这套东西涉及三方:

谁
做了什么
类比一台机器
Google
定 HAL3 接口标准 camera3_device_ops
定"插座标准"
高通(SoC 厂商)
写了 CamX core + CHI 整套(含默认实现)
造整台机器:core = 马达+标准零件库+装配线;CHI = 可编程控制器(还预置了 ZSL/HDR/MFNR 等高通自己的程序)
OEM(车厂/手机厂)
在 CHI 上加自己的 usecase / topology / Feature / vendor tag
给控制器写自己的程序、换个面板——但不改动机器的马达和装配线

所以 core 和 CHI 都是高通交付的 HAL 实现;它俩的真正区别**不是"谁写的",而是"能不能被 OEM 覆写"**:

谁写
能否被 OEM 覆写
负责
CamX core
高通
否
(稳定基座)
Node/Pipeline 的实现 + 执行
CHI override
高通(默认)+ OEM(定制)
是
(专门留的覆写口子)
决定用哪套 usecase / topology

"OEM 定制只换 com.qti.chi.override.so、不动 camera.qcom.so"——就是这个意思:改可覆写的 CHI,不动稳定的 core。

这么切分带来的三个好处

Google 的 HAL3 接口是"隐式"的:应用提交一个请求,至于 HAL 内部把它拆成几条流、走哪个 ISP 引擎、要不要多帧合成——全由厂商在内部黑盒决定。高通做的事,是把这块黑盒里"怎么组 pipeline、选哪个引擎、多帧怎么控"的决策,从 core 里抽出来、显式化成一个可覆写的 CHI 层。高通官方对 CHI 的定位原文正是:CHI override 模块"supplements the Google HAL3 interface",提供"explicit image processing pipeline generation, explicit engine selection, and multiframe control"。

这么切分,带来三个实际的好处:

  1. 一套 core 适配所有芯片和客户:不同 OEM、不同产品要的成像效果千差万别,但底层的 node 执行引擎、调度、buffer 管理是通用的。core 稳定不动,差异全下沉到 CHI——高通不用为每个客户改 core。
  2. OEM 不改动底层引擎就能定制:车厂想加一套自己的成像 usecase、调 topology,只需改 CHI override 或它读的 XML,无需改动、也无法改动闭源的 core。风险小、维护清晰。
  3. core 能独立升级:高通升级 core(修 bug、加能力),不会影响 OEM 在 CHI 层的定制;反过来 OEM 换 CHI,也不动 core。两层解耦,各自演进。

工程上,这两层用"两个 .so 双向 dlopen + 操作跳转表"对接:HAL3 初始化时 core 调 chi_hal_override_entry(),CHI 把自己的函数接口指针交回给 core(官方原文"return function interface pointers");core 也把自身能力(造 node、建 pipeline 的接口)通过跳转表交给 CHI。换掉 override 那个 .so,就换掉整套策略,而 core 二进制不动。

那么"CHI 出图纸、core 造流水线"具体怎么发生?看这张创建流程:

CHI 出图纸(选 usecase、定 topology),core 按图纸用自己的零件把流水线构建、运行起来。core 稳定通用、CHI 可被 OEM 覆写——这道切分,就是 CamX-CHI 整个架构的核心设计。


四、一个请求的路径:从 Camera2 到硬件出帧

把路径 A 的一个具体场景走一遍:座舱里一个 Android 相机应用(比如车内视频通话)打开预览。看你写的每行 Camera2,对应 HAL 里发生了什么——用你熟悉的 Camera2 当锚点,最容易看懂 CamX-CHI。

先给对照表(app 侧是 Google 公开的 Camera2 API,HAL3 回调是 Google 定义,CHI 入口名来自高通官方时序图):

app 侧(你写的 Camera2)
HAL3 回调(Google 定义)
CamX-CHI 内部发生什么
CameraManager.openCamerainitialize
加载 camera.qcom.so,core 调 chi_hal_override_entry 与 CHI 握手
createCaptureRequest(TEMPLATE_PREVIEW)construct_default_request_settings
按 template 返回一份默认参数
createCaptureSession
(给预览 Surface)
configure_streamscore 请 CHI 选 usecase、建 pipeline/topology
(chi_initialize_override_session)
setRepeatingRequest
(预览连续出帧)
process_capture_request
core 调度 Node,经 CSL 下到 ISP
CaptureCallback.onCaptureCompletedprocess_capture_result
结果帧 + metadata 原路回传

一句话映射:openCamera=握手 | createCaptureSession=选 usecase、建流水线 | setRepeatingRequest=执行出帧 | onCaptureCompleted=结果回传。

画成时序图(注意主从:framework 只和 CamX core 打交道,core 再去调 CHI):

一步步看:

  1. **openCamera**:app 打开相机。请求经 framework、Provider 落到 CamX core(它实现 HAL3 入口),core 加载 CHI、通过 chi_hal_override_entry 与它握手,两个 .so 互取接口。
  2. createCaptureSession:app 声明"我要这路预览输出流"。这触发 HAL3 的 configure_streams——关键一步在这里:core 请 CHI(chi_initialize_override_session),CHI 的 UsecaseSelector 选出预览 usecase、定好 topology(比如 IFE → IPE 这一条),再借 core 的能力把 Session/Pipeline/Node 建好。流水线在这一步就建好,不是每帧重建。
  3. **setRepeatingRequest**:app 提交重复请求(预览连续出帧)。之后每个显示周期,core 把请求送入已建好的 pipeline,调度各 Node,经 CSL submit 到内核。
  4. 硬件出帧:内核驱动配置 sensor 与 ISP,硬件按 topology 流转(预览这类的 topology,硬件上就是 IFE → IPE 这条通路)。
  5. 结果回传:硬件完成经 fence 通知,core 逐级回收结果 → 通知 CHI → process_capture_result 把结果帧和 metadata 交回 framework,app 的 onCaptureCompleted 被调用,预览显示出来。

如果想看接口级怎么落地(下面是按官方入口名 + 公开机制画的职责示意,不是 CamX 真实源码——core/CHI 闭源):

// —— 职责示意,非 CamX 真实源码 ——
// core 侧:configure_streams 落到 CamX core(core 实现 HAL3)
intconfigure_streams(camera3_stream_configuration* cfg){
// core 委托 CHI 决策,并把"自己的能力"交给它
return chi_initialize_override_session(cfg, &g_chiContextOps);   // core → CHI
}
// CHI 侧:设计 topology,再借 core 的能力实例化
Session* chi_initialize_override_session(cfg, CoreOps* coreOps){
    UsecaseId id  = UsecaseSelector::select(cfg);   // CHI 设计:选 usecase(预览)
    Topology topo = buildTopology(id);              // CHI 设计:要 IFE→IPE 两个 node、怎么连
    Pipeline* p   = coreOps->CreatePipeline(topo);  // core 实现:造 node、组装 pipeline
return          coreOps->CreateSession(p);      // core 实现:建 session
}

这条链最关键的两跳都在 CHI:第 2 步"选哪套 usecase""建哪张 topology"——正是那道 override 缝被显式化的位置。core 只在其后忠实地调度执行。归纳一句:入口与执行在 core,决策在 CHI。


五、边界与对号入座

把两条路径的边界厘清。核心划分维度是"相机怎么接进来",不是"哪种相机"或"app 用了什么 API":

相机类型
主路径
底层 ISP
说明
座舱应用相机(视频通话/自拍/拍录,MIPI 直连)
A:Camera2 → CamX-CHI
Spectra
本篇主体
RVC 倒车 / AVM 环视
B:QCarCam/AIS
(Android 侧对应 EVS)
可复用 CamX/Spectra
早启动、法规 2 秒,留后续篇
DMS / OMS(舱内监测)
B:QCarCam/AIS
(取流层面)
可复用 CamX/Spectra
算法跑在哪取决于方案,见下
ADAS 感知相机
B:QCarCam/AIS
(新平台 QCX)
Spectra
留后续篇
GMSL 相机被桥接成 Camera2
Camera2 表面,后端 AIS
AIS
"走 Camera2 ≠ 走 CamX-CHI"

几个不能写成绝对、必须留余地的点:

  • 不要说"车载相机不经 CamX":AIS 做 ISP 处理时可选复用 CamX/Spectra(有编译开关 USE_IMAGING_AIS / AIS_BUILD_CAMX 为证)。准确说法是"车规相机不以 Camera2→CamX-CHI 这条 HAL3 链为主路径",但底层 ISP 硬件仍可能是那套。AIS 与 CamX 是"独立通路 + 可选复用"的关系,不是谁替代谁。

判断一颗车载相机走哪条,不要只看 app 用了 Camera2 还是 QCarCam——要看它怎么接进来、要满足什么需求:要早启动/功能安全/GMSL 多路的,走 B;座舱里 MIPI 直连、像手机一样的应用相机,走 A。


小结

  • 两条路:手机相机只有 A(Android 栈);车载 A、B 都有——A 是座舱 Android 应用相机(Camera2→CamX-CHI),B 是车载专用相机栈(QCarCam/AIS/EVS,服务 RVC/AVM/DMS/ADAS)。
  • 本篇是 A 的 HAL:CamX-CHI 是高通对 Google HAL3 的实现,camera.qcom.so(core)+ com.qti.chi.override.so(CHI)两层。
  • 核心设计:CHI 出图纸(选 usecase/定 topology)、core 造流水线(实现/执行);core 稳定通用、CHI 可被 OEM 覆写——一套 core 适配所有芯片和客户,OEM 不改动引擎就能定制。
  • 三方区分:core、CHI 都是高通写的;OEM 只在 CHI 层定制。
  • 纠偏:走 Camera2 ≠ 走 CamX-CHI(后端可能是 AIS 桥接);判断走哪条看相机怎么接入。

一句判断:不要把手机的"一条路"套到车载。 车载相机是两条路并行——想清楚你面对的相机走哪条,是做车载相机开发的第一步。而这两条路里,车载真正的主角其实是 B。

至于 B 这条——QCarCam/AIS 到底怎么让倒车画面在 Android 起来之前就出图、怎么跨 QNX 与 Android 双域、怎么管理全车多路 GMSL 相机,下一篇正式打开。


参考资料

  • CamX architecture(129_CamX)— Qualcomm 官方:CamX = camx + chicdk 两层、软件分层图。
  • CHI(126_CHI)— Qualcomm 官方:CHI override 定位、"supplements the Google HAL3 interface"原文。
  • CHI architecture model(127)— Qualcomm 官方:CHI 初始化 UML 时序图与官方入口名(chi_hal_override_entry 等)。
  • Qualcomm Spectra 480(124)— Qualcomm 官方:IFE / IPE / BPS 数据通路。
  • Qualcomm 专利 US10613870B2:Node / Topology(DAG) / Session / Pipeline / Usecase 的一手定义。
  • Android Camera HAL3 / AIDL — source.android.com:HAL3 接口与 Android 13 起的 AIDL 化范围。
  • Vehicle Camera HAL / EVS — source.android.com:车载 EVS、早启动(开机 2 秒内出图)、倒车/环视用 EVS 的官方说明。
  • Camera2 API — developer.android.com:CameraManager / CameraDevice / CameraCaptureSession 等 app 侧接口。
  • 路径 B(QCarCam/AIS)的具体划分依据多为二手/逆向来源,详见下一篇专篇梳理。

如果觉得有帮助,欢迎点赞、在看、转发三连。

这是《车载Camera·软件栈》系列第 5 篇。如果你在做车载摄像头、Android / QNX 相机开发,欢迎关注追更。


系列导航:《车载Camera·软件栈》讲应用层如何拿到摄像头画面、软件栈如何分层;另一个系列《车载Camera·技术全栈》讲一帧数据怎么流(硬件 → 驱动 → 框架 → 跨 VM 共享)。公众号点「合集」看全部。

相关学习资料