Android 允许设备支持摄像头设备的并发流式传输。例如,这可以让设备同时运行前置摄像头和后置摄像头。从 Android 11 开始,Camera2 API 包含以下方法,应用可以调用这些方法来确定摄像头是否支持并发流式传输和支持的流式传输配置。
getConcurrentStreamingCameraIds
:会获取一组当前连接的摄像头设备标识符组合,此类标识符支持同时配置摄像头设备会话。isConcurrentSessionConfigurationSupported
:用于检查是否可以同时配置提供的一组摄像头设备及其相应的会话配置。
一组在并发流式传输中必须支持的强制性信息流组合通过摄像头设备的摄像头特性包含在 SCALER_MANDATORY_CONCURRENT_STREAM_COMBINATIONS
属性中。
通过 getConcurrentStreamingCameraIds()
通告的每个摄像头设备必须支持并发数据流的以下有保证配置。
目标 1 | 目标 2 | |||
---|---|---|---|---|
类型 | 最大大小 | 类型 | 最大大小 | 用例示例 |
YUV | s1440p | 应用内视频或图片处理 | ||
PRIV | s1440p | 应用内取景器分析 | ||
JPEG | s1440p | 无取景器静态图片拍摄 | ||
YUV / PRIV | s720p | JPEG | s1440p | 标准静态成像 |
YUV / PRIV | s720p | YUV / PRIV | s1440p | 应用内视频或使用预览进行视频处理 |
具有 MONOCHROME
功能(CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
,包括 CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME
)且支持 Y8 的设备必须支持在所有有保证的数据流组合中将 YUV 数据流替换为 Y8 数据流。
s720p
指的是 720p (1280 x 720) 或 StreamConfigurationMap.getOutputSizes()
返回的特定格式所支持的最大分辨率。s1440p
表示 1440p (1920 x 1440) 或 StreamConfigurationMap.getOutputSizes()
返回的特定格式所支持的最大分辨率。功能不具备 ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE
的设备在并发操作期间必须至少支持一个分辨率为 sVGA 的 Y16 流 Dataspace::DEPTH
,其中 sVGA 为以下两个分辨率中较小者:
- 给定格式的最大输出分辨率
- 640 x 480
实现
如需允许应用查询设备以确定其摄像头是否支持并发流式传输,请实现 ICameraProvider@2.6
HAL 接口,方法包括:
有关 ICameraProvider@2.6
HAL 接口的参考实现,请参阅 EmulatedCameraProviderHWLImpl.cpp
处的模拟相机 HAL 库。
验证
要测试此功能的实现是否正常,请使用 ConcurrentCameraTest.java
CTS 测试。此外,也请使用能够打开多个摄像头并同时运行这些摄像头的应用进行测试。
资源分配问题
如果相机 HAL 通告支持摄像头设备的并发操作,则可能会遇到资源分配问题,尤其是在下述情况下:手机上有足够的图像信号处理器 (ISP) 资源,可支持同时流式传输前置和后置(或其他)摄像头的数据,但无法达到其最大负载。在这种情况下,相机 HAL 必须向每个摄像头设备分配有限的硬件资源。
示例场景
以下场景演示了此问题。
问题
设备具有以下配置:
- 摄像头 ID
0
是一个由广角摄像头和超广角摄像头组成的逻辑摄像头,其中每个摄像头都占用一个 ISP 资源。 - 摄像头 ID
1
是占用一个 ISP 资源的摄像头。
设备(手机)有两个 ISP。如果打开摄像头 ID 0
并配置会话,则相机 HAL 可能会预留两个 ISP 来满足同时使用超广角和广角摄像头的情况。
如果是这种情况,前置摄像头 (ID 1
) 就无法配置任何数据流,因为两个 ISP 都正在使用中。
解决方法
为了解决此问题,相机框架需要在配置会话之前将摄像头 ID 0
和 1
都打开,以便向相机 HAL 提供有关如何分配资源的提示(因为它现在要求执行并发操作)。
但是,这可能会导致功能受限,例如,缩放功能可能无法处理完整的缩放范围比例(因为切换实体摄像头 ID 可能会带来问题)。
如需解决此问题,请对 provider@2.6::ICameraProvider::getConcurrentCameraStreamingCameraIds
进行以下更新。
要求在执行并发摄像头操作时,相机框架必须先打开摄像头设备 (
@3.2::ICameraDevice::open
),然后再配置摄像头设备上的任何会话。这将使相机提供程序能够相应地分配资源。为了解决无法处理完整缩放范围比例的问题,请确保在同时使用摄像头时,相机应用只能将
ZOOM_RATIO
控制设置为 1 倍至MAX_DIGITAL_ZOOM
,而不是完整的ZOOM_RATIO_RANGE
(这样可以防止因内部切换实体摄像头而需要更多 ISP)。
testDualCameraPreview 问题
进行上述更新时,MultiViewTest.java#testDualCameraPreview
测试允许的行为可能会出现问题。
测试 testDualCameraPreview
仅在打开所有摄像头后才配置会话。其顺序如下:
for each camera in cameraDevices :
device = openCamera(camera)
createCaptureSession(device);
但是,它能容忍 ERROR_MAX_CAMERAS_IN_USE [1]
导致的摄像头打开失败。第三方应用可能依赖于此行为。
由于相机 HAL 在配置会话之前不会知道用于并发操作的完整摄像头 ID 组合,因此很难分配硬件资源(假设摄像头之间存在一定的竞争)。
为了解决此问题,除了支持并发流式传输之外,相机 HAL 应保持向后兼容性,并且应在无法支持所有摄像头并行运行的完整数据流配置时发出 ERROR_MAX_CAMERAS_IN_USE
,使 openCamera
调用失败。