2. QCOM Camera HAL 架构分析:模块划分与关键数据结构

Qualcomm Camera HAL 是 Android 平台上最成熟、最复杂的 Camera 实现之一。从 Android N 开始,QCOM 逐步从传统的 mm-camera 架构向 chi-cdk (Camera Hardware Interface - Camera Development Kit) 架构演进。理解这两大模块的划分、关键数据结构与核心流程,是后续进行 MTK 平台适配的基础。

学习提示: 本章重点在于理解 QCOM Camera HAL 的“双模块”设计哲学——mm-camera 负责底层硬件抽象与 ISP 管线,chi-cdk 负责上层算法插桩与 vendor tag 管理。两者通过 UMD (User Mode Driver) 与 KMD (Kernel Mode Driver) 的边界进行交互。

2.1 模块划分:mm-camera vs. chi-cdk

QCOM Camera HAL 的软件栈可以划分为两大核心模块,它们在职责、代码位置和生命周期上存在显著差异:

对比维度 mm-camera (传统模块) chi-cdk (新架构模块)
引入时间 Android 4.x ~ 8.x 主流 Android 9+ 逐步取代
核心职责 底层 ISP 管线控制、Sensor 驱动、Stats 处理 上层算法插桩、Vendor Tag 管理、Session 配置
代码形态 共享库 (libmmcamera_*.so) CHI 模块 + CDK 插件 (.so)
与 Framework 接口 通过 camera_module_t 直接对接 通过 camera3_device_t + CHI API 对接
算法集成方式 硬编码在模块内部 通过 XML 配置 + 插件化加载
调试复杂度 较高,需整体编译 较低,支持独立更新算法库
架构演进关键点: chi-cdk 的引入本质上是将“硬件控制”与“算法策略”解耦。mm-camera 仍然负责底层的帧处理,但上层策略(如 3A 算法、HDR 策略)通过 CHI 的 Usecase 和 Pipeline 配置进行动态组合。

2.2 关键数据结构

在 QCOM Camera HAL 中,有几个核心数据结构贯穿整个请求-响应流程,理解它们是读懂代码的关键:

  • mm_camera_vtbl_t:mm-camera 层的虚函数表,封装了 open、close、ops_register 等底层操作接口。
  • camera3_device_t:Android Camera HAL3 标准设备结构体,QCOM 通过 qcamera_device 对其进行扩展。
  • chi_ops_t:CHI 核心操作结构体,包含 open_session、pipeline_create、submit_request 等接口。
  • camera_metadata_t:Android 标准元数据,QCOM 通过 vendor tag 扩展了大量私有控制项。
  • stream_info_t:流信息结构体,描述 YUV/RAW/JPEG 等 stream 的格式、分辨率、buffer 句柄。
// 核心数据结构示例:qcamera_device 扩展
typedef struct {
    camera3_device_t          base;         // 标准 HAL3 设备
    mm_camera_vtbl_t         *camera_handle; // 指向底层 mm-camera 实例
    chi_ops_t                *chi_ops;      // CHI 操作接口
    camera_metadata_t        *static_metadata; // 静态能力元数据
    pthread_mutex_t           lock;         // 设备锁
    uint32_t                  open_session; // 当前打开的 session 数
} qcamera_device_t;

2.3 核心流程:从 Request 到 Frame

一个典型的 Camera 请求处理流程在 QCOM HAL 中分为三个阶段:

  1. Session 创建与 Pipeline 配置:Framework 下发 configure_streams,HAL 根据 stream 配置创建 CHI session 并绑定 mm-camera pipeline。
  2. Request 提交与参数处理:process_capture_request 被调用,HAL 将 Android 元数据转换为 CHI vendor tag,并填充到 request 结构体中。
  3. Frame 回调与结果返回:mm-camera 完成 ISP 处理后,通过 CHI 回调将 result metadata 和 buffer 返回给 Framework。
常见适配陷阱: 在从 QCOM 向 MTK 移植时,最容易出问题的是 vendor tag 的映射。QCOM 使用 com.qcom.* 命名空间,而 MTK 使用 com.mediatek.*。如果上层算法库直接依赖 QCOM 私有 tag,需要做一层“tag 翻译层”。
QCOM Camera HAL 请求处理流程 QCOM Camera HAL 请求处理流程 Android Framework CHI-CDK (Usecase) mm-camera (UMD) KMD + ISP 硬件 流程说明 1. Framework 下发 request 2. CHI 解析 metadata 并配置 pipeline 3. mm-camera 填充 request 到 UMD 4. KMD 驱动 ISP 处理帧 5. 结果通过回调链返回 回调结果

