4. CameraCaptureSession 创建:createCaptureSession 参数详解、Session 状态回调、配置流程
CameraCaptureSession 是 Camera2 架构中连接应用层与 Camera HAL Pipeline 的核心桥梁。它负责将 CaptureRequest 提交给底层硬件,并协调输出 Surface 的配置与数据流。本章将深入解析 createCaptureSession 的完整参数、Session 状态回调机制以及标准配置流程。
4.1 createCaptureSession 参数详解
CameraDevice.createCaptureSession 方法有多个重载版本,最常用的是基于 OutputConfiguration 的版本。其核心参数决定了 Pipeline 的拓扑结构与性能边界。
| 参数 | 类型 | 说明 | 性能影响 |
|---|---|---|---|
| outputConfigurations | List<OutputConfiguration> | 定义输出 Surface 的集合,每个配置包含 Surface、格式、尺寸、数据空间等 | 直接影响 Stream 数量与组合,决定 ISP 带宽与内存占用 |
| callback | CameraCaptureSession.StateCallback | Session 状态变化的回调接口,包括配置完成、失败、关闭等 | 回调延迟影响应用层状态机切换时机 |
| handler | Handler | 指定回调执行的线程,避免阻塞主线程 | Handler 的 Looper 性能影响回调响应速度 |
| (可选)sessionParameters | CaptureRequest | 在创建 Session 时预置的初始参数,如 AE/AWB 锁定 | 减少首次 Capture 的收敛时间 |
4.1.1 OutputConfiguration 深度解析
OutputConfiguration 是描述输出目标的载体,其构造参数直接影响底层 Stream 的创建方式。
- Surface:必须从
SurfaceView、ImageReader、MediaRecorder等获取,且需在创建 Session 前配置好尺寸与格式。 - SurfaceSet:支持将多个 Surface 绑定到同一个 OutputConfiguration,实现同尺寸、同格式的 Surface 复用同一个 Stream,减少 ISP 负载。
- 物理相机 ID:在多摄场景下,指定该输出属于哪个物理相机,用于逻辑相机下的独立流配置。
- 数据空间(DataSpace):定义色彩空间与动态范围,如
DATASPACE_SRGB或DATASPACE_BT2020_HLG,影响 Tone Mapping 与色彩处理。
OutputConfiguration.setSurfaceSet() 合并 Stream。这可以减少 HAL 端的 Stream 数量,降低带宽争抢,尤其在高帧率场景下效果显著。
4.2 Session 状态回调机制
CameraCaptureSession.StateCallback 提供了 5 个关键回调方法,用于跟踪 Session 的生命周期。每个回调的触发时机与 Pipeline 状态紧密相关。
4.2.1 回调时序与 Pipeline 状态映射
| 回调方法 | 触发时机 | Pipeline 状态 | 应用层操作建议 |
|---|---|---|---|
onConfigured |
HAL 完成 Stream 配置,Session 可用 | IDLE → CONFIGURED | 此时可安全调用 setRepeatingRequest |
onReady |
所有输出 Surface 已连接且 BufferQueue 空闲 | CONFIGURED → READY | 可开始提交 CaptureRequest |
onActive |
第一个 CaptureRequest 被 HAL 接收处理 | READY → ACTIVE | 此时 Pipeline 处于工作状态,注意帧率监控 |
onClosed |
Session 被关闭,所有资源释放 | ACTIVE → CLOSED | 清理相关 Surface 引用,避免内存泄漏 |
onConfigureFailed |
HAL 无法满足配置请求 | IDLE | 检查 Stream 组合是否超出设备能力,降级重试 |
onConfigured 回调之前调用 capture 或 setRepeatingRequest 会导致 IllegalStateException。务必在回调确认后再提交请求。
4.3 配置流程与 Pipeline 交互
从应用层调用 createCaptureSession 到 HAL 完成配置,整个过程涉及 Framework、Camera Service 和 HAL 三层协作。理解这一流程有助于定位配置延迟或失败问题。
4.3.1 标准配置代码模板
以下代码展示了从创建 OutputConfiguration 到 Session 就绪的完整流程,包含必要的异常处理与状态校验。
// 1. 准备输出 Surface 列表
List<OutputConfiguration> outputConfigs = new ArrayList<>();
// 预览 Surface
Surface previewSurface = surfaceView.getHolder().getSurface();
OutputConfiguration previewConfig = new OutputConfiguration(previewSurface);
outputConfigs.add(previewConfig);
// 拍照 ImageReader
ImageReader imageReader = ImageReader.newInstance(width, height, ImageFormat.JPEG, 2);
OutputConfiguration captureConfig = new OutputConfiguration(imageReader.getSurface());
outputConfigs.add(captureConfig);
// 2. 创建 Session
cameraDevice.createCaptureSession(
outputConfigs,
new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(@NonNull CameraCaptureSession session) {
// Session 配置成功,保存引用
captureSession = session;
// 此时可安全提交请求
startRepeatingRequest(session);
}
@Override
public void onConfigureFailed(@NonNull CameraCaptureSession session) {
// 配置失败,降级处理
Log.e(TAG, "Session 配置失败");
// 尝试减少输出 Surface 数量或降低分辨率
retryWithLowerConfig();
}
@Override
public void onReady(@NonNull CameraCaptureSession session) {
// 所有 Surface 就绪,可开始捕获
}
@Override
public void onActive(@NonNull CameraCaptureSession session) {
// Pipeline 开始处理请求
}
@Override
public void onClosed(@NonNull CameraCaptureSession session) {
// 清理资源
captureSession = null;
}
},
backgroundHandler // 使用后台 Handler 避免阻塞主线程
);
4.4 配置失败常见原因与排查
onConfigureFailed 回调是性能调优中需要重点关注的信号。以下表格总结了最常见的失败原因及对应的排查方向。
| 失败原因 | 典型场景 | 排查方法 |
|---|---|---|
| Stream 组合超出设备能力 | 同时请求 4K 预览 + 4K 录像 + 高分辨率拍照 | 检查 CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP 中的组合限制 |
| Surface 尺寸/格式不匹配 | Surface 尺寸未在 StreamConfigurationMap 中列出 | 使用 getOutputSizes() 验证支持的尺寸列表 |
| BufferQueue 已满或已销毁 | SurfaceView 在创建 Session 前被销毁 | 确保 Surface 在 Session 创建期间保持有效 |
| HAL 内部资源不足 | 同时打开多个 CameraDevice | 检查 getCameraIdList() 确认并发支持数量 |
| Session 参数冲突 | sessionParameters 中设置了不兼容的控制模式 | 移除 sessionParameters 或使用默认参数重试 |
onConfigureFailed 回调中,不要立即重试相同的配置。建议先通过 CameraCharacteristics 查询当前设备的 Stream 能力上限,然后逐步降低分辨率或减少输出 Surface 数量,采用二分法找到可用的配置组合。
4.5 多输出场景下的 Session 配置策略
在需要同时输出预览、拍照、录像等多路数据时,合理的配置策略可以显著提升 Pipeline 的吞吐效率。
- 优先使用 SurfaceSet 合并同尺寸 Stream:当预览和录像使用相同分辨率时,将它们绑定到同一个 OutputConfiguration 的 SurfaceSet 中,HAL 只需维护一个 Stream,减少 ISP 通道占用。
- 区分实时与非实时输出:预览和录像属于实时输出,需要低延迟;拍照可以容忍一定延迟。在配置时,为拍照使用独立的 ImageReader,避免阻塞实时流。
- 利用物理相机流:在逻辑相机(如 Dual Camera)场景下,通过
OutputConfiguration.setPhysicalCameraId()指定物理相机,可以获取特定摄像头的独立数据流,用于深度计算或超广角拍摄。
通过合理的 Session 配置策略,可以在不牺牲功能的前提下,有效降低 ISP 负载和内存占用,为后续的高帧率或高分辨率 Capture 预留充足的 Pipeline 资源。