4. CameraCaptureSession 创建:createCaptureSession 参数详解、Session 状态回调、配置流程

CameraCaptureSession 是 Camera2 架构中连接应用层与 Camera HAL Pipeline 的核心桥梁。它负责将 CaptureRequest 提交给底层硬件,并协调输出 Surface 的配置与数据流。本章将深入解析 createCaptureSession 的完整参数、Session 状态回调机制以及标准配置流程。

核心要点:Session 的创建过程本质上是 Camera HAL 对 CameraDevice 内部 Pipeline 进行重新配置(Reconfigure)的过程,涉及 Stream 的合并、拆分与带宽计算。

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 与色彩处理。
性能优化提示:当多个输出 Surface 具有相同的尺寸和格式时,优先使用 OutputConfiguration.setSurfaceSet() 合并 Stream。这可以减少 HAL 端的 Stream 数量,降低带宽争抢,尤其在高帧率场景下效果显著。

4.2 Session 状态回调机制

CameraCaptureSession.StateCallback 提供了 5 个关键回调方法,用于跟踪 Session 的生命周期。每个回调的触发时机与 Pipeline 状态紧密相关。

CameraCaptureSession 状态回调流程 onConfigured onReady onActive onClosed onConfigureFailed 回调触发条件 • onConfigured: HAL 配置完成 • onReady: 所有 Surface 就绪 • onActive: 首次 Capture 提交 • onClosed: Session 资源释放 • onConfigureFailed: 配置失败

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 三层协作。理解这一流程有助于定位配置延迟或失败问题。

createCaptureSession 配置流程时序 App Framework Camera Service HAL createCaptureSession validateStream组合 configureStreams HAL配置Pipeline onConfigured回调 setRepeatingRequest 配置流程关键点 1. Stream 组合验证:Framework 检查输出配置是否超出 CameraCharacteristics 声明的能力 2. configureStreams:Camera Service 将 OutputConfiguration 转换为 HAL 的 stream_t 结构 3. HAL Pipeline 重配置:包括 ISP 通道分配、Sensor 输出模式切换、内存 Buffer 分配 4. 回调传递:HAL 完成配置后,逐层回调至应用层的 onConfigured 5. 首次请求:onConfigured 后立即提交 setRepeatingRequest 可减少启动延迟

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 配置策略对比 未优化:独立 Stream 配置 预览 Stream 录像 Stream 拍照 Stream ISP 通道占用:3 个 内存开销:高 优化后:SurfaceSet 合并 预览+录像 SurfaceSet 拍照 Stream ISP 通道占用:2 个 内存开销:降低 30%

通过合理的 Session 配置策略,可以在不牺牲功能的前提下,有效降低 ISP 负载和内存占用,为后续的高帧率或高分辨率 Capture 预留充足的 Pipeline 资源。