Cómo usar un dispositivo como cámara web

En dispositivos que ejecutan Android 14-QPR1 o versiones posteriores, Android admite el uso del dispositivo como cámara web USB. Los dispositivos Android que admiten esta función se anuncian como dispositivos UVC, lo que permite que una amplia variedad de hosts USB con diferentes sistemas operativos (por ejemplo, Linux, macOS, Windows y ChromeOS) usen la cámara del dispositivo como una cámara web. El servicio DeviceAsWebcam admite esta función para usar el dispositivo como cámara web.

Servicio DeviceAsWebcam

El servicio DeviceAsWebcam en AOSP incluye una actividad de vista previa (DeviceAsWebcamPreview.java) que permite a los usuarios encuadrar la escena. La actividad de vista previa le permite al usuario hacer lo siguiente:

  • Obtén una vista previa de cómo se verá el feed de la cámara web en la máquina host antes de que comience la transmisión.

  • Personaliza el feed de la cámara web que se envía al host de las siguientes maneras:

    • Selecciona la cámara que quieres transmitir, frontal o posterior.
    • Selección del nivel de zoom con un control deslizante o botones
    • Presionar una región en particular de la vista previa para enfocar o quitar el foco en una región

La actividad de vista previa funciona con las funciones de accesibilidad generales de Android, como TalkBack, Accesibilidad con interruptores y Acceso por voz.

Se transmitió el feed de la cámara web al host

Figura 1: El feed de cámara web se está transmitiendo a un host cuya vista previa controla el feed.

Arquitectura

En la Figura 2, se ilustra la arquitectura para admitir el uso de un dispositivo como cámara web. A continuación, se describe el flujo de interacción del servicio DeviceAsWebcam con el resto del framework de Android:

  1. El usuario selecciona la opción de cámara web USB en la app de Configuración.
  2. La app de Configuración envía una llamada a Binder a system_server a través de la clase UsbManager para informarle que se seleccionó FUNCTION_UVC.
  3. El servidor del sistema hace lo siguiente:
    1. Informa al HAL del gadget USB para que recupere la función del gadget UVC a través de una llamada a la interfaz de HAL de setUsbFunctions.
    2. Informa al HAL del dispositivo USB para que configure el controlador de dispositivos UVC con ConfigFs.
  4. Cuando recibe una devolución de llamada de la HAL del aparato, system_server envía una transmisión al framework para que el servicio DeviceAsWebcam la recoja.
  5. El controlador de dispositivos USB inicia la transmisión de la cámara web cuando recibe comandos de configuración del host a través de los nodos V4L2 en /dev/video*.

arquitectura del dispositivo como cámara web

Figura 2: Arquitectura de DeviceAsWebcam.

Implementación

En esta sección, se describe cómo admitir el uso de un dispositivo Android como cámara web.

Compatibilidad con kernel

En el caso de Android 14 o versiones posteriores, la imagen genérica del kernel (GKI) habilita el controlador de gadgets UVC de forma predeterminada (consulta los detalles en el parche de AOSP).

Compatibilidad con UVC en el HAL de Gadget

A partir de Android 14, la función UVC se incluye en la interfaz de HAL de GadgetFunction.aidl. En el caso del HAL de Gadget, el gadget UVC se activa en ConfigFS de la misma manera que otras funciones de ConfigFS, como MTP o ADB.

Para implementar el HAL de Gadget, realiza modificaciones para activar la función UVC en ConfigFS. El siguiente es un fragmento de ejemplo de una implementación de la HAL de gadgets que admite la función UVC:

UsbGadget::setCurrentUsbFunctions(long functions) {
   ...
   // Existing functions
   if ((functions & GadgetFunction::MTP) != 0) {
       ...
       linkFunction("ffs.mtp"); // Mount to ConfigFS
       ...
   }
   ...
   // UVC function follows the same pattern!
   if ((functions & GadgetFunction::UVC) != 0) {
       ...
       linkFunction("uvc.0"); // Mount to ConfigFS
       ...
   }
   ...
}

