Qcom CamX

Camx架构全景图:从V4L2到Pipeline的完整拆解

写了很多Camera实战文章,但一直没系统梳理过架构。这篇补上——从V4L2框架到Pipeline/Node体系,从CRM请求管理器到IFE硬件状态机,把Camx的核心架构串一遍。理解了架构,后面的调试和开发才能有的放矢。

一、整体架构:KMD + UMD分层

高通Camera软件架构分为两层:内核态驱动(KMD)用户态驱动(UMD),两者通过V4L2接口通信。

层级
职责
核心组件
UMD(用户态)
Pipeline编排、算法处理、3A
Camx Core、CHI Framework、Node
KMD(内核态)
硬件控制、中断处理、DMA
CRM、IFE/VFE、CPAS、CSL
通信接口
UMD↔KMD数据交换
V4L2 Subdevice + IOCTL

关键设计理念:KMD只负责硬件控制,不做任何图像处理逻辑。Pipeline编排、算法决策全在UMD。这样设计的好处是KMD可以跨平台复用,而UMD可以灵活适配不同产品需求。

二、V4L2框架:Camera的通信基石

V4L2(Video4Linux2)是Linux的视频设备标准框架。高通Camera驱动基于V4L2构建,但做了大量定制。

2.1 V4L2的两层结构

V4L2是两层驱动系统:


  • 顶层 videodev 模块
    :注册为字符设备(major 81),提供统一的V4L2接口

  • 底层 subdevice 模块
    :各Camera硬件组件注册为V4L2子设备

当UMD需要操作某个Camera硬件时,通过Videodev找到对应的子设备,然后通过IOCTL发送命令。

2.2 Camera子设备清单

开机时,所有Camera硬件组件都会注册为V4L2子设备:

// 开机时子设备注册日志
CAM_INFO: CAM-CRM: cam_register_subdev: v4l2_device_register_subdev sd: cam-cpas
CAM_INFO: CAM-CRM: cam_register_subdev: v4l2_device_register_subdev sd: cam-isp
CAM_INFO: CAM-CRM: cam_register_subdev: v4l2_device_register_subdev sd: cam-cci-driver
CAM_INFO: CAM-CRM: cam_register_subdev: v4l2_device_register_subdev sd: cam-csiphy-driver
CAM_INFO: CAM-CRM: cam_register_subdev: v4l2_device_register_subdev sd: cam-actuator-driver
CAM_INFO: CAM-CRM: cam_register_subdev: v4l2_device_register_subdev sd: cam-sensor-driver
CAM_INFO: CAM-CRM: cam_register_subdev: v4l2_device_register_subdev sd: cam-flash-dev
CAM_INFO: CAM-CRM: cam_register_subdev: v4l2_device_register_subdev sd: cam-eeprom
CAM_INFO: CAM-CRM: cam_register_subdev: v4l2_device_register_subdev sd: cam-ois
CAM_INFO: CAM-CRM: cam_register_subdev: v4l2_device_register_subdev sd: cam-icp
CAM_INFO: CAM-CRM: cam_register_subdev: v4l2_device_register_subdev sd: cam-jpeg
CAM_INFO: CAM-CRM: cam_register_subdev: v4l2_device_register_subdev sd: cam-fd
CAM_INFO: CAM-CRM: cam_register_subdev: v4l2_device_register_subdev sd: cam-lrme

2.3 设备分类:实时 vs 非实时

Camera设备按功能分为两类:

类型
定义
设备
实时(Real-time)
流式传输实时数据
Sensor、Flash、IFE、OIS
非实时(Non-real-time)
内存到内存处理
IPE、JPEG、FD、LRME、Actuator

这个分类很重要——实时设备通过CRM同步,非实时设备不需要CRM同步。理解这一点,调试帧同步问题时就知道该查哪个链路。

三、CRM:请求管理器

CRM(Camera Request Manager)是KMD中最核心的组件,负责同步所有实时设备的请求应用

