2. Android Camera API 演进:Camera1 vs Camera2 vs CameraX,架构对比与选型策略

Android 相机框架自诞生以来经历了三次重大架构迭代:从最初的 Camera1(Android 1.0)到革命性的 Camera2(Android 5.0),再到 Jetpack 生态下的 CameraX(Android 5.0+,通过 Jetpack 扩展)。理解这三代 API 的设计哲学、架构差异和适用场景,是构建高性能滤镜相机与实时特效系统的基石。

2.1 三代 API 核心架构对比

下表从架构模式、线程模型、数据流控制、设备兼容性等关键维度,对 Camera1、Camera2 和 CameraX 进行横向对比:

对比维度 Camera1 Camera2 CameraX
架构模式 单体式(Monolithic) 管道式(Pipeline) 用例驱动(Use-case)
控制模型 回调 + 参数设置 CaptureRequest + CaptureResult UseCase + 绑定生命周期
线程模型 单线程回调 多线程 + 独立回调 内部封装,自动管理
数据流 SurfaceView / TextureView Surface + ImageReader PreviewView / ImageAnalysis
设备兼容性 高(所有设备) 中(需 Level 3+ 支持) 高(自动适配 + 厂商扩展)
实时滤镜支持 困难(需 Surface 重绘) 原生支持(YUV_420_888) 良好(ImageAnalysis + GL)
生命周期管理 手动 手动 自动(Lifecycle 绑定)
推荐场景 简单拍照 / 遗留系统 专业相机 / 自定义管线 快速集成 / 跨版本兼容
选型速判: 如果你的目标设备是 Android 5.0+,且需要 实时滤镜 + OpenGL ES 渲染管线,Camera2 是性能上限最高的选择;如果追求开发效率和设备覆盖率,CameraX 是更稳妥的起点。

2.2 Camera1:遗留时代的单体架构

Camera1 是 Android 最早的相机 API,设计上采用 单体式架构:一个 Camera 对象同时负责预览、拍照、参数设置和回调分发。开发者通过 setParameters() 设置曝光、白平衡、对焦等参数,通过 setPreviewCallback() 获取预览帧数据。

Camera1 的致命缺陷: 预览回调(onPreviewFrame)返回的 YUV 数据格式因厂商而异(NV21 / YV12 / YUY2),且无法保证帧率稳定。对于需要逐帧处理像素的滤镜相机,这会导致严重的兼容性问题和性能瓶颈。

Camera1 的典型数据流如下:

// Camera1 预览回调(遗留代码示例)
Camera camera = Camera.open();
Camera.Parameters params = camera.getParameters();
params.setPreviewFormat(ImageFormat.NV21); // 常见但非标准
camera.setParameters(params);

camera.setPreviewCallback(new Camera.PreviewCallback() {
    @Override
    public void onPreviewFrame(byte[] data, Camera camera) {
        // data 格式为 NV21,需手动转换为 RGB 或 YUV_420_888
        // 无法保证回调频率与帧率同步
        processFrameForFilter(data);
    }
});
camera.startPreview();

2.3 Camera2:管道式架构与精细控制

Camera2 在 Android 5.0(API 21)引入,彻底重构了相机框架。其核心是 管道式架构:CameraManager 管理设备,CameraDevice 代表物理相机,CameraCaptureSession 管理数据流管道,CaptureRequest 封装每一帧的配置参数。

Camera2 的关键优势在于:

  • 逐帧控制:每个 CaptureRequest 可独立设置曝光、增益、白平衡、3A 模式等参数。
  • 多路输出:支持同时输出预览 Surface、拍照 ImageReader、YUV_420_888 分析流。
  • YUV_420_888 标准化:所有 Camera2 设备必须支持此格式,为 OpenGL ES 滤镜处理提供了统一输入。
  • 高速连拍:支持 BURST 模式,帧率可达 30fps+。
实时特效管线关键: Camera2 的 ImageReader 配合 YUV_420_888 格式,可以直接将预览帧送入 OpenGL ES 纹理(通过 SurfaceTexture 或 EGLImageKHR),实现零拷贝的 GPU 滤镜处理。

Camera2 的架构关系如下图所示:

Camera2 管道式架构核心组件 CameraManager CameraDevice CaptureRequest CameraCaptureSession CaptureResult Preview Surface (SurfaceView/TextureView) ImageReader (YUV_420_888 / JPEG) MediaRecorder (视频编码) 关键说明: • CaptureRequest 可独立配置每一帧的曝光、ISO、对焦、白平衡等参数。 • CameraCaptureSession 支持同时绑定多个输出 Surface,实现预览 + 分析 + 拍照并行。 • CaptureResult 回调提供每一帧的元数据(帧号、时间戳、3A 状态)。

2.4 CameraX:用例驱动的 Jetpack 封装

CameraX 是 Google 在 2019 年推出的 Jetpack 相机库,基于 Camera2 封装,但提供了更高级的 用例(UseCase)抽象。开发者不再直接操作 CameraDevice 和 CaptureSession,而是声明 Preview、ImageCapture、ImageAnalysis、VideoCapture 四个用例,由 CameraX 内部协调生命周期、设备适配和会话管理。

