夜雨聆风学习资料网

ARTICLE · 994848

车载Camera·软件栈·第6篇 | QCarCam:车载专用的 Camera 取流框架

车载Camera·软件栈·第6篇 | QCarCam:车载专用的 Camera 取流框架

导读:一辆车上十几颗摄像头,走的不是手机那套 Camera2 → CamX-CHI,而是高通车载专用的 QCarCam。本篇讲清三件事:QCarCam 是什么、车载为何另起一套、一次取流如何完成——含 QNX / Android 双域分层架构、底层 AIS → QCX 换代、以及与 CamX / EVS 的边界(EVS 已弃用、迁往 Camera2,文中说明)。全篇通篇标注来源硬度,闭源处不装作确定。系列第 6 篇。

阅读前提

  • 系列内:承接第5篇。上一篇分清两条路——一条是 Android Camera 栈(Camera2 → CamX-CHI,座舱应用摄像头),另一条是车载专用栈(以 QCarCam 为对外 API,服务倒车 / 环视 / DMS / ADAS 等 GMSL 车规摄像头)。本篇讲后一条:QCarCam 是什么、车载为何用它、一次取流如何完成。
  • 系列外:需要 GMSL(车载长距离串行摄像头接口)、ISP(图像信号处理器)、双 OS(QNX 安全域 + Android 座舱经 Hypervisor 共存于同一颗芯片)、以及 C 语言 API 的基本概念,不熟悉时按字面理解即可。
  • 深度与依据:QCarCam 的逐字官方 API 文档在高通开发者门户登录墙内,公开可引者有限。本篇依据高通公开文档(QcNode、Qualcomm Linux Camera Guide 的 GMSL 说明)、AAOS 官方(EVS)、一份把 QCarCam API 与底层实现串起来的逆向 wiki及多篇技术博客交叉核实;实现细节(如事件队列条数、参数字段)来源不硬者,文中标注、不作定论。脱敏:不涉及任何项目私有 / QNX NDA / 具体 sensor 连法 / tuning。

一、车载为什么要用 QCarCam

一辆车上的摄像头数量可观:环视 4 路、倒车、DMS / OMS,再加 ADAS 前视周视,十余颗常见,多经 GMSL 长线束接入、多路常开。这些车规摄像头走的不是上一篇的 Android 路径,而是 QCarCam。

Android 的 Camera 栈本质上为手机设计:应用触发、单路或少数几路、消费者少、可容忍秒级启动、摄像头以 MIPI 直连为主。车载需求与之不匹配,故高通另建 QCarCam(含底层采集系统)。三条硬需求:

其一,GMSL 多路常开的统一采集。 车规摄像头经 GMSL / FPD-Link 串化器走长同轴线接入(抗长距离、抗干扰),一颗芯片的 CSI 需扇出多路。高通官方 Camera Guide 记载了对应机制:一个 GMSL port 挂 4 路摄像头至同一 CSI(以 virtual channel 区分)、按 group 并发,并有 offline IFE 支撑多路并发。多路常开与分组仲裁,正是 QCarCam 要解决的问题。

其二,多客户端仲裁。 一路摄像头的画面常有多个消费者:倒车 App 显示、泊车算法读取、行车记录录制。需要一个系统级服务进程统一持有摄像头资源、按客户端分发——即下一节的 ais_server。

其三,跨 OS 可移植。 车载常为双 OS:安全域运行 QNX、座舱运行 Android,经 Hypervisor 共存于同一颗芯片。QCarCam 的一项特性是 OS 可移植——同一套 API 在 QNX 与 Android 上均可使用。因此它并非"Android 侧技术",而是横跨两个 OS 的车载 Camera 取流框架:QNX 安全域可直接取流,Android 座舱侧经 EVS 用到它(EVS 弃用后迁 Camera2,第四节详述)。

还有一条常被摆在最前的需求——早启动。车规摄像头(尤其倒车)要求极早出图,而 Android 完整 Camera 框架冷启动需十余秒,无法满足。QCarCam 底层轻量、原生 C、可极早拉起,为"极早出图"提供了前提。但倒车挂挡瞬间的秒级出图如何落地——QNX 先出图、EVS 在 Android boot 内尽早拉起、以及双系统间的 handoff——属下一篇内容,本篇不展开。

小结:Android Camera 栈面向"手机式、应用触发、少消费者、容忍秒级启动";车载摄像头面向"GMSL 多路常开 + 多客户端 + 跨 OS"。需求错配,故高通另建 QCarCam。


二、QCarCam 是什么:统一的取流接口

