多摄像头支持

Android 9 通过新的逻辑摄像头设备引入了对多摄像头设备的 API 支持,该设备由两个或多个指向同一方向的物理摄像头设备组成。逻辑摄像头设备作为单个 CameraDevice/CaptureSession 向应用公开,从而允许与 HAL 集成的多摄像头功能进行互动。应用可以选择访问和控制底层物理摄像头流、元数据和控件。

Multi-camera support

图 1. 多摄像头支持

在此图中,不同的摄像头 ID 采用颜色编码。应用可以同时从每个物理摄像头流式传输原始缓冲区。也可以设置单独的控件并从不同的物理摄像头接收单独的元数据。

示例和来源

多摄像头设备必须通过 logical multi-camera 功能进行通告。

摄像头客户端可以通过调用 getPhysicalCameraIds() 查询特定逻辑摄像头所包含的物理设备的摄像头 ID。作为结果一部分返回的 ID 随后通过 setPhysicalCameraId() 用于单独控制物理设备。可以通过调用 getPhysicalCameraResults() 从完整结果中查询此类单独请求的结果。

各个物理摄像头请求可能仅支持参数的有限子集。要接收受支持参数的列表,开发者可以调用 getAvailablePhysicalCameraRequestKeys()

物理摄像头数据流仅支持非重新处理请求,且仅支持单色和拜耳传感器。

实现

支持清单

要在 HAL 端添加逻辑多摄像头设备

对于运行 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 数据流替换为两个来自不同物理摄像头的相同大小和格式的物理数据流,前提是物理摄像头支持该大小和格式。

  • 如果逻辑摄像头未通告 RAW 功能,但底层物理摄像头通告了 RAW 功能,则添加两个 RAW 数据流,每个数据流来自一个物理摄像头。当物理摄像头具有不同的传感器尺寸时,通常会发生这种情况。

  • 使用物理数据流代替相同大小和格式的逻辑数据流。当物理数据流和逻辑数据流的最小帧持续时间相同时,这不得降低捕获的帧速率。

性能和功耗注意事项

  • 性能

    • 由于资源限制,配置和流式传输物理数据流可能会降低逻辑摄像头的捕获速率。
    • 如果将底层摄像头设置为不同的帧速率,则应用物理摄像头设置可能会降低捕获速率。
  • 电源

    • HAL 的功耗优化在默认情况下继续工作。
    • 配置或请求物理数据流可能会覆盖 HAL 的内部功耗优化,并导致更高的功耗。

自定义

您可以通过以下方式自定义设备实现。

  • 逻辑摄像头设备的融合输出完全取决于 HAL 实现。融合逻辑数据流如何从物理摄像头派生而来这一决定对于应用和 Android 摄像头框架是透明的。
  • 可以有选择地支持单个物理请求和结果。此类请求中可用参数的集合也完全取决于特定的 HAL 实现。
  • 从 Android 10 开始,HAL 可以通过选择不在 getCameraIdList 中通告部分或全部 PHYSICAL_ID,来减少应用可以直接打开的摄像头数量。然后,调用 getPhysicalCameraCharacteristics 必须返回物理摄像头的特性。

验证

逻辑多摄像头设备必须像任何其他常规摄像头一样通过摄像头 CTS。LogicalCameraDeviceTest 模块中可以找到针对此类设备的测试用例。

以下三个 ITS 测试针对多摄像头系统,以促进图像的正确融合

场景 1 和场景 4 测试使用 ITS-in-a-box 测试装置运行。test_multi_camera_match 测试断言,当两个摄像头都启用时,图像中心的亮度是否匹配。test_multi_camera_alignment 测试断言,摄像头间距、方向和畸变参数是否已正确加载。如果多摄像头系统包含广角 FoV 摄像头 (>90o),则需要 rev2 版本的 ITS box。

Sensor_fusion 是第二个测试装置,它支持重复的、规定的手机运动,并断言陀螺仪和图像传感器时间戳是否匹配,以及多摄像头帧是否同步。

所有 box 均可通过 AcuSpec, Inc. (www.acuspecinc.com, fred@acuspecinc.com) 和 MYWAY Manufacturing (www.myway.tw, sales@myway.tw) 获得。此外,rev1 ITS box 可以通过 West-Mark (www.west-mark.com, dgoodman@west-mark.com) 购买。

