2. CaptureRequest 数据结构详解

在 Android Camera HAL3 架构中,CaptureRequest 是连接上层应用与底层硬件驱动的最核心数据载体。每一次拍照、预览或录像,本质上都是构建一个或多个 CaptureRequest 并提交给 Camera HAL 处理。理解其内部结构,是进行参数校验和链路异常定位的基础。

核心认知: CaptureRequest 是一个“命令包”,它告诉 HAL 三件事——用什么参数、拍哪张照片、结果放到哪里。

2.1 整体结构总览

一个标准的 CaptureRequest 包含以下五个核心字段,它们共同定义了单次图像捕获的完整语义:

字段 类型 必选/可选 核心作用
request ID int32_t 必选 唯一标识一次捕获请求,用于结果回传时的匹配
settings ACameraMetadata 必选 包含所有控制参数(AE/AWB/AF、传感器模式、输出尺寸等)
output buffers buffer_handle_t 数组 必选 指定图像数据写入的目标缓冲区(Surface/ANativeWindow)
input buffers buffer_handle_t 数组 可选 指定输入缓冲区(用于 reprocess 场景,如 ZSL、美颜)
physical camera settings ACameraMetadata 数组 可选 多摄场景下,为物理摄像头单独指定的参数覆盖
调试提示: 在 HAL3 链路中,process_capture_request() 函数收到的第一个参数就是 camera3_capture_request_t 结构体。该结构体与上表中的字段一一对应,是驱动层解析请求的入口。
CaptureRequest 数据结构全景图 CaptureRequest request ID settings output buffers input buffers physical
settings 字段说明: • request ID:单调递增的整数,用于匹配 request 与 result,异常时可通过 ID 回溯链路。 • settings:核心参数集合,包含 200+ 个 key-value 对,是参数校验的主要战场。 • output buffers:至少 1 个,最多 32 个(取决于 HAL 能力),每个 buffer 对应一个 Surface。 • input buffers:仅 reprocess 请求需要,用于输入原始图像数据。 • physical camera settings:逻辑摄像头下,为不同物理摄像头指定差异化参数。

2.2 request ID:链路的“身份证”

request ID 是一个单调递增的 32 位无符号整数,由 Camera Framework 在构建请求时自动分配。它在 HAL3 链路中承担两个关键角色:

  • 请求-结果匹配: HAL 在完成捕获后,通过 camera3_capture_result_t 结构体返回结果,其中包含相同的 frame_number(即 request ID),Framework 据此将结果与原始请求关联。
  • 异常回溯锚点: 当出现 buffer 超时、参数无效或 HAL 崩溃时,log 中记录的 request ID 是定位问题发生时刻的唯一线索。
常见异常: 如果 HAL 返回的 frame_number 与 Framework 期望的不一致,会导致 result callback 无法匹配,进而引发 ANR 或预览黑屏。调试时务必检查 ID 是否连续、无跳变。

2.3 settings:参数校验的核心战场

settings 是一个 ACameraMetadata 对象,本质上是 key-value 对的集合。每个 key 对应一个 camera_metadata_tag_t,value 可以是 int32、float、int64、double、rational 或它们的数组。

根据作用域,settings 中的参数可分为三类:

参数类别 示例 Tag 校验要点
3A 参数 ANDROID_CONTROL_AE_MODE
ANDROID_CONTROL_AF_MODE
ANDROID_CONTROL_AWB_MODE
值必须在 available 列表中;OFF 模式下需提供手动值
传感器参数 ANDROID_SENSOR_EXPOSURE_TIME
ANDROID_SENSOR_SENSITIVITY
ANDROID_SENSOR_FRAME_DURATION
必须在 min/max 范围内;帧时长不能小于曝光时间
输出参数 ANDROID_SCALER_CROP_REGION
ANDROID_SCALER_ROTATION
ANDROID_STATISTICS_FACE_DETECT_MODE
crop region 必须在 active array 内;旋转角度必须为 0/90/180/270
调试经验: 70% 的 CaptureRequest 校验失败发生在 settings 阶段。建议在 HAL 的 process_capture_request() 入口处,打印 settings 中所有非默认值的 key,与 HAL 的 static_metadata 进行交叉比对。
Settings 参数校验流程 解析 settings 遍历 key-value 校验合法性 返回结果 值在可用范围内? 是 否 返回错误码 继续下一项 全部通过

2.4 output buffers:图像数据的“目的地”

output buffers 是一个 buffer_handle_t* 数组,每个元素对应一个待填充的图像缓冲区。这些缓冲区通常来自 Surface 或 ANativeWindow,由 Framework 的 Stream 配置阶段预先分配。

在 HAL3 中,output buffers 的配置遵循以下规则:

  • 数量限制: 每个 request 的 output buffers 数量不能超过 ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS(通常为 3~4 个)。
  • 格式匹配: buffer 的格式(如 YUV420_888、JPEG、RAW10)必须与创建 Stream 时声明的格式一致。
  • 尺寸匹配: buffer 的宽高必须与 Stream 配置的尺寸完全一致,否则 HAL 会拒绝写入。
  • 生命周期: HAL 在 process_capture_request() 中获取 buffer 的 handle,在 process_capture_result() 中释放。Framework 负责 buffer 的分配与回收。
