相机
相机
Android 的相机硬件抽象层 (HAL) 可将 Camera 2 中较高级别的相机框架 API 连接到底层的相机驱动程序和硬件。相机子系统包括相机管道组件的实现,而相机 HAL 则可提供用于实现您的这些组件版本的接口。
注意:如果您要在搭载 Android 8.0 或更高版本的设备上实现相机 HAL,则必须使用 HIDL 接口。要了解旧版组件,请参阅旧版 HAL 组件。架构
下列图表和列表说明了 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
- 硬件抽象层定义了由相机服务调用、且您必须实现以确保相机硬件正常运行的标准接口。
实现 HAL
HAL 位于相机驱动程序和更高级别的 Android 框架之间,它定义您必须实现的接口,以便应用可以正确地操作相机硬件。从 Android 8.0 开始,相机 HAL 接口是 Project Treble 的一部分,相应的 HIDL 接口在 hardware/interfaces/camera 中定义。
典型的绑定式 HAL 必须实现以下 HIDL 接口:
- ICameraProvider:用于枚举单个设备并管理其状态。
- ICameraDevice:相机设备接口。
- ICameraDeviceSession:活跃的相机设备会话接口。
参考 HIDL 实现适用于 CameraProvider.cpp、CameraDevice.cpp 和 CameraDeviceSession.cpp。该实现封装了仍在使用旧版 API 的旧 HAL。从 Android 8.0 开始,相机 HAL 实现必须使用 HIDL API;不支持使用旧版接口。
要详细了解 Treble 和 HAL 开发,请参阅 Treble 资源。
旧版 HAL 组件
此部分介绍了旧版 HAL 组件的架构以及如何实现 HAL。搭载 Android 8.0 或更高版本的设备上的相机 HAL 实现必须改用 HIDL API(如上所述)。
架构(旧版)
下列图表和列表说明了旧版相机 HAL 组件:
- 应用框架
- 应用代码位于应用框架级别,它利用 android.hardware.Camera API 与相机硬件进行交互。在内部,此代码会调用相应的 JNI 粘合类,以访问与相机互动的原生代码。
- JNI
- 与 android.hardware.Camera 关联的 JNI 代码位于
frameworks/base/core/jni/android_hardware_Camera.cpp
中。此代码会调用较低级别的原生代码以获取对实体相机的访问权限,并返回用于在框架级别创建 android.hardware.Camera 对象的数据。 - 原生框架
- 在
frameworks/av/camera/Camera.cpp
中定义的原生框架可提供相当于 android.hardware.Camera 类的原生类。此类会调用 IPC binder 代理,以获取对相机服务的访问权限。 - Binder IPC 代理
- IPC binder 代理用于促进跨越进程边界的通信。调用相机服务的 3 个相机 binder 类位于
frameworks/av/camera
目录中。ICameraService 是相机服务的接口,ICamera 是已打开的特定相机设备的接口,ICameraClient 是指回应用框架的设备接口。 - 相机服务
- 位于
frameworks/av/services/camera/libcameraservice/CameraService.cpp
下的相机服务是与 HAL 进行互动的实际代码。 - HAL
- 硬件抽象层定义了由相机服务调用、且您必须实现以确保相机硬件正常运行的标准接口。
- 内核驱动程序
- 相机的驱动程序可与实际相机硬件以及您的 HAL 实现进行互动。相机和驱动程序必须支持 YV12 和 NV21 图像格式,以便在显示和视频录制时支持预览相机图像。
实现 HAL(旧版)
HAL 位于相机驱动程序和更高级别的 Android 框架之间,它定义您必须实现的接口,以便应用可以正确地操作相机硬件。HAL 接口在 hardware/libhardware/include/hardware/camera.h
和 hardware/libhardware/include/hardware/camera_common.h
标头文件中定义。
camera_common.h
定义 camera_module
;这是一个标准结构,可用于获取有关相机的一般信息,例如相机 ID 和所有相机通用的属性(例如,摄像头是前置还是后置)。
camera.h
包含与 android.hardware.Camera 对应的代码。此标头文件会声明一个 camera_device
结构,该结构又反过来包含一个带函数指针(可实现 HAL 接口)的 camera_device_ops
结构。有关开发者可以设置的相机参数的文档,请参阅 frameworks/av/include/camera/CameraParameters.h
。通过 HAL 中的 int (*set_parameters)(struct camera_device *, const char *parms)
来设置这些参数以及指向的函数。
有关 HAL 实现的示例,请参阅 hardware/ti/omap4xxx/camera
中的 Galaxy Nexus HAL 实现。
配置共享库
设置 Android 编译系统,以将 HAL 实现正确打包到共享库中,并通过创建 Android.mk
文件将其复制到相应位置:
- 创建一个
device/<company_name>/<device_name>/camera
目录以包含您库的源文件。 - 创建一个
Android.mk
文件来编译共享库。确保 Makefile 包含以下行:LOCAL_MODULE := camera.<device_name> LOCAL_MODULE_RELATIVE_PATH := hw
您的库必须命名为
camera.<device_name>
(自动附加.so
),以便 Android 可以正确加载库。例如,请参阅hardware/ti/omap4xxx/Android.mk
中的 Galaxy Nexus 相机的 Makefile。 - 使用您设备的 Makefile 复制
frameworks/native/data/etc
目录中的必要功能 XML 文件,以指定您的设备具有相机功能。例如,要指定您的设备具有相机闪光灯并可自动对焦,请在您设备的<device>/<company_name>/<device_name>/device.mk
Makefile 中添加以下行:PRODUCT_COPY_FILES := \ ... PRODUCT_COPY_FILES += \ frameworks/native/data/etc/android.hardware.camera.flash-autofocus.xml:system/etc/permissions/android.hardware.camera.flash-autofocus.xml \
有关设备 Makefile 的示例,请参阅
device/samsung/tuna/device.mk
。 - 在
device/<company_name>/<device_name>/media_profiles.xml
和device/<company_name>/<device_name>/media_codecs.xml
XML 文件中声明您相机的媒体编解码器、格式和分辨率功能。如需了解详情,请参阅将编解码器展示给框架。 - 在您设备的
device/<company_name>/<device_name>/device.mk
Makefile 中添加以下行,以将media_profiles.xml
和media_codecs.xml
文件复制到相应位置:# media config xml file PRODUCT_COPY_FILES += \ <device>/<company>/<device>/media_profiles.xml:system/etc/media_profiles.xml # media codec config xml file PRODUCT_COPY_FILES += \ <device>/<company>/<device>/media_codecs.xml:system/etc/media_codecs.xml
- 要将相机应用包含在设备的系统映像中,请在设备的
device/<company>/<device>/device.mk
Makefile 中的PRODUCT_PACKAGES
变量中指定该应用:PRODUCT_PACKAGES := \ Gallery2 \ ...
相机 HAL3
Android 的相机硬件抽象层 (HAL) 可将 android.hardware.camera2 中较高级别的相机框架 API 连接到底层的相机驱动程序和硬件。Android 8.0 引入了 Treble,用于将 CameraHal API 切换到由 HAL 接口描述语言 (HIDL) 定义的稳定接口。如果您之前为 Android 7.0 及更低版本开发过相机 HAL 模块和驱动程序,请注意相机管道中发生的重大变化。
相机 HAL3 功能
重新设计 Android Camera API 的目的在于大幅提高应用对于 Android 设备上的相机子系统的控制能力,同时重新组织 API,提高其效率和可维护性。借助额外的控制能力,您可以更轻松地在 Android 设备上构建高品质的相机应用,这些应用可在多种产品上稳定运行,同时仍会尽可能使用设备专用算法来最大限度地提升质量和性能。
版本 3 相机子系统将多个运行模式整合为一个统一的视图,您可以使用这种视图实现之前的任何模式以及一些其他模式,例如连拍模式。这样一来,便可以提高用户对聚焦、曝光以及更多后期处理(例如降噪、对比度和锐化)效果的控制能力。此外,这种简化的视图还能够使应用开发者更轻松地使用相机的各种功能。
API 将相机子系统塑造为一个管道,该管道可按照 1:1 的基准将传入的帧捕获请求转化为帧。这些请求会封装有关帧的捕获和处理的所有配置信息,其中包括分辨率和像素格式;手动传感器、镜头和闪光灯控件;3A 运行模式;RAW->YUV 处理控件;统计信息生成等等。
简单来说,应用框架从相机子系统请求帧,然后相机子系统将结果返回到输出流。此外,系统还会针对每组结果生成包含色彩空间和镜头阴影等信息的元数据。您可以将相机版本 3 看作相机版本 1 的单向流管道。它会将每个捕获请求转化为传感器捕获的一张图像,这张图像将被处理成:
- 包含有关捕获的元数据的结果对象。
- 图像数据的 1 到 N 个缓冲区,每个缓冲区会进入自己的目的地 Surface。
可能的输出 Surface 组经过预配置:
- 每个 Surface 都是一个固定分辨率的图像缓冲区流的目标位置。
- 一次只能将少量 Surface 配置为输出(约 3 个)。
一个请求中包含所需的全部捕获设置,以及要针对该请求将图像缓冲区(从总配置组)推送到其中的输出 Surface 的列表。请求可以只发生一次(使用 capture()
),也可以无限重复(使用 setRepeatingRequest()
)。捕获的优先级高于重复请求的优先级。
相机 HAL1 概述
注意:由于相机 HAL1 已弃用,建议在搭载 Android 9 或更高版本的设备上使用相机 HAL3。相机子系统的第 1 个版本被设计为具有高级控件和以下三种运行模式的黑盒子:
- 预览
- 视频录制
- 静态拍摄
三种模式具有略有不同又相互重叠的功能。这样就难以实现介于其中两种运行模式之间的新功能,例如连拍模式。
由于很多设备仍然依赖相机 HAL1,因此 Android 7.0 继续支持该模块。此外,Android 相机服务还支持同时实现两种 HAL(1 和 3),如果您希望通过相机 HAL1 支持性能略低的前置摄像头,并通过相机 HAL3 支持更为高级的后置摄像头,那么这项支持将非常有用。
有一种单独的相机 HAL 模块(拥有自己的版本号),其中列出了多种独立的相机设备,每种都有自己的版本号。要支持设备 2 或更新版本,必须使用相机模块 2 或更新版本,而且此类相机模块可以具有混合的相机设备版本(我们在上文中提到 Android 支持同时实现两种 HAL,就是这个含义)。
HAL 子系统
请求
应用框架会针对捕获的结果向相机子系统发出请求。一个请求对应一组结果。请求包含有关捕获和处理这些结果的所有配置信息。其中包括分辨率和像素格式;手动传感器、镜头和闪光灯控件;3A 操作模式;RAW 到 YUV 处理控件;以及统计信息的生成等。这样一来,便可更好地控制结果的输出和处理。一次可发起多个请求,而且提交请求时不会出现阻塞。请求始终按照接收的顺序进行处理。
HAL 和相机子系统
相机子系统包括相机管道中组件的实现,例如 3A 算法和处理控件。相机 HAL 为您提供了用于实现您的这些组件版本的接口。为了保持多个设备制造商和图像信号处理器(ISP,也称为相机传感器)供应商之间的跨平台兼容性,相机管道模型是虚拟的,且不直接对应于任何真正的 ISP。不过,它与真正的处理管道足够相似,因此您可以有效地将其映射到硬件。此外,它足够抽象,可支持多种不同的算法和运算顺序,而不会影响质量、效率或跨设备兼容性。
相机管道还支持应用框架可以启动来开启自动对焦等功能的触发器。它还会将通知发送回应用框架,以通知应用自动对焦锁定或错误等事件。
请注意,上图所示的一些图像处理块在初始版本中没有明确定义。相机管道做出以下假设:
- RAW Bayer 输出在 ISP 内部不经过任何处理。
- 统计信息根据原始传感器数据生成。
- 将原始传感器数据转换为 YUV 的各种处理块按任意顺序排列。
- 当显示多个刻度和剪裁单元时,所有缩放器单元共享输出区域控件(数字缩放)。不过,每个单元都可能具有不同的输出分辨率和像素格式。
API 用途摘要
下面简要介绍了使用 Android Camera API 的步骤。有关这些步骤(包括 API 调用)的详细说明,请参阅“启动和预期操作顺序”部分。
- 监听和枚举相机设备。
- 打开设备并连接监听器。
- 配置目标使用情形的输出(如静态捕获、录制等)。
- 为目标使用情形创建请求。
- 捕获/重复请求和连拍。
- 接收结果元数据和图片数据。
- 切换使用情形时,返回到第 3 步。
HAL 操作摘要
- 捕获的异步请求来自于框架。
- HAL 设备必须按顺序处理请求。对于每个请求,均生成输出结果元数据以及一个或多个输出图像缓冲区。
- 请求和结果以及后续请求引用的信息流遵守先进先出规则。
- 指定请求的所有输出的时间戳必须完全相同,以便框架可以根据需要将它们匹配在一起。
- 所有捕获配置和状态(不包括 3A 例程)都包含在请求和结果中。
启动和预期操作顺序
本部分详细说明了使用 Camera API 时应遵循的步骤。有关 HIDL 接口的定义,请参阅 platform/hardware/interfaces/camera/。
枚举、打开相机设备并创建有效会话
- 初始化后,框架开始监听实现
ICameraProvider
接口的任何现有相机提供程序。如果存在一个或多个此类提供程序,框架将尝试建立连接。 - 框架通过
ICameraProvider::getCameraIdList()
枚举相机设备。 - 框架通过调用相应的
ICameraProvider::getCameraDeviceInterface_VX_X()
来实例化一个新的ICameraDevice
。 - 框架调用
ICameraDevice::open()
来创建一个新的有效捕获会话 ICameraDeviceSession。
使用有效相机会话
- 框架调用
ICameraDeviceSession::configureStreams()
并传入到 HAL 设备的输入/输出流列表。 - 框架通过调用
ICameraDeviceSession::constructDefaultRequestSettings()
来为某些使用情形请求默认设置。这可能会在ICameraDevice::open
创建ICameraDeviceSession
之后的任何时间发生。 - 框架通过基于某一组默认设置的设置以及框架之前注册的至少一个输出流来构建第一个捕获请求并将其发送到 HAL。此请求通过
ICameraDeviceSession::processCaptureRequest()
发送到 HAL。HAL 必须阻止此调用返回,直到准备好发送下一个请求为止。 - 框架继续提交请求并根据需要调用
ICameraDeviceSession::constructDefaultRequestSettings()
以获取其他使用情形的默认设置缓冲区。 - 当请求捕获开始(传感器开始曝光以进行捕获)时,HAL 会调用
ICameraDeviceCallback::notify()
并显示 SHUTTER 消息,包括帧号和开始曝光的时间戳。此通知回调不必在对请求第一次调用processCaptureResult()
之前发生,但直到针对相应的捕获调用notify()
之后,才会向应用提供有关该捕获的结果。 - 经过一定的管道延迟后,HAL 开始使用
ICameraDeviceCallback::processCaptureResult()
将完成的捕获返回到框架。这些捕获按照与提交请求相同的顺序返回。一次可发起多个请求,具体取决于相机 HAL 设备的管道深度。
一段时间后,会出现以下某种情况:
- 框架可能会停止提交新的请求,等待现有捕获完成(所有缓冲区都已填充,所有结果都已返回),然后再次调用
ICameraDeviceSession::configureStreams()
。这会重置相机硬件和管道,以获得一组新的输入/输出流。可重复使用先前配置中的部分信息流。如果至少还有一个已注册的输出流,则框架将从发送到 HAL 的第一个捕获请求继续。(否则,需要先调用ICameraDeviceSession::configureStreams()
。) - 框架可能会调用
ICameraDeviceSession::close()
以结束相机会话。当框架中没有其他处于有效状态的调用时,可能随时会调用此函数;不过,在所有发起的捕获完成(所有结果都已返回,所有缓冲区都已填充)之前,调用可能会阻塞。close()
调用返回后,不允许再从 HAL 对ICameraDeviceCallback
进行调用。一旦进行close()
调用,框架便不能再调用其他任何 HAL 设备函数。 - 在发生错误或其他异步事件时,HAL 必须调用
ICameraDeviceCallback::notify()
并返回相应的错误/事件消息。从严重的设备范围错误通知返回后,HAL 的行为方式应像对其调用了close()
一样。但是,HAL 必须在调用notify()
之前取消或完成所有待处理的捕获,以便在调用notify()
并返回严重错误时,框架不会收到来自设备的更多回调。在notify()
方法从严重错误消息返回后,close()
之外的方法应返回 -ENODEV 或 NULL。
硬件级别
相机设备可以根据其功能实现多个硬件级别。如需了解详情,请参阅支持的硬件级别。
应用捕获请求、3A 控件和处理管道之间的交互
根据 3A 控件块中的设置,相机管道会忽略应用捕获请求中的某些参数,而改用 3A 控件例程提供的值。例如,启用自动曝光后,传感器的曝光时间、帧时长和感光度参数由平台 3A 算法控制,所有应用指定的值都会被忽略。必须在输出元数据中报告由 3A 例程为帧选择的值。下表描述了 3A 控件块的不同模式以及由这些模式控制的属性。有关这些属性的定义,请参阅 platform/system/media/camera/docs/docs.html 文件。
参数 | 状态 | 受控制的属性 |
---|---|---|
android.control.aeMode | OFF | 无 |
ON | android.sensor.exposureTime android.sensor.frameDuration android.sensor.sensitivity android.lens.aperture(如果支持的话) android.lens.filterDensity(如果支持的话) | |
ON_AUTO_FLASH | 均已开启,还有 android.flash.firingPower、android.flash.firingTime 和 android.flash.mode | |
ON_ALWAYS_FLASH | 与 ON_AUTO_FLASH 相同 | |
ON_AUTO_FLASH_RED_EYE | 与 ON_AUTO_FLASH 相同 | |
android.control.awbMode | OFF | 无 |
WHITE_BALANCE_* | android.colorCorrection.transform。如果 android.colorCorrection.mode 为 FAST 或 HIGH_QUALITY,则进行特定于平台的调整。 | |
android.control.afMode | OFF | 无 |
FOCUS_MODE_* | android.lens.focusDistance | |
android.control.videoStabilization | OFF | 无 |
ON | 可调整 android.scaler.cropRegion 来实现视频防抖 | |
android.control.mode | OFF | AE、AWB 和 AF 处于停用状态 |
AUTO | 单独使用 AE、AWB 和 AF 设置 | |
SCENE_MODE_* | 可替换上述所有参数。各个 3A 控件均处于停用状态。 |
在图 2 中,图像处理块中的控件都以类似的原理操作,并且每个块一般都具有 3 种模式:
- OFF:该处理块处于停用状态。无法停用去马赛克、色彩校正和色调曲线调整块。
- FAST:与 OFF 模式相比,在这种模式下,处理块可能不会降低输出帧速率,但是考虑到限制条件,它应该会产生能够产生的最优质输出。通常,该模式会用于预览或视频录制模式,或用于连拍静态图像。在一些设备上,该模式可能等同于 OFF 模式(进行任何处理都会降低帧速率);而在另外一些设备上,该模式可能等同于 HIGH_QUALITY 模式(最佳质量仍不会降低帧速率)。
- HIGH_QUALITY:在这种模式下,处理块应尽可能产生最优质结果,根据需要降低输出帧速率。通常,该模式会用于拍摄优质静态图像。一些块包括可以被选中的手动控件(而非 FAST 或 HIGH_QUALITY)。例如,色彩校正块支持颜色变换矩阵,而色调曲线调整支持任意的全局色调映射曲线。
相机子系统可以支持的最大帧速率受到多种因素的影响:
- 所请求的输出图像流的分辨率
- 成像器上像素组合/跳过模式的可用性
- 成像器接口的带宽
- 各种 ISP 处理块的带宽
由于这些因素在不同的 ISP 和传感器之间可能有很大差异,因此相机 HAL 接口会设法将带宽限制抽象为尽可能简单的模型。显示的模型具有以下特性:
- 考虑到应用的请求输出流大小,图像传感器始终配置为输出尽可能最小的分辨率。最小分辨率定义为至少与请求的最大输出流一样大。
- 因为任何请求都可能使用当前配置的任意或所有输出流,所以传感器和 ISP 必须配置为支持将单个捕获同时扩展到所有信息流。
- 对于不包含 JPEG 流的请求,JPEG 流表现得像经过处理的 YUV 流一样;在直接引用它们的请求中,它们用作 JPEG 流。
- JPEG 处理器可以并行运行到相机管道的剩余部分,但不能一次处理多个捕获。
元数据和控件
元数据支持
要支持通过 Android 框架保存原始图片文件,需要具有大量有关传感器特性的元数据,包括色彩空间和镜头遮蔽功能等信息。
其中大多数信息是相机子系统的静态属性,因此可以在配置任何输出管道或提交任何请求之前进行查询。新的相机 API 极大地扩展了 getCameraInfo()
方法提供的信息,以便将此类信息提供给应用。
此外,手动控制相机子系统需要各种设备提供的有关其当前状态的反馈,以及在捕获指定帧时使用的实际参数。必须在输出元数据中包含硬件实际使用的控制(曝光时间、帧时长和感光度)的实际值。这一点至关重要,这样应用就知道限制或舍入何时发生,并且可以补偿用于图片捕获的实际设置。
例如,如果应用在请求中将帧时长设置为 0,则 HAL 必须将帧时长限制到该请求的实际最小帧时长,并在输出结果元数据中报告这一钳位最小持续时间。
因此,如果应用需要实现一个自定义 3A 例程(例如,为了适当地测量 HDR 连拍),则需要知道用于捕获其收到的最新一组结果的设置,以便更新下一个请求的设置。因此,新的相机 API 会向每个捕获的帧添加大量动态元数据。这包括用于捕获的已请求参数和实际参数,以及时间戳和统计信息生成器输出等其他每帧元数据。
每个设置的控制
对于大多数设置而言,它们应该能够随着每一帧发生变化,而不会给输出帧流带来明显的卡顿或延迟。理想情况下,输出帧速率应该仅由捕获请求的帧时长字段控制,且不受处理块配置发生的任何变化影响。实际上,我们已经知道一些特定控制改变的速度偏缓;这些控制包括相机管道的输出分辨率和输出格式,以及镜头焦距等影响物理设备的控制。稍后会详细说明每个控制集的确切要求。
原始传感器数据支持
除了旧 API 支持的像素格式之外,新 API 还添加了对原始传感器数据 (Bayer RAW) 的支持要求,这既适合高级相机应用,又是为了支持原始图片文件。
3A 模式和状态转换
虽然实际的 3A 算法取决于 HAL 实现,但高级状态机的说明由 HAL 接口定义,以支持 HAL 设备和框架就 3A 的当前状态进行通信并触发 3A 事件。
当设备开启时,所有单独的 3A 状态都必须为 STATE_INACTIVE。流配置不会重置 3A。例如,在整个 configure()
调用期间必须保持焦点锁定。
要触发 3A 操作,只需在下一个请求的设置中设置相关触发条目,以指示触发开始即可。例如,若要触发自动对焦扫描的启动操作,只需将相应请求的 ANDROID_CONTROL_AF_TRIGGER 条目设为 ANDROID_CONTROL_AF_TRIGGER_START 即可;若要触发自动对焦扫描的取消操作,只需将 ANDROID_CONTROL_AF_TRIGGER 设为 ANDROID_CONTRL_AF_TRIGGER_CANCEL 即可。否则,条目将会不存在或被设为 ANDROID_CONTROL_AF_TRIGGER_IDLE。凡是具有已设为非 IDLE 值的触发条目的请求,都会被视为独立的触发事件。
在顶层,3A 由 ANDROID_CONTROL_MODE 设置控制。该设置选项包括关闭 3A (ANDROID_CONTROL_MODE_OFF)、正常自动 (AUTO) 模式 (ANDROID_CONTROL_MODE_AUTO),以及使用取景模式设置 (ANDROID_CONTROL_USE_SCENE_MODE):
- 在 OFF 模式下,单个的自动对焦 (AF)、自动曝光 (AE) 和自动白平衡 (AWB) 模式都会有效地关闭,且任何拍摄控件都不会被 3A 例程覆盖。
- 在 AUTO 模式下,AF、AE 和 AWB 模式都会运行各自的独立算法,且具有自己的模式、状态和触发元数据条目,具体如下一节所示。
- 在 USE_SCENE_MODE 下,必须使用 ANDROID_CONTROL_SCENE_MODE 条目的值来确定 3A 例程的行为。在除 FACE_PRIORITY 以外的 SCENE_MODE 下,HAL 必须将 ANDROID_CONTROL_AE/AWB/AF_MODE 的值替换为它倾向于让所选的 SCENE_MODE 使用的模式。例如,HAL 可能倾向于在 SCENE_MODE_NIGHT 下使用 CONTINUOUS_FOCUS AF 模式。当必须忽略这些取景模式下的场景时,用户可随意选择 AE/AWB/AF_MODE。
- 对于 SCENE_MODE_FACE_PRIORITY,AE/AWB/AFMODE 控件的工作方式与在 ANDROID_CONTROL_MODE_AUTO 模式下相同,但 3A 例程必须偏向测光,并对焦到场景中任何已检测到的人脸上。
自动对焦设置与结果条目
主要元数据条目 | |
---|---|
ANDROID_CONTROL_AF_MODE | 用于选择当前的自动对焦模式的控件。由请求设置中的框架进行设置。 |
AF_MODE_OFF | AF 已停用;框架/应用直接控制镜头位置。 |
AF_MODE_AUTO | 单相扫描自动对焦。镜头在该模式下不会移动,除非 AF 被触发。 |
AF_MODE_MACRO | 单相扫描近距离自动对焦。镜头在该模式下不会移动,除非 AF 被触发。 |
AF_MODE_CONTINUOUS_VIDEO | 流畅连续对焦,用于录制视频。触发后会立刻将焦点锁定在当前位置。取消后即会恢复连续对焦。 |
AF_MODE_CONTINUOUS_PICTURE | 快速连续对焦,用于快门零延迟静像拍摄。待当前处于活动状态的扫描结束后,触发即可锁定焦点。取消后即会恢复连续对焦。 |
AF_MODE_EDOF | 高级扩展景深对焦。该模式下没有自动对焦扫描,因此触发或取消操作均无效。图像由 HAL 自动对焦。 |
ANDROID_CONTROL_AF_STATE | 用于描述当前 AF 算法状态的动态元数据,由结果元数据中的 HAL 报告。 |
AF_STATE_INACTIVE | 未进行对焦,或算法被重置。镜头未移动。始终处于 MODE_OFF 或 MODE_EDOF 状态。当设备开启时,必须以此状态启动。 |
AF_STATE_PASSIVE_SCAN | 连续对焦算法目前正在扫描理想对焦。镜头正在移动。 |
AF_STATE_PASSIVE_FOCUSED | 连续对焦算法认为已良好对焦。镜头未移动。HAL 可能会自发退出此状态。 |
AF_STATE_PASSIVE_UNFOCUSED | 连续对焦算法认为未良好对焦。镜头未移动。HAL 可能会自发退出此状态。 |
AF_STATE_ACTIVE_SCAN | 用户触发的扫描正在进行中。 |
AF_STATE_FOCUSED_LOCKED | AF 算法认为已对焦。镜头未移动。 |
AF_STATE_NOT_FOCUSED_LOCKED | AF 算法无法对焦。镜头未移动。 |
ANDROID_CONTROL_AFTRIGGER | 用于启动自动对焦扫描的控件。具体意义取决于模式和状态。由框架在请求设置中进行设置。 |
AF_TRIGGER_IDLE | 当前未触发。 |
AF_TRIGGER_START | 触发 AF 扫描的启动操作。扫描效果取决于模式和状态。 |
AF_TRIGGER_CANCEL | 取消当前 AF 扫描(如有),并将算法重置为默认值。 |
其他元数据条目 | |
---|---|
ANDROID_CONTROL_AF_REGIONS | 用于选择为确定良好对焦而需使用的视野 (FOV) 区域的控件。该控件适用于所有可扫描对焦的 AF 模式。由框架在请求设置中进行设置。 |
自动曝光设置与结果条目
主要元数据条目 | |
---|---|
ANDROID_CONTROL_AE_MODE | 用于选择当前自动曝光模式的控件。由请求设置中的框架进行设置。 |
AE_MODE_OFF | 自动曝光已停用;用户控制曝光、增益、帧时长和闪光。 |
AE_MODE_ON | 标准自动曝光,闪光灯控件已停用。用户可以将闪光灯设为触发或手电筒模式。 |
AE_MODE_ON_AUTO_FLASH | 标准自动曝光,闪光灯听从 HAL 指令开启,以进行预拍摄和静像拍摄。允许用户控制闪光灯的功能已停用。 |
AE_MODE_ON_ALWAYS_FLASH | 标准自动曝光,闪光灯始终触发以进行拍摄,并听从 HAL 指令进行预拍摄。允许用户控制闪光灯的功能已停用。 |
AE_MODE_ON_AUTO_FLASH_REDEYE | 标准自动曝光,闪光灯听从 HAL 指令开启,以进行预拍摄和静像拍摄。在预拍摄序列结束时使用闪光灯连拍,以减轻最终照片中的红眼现象。允许用户控制闪光灯的功能已停用。 |
ANDROID_CONTROL_AE_STATE | 描述当前 AE 算法状态的动态元数据,在结果元数据中由 HAL 报告。 |
AE_STATE_INACTIVE | 切换模式后的初始 AE 状态。当设备开启时,必须以此状态启动。 |
AE_STATE_SEARCHING | AE 没有聚焦到一个理想值,且正在调整曝光参数。 |
AE_STATE_CONVERGED | AE 已经为当前场景找到了理想曝光值,且曝光参数不会变化。HAL 可能会自发退出此状态,以寻找更好的解决方案。 |
AE_STATE_LOCKED | AE 已通过 AE_LOCK 控件进行锁定。曝光值不变。 |
AE_STATE_FLASH_REQUIRED | HAL 已聚焦曝光,但认为需要启动闪光灯才能保证照片亮度充足。用于确定是否可使用零快门延迟帧。 |
AE_STATE_PRECAPTURE | HAL 正在处理预拍序列。根据 AE 模式,该模式可能包括触发闪光灯以进行测光,或发出闪光脉冲以减轻红眼现象。 |
ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER | 用于在拍摄高品质图像之前启动测光序列的控件。由框架在请求设置中进行设置。 |
PRECAPTURE_TRIGGER_IDLE | 当前未触发。 |
PRECAPTURE_TRIGGER_START | 启动预拍序列。HAL 应使用后续请求进行衡量并达到理想的曝光/白平衡,以便接下来拍摄高分辨率的照片。 |
其他元数据条目 | |
---|---|
ANDROID_CONTROL_AE_LOCK | 用于将 AE 控件锁定到其当前值的控件。 |
ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION | 用于调整 AE 算法目标亮度点的控件。 |
ANDROID_CONTROL_AE_TARGET_FPS_RANGE | 用于为 AE 算法选择目标帧速率范围的控件。AE 例程无法将帧速率变为超出这些范围的值。 |
ANDROID_CONTROL_AE_REGIONS | 用于选择应该用于确定良好曝光水平的 FOV 区域的控件。该控件适用于除 OFF 模式外的所有 AE 模式。 |
自动白平衡设置和结果条目
主要元数据条目 | |
---|---|
ANDROID_CONTROL_AWB_MODE | 用于选择当前白平衡模式的控件。 |
AWB_MODE_OFF | 自动白平衡已停用。用户控制颜色矩阵。 |
AWB_MODE_AUTO | 自动白平衡已启用。3A 控制颜色变换,使用的变换方式可能比简单矩阵更复杂。 |
AWB_MODE_INCANDESCENT | 适用于室内白炽灯(钨丝)照明的固定白平衡设置,约为 2700K。 |
AWB_MODE_FLUORESCENT | 适用于荧光灯照明的固定白平衡设置,约为 5000K。 |
AWB_MODE_WARM_FLUORESCENT | 适用于荧光灯照明的固定白平衡设置,约为 3000K。 |
AWB_MODE_DAYLIGHT | 适用于日光的固定白平衡设置,约为 5500K。 |
AWB_MODE_CLOUDY_DAYLIGHT | 适用于多云日光的固定白平衡设置,约为 6500K。 |
AWB_MODE_TWILIGHT | 适用于近日落/日出的固定白平衡设置,约为 15000K。 |
AWB_MODE_SHADE | 适用于非阳光直射区域的固定白平衡设置,约为 7500K。 |
ANDROID_CONTROL_AWB_STATE | 描述当前 AWB 算法状态的动态元数据,在结果元数据中由 HAL 报告。 |
AWB_STATE_INACTIVE | 切换模式后的初始 AWB 状态。当设备开启时,必须以此状态启动。 |
AWB_STATE_SEARCHING | AWB 未聚焦为一个理想值,正在改变颜色调整参数。 |
AWB_STATE_CONVERGED | AWB 已发现适用于当前场景的理想颜色调整值,参数不会更改。HAL 可能会自发退出此状态以寻找更好的解决方案。 |
AWB_STATE_LOCKED | AWB 已由 AWB_LOCK 控件锁定。颜色调整值不会更改。 |
其他元数据条目 | |
---|---|
ANDROID_CONTROL_AWB_LOCK | 用于将 AWB 颜色调整锁定为当前值的控件。 |
ANDROID_CONTROL_AWB_REGIONS | 用于选择应该用于确定良好色彩平衡的 FOV 区域的控件。该模式仅适用于自动白平衡模式。 |
一般状态机转换说明
在 AF、AE 和 AWB 模式之间进行切换一律会将算法状态重置为 INACTIVE 状态。同样,如果 CONTROL_MODE == USE_SCENE_MODE,在 CONTROL_MODE 和 CONTROL_SCENE_MODE 之间进行切换也会将所有算法状态重置为 INACTIVE 状态。
下表列出了各模式的情况。
AF 状态机
模式 = AF_MODE_OFF 或 AF_MODE_EDOF | |||
---|---|---|---|
状态 | 转换原因 | 新状态 | 备注 |
INACTIVE | AF 已停用 |
模式 = AF_MODE_AUTO 或 AF_MODE_MACRO | |||
---|---|---|---|
状态 | 转换原因 | 新状态 | 备注 |
INACTIVE | AF_TRIGGER | ACTIVE_SCAN |
开始 AF 扫描 镜头正在移动 |
ACTIVE_SCAN | AF 扫描已完成 | FOCUSED_LOCKED |
若 AF 成功 镜头现已锁定 |
ACTIVE_SCAN | AF 扫描已完成 | NOT_FOCUSED_LOCKED |
若 AF 成功 镜头现已锁定 |
ACTIVE_SCAN | AF_CANCEL | INACTIVE |
取消/重置 AF 镜头现已锁定 |
FOCUSED_LOCKED | AF_CANCEL | INACTIVE | 取消/重置 AF |
FOCUSED_LOCKED | AF_TRIGGER | ACTIVE_SCAN |
开始新的扫描 镜头正在移动 |
NOT_FOCUSED_LOCKED | AF_CANCEL | INACTIVE | 取消/重置 AF |
NOT_FOCUSED_LOCKED | AF_TRIGGER | ACTIVE_SCAN |
开始新的扫描 镜头正在移动 |
所有状态 | 模式更改 | INACTIVE |
模式 = AF_MODE_CONTINUOUS_VIDEO | |||
---|---|---|---|
状态 | 转换原因 | 新状态 | 备注 |
INACTIVE | HAL 启动新的扫描 | PASSIVE_SCAN |
开始 AF 扫描 镜头正在移动 |
INACTIVE | AF_TRIGGER | NOT_FOCUSED_LOCKED |
AF 状态查询 镜头现已锁定 |
PASSIVE_SCAN | HAL 完成当前扫描 | PASSIVE_FOCUSED |
结束 AF 扫描 镜头现已锁定 |
PASSIVE_SCAN | AF_TRIGGER | FOCUSED_LOCKED |
若对焦理想,则立即转换 镜头现已锁定 |
PASSIVE_SCAN | AF_TRIGGER | NOT_FOCUSED_LOCKED |
若对焦不良,则立即转换 镜头现已锁定 |
PASSIVE_SCAN | AF_CANCEL | INACTIVE |
重置镜头位置 镜头现已锁定 |
PASSIVE_FOCUSED | HAL 启动新的扫描 | PASSIVE_SCAN |
开始 AF 扫描 镜头正在移动 |
PASSIVE_FOCUSED | AF_TRIGGER | FOCUSED_LOCKED |
若对焦理想,则立即转换 镜头现已锁定 |
PASSIVE_FOCUSED | AF_TRIGGER | NOT_FOCUSED_LOCKED | 若对焦不良,则立即转换
镜头现已锁定 |
FOCUSED_LOCKED | AF_TRIGGER | FOCUSED_LOCKED | 无效果 |
FOCUSED_LOCKED | AF_CANCEL | INACTIVE | 重新启动 AF 扫描 |
NOT_FOCUSED_LOCKED | AF_TRIGGER | NOT_FOCUSED_LOCKED | 无效果 |
NOT_FOCUSED_LOCKED | AF_CANCEL | INACTIVE | 重新启动 AF 扫描 |
模式 = AF_MODE_CONTINUOUS_PICTURE | |||
---|---|---|---|
状态 | 转换原因 | 新状态 | 备注 |
INACTIVE | HAL 启动新的扫描 | PASSIVE_SCAN |
开始 AF 扫描 镜头正在移动 |
INACTIVE | AF_TRIGGER | NOT_FOCUSED_LOCKED |
AF 状态查询 镜头现已锁定 |
PASSIVE_SCAN | HAL 完成当前扫描 | PASSIVE_FOCUSED | 结束 AF 扫描
镜头现已锁定 |
PASSIVE_SCAN | AF_TRIGGER | FOCUSED_LOCKED |
一旦对焦理想,则进行最终转换 镜头现已锁定 |
PASSIVE_SCAN | AF_TRIGGER | NOT_FOCUSED_LOCKED |
若无法对焦,则进行最终转换 镜头现已锁定 |
PASSIVE_SCAN | AF_CANCEL | INACTIVE |
重置镜头位置 镜头现已锁定 |
PASSIVE_FOCUSED | HAL 启动新的扫描 | PASSIVE_SCAN |
开始 AF 扫描 镜头正在移动 |
PASSIVE_FOCUSED | AF_TRIGGER | FOCUSED_LOCKED |
若对焦理想,则立即转换 镜头现已锁定 |
PASSIVE_FOCUSED | AF_TRIGGER | NOT_FOCUSED_LOCKED |
若对焦不良,则立即转换 镜头现已锁定 |
FOCUSED_LOCKED | AF_TRIGGER | FOCUSED_LOCKED | 无效果 |
FOCUSED_LOCKED | AF_CANCEL | INACTIVE | 重新启动 AF 扫描 |
NOT_FOCUSED_LOCKED | AF_TRIGGER | NOT_FOCUSED_LOCKED | 无效果 |
NOT_FOCUSED_LOCKED | AF_CANCEL | INACTIVE | 重新启动 AF 扫描 |
AE 和 AWB 状态机
AE 和 AWB 状态机大致上相同,但 AE 具有额外的 FLASH_REQUIRED 和 PRECAPTURE 状态。因此,对于 AWB 状态机,应忽略下表中这两个状态对应的行。
模式 = AE_MODE_OFF/AWB 模式不是 AUTO | |||
---|---|---|---|
状态 | 转换原因 | 新状态 | 备注 |
INACTIVE | AE/AWB 已停用 |
模式 = AE_MODE_ON_ * / AWB_MODE_AUTO | |||
---|---|---|---|
状态 | 转换原因 | 新状态 | 备注 |
INACTIVE | HAL 启动 AE/AWB 扫描 | SEARCHING | |
INACTIVE | AE/AWB_LOCK 已开启 | LOCKED | 值已锁定 |
SEARCHING | HAL 完成 AE/AWB 扫描 | CONVERGED | 理想值,不作改变 |
SEARCHING | HAL 完成 AE 扫描 | FLASH_REQUIRED | 已聚焦,但无闪光灯导致过暗 |
SEARCHING | AE/AWB_LOCK 已开启 | LOCKED | 值已锁定 |
CONVERGED | HAL 启动 AE/AWB 扫描 | SEARCHING | 值已锁定 |
CONVERGED | AE/AWB_LOCK 已开启 | LOCKED | 值已锁定 |
FLASH_REQUIRED | HAL 启动 AE/AWB 扫描 | SEARCHING | 值已锁定 |
FLASH_REQUIRED | AE/AWB_LOCK 已开启 | LOCKED | 值已锁定 |
LOCKED | AE/AWB_LOCK 已关闭 | SEARCHING | 解锁后值不理想 |
LOCKED | AE/AWB_LOCK 已关闭 | CONVERGED | 解锁后值理想 |
LOCKED | AE_LOCK 已关闭 | FLASH_REQUIRED | 曝光良好但过暗 |
所有 AE 状态 | PRECAPTURE_START | PRECAPTURE | 开始预拍序列 |
PRECAPTURE | 序列完成,AE_LOCK 已关闭 | CONVERGED | 高质量拍摄就绪 |
PRECAPTURE | 序列完成,AE_LOCK 已开启 | LOCKED | 高质量拍摄就绪 |
启用手动控制
配置设备 3A 块以实现直接应用控制的过程还涉及到多个控件。
用于 3A 控制的 HAL 模式的运作方式为:对于每个请求,HAL 都会检查 3A 控制字段的状态。如果启用了任何 3A 例程,则该例程会覆盖与该例程相关的控制变量,然后这些覆盖值会在该拍摄的结果元数据中提供。例如,如果在请求中启用自动曝光,则 HAL 应覆盖请求的曝光、增益和帧时长字段(还可能包括闪光灯字段,具体取决于 AE 模式)。相关控件如下:
控件名称 | 单位 | 备注 |
---|---|---|
android.control.mode | 枚举:OFF、AUTO、USE_SCENE_MODE | 高级 3A 控制。当设为 OFF 时,所有由 HAL 启用的 3A 控件都会被停用。应用必须为拍摄参数本身设置字段。当设为 AUTO 时,android.control.* 中的单个算法控件(例如 android.control.afMode)会生效。当设为 USE_SCENE_MODE 时,android.control.* 中的各控件大都被停用;HAL 根据需要,实现其中的一个场景模式设置(如 ACTION、SUNSET 或 PARTY)。 |
android.control.afMode | 枚举 | OFF 表示使用 android.lens.focusDistance 手动控制镜头对焦。 |
android.control.aeMode | 枚举 | OFF 表示使用 android.sensor.exposureTime / .sensitivity / .frameDuration 手动控制曝光/增益/帧时长。 |
android.control.awbMode | 枚举 |
OFF 表示手动控制白平衡。 |
创建和提交请求
默认请求
要构建默认捕获请求,请调用 ICameraDeviceSession::constructDefaultRequestSettings()
。
提交请求
要提交相机捕获请求,请调用 ICameraDeviceSession::processCaptureRequest()
。
其他方法
请求/结果消息队列
相机捕获结果和请求 IPC 开销可通过快速消息队列进一步优化。调用 ICameraDeviceSession::getCaptureRequestMetadataQueue()
和 ICameraDeviceSession::getCaptureResultMetadataQueue()
方法可查询相应的队列。
刷新请求
要清空所有待处理的捕获请求,请调用 ICameraDeviceSession::flush()
。
Stream Configurations
Android 10 introduces features allowing camera clients to choose optimal camera streams for specific use cases and to ensure that certain stream combinations are supported by the camera device. A stream configurationrefers to a single camera stream configured in the camera device and a stream combination refers to one or more sets of streams configured in the camera device. For more on these features, see recommended stream configurations and API to query stream combinations.
Reference implementation
There is a vendor-side reference implementation of the recommended configuration streams and the API to query stream combination features. You can find this implementation at QCamera3HWI.cpp
Recommended stream configurations
Camera vendors can advertise recommended stream configurations for specific use cases to camera clients. These recommended stream configurations, which are subsets of StreamConfigurationMap, can help camera clients choose optimal configurations.
Although StreamConfigurationMap provides exhaustive stream configuration information to camera clients, it doesn't provide any information about the efficiency, power, or performance impacts of choosing one stream over another. Camera clients can freely choose from all the possible stream configurations but in many cases, this leads to clients using sub-optimal camera configurations and applications making time-consuming exhaustive searches.
For example, although some processed YUV formats are required and must be supported, the camera device might not have native support for the formats. This results in an additional processing pass for the format conversion and reduces efficiency. The size and corresponding aspect ratio can also have a similar impact making particular dimensions preferable in terms of power and performance.
Your recommended stream configuration maps aren't required to be exhaustive compared to theStreamConfigurationMap. The suggested configuration maps must follow the requirements in theimplementation section and can include any of the available formats, sizes, or other values found inStreamConfigurationMap. Hidden formats, sizes, or other values not found in StreamConfigurationMap can't be included in recommended stream configuration maps.
All tests remain unchanged and aren't relaxed depending on the recommended stream configurations.
The recommended stream configurations provided by the camera implementation are optional and the camera client can ignore them.
Implementation
Follow these steps to implement this feature.
Metadata entries
To enable this feature the Camera HAL must populate the following static metadata entries:
-
android.scaler.availableRecommendedStreamConfigurations
: The recommended subset of stream configurations for specific use cases. The declaration uses simple bitmaps indicating the suggested use cases in the form of[1 << PREVIEW | 1 << RECORD..]
. The use cases extend the regular (format, width, height, input) tuple with one additional entry. Non-existing public use cases or any other bits set within the range[PUBLIC_END, VENDOR_START]
are prohibited.This information is stored in the
availableRecommendedStreamConfigurations
metadata tag.The following example shows an array for a recommended stream configuration for a camera device that only supports 4K and 1080p, where both resolutions are preferred for video recording but only 1080p is suggested for preview.
Note: The above array example only illustrates one particular scenario and isn't complete. The complete final array must include the recommended stream configurations for all required use cases mentioned below.[3840, 2160, HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED,
ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,
(1 << ANDROID_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_RECORD |
1 << ANDROID_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_SNAPSHOT |
1 << ANDROID_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_VIDEO_SNAPSHOT),
1920, 1080, HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED,
ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,
(1 << ANDROID_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_PREVIEW |
1 << ANDROID_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_RECORD |
1 << ANDROID_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_SNAPSHOT |
1 << ANDROID_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_VIDEO_SNAPSHOT)] -
android.depth.availableRecommendedDepthStreamConfigurations
(available only if supported by device): The recommended depth dataspace stream configurations suggested for this camera device. Similar to the above metadata entry, an additional use case bitmap indicates the suggested use cases.This information is stored in the
availableRecommendedInputOutputFormatsMap
metadata tag. -
android.scaler.availableRecommendedInputOutputFormatsMap
(available only if supported by device): The mapping of recommended image formats that are suggested for this camera device for input streams, to their corresponding output formats.This information is stored in the
availableRecommendedDepthStreamConfigurations
metadata tag.
This information is available to camera clients through the RecommendedStreamConfigurationMap API.
Required use cases
Recommended stream configurations must be provided for the following use cases and meet the corresponding requirements:
Use case | Requirement |
---|---|
PREVIEW |
A preview must only include non-stalling processed stream configurations with output formats such as YUV_420_888 and IMPLEMENTATION_DEFINED . |
RECORD |
A video record must include stream configurations that match the advertised supported media profiles with the IMPLEMENTATION_DEFINED format. |
VIDEO_SNAPSHOT |
A video snapshot must include stream configurations that are at least as large as the maximum RECORD resolutions and only with the BLOB + DATASPACE_JFIF format/dataspace combination (JPEG). The configurations should not cause preview glitches and should be able to run at 30 fps. |
SNAPSHOT |
Snapshot stream configurations must include at least one with a size close to android.sensor.info.activeArraySize with the BLOB + DATASPACE_JFIF format/dataspace combination (JPEG). Taking into account restrictions on aspect ratio, alignment, and other vendor-specific restrictions, the area of the maximum suggested size should not be less than 97% of the sensor array size area. |
ZSL (if supported) |
If supported by the camera device, recommended input stream configurations must only be advertised together with other processed or stalling output formats. |
RAW (if supported) |
If supported by the camera device, recommended raw stream configurations must only include RAW based output formats. |
Other use cases
You can provide additional recommended configuration streams for use cases specific to your implementation.
Validation
To test your implementation of the recommended configuration streams, run the following CTS and VTS tests:
API to query stream combinations
The Android platform supports an API to query stream combinations. Implementing this API allows camera clients to safely query stream combinations at any point after receiving a valid CameraDevice instance, removing the overhead of initializing a camera capture session and the potential of having subsequent camera exceptions including camera breakage, and allowing for faster queries.
This feature also allows camera clients to receive a list of stream combinations compiled according to theguidelines for CameraDevice and the supported HW level. CTS tests are available to enforce the correctness of query results as much as possible covering a minor subset of the most common stream combinations.
You can choose to support this feature by implementing one additional HIDL API call in the Camera HAL.
Implementation
To support an API to query stream combinations, the Camera HAL must provide an implementation for theisStreamCombinationSupported
HIDL API interface. This interface checks whether the camera device supports a specified camera stream combination.
When called, the API must return one of the following status codes:
OK
: The stream combination query was successful.METHOD_NOT_SUPPORTED
: The camera device does not support the stream combination query.INTERNAL_ERROR
: The stream combination query cannot complete due to an internal error.
The API returns true if the stream combination is supported. Otherwise, it returns false.
The framework uses the public API isSessionConfigurationSupported
to check whether the particular session configuration is supported by the camera device.
Calls to the API must not have any side effects on normal camera operation. API calls must not alter any internal states or slow down the camera performance. Make sure that after the Camera HAL successfully validates a stream combination, camera clients can successfully configure the stream combination. To avoid issues, make sure the implementation does not store any information during stream combination queries, change its internal state, or engage in time-consuming operations.
Validation
To validate this feature, run the following Camera CTS and VTS test cases:
Camera CTS modules:
Camera VTS:
VtsHalCameraProviderV2_4TargetTest.cpp
错误和信息流处理
错误管理
与摄像头交互的 HIDL 接口方法必须生成相应的摄像头特定状态。
如果调用了 ICameraDeviceCallbacks::notify()
且返回 ERROR_DEVICE
,则只能成功调用 ICameraDeviceSession::close()
方法。其他所有方法都将返回 INTERNAL_ERROR
。
图像拍摄过程中的瞬时错误必须通过 ICameraDeviceCallbacks::notify()
进行报告且返回相应的错误代码。在发生各种瞬时失败的情况下,HAL 必须仍然调用 ICameraDeviceCallbacks::processCaptureResult()
且返回相应的捕获结果。
信息流管理
HAL 客户端必须通过调用 ICameraDeviceSession::configurestreams()
来配置摄像头信息流。
输出流和剪裁
输出流
相机子系统针对所有分辨率和输出格式都仅在基于 ANativeWindow 的管道上运行。您可以一次配置多个流,以便将单个帧发送至多个目标,例如:GPU、视频编码器、RenderScript,或应用可见的缓冲区(RAW Bayer 缓冲区、经处理的 YUV 缓冲区或经 JPEG 编码的缓冲区)。
出于优化的目的,这些输出流必须提前配置,而且只有有限的输出流可同时存在。这样一来,就可以预先分配内存缓冲区和配置相机硬件,以便在提交列有多个或者不同输出管道的请求时,不会出现请求延迟执行的情况。
如需详细了解取决于支持的硬件级别的保证流输出组合,请参阅 createCaptureSession()
。
剪裁
完整像素阵列的剪裁(用于数字变焦和需要更小 FOV 的其他使用情况)通过 ANDROID_SCALER_CROP_REGION 设置进行传递。这个设置可按需更改,这种方式对于实现平滑的数字变焦至关重要。
该区域被定义为矩形(x 和 y 分别表示宽和高),其中 (x,y) 表示矩形的左上角。该矩形在传感器有源像素阵列的坐标系中进行定义,其中 (0,0) 对应有源像素阵列的左上角像素。因此,宽度和高度不能大于 ANDROID_SENSOR_ACTIVE_PIXEL_ARRAY 静态信息字段中所报告的尺寸。允许的最小宽度和高度由 HAL 通过 ANDROID_SCALER_MAX_DIGITAL_ZOOM 静态信息字段进行报告,该字段描述了所支持的缩放因子的最大值。因此,最小剪裁区域的宽度和高度为:
{width, height} = { floor(ANDROID_SENSOR_ACTIVE_PIXEL_ARRAY[0] / ANDROID_SCALER_MAX_DIGITAL_ZOOM), floor(ANDROID_SENSOR_ACTIVE_PIXEL_ARRAY[1] / ANDROID_SCALER_MAX_DIGITAL_ZOOM) }
如果剪裁区域需要满足特定需求(例如:要求起始位置坐标为偶数,并且其宽度/高度需均为偶数),则 HAL 必须进行必要的舍入运算,并写出输出结果元数据中所用的最终剪裁区域。同样,HAL 要实现视频防抖功能,则必须调整结果剪裁区域,以描述在应用视频防抖功能后输出结果中实际包含的区域。一般情况下,使用相机的应用必须能够根据剪裁区域、图像传感器的尺寸和镜头焦距确定其接收的视野范围。
由于剪裁区域适用于所有视频流,这些视频流的宽高比可能与剪裁区域的不同,所以每路视频流所用的实际传感器区域可能小于剪裁区域。具体而言,每路视频流应尽量避免进一步剪裁已定义的剪裁区域,以维持方形像素及其宽高比。如果视频流的宽高比大于剪裁区域,则该视频流应该在垂直方向上进一步剪裁,如果视频流的宽高比小于剪裁区域,则该视频流应该在水平方向上进一步剪裁。
在所有情况下,视频流剪裁均必须位于整个剪裁区域的中心位置,并且相对于整个剪裁区域,每路视频流要么在水平方向上进行剪裁,要么在垂直方向上进行剪裁,但绝不能在这两个方向上同时进行剪裁。
例如,如果两路视频流分别定义为 640x480(宽高比为 4:3)和 1280x720(宽高比为 16:9),并假设传感器为 300 万像素级(2000 x 1500 像素阵列),则下面展示了针对几个样本剪裁区域,每路视频流的预期输出区域。
剪裁区域:(500、375、1000、750)(宽高比为 4:3)
640x480 视频流剪裁:(500、375、1000、750)(与剪裁区域相同)
1280x720 视频流剪裁:(500、469、1000、562)
剪裁区域:(500、375、1333、750)(宽高比为 16:9)
640x480 视频流剪裁:(666、375、1000、750)
1280×720 视频流剪裁:(500、375、1333、750)(与剪裁区域相同)
剪裁区域:(500、375、750、750)(宽高比为 1:1)
640x480 视频流剪裁:(500、469、750、562)
1280x720 视频流剪裁:(500、543、750、414)
最后一个示例是宽高比为 1024×1024(方形)的视频流,而不是 480p 视频流:
剪裁区域:(500、375、1000、750)(宽高比为 4:3)
1024x1024 视频流剪裁:(625、375、750、750)
1280x720 视频流剪裁:(500、469、1000、562)
重新处理
对原始图片文件提供额外的支持功能,即 RAW Bayer 数据重新处理支持功能。该支持功能允许相机管道处理之前捕获的 RAW 缓冲区和元数据(之前记录的整个帧),以生成新渲染的 YUV 或 JPEG 输出。
会话参数
在捕获会话初始化阶段,会话参数功能使摄像头客户端可以主动配置一部分耗时较长的请求参数(即会话参数),从而减少延迟。借助此功能,您的 HAL 实现会在信息流配置阶段(而不是第一个捕获请求期间)接收客户端参数,并且可以根据它们的值更高效地准备和构建内部流水线。
在 Android 10 中,您可以使用可选的会话重新配置查询功能来更好地控制内部会话参数重新配置逻辑,从而提高性能。如需了解详情,请参阅会话重新配置查询。
示例和来源
参考会话参数实现已经是 CameraHal 的一部分。此 HAL 使用旧版 Hal API。实现 Camera HIDL API 的绑定式CameraHal 必须使用相应的 HIDL sessionParams 条目在信息流配置期间访问所有新的传入会话参数。
摄像头客户端可以通过调用 getAvailableSessionKeys()
来查询所有受支持的会话参数的密钥,并最终通过 setSessionParameters()
设置它们的初始值。
实现
您的 CameraHal 实现必须在相应的静态摄像头元数据中填充 ANDROID_REQUEST_AVAILABLE_SESSION_KEYS
,并提供 ANDROID_REQUEST_AVAILABLE_REQUEST_KEYS
的一个子集(其中包含难以按帧应用的密钥的列表,如果在捕获会话生命周期内修改这些密钥,则可能会导致意外延迟)。
典型示例包括:需要耗费时间重新配置硬件或更改内部摄像头流水线的参数。控制会话参数仍然可以在捕获请求中发挥作用,不过,客户端应意识到并预料到其应用会出现延迟。
框架会监控所有传入请求,如果它检测到会话参数值发生变化,则会在内部重新配置相机。然后,已传递到 CameraHal 的新流配置中会包含更新后的会话参数值(用于更高效地配置相机流水线)。
自定义
您可以在 CameraHal 端填充的可用会话参数列表中定义标记。如果 CameraHal 将可用会话参数列表留空,则此功能无效。
验证
CTS 提供以下用于测试会话参数的新用例:
CameraDeviceTest#testSessionConfiguration
CameraDeviceTest#testCreateSessionWithParameters
CameraDeviceTest#testSessionParametersStateLeak
NativeCameraDeviceTest#testCameraDevicePreviewWithSessionParameters
通常,在某个参数成为会话密钥列表的一部分之后,其当前值就会添加到在信息流配置期间在 HAL 层传递的会话参数中。
选择会话参数时请务必谨慎。不应频繁更改流配置之间的会话参数值(如果有的话)。如果参数频繁更改(例如出于捕获目的),其适用性会非常低;如果将此类参数添加到会话参数列表中,则可能会因内部重新配置过多而导致 CTS 问题。
会话重新配置查询
Android 10 引入了可选的会话重新配置查询功能来提高性能,因为会话参数值修改导致的内部信息流重新配置会降低性能。为了解决此问题,HIDL ICameraDeviceSession
3.5 及更高版本支持 isReconfigurationRequired
方法,该方法提供对内部会话参数重新配置逻辑的精细控制。使用此方法,可在需要时精确地进行信息流重新配置。
isReconfigurationRequired
的参数提供有关每个待修改会话参数的必需信息,允许针对各种设备进行自定义。
此功能仅在摄像头服务和相机 HAL 中实现。没有面向公众的 API。如果实现此功能,则摄像头客户端在使用会话参数时的性能应该有明显的提升。
实现
要支持会话重新配置查询,您必须实现 isReconfigurationRequired
方法来检查新会话参数值是否需要完整的信息流重新配置。
如果客户端更改任何通告的会话参数的值,则摄像头传输框架会调用 isReconfigurationRequired
方法。根据具体值,HAL 决定是否需要完整的信息流重新配置。如果 HAL 返回 false
,则摄像头传输框架会跳过内部重新配置。如果 HAL 返回 true
,则框架会重新配置信息流并相应地传递新的会话参数值。
在使用新参数的请求提交给 HAL 之前,框架可以调用 isReconfigurationRequired
方法,并且可以在该请求提交之前将其取消。因此,HAL 不得使用此方法调用以任何方式更改其行为。
HAL 实现必须满足以下要求:
- 在配置活动会话后,框架必须能够随时调用
isReconfigurationRequired
方法。 - 必须不能对待处理的摄像头请求的性能产生影响。特别是,在正常的摄像头流式传输期间,不得有任何故障或延迟。
设备和 HAL 实现必须满足以下性能方面的要求:
- 不得更改硬件和软件摄像头设置。
- 不得对摄像头性能造成用户可见的影响。
isReconfigurationRequired
方法采用以下参数:
oldSessionParams
:上一个会话的会话参数。通常是现有的会话参数。newSessionParams
:客户端设置的新会话参数。
预期的返回状态代码包括:
OK
:成功重新配置所需的查询。METHOD_NOT_SUPPORTED
:摄像头设备不支持重新配置查询。INTERNAL_ERROR
:由于内部错误,重新配置查询无法完成。
返回值包括:
true
:需要进行信息流重新配置。false
:不需要进行信息流重新配置。
要忽略会话重新配置查询,HAL 应返回 METHOD_NOT_SUPPORTED
或 false
。这会导致默认的摄像头服务行为,其中在每个会话参数更改时触发信息流重新配置。
验证
可以使用 CameraHidlTest#configureStreamsWithSessionParameters
中的 VTS 测试用例验证会话重新配置查询功能。
“单个生产者-多个消费者”摄像头缓冲区传输
该功能引入了一组方法,当拍摄会话处于活动状态且摄像头流式传输正在进行时,摄像头客户端可通过该功能动态添加和移除输出 Surface。新的输出可以映射到用户选择的特定共享摄像头信息流。Surface 添加后,您可以随时将其移除。
总的想法是,在多个输出 Surface 中共享与特定摄像头信息流关联的缓冲区。当缓冲区准备好在消费者端进行进一步处理时,内部引用计数器便开始跟踪缓冲区。当所有消费者完成各自的任务后,缓冲区便会离开队列,并可供摄像头使用。
图 1. 缓冲区共享
图 1 描绘了一个示例场景:系统采用动态方式连接和分离由摄像头信息流 2 处理的缓冲区,并由摄像头服务内的专用共享输出流内部的信息流分流器组件对引用进行计数和管理。
示例和源代码
可在 Camera3StreamSplitter
模块中找到该功能的核心实现,并可在面向开发者的参考资料中找到关于该功能的文档:
实现
摄像头 HAL 端不需要任何实现,因为该功能在框架端实现。
验证
您的实现必须通过 MultiViewTest 模块中以及本机 API 的本机 JNI 库中涵盖该功能的 CTS 测试。
Camera HAL3 Buffer Management APIs
Android 10 introduces optional camera HAL3 buffer management APIs that allow you to implement buffer management logic to achieve different memory and capture latency tradeoffs in camera HAL implementations.
The camera HAL requires N requests (where N is equal to the pipeline depth) queued in its pipeline, but it often doesn't require all N sets of output buffers at the same time.
For example, the HAL might have eight requests queued in the pipeline, but it only requires output buffers for the two requests in the last stages of the pipeline. On devices running Android 9 and lower, the camera framework allocates buffers when the request is queued in the HAL so there could be six sets of buffers in the HAL that aren't in use. In Android 10, the camera HAL3 buffer management APIs allow for the decoupling of the output buffers to free up the six sets of buffers. This can lead to hundreds of megabytes of memory savings on high-end devices and can also be beneficial for low-memory devices.
Figure 1 shows a diagram of the camera HAL interface for devices running Android 9 and lower. Figure 2 shows the camera HAL interface in Android 10 with the camera HAL3 buffer management APIs implemented.
Figure 1. Camera HAL interface in Android 9 and lower
Figure 2. Camera HAL interface in Android 10 using the buffer management APIs
Implementing the buffer management APIs
To implement the buffer management APIs, the camera HAL must:
- Implement HIDL
ICameraDevice@3.5
. - Set the camera characteristics key
android.info.supportedBufferManagementVersion
toHIDL_DEVICE_3_5
.
The camera HAL uses the requestStreamBuffers
and returnStreamBuffers
methods inICameraDeviceCallback.hal
to request and return buffers. The HAL must also implement thesignalStreamFlush
method in ICameraDeviceSession.hal
to signal the camera HAL to return buffers.
requestStreamBuffers
Use the requestStreamBuffers
method to request buffers from the camera framework. When using the camera HAL3 buffer management APIs, capture requests from the camera framework don't contain output buffers, that is, the bufferId
field in StreamBuffer
is 0
. Therefore, the camera HAL must use requestStreamBuffers
to request buffers from the camera framework.
The requestStreamBuffers
method allows the caller to request multiple buffers from multiple output streams in a single call, allowing for fewer HIDL IPC calls. However, calls take more time when more buffers are requested at the same time and this might negatively affect the total request-to-result latency. Also, because calls into requestStreamBuffers
are serialized in the camera service, it's recommended that the camera HAL use a dedicated high-priority thread to request buffers.
If a buffer request fails, the camera HAL must be able to properly handle nonfatal errors. The following list describes common reasons that buffer requests fail and how they should be handled by the camera HAL.
- App disconnects from the output stream: This is a nonfatal error. The camera HAL should send
ERROR_REQUEST
for any capture request targeting a disconnected stream and be ready to process subsequent requests normally. - Timeout: This can occur when an app is busy doing intensive processing while holding onto some buffers. The camera HAL should send
ERROR_REQUEST
for capture requests that can't be fulfilled due to a timeout error and be ready to process subsequent requests normally. - Camera framework is preparing a new stream configuration: The camera HAL should wait until the next
configureStreams
call is complete before callingrequestStreamBuffers
again. - The camera HAL has reached its buffer limit (the
maxBuffers
field): The camera HAL should wait until it returns at least one buffer of the stream before callingrequestStreamBuffers
again.
returnStreamBuffers
Use the returnStreamBuffers
method to return extra buffers to the camera framework. The camera HAL normally returns buffers to the camera framework through the processCaptureResult
method, but it can only account for capture requests that have been sent to the camera HAL. With the requestStreamBuffers
method, it's possible for the camera HAL implementation to retain more buffers than what has been requested by the camera framework. This is when the returnStreamBuffers
method should be used. If the HAL implementation never holds more buffers than requested, the camera HAL implementation doesn't need to call the returnStreamBuffers
method.
signalStreamFlush
The signalStreamFlush
method is called by the camera framework to notify the camera HAL to return all buffers at hand. This is normally called when the camera framework is about to call configureStreams
and must drain the camera capture pipeline. Similar to the returnStreamBuffers
method, if a camera HAL implementation doesn't hold more buffers than requested, it's possible to have an empty implementation of this method.
After the camera framework calls signalStreamFlush
, the framework stops sending new capture requests to the camera HAL until all buffers have been returned to the camera framework. When all buffers are returned, the requestStreamBuffers
method calls fail, and the camera framework can continue its work in a clean state. The camera framework then calls either the configureStreams
or processCaptureRequest
method. If the camera framework calls the configureStreams
method, the camera HAL can start requesting buffers again after the configureStreams
call returns successfully. If the camera framework calls the processCaptureRequest
method, the camera HAL can start requesting buffers during the processCaptureRequest
call.
The semantics are different for the signalStreamFlush
method and the flush
method. When the flush
method is called, the HAL can abort pending capture requests with ERROR_REQUEST
to drain the pipeline as soon as possible. When the signalStreamFlush
method is called, the HAL must finish all pending capture requests normally and return all buffers to the camera framework.
Another difference between the signalStreamFlush
method and other methods is that signalStreamFlush
is a one-way HIDL method, which means that the camera framework might call into other blocking APIs before the HAL receives the signalStreamFlush
call. This means that the signalStreamFlush
method and other methods (specifically the configureStreams
method) might arrive at the camera HAL in a different order than the order they were called in the camera framework. To address this asynchrony issue, the streamConfigCounter
field was added to StreamConfiguration
and added as an argument to the signalStreamFlush
method. The camera HAL implementation should use the streamConfigCounter
argument to determine whether a signalStreamFlush
call arrives later than its corresponding configureStreams
call. See Figure 3 for an example.
Figure 3. How the camera HAL should detect and handle signalStreamFlush calls that arrive late
Behavior changes when implementing the buffer management APIs
When using the buffer management APIs to implement the buffer management logic, consider the following possible behavior changes to the camera and camera HAL implementation:
-
Capture requests arrive at the camera HAL faster and more frequently: Without buffer management APIs, the camera framework requests output buffers for each capture request before sending a capture request to the camera HAL. When using the buffer management APIs, the camera framework no longer needs to wait for buffers and can therefore send capture requests to the camera HAL earlier.
Also, without buffer management APIs, the camera framework stops sending capture requests if one of the output streams of the capture request has reached the maximum number of buffers that the HAL can hold at one time (this value is designated by the camera HAL in the
HalStream::maxBuffers
field in the return value of aconfigureStreams
call). With the buffer management APIs, this throttling behavior no longer exists and the camera HAL implementation must not acceptprocessCaptureRequest
calls when the HAL has too many capture requests queued. -
requestStreamBuffers
call latency varies significantly: There are many reasons arequestStreamBuffers
call might take a longer time than average. For example:- For the first few buffers of a newly created stream, calls can take longer because the device needs to allocate memory.
- The expected latency increases in proportion to the number of buffers requested in each call.
- The app is holding buffers and is busy processing. This can cause buffer requests to slow down or hit a timeout because of a lack of buffers or a busy CPU.
Buffer management strategies
The buffer management APIs allow for different kinds of buffer management strategies to be implemented. Some examples are:
- Backward compatible: The HAL requests buffers for a capture request during the
processCaptureRequest
call. This strategy doesn't provide any memory savings, but can serve as the first implementation of the buffer management APIs, requiring very few code changes to the existing camera HAL. - Maximized memory savings: The camera HAL only requests output buffers immediately before one is needed to be filled. This strategy allows for maximized memory savings. The potential downside is more camera pipeline jank when buffer requests take an unusually long time to finish.
- Cached: The camera HAL caches a few buffers so that it's less likely to be affected by an occasional slow buffer request.
The camera HAL can adopt different strategies for particular use cases, for example, using the maximized memory saving strategy for use cases that use a lot of memory and using the backward-compatible strategy for other use cases.
Sample implementation in the external camera HAL
The external camera HAL was introduced in Android 9 and can be found in the source tree athardware/interfaces/camera/device/3.5/
. In Android 10, it has been updated to includeExternalCameraDeviceSession.cpp
, an implementation of the buffer management API. This external camera HAL implements the maximized memory savings strategy mentioned in Buffer management strategies in a few hundred lines of C++ code.
HEIF 图片处理
搭载 Android 10 的设备支持 HEIC 压缩图片格式,它是 ISO/IEC 23008-12 中规定的高效图片文件格式 (HEIF) 的高效视频编码 (HEVC) 特定品牌。与 JPEG 文件相比,HEIC 编码的图片质量更好且文件更小。
HEIC 图片由摄像头传输框架生成,请求来自相机 HAL 的未压缩图片并将其发送到媒体子系统,以便由 HEIC 或 HEVC 编码器进行编码。
要求
要支持 HEIC 图片格式,您的设备必须拥有支持 MIMETYPE_IMAGE_ANDROID_HEIC
或 MIMETYPE_VIDEO_HEVC
(具有恒定质量模式)的硬件编码器。
实现
要在您的设备上支持 HEIC 图片格式,请实现 HEIC/HEVC 编解码器,并为所需的流配置(即 IMPLEMENTATION_DEFINED
/YUV
流和 JPEG 应用细分流)提供支持。
媒体
对于相应的硬件,以恒定质量 (CQ) 模式实现 HEIC/HEVC 编解码器,如下所示:
- HEVC 类型编解码器使用具有
GRALLOC_USAGE_HW_VIDEO_ENCODER
用法的IMPLEMENTATION_DEFINED
格式或HAL_PIXEL_FORMAT_YCBCR_420_888
格式,具体取决于图片大小。 - HEIC 类型编解码器使用具有
GRALLOC_USAGE_HW_IMAGE_ENCODER
用法的IMPLEMENTATION_DEFINED
格式。
摄像头
在静态元数据中,将 ANDROID_HEIC_INFO_SUPPORTED
设置为 true,并将 ANDROID_HEIC_INFO_MAX_JPEG_APP_SEGMENTS_COUNT
设置为介于 [1, 16]
之间的值,以表明 JPEG 应用细分的数量。
对于每个必要的流组合,您的摄像头设备必须支持使用相同大小的 HEIC 流替换 JPEG 流。
对于公共 API 上的 HEIC 输出流,摄像头服务会创建两个 HAL 内部流:
- 具有
JPEG_APPS_SEGMENT
使用标记的 BLOB 流,可存储应用细分(包括 EXIF 和缩略图细分) IMPLEMENTATION_DEFINED
和YCBCR_420_888
会根据目标编解码器和 HEIC 流的大小流式传输 HEIC 流的大小
摄像头传输框架根据 ANDROID_HEIC_INFO_MAX_JPEG_APP_SEGMENTS_COUNT
为相机 HAL 分配足够大的缓冲区,以便填充 JPEG 应用细分。APP1
细分为必填项,但 APP1
之后(APP2
及以上)的细分为可选项。摄像头传输框架可以覆盖 APP1
细分中的 EXIF 标记(这些标记可以派生自捕获结果元数据或者与主图片比特流相关),并将它们发送至 MediaMuxer
。
由于媒体编码器将屏幕方向嵌入到了输出图片的元数据中,以确保主图片和缩略图的屏幕方向一致,因此相机 HAL 不得根据 android.jpeg.orientation.
旋转缩略图。 该框架将屏幕方向写入到 EXIF 元数据和 HEIC 容器中。
与 JPEG 格式相关的静态、控制和动态元数据标记也适用于 HEIC 格式。例如,捕获请求中的 android.jpeg.orientation
和 android.jpeg.quality
元数据标记用于控制 HEIC 图片的屏幕方向和质量。
要在应用中使用 HEIC 格式,请使用 HEIC 公共 API。
如需了解详情,请参阅以下来源。
相机 HAL
docs.html
CameraBlob
ANDROID_HEIC_INFO_SUPPORTED
ANDROID_HEIC_INFO_MAX_JPEG_APP_SEGMENTS_COUNT
图形缓冲区数据空间
JPEG_APP_SEGMENTS
HEIF
图形缓冲区使用空间
HW_IMAGE_ENCODER
验证
要验证您的实现是否支持 HEIC 图片,请使用 TestingCamera2
测试应用,并运行以下摄像头 CTS 和 VTS 测试。
摄像头 CTS 测试
NativeImageReaderTest#testHeic
ImageReaderTest#testHeic
ImageReaderTest#testRepeatingHeic
ReprocessCaptureTest#testBasicYuvToHeicReprocessing
ReprocessCaptureTest#testBasicOpaqueToHeicReprocessing
RobustnessTest#testMandatoryOutputCombinations
StillCaptureTest#testHeicExif
摄像头 VTS 测试
运动跟踪
在 Android 9 中,摄像头设备可以支持运动跟踪功能。支持此功能的摄像头本身不会生成运动跟踪数据,而是供 ARCore 或图像稳定算法以及其他传感器用于进行场景分析。要支持此功能,设备必须支持 CONTROL_CAPTURE_INTENT_MOTION_TRACKING
。如果该 intent 是捕获请求的一部分,则摄像头必须将曝光时间限制为不超过 20 毫秒,以减少运动模糊。
示例和源代码
HAL 端的参考运动跟踪实现是摄像头 HAL 的一部分。
实现
要在摄像头设备上启用运动跟踪功能,请确保:
ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MOTION_TRACKING
功能处于启用状态。ANDROID_CONTROL_CAPTURE_INTENT_MOTION_TRACKING
intent 受支持,并且当该 intent 包含在捕获请求中时,将摄像头曝光时间限制为不超过 20 毫秒。-
在静态信息和动态元数据字段中准确报告以下列表中的镜头校准数据:
验证
支持运动跟踪功能的摄像头设备必须通过摄像头 CTS 测试。
单色摄像头
搭载 Android 9 或更高版本的设备可以支持单色摄像头。Android 10 为 Y8 流格式、单色和近红外 (NIR) 色彩滤镜数组静态元数据提供了额外的支持,并为单色摄像头提供了 DngCreator
函数。
借助此功能,设备制造商可以实现单色或近红外线摄像头设备,并通过使用 Y8 流格式减少内存使用量。单色摄像头可以用作逻辑多摄像头设备的底层物理摄像头以获取更出色的低光噪音特性。
实现
硬件要求
要实现此功能,您的设备必须拥有单色摄像头传感器和图像信号处理器 (ISP) 以处理传感器输出。
实现单色摄像头
要将摄像头设备播发为单色摄像头,相机 HAL 必须满足以下要求:
android.sensor.info.colorFilterArray
设置为MONO
或NIR
。- 支持
BACKWARD_COMPATIBLE
必需键,不支持MANUAL_POST_PROCESSING
。 android.control.awbAvailableModes
只包含AUTO
,且android.control.awbState
为CONVERTED
或LOCKED
(具体取决于android.control.awbLock
)。android.colorCorrection.mode
、android.colorCorrection.transform
和android.colorCorrection.gains
不在可用的请求和结果键中。因此,摄像头设备是LIMITED
。-
不存在以下与颜色相关的静态元数据键:
android.sensor.referenceIlluminant*
android.sensor.calibrationTransform*
android.sensor.colorTransform*
android.sensor.forwardMatrix*
android.sensor.neutralColorPoint
android.sensor.greenSplit
-
对于以下元数据键,所有颜色通道的值都相同:
android.sensor.blackLevelPattern
android.sensor.dynamicBlackLevel
android.statistics.lensShadingMap
android.tonemap.curve
-
android.sensor.noiseProfile
只有一个颜色通道。
对于支持 Y8 流格式的单色设备,相机 HAL 必须支持将强制性信息流组合中的 YUV_420_888
格式替换(包括重新处理)为 Y8 格式。
该功能中会使用以下公共 API:
- Y8 映像格式
- SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_MONO
- SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_NIR
- MONOCHROME 摄像头功能(在 Android 9 中引入)
要详细了解相机 HAL,请参阅 docs.html。要详细了解相关公共 API,请参阅 ImageFormat、CameraCharacteristics、CaptureRequest 和 CaptureResult。
验证
要验证单色摄像头的实现情况,请运行以下 CTS 和 VTS 测试。
CTS 测试
testMonochromeCharacteristics
CaptureRequestTest
CaptureResultTest
StillCaptureTest
DngCreatorTest
VTS 测试
getCameraCharacteristics
processMultiCaptureRequestPreview
多摄像头支持
Android 9 通过一个新的逻辑摄像头设备(该设备由两个或两个以上指向同一方向的物理摄像头设备组成)引入了对多摄像头设备的 API 支持。该逻辑摄像头设备作为单个 CameraDevice/CaptureSession 提供给应用,从而允许与集成了 HAL 的多摄像头功能互动。应用可以选择访问和控制底层物理摄像头信息流、元数据和控件。
图 1. 多摄像头支持
在此图中,不同的摄像头 ID 用不同颜色标识。应用可以同时流式传输来自每个物理摄像头的原始缓冲区。您也可以设置单独的控件并从不同的物理摄像头单独接收元数据。
示例和来源
必须通过逻辑多摄像头功能播发多摄像头设备。
摄像头客户端可以通过调用 getPhysicalCameraIds()
,查询构成特定逻辑摄像头的物理设备的摄像头 ID。随结果返回的 ID 之后会用于通过 setPhysicalCameraId()
单独控制各个物理设备。可以通过调用 getPhysicalCameraResults()
从完整结果中查询这类单个请求的结果。
单个物理摄像头请求可能仅支持有限的部分参数。为了接收受支持参数的列表,开发者可以调用 getAvailablePhysicalCameraRequestKeys()
。
只有非重新处理请求以及单色和 Bayer 传感器支持物理摄像头信息流。
实现
支持核对清单
要在 HAL 端添加逻辑多摄像头设备,请执行以下操作:
- 为由两个或两个以上物理摄像头(这些摄像头也会提供给应用)提供支持的任何逻辑摄像头设备添加
ANDROID_REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA
功能。 - 使用物理摄像头 ID 列表填充静态
ANDROID_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS
元数据字段。 - 填充在物理摄像头信息流的像素之间建立关联所需的深度相关静态元数据:
ANDROID_LENS_POSE_ROTATION
、ANDROID_LENS_POSE_TRANSLATION
、ANDROID_LENS_INTRINSIC_CALIBRATION
、ANDROID_LENS_DISTORTION
、ANDROID_LENS_POSE_REFERENCE
。 -
将静态
ANDROID_LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE
元数据字段设置为:ANDROID_LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE_APPROXIMATE
:对于主主模式下的传感器,不执行硬件快门/曝光同步。ANDROID_LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE_CALIBRATED
:对于主从模式下的传感器,执行硬件快门/曝光同步。
-
使用各个物理摄像头支持的参数列表填充
ANDROID_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS
。如果逻辑设备不支持单个请求,则列表可以为空。 -
如果支持单个请求,则处理并应用可以在捕获请求中到达的各个
physicalCameraSettings
,并相应地附加单个physicalCameraMetadata
。 -
对于相机 HAL 设备版本 3.5(在 Android 10 中引入)或更高版本,请使用支持逻辑摄像头的当前有效物理摄像头的 ID 填充
ANDROID_LOGICAL_MULTI_CAMERA_ACTIVE_PHYSICAL_ID
结果密钥。
对于搭载 Android 9 的设备,摄像头设备必须支持将一个逻辑 YUV/RAW 信息流替换为来自两个物理摄像头的大小(不适用于 RAW 信息流)和格式相同的物理信息流。这并不适用于搭载 Android 10 的设备。
对于搭载 Android 10(其中相机 HAL 设备版本为 3.5)或更高版本的设备,摄像头设备必须支持 isStreamCombinationSupported
,以便应用查询包含物理信息流的特定信息流组合是否受支持。
信息流配置映射
对于逻辑摄像头,特定硬件级别的摄像头设备的强制性信息流组合与 CameraDevice.createCaptureSession
中所需的信息流组合相同。信息流配置映射中的所有信息流都必须是逻辑信息流。
对于支持 RAW 功能、物理子摄像头大小不同的逻辑摄像头设备,如果应用配置逻辑 RAW 信息流,则逻辑摄像头设备不得切换到具有不同传感器尺寸的物理子摄像头。这样可以确保现有 RAW 捕获应用不会中断。
要在 RAW 捕获期间通过在物理子摄像头之间进行切换来利用 HAL 实现的光学变焦,应用必须配置物理子摄像头信息流(而不是逻辑 RAW 信息流)。
有保证的信息流组合
逻辑摄像头及其底层物理摄像头都必须保证其设备级别所需的强制性信息流组合。
逻辑摄像头设备的运行方式应该与物理摄像头设备相同,具体取决于其硬件级别和功能。建议将其特征集设为单个物理摄像头的特征集的超集。
在搭载 Android 9 的设备上,对于每个有保证的信息流组合,逻辑摄像头必须支持:
-
将一个逻辑 YUV_420_888 或原始信息流替换为两个相同大小和格式的物理信息流(每个信息流来自不同的物理摄像头),只要物理摄像头支持这种大小和格式就可以。
-
添加两个原始信息流(在每个物理摄像头中各添加一个),条件是逻辑摄像头不播发 RAW 功能,但底层物理摄像头播发该功能。当两个物理摄像头具有不同的传感器尺寸时,通常会出现这种情况。
-
使用物理信息流代替大小和格式相同的逻辑信息流。当物理信息流和逻辑信息流的最小帧时长相同时,这么做必须不能减慢捕获的帧速率。
性能和功率考虑因素
-
性能:
- 由于资源限制,配置和流式传输物理信息流可能会降低逻辑摄像头的捕获速率。
- 如果将底层摄像头设为不同的帧速率,则应用物理摄像头设置可能会降低捕获速率。
-
功率:
- HAL 的功率优化在默认情况下继续有效。
- 配置或请求物理信息流可能会替换 HAL 的内部功率优化并消耗更多电量。
自定义
您可以通过以下方式自定义设备实现。
- 逻辑摄像头设备的融合输出完全取决于 HAL 实现。关于如何从物理摄像头派生融合逻辑信息流的决定对于应用和 Android 摄像头框架来说都是透明的。
- 可以选择支持单个物理请求和结果。此类请求中的可用参数集也完全取决于特定的 HAL 实现。
- 从 Android 10 开始,HAL 可以选择不在
getCameraIdList
中播发部分或所有 PHYSICAL_ID,从而减少应用可以直接打开的摄像头数量。然后,调用getPhysicalCameraCharacteristics
必须返回物理摄像头的特征。
验证
逻辑多摄像头设备必须像任何其他普通摄像头一样通过摄像头 CTS。可以在 LogicalCameraDeviceTest
模块中找到针对此类设备的测试用例。
以下三个 ITS 测试针对多摄像头系统,以便于正确融合图像:
scene1/test_multi_camera_match.py
scene4/test_multi_camera_alignment.py
sensor_fusion/test_multi_camera_frame_sync.py
scene1 和 scene4 测试使用盒装 ITS 测试装置运行。当两个摄像头都启用时,test_multi_camera_match
测试会声明图像中心的亮度匹配。test_multi_camera_alignment
测试会声明摄像头间距、方向和失真参数已正确加载。如果多摄像头系统包含广视野摄像头(大于 90o),则需要 rev2 版 ITS 包装盒。
Sensor_fusion
是另一个测试装置,它可以实现规定的重复手机动作,并声明陀螺仪和图像传感器时间戳匹配以及多摄像头帧保持同步。
所有测试盒均由 AcuSpec, Inc.(www.acuspecinc.com,fred@acuspecinc.com)和 MYWAY Manufacturing(www.myway.tw,sales@myway.tw)提供。此外,rev1 ITS 测试盒可从 West-Mark(www.west-mark.com,dgoodman@west-mark.com)购买。
外接 USB 摄像头
Android 平台支持使用即插即用的 USB 摄像头(即网络摄像头),但前提是这些摄像头采用标准的 Android Camera2 API 和摄像头 HIDL 接口。网络摄像头通常支持 USB 视频类 (UVC) 驱动程序,并且在 Linux 上,系统采用标准的 Video4Linux (V4L) 驱动程序控制 UVC 摄像头。
如果系统支持网络摄像头,设备便可用于视频聊天和照片冲印机等轻量级用例。此功能不能替代 Android 手机上典型的内部相机 HAL,也不是为了协助执行涉及高分辨率和高速流式传输、AR 以及手动 ISP/传感器/摄像头控制且对性能要求很高的复杂任务。
USB 相机 HAL 进程是外接摄像头提供程序的一部分,该提供程序会监听 USB 设备可用性,并相应地枚举外接摄像头设备。该进程具有与内置相机 HAL 进程类似的权限和 SE 策略。直接与 USB 设备通信的第三方网络相机应用访问 UVC 设备时所需的相机权限与所有常规相机应用所需的权限相同。
示例和来源
如需详细了解如何实现 USB 摄像头,请参阅 ExternalCameraProvider
中的外接摄像头提供程序参考实现。外接摄像头设备和会话实现包含在 ExternalCameraDevice
和 ExternalCameraDeviceSession
中。从 API 级别 28 开始,Java 客户端 API 包含 EXTERNAL
硬件级别。
实现
实现必须支持 android.hardware.usb.host
系统功能。
此外,还必须启用对 UVC 设备的内核支持。您可以通过将以下内容添加到相应的内核 deconfig
文件来启用该支持。
+CONFIG_USB_VIDEO_CLASS=y
+CONFIG_MEDIA_USB_SUPPORT=y
注意:请确保您还针对 UVC 视频安装了此补丁程序。
要在相应的设备细分版本中启用外接摄像头提供程序,以便添加必要的 SELinux 权限、外接摄像头配置以及外接摄像头提供程序依赖项,请完成以下步骤:
-
将外接摄像头配置文件和外接摄像头库添加到
device.mk
。+PRODUCT_PACKAGES += android.hardware.camera.provider@2.4-impl
+PRODUCT_PACKAGES += android.hardware.camera.provider@2.4-external-service
+PRODUCT_COPY_FILES += \
+device/manufacturerX/productY/external_camera_config.xml:$(TARGET_COPY_OUT_VENDOR)/etc/external_camera_config.xml -
将外接摄像头提供程序名称添加到设备 Treble HAL 清单。
<hal format="hidl">
<name>android.hardware.camera.provider</name>
<transport arch="32+64">passthrough</transport>
<impl level="generic"></impl>
<version>2.4</version>
<interface>
<name>ICameraProvider</name>
<instance>legacy/0</instance>
+ <instance>external/0</instance>
</interface>
</hal> -
(选做)如果设备在 Treble 直通模式下运行,请更新
sepolicy
,以便cameraserver
可以访问 UVC 摄像头。+# for external camera
+allow cameraserver device:dir r_dir_perms;
+allow cameraserver video_device:dir r_dir_perms;
+allow cameraserver video_device:chr_file rw_file_perms;
下面的示例展示了 external_camera_config.xml
(省略了版权行)。
<ExternalCamera>
<Provider>
<!-- Internal video devices to be ignored by external camera HAL -->
<id>0</id> <!-- No leading/trailing spaces -->
<id>1</id>
</Provider>
<!-- See ExternalCameraUtils.cpp for default values of Device configurations below -->
<Device>
<!-- Max JPEG buffer size in bytes-->
<MaxJpegBufferSize bytes="3145728"/> <!-- 3MB (~= 1080p YUV420) -->
<!-- Size of v4l2 buffer queue when streaming >= 30fps -->
<!-- Larger value: more request can be cached pipeline (less janky) -->
<!-- Smaller value: use less memory -->
<NumVideoBuffers count="4"/>
<!-- Size of v4l2 buffer queue when streaming < 30fps -->
<NumStillBuffers count="2"/>
<!-- List of maximum fps for various output sizes -->
<!-- Any image size smaller than the size listed in Limit row will report
fps (as minimum frame duration) up to the fpsBound value. -->
<FpsList>
<!-- width/height must be increasing, fpsBound must be decreasing-->
<Limit width="640" height="480" fpsBound="30.0"/>
<Limit width="1280" height="720" fpsBound="15.0"/>
<Limit width="1920" height="1080" fpsBound="10.0"/>
<!-- image size larger than the last entry will not be supported-->
</FpsList>
</Device>
</ExternalCamera>
自定义
您可以通过常规自定义选项或设备专用的优化来提升 Android 摄像头的性能。
常规自定义
您可以通过修改 external_camera_config.xml
文件来自定义外接摄像头提供程序。具体而言,客户可以自定义以下参数:
- 内部摄像头的排除视频节点
- 支持的图片大小和帧速率上限
- Inflight 缓冲区数量(在卡顿与内存之间进行权衡)
除了这些参数之外,您还可以添加自己的参数或开发自己的配置。
设备专用的优化
您还可以通过添加设备专用的优化来提升性能。
缓冲区复制/调整大小和 JPEG 解码/编码
通用实现使用的是 CPU (libyuv/libjpeg),但您可以将其替换为设备专用的优化。
HAL 输出格式
通用实现采用以下输出格式:
YUV_420_888
:适用于视频IMPLEMENTATION_DEFINED
缓冲区YUV12
:适用于所有其他IMPLEMENTATION_DEFINED
缓冲区
为了提升性能,您可以将输出格式替换为设备专用的高效格式。此外,您还可以在自定义的实现中支持其他格式
验证
支持外接摄像头的设备必须通过摄像头 CTS 测试。在整个测试运行期间,外接 USB 网络摄像头必须始终插入到特定设备,否则某些测试用例会失败。
注意:media_profiles
条目不适用于外接 USB 网络摄像头,因此没有 camcorder 配置文件。相机版本支持
本页详细介绍了相机 HAL、API 和相关的兼容性测试套件 (CTS) 测试中的版本差异,还介绍了在 Android 7.0 中为增强和提高相机框架安全性而进行的几项架构更改,在 Android 8.0 中引入的 Treble,以及供应商在其相机实现中为支持这些更改而必须进行的更新。
术语
本页中用到以下术语:
- 相机 API1
- Android 4.4 及更低版本设备上的应用级相机框架,通过
android.hardware.Camera
类提供。 - 相机 API2
- Android 5.0 及更高版本设备上的应用级相机框架,通过
android.hardware.camera2
包提供。 - 相机 HAL
- 由 SoC 供应商实现的相机模块层。应用级公共框架基于相机 HAL 构建而成。
- 相机 HAL3.1
- 随 Android 4.4 发布的相机设备 HAL 版本。
- 相机 HAL3.2
- 随 Android 5.0 发布的相机设备 HAL 版本。
- 相机 API1 CTS
- 在相机 API1 之上运行的相机 CTS 测试集。
- 相机 API2 CTS
- 在相机 API2 之上运行的另一个相机 CTS 测试集。
- Treble
- 利用新的供应商接口,将供应商实现(由芯片制造商编写的设备专用底层软件)与 Android 操作系统框架分离开来。
- HIDL
- HAL 接口定义语言随 Treble 引入,用于指定 HAL 和其用户之间的接口。
- VTS
- 供应商测试套件随 Treble 引入。
相机 API
Android 包含以下相机 API。
相机 API1
Android 5.0 已弃用 Camera API1,而且随着新平台开发的重点放在 Camera API2 上,Camera API1 会逐渐被淘汰。但是,淘汰期限将会很长,而且在一段时间内新 Android 版本会继续支持 Camera API1 应用。具体来说,将继续为以下内容提供支持:
- 供应用使用的相机 API1 接口。 在相机 API1 之上构建的相机应用应该像在搭载较低 Android 版本的设备上一样工作。
- 相机 HAL 版本。 包括对相机 HAL1.0 的支持。
相机 API2
Camera API2 框架为应用提供更接近底层的相机控件,包括高效的零复制连拍/视频流以及曝光、增益、白平衡增益、颜色转换、去噪、锐化等方面的每帧控件。如需了解详情,请观看 Google I/O 视频概览。
Android 5.0 及更高版本提供相机 API2;但是,搭载 Android 5.0 及更高版本的设备可能并不支持所有相机 API2 功能。应用可通过相机 API2 接口查询 android.info.supportedHardwareLevel
属性。该属性会报告以下支持级别之一:
LEGACY
(旧版)。这些设备通过相机 API2 接口为应用提供功能,但这些功能与通过相机 API1 接口提供给应用的功能大致相同。旧版框架代码在概念上将相机 API2 调用转换为相机 API1 调用;旧版设备不支持相机 API2 功能,例如每帧控件。LIMITED
:这些设备支持部分(但不是全部)相机 API2 功能,并且必须使用相机 HAL 3.2 或更高版本。FULL
:这些设备支持相机 API2 的所有主要功能,并且必须使用相机 HAL 3.2 或更高版本以及 Android 5.0 或更高版本。LEVEL_3
(级别 3):这些设备支持 YUV 重新处理和 RAW 图像捕获,以及其他输出流配置。EXTERNAL
(外部):这些设备类似于LIMITED
设备,但有一些例外情况;例如,某些传感器或镜头信息可能未被报告或具有较不稳定的帧速率。此级别用于外部相机(如 USB 网络摄像头)。
各项功能通过相机 API2 接口中的 android.request.availableCapabilities
属性提供。FULL
设备需要具备 MANUAL_SENSOR
和 MANUAL_POST_PROCESSING
等功能。但即使是 FULL
设备,也并非必须实现 RAW
功能。LIMITED
设备可以提供这些功能的任何子集,甚至可以不提供其中任何功能。但是,必须始终定义 BACKWARD_COMPATIBLE
功能。
设备支持的硬件级别及其支持的特定 Camera API2 功能采用以下功能标记的形式指明,以允许 Google Play 过滤 Camera API2 相机应用。
android.hardware.camera.hardware_level.full
android.hardware.camera.capability.raw
android.hardware.camera.capability.manual_sensor
android.hardware.camera.capability.manual_post_processing
CTS 要求
搭载 Android 5.0 及更高版本的设备必须通过相机 API1 CTS、相机 API2 CTS 和 CTS 验证程序相机测试。
不具备相机 HAL3.2 实现且无法支持完整的相机 API2 接口的设备仍必须通过相机 API2 CTS 测试。但是,该设备在相机 API2 LEGACY
模式下运行(在该模式下,相机 API2 调用在概念上映射到相机 API1 调用),因此相机 API1 未涵盖的特征或功能对应的任何相机 API2 CTS 测试都将自动跳过。
在旧版设备上,运行的相机 API2 CTS 测试使用现有的公共相机 API1 接口和功能,没有新的要求。发现的错误(会导致相机 API2 CTS 失败)是设备现有相机 HAL 中已经存在的错误,因此可由现有相机 API1 应用找到。我们预计不会有很多这种性质的错误(但是,必须修复任何此类错误才能通过相机 API2 CTS 测试)。
VTS 要求
采用绑定式 HAL 实现的运行 Android 8.0 及更高版本的设备必须通过相机 VTS 测试。
相机框架强化
为了增强媒体和相机框架的安全性,Android 7.0 已将相机服务从 mediaserver 中移出。从 Android 8.0 开始,每个绑定式相机 HAL 都会在与相机服务不同的进程中运行。供应商可能需要根据正在使用的 API 和 HAL 版本对相机 HAL 进行更改。以下部分详细介绍了在 HAL1 和 HAL3 的 AP1 和 AP2 中进行的架构更改,以及常规要求。
API1 的架构更改
API1 视频录制可能会假定相机和视频编码器存在于同一进程中。在以下对象上使用 API1 时:
- HAL3,其中相机服务使用 BufferQueue 在进程之间传递缓冲区,不需要供应商更新。
- HAL1(支持在视频缓冲区中传递元数据),供应商必须更新 HAL 才能使用
kMetadataBufferTypeNativeHandleSource
。(Android 7.0 中不再支持kMetadataBufferTypeCameraSource
)。
API2 的架构更改
对于 HAL1 或 HAL3 上的 API2,BufferQueue 会传递缓冲区,以便这些路径能继续工作。Android 7.0 的 API2 架构:
- 若在 HAL1 上,则不受 cameraservice 移动的影响,并且不需要供应商更新。
- 若在 HAL3 上,则会受到 cameraservice 移动的影响,但不需要供应商更新。
其他要求
为增强媒体和相机框架安全性而进行的架构更改包括以下附加设备要求。
- 常规。 由于 IPC,设备需要额外带宽,这可能会影响对时间敏感的相机使用情景,例如高速视频录制。供应商可以运行
android.hardware.camera2.cts.PerformanceTest
和 Google 相机应用,进行 120/240 FPS 高速视频录制,从而衡量实际影响。设备还需要少量额外的 RAM 来创建新进程。 - 在视频缓冲区中传递元数据(仅限 HAL1)。如果 HAL1 在视频缓冲区中存储元数据而非实际的 YUV 帧数据,则 HAL 必须使用
kMetadataBufferTypeNativeHandleSource
作为元数据缓冲区类型,并在视频缓冲区中传递VideoNativeHandleMetadata
。(kMetadataBufferTypeCameraSource
在 Android 7.0 中不再受支持。)通过VideoNativeHandleMetadata
,相机和媒体框架能够正确地对原生句柄进行序列化和反序列化,从而在进程之间传递视频缓冲区。 - 缓冲区句柄地址并不总是存储相同的缓冲区(仅限 HAL3)。对于每个捕获请求,HAL3 会获取缓冲区句柄的地址。HAL 不能使用地址来识别缓冲区,因为相应地址可能会在 HAL 返回缓冲区之后用于存储另一个缓冲区句柄。您必须更新 HAL 才能使用缓冲区句柄来标识缓冲区。例如:HAL 接收到缓冲区句柄地址 A,当时该地址中存储了缓冲区句柄 A。在 HAL 返回缓冲区句柄 A 之后,下次又接收到缓冲区句柄地址 A 时,该地址中存储的可能是缓冲区句柄 B。
- 更新用于 cameraserver 的 SELinux 策略。 如果特定于设备的 SELinux 策略向 mediaserver 授予运行相机的权限,则您必须更新 SELinux 策略,以授予 cameraserver 正确的权限。我们建议不要为 cameraserver 复制 mediaserver 的 SELinux 策略(因为 mediaserver 和 cameraserver 通常需要系统中的不同资源)。Cameraserver 应仅具有执行相机功能所需的权限,并且 mediaserver 中任何不必要的相机相关权限均应被移除。
- 将相机 HAL 与 cameraserver 分离开。 此外,搭载 Android 8.0 或更高版本的设备会在与 cameraserver 不同的进程中分离绑定式相机 HAL。IPC 会通过 HIDL 定义的接口进行。
验证
对于所有包含相机并搭载 Android 7.0 的设备,请通过运行 Android 7.0 CTS 来验证实现。尽管 Android 7.0 不包含验证相机服务更改的新 CTS 测试,但如果您尚未进行上述更新,则现有的 CTS 测试将会失败。
对于包含相机并搭载 Android 8.0 或更高版本的所有设备,请通过运行 VTS 来验证供应商实现。
相机 HAL 版本历史记录
有关可用于评估 Android 相机 HAL 的测试列表,请参阅相机 HAL 测试核对清单。
Android 10
Android 10 引入了以下更新。
Camera API
- 多相机方面的改进;既可单独使用各个物理相机,也可通过隐藏物理相机 ID 并借助相应的逻辑相机来使用物理相机。请参阅多相机支持。
- 能够检查是否支持特定的会话配置,而不会因创建新会话而产生性能开销。请参阅
CameraDevice
。 - 能够检索指定使用情形的推荐数据流配置,从而使客户端更加节能和高效。请参阅
getRecommendedStreamConfigurationMap
。 - 支持深度 JPEG 图片格式。如需更多详细信息,请参阅动态深度规范。
- 支持 HEIC 图片格式。请参阅 HEIF 图片处理。
- 隐私方面的改进。客户端需要某些密钥才能获取
CAMERA
权限,然后才能从CameraCharacteristics
中进行检索。请参阅getKeysNeedingPermission
。
相机 HAL
Android 10 中更新了以下相机 HAL 版本。
3.5
ICameraDevice
getPhysicalCameraCharacteristics
:某个逻辑相机设备对应的物理相机 ID 的静态相机信息,请参阅多相机支持。isStreamCombinationSupported
:此方法支持公共 API,可帮助客户端查询是否支持某个会话配置。请参阅使用 API 查询数据流组合。
ICameraDeviceSession
isReconfigurationNeeded
:该方法可告知相机框架,可能的新会话参数值是否需要完整的数据流重新配置。这有助于避免不必要的相机重新配置延迟。请参阅会话重新配置查询。- HAL 缓冲区管理 API:这些 API 允许相机 HAL 仅在需要时从相机框架请求缓冲区,而不是将每个捕获请求与整个相机管道中的相关缓冲区进行耦合,从而可能节省大量内存。
signalStreamFlush
:向 HAL 发出信号,指明相机服务即将执行configureStreams_3_5
,该 HAL 必须返回指定数据流的所有缓冲区。configureStreams_3_5
:类似于ICameraDevice3.4.configureStreams
,但除此之外会提供streamConfigCounter
计数器,以检查configureStreams_3_5
和signalStreamFlush
调用之间的竞态条件。
对 ICameraDeviceCallback
的更新:
requestStreamBuffers
:供相机 HAL 调用的同步回调函数,用于向相机服务器索取缓冲区。请参阅requestStreamBuffers
。returnStreamBuffers
:供相机 HAL 调用的同步回调函数,用于向相机服务器返回输出缓冲区。请参阅returnStreamBuffers
。
3.4
Android 10 的相机元数据中添加了以下键。
- 图片格式
ANDROID_SCALER_AVAILABLE_FORMATS_RAW10
ANDROID_SCALER_AVAILABLE_FORMATS_RAW12
ANDROID_SCALER_AVAILABLE_FORMATS_Y8
- 相机元数据标记
ANDROID_REQUEST_CHARACTERISTIC_KEYS_NEEDING_PERMISSION
ANDROID_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS
ANDROID_SCALER_AVAILABLE_RECOMMENDED_INPUT_OUTPUT_FORMATS_MAP
ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION
ANDROID_DEPTH_AVAILABLE_RECOMMENDED_DEPTH_STREAM_CONFIGURATIONS
ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS
ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_MIN_FRAME_DURATIONS
ANDROID_LOGICAL_MULTI_CAMERA_ACTIVE_PHYSICAL_ID
ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS
ANDROID_HEIC_AVAILABLE_HEIC_MIN_FRAME_DURATIONS
ANDROID_HEIC_AVAILABLE_HEIC_STALL_DURATIONS
ANDROID_HEIC_INFO_SUPPORTED
ANDROID_HEIC_INFO_MAX_JPEG_APP_SEGMENTS_COUNT
- 权能
ANDROID_REQUEST_AVAILABLE_CAPABILITIES_SECURE_IMAGE_DATA
ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT
键的值ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_MONO
ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_NIR
- 可用的动态深度数据流配置
ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS_OUTPUT
ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS_INPUT
- 可用的 HEIC 数据流配置
ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS_OUTPUT
ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS_INPUT
相机模块
Android 10 中更新了以下相机模块版本。
2.5
- 为设备添加
notifyDeviceStateChange
方法,以便在物理更改(例如折叠)影响相机和路由时通知相机 HAL。
2.4
- API 级别为 29 或更高级别的设备必须针对
isTorchModeSupported
报告true
。
Android 9
Android 9 版本对相机 API2 和 HAL 界面进行了以下更新。
Camera API
- 引入了多相机 API,以更好地支持多个相机朝向同一方向的设备,实现散景和无缝变焦等功能。这样,应用就可以将设备上的多个相机视为一个逻辑单元(逻辑相机)。拍摄请求也可以发送到同一个逻辑相机下属的多个相机设备。请参阅多相机支持。
- 引入会话参数。会话参数是可用拍摄参数的一个子集,在进行修改时会导致严重的处理延迟。如果客户端在拍摄会话初始化期间传递其初始值,则可以减少这些开销。请参阅会话参数。
- 添加光学防抖 (OIS) 数据键,以实现应用级稳定性和效果。请参阅
STATISTICS_OIS_SAMPLES
。 - 添加外部闪存支持。请参阅
CONTROL_AE_MODE_ON_EXTERNAL_FLASH
。 - 在
CAPTURE_INTENT
中添加了运动跟踪 intent。请参阅CONTROL_CAPTURE_INTENT_MOTION_TRACKING
。 - 弃用了
LENS_RADIAL_DISTORTION
并在其位置添加了LENS_DISTORTION
。 - 在
CaptureRequest
中添加了失真校正模式。请参阅DISTORTION_CORRECTION_MODE
。 - 在支持的设备上添加了对外部 USB/UVC 相机的支持。请参阅
INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL
。
相机 HAL
3.4
ICameraDeviceSession
更新
configureStreams_3_4
:添加了对sessionParameters
和逻辑相机的支持。processCaptureRequest_3_4
:支持在数据流结构中包含物理相机 ID。
ICameraDeviceCallback
更新
processCaptureResult_3_4
:在拍摄结果中添加了物理相机元数据。
3.3
Android 9 的相机元数据中添加了以下键。
- 权能
ANDROID_REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA
ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MOTION_TRACKING
ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME
- 相机元数据标记
ANDROID_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS
ANDROID_LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE
ANDROID_DISTORTION_CORRECTION_AVAILABLE_MODES
ANDROID_LENS_POSE_REFERENCE
ANDROID_LENS_DISTORTION
ANDROID_REQUEST_AVAILABLE_SESSION_KEYS
ANDROID_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS
ANDROID_STATISTICS_OIS_DATA_MODE
ANDROID_STATISTICS_OIS_TIMESTAMPS
ANDROID_STATISTICS_OIS_X_SHIFTS
ANDROID_STATISTICS_OIS_Y_SHIFTS
Android 8.0
Android 8.0 版本引入了 Treble。引入 Treble 后,供应商相机 HAL 实现必须为绑定式。Android 8.0 还包含对相机服务的以下主要增强功能:
- 共享 surface - 可让多个 surface 共享同一个
OutputConfiguration
- 适用于自定义相机模式的系统 API
onCaptureQueueEmpty
有关这些功能的详细信息,请参阅以下部分。
共享 surface
借助此功能,只需一组缓冲区就可以驱动两个输出(例如预览和视频编码),从而降低功耗和内存消耗。要支持此功能,设备制造商需要确保其相机 HAL 和 gralloc HAL 实现可以创建由多个不同使用方(而不是仅一个使用方;例如 Hardware Composer/GPU 和视频编码器)使用的 gralloc 缓冲区。相机服务将使用方使用情况标记传递到相机 HAL 和 gralloc HAL;它们需要分配正确的缓冲区类型,或者相机 HAL 需要返回一个表明该使用方组合不受支持的错误。
有关其他详细信息,请参阅 enableSurfaceSharing
。
适用于自定义相机模式的系统 API
公共相机 API 定义了两种操作模式:正常模式和受限高速录制模式。这两种模式的语义截然不同;例如,高速模式受限于一次最多只能有两个具体输出。各个原始设备制造商 (OEM) 已表现出极大的兴趣想要针对特定于硬件的功能定义其他自定义模式。说白了,该模式只是一个传递到 configure_streams
的整数。请参阅:hardware/camera/device/3.2/ICameraDeviceSession#configurestreams
。
此功能包括一个系统 API 调用,OEM 相机应用可以使用该调用来启用自定义模式。这些自定义模式必须以整数值 0x8000 开头,以避免与未来添加到公共 API 的模式发生冲突。
要支持这一功能,OEM 只需将新模式添加到其 HAL 即可,传递至 HAL 的这一整数会在 configure_streams 上触发该模式,然后 OEM 就可以让其自定义相机应用使用系统 API。
方法名称是 android.hardware.camera2.CameraDevice#createCustomCaptureSession
。请参阅:frameworks/base/core/java/android/hardware/camera2/CameraDevice.java#805
。
onCaptureQueueEmpty
此 API 的目的是通过尽可能让请求队列为空,来缩短控制更改(如缩放)的延迟时间。onCaptureQueueEmpty
不需要 HAL 发挥作用;它只是一种框架端补充。想要利用此 API 的应用需要向该回调添加监听器,并相应地做出响应。通常,响应方式是向相机设备发送另一个捕获请求。
相机 HIDL 接口
相机 HIDL 接口在相机 HAL 接口(使用以 HIDL 定义的稳定 API)基础上进行了全面改造。在最近的旧版本 3.4 和 2.4(针对相机模块)中引入的所有功能和相机功能也是 HIDL 定义的一部分。
3.4
对受支持的元数据添加了少许内容并对 data_space 支持进行了更改:
- 如果支持
RAW_OPAQUE
格式,则必须强制添加ANDROID_SENSOR_OPAQUE_RAW_SIZE
静态元数据。 - 如果支持任何 RAW 格式,则必须强制添加
ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST_RANGE
静态元数据。 - 使用数据空间编码的版本 0 定义,将
camera3_stream_t data_space
字段切换为更灵活的定义。 - 可用于 HALv3.2 或更高版本的常规元数据添加项:
ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_3
ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST
ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST_RANGE
ANDROID_SENSOR_DYNAMIC_BLACK_LEVEL
ANDROID_SENSOR_DYNAMIC_WHITE_LEVEL
ANDROID_SENSOR_OPAQUE_RAW_SIZE
ANDROID_SENSOR_OPTICAL_BLACK_REGIONS
3.3
扩展功能 HAL 的小修订:
- OPAQUE 和 YUV 重新处理 API 更新。
- 对深度输出缓冲区的基本支持。
- 为
camera3_stream_t
添加了data_space
字段。 - 为
camera3_stream_t
添加了旋转字段。 - 为
camera3_stream_configuration_t
添加了 camera3 流配置操作模式。
3.2
扩展功能 HAL 的小修订:
- 弃用了
get_metadata_vendor_tag_ops
。在camera_common.h
中改用get_vendor_tag_ops
。 - 弃用了
register_stream_buffers
。框架在process_capture_request
中提供给 HAL 的所有 gralloc 缓冲区在任何时候可能都是新的。 - 添加了部分结果支持。在获得完整结果之前,通过多次调用
process_capture_result
可以获得可用结果的子集。 - 为
camera3_request_template
添加了手动模板。应用可以使用此模板直接控制捕获设置。 - 重新制定双向和输入流规范。
- 更改输入缓冲区返回路径。缓冲区在
process_capture_result
而不是process_capture_request
中返回。
3.1
扩展功能 HAL 的小修订:
configure_streams
将消耗方使用标记传递给 HAL。- 刷新调用以尽可能快地丢弃所有传输中的请求/缓冲区。
3.0
扩展功能 HAL 的首次修订:
- 重要版本更改,因为 ABI 完全不同。在所需的硬件功能或操作模式方面,与 2.0 相比没有更改。
- 重新设计了输入请求和流队列接口:框架调用 HAL 且后续请求和流缓冲区已经出队。包含同步框架支持,这是高效实现所必需的。
- 已将触发器移动到请求中,将大多数通知移动到结果中。
- 将框架中的所有回调合并到一个结构中,并将所有设置方法合并到单个
initialize()
调用中。 - 将数据流配置整合到单个调用中,从而简化数据流管理。双向数据流替代
STREAM_FROM_STREAM
构造。 - 为较旧/受限的硬件设备限制了模式语义。
2.0
初始版本的扩展功能 HAL (Android 4.2) [camera2.h]:
- 足够用于实现现有的
android.hardware.Camera
API。 - 允许用于相机服务层中的 ZSL 队列。
- 未针对任何新功能(如手动捕获控制、Bayer RAW 捕获,RAW 数据的重新处理等)进行测试。
1.0
初始 Android 相机 HAL (Android 4.0) [camera.h]:
- 已从 C++ CameraHardwareInterface 抽象层进行转换。
- 支持
android.hardware.Camera
API。
相机模块版本历史记录
本部分包含相机硬件模块的模块版本控制信息(基于 camera_module_t.common.module_api_version
)。两个最重要的十六进制数字表示 Major 版本,而两个最不重要的数字表示 Minor 版本。
2.4
此相机模块版本添加了以下 API 更改:
- 手电筒模式支持。 框架可以为具有闪光灯元件的任何相机设备打开手电筒模式,而无需打开相机设备。相机设备对闪光灯元件的访问优先级高于相机模块;如果已通过模块接口启用手电筒,则打开相机设备会关闭手电筒。当出现任何资源冲突时(例如调用
open()
以打开相机设备),相机 HAL 模块必须通过手电筒模式状态回调告知框架手电筒模式已关闭。 - 外部相机(如 USB 热插拔相机)支持。 仅当相机已连接且准备好用于外部热插拔相机时,API 更新才会指明相机静态信息可用。当相机状态不是
CAMERA_DEVICE_STATUS_PRESENT
时,获取静态信息的调用为无效调用。框架仅依赖设备状态更改回调来管理可用的外部相机列表。 - 相机仲裁提示。 添加了相关支持,以明确指明可以同时打开和使用的相机设备数量。要指定有效的设备组合,应始终在由
get_camera_info
调用返回的camera_info
结构中设置resource_cost
和conflicting_devices
字段。 - 模块初始化方法。 在加载 HAL 模块后由相机服务调用,以允许初始化 HAL 一次。该方法在调用任何其他模块方法之前调用。
2.3
该相机模块版本添加了对打开旧版相机 HAL 设备的支持。如果同一设备可以支持多个设备 API 版本,则框架利用该支持可以打开相机设备作为较低设备 HAL 版本的 HAL 设备。标准硬件模块打开调用 (common.methods->open
) 会继续使用支持的最新版本(即 camera_info_t.device_version
中列出的版本)打开相机设备。
2.2
该相机模块版本添加了模块供应商标记支持,并且弃用了以前只能通过打开设备才可访问的旧版 vendor_tag_query_ops
。
2.1
该相机模块版本添加了对从相机 HAL 模块到框架的异步回调支持,利用该支持可以通知框架关于相机模块状态的更改。提供有效 set_callbacks()
方法的模块必须至少报告此版本号。
2.0
报告此版本号的相机模块会实现相机模块 HAL 接口的第二个版本。可通过此模块打开的相机设备可能支持 1.0 版本或 2.0 版本的相机设备 HAL 接口。camera_info 的 device_version
字段始终有效;如果 device_version
字段为 2.0 或更高版本,则 camera_info
的 static_camera_characteristics
字段有效。
1.0
报告这些版本号的相机模块实现了初始相机模块 HAL 接口。可通过此模块打开的所有相机设备仅支持版本 1 的相机设备 HAL。camera_info
的 device_version
和 static_camera_characteristics
字段无效。只有 android.hardware.Camera
API 可以受该模块及其设备的支持。