Android 源码 Camera2 架构初识

706 阅读7分钟

android.hardware.camera2 包为连接到 Android 设备的单个相机设备提供了接口。

该包将相机设备建模为管道,它接收捕获单个帧的输入请求,捕获每个请求的单个图像,然后输出一个捕获结果元数据包,以及一组用于请求的输出图像缓冲区。请求按顺序处理,可以同时处理多个请求。由于相机设备是一个多阶段的管道,所以在大多数 Android 设备上,要保持完整的帧率需要有多个请求在运行。

要枚举、查询和打开可用的相机设备,需要获取 CameraManager 实例。

各个 CameraDevices 提供了一组静态属性信息,这些信息描述了硬件设备以及该设备的可用设置和输出参数。此信息通过 CameraCharacteristics 对象提供,并且可以通过 getCameraCharacteristics(String) 获得。

要从相机设备捕获或流式传输图像,应用程序必须首先使用 createCaptureSession(SessionConfiguration) 创建具有一组供相机设备使用的输出 Surface 的相机捕获会话。必须为每个 Surface 预先配置适当的大小和格式(如果适用),以匹配相机设备可用的大小和格式。可以从各种类中获取目标 Surface,包括 SurfaceView,通过 Surface(SurfaceTexture)获得 SurfaceTexture、MediaCodec、MediaRecorder、Allocation 和 ImageReader。

通常,将相机预览图像发送到 SurfaceView 或 TextureView(通过其 SurfaceTexture)。可以使用具有 JPEG 和 RAW_SENSOR 格式的 ImageReader 捕获 DngCreator 的 JPEG 图像或 RAW 缓冲区。在 RenderScript、OpenGL ES 中,或直接在托管代码或本地代码中,应用程序驱动的相机数据处理最好是通过 Allocation 分别使用 YUV 类型、SurfaceTexture 和 YUV_420_888 格式的 ImageReader 来完成。

然后,应用程序需要构造一个 CaptureRequest,它定义相机设备捕获单个图像所需的所有捕获参数。该请求还列出了应将哪个已配置的输出 Surface 用作此捕获的目标。CameraDevice 具有用于为给定用例创建请求生成器的工厂方法,该方法针对运行应用程序的 Android 设备进行了优化。

一旦建立了请求,就可以将其传递给活动捕获会话,进行一次性捕获或无休止地重复使用。这两种方法都有一个变体,它接受一个请求列表作为突发捕获/重复突发。重复请求的优先级比捕获低,因此通过 capture() 提交的请求在配置了重复请求时将在当前重复(突发)获得任何新实例开始捕获之前捕获。

处理请求后,相机设备将产生 TotalCaptureResult 对象,该对象包含有关相机在捕获时的状态以及使用的最终设置的信息。如果需要舍入或解决矛盾的参数,则这些可能与请求有所不同。相机设备还将向请求中包含的每个输出 Surface 中发送一帧图像数据。这些是相对于输出 CaptureResult 异步生成的,有时会稍后生成。

CameraCaptureSession:CameraDevice 的已配置捕获会话,用于捕获来自相机的图像或重新处理先前在同一会话中从相机捕获的图像。

CameraCaptureSession.CaptureCallback:一个回调对象,用于跟踪提交给相机设备的 CaptureRequest 的进度。

CameraCaptureSession.StateCallback:一个用于接收有关相机捕获会话状态更新的回调对象。

CameraCharacteristics:描述 CameraDevice 的属性。

CameraCharacteristics.Key:键用于通过 CameraCharacteristics#get 进行相机特征字段查找。

CameraConstrainedHighSpeedCaptureSession:CameraDevice 的受限高速捕获会话,用于从 CameraDevice 捕获高速图像以用于高速视频录制用例。

CameraDevice:CameraDevice 类是一个连接到 Android 设备的单个相机的表示,允许在高帧率下对图像捕获和后处理进行细粒度控制。

CameraDevice.StateCallback:回调对象,用于接收有关摄像头设备状态的更新。

CameraManager:系统服务管理器用于检测、表征和连接到 CameraDevice。

CameraManager.AvailabilityCallback:相机设备可用或无法打开的回调。

CameraManager.TorchCallback:相机闪光灯的手电筒模式变得不可用、已禁用或已启用回调。

CameraMetadata:相机控件和信息的基类。

CameraOfflineSession:通过成功调用 CameraCaptureSession#switchToOffline 将相机捕获会话切换为脱机模式。

CameraOfflineSession.CameraOfflineSessionCallback:相机脱机会话回调。

CaptureFailure:从图像传感器捕获单个图像失败捕获的报告。

CaptureRequest:从相机捕获单个图像所需的一组不变的设置和输出。