异常定位技巧: 如果 HAL 返回 CAMERA3_BUFFER_STATUS_ERROR,首先检查 output buffers 的 handle 是否为 NULL,其次检查 buffer 的 stride 是否与 HAL 期望的对齐要求一致。

2.5 input buffers:reprocess 场景的“原料”

input buffers 仅在 reprocess 请求中出现,用于提供需要重新处理的原始图像数据。典型场景包括:

  • ZSL(零快门延迟): 从环形缓冲区中取出之前捕获的 RAW 图,重新处理为 JPEG。
  • 美颜/滤镜: 对已拍好的 YUV 图进行二次处理,输出新的 YUV 或 JPEG。
  • 多帧合成: 输入多张 RAW 图,输出一张 HDR 或超分辨率结果。

input buffers 的校验要点:

校验项 要求 异常后果
buffer 非空 reprocess 请求必须提供 input buffer HAL 返回 NULL 指针,链路中断
格式兼容 input 格式必须与 HAL 声明的 reprocess 能力匹配 HAL 拒绝处理,返回错误
时间戳有效 input buffer 的 timestamp 必须在合理范围内 3A 同步失败,图像颜色/亮度异常

2.6 physical camera settings:多摄场景的“参数覆盖”

在逻辑摄像头(Logical Camera)架构下,一个 CaptureRequest 可能对应多个物理摄像头(Physical Camera)。physical camera settings 允许为每个物理摄像头单独指定参数,覆盖逻辑摄像头 settings 中的全局值。

典型使用场景:

  • 主摄+广角同时输出: 主摄使用 ANDROID_CONTROL_AE_MODE_ON,广角使用 ANDROID_CONTROL_AE_MODE_OFF 并手动设置曝光时间。
  • 景深计算: 主摄输出彩色图,副摄输出黑白图,各自使用不同的 sensor 增益和帧率。
调试要点: 当启用 physical camera settings 时,务必检查 ANDROID_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS 中声明的 key 列表。只有列表中的 key 才能在 physical settings 中被覆盖,否则 HAL 会忽略该设置。
Physical Camera Settings 覆盖机制 Logical Camera Settings Physical Camera 0 Physical Camera 1 Physical Camera 2 physical camera settings 中的 key 会覆盖 logical settings 中的同名 key,未指定的 key 则继承 logical settings 的值。

2.7 数据结构在 HAL3 链路中的流转

理解 CaptureRequest 的五个字段后,需要掌握它们在 HAL3 链路中的完整流转路径:

  1. Framework 构建: CameraService 根据应用层请求,组装 CaptureRequest,分配 request ID,填充 settings 和 buffers。
  2. HAL 接收: HAL 的 process_capture_request() 被调用,传入 camera3_capture_request_t 指针。
  3. 参数校验: HAL 内部校验 settings 的合法性,检查 output buffers 的有效性,解析 physical camera settings。
  4. 硬件执行: HAL 将参数下发到 ISP 和传感器驱动,开始曝光和图像处理。
  5. 结果回传: HAL 通过 process_capture_result() 返回 camera3_capture_result_t,包含相同的 request ID 和填充后的 buffers。
关键检查点: 在步骤 3 中,如果 HAL 发现 settings 中的某个 key 值超出 static_metadata 声明的范围,必须返回 CAMERA3_MSG_ERROR_REQUEST 错误,并停止处理该 request。这是参数校验的最后一道防线。
CaptureRequest 在 HAL3 链路中的流转 ① Framework 构建请求 ② HAL 接收 process_request ③ 参数校验 settings/buffers ④ 硬件执行 ISP + Sensor ⑤ 结果回传 process_result 异常定位关键节点: • 步骤②:检查 HAL 是否成功解析 request 结构体,重点关注 input/output buffers 的 handle 有效性。 • 步骤③:settings 校验失败时,HAL 应返回错误码,此时需检查 log 中的 key 值越界信息。 • 步骤⑤:result 中的 request ID 必须与原始请求一致,否则 Framework 侧会丢弃结果。

2.8 常见异常与调试建议

基于 CaptureRequest 数据结构的特性,以下是实际调试中最高频的异常场景及应对策略:

异常现象 根因分析 调试命令/方法
预览黑屏,log 显示 buffer 错误 output buffers 的 handle 为 NULL,或格式/尺寸不匹配 在 HAL 的 process_capture_request 中打印每个 buffer 的 handle、width、height、format
拍照后 JPEG 花屏 settings 中的 JPEG 质量参数超出范围,或 output buffer 的 stride 不对齐 检查 ANDROID_JPEG_QUALITY 是否在 [1,100] 内;检查 buffer 的 stride 是否 16 字节对齐
多摄切换时卡顿 physical camera settings 中指定了不支持的 key 对比 ANDROID_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS 与实际设置的 key 列表
reprocess 请求失败 input buffer 的时间戳与当前 3A 状态不匹配 打印 input buffer 的 timestamp,与 HAL 内部的 sensor 时间戳进行比对
总结: CaptureRequest 的五个字段——request ID、settings、output buffers、input buffers、physical camera settings——构成了 HAL3 链路中数据流动的完整骨架。掌握每个字段的语义、校验规则和常见异常模式,是进行参数校验和链路异常定位的第一步,也是最重要的一步。