3.1 CRM的核心职责


  • 请求同步
    :确保同一帧的Sensor配置、IFE配置、Flash配置同步生效

  • SOF触发
    :IFE每帧产生SOF中断后通知CRM,CRM决定该帧应用哪个请求

  • 请求追踪
    :追踪每个请求在各设备上的就绪状态

  • 错误恢复
    :请求应用失败时进行重试或跳帧

  • Flush处理
    :Session关闭时清理所有未完成请求

3.2 CRM的关键概念:Pipeline Delay

CRM管理请求的核心机制是Pipeline Delay(PD)。不同设备有不同的处理延迟:

// CRM Link时输出的设备Pipeline Delay信息
CAM_DBG: CAM-CRM: connected: cam-isp, id 4, delay 1, trigger 1
CAM_DBG: CAM-CRM: connected: cam-sensor, id 1, delay 2, trigger 1
CAM_DBG: CAM-CRM: connected: cam-actuator, id 3, delay 1, trigger 1
CAM_DBG: CAM-CRM: connected: cam-flash, id 2, delay 1, trigger 1

解释:


  • delay 2
    :Sensor,需要提前2帧配置(因为Sensor有上电+曝光延迟)

  • delay 1
    :IFE/Flash/Actuator,提前1帧配置

这意味着:请求N在Sensor上配置后,需要在第N+2帧的SOF时才能生效。CRM就是通过这个PD机制来同步不同设备的配置时序。

3.3 CRM请求处理流程

// CRM在SOF中断时的处理流程
// 1. IFE产生SOF中断,通知CRM
CAM_INFO: CAM-ISP: __cam_isp_ctx_notify_sof_in_activated_state: Start Notify CRM SOF frame 1

// 2. CRM工作队列被唤醒
CAM_DBG: CAM-CRM: cam_req_mgr_workq_enqueue_task: enq task pending_cnt 1

// 3. CRM查找该SOF应该应用的请求
CAM_DBG: CAM-REQ: cam_req_mgr_process_trigger: link_hdl 43010d frame_id 1, trigger 1

// 4. 检查请求就绪状态(pd_mask 6 = 0b110 = pd2+pd1就绪)
CAM_DBG: CAM-CRM: __cam_req_mgr_check_link_is_ready: SOF: idx 0 result 6 pd_mask 6

// 5. 向各设备发送应用请求
CAM_DBG: CAM-REQ: __cam_req_mgr_send_req: SEND: link_hdl: 43010d pd 2 req_id 1
CAM-REQ: cam_sensor_apply_request: Sensor update req id: 1

CAM_DBG: CAM-REQ: __cam_req_mgr_send_req: SEND: link_hdl: 43010d pd 1 req_id 1
CAM-REQ: __cam_isp_ctx_apply_req_in_activated_state: Apply request 1

日志中req_id=1:-1:0的格式表示(pd2:pd1:pd0),即pd2设备应用请求1,pd1设备跳过(-1),无pd0设备。

3.4 CRM常见错误

错误
含义
排查方向
SOF freeze
IFE没产生SOF中断
Sensor是否正常出流、IFE硬件是否异常
Skip Frame
请求未就绪,跳帧
UMD未及时提交请求,查add_req日志
APPLY_FAILED
设备拒绝应用请求
IFE状态机卡住,检查IFE日志

四、IFE/VFE:图像处理引擎

IFE(Image Front End)是Camera硬件的图像处理前端,负责接收Sensor输出的Raw数据并进行实时ISP处理。

4.1 IFE的硬件组成

IFE硬件包含以下主要模块:


  • CSID
    :Camera Serial Interface Decoder,解码MIPI数据

  • CAMIF
    :Camera Interface,接收解码后的数据

  • ISP模块
    :图像信号处理(去马赛克、降噪、色彩校正等)

  • BUS_IF
    :总线接口,连接后端DMA

4.2 IFE的三层架构

IFE在KMD中分为三层:

层级
职责
说明
IFE Interface
V4L2接口层
注册subdevice,接收CSL IOCTL
IFE Context
会话管理层
处理核心逻辑:SOF通知、配置缓存、Bubble检测
IFE HW Manager
硬件资源管理层
管理物理IFE硬件资源分配

4.3 IFE Context状态机

