Camera HAL3 的 Metadata 机制 是其实现强大、灵活的 Per-Frame Control(逐帧控制) 能力的核心。它本质上是一个结构化的键值对(Tag-Value)数据容器,承载着相机系统的配置、状态和结果信息,在应用程序(APP)、框架(Framework, FWK)和硬件抽象层(HAL)之间高效穿梭。
以下是其机制的详细解释:
1. Metadata 的本质和作用:信息容器与穿梭桥梁
- 结构化数据容器: Metadata 不是原始图像数据(YUV, RAW),而是描述图像数据如何被捕获和处理、相机当前状态是什么、以及捕获结果如何的关键信息集合。它使用预定义的 Tag(标签/枚举) 来索引对应的 Value(值)。
- 标准化通信语言: 它定义了一套 APP、FWK、HAL 三方都能理解和操作的标准数据格式和语义。这使得不同厂商的 HAL 实现能够与 Android 相机框架和应用程序无缝协作。
- 穿梭作用:metadata分成control、dynamic以及static三类
- (Request)APP -> FWK -> HAL : APP 通过 Metadata (
CaptureRequest
) 向 FWK 和 HAL 传达其拍摄意图和具体参数要求(例如:曝光时间、感光度 ISO、对焦模式、目标区域、处理参数等)。FWK 会进行权限检查、参数合理性校验和可能的转换/补全,然后将请求 Metadata 传递给 HAL。 - (Result)HAL -> FWK -> APP : HAL 执行完一个 CaptureRequest 后,将捕获的结果状态、实际使用的参数、以及图像相关的动态信息填充到 Metadata (
CaptureResult
) 中,通过 FWK 返回给 APP。FWK 可能也会添加一些框架层面的信息。 - (Static)HAL -> FWK -> APP : 设备启动或相机首次打开时,HAL 会向 FWK 提供描述相机设备固有能力和限制的静态 Metadata。FWK 缓存这些信息并提供给 APP 查询。这些信息在相机会话期间通常不会改变。
- (Request)APP -> FWK -> HAL : APP 通过 Metadata (
- 承载信息类型: Metadata 承载的信息极其丰富,包括但不限于:
- 控制参数(曝光、对焦、白平衡、闪光灯、降噪、畸变校正等)
- 传感器信息(尺寸、像素阵列、原始模式支持等)
- 镜头信息(焦距、光圈范围、光学防抖能力等)
- 处理单元信息(支持的 YUV/RAW 格式、最大分辨率、后处理效果等)
- 3A 状态(AE/AF/AWB 的当前模式、锁定状态、区域等)
- 捕获结果(时间戳、帧号、实际使用的曝光/增益、3A 收敛状态、陀螺仪数据等)
- 设备特性(支持的硬件等级、能力枚举等)
2. Metadata 的三类划分及其在 Per-Frame Control 中的角色
为了实现高效的逐帧控制,Metadata 被逻辑上划分为三类,每类有不同的生命周期和作用域:
- a. Static Metadata:
- 定义: 描述相机设备固有的、不可变的物理特性和能力限制。在相机设备初始化(首次打开或设备启动)时,由 HAL 生成并上报给 FWK。
- 内容示例:
android.lens.info.availableApertures
(可用光圈值列表)android.sensor.info.activeArraySize
(有效像素阵列尺寸)android.sensor.info.physicalSize
(传感器物理尺寸)android.sensor.info.pixelArraySize
(像素阵列总尺寸)android.sensor.info.sensitivityRange
(ISO 感光度范围)android.sensor.info.exposureTimeRange
(曝光时间范围)android.jpeg.maxSize
(JPEG 最大支持分辨率)android.request.availableCapabilities
(支持的硬件等级和能力,如 RAW, MANUAL_SENSOR, BURST_CAPTURE 等)android.colorCorrection.availableAberrationModes
(支持的色差校正模式)android.control.maxRegions
(对焦/测光/AWB 区域的最大支持数量)
- 作用与 Per-Frame Control:
- 为 APP 和 FWK 提供决策依据。APP 需要知道设备支持哪些分辨率、哪些手动控制模式(如手动曝光)、哪些功能(如 RAW 捕获、光学防抖)才能构建有效的 CaptureRequest。
- FWK 根据 Static Metadata 来验证 APP 提交的 CaptureRequest 中的参数是否在设备能力范围内。
- 不参与逐帧变化,它在会话期间是常量,是构建有效动态控制的基础。
- Static Metadata 其实就是CameraCharacteristics,而CameraCharacteristics在CameraService 启动时,调用CameraProviderManager::initialize(),完成了deviceinfo的初始化,此时metadata 会被赋值给DeviceInfo::mCameraCharacteristics,当上层 Java 层调用 CameraManager.getCameraCharacteristics(cameraId)的时候,其实就把mCameraCharacteristics取出来给CameraCharacteristics。
- b. Control Metadata (CaptureRequest Metadata):
- 定义: 由 APP 主动设置并包含在
CaptureRequest
中,用于精确控制下一帧(或一组帧)的捕获和处理行为的参数。这是 APP 表达其拍摄意图的核心手段。 - 内容示例:
android.control.mode
(控制模式:OFF, AUTO, USE_SCENE_MODE, USE_TEMPLATE_*)android.control.aeMode
(自动曝光模式)android.control.afMode
(自动对焦模式)android.control.awbMode
(自动白平衡模式)android.control.aeExposureCompensation
(曝光补偿值)android.control.aeTargetFpsRange
(目标帧率范围)android.control.aeRegions
(自动测光区域)android.control.afRegions
(自动对焦区域)android.control.awbRegions
(自动白平衡区域)android.sensor.exposureTime
(手动设置的曝光时间 - 需要 MANUAL_SENSOR 能力)android.sensor.sensitivity
(手动设置的 ISO 感光度 - 需要 MANUAL_SENSOR 能力)android.lens.focusDistance
(手动设置的对焦距离 - 需要 MANUAL_SENSOR 能力)android.flash.mode
(闪光灯模式)android.noiseReduction.mode
(降噪模式)android.colorCorrection.mode
/android.colorCorrection.transform
/android.colorCorrection.gains
(色彩校正参数)android.scaler.cropRegion
(裁剪区域)
- 作用与 Per-Frame Control:
- 这是 Per-Frame Control 的“输入”。APP 可以且鼓励为每一帧设置不同的 Control Metadata,以实现诸如:
- HDR 连拍:交替设置不同的曝光时间 (
android.sensor.exposureTime
)。 - 高速对焦跟踪:持续更新对焦区域 (
android.control.afRegions
) 或对焦距离 (android.lens.focusDistance
)。 - 平滑曝光调整:逐步改变曝光补偿 (
android.control.aeExposureCompensation
)。 - 动态帧率切换:根据场景改变目标帧率 (
android.control.aeTargetFpsRange
)。 - 后处理效果切换:逐帧改变降噪强度或色彩风格。
- HDR 连拍:交替设置不同的曝光时间 (
- HAL 必须尽最大努力满足
CaptureRequest
中指定的 Control Metadata 参数。如果无法完全满足(如请求的曝光时间超出传感器范围),HAL 应使用最接近的有效值并在 Result Metadata 中报告实际使用的值。
- 这是 Per-Frame Control 的“输入”。APP 可以且鼓励为每一帧设置不同的 Control Metadata,以实现诸如:
- 定义: 由 APP 主动设置并包含在
CONTROL_AE_MODE 就是tag,只不过是java封装了一层,CONTROL_AF_MODE_CONTINUOUS_PICTURE是tag对应的value
- c. Dynamic Metadata (CaptureResult Metadata):
- 定义: 由 HAL 填充并包含在
CaptureResult
中,用于反馈与 特定帧 捕获和处理结果相关的实时状态和实际使用的参数。它描述了 HAL 执行完对应CaptureRequest
后的实际结果。 - 内容示例:
android.sensor.timestamp
(图像传感器开始曝光的精确时间戳 - 纳秒级)android.sensor.frameDuration
(该帧的实际曝光+读取时间)android.sensor.exposureTime
(该帧实际使用的曝光时间)android.sensor.sensitivity
(该帧实际使用的 ISO 感光度)android.lens.focusDistance
(该帧实际使用的对焦距离)android.lens.focalLength
(该帧使用的实际焦距 - 变焦镜头)android.lens.aperture
(该帧使用的实际光圈值 - 可变光圈镜头)android.lens.state
(镜头移动状态,如 STATIONARY, MOVING)android.control.aeState
(自动曝光当前状态:INACTIVE, SEARCHING, CONVERGED, LOCKED, FLASH_REQUIRED, PRECAPTURE)android.control.afState
(自动对焦当前状态)android.control.awbState
(自动白平衡当前状态)android.statistics.lensShadingMapMode
(实际使用的镜头阴影校正图模式)android.statistics.sceneFlicker
(检测到的场景闪烁频率)android.statistics.faces
(检测到的人脸信息)android.tonemap.curve
(实际应用的颜色映射曲线)- 陀螺仪、加速度计等传感器在该帧曝光时刻的数据(用于高级防抖或计算)
- 作用与 Per-Frame Control:
- 这是 Per-Frame Control 的“输出”和“反馈”。它为 APP 提供了:
- 实际执行结果: 确认 HAL 实际使用了哪些参数值(可能与 Request 略有不同)。
- 实时状态监控: 了解 3A (AE/AF/AWB) 算法当前的运行状态(如是否已收敛、是否在搜索中、是否需要闪光灯)。
- 精确的时间关联: 高精度时间戳 (
android.sensor.timestamp
) 是逐帧控制的关键,它允许 APP 将图像帧与手机运动传感器(陀螺仪、加速度计)在同一时刻的数据精确对齐,用于高级计算摄影(如计算光学防抖补偿、多帧合成时的运动估计)。 - 决策依据: APP 可以根据前一帧的 Dynamic Metadata(尤其是 3A 状态)来智能地调整下一帧的 Control Metadata,形成一个闭环控制。例如,如果 AE 状态是
SEARCHING
,APP 可能暂时不进行 HDR 连拍;如果 AF 状态是FOCUSED
,APP 可以锁定对焦。
- 这是 Per-Frame Control 的“输出”和“反馈”。它为 APP 提供了:
- 定义: 由 HAL 填充并包含在
3. Per-Frame Control 的工作流程(结合 Metadata)
- APP 查询 Static Metadata: APP 启动时或打开相机前,通过 FWK 获取设备的 Static Metadata,了解其能力。
- APP 创建 CaptureRequest:
- APP 创建一个新的
CaptureRequest
对象。 - APP 设置 Control Metadata (
request
): 根据当前拍摄意图(自动、手动、HDR、人像等)和从 Static Metadata 了解到的设备能力,设置所需的参数(曝光模式、ISO、对焦区域、裁剪、处理参数等)。关键:APP 可以为 每一帧 设置不同的 Control Metadata。 - APP 指定该 Request 的输出目标(Surface),如预览 Surface、拍照 Surface、RAW Surface。
- APP 创建一个新的
- APP 提交 Request 给 FWK: APP 将构建好的
CaptureRequest
提交给相机框架 (FWK)。 - FWK 处理 Request:
- FWK 进行权限检查、参数校验(参考 Static Metadata)、资源管理。
- FWK 可能对 Request 进行修改或补充(例如,确保必要的 Tag 被设置,或应用全局设置)。
- FWK 将 Request(包含 Control Metadata 和输出目标信息)加入待处理队列。
- FWK 传递 Request 给 HAL: FWK 从队列中取出 Request,将其(主要是 Control Metadata 和输出 Buffer 信息)传递给 Camera HAL。
- HAL 执行 Request:
- HAL 解析
CaptureRequest
中的 Control Metadata。 - HAL 驱动相机硬件(传感器、镜头、ISP)按照 Control Metadata 的要求进行单帧图像的捕获(曝光、对焦、变焦等)。
- HAL 将捕获到的图像数据(RAW 或处理后的 YUV)写入到 Request 指定的输出 Surface 对应的 Buffer 中。
- HAL 生成 CaptureResult:
- 收集该帧捕获过程中的实际使用的参数(可能与 Request 不同)。
- 收集该帧相关的动态状态信息(3A 状态、时间戳、传感器数据等)。
- 将以上信息填充到
CaptureResult
的 Dynamic Metadata 部分。 - (可选)HAL 可以包含一些额外的状态信息。
- HAL 解析
- HAL 返回 Result 给 FWK: HAL 将包含图像 Buffer 的句柄和填充好的
CaptureResult
(包含 Dynamic Metadata) 返回给 FWK。 - FWK 处理 Result:
- FWK 将图像 Buffer 分发到对应的 APP Surface。
- FWK 可能对
CaptureResult
进行补充(添加框架相关的信息或状态)。
- FWK 传递 Result 给 APP: FWK 将最终的
CaptureResult
(包含 Dynamic Metadata) 传递给 APP。 - APP 处理 Result:
- APP 接收到图像数据,进行显示(预览)或保存(拍照)。
- APP 解析
CaptureResult
中的 Dynamic Metadata:- 获取实际参数,确认执行效果。
- 监控 3A 状态 (
aeState
,afState
,awbState
)。 - 获取关键的高精度时间戳 (
sensor.timestamp
)。 - 获取传感器数据(用于防抖或多帧合成)。
- 基于 Dynamic Metadata 进行闭环决策: APP 分析当前帧的结果和状态,为 下一帧 或 后续帧 的
CaptureRequest
设置新的、可能不同的 Control Metadata,以实现更复杂的功能(如触发 HDR 连拍、调整对焦区域、平滑过渡曝光补偿)。这就是 Per-Frame Control 的精髓所在!
- 循环: APP 创建并提交新的
CaptureRequest
,流程回到步骤 2。这个过程持续进行,APP 通过不断调整 Control Metadata 并观察 Dynamic Metadata 反馈,实现对相机行为的细粒度、实时的逐帧控制。
4.帧控制的伪代码
// 1. 打开相机后,创建一个 CaptureRequest.Builder
CaptureRequest.Builder builder =
cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
// 添加预览输出 Surface
builder.addTarget(previewSurface);
// 2. 连续下发不同的 Request,模拟 Per-Frame Control
List<CaptureRequest> burstRequests = new ArrayList<>();
// 帧 1: 自动曝光 + 连续自动对焦
builder.set(CaptureRequest.CONTROL_AE_MODE,
CaptureRequest.CONTROL_AE_MODE_ON);
builder.set(CaptureRequest.CONTROL_AF_MODE,
CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
burstRequests.add(builder.build());
// 帧 2: 固定曝光时间 10ms,ISO 200,手动对焦
builder.set(CaptureRequest.CONTROL_MODE,
CaptureRequest.CONTROL_MODE_OFF); // 关闭 3A 自动
builder.set(CaptureRequest.SENSOR_EXPOSURE_TIME, 10_000_000L); // 10ms
builder.set(CaptureRequest.SENSOR_SENSITIVITY, 200); // ISO 200
builder.set(CaptureRequest.LENS_FOCUS_DISTANCE, 0.3f); // 对焦到 0.3 米
burstRequests.add(builder.build());
// 帧 3: 曝光时间 30ms,ISO 800,自动对焦
builder.set(CaptureRequest.SENSOR_EXPOSURE_TIME, 30_000_000L); // 30ms
builder.set(CaptureRequest.SENSOR_SENSITIVITY, 800); // ISO 800
builder.set(CaptureRequest.CONTROL_AF_MODE,
CaptureRequest.CONTROL_AF_MODE_AUTO);
burstRequests.add(builder.build());
// 3. 一次性发给 Camera HAL,逐帧执行
captureSession.captureBurst(
burstRequests,
new CameraCaptureSession.CaptureCallback() {
@Override
public void onCaptureCompleted(CameraCaptureSession session,
CaptureRequest request,
TotalCaptureResult result) {
// 每一帧都会回调对应的 Dynamic Metadata
long exposureTime = result.get(CaptureResult.SENSOR_EXPOSURE_TIME);
int iso = result.get(CaptureResult.SENSOR_SENSITIVITY);
int afState = result.get(CaptureResult.CONTROL_AF_STATE);
Log.d("PerFrame", "Frame done: exposure=" +
exposureTime + " iso=" + iso + " af=" + afState);
}
},
null
);
// HAL 接口:每来一帧,都会调用一次
int process_capture_request(camera3_device *device,
camera3_capture_request_t *request) {
// 取出这帧的 metadata(控制参数)
const camera_metadata_t *settings = request->settings;
CameraMetadata ctrlMeta(settings);
int64_t exposureTime = 0;
int32_t sensitivity = 0;
int32_t afMode = 0;
// 1. 解析 AE/曝光控制
if (ctrlMeta.exists(ANDROID_SENSOR_EXPOSURE_TIME)) {
exposureTime = ctrlMeta.find(ANDROID_SENSOR_EXPOSURE_TIME).data.i64[0];
applyExposure(exposureTime); // 应用到 ISP/传感器驱动
}
// 2. 解析 ISO
if (ctrlMeta.exists(ANDROID_SENSOR_SENSITIVITY)) {
sensitivity = ctrlMeta.find(ANDROID_SENSOR_SENSITIVITY).data.i32[0];
applyISO(sensitivity);
}
// 3. 解析 AF 模式
if (ctrlMeta.exists(ANDROID_CONTROL_AF_MODE)) {
afMode = ctrlMeta.find(ANDROID_CONTROL_AF_MODE).data.i32[0];
applyAfMode(afMode); // 设置对焦算法状态机
}
// 4. 实际驱动 sensor 输出一帧图像
BufferHandle buffer = request->output_buffers[0];
captureOneFrame(buffer, exposureTime, sensitivity, afMode);
// 5. 构造 Dynamic Metadata,反馈给上层
CameraMetadata result;
result.update(ANDROID_SENSOR_EXPOSURE_TIME, &exposureTime, 1);
result.update(ANDROID_SENSOR_SENSITIVITY, &sensitivity, 1);
result.update(ANDROID_CONTROL_AF_MODE, &afMode, 1);
camera3_capture_result captureResult;
memset(&captureResult, 0, sizeof(captureResult));
captureResult.frame_number = request->frame_number;
captureResult.result = result.release();
captureResult.num_output_buffers = 1;
captureResult.output_buffers = request->output_buffers;
// 回调给 Framework
callbacks->process_capture_result(callbacks, &captureResult);
return 0;
}
总结
Camera HAL3 的 Metadata 机制是一个强大、标准化的信息交换系统。通过将 Metadata 明确划分为 Static(设备能力)、Control(逐帧输入/意图)和 Dynamic(逐帧输出/结果/反馈)三类,它完美地支撑了 Per-Frame Control 的核心思想:
- Static Metadata 提供基础,定义可能性的边界。
- Control Metadata 赋予 APP 对每一帧参数的精确控制权,实现灵活多变的拍摄策略。
- Dynamic Metadata 提供每一帧执行后的真实反馈和精确时空信息(尤其是时间戳),使得 APP 能够基于实际结果进行闭环决策并执行高级计算摄影算法。
Metadata 作为贯穿 APP、FWK、HAL 三层的结构化数据总线,是 HAL3 相较于早期 HAL 实现更强大功能和更优性能的关键架构创新。它使得现代智能手机上的复杂计算摄影功能(如 HDR+、人像模式、超级夜景、动态帧率切换)得以高效、灵活地实现。
一个完整的Metadata的结构如下图所示,包含了vendortag、values和type
值得注意的是TAG 是 Metadata 的索引基石:通过 (Section + 子索引)(其实表示了这个Metadata想要管理什么)
唯一标识参数,映射到Metadata内存中的 Entry 存储单元