并发摄像头串流

Android 允许设备支持摄像头设备的并发流式传输。例如,这允许设备同时运行前置和后置摄像头。从 Android 11 开始,Camera2 API 包含以下方法,应用可以调用这些方法来确定摄像头是否支持并发流式传输以及支持的流配置。

在并发流式传输期间必须支持的一组强制性流组合通过摄像头设备的摄像头特性包含在 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 的设备必须支持在所有保证的流组合中使用 Y8 替换 YUV 流。

s720p 指的是 720p (1280 x 720) 或 StreamConfigurationMap.getOutputSizes() 返回的特定格式的最大支持分辨率。s1440p 指的是 1440p (1920 x 1440) 或 StreamConfigurationMap.getOutputSizes() 返回的特定格式的最大支持分辨率。功能不包括 ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE 的设备必须在并发操作期间至少支持单个 Y16 流,Dataspace::DEPTH 具有 sVGA 分辨率,其中 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 01,以便向摄像头 HAL 提供关于如何分配资源的提示(因为它现在期望摄像头并发操作)。但是,这可能会导致功能受限,例如,变焦可能无法处理完整的变焦范围比率(因为切换物理摄像头 ID 可能会有问题)。

为了实现此解决方案,请对 provider@2.6::ICameraProvider::getConcurrentCameraStreamingCameraIds 进行以下更新。

  • 强制规定,对于摄像头的并发操作,摄像头框架必须在摄像头设备上配置任何会话之前打开摄像头设备(@3.2::ICameraDevice::open)。这允许摄像头供应商相应地分配资源。

  • 为了解决无法处理完整变焦范围比率的问题,请确保摄像头应用在并发使用摄像头时,保证仅在 1 倍和 MAX_DIGITAL_ZOOM 之间使用 ZOOM_RATIO 控制设置,而不是完整的 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 无法支持所有并发运行的摄像头的完整流配置,则应使 openCamera 调用失败并返回 ERROR_MAX_CAMERAS_IN_USE