CaptureRequest.Builder:捕获请求的构建器。

CaptureRequest.Key:键用于通过 CaptureResult#get 进行捕获请求字段查找,或通过 CaptureRequest.Builder#set(key,Object) 设置字段。

CaptureResult:从图像传感器捕获单个图像的结果的子集。

CaptureResult.Key:键用于通过 CaptureResult#get 捕获结果字段。

DngCreator:DngCreator 类提供了将原始像素数据写入 DNG 文件的功能。

TotalCaptureResult:从图像传感器捕获单个图像的总组装结果。

CameraAccessException:如果 CameraManager 无法查询或打开相机设备,或者与打开的 CameraDevice 的连接不再有效,则抛出 CameraAccessException。

Camera2 API 使用步骤

1.使用 getCameraIdList 可以获取所有可用相机的列表。然后,可以使用 getCameraCharacteristics 并找到适合你需要的最佳相机(正面/背面、分辨率等)。

2.创建 CameraDevice.StateCallback 的实例并打开相机。打开相机后,便可以开始预览相机了。

3.使用 TextureView 来显示相机预览。创建一个 CameraCaptureSession 并为其设置一个重复的 CaptureRequest。

4.静止图像捕获需要几个步骤。 首先,你需要通过更新相机预览的 CaptureRequest 来锁定相机的焦点。然后,以类似的方式,你需要运行预捕获序列。 之后,就可以拍摄图片了。创建一个新的 CaptureRequest 并调用 capture(android.hardware.camera2.CaptureRequest, android.hardware.camera2.CameraCaptureSession.CaptureCallback, android.os.Handler)。 完成后,别忘了释放相机的焦点。

Android 的相机硬件抽象层 (HAL) 可将 Camera2 中较高层级的相机框架 API 连接到底层的相机驱动程序和硬件。相机子系统包括相机管道组件的实现,而相机 HAL 可提供用于实现这些组件版本的接口。
在这里插入图片描述
应用框架

应用代码位于应用框架级别,它使用 Camera 2 API 与相机硬件进行交互。在内部,这些代码会调用相应的 Binder 接口,以访问与相机互动的原生代码。

AIDL

与 CameraService 关联的 Binder 接口可在 frameworks/av/camera/aidl/android/hardware 中找到。生成的代码会调用较低级别的原生代码以获取对实体相机的访问权限,并返回用于在框架级别创建 CameraDevice 并最终创建 CameraCaptureSession 对象的数据。

原生框架

此框架位于 frameworks/av/ 中,并提供相当于 CameraDevice 和 CameraCaptureSession 类的原生类。另请参阅 NDK camera2 参考。

Binder IPC 接口

IPC binder 接口用于实现跨越进程边界的通信。调用相机服务的若干个相机 Binder 类位于 frameworks/av/camera/camera/aidl/android/hardware 目录中。 ICameraService 是相机服务的接口;ICameraDeviceUser 是已打开的特定相机设备的接口;ICameraServiceListener 和 ICameraDeviceCallbacks 分别是对应用框架的 CameraService 和 CameraDevice 回调。

相机服务

位于 frameworks/av/services/camera/libcameraservice/CameraService.cpp 下的相机服务是与 HAL 进行互动的实际代码。

HAL

硬件抽象层定义了由相机服务调用、且您必须实现以确保相机硬件正常运行的标准接口。

应用框架会针对捕获的结果向相机子系统发出请求。一个请求对应一组结果。请求包含有关捕获和处理这些结果的所有配置信息。其中包括分辨率和像素格式;手动传感器、镜头和闪光灯控件;3A 操作模式;RAW 到 YUV 处理控件;以及统计信息的生成等。这样一来,便可更好地控制结果的输出和处理。一次可发起多个请求,而且提交请求时不会出现阻塞。请求始终按照接收的顺序进行处理。
在这里插入图片描述下面是分析 Camera2 架构的一系列文章:

1.Android 源码 Camera2 架构初识
2.Android 源码 Camera2 获取 CameraManager 对象
3.Android 源码 Camera2 CameraService 启动
4.Android 源码 QCamera2 HAL 分析
5.Android 源码 Camera2 获取 CameraId 列表
6.Android 源码 Camera2 openCamera 流程分析
7.Android 源码 Camera2 预览流程分析一
8.Android 源码 Camera2 预览流程分析二
9.Android 源码 Camera2 HAL3 流配置
10.Android 源码 Camera2 预览流程分析三
11.Android 源码 Camera2 预览流程分析四

参考资料

  1. developer.android.google.cn/reference/a…
  2. source.android.google.cn/devices/cam…
  3. source.android.google.cn/devices/cam…