IFE Context有5个状态,描述了从初始化到工作再到释放的完整生命周期:

IFE Context状态流转:

Uninit → Available → Acquired → Ready → Activated
  │          │          │         │        │
  │          │          │         │        └─ 主工作状态:处理每帧请求
  │          │          │         └─── 等待stream-on命令
  │          │          └───── 等待初始配置 + Link
  │          └──────── 初始化完成,在free pool中等待acquire
  └────────── 构造完成,等硬件probe

各状态的关键行为:


  • Available
    :IFE Context已初始化,在free pool中等待被acquire

  • Acquired
    :已获取硬件资源,等待初始配置包和Link命令

  • Ready
    :初始配置完成,等待stream-on命令

  • Activated
    :主工作状态,处理SOF、配置应用、Bubble检测、BUF_DONE等

4.4 Activated状态的子状态机

进入Activated状态后,IFE还有一套子状态机,由中断驱动:

子状态
触发中断
行为
SOF
SOF IRQ
帧计数器+1,接收CRM的配置触发
APPLIED
配置已应用
等待REG_UPD或EPOCH中断
EPOCH
REG_UPD IRQ
配置已写入硬件寄存器,等待EPOCH
BUBBLE
EPOCH IRQ(异常)
Bubble检测,触发恢复流程

理解这个子状态机对调试至关重要——当你看到日志中IFE在某个子状态卡住时,就知道该查哪个中断没有按预期到来。

五、CPAS:时钟与总线管理

CPAS(Camera Power and Arbiter System)管理Camera硬件的时钟投票和总线带宽分配。

5.1 CPAS的核心功能


  • 时钟投票
    :各Camera模块需要工作时,通过CPAS申请时钟

  • 带宽分配
    :为DMA传输分配总线带宽(通过CAMNOC)

  • 电源域管理
    :管理Camera子系统的电源域

  • 资源仲裁
    :多个Camera同时使用时,仲裁资源优先级

5.2 CAMNOC总线

CAMNOC是Camera专用总线,分为三个通道:

CAMNOC通道划分:

hf1 (High-Frequency 1) → IFE实时数据传输(高带宽低延迟)
hf2 (High-Frequency 2) → IPE/JPEG非实时数据传输
sf1 (Shared-Frequency) → 配置寄存器访问(低带宽)

当出现ISP Overflow带宽不足的问题时,CPAS日志是关键排查入口。

5.3 开启CPAS日志

# 开启CPAS调试日志
adb shell "echo 0x40 > /sys/module/cam_debug_util/parameters/debug_mdl"

# 查看CPAS时钟投票
adb shell "cat /sys/kernel/debug/camera/cpas/cpas_info"

# 查看各模块带宽申请
adb shell "cat /sys/kernel/debug/camera/cpas/bw_info"

六、UMD:Pipeline与Node体系

在KMD之上,UMD负责所有Camera业务逻辑。核心概念是PipelineNode

6.1 Pipeline

Pipeline是一条处理流水线,由多个Node串联组成。一个Pipeline的典型结构:

RealtimePreview Pipeline:
  SensorNode → IFENode → IPENode → OutputNode(JPEG/Preview/Video)

OfflineSnapshot Pipeline:
  IFENode → IPENode → JPEGNode → OutputNode

每个Pipeline有自己的Session和Request队列。UMD通过ProcessCaptureRequest接收来自Framework的请求,分发给Pipeline处理。

6.2 Node

Node是Pipeline中的最小处理单元。每个Node有:


  • 输入端口
    :接收上游Node的数据(通过Fence同步)

  • 处理逻辑
    :ExecuteProcessRequest方法,处理一帧数据

  • 输出端口
    :输出处理后的数据给下游Node

  • Fence机制
    :Buffer就绪通知,跨Node异步同步

6.3 UMD到KMD的调用链

一个完整的请求从Framework到硬件的调用链:

// 1. Framework发请求到Camx
camxsession.cpp: ProcessCaptureRequest()
  → 添加到请求队列,启动Job

