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天

相关推荐
hunterandroid2 小时前
[Android 从零到一] Custom View 触摸反馈与手势冲突解决
android
coderSong25683 小时前
Android | 四大组件之 BroadcastReceiver(广播接收器)
android
爱笑鱼5 小时前
Android 系统启动机制(二):init.rc 不是普通脚本,service、action 和 property 怎样驱动启动?
android
新鲜势力呀6 小时前
深入理解 Elliot CUDA 编程核心:PHP 实现 CUDA 并行计算思想与实践
android·开发语言·php
2501_916007476 小时前
申请 iOS 推送证书并配置 APNs 群发推送教程
android·ios·小程序·https·uni-app·iphone·webview
恋猫de小郭6 小时前
Flutter 3.47 首坑,analysis_options 问题连环回归
android·前端·flutter
ue星空8 小时前
第一个安卓程序
android
淡淡的香烟8 小时前
Androidiot蓝牙配网简单封装
android·物联网
gxgldyh8 小时前
Android Framework源码解析(九):App进程诞生全流程——从AMS请求到Zygote fork源码深度拆解
android·framework·zygote·android 启动流程·android app创建流程