2、Android Camera2 API 架构:CameraManager、CameraDevice、CameraCaptureSession、CaptureRequest 详解

Camera2 API 是 Android 5.0(API 21)引入的、用于替代已废弃的 Camera1 API 的现代相机框架。它采用管道(Pipeline)架构,将相机设备抽象为一系列可配置的捕获请求与结果流。理解其核心组件是进行音视频采集的基础。

2.1 CameraManager:系统相机服务的管理者

CameraManager 是应用与系统相机服务交互的入口。它负责枚举、查询和连接相机设备。

  • 获取实例:通过 Context.getSystemService(Context.CAMERA_SERVICE) 获取。
  • 核心职责
    • 枚举相机getCameraIdList() 返回所有可用相机的 ID 列表(通常包含后置、前置等)。
    • 查询特性getCameraCharacteristics(String cameraId) 返回 CameraCharacteristics 对象,包含该相机的所有静态属性,如:
      • SCALER_STREAM_CONFIGURATION_MAP:支持的输出尺寸、格式(YUV_420_888、NV21、JPEG 等)。
      • FLASH_INFO_AVAILABLE:是否支持闪光灯。
      • LENS_FACING:相机朝向(前置/后置)。
      • SENSOR_ORIENTATION:传感器方向(用于旋转预览画面)。
    • 打开相机openCamera(String cameraId, CameraDevice.StateCallback callback, Handler handler) 异步打开指定相机。
// 示例:获取 CameraManager 并查询后置相机
CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
try {
    String[] cameraIds = manager.getCameraIdList();
    for (String id : cameraIds) {
        CameraCharacteristics characteristics = manager.getCameraCharacteristics(id);
        Integer facing = characteristics.get(CameraCharacteristics.LENS_FACING);
        if (facing != null && facing == CameraCharacteristics.LENS_FACING_BACK) {
            // 找到后置相机,准备打开
            manager.openCamera(id, stateCallback, backgroundHandler);
            break;
        }
    }
} catch (CameraAccessException e) {
    e.printStackTrace();
}

2.2 CameraDevice:相机硬件的抽象代理

CameraDevice 代表一个物理或逻辑相机设备。一旦通过 CameraManager.openCamera() 成功打开,系统会通过 CameraDevice.StateCallback 回调返回该实例。

  • 状态回调
    • onOpened(CameraDevice camera):相机成功打开,此时可以创建 CameraCaptureSession
    • onDisconnected(CameraDevice camera):相机断开连接(如被其他应用抢占)。
    • onError(CameraDevice camera, int error):发生错误。
  • 核心方法
    • createCaptureSession(SessionConfiguration config):创建捕获会话(推荐方式,API 23+)。
    • createCaptureRequest(int templateType):创建 CaptureRequest.Builder,模板类型包括:
      • TEMPLATE_PREVIEW:预览模式,高帧率。
      • TEMPLATE_RECORD:视频录制模式,稳定帧率。
      • TEMPLATE_STILL_CAPTURE:拍照模式,高质量。
      • TEMPLATE_VIDEO_SNAPSHOT:录制时拍照。
      • TEMPLATE_MANUAL:手动模式,完全控制参数。
// 示例:CameraDevice.StateCallback 实现
private final CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {
    @Override
    public void onOpened(@NonNull CameraDevice camera) {
        cameraDevice = camera;
        // 相机已打开,可以创建会话
        createCameraPreviewSession();
    }

    @Override
    public void onDisconnected(@NonNull CameraDevice camera) {
        cameraDevice.close();
        cameraDevice = null;
    }

    @Override
    public void onError(@NonNull CameraDevice camera, int error) {
        cameraDevice.close();
        cameraDevice = null;
    }
};

2.3 CameraCaptureSession:捕获请求的会话管道

CameraCaptureSession 是相机设备与输出目标(如 Surface)之间的桥梁。它负责接收 CaptureRequest,并将其发送到相机硬件进行处理,最终将数据输出到指定的 Surface

  • 创建会话:通过 CameraDevice.createCaptureSession() 创建,需要提供一组输出 Surface(例如:用于预览的 SurfaceView 的 Surface,用于录制的 MediaCodec 的 Surface,用于拍照的 ImageReader 的 Surface)。
  • 状态回调CameraCaptureSession.StateCallback
    • onConfigured(CameraCaptureSession session):会话配置成功,可以开始发送请求。
    • onConfigureFailed(CameraCaptureSession session):配置失败。
  • 核心方法
    • setRepeatingRequest(CaptureRequest request, CameraCaptureSession.CaptureCallback callback, Handler handler):发起持续重复的请求(如预览、视频流)。
    • capture(CaptureRequest request, CameraCaptureSession.CaptureCallback callback, Handler handler):发起单次请求(如拍照)。
    • abortCaptures():中止当前所有待处理的请求。
// 示例:创建预览会话
private void createCameraPreviewSession() {
    try {
        // 假设 previewSurface 是 SurfaceView 的 Surface
        List<Surface> outputs = new ArrayList<>();
        outputs.add(previewSurface);

        cameraDevice.createCaptureSession(outputs, new CameraCaptureSession.StateCallback() {
            @Override
            public void onConfigured(@NonNull CameraCaptureSession session) {
                captureSession = session;
                // 创建预览请求
                CaptureRequest.Builder builder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
                builder.addTarget(previewSurface);
                // 设置自动对焦模式
                builder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
                // 开始重复请求
                captureSession.setRepeatingRequest(builder.build(), null, backgroundHandler);
            }

            @Override
            public void onConfigureFailed(@NonNull CameraCaptureSession session) {
                // 处理失败
            }
        }, backgroundHandler);
    } catch (CameraAccessException e) {
        e.printStackTrace();
    }
}

2.4 CaptureRequest:一次捕获的完整配置

CaptureRequest 定义了相机在一次捕获中需要执行的所有参数和目标。它由 CaptureRequest.Builder 构建。

  • 核心组成
    • 目标 Surface:通过 addTarget(Surface) 添加,指定数据输出到哪里。一个请求可以同时输出到多个 Surface(例如:同时输出预览和录制)。
    • 捕获参数:通过 set(CaptureRequest.Key<T> key, T value) 设置,常用参数包括:
      • CONTROL_AF_MODE:对焦模式(自动、连续、手动)。
      • CONTROL_AE_MODE:自动曝光模式。
      • CONTROL_AWB_MODE:白平衡模式。
      • FLASH_MODE:闪光灯模式。
      • SENSOR_EXPOSURE_TIME:曝光时间(手动模式)。
      • SENSOR_SENSITIVITY:ISO 感光度(手动模式)。
      • JPEG_QUALITY:JPEG 压缩质量。
  • 请求类型
    • 重复请求:通过 setRepeatingRequest() 提交,相机将持续按此配置捕获帧,直到被新的重复请求替换或会话关闭。适用于预览和视频流。
    • 单次请求:通过 capture() 提交,只执行一次捕获。适用于拍照。
// 示例:构建一个拍照请求
private void captureStillPicture() {
    try {
        CaptureRequest.Builder builder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
        builder.addTarget(imageReader.getSurface()); // ImageReader 用于获取 JPEG 数据

        // 设置自动对焦锁定
        builder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
        // 设置闪光灯自动
        builder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_AUTO);
        // 设置 JPEG 质量
        builder.set(CaptureRequest.JPEG_QUALITY, (byte) 95);

        // 发送单次请求
        captureSession.capture(builder.build(), new CameraCaptureSession.CaptureCallback() {
            @Override
            public void onCaptureCompleted(@NonNull CameraCaptureSession session,
                                           @NonNull CaptureRequest request,
                                           @NonNull TotalCaptureResult result) {
                // 拍照完成,可以处理 ImageReader 中的图片数据
            }
        }, backgroundHandler);
    } catch (CameraAccessException e) {
        e.printStackTrace();
    }
}

2.5 组件协作流程总结

整个 Camera2 的工作流程可以概括为以下步骤:

  1. 获取 CameraManager:通过系统服务获取。
  2. 查询并打开 CameraDevice:使用 CameraManager.openCamera() 异步打开。
  3. 准备输出 Surface:创建 SurfaceViewTextureViewImageReaderMediaCodec 的 Surface。
  4. 创建 CameraCaptureSession:将输出 Surface 列表传入 CameraDevice.createCaptureSession()
  5. 构建 CaptureRequest:根据需求(预览/录制/拍照)创建 CaptureRequest.Builder,设置参数并添加目标 Surface。
  6. 提交请求:调用 setRepeatingRequest()capture() 开始数据流。
  7. 处理结果:通过 CaptureCallback 获取捕获元数据,通过 ImageReaderSurface 获取图像数据。

理解这四个核心组件的职责与协作关系,是掌握 Camera2 API 的关键。后续章节将基于此架构,深入讲解预览、拍照、视频录制以及编码的具体实现。