CameraX 的核心特性:

  • 生命周期感知:自动绑定 LifecycleOwner,在 Activity/Fragment 的 onResume/onPause 时自动开启/关闭相机。
  • 设备兼容性:通过 CameraXConfig 和厂商扩展(如美颜、HDR)自动适配不同设备。
  • 预览视图:PreviewView 封装了 SurfaceView 和 TextureView 的切换逻辑,支持缩放、旋转。
  • 分析流:ImageAnalysis 提供 YUV_420_888 格式的帧数据,支持背压策略(非阻塞 / 阻塞)。
CameraX 与 OpenGL ES 集成: 虽然 CameraX 的 PreviewView 内部使用 SurfaceView/TextureView,但 ImageAnalysis 返回的 ImageProxy 可以转换为 OpenGL 纹理。不过相比 Camera2 的直接 Surface 绑定,CameraX 多了一层内存拷贝,对极致性能场景(如 60fps 实时滤镜)有一定影响。

CameraX 的用例架构如下图所示:

CameraX 用例驱动架构 ProcessCameraProvider LifecycleOwner UseCaseGroup Preview → PreviewView ImageCapture → JPEG / RAW ImageAnalysis → YUV_420_888 VideoCapture → MediaRecorder CameraXConfig CameraX 优势: • 自动绑定生命周期,无需手动 open/release。 • 内置设备兼容性适配,减少厂商碎片化问题。

2.5 选型策略:滤镜相机与实时特效场景

针对本课程的核心目标——滤镜相机与实时特效集成,我们给出以下选型建议:

场景需求 推荐 API 理由
快速原型 / MVP 验证 CameraX 代码量少,生命周期自动管理,内置 PreviewView
高性能实时滤镜(60fps) Camera2 直接绑定 SurfaceTexture,零拷贝送入 GPU
多路并行输出(预览 + 分析 + 录制) Camera2 原生支持多 Surface 绑定,帧同步精确
跨版本兼容(Android 5.0 ~ 14) CameraX Jetpack 库自动适配厂商差异
自定义 3A 算法 / 专业摄影 Camera2 逐帧控制曝光、增益、对焦区域
遗留系统维护(minSdk < 21) Camera1 唯一选择,但需自行处理兼容性
本课程的技术路线: 我们将以 Camera2 作为主力 API,因为它提供了最完整的帧级控制能力和最低延迟的 GPU 数据通路。在后续章节中,我们会从 Camera2 的初始化、CaptureRequest 配置、YUV_420_888 到 OpenGL 纹理的绑定,逐步构建完整的实时滤镜管线。同时,我们会在第 8 章单独讲解 CameraX 的集成方案,作为快速备选方案。

2.6 从 Camera1 到 Camera2 的迁移要点

如果你正在维护一个基于 Camera1 的滤镜相机项目,迁移到 Camera2 时需注意以下关键变化:

  1. 权限模型:Camera2 需要 CAMERA 权限,且 Android 6.0+ 需运行时申请。
  2. 线程模型:Camera2 的所有回调都在独立线程中执行,需自行管理 HandlerThread。
  3. 参数设置:从 setParameters() 改为 CaptureRequest.Builder 逐帧构建。
  4. 预览数据:从 onPreviewFrame(byte[]) 改为 ImageReader.OnImageAvailableListener,格式统一为 YUV_420_888。
  5. 状态管理:Camera2 的状态机更复杂,需处理 CameraDevice.StateCallback 和 CameraCaptureSession.StateCallback。
常见迁移陷阱: Camera2 的 CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL 决定了设备的能力等级(LEGACY / LIMITED / FULL / LEVEL_3)。LEGACY 级别的设备仅支持 Camera1 的功能子集,无法使用 YUV_420_888 多路输出。在迁移前务必检查硬件级别,并准备降级方案。

以下是一个简单的硬件级别检查代码片段:

// 检查 Camera2 硬件支持级别
CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
String cameraId = manager.getCameraIdList()[0]; // 通常为 "0"
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
Integer level = characteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);

if (level == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY) {
    // 降级到 Camera1 或限制功能
    Log.w("CameraAPI", "设备仅支持 LEGACY 级别,无法使用高级特性");
} else if (level >= CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL) {
    // 支持 FULL 级别,可以使用 YUV_420_888 多路输出
    Log.i("CameraAPI", "设备支持 FULL 级别,适合实时滤镜管线");
}

2.7 本章小结

  • Camera1 是遗留架构,适合 minSdk < 21 的兼容场景,但无法满足高性能滤镜需求。
  • Camera2 是管道式架构,提供逐帧控制和 YUV_420_888 标准化输出,是实时特效管线的首选。
  • CameraX 是 Jetpack 封装,简化了生命周期和设备适配,适合快速集成和跨版本兼容。
  • 在滤镜相机项目中,推荐以 Camera2 为主力 API,结合 OpenGL ES 实现零拷贝的 GPU 渲染管线。
  • 迁移时需注意硬件级别检查、线程模型重构和参数设置方式的改变。