Cómo usar un dispositivo como cámara web

En el caso de los dispositivos que ejecutan Android 14-QPR1 o versiones posteriores, Android admite el uso del dispositivo como una 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 cámara web. El servicio DeviceAsWebcam admite esta función para usar el dispositivo como cámara web.

Servicio DeviceAsWebcam

El servicio DeviceAsWebcam del AOSP incluye una actividad de vista previa (DeviceAsWebcamPreview.java) que permite a los usuarios enmarcar 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 anfitrión antes de que se inicie la transmisión.

  • Personaliza el feed de la cámara web enviado al anfitrión de las siguientes maneras:

    • Selección de la cámara para 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.

Feed de cámara web transmitido al organizador

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 que se admite para usar 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 de 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 a la HAL del gadget USB que recupere la función del gadget de UVC a través de una llamada a la interfaz de la HAL setUsbFunctions.
    2. Informa a la HAL del gadget USB que configure el controlador del gadget de 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 gadgets USB inicia la transmisión de la cámara web al recibir los comandos de configuración del host a través de los nodos V4L2 en /dev/video*.

dispositivo como arquitectura de 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 de UFC de forma predeterminada (consulta los detalles en el parche de AOSP).

Compatibilidad con UVC en la HAL del aparato

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

Para implementar la HAL del gadget, realiza modificaciones para activar la función de 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 una cámara web, asegúrate de que la HAL del gadget USB muestre las combinaciones de VID/PID adecuadas.

Debido a que toda la lógica de UVC se encuentra en el init del proveedor o en el servicio DeviceAsWebcam, no se requiere ninguna lógica específica de UVC, excepto la vinculación simbólica de la función de UVC con ConfigFS, en la HAL del gadget.

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

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

Para informar al controlador del gadget de UVC qué formatos, tamaños y velocidades de fotogramas son compatibles con la cámara web de Android, configura ConfigFS con las configuraciones de UVC. Para obtener más información, consulta la documentación ascendente de Linux en la ABI del gadget de 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 capacidades se comunican al host USB cuando consulta las resoluciones y velocidades de fotogramas compatibles.

Los siguientes son lineamientos generales para seleccionar la configuración que anuncia la cámara web:

  • Los dos formatos de transmisión que admite el servicio DeviceAsWebcam son MJPEG y YUYV sin comprimir.
  • El USB 2.0 admite una transferencia de datos de 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 fotograma admitido es 720p porque YUYV es de 2 bytes por píxel.
    • Transmisiones MJPEG comprimidas: suponiendo una relación de compresión de 1:10 con YUV, USB 2.0 puede admitir 4K (1.18 MB por fotograma).
  • Los dispositivos de cámara frontal y posterior principales deben admitir todos los tamaños de fotogramas que se anuncian. Esto se debe a que el usuario puede cambiar entre los IDs de 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 de cámara frontal y posterior principales deben admitir todas las velocidades de fotogramas que se anuncian. Recomendamos enfáticamente 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 ejemplo de AOSP.

Habilitar la cámara web en la compilación

Para habilitar el servicio DeviceAsWebcam, debes establecer la propiedad del sistema ro.usb.uvc.enabled como 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 al dispositivo host.

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

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

adb shell svc usb setFunctions uvc

Ten en cuenta los problemas térmicos y de potencia

Las operaciones con la cámara web implican que la cámara de un dispositivo podría 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 se mantengan debajo de ciertos límites. Las siguientes son soluciones recomendadas para mantener el consumo de energía debajo 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 la energía es un problema incluso con STREAM_USE_CASE_VIDEO_CALL habilitado, el servicio de DeviceAsWebcam ofrece la opción de reducir aún más el consumo de energía mediante transmisiones físicas. Puedes usar superposiciones de recursos de tiempo 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 recomendada para los problemas de energía. Para obtener más información sobre las RRO compatibles con el servicio DeviceAsWebcam, consulta readme.md.

    El siguiente es un ejemplo de una RRO configurada para usar el ID de cámara físico 3 en lugar del ID de cámara lógico 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 tu implementación del servicio DeviceAsWebcam en tu dispositivo, usa las siguientes pruebas:

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

Errores conocidos

Los siguientes son problemas conocidos del servicio DeviceAsWebcam: