CaptureSession配置复用与多路流并发性能调优 - 第2节

2.1 CaptureRequest 的构建与参数体系

CaptureRequest 是 Camera2 中一次拍照或预览的“指令单”,它封装了所有控制参数和目标输出 Surface。理解其构建过程是复用配置和并发调优的基础。

2.1.1 构建流程

  1. 从 CameraDevice 创建模板:调用 cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW) 获得一个初始化的 CaptureRequest.Builder。
  2. 设置输出 Surface:通过 builder.addTarget(surface) 将 Surface 绑定到请求中。每个请求可以绑定多个 Surface,但必须与 OutputConfiguration 中声明的 Surface 一致。
  3. 注入控制参数:使用 builder.set(CaptureRequest.CONTROL_AE_MODE, ...) 等 API 设置曝光、白平衡、对焦等参数。
  4. 构建请求:调用 builder.build() 生成不可变的 CaptureRequest 对象。
关键约束:一个 CaptureRequest 中所有 Surface 必须来自同一个 CameraDevice,且必须与当前 CaptureSession 的 OutputConfiguration 列表匹配。否则会抛出 IllegalArgumentException。

2.1.2 核心参数分类

参数类别 示例 Key 作用
3A 控制 CONTROL_AE_MODE, CONTROL_AF_MODE, CONTROL_AWB_MODE 自动曝光、对焦、白平衡模式
传感器 SENSOR_EXPOSURE_TIME, SENSOR_SENSITIVITY 曝光时间、ISO 值
图像处理 TONEMAP_MODE, EDGE_MODE, NOISE_REDUCTION_MODE 色调映射、边缘增强、降噪
输出格式 JPEG_QUALITY, JPEG_ORIENTATION JPEG 压缩质量、旋转方向
统计信息 STATISTICS_FACE_DETECT_MODE 人脸检测、镜头阴影校正等
性能提示:在多路流并发场景下,尽量复用同一个 CaptureRequest.Builder 实例,通过 builder.set() 增量修改参数,避免频繁创建 Builder 带来的内存开销。

2.2 OutputConfiguration:Surface 的“配置契约”

OutputConfiguration 是 Camera2 中描述输出 Surface 的配置对象,它定义了 Surface 的格式、大小、旋转、镜像等属性,是 CaptureSession 配置复用的核心单元。

2.2.1 与 Surface 的关系

Surface 是 Android 图形系统的生产者端,而 OutputConfiguration 是对 Surface 的“包装”和“约束”。一个 OutputConfiguration 可以包含一个或多个 Surface(通过 addSurface()),但所有 Surface 必须共享相同的格式和尺寸。

// 创建 OutputConfiguration 的典型方式
Surface previewSurface = surfaceView.getHolder().getSurface();
OutputConfiguration outputConfig = new OutputConfiguration(previewSurface);

// 或者指定格式和尺寸
OutputConfiguration outputConfig2 = new OutputConfiguration(
    new Size(1920, 1080), ImageFormat.YUV_420_888);
outputConfig2.setSurface(surface);

2.2.2 关键属性

属性 类型 说明
Surface Surface 实际的生产者端 Surface
SurfaceGroup SurfaceGroup 用于共享同一 BufferQueue 的 Surface 组
PhysicalCameraId String 多摄像头场景下指定物理摄像头 ID
Rotation int 输出旋转角度(0/90/180/270)
Mirror boolean 是否镜像翻转
常见错误:在创建 OutputConfiguration 后,如果 Surface 被销毁或重新创建(如 SurfaceView 生命周期变化),必须重新创建 OutputConfiguration 并更新 CaptureSession。复用旧的 OutputConfiguration 会导致 SessionConfiguration 创建失败。

2.3 CaptureRequest 与 OutputConfiguration 的协作流程

下图展示了从 OutputConfiguration 配置到 CaptureRequest 提交的完整数据流:

CaptureRequest 与 OutputConfiguration 协作流程 CameraDevice OutputConfiguration Surface CaptureRequest.Builder addTarget(Surface) CaptureRequest CaptureSession 关键约束 • Surface 必须来自 同一 CameraDevice • 必须与 OutputConfig 列表匹配

2.4 多路流并发中的配置复用策略

在多路流场景(如同时预览、拍照、视频录制)中,复用 OutputConfiguration 和 CaptureRequest 可以显著减少配置开销:

2.4.1 OutputConfiguration 复用模式

  • 共享 SurfaceGroup:将多个 Surface 放入同一个 SurfaceGroup,共享 BufferQueue,减少内存占用。
  • 预创建配置池:在应用启动时创建所有可能用到的 OutputConfiguration 对象,避免运行时动态创建。
  • 增量更新:只修改需要变更的 OutputConfiguration 属性(如旋转角度),而不是重新创建整个配置。

2.4.2 CaptureRequest 复用模式

模式 适用场景 实现方式
Builder 复用 连续预览帧 保留 Builder 实例,每次调用 set() 修改参数后 build()
请求缓存 固定参数拍照 预构建多个 CaptureRequest 对象,按需选择
参数模板 场景切换 定义多个参数模板(如夜景、人像),快速切换
性能收益:在 30fps 预览 + 1080p 视频录制 + 1200 万像素拍照的三路流场景中,复用 OutputConfiguration 和 CaptureRequest 可以减少约 40% 的配置时间,降低帧率抖动风险。

2.5 常见问题与避坑指南

  • Surface 生命周期管理:SurfaceView 的 Surface 在 onPause 后可能被销毁,必须重新创建 OutputConfiguration 并更新 Session。
  • 格式不匹配:OutputConfiguration 的格式必须与 Surface 的格式一致,否则 createCaptureSession 会失败。
  • 多路流 Surface 冲突:同一个 Surface 不能同时出现在两个不同的 OutputConfiguration 中,除非使用 SurfaceGroup。
  • 参数覆盖:CaptureRequest 中的参数会覆盖 OutputConfiguration 中的默认设置,但 OutputConfiguration 的旋转和镜像属性优先级更高。
调试建议:使用 CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP 查询设备支持的输出配置组合,避免配置不支持的流组合导致性能下降或崩溃。