// 2. Camx Pipeline分发请求到各Node
camxpipeline.cpp: ProcessRequest()
  → SensorNode: ApplySensorUpdate()
  → IFENode: ExecuteProcessRequest()

// 3. Node通过CSL提交硬件配置包
camxifenode.cpp: ExecuteProcessRequest()
  → CSLSubmitPacket()

// 4. KMD接收到配置包
cam_req_mgr_cb_add_req() → CRM处理

// 5. CRM在SOF时触发应用
cam_req_mgr_process_trigger()
  → __cam_isp_ctx_apply_req_in_activated_state()

// 6. 硬件配置生效,处理数据
// 7. IFE产出数据,BUF_DONE通知
__cam_isp_ctx_handle_buf_done_in_activated_state()

// 8. UMD收到Fence回调
camxnode.cpp: CSLFenceCallback()
  → SinkPortFenceSignaled()
  → 上报stream done给Framework

理解这条调用链,是排查Camera延迟和帧丢失问题的基础。当预览卡顿或帧丢失时,沿着这条链路逐段检查日志,就能定位到卡在哪个环节。

七、架构调试速查表

问题现象
排查模块
关键日志关键词
Camera打不开
CSL/Probe/Power
acquire_device, probe, power_on
预览黑屏
CRM/IFE
SOF, stream_on, skip_frame
预览卡顿/掉帧
CRM/UMD Pipeline
not_ready, open_req, skip
ISP Overflow
IFE/CPAS
overflow, csid, bus_wr_err
Crash
UMD/Tombstone
abort, F DEBUG, signal
功耗过高
CPAS/Clock
ahb_vote, hw_src_vote

小结

Camx架构的核心可以浓缩为一张图:

┌─────────────────────────────────────────┐
│              Android Camera Framework            │
│              (Camera2 API / CameraX)              │
├─────────────────────────────────────────┤
│              UMD (Camx + CHI)                    │
│  ┌─────────┐  ┌─────────┐  ┌─────────┐    │
│  │Pipeline │→│  Node   │→│  Node   │    │
│  │Session  │  │(IFE/IPE)│  │(JPEG等) │    │
│  └─────────┘  └─────────┘  └─────────┘    │
│         │ CSL Interface                     │
├─────────┼──────────────────────────────────┤
│         │ V4L2 IOCTL                       │
│  ┌──────▼──────────────────────────────┐  │
│  │         KMD (Kernel Driver)          │  │
│  │                                      │  │
│  │  ┌─────┐  ┌─────┐  ┌─────┐         │  │
│  │  │ CRM │  │ IFE │  │CPAS │         │  │
│  │  │     │  │/VFE │  │     │         │  │
│  │  └──┬──┘  └──┬──┘  └─────┘         │  │
│  │     │        │                      │  │
│  │  ┌──▼──┐  ┌──▼──────────┐          │  │
│  │  │Sensor│ │CSI/ISP/BUS  │          │  │
│  │  │Flash │ │Hardware     │          │  │
│  │  │OIS   │ │             │          │  │
│  │  └─────┘  └─────────────┘          │  │
│  └──────────────────────────────────────┘  │
├─────────────────────────────────────────┤
│              Camera Hardware                     │
└─────────────────────────────────────────┘

理解架构是深度开发的前提。当你遇到问题时,先定位问题发生在哪一层(UMD还是KMD),再定位是哪个模块(CRM还是IFE还是CPAS),最后用对应模块的调试命令深入排查——这就是架构驱动的调试方法论

更多Camera开发实战内容

欢迎加入知识星球「小驰成长圈」

120+ Camera工程师 · 340+ 实战内容 · 已运营1565天

小驰成长圈 知识星球

微信扫码 · 加入星球

欢迎扫码关注「小驰行动派」公众号 10 年Camera开发 | Camera技术干货 | 行业洞察 | Camera实战分享
小驰行动派公众号 扫一扫关注
分享到: 复制链接
← 上一篇 Camera提Case全流程:从日志采集到问题闭环 下一篇 → Camera开发实用调试工具箱

推荐课程

想系统学习 Camera 开发?看看这些课程

评论 (0)

暂无评论,快来抢沙发吧