最佳实践

为了充分利用多摄像头启用的功能,同时保持应用兼容性,在实现逻辑多摄像头设备时,请遵循以下最佳实践

  • (Android 10 或更高版本)从 getCameraIdList 中隐藏物理子摄像头。这减少了应用可以直接打开的摄像头数量,从而消除了应用进行复杂摄像头选择逻辑的需要。
  • (Android 11 或更高版本)对于支持光学变焦的逻辑多摄像头设备,实现 ANDROID_CONTROL_ZOOM_RATIO API,并仅使用 ANDROID_SCALER_CROP_REGION 进行宽高比裁剪。ANDROID_CONTROL_ZOOM_RATIO 使设备能够缩小并保持更好的精度。在这种情况下,HAL 必须调整 ANDROID_SCALER_CROP_REGIONANDROID_CONTROL_AE_REGIONSANDROID_CONTROL_AWB_REGIONSANDROID_CONTROL_AF_REGIONSANDROID_STATISTICS_FACE_RECTANGLESANDROID_STATISTICS_FACE_LANDMARKS 的坐标系,以将变焦后的视野视为传感器活动阵列。有关 ANDROID_SCALER_CROP_REGION 如何与 ANDROID_CONTROL_ZOOM_RATIO 协同工作的更多信息,请参阅 camera3_crop_reprocess#cropping
  • 对于物理摄像头功能不同的多摄像头设备,请确保设备仅在其整个变焦范围支持某个值或范围时才通告对该控件的特定值或范围的支持。例如,如果逻辑摄像头由超广角、广角和长焦摄像头组成,请执行以下操作
    • 如果物理摄像头的活动阵列尺寸不同,则摄像头 HAL 必须执行从物理摄像头的活动阵列到逻辑摄像头活动阵列的映射,以用于 ANDROID_SCALER_CROP_REGIONANDROID_CONTROL_AE_REGIONSANDROID_CONTROL_AWB_REGIONSANDROID_CONTROL_AF_REGIONSANDROID_STATISTICS_FACE_RECTANGLESANDROID_STATISTICS_FACE_LANDMARKS,以便从应用的视角来看,坐标系是逻辑摄像头的活动阵列尺寸。
    • 如果广角和长焦摄像头支持自动对焦,但超广角摄像头是固定对焦,请确保逻辑摄像头通告自动对焦支持。HAL 必须为超广角摄像头模拟自动对焦状态机,以便当应用缩小到超广角镜头时,底层物理摄像头是固定对焦这一事实对于应用是透明的,并且受支持的 AF 模式的自动对焦状态机按预期工作。
    • 如果广角和长焦摄像头支持 4K @ 60 fps,而超广角摄像头仅支持 4K @ 30 fps 或 1080p @ 60 fps,但不支持 4K @ 60 fps,请确保逻辑摄像头不在其支持的数据流配置中通告 4k @ 60 fps。这保证了逻辑摄像头功能的完整性,确保应用不会遇到在 ANDROID_CONTROL_ZOOM_RATIO 值小于 1 时无法实现 4k @ 60 fps 的问题。
  • 从 Android 10 开始,逻辑多摄像头不需要支持包含物理数据流的数据流组合。如果 HAL 支持包含物理数据流的组合
    • (Android 11 或更高版本)为了更好地处理诸如来自立体的深度和运动跟踪等用例,请使物理数据流输出的视野尽可能大,以硬件可以实现的程度为限。但是,如果物理数据流和逻辑数据流源自同一物理摄像头,则硬件限制可能会强制物理数据流的视野与逻辑数据流相同。
    • 为了解决由多个物理数据流引起的内存压力,请确保应用使用 discardFreeBuffers 来释放空闲缓冲区(使用者释放但生产者尚未出队的缓冲区),如果预计物理数据流将空闲一段时间。
    • 如果来自不同物理摄像头的物理数据流通常未附加到同一请求,请确保应用使用 surface group,以便使用一个缓冲区队列来支持两个面向应用 Surface,从而减少内存消耗。