QCarCam(Qualcomm Car Camera)是高通为车载摄像头定义的一套 C API,向上层提供统一的取流接口:应用只需调 API 取帧——

  • 无需关心摄像头是 MIPI 直连还是 GMSL 串化;
  • 无需关心底层是哪套 ISP;
  • 无需关心访问硬件的服务进程在哪个域(实际常落在 QNX 安全域)。

它覆盖车载多样化的摄像头入口:MIPI CSI sensor(直连)、deserializer / aggregator(GMSL、FPD-Link 等车规长线束串化方案的收端)、HDMI / CVBS(经转换芯片的数字 / 模拟视频输入)、以及 memory buffer(把内存中的帧当作一路"虚拟输入")。

分层架构:QNX 域与 Android 域

图中 QNX 域与 Android 域各自分层,两域共同下方是 Hypervisor(隔离并托管两个 VM),最底层是硬件。QNX 域(安全 / 早启动):应用 / 服务 → Middleware(ais_client 与 ais_server)→ 内核 / 驱动(内核相机驱动)→ 硬件;应用调 qcarcam_* 进入 ais_client,ais_client 经本域 socket 连 ais_server,ais_server 不直接访问硬件——经内核相机驱动操作,而硬件由 Hypervisor 一次性直通(passthrough)给 QNX:分配完成后,驱动近乎直接操作硬件,Hypervisor 不再逐次中转。Android 域(座舱):应用 → HAL(ais_client,在 EVS / AIS HAL 内);应用经 EVS 进入 ais_client,其 ais_client 跨 VM、经 HAB(Hypervisor 的跨域通信机制)连到 QNX 的 ais_server 取帧——注意这与 QNX 同域的 socket 不同。两点值得记住:**ais_server 只在 QNX 域、独占硬件,两域客户端都连它;Android 侧接入 AIS 目前经 EVS(EVS 正弃用、迁往 Camera2,见第四节),座舱内**相机则走另一条 Camera2 → CamX-CHI 路径。

关于这张图的性质:QCarCam 底层闭源,逐字官方架构图在高通开发者门户登录墙内。此图为综合公开逆向资料与高通公开文档交叉整理,非高通官方架构图,请作"帮助理解的骨架参考"。其中 QNX 侧的中间层用 "Middleware" 泛称(ais_client 与 ais_server 都在此,确切子层名各平台不一);Android 侧接入 AIS 目前经 EVS(EVS 弃用中→Camera2,见第四节)。图中 ais_server 落在 QNX 域、Android 经 HAL 跨域取帧属逻辑关系;跨 VM 传输经 HAB(高通 hypervisor 机制;QNX Hypervisor 设计常走 VIRTIO,随平台而定),其细节与倒车早启动属下一篇内容。

关键组件:三个角色

qcarcam.h(对外 API 头文件)。 应用面对的唯一入口:一组 qcarcam_* 函数声明(initialize / open / start / get_frame…)与类型定义。它只是头文件、非库——实现这组 API 的是 libais_client.so。价值在稳定:底层换代,函数签名基本不变,应用改动小。

libais_client(框架层的客户端库 .so)。 它不在 app 进程,而在框架层——QNX 侧属 Middleware,Android 侧包在 HAL(EVS / AIS HAL)内。上层经它调 QCarCam API,每个调用被翻译为发往服务进程的 socket / IPC 请求;服务进程侧的事件(尤其"帧就绪")也由它接收、投递回上层。它维护优先级事件队列,保证"帧就绪"等关键事件优先于"参数变更"送达;等帧以条件变量阻塞 / 唤醒,get_frame 支持超时。(事件队列条数属逆向资料的实现细节,机制如此,条数不追究。)

ais_server(守护进程)。 运行在 QNX 域,是框架中唯一操作摄像头硬件的进程(经内核驱动访问 CSI / ISP / 解串器),角色近似 Android 的 cameraserver。职责:系统级管理摄像头资源、接受多客户端连接、协调设备访问与仲裁、配置 ISP。一个 server 统一持有所有摄像头,两域的 client 均连接它取流(Android 侧经 HAB 跨 VM)。

与 CamX 的关系(此图未画,第四节展开)。ais_server 做 ISP 处理时,可(编译开关 USE_IMAGING_AIS)复用 CamX 的 ISP 能力,也可独立运行;CamX 是可选后端,非必经节点。

底层换代:当代 AIS,下一代 QCX