2.4 mm-camera 内部模块详解

mm-camera 内部并非单一模块,而是由多个独立的子模块组成,每个子模块负责 ISP 管线中的一个特定阶段:

  • sensor:负责 Sensor 驱动、帧率控制、曝光行配置。
  • isp:图像信号处理核心,包括 BPC、AWB、Gamma 校正等。
  • stats:统计信息处理,输出 3A 算法所需的 AE/AWB/AF 统计数据。
  • imglib:图像后处理库,如 HDR 合成、多帧降噪。
  • cpp:Color Processing Pipeline,负责 YUV 转换与色彩增强。
// mm-camera 模块注册示例
static mm_camera_module_t g_sensor_module = {
    .name = "sensor",
    .init = sensor_module_init,
    .process = sensor_module_process,
    .deinit = sensor_module_deinit,
};

// 在 HAL 初始化时注册
mm_camera_module_register(&g_sensor_module);

2.5 chi-cdk 的 Usecase 与 Pipeline 模型

chi-cdk 引入了一种“Usecase + Pipeline”的配置模型,使得算法组合更加灵活:

概念 说明 示例
Usecase 定义一种拍照场景的完整行为,包括输入流、输出流、算法链 PreviewUseCase, HDRUseCase
Pipeline Usecase 内部的一条具体处理路径,包含多个 Node MainPipeline, AuxPipeline
Node Pipeline 中的最小处理单元,对应一个算法或硬件模块 SensorNode, ISPNode, StatsNode
Link 定义 Node 之间的数据流连接关系 SensorNode → ISPNode → StatsNode
适配启示: MTK 的 Camera HAL 也采用了类似的“Pipeline”概念(称为 P1/P2 管线)。理解 QCOM 的 Usecase 模型,有助于在 MTK 上快速定位对应的 Pipeline 配置入口。
chi-cdk Usecase 与 Pipeline 结构 chi-cdk Usecase 与 Pipeline 结构 Usecase: HDRUseCase Pipeline: MainPipeline SensorNode ISPNode StatsNode Pipeline: AuxPipeline HDRNode MergeNode Node 之间通过 Link 连接 数据流由 CHI 引擎调度

2.6 关键流程:configure_streams 与 request 提交

以下代码展示了 QCOM HAL 中 configure_streams 的核心逻辑,注意 CHI session 的创建时机:

// QCOM HAL configure_streams 简化实现
int qcamera_device_configure_streams(
    camera3_device_t *device,
    camera3_stream_configuration_t *stream_list)
{
    qcamera_device_t *qc_dev = (qcamera_device_t *)device;

    // 1. 解析 stream 配置,确定 Usecase 类型
    chi_usecase_type_t usecase = get_usecase_from_streams(stream_list);

    // 2. 创建 CHI session
    chi_session_descriptor_t session_desc;
    qc_dev->chi_ops->open_session(&session_desc);

    // 3. 根据 Usecase 创建 Pipeline
    for (int i = 0; i < stream_list->num_streams; i++) {
        chi_pipeline_descriptor_t pipeline;
        pipeline.stream = stream_list->streams[i];
        qc_dev->chi_ops->pipeline_create(session_desc, &pipeline);
    }

    // 4. 通知 mm-camera 底层配置 ISP
    mm_camera_configure_pipeline(qc_dev->camera_handle, stream_list);

    return 0;
}
调试技巧: 在 QCOM 平台上,可以通过 adb shell dumpsys media.camera 查看当前活跃的 Usecase 和 Pipeline 状态。如果遇到 configure_streams 失败,优先检查 stream 的 format 和 resolution 是否在 sensor 的 native 能力范围内。

2.7 本章小结

QCOM Camera HAL 的架构核心在于 mm-camera 与 chi-cdk 的分层协作:mm-camera 提供底层的 ISP 管线控制,chi-cdk 提供上层的算法编排能力。关键数据结构如 qcamera_device_t 和 chi_ops_t 是连接这两层的桥梁。理解 Usecase + Pipeline 的配置模型,是后续进行 MTK 平台适配时进行概念映射的基础。