2. Android Camera2 框架基础:核心组件详解
在实现 HDR 多帧融合之前,必须深入理解 Camera2 框架的四大核心组件:CameraManager、CameraDevice、CaptureSession 和 CaptureRequest。它们构成了从设备发现、打开、会话建立到单次捕获请求的完整链路。HDR 的多帧曝光序列正是通过精确控制这些组件的协作来完成的。
2.1 组件全景与职责划分
下表总结了四个核心组件在 Camera2 框架中的角色与关键职责:
| 组件 | 角色 | 关键职责 | HDR 相关要点 |
|---|---|---|---|
| CameraManager | 系统级相机管理器 | 枚举相机、获取特性、打开相机 | 查询是否支持 HDR 模式、获取传感器能力 |
| CameraDevice | 相机设备代理 | 创建捕获会话、配置输出流 | 创建支持多帧输出的会话 |
| CaptureSession | 捕获会话 | 管理捕获请求队列、回调结果 | 发送多帧 HDR 请求序列、接收融合帧 |
| CaptureRequest | 单次捕获指令 | 定义曝光、增益、对焦等参数 | 设置不同曝光值(EV)的请求序列 |
关键理解:Camera2 框架采用管道(Pipeline)架构。CaptureRequest 是输入,经过 CameraDevice 内部的 ISP 管道处理,最终通过 CaptureSession 的回调输出结果。HDR 多帧融合正是利用这一管道,在短时间内注入多组不同曝光的 CaptureRequest。
2.2 CameraManager:相机系统的入口
CameraManager 是应用与相机硬件之间的第一个接触点。它负责系统级相机设备的发现与特性查询。
- 获取实例:通过
context.getSystemService(Context.CAMERA_SERVICE)获得。 - 枚举相机:
getCameraIdList()返回所有可用相机 ID。 - 查询特性:
getCameraCharacteristics(cameraId)返回CameraCharacteristics对象,包含传感器尺寸、像素大小、AE 补偿范围、是否支持 HDR 等关键信息。 - 打开相机:
openCamera(cameraId, stateCallback, handler)异步打开指定相机。
// 获取 CameraManager 实例
CameraManager manager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
// 查询相机特性,判断是否支持 HDR
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
int[] availableModes = characteristics.get(
CameraCharacteristics.CONTROL_AVAILABLE_MODES);
boolean supportsHdr = false;
for (int mode : availableModes) {
if (mode == CameraMetadata.CONTROL_MODE_USE_SCENE_MODE) {
// 进一步检查场景模式是否包含 HDR
int[] sceneModes = characteristics.get(
CameraCharacteristics.CONTROL_AVAILABLE_SCENE_MODES);
for (int scene : sceneModes) {
if (scene == CameraMetadata.CONTROL_SCENE_MODE_HDR) {
supportsHdr = true;
break;
}
}
}
}
实践提示:在 HDR 实现中,CameraManager 主要用于在初始化阶段确认设备能力。如果设备不支持 HDR 场景模式,可以考虑使用手动曝光补偿(AE Compensation)实现多帧融合。
2.3 CameraDevice:相机硬件抽象
CameraDevice 代表一个打开的相机设备。它是创建捕获会话和配置输出流的唯一入口。
- 状态回调:
CameraDevice.StateCallback监听设备打开、断开、错误等状态。 - 创建会话:
createCaptureSession(sessionConfig, callback, handler)创建捕获会话。 - 输出配置:通过
SessionConfiguration或createCaptureRequest配置输出 Surface(如 TextureView、ImageReader)。
// 打开相机
manager.openCamera(cameraId, new CameraDevice.StateCallback() {
@Override
public void onOpened(@NonNull CameraDevice camera) {
// 保存 CameraDevice 实例
cameraDevice = camera;
// 创建捕获会话
createCaptureSession();
}
@Override
public void onDisconnected(@NonNull CameraDevice camera) {
camera.close();
}
@Override
public void onError(@NonNull CameraDevice camera, int error) {
camera.close();
}
}, backgroundHandler);
注意:CameraDevice 是重量级资源。在 HDR 多帧捕获过程中,必须确保在 Activity/Fragment 生命周期中正确打开和关闭,避免资源泄漏。建议在
onPause() 中关闭设备。
2.4 CaptureSession:捕获会话与管道管理
CaptureSession 是 Camera2 框架中最核心的运行时组件。它管理着从应用发送 CaptureRequest 到硬件处理并返回结果的全过程。
- 请求提交:
capture(request, callback, handler)提交单次捕获;setRepeatingRequest(request, callback, handler)提交重复捕获。 - 结果回调:
CameraCaptureSession.CaptureCallback提供onCaptureStarted、onCaptureProgressed、onCaptureCompleted等回调。 - 会话关闭:
close()释放会话资源。
// 创建捕获会话
List<Surface> outputSurfaces = Arrays.asList(imageReader.getSurface(), textureView.getSurface());
cameraDevice.createCaptureSession(outputSurfaces,
new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(@NonNull CameraCaptureSession session) {
captureSession = session;
// 会话就绪,可以发送请求
startHdrCapture();
}
@Override
public void onConfigureFailed(@NonNull CameraCaptureSession session) {
// 处理配置失败
}
}, backgroundHandler);
HDR 关键点:CaptureSession 支持同时提交多个 CaptureRequest。在 HDR 多帧融合中,我们通常连续提交 3 个请求(欠曝、正常、过曝),每个请求的曝光补偿不同。会话会按顺序处理这些请求,并通过回调返回每一帧的原始数据。
2.5 CaptureRequest:精确控制每一帧
CaptureRequest 是 Camera2 框架中粒度最小的控制单元。它定义了单次捕获所需的所有参数,包括曝光、对焦、白平衡、输出目标等。
- 创建:通过
cameraDevice.createCaptureRequest(templateType)创建,模板类型包括TEMPLATE_PREVIEW、TEMPLATE_STILL_CAPTURE、TEMPLATE_MANUAL等。 - 参数设置:通过
builder.set(key, value)设置各种控制参数。 - 输出目标:通过
builder.addTarget(surface)指定输出 Surface。 - 构建:
builder.build()生成不可变的 CaptureRequest 对象。
// 创建 HDR 多帧请求序列
CaptureRequest.Builder builder = cameraDevice.createCaptureRequest(
CameraDevice.TEMPLATE_STILL_CAPTURE);
// 设置输出目标
builder.addTarget(imageReader.getSurface());
// 创建三个不同曝光的请求
// 欠曝帧:-2 EV
builder.set(CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION, -6);
CaptureRequest underexposed = builder.build();
// 正常帧:0 EV
builder.set(CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION, 0);
CaptureRequest normal = builder.build();
// 过曝帧:+2 EV
builder.set(CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION, 6);
CaptureRequest overexposed = builder.build();
// 依次提交三个请求
captureSession.capture(underexposed, captureCallback, backgroundHandler);
captureSession.capture(normal, captureCallback, backgroundHandler);
captureSession.capture(overexposed, captureCallback, backgroundHandler);
曝光补偿单位:曝光补偿值(EV)的单位是 1/3 EV step。因此 -6 表示 -2 EV,+6 表示 +2 EV。不同设备的步长可能不同,建议通过
CameraCharacteristics.CONTROL_AE_COMPENSATION_STEP 查询实际步长。
2.6 核心组件协作流程(SVG 架构图)
下图展示了 Camera2 框架四大核心组件在 HDR 多帧捕获场景下的完整协作流程:
2.7 组件生命周期与 HDR 调度时序
在 HDR 多帧捕获中,组件的生命周期管理直接影响融合质量。以下是推荐的调度时序:
- 初始化阶段:通过 CameraManager 查询设备能力,确认支持 HDR 或手动曝光补偿。
- 打开设备:异步打开 CameraDevice,在
onOpened回调中创建 CaptureSession。 - 会话就绪:在
onConfigured回调中构建 HDR 请求序列。 - 捕获阶段:连续提交 3 个不同曝光的 CaptureRequest,确保帧间间隔最小化。
- 结果处理:在
onCaptureCompleted回调中收集每一帧的 Image 数据。 - 融合输出:所有帧就绪后,执行多帧融合算法生成 HDR 结果。
- 资源释放:关闭 CaptureSession 和 CameraDevice。
时序关键点:HDR 多帧捕获要求三帧之间的时间差尽可能小,以避免场景运动导致的重影(Ghosting)问题。建议在提交请求时使用
capture() 而非 setRepeatingRequest(),并确保三个请求在同一个消息循环中连续提交。
2.8 核心组件 API 速查表
| 组件 | 关键方法/回调 | HDR 使用场景 |
|---|---|---|
| CameraManager | getCameraCharacteristics() |
查询 AE 补偿范围、HDR 场景模式支持 |
| CameraDevice | createCaptureSession() |
创建支持多帧输出的会话 |
| CaptureSession | capture() |
提交 HDR 多帧请求序列 |
| CaptureRequest | CONTROL_AE_EXPOSURE_COMPENSATION |
设置不同 EV 值生成多帧 |
| CaptureCallback | onCaptureCompleted() |
接收每一帧的元数据和图像数据 |
总结:Camera2 框架的四大核心组件构成了一个从系统管理到硬件控制的完整链路。在 HDR 多帧融合实现中,CameraManager 负责能力探测,CameraDevice 负责设备管理,CaptureSession 负责请求调度,CaptureRequest 负责精确控制每一帧的曝光参数。理解这四者的协作关系,是后续实现多帧融合算法的基础。