需区分两层。上述组件(ais_server / libais_client)是 QCarCam 当代的底层实现,称 AIS(Automotive Imaging System,高通车载成像系统),用于 SA8155P / 8295P 世代。底层实现会换代:新一代 ADAS 平台(SA8650P / 8775P 等)上,AIS 演进为 QCX(Qualcomm Camera Next,服务进程由 ais_server 变为 qcxserver),ISP 组织方式重构,但对外仍是 QCarCam API(升至 6.X)。QCX 是 AIS 的下一代,而非并列的另一套;换代的是实现,QCarCam 这层抽象不变。正因这层 C API 一脉相承,底层从 AIS 换到 QCX,应用改动才小——这是它作为稳定抽象层的价值。

API 生命周期

QCarCam 是一套调用顺序严格的 C API,与 Camera2 的生命周期同构——打开 → 配置 → 取帧 → 关闭。对照如下:

阶段
函数
这一步做什么
初始化
qcarcam_initialize()
系统级初始化
发现
qcarcam_query_inputs()
枚举有几路输入、各自 input_id——找到后视这一路
打开
qcarcam_open()
按 input_id 取这路摄像头的 handle
配置
qcarcam_s_param()
设分辨率、格式等
缓冲
qcarcam_s_buffers()
绑定 / 分配帧缓冲池
启动
qcarcam_start()
开始采集
取帧
qcarcam_get_frame()
取一帧(支持超时,阻塞等帧)
还帧
qcarcam_release_frame()
把 buffer 归还缓冲池
停止
qcarcam_stop()
停止采集
关闭
qcarcam_close()
释放 handle
反初始化
qcarcam_uninitialize()
系统级 teardown

诚实标注:上表为基于公开 API 语义整理的示意(参数字段、事件是回调还是 poll 的确切签名未取到官方直链);query_inputs 之外是否有独立的 get_param 类函数,公开证据不足,不列。

QCarCam 是统一的取流接口(一套 C API):应用只管取帧,摄像头接法、ISP、服务所在 OS 均被隐藏。底层当代为 AIS,下一代为 QCX;无论哪代,对外都是 QCarCam。


三、一次取流的完整链路:以 RVC 后视为例

本节讲一次取流的完整过程,以最典型的后视 RVC(倒车影像)为例:单路摄像头 → 单个消费者 → 上屏,一条直链,无多路并发、无算法回路,便于讲清生命周期与组件间通信。

这些函数的调用顺序与 Camera2 同构,但背后是一套独立的车载取流栈(而非 Camera2 → cameraserver → CamX-CHI):应用调用经 libais_client 翻译为 IPC 发往 ais_server。时序如下:

分三个阶段读这张图:

① 打开 + 配置 + 启动。 倒车 App 依次调 open(取 handle)、s_param(设分辨率 / 格式)、s_buffers(绑缓冲池)、start(启动采集)。每个调用都是两跳:先进 libais_client,翻译为 IPC 发往 ais_server,再由 ais_server 配置 sensor / ISP、启动采集。App 全程不接触硬件。

② 稳态出帧(每帧循环一次)。 核心回路:

  • ais_server 每采到一帧,经优先级事件队列抛出 frame-ready 事件,libais_client 收到后投递给 App;
  • App 收到事件,调 get_frame 取帧——同样两跳转成 IPC 到 ais_server,帧 buffer 原路回到 App 上屏;
  • App 用完,调 release_frame 把 buffer 归还缓冲池——继续两跳。

③ 结束。stop / close / uninitialize,与启动对称,逐跳退回。

组件间通信:App 与 ais_server 无直连,一切经 libais_client 走 IPC;事件(尤其 frame-ready)走优先级队列,等帧以条件变量阻塞 / 唤醒。帧在硬件侧的来路:**sensor → serializer(摄像头侧串化)→ 长同轴线 → deserializer(SoC 侧还原)→ CSI → IFE → ais_server**,再经 libais_client 交至应用。

RVC 单路讲清后,另两类可类推:环视 AVM 是同一链路复制为多路并发(4 路各自 open / start,ais_server 分组仲裁);DMS 是在消费端加挂算法(取帧后交人脸 / 视线算法,而非直接上屏)。机制不变,仅"路数 + 帧的去向"不同。

这是一套独立于 Android Camera 栈(Camera2 → cameraserver → CamX-CHI)的车载取流通路——libais_client → ais_server,走 socket / HAB。倒车挂挡瞬间画面早于 Android 上屏,属早启动 / 跨域 handoff,下一篇专述。


四、总结与注意事项

两代实现对照如下(最易记混,需记准):

对外 API
底层实现
服务进程
代表平台
当代
QCarCam(较早版本)
AISais_server
SA8155P / 8295P
下一代
QCarCam 6.X
QCXqcxserver
SA8650P / 8775P