Cuando el dispositivo funcione como cámara web, asegúrate de que el HAL del dispositivo USB anuncie las combinaciones de VID/PID correctas.

Debido a que toda la lógica de UVC está en la inicialización del proveedor o en el servicio DeviceAsWebcam, no se requiere ninguna lógica específica de UVC, excepto la creación de un symlink de la función UVC a ConfigFS, en el HAL del gadget.

Para obtener más orientación sobre la implementación, consulta el siguiente código de muestra en AOSP:

Configura ConfigFS con parámetros de configuración de UVC

Para informar al controlador de gadgets UVC qué formatos, tamaños y velocidades de fotogramas admite la cámara web de Android, configura ConfigFS con parámetros de configuración de UVC. Para obtener más información, consulta la documentación de Linux upstream sobre la ABI del gadget UVC de ConfigFS.

El siguiente es un ejemplo de cómo init del proveedor puede configurar el controlador de gadgets UVC (fragmento de código en AOSP):

# uvc function
   mkdir /configfs_path/functions/uvc.0
   write /configfs_path/functions/uvc.0/function_name "Android Webcam"
   write /configfs_path/functions/uvc.0/streaming_maxpacket 3072
   # setup control params
   mkdir /configfs_path/functions/uvc.0/control/header/h
   symlink /configfs_path/functions/uvc.0/control/header/h \
                /configfs_path/functions/uvc.0/control/class/fs/h
   symlink /configfs_path/functions/uvc.0/control/header/h \
                /configfs_path/functions/uvc.0/control/class/ss/h
   # advertise 1080p resolution for webcam encoded as mjpeg
   mkdir /configfs_path/functions/uvc.0/streaming/mjpeg/m/1080p
   write /configfs_path/functions/uvc.0/streaming/mjpeg/m/1080p/wHeight 1080
   write /configfs_path/functions/uvc.0/streaming/mjpeg/m/1080p/wWidth 1920
   write /configfs_path/functions/uvc.0/streaming/mjpeg/m/1080p/dwMaxVideoFrameBufferSize 4147200
   # advertise 30 fps support for 1080p.
   write /configfs_path/functions/uvc.0/streaming/mjpeg/m/1080p/dwDefaultFrameInterval 333333
   write /configfs_path/functions/uvc.0/streaming/mjpeg/m/1080p/dwFrameInterval "333333"
   # setup streaming params
   mkdir /configfs_path/functions/uvc.0/streaming/header/h
   symlink /configfs_path/functions/uvc.0/streaming/mjpeg/m \
                /configfs_path/functions/uvc.0/streaming/header/h/m
   symlink /configfs_path/functions/uvc.0/streaming/header/h \
                /configfs_path/functions/uvc.0/streaming/class/fs/h
   symlink /configfs_path/functions/uvc.0/streaming/header/h \
                /configfs_path/functions/uvc.0/streaming/class/hs/h
   symlink /configfs_path/functions/uvc.0/streaming/header/h \
                /config/usb_gadget/g1/functions/uvc.0/streaming/class/ss/h
   # ...

Este fragmento configura el controlador de gadgets UVC para anunciar una transmisión MJPEG en 1080p a 30 FPS. Estas funciones se comunican al host USB cuando consulta las resoluciones y velocidades de fotogramas compatibles.

Los siguientes son lineamientos generales para seleccionar las configuraciones que anuncia la cámara web:

  • Los dos formatos de transmisión que admite el servicio DeviceAsWebcam son MJPEG y YUYV sin comprimir.
  • USB 2.0 admite la transferencia de datos a 480 Mbps (60 MBps). Esto significa que, a 30 FPS, cada fotograma debe tener un tamaño máximo de 2 MB y, a 60 FPS, un tamaño máximo de 1 MB.
    • Transmisiones sin comprimir (YUYV): A 30 fps, el tamaño máximo de fotogramas compatible es de 720p porque YUYV es de 2 bytes por píxel.
    • Flujos de MJPEG comprimidos: Si se supone una relación de compresión de 1:10 desde YUV, USB 2.0 puede admitir 4K (1.18 MB por fotograma).
  • Los dispositivos principales de cámara frontal y posterior deben admitir todos los tamaños de fotogramas que se anuncian. Esto se debe a que el usuario puede cambiar entre los IDs de la cámara con la IU de vista previa. Para las transmisiones MJPEG, recomendamos que los proveedores anuncien tamaños de fotogramas de 480p (640 x 480), 720p (1280 x 820) y 1080p (1920 x 1080), ya que son los que suelen usar las apps host.
  • Los dispositivos principales de cámara frontal y posterior deben admitir todas las velocidades de fotogramas que se anuncian. Recomendamos que los proveedores admitan 30 fps.

Para ver un ejemplo de cómo agregar configuraciones de transmisión de cámara web (ConfigFS), consulta el parche de muestra de AOSP.

Habilita la cámara web en la compilación

Para habilitar el servicio DeviceAsWebcam, debes establecer la propiedad del sistema ro.usb.uvc.enabled en true en el archivo device.mk.

# Enable UVC support
PRODUCT_VENDOR_PROPERTIES += \
    ro.usb.uvc.enabled=true

Cuando se habilita esta propiedad del sistema, aparece la opción Cámara web en la app de Configuración en las preferencias de USB, como se muestra en la Figura 3. Cuando se selecciona la opción, el dispositivo Android aparece como una cámara web USB para el dispositivo host.

Figura 3: Preferencias de USB en la app de Configuración.

También puedes configurar el dispositivo en la función de cámara web USB a través de ADB con este comando:

adb shell svc usb setFunctions uvc

Considera las preocupaciones sobre la energía y la temperatura

Las operaciones de la cámara web implican que la cámara de un dispositivo puede estar encendida durante varias horas al día, por lo que recomendamos tomar medidas para garantizar que el consumo de energía y la temperatura del dispositivo permanezcan dentro de ciertos límites. Las siguientes son soluciones recomendadas para mantener el consumo de energía dentro de los límites:

  • Para obtener un mejor rendimiento de la energía de la HAL de la cámara, habilita STREAM_USE_CASE_VIDEO_CALL en el servicio DeviceAsWebcam.
  • Si el consumo de energía es un problema incluso con STREAM_USE_CASE_VIDEO_CALL habilitado, el servicio DeviceAsWebcam proporciona una opción para disminuir aún más el consumo de energía mediante transmisiones físicas. Puedes usar las superposiciones de recursos del entorno de ejecución (RRO) para especificar qué cámara física usar. Las transmisiones físicas disminuyen significativamente la calidad del video y generan una UX confusa, por lo que debes usar esta solución solo como último recurso. La optimización de STREAM_USE_CASE_VIDEO_CALL es la solución preferida para las inquietudes de energía. Para obtener más información sobre los RRO compatibles con el servicio de DeviceAsWebcam, consulta readme.md.

    El siguiente es un ejemplo de un RRO configurado para usar el ID de cámara física 3 en lugar del ID de cámara lógica 0. Para ver un ejemplo en AOSP, consulta DeviceAsWebcamRaven.

    // For logical camera id 0 - use physical camera id 3
    {"0": {"3" : "UW"}}
    

Verificación

Para probar la implementación del servicio DeviceAsWebcam en tu dispositivo, usa las siguientes pruebas:

  • Prueba de verificador de CTS webcam: Prueba que el dispositivo admita los formatos, los tamaños y las velocidades de fotogramas.
  • Pruebas manuales: Prueba que la función de cámara web funcione con diferentes apps host en diversos sistemas operativos.

Problemas conocidos

Los siguientes son problemas conocidos del servicio DeviceAsWebcam: