高通Camera HAL层开发项目实战 - 第2节
2.1 HAL1 与 HAL3 架构对比
Camera HAL(硬件抽象层)是 Android 相机框架中连接上层 Camera Service 与底层硬件驱动的关键中间层。高通平台从 Android 5.0 开始全面转向 HAL3 架构,但理解 HAL1 与 HAL3 的差异仍然是开发者的基本功。
2.1.1 架构演进背景
HAL1 是 Android 早期(4.x 及之前)的相机抽象层设计,采用“单线程、单会话”模型,每次只能打开一个 Camera Device,且预览、拍照、录像等操作串行执行。HAL3 从 Android 5.0 引入,基于“请求-结果”管道模型,支持多会话、多流并发、逐帧控制,是高通平台现代相机 HAL 开发的基础。
关键认知: 高通平台从 MSM8996(骁龙820)开始,Camera HAL 强制使用 HAL3 架构。HAL1 仅在 legacy 模式或部分低端平台保留兼容层。
2.1.2 核心差异对比表
| 对比维度 | HAL1 | HAL3 |
|---|---|---|
| 架构模型 | 函数调用 + 回调 | 异步请求-结果管道 |
| 并发能力 | 单设备、单流 | 多设备、多流并发 |
| 控制粒度 | 粗粒度(打开/关闭/参数设置) | 逐帧控制(per-frame settings) |
| 数据通路 | 预览/拍照/录像分离 | 统一 Stream 抽象 |
| Buffer 管理 | Gralloc 直接分配 | BufferQueue + 生产者-消费者 |
| 高通适配 | mm-camera 框架 | CamX + ChiAPI 框架 |
| 延迟特性 | 高延迟(~100ms) | 低延迟(~30ms) |
2.1.3 HAL1 vs HAL3 架构对比图
开发建议: 在高通平台新项目中,始终以 HAL3 为开发目标。HAL1 仅用于兼容旧平台或快速原型验证,生产环境不建议使用。
2.2 Camera Device 详解
Camera Device 是 HAL3 架构中代表物理或逻辑相机的核心对象。每个 Camera Device 对应一个 camera_id,通过 open() 调用创建,负责管理该相机的所有操作。
2.2.1 Camera Device 生命周期
- 初始化: HAL 加载
camera_module_t,调用get_camera_info()获取设备信息,然后open()创建 Device 实例。 - 配置: 通过
configure_streams()设置输出流集合,建立 Session。 - 运行: 接收 Capture Request,处理并返回 Capture Result。
- 销毁:
close()释放资源,Device 实例失效。
2.2.2 Camera Device 核心接口
// HAL3 Camera Device 核心接口定义(简化)
typedef struct camera3_device_ops {
// 配置输出流
int (*configure_streams)(const struct camera3_device *device,
camera3_stream_configuration_t *stream_list);
// 提交捕获请求
int (*process_capture_request)(const struct camera3_device *device,
camera3_capture_request_t *request);
// 获取元数据
int (*get_metadata)(const struct camera3_device *device,
uint32_t frame_number,
camera3_capture_result_t *result);
// 通知错误/事件
void (*notify)(const struct camera3_device *device,
const camera3_notify_msg_t *message);
// 刷新待处理请求
int (*flush)(const struct camera3_device *device);
// 销毁设备
void (*close)(struct camera3_device *device);
} camera3_device_ops_t;
2.2.3 Camera Device 状态机
常见陷阱: 在 ACTIVE 状态下直接调用
close() 而不先 flush(),会导致未完成的 Capture Request 丢失,可能引发 Buffer 泄漏或 ISP 挂起。高通平台建议先 flush() 再 close()。
2.3 Camera Session 机制
Camera Session 是 HAL3 中管理 Capture Request 生命周期的逻辑单元。一个 Session 对应一次 configure_streams() 调用,包含一组配置好的 Stream 集合。Session 负责协调 Request 的提交、处理和结果返回。
2.3.1 Session 与 Device 的关系
- 一对一: 一个 Camera Device 在同一时刻只能有一个活跃的 Session。
- 生命周期: Session 从
configure_streams()开始,到下一次configure_streams()或close()结束。 - 重配置: 切换分辨率或帧率时,需要销毁旧 Session 并创建新 Session。
2.3.2 Session 工作流程
- 配置阶段: 应用层通过
configure_streams()指定输出 Stream 列表(预览、拍照、录像等)。 - 请求阶段: 应用层提交
camera3_capture_request_t,包含目标 Stream、元数据设置、Buffer 句柄。 - 处理阶段: HAL 将 Request 分发给 ISP 管线,逐帧处理。
- 结果阶段: HAL 通过回调返回
camera3_capture_result_t,包含输出 Buffer 和元数据。
2.3.3 Session 状态转换图
性能要点: 高通平台建议在 Session 中保持至少 3~5 个 Request 的流水线深度(pipeline depth),以充分利用 ISP 并行处理能力,避免 CPU 等待造成帧率下降。
2.4 Camera Stream 详解
Camera Stream 是 HAL3 中定义输出数据通路的抽象概念。每个 Stream 代表一路独立的图像输出,具有特定的分辨率、格式、用途和 Buffer 管理方式。
2.4.1 Stream 类型
| Stream 类型 | 用途 | 典型格式 | Buffer 方向 |
|---|---|---|---|
| CAMERA3_STREAM_OUTPUT | 预览、录像、拍照输出 | NV12, YUV420, JPEG | HAL → 应用 |
| CAMERA3_STREAM_INPUT | 输入流(如重处理) | NV12, YUV420 | 应用 → HAL |
| CAMERA3_STREAM_BIDIRECTIONAL | 双向流(少见) | NV12 | 双向 |
2.4.2 Stream 配置参数
// Stream 配置结构体(关键字段)
typedef struct camera3_stream {
// 流类型:OUTPUT / INPUT / BIDIRECTIONAL
int stream_type;
// 图像宽度(像素)
uint32_t width;
// 图像高度(像素)
uint32_t height;
// 像素格式:HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED 等
int format;
// 使用位掩码:GRALLOC_USAGE_HW_TEXTURE 等
uint32_t usage;
// 最大缓冲数(HAL 可修改)
uint32_t max_buffers;
// 私有数据(高通扩展字段)
void *priv;
// 数据空间(颜色空间)
android_dataspace_t data_space;
// 旋转角度
int rotation;
// 物理相机 ID(多摄场景)
const char *physical_camera_id;
} camera3_stream_t;
2.4.3 多 Stream 并发架构图
2.4.4 Stream 配置最佳实践
高通平台 Stream 配置要点:
- 格式选择: 预览和录像优先使用
HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED,让 HAL 选择最优格式;拍照使用HAL_PIXEL_FORMAT_BLOB(JPEG)。 - Buffer 数量: 预览流建议 4~6 个 Buffer,录像流建议 6~8 个 Buffer,拍照流 2~3 个 Buffer。
- 分辨率对齐: 高通 ISP 对宽度和高度有对齐要求(通常 16 或 32 像素对齐),非对齐尺寸会导致性能下降。
- 多流限制: 同一 Session 中 Stream 数量受 ISP 管线资源限制,骁龙 8 系列通常支持 3~5 路并发输出。
2.5 三者的协作关系
Camera Device、Camera Session、Camera Stream 三者构成 HAL3 架构的核心三角:
- Device 是硬件抽象实体,负责生命周期管理。
- Session 是逻辑会话单元,负责请求调度和结果分发。
- Stream 是数据通路定义,负责 Buffer 管理和格式转换。
2.5.1 协作流程图
开发口诀: “Device 管生管死,Session 管调度,Stream 管数据”。理解这三者的职责边界,是写出稳定 HAL 代码的第一步。