对外始终是 QCarCam,底层从 AIS 换到 QCX。

再看两处最易讲错的关系:

① 与 CamX:独立通路 + 可选复用。 QCarCam 的底层(AIS)是独立于 CamX-CHI(上一篇的 Android HAL)的车载 Camera 采集 / 服务 / 仲裁框架,有自成一套的 server / client / API / 事件队列;做 ISP 处理时可复用 CamX(USE_IMAGING_AIS 决定是否链接 CamX 模块,AIS_BUILD_CAMX 决定用 CamX 处理还是独立运行)。故"车规摄像头不经 CamX"并不准确,准确表述是"不以 Camera2 → CamX-CHI 的 HAL3 链为主路径",但底层 ISP 仍可能是 CamX / Spectra。

② 与 EVS:EVS 是 Android 侧的标准接口,后端落在 QCarCam。 EVS(Exterior View System)是 Google / AAOS 定义的车载 Camera HAL,为 IVI 的倒车 / 环视应用提供标准接口。高通平台的公开 vendor 兼容性矩阵中有 HAL 声明 vendor.qti.automotive.qcarcam、接口 IQcarCamera v1.0——即高通把 QCarCam 暴露为一个 HAL,EVS 的高通实现后端坐在 QCarCam 上。故"EVS 就是高通的"亦不准确:EVS 是 AAOS 标准,高通提供的是其下的 QCarCam 后端。

时效补充:AAOS 近版本已弃用 EVS API,引导迁移到 Camera2(车外相机走 privileged AID_AUTOMOTIVE_EVS + system camera,并提供 shim 兼容层过渡)。但要点在于——弃用的是 Android 应用侧的接入口,QCarCam / AIS 这个 vendor 后端不变:只是 Android 侧从 EVS 换成 Camera2 去接同一个 AIS。因此本篇的 QCarCam/AIS 主线不受影响,变的只是座舱侧的"提货口"。

注意事项 · 依据。 QCarCam 底层闭源,逐字官方 API 文档在高通开发者门户登录墙内。本篇的架构分层、组件职责、C/S 通信方式,来自高通公开文档、AAOS 官方与逆向 wiki 的交叉核实;字段级细节(参数签名、事件队列条数、精确版本号)公开证据不足,文中已逐处标注"示意 / 逆向 / 不写死",请勿当作官方定义照抄——落到具体量产平台,以各自 BSP 与官方门户为准。

车载 Camera 并非"手机摄像头装上车"——车规摄像头这条主路径,是独立于 Android Camera 栈、跨 OS 的 QCarCam。理清它,才算把握车载 Camera 软件栈的主体。至于倒车挂挡秒级出图:QCarCam 底层可极早拉起只是前提,真正让画面早于 Android 上屏的,是 EVS 早启动、QNX 安全域先出图与双系统间的跨域 handoff——下一篇展开。


参考资料

  • QcNode — Qualcomm 官方 GitHub:Camera node "用 qcarcam 库做 streaming"、QNN node 做 AI 推理——佐证 QCarCam 是取流库、ADAS 感知分取流 / 推理两路。
  • Qualcomm Linux Camera Guide · Stream cameras — Qualcomm 官方:GMSL per-port grouping、virtual channel、offline IFE 多路并发。
  • Vehicle Camera HAL — source.android.com(AAOS 官方):EVS 定位、车载早启动(开机 2 秒内出图)、倒车 / 环视用 EVS(注:EVS 已弃用,官方引导迁 Camera2)。
  • EVS Overview — source.android.com(AAOS 官方):EVS 概览(已弃用→Camera2)。
  • Migrate to Camera2 — source.android.com(AAOS 官方):EVS 弃用、迁 Camera2 的官方指引(privileged 早访问 AID_AUTOMOTIVE_EVS、shim 兼容层)。
  • QCarCam 底层实现(AIS)系统架构(DeepWiki,逆向):QCarCam API 生命周期、ais_server / libais_client、事件队列、USE_IMAGING_AIS / AIS_BUILD_CAMX——把全链串起来的公开物(逆向 wiki,实现细节需谨慎)。
  • vendor 兼容性矩阵中的 vendor.qti.automotive.qcarcam / IQcarCamera v1.0(LineageOS 镜像):佐证 EVS 高通后端坐在 QCarCam 上。
  • 说明:QCarCam 逐字官方 API 定义在高通开发者门户(登录墙内);本篇 API 语义为公开逆向 + 多篇技术博客交叉核实,实现细节已在文中标注来源强度。

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

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


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

相关学习资料