3、Android Camera2 API概览:CameraManager、CameraDevice、CaptureRequest、CaptureSession核心组件

Android Camera2 API 是 Android 5.0(API 21)引入的相机框架,取代了已废弃的 Camera1 API。它为开发者提供了对相机设备的精细控制,是实现多帧融合、HDR 处理等高级算法的基石。本章将深入剖析 Camera2 的四大核心组件:CameraManager、CameraDevice、CaptureRequest 和 CaptureSession,并阐述它们如何协同工作以完成一次高质量的图像捕获。

核心概念:Camera2 API 采用管道(Pipeline)架构,将相机设备抽象为一个数据流处理系统。应用程序通过发送 CaptureRequest 到 CaptureSession,驱动 CameraDevice 输出图像数据。

3.1 CameraManager:相机系统的入口

CameraManager 是系统服务的客户端代理,负责枚举和管理所有可用的相机设备。它是整个 Camera2 操作的起点。

3.1.1 主要职责

  • 枚举相机:通过 getCameraIdList() 获取所有可用相机的 ID 列表。
  • 查询特性:通过 getCameraCharacteristics(cameraId) 获取指定相机的详细能力参数,如传感器尺寸、像素大小、支持的 AE/AWB 模式、HDR 支持级别等。
  • 打开相机:通过 openCamera(cameraId, stateCallback, handler) 异步打开指定相机设备。

3.1.2 关键方法

方法 描述 返回值/回调
getCameraIdList() 获取所有可用相机 ID 的数组 String[]
getCameraCharacteristics(String cameraId) 获取指定相机的静态特性信息 CameraCharacteristics
openCamera(String cameraId, CameraDevice.StateCallback callback, Handler handler) 异步打开相机设备 通过 CameraDevice.StateCallback 回调
最佳实践:在打开相机前,务必通过 CameraCharacteristics 检查 INFO_SUPPORTED_HARDWARE_LEVEL,以确认设备是 FULL 或 LEVEL_3 级别,这些级别才支持多帧融合所需的同步帧和高速连拍能力。

3.1.3 CameraCharacteristics 关键查询项

  • SCALER_STREAM_CONFIGURATION_MAP:获取支持的输出尺寸和格式。
  • SENSOR_INFO_SENSITIVITY_RANGE:ISO 感光度范围。
  • CONTROL_AE_AVAILABLE_MODES:自动曝光支持的模式(如 ON、OFF、ON_AUTO_FLASH)。
  • STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES:人脸检测支持级别。
CameraManager 工作流程 getCameraIdList() getCameraCharacteristics() openCamera() 说明 CameraManager 是系统服务的代理,所有操作均为异步。 通过 CameraCharacteristics 可预检设备能力,避免运行时错误。

3.2 CameraDevice:相机硬件抽象

CameraDevice 代表一个物理或逻辑相机设备。一旦通过 CameraManager.openCamera() 成功打开,应用程序便获得了一个 CameraDevice 实例,用于创建捕获会话和请求。

3.2.1 状态回调

打开相机时需传入 CameraDevice.StateCallback,其回调方法包括:

  • onOpened(CameraDevice camera):相机成功打开,可以开始创建会话。
  • onDisconnected(CameraDevice camera):相机连接断开(如被其他应用抢占)。
  • onError(CameraDevice camera, int error):相机发生错误,需要释放资源。

3.2.2 核心方法

方法 描述
createCaptureRequest(int templateType) 根据模板类型(如 TEMPLATE_PREVIEW、TEMPLATE_STILL_CAPTURE)创建 CaptureRequest.Builder
createCaptureSession(SessionConfiguration config) 创建捕获会话,配置输入/输出 Surface
close() 关闭相机设备,释放资源
重要:CameraDevice 是重量级资源,必须在不再使用时显式调用 close() 释放。建议在 onPause() 或 onDestroy() 中执行关闭操作,避免内存泄漏。

3.3 CaptureRequest:捕获参数配置

CaptureRequest 定义了单次图像捕获的所有参数,包括曝光、对焦、白平衡、输出目标等。它由 CaptureRequest.Builder 构建,是不可变对象。

3.3.1 模板类型

createCaptureRequest(int templateType) 支持以下预定义模板:

模板常量 适用场景
TEMPLATE_PREVIEW 取景预览,优化帧率和功耗
TEMPLATE_STILL_CAPTURE 静态照片捕获,优先画质
TEMPLATE_VIDEO_SNAPSHOT 视频录制中的快照
TEMPLATE_ZERO_SHUTTER_LAG 零快门延迟模式(需硬件支持)
TEMPLATE_MANUAL 完全手动控制,不应用任何自动算法

3.3.2 关键参数设置

// 创建 CaptureRequest.Builder
CaptureRequest.Builder builder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);

// 设置曝光补偿
builder.set(CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION, 0);

// 设置 ISO 和曝光时间(手动模式)
builder.set(CaptureRequest.SENSOR_SENSITIVITY, 200);
builder.set(CaptureRequest.SENSOR_EXPOSURE_TIME, 10000000L); // 10ms

// 设置对焦模式
builder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);

// 添加输出目标 Surface
builder.addTarget(surface);

// 构建不可变的 CaptureRequest
CaptureRequest request = builder.build();

3.3.3 多帧融合中的关键参数

  • 曝光时间(SENSOR_EXPOSURE_TIME):控制每帧的曝光时长,HDR 多帧融合通常需要不同曝光时间的帧序列。
  • 感光度(SENSOR_SENSITIVITY):ISO 值,影响图像亮度和噪声水平。
  • 帧持续时间(SENSOR_FRAME_DURATION):控制帧间隔,影响连拍速度。
  • AE 模式(CONTROL_AE_MODE):设置为 OFF 以手动控制曝光参数。
CaptureRequest 构建与参数配置 createCaptureRequest() CaptureRequest.Builder CaptureRequest Builder 可配置参数(部分) • CONTROL_AE_EXPOSURE_COMPENSATION:曝光补偿 • SENSOR_SENSITIVITY:ISO 感光度 • SENSOR_EXPOSURE_TIME:曝光时间(纳秒) • CONTROL_AF_MODE:对焦模式 • addTarget(Surface):添加输出目标

3.4 CaptureSession:捕获会话管理

CaptureSession 是 Camera2 管道中的核心执行单元。它负责接收 CaptureRequest,驱动 CameraDevice 输出图像数据到指定的 Surface。一个 CameraDevice 一次只能有一个活跃的 CaptureSession。

3.4.1 创建会话

通过 CameraDevice.createCaptureSession(SessionConfiguration config) 创建。SessionConfiguration 包含:

  • 输出配置(OutputConfiguration):定义输出 Surface 及其格式、尺寸。
  • 会话回调(CameraCaptureSession.StateCallback):监听会话状态变化。
  • 执行器(Executor):回调执行的线程池。

3.4.2 捕获模式

方法 描述 适用场景
capture(CaptureRequest request, CaptureCallback callback, Handler handler) 单次捕获,返回一帧图像 普通拍照
captureBurst(List<CaptureRequest> requests, CaptureCallback callback, Handler handler) 批量捕获,按顺序返回多帧图像 多帧融合、HDR 连拍
setRepeatingRequest(CaptureRequest request, CaptureCallback callback, Handler handler) 持续重复捕获,用于预览 取景器预览
setRepeatingBurst(List<CaptureRequest> requests, CaptureCallback callback, Handler handler) 持续重复批量捕获 高速连拍、视频录制

3.4.3 CaptureCallback 关键回调

  • onCaptureStarted(CaptureSession session, CaptureRequest request, long timestamp, long frameNumber):捕获开始,可用于同步 UI。
  • onCaptureProgressed(CaptureSession session, CaptureRequest request, CaptureResult partialResult):部分结果可用(如 AE 状态)。
  • onCaptureCompleted(CaptureSession session, CaptureRequest request, TotalCaptureResult result):捕获完成,包含完整的元数据。
  • onCaptureFailed(CaptureSession session, CaptureRequest request, CaptureFailure failure):捕获失败,需处理错误。
多帧融合关键:使用 captureBurst() 发送一组不同曝光参数的 CaptureRequest,在 onCaptureCompleted() 中收集所有帧的 TotalCaptureResult 和 Image,然后传递给融合算法。注意帧顺序与请求顺序一致。
Camera2 四大核心组件协作架构 CameraManager 系统入口 CameraDevice 硬件抽象 CaptureRequest 参数配置 CaptureSession 执行引擎 协作流程 CameraManager 打开 CameraDevice → CameraDevice 创建 CaptureRequest.Builder → CameraDevice 创建 CaptureSession → CaptureSession 接收 CaptureRequest 并输出图像

3.5 组件协作流程示例

以下代码片段展示了四大组件如何协同完成一次 HDR 多帧捕获:

// 1. 获取 CameraManager
CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);

// 2. 打开相机
manager.openCamera(cameraId, new CameraDevice.StateCallback() {
    @Override
    public void onOpened(@NonNull CameraDevice camera) {
        // 3. 创建 CaptureRequest.Builder(使用手动模板)
        CaptureRequest.Builder builder = camera.createCaptureRequest(CameraDevice.TEMPLATE_MANUAL);
        builder.addTarget(outputSurface);

        // 4. 构建多帧请求列表(不同曝光)
        List<CaptureRequest> requestList = new ArrayList<>();
        for (int exp : new int[]{-3, 0, 3}) {
            builder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_OFF);
            builder.set(CaptureRequest.SENSOR_EXPOSURE_TIME, expTimeBase * (long) Math.pow(2, exp));
            requestList.add(builder.build());
        }

        // 5. 创建 CaptureSession
        camera.createCaptureSession(new SessionConfiguration(
            SessionConfiguration.SESSION_REGULAR,
            Arrays.asList(new OutputConfiguration(outputSurface)),
            new CameraCaptureSession.StateCallback() {
                @Override
                public void onConfigured(@NonNull CameraCaptureSession session) {
                    // 6. 发送 burst 请求
                    session.captureBurst(requestList, new CameraCaptureSession.CaptureCallback() {
                        @Override
                        public void onCaptureCompleted(@NonNull CameraCaptureSession session,
                                @NonNull CaptureRequest request, @NonNull TotalCaptureResult result) {
                            // 7. 收集帧数据,传递给融合算法
                            processFrame(result);
                        }
                    }, backgroundHandler);
                }
            }, backgroundHandler
        ));
    }
}, backgroundHandler);
调试建议:在开发多帧融合功能时,务必在 onCaptureFailed() 中打印 CaptureFailure.getReason(),常见原因包括:帧超时、Surface 已释放、硬件资源不足。这些信息对定位问题至关重要。

3.6 本章小结

  • CameraManager 是系统入口,负责枚举和打开相机设备。
  • CameraDevice 代表相机硬件,提供创建请求和会话的方法。
  • CaptureRequest 封装了每次捕获的参数,支持手动控制曝光、ISO 等关键参数。
  • CaptureSession 是执行引擎,通过 captureBurst() 实现多帧序列捕获,是多帧融合的核心机制。
  • 四大组件通过异步回调协作,开发者需正确处理状态转换和错误恢复。