外部 USB 摄像头

Android 平台支持使用即插即用的 USB 摄像头(即网络摄像头),方法是使用标准 Android Camera2 API 和摄像头 HAL 接口。网络摄像头通常支持 USB 视频类 (UVC) 驱动程序,并且在 Linux 上,标准 Video4Linux (V4L) 驱动程序用于控制 UVC 摄像头。

由于支持网络摄像头,设备可以用于轻量级用例,例如视频聊天和照片亭。此功能不会取代 Android 手机上典型的内部摄像头 HAL,并且不旨在支持性能密集型、复杂的任务,这些任务涉及高分辨率和高速流媒体、AR 以及手动 ISP/传感器/镜头控制。

USB 摄像头 HAL 进程是外部摄像头提供程序的一部分,该提供程序监听 USB 设备可用性并相应地枚举外部摄像头设备。此进程具有与内置摄像头 HAL 进程类似的权限和 SE 策略。与 USB 设备直接通信的第三方网络摄像头应用需要与任何常规摄像头应用相同的摄像头权限才能访问 UVC 设备。

示例和来源

有关如何实现 USB 摄像头的更多信息,请参阅 ExternalCameraProvider 上的外部摄像头提供程序参考实现。外部摄像头设备和会话实现在 ExternalCameraDeviceExternalCameraDeviceSession 中。从 API 级别 28 开始,Java 客户端 API 包含 EXTERNAL 硬件级别。

实现

该实现必须支持 android.hardware.usb.host 系统功能。

还必须启用对 UVC 设备的内核支持。您可以通过将以下内容添加到相应的内核 defconfig 文件来启用此功能。

+CONFIG_USB_VIDEO_CLASS=y
+CONFIG_MEDIA_USB_SUPPORT=y

要在相应的设备版本中启用外部摄像头提供程序,这将添加必要的 SELinux 权限、外部摄像头配置和外部摄像头提供程序依赖项,请完成以下步骤

  • 将外部摄像头配置文件和外部摄像头库添加到 device.mk

    +PRODUCT_PACKAGES += android.hardware.camera.provider-V1-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="aidl">
        <name>android.hardware.camera.provider</name>
        <version>1</version>
        <interface>
            <name>ICameraProvider</name>
            <instance>internal/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>
        <ignore> <!-- Internal video devices to be ignored by external camera HAL -->
            <id>0</id> <!-- No leading/trailing spaces -->
            <id>1</id>
        </ignore>
    </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 文件来自定义外部摄像头提供程序。具体来说,客户端可以自定义以下参数

  • 排除内部摄像头的视频节点
  • 支持的图像尺寸和帧速率上限
  • 飞行中缓冲区数量(卡顿与内存权衡)

除了这些参数之外,您还可以添加自己的参数或开发自己的配置。

设备特定的优化

您还可以通过添加设备特定的优化来提高性能。

缓冲区复制/缩放和 JPEG 解码/编码

通用实现使用 CPU (libyuv/libjpeg),但您可以将其替换为设备特定的优化。

HAL 输出格式

通用实现使用以下输出格式

  • YUV_420_888 用于视频 IMPLEMENTATION_DEFINED 缓冲区
  • YUV12 用于所有其他 IMPLEMENTATION_DEFINED 缓冲区

为了提高性能,您可以将输出格式替换为设备特定的高效格式。您还可以在自定义实现中支持其他格式

验证

支持外部摄像头的设备必须通过 camera CTS。在整个测试运行期间,外部 USB 网络摄像头必须保持插入特定设备,否则某些测试用例将失败。