2、高通平台AF架构:高通Camera子系统概览、AF算法模块位置、AF与ISP/CPP的交互
好,咱们正式进入高通平台AF架构这一章。说实话,很多做AF的工程师干了两年,可能都没搞明白自己写的代码到底跑在哪个核上、数据是怎么流转的。我刚开始接触高通平台时也踩过这个坑——调了半天AF参数,结果发现算法根本没被调用,因为ISP pipeline根本没把统计数据送过来。
这一章,我就带你把这个架构理清楚。你不需要记住每一行寄存器配置,但必须知道AF算法模块在哪儿、它跟ISP和CPP之间是怎么“对话”的。
2.1 高通Camera子系统整体架构
先看一张总览图。高通平台的Camera子系统,说白了就是三大块:传感器端(Sensor)、ISP处理管线、应用层/算法层。AF算法夹在中间,既要从ISP拿统计数据,又要通过CPP(Camera Post-Processor)把控制指令送回去。
核心要点:AF算法不是独立运行的,它依赖ISP提供的统计数据(如对比度值、相位差数据),并通过CPP或直接驱动VCM(音圈马达)来调整镜头位置。
这张图我建议你多看几遍。它把AF相关的数据流和控制流都画出来了。我个人习惯把这种图贴在工位上,调试时一眼就能定位问题出在哪个环节。
2.2 AF算法模块在系统中的位置
AF算法模块到底在哪儿?这个问题我问过不少新人,答案五花八门。有人说是ISP内部的硬件模块,有人说是CPP里的一个线程。其实都不完全对。
在高通平台上,AF算法模块是一个软件模块,运行在应用处理器(AP)侧,通常位于Camera HAL层或者一个独立的AF Daemon进程中。它不跑在ISP内部,也不跑在CPP内部。
| 层级 | 位置 | 职责 | 典型文件/模块 |
|---|---|---|---|
| 应用层 | Camera App | 发起AF请求、设置AF模式 | Java/Kotlin API |
| 框架层 | Camera HAL | 管理AF状态机、调用算法 | QCamera2/HAL3 |
| 算法层 | AF Algorithm Library | 执行搜索策略、计算对焦位置 | libaf.so / vendor.qti.hardware.camera.af |
| 驱动层 | Kernel Driver | 控制VCM、读取马达状态 | vcm驱动 / I2C |
我的经验:调试AF问题时,第一步就是确认AF算法库是否被正确加载。我遇到过好几次,因为权限问题导致libaf.so没加载成功,AF直接退化成固定焦距。用logcat | grep af看一眼就能发现。
2.3 AF与ISP的交互
AF算法要工作,首先得有“眼睛”——也就是统计数据。这些数据从哪里来?从ISP来。
ISP在每一帧图像处理过程中,会计算出一组统计信息,包括但不限于:
- 对比度统计(Focus Value):对指定ROI区域做高通滤波,得到清晰度评价值
- 相位差统计(PDAF):从双像素或相位检测点提取相位偏移量
- 亮度统计:用于判断场景光照条件
这些统计信息会被打包成一个结构体,通过Meta Data或者专用Buffer传递给AF算法模块。我见过最典型的坑是:ISP统计窗口配置错了,AF算法拿到的数据全是零,还以为是算法有问题。
注意:ISP统计信息的输出频率不一定跟帧率完全一致。有些平台为了省电,会降低统计信息的更新率。如果你的AF算法发现数据“卡住”了,先检查ISP的统计输出配置,别急着改算法参数。
2.4 AF与CPP的交互
AF算法算出目标位置后,怎么让镜头动起来?这就轮到CPP出场了。
CPP(Camera Post-Processor)在高通平台上负责后处理任务,同时也承担了一部分VCM控制的职责。AF算法通过CPP提供的接口,把目标位置写入VCM驱动寄存器,驱动马达移动镜头。
交互流程大致如下:
- AF算法计算出新的对焦位置(比如:当前镜头在200步,目标位置在350步)
- AF算法通过CPP的
setFocusPosition()接口下发指令 - CPP将位置值写入VCM驱动(通常通过I2C或SPI总线)
- VCM驱动控制马达移动到指定位置
- 马达到位后,VCM驱动返回状态(成功/失败/超时)
// 伪代码示例:AF算法通过CPP下发对焦位置
void af_algorithm_process(af_stats_t *stats) {
int32_t target_position;
// 1. 根据统计数据计算目标位置
target_position = calculate_focus_position(stats);
// 2. 通过CPP接口下发
cpp_set_focus_position(target_position);
// 3. 等待马达到位(或异步回调)
wait_for_motor_ready(50); // 最多等50ms
}
关键点:AF算法和CPP之间的通信是异步的。算法下发位置后,不会阻塞等待马达到位,而是继续处理下一帧的统计数据。马达到位后通过中断或回调通知AF算法。这个机制如果不理解,很容易写出“卡帧”的AF逻辑。
2.5 数据流与控制流总结
我把整个AF相关的数据流和控制流整理成一个表格,方便你对照理解:
| 步骤 | 数据/控制 | 源 | 目标 | 说明 |
|---|---|---|---|---|
| 1 | RAW图像数据 | Sensor | ISP | 原始数据输入ISP管线 |
| 2 | AF统计信息 | ISP | AF算法 | 对比度/PDAF/亮度等 |
| 3 | 对焦位置指令 | AF算法 | CPP | 目标位置值 |
| 4 | VCM控制信号 | CPP | VCM驱动 | I2C/SPI写入寄存器 |
| 5 | 马达状态反馈 | VCM驱动 | AF算法 | 到位/失败/超时 |
嗯,到这里你应该对高通平台的AF架构有了一个整体的认识。说白了,AF算法就是个“中间人”——从ISP拿数据,算一算,然后告诉CPP怎么动镜头。搞清楚了谁给你数据、你把数据给谁,调试起来就顺了。
避坑指南:我曾经在一个项目上花了三天时间调AF,结果发现是ISP的统计输出使能位没置起来。从那以后,我每次调试AF都先检查三个地方:ISP统计是否使能、统计窗口是否在ROI内、CPP的VCM驱动是否注册成功。这三个点检查完,80%的问题都能定位到。