En este artículo explico de forma práctica cómo importar texturas externas en WebGPU usando la API actualizada de Dawn y, concretamente, cómo integrar un flujo de vídeo generado por FFmpeg en un contexto DirectX11 para su uso en WGPU nativo. También describo la arquitectura que implementé en mi motor NervLand y comparto ideas clave para gestionar la decodificación por hardware, la conversión NV12 a RGBA y la importación de texturas compartidas en Dawn.

Resumen del flujo de trabajo: partimos de un fichero de vídeo mp4 con codificación x264 que abrimos con FFmpeg. Configuramos el decodificador para usar aceleración por hardware y producir frames directamente como texturas DirectX en el dispositivo de decodificación. Copiamos la subcapa relevante de la textura NV12 generada por FFmpeg a una textura intermedia susceptible de ser usada como shader resource. Convertimos NV12 a RGBA en DX11 con un compute shader, exportamos esa textura RGBA como textura compartida y la importamos en Dawn/WGPU mediante la API Shared Texture handling. Finalmente procesamos la textura WGPU como cualquier otra textura y la mostramos en la escena.

Limitaciones actuales: implementación mínima y orientada a Windows. El decodificador concreto FFMPEGVideoDecoder depende de los binarios de FFmpeg y por ahora se compila y ejecuta sólo en la versión nativa del motor, no en builds con Emscripten. Además se exige el backend DirectX12 en Dawn y DirectX11 VA en FFmpeg para el flujo que aquí describo. Es un punto de partida funcional pero sujeto a más pruebas y portabilidad.

Arquitectura del reproductor: añadí una clase VideoPlayer que contiene una abstracción VideoDecoder y una implementación concreta FFMPEGVideoDecoder. Al crear un VideoPlayer se registra en el motor para mantener su referencia, se le asigna una región objetivo dentro de la textura BSP del mundo y se lanza la reproducción. El ciclo de reproducción se integra con el bucle del motor registrando una callback previa al render que actualiza el playback y solicita frames al decodificador según el tiempo transcurrido y la tasa de frames del vídeo.

Inicialización del decodificador: al abrir el fichero usamos avformat_open_input y avformat_find_stream_info para localizar la pista de vídeo. Calculamos el FPS con r_frame_rate o avg_frame_rate y leemos las dimensiones del frame. Si se solicita aceleración por hardware intentamos configurar un contexto AVHWDeviceContext con av_hwdevice_ctx_alloc para el tipo AV_HWDEVICE_TYPE_D3D11VA y asignamos la D3D11 device del motor al campo adecuado del contexto FFmpeg. Tras av_hwdevice_ctx_init creamos un AVCodecContext y lo enlazamos al hw_device_ctx con av_buffer_ref. Con ello FFmpeg decodifica frames en texturas DirectX con formato DXGI_FORMAT_NV12.

Problemas habituales y su solución: la textura salida del decodificador suele tener las siguientes restricciones que hay que tratar: 1) formato NV12 que no es RGBA, 2) la textura está creada con BIND_DECODER y no es usable como shader resource, 3) la textura no tiene por defecto flags de compartición, 4) FFmpeg presenta el resultado como Texture2DArray y cada frame puede residir en un layer distinto. Para resolverlo copiamos la subcapa o slice necesaria con CopySubresourceRegion a una textura intermedia NV12 de una sola capa que sí podamos usar como shader resource.

Conversión NV12 a RGBA en DX11: a partir de la textura NV12 intermedia creamos dos SRV que referencian las dos planos: SRV luminancia con formato R8_UNORM y SRV crominancia con formato R8G8_UNORM. Ejecutamos un compute shader que muestrea Y a resolución completa y UV a resolución reducida (cada UV cubre 2x2 píxeles), reconstruye YUV, aplica la matriz BT.709 de conversión a RGB y escribe en una textura RWTexture2D RGBA8. Ese resultado lo creamos como textura compartida con flags apropiados para compartir entre dispositivos y obtener un handle de compartición.

Importación en Dawn/WGPU: con el handle de la textura compartida creamos un SharedTextureMemory en Dawn mediante la estructura SharedTextureMemoryDXGISharedHandleDescriptor y luego creamos una WGPU Texture interfase que representa la textura DX11 dentro del contexto WGPU. Para acceder a ese recurso es necesario encerrar la operación con BeginAccess y EndAccess sobre el SharedTextureMemory, y después ejecutar una operación de copia en WGPU que lleve los píxeles desde la textura importada a la textura objetivo en el atlas o la región del BSP que use la escena.

Bucle de reproducción y sincronización: el VideoPlayer mantiene tiempo de reproducción y contador de frames. En cada tick calculamos si corresponde decodificar el siguiente frame según el FPS. Cuando el decodificador produce un frame hw_frame con formato AV_PIX_FMT_D3D11 tomamos el puntero ID3D11Texture2D y el índice de layer, copiamos la subcapa a la textura NV12 intermedia, ejecutamos el compute shader NV12 a RGBA, y luego iniciamos BeginAccess en la memoria compartida, ejecutamos la copia WGPU y cerramos con EndAccess. Si se alcanza el final del fichero se detiene la reproducción.

Resumen técnico: 1) FFmpeg decodifica frames HW en texturas DX11 NV12; 2) copiar el slice de interés a una textura NV12 de una sola capa; 3) descomponer NV12 en Y y UV mediante SRV y convertir a RGBA con compute shader; 4) crear la textura RGBA como recurso compartido y obtener su handle; 5) importar ese handle en Dawn como SharedTextureMemory y crear la textura WGPU asociada; 6) envolver accesos con BeginAccess/EndAccess y copiar a la textura objetivo en WGPU. Con este flujo se logra reproducción acelerada por GPU y la integración de frames de vídeo nativos en pipelines WebGPU.

Recomendaciones y buenas prácticas: validar formatos DXGI y convertir a los formatos WGPU equivalentes, gestionar correctamente referencias COM en D3D para evitar fugas, configurar sincronización al compartir recursos entre dispositivos y precomputar grupos de dispatch del compute shader según el tamaño del frame para mantener eficiencia. Probar con diferentes perfiles de codificación y resoluciones para asegurar estabilidad en entornos reales.

Acerca de Q2BSTUDIO: en Q2BSTUDIO somos una empresa de desarrollo de software y aplicaciones a medida especializada en soluciones personalizadas para empresas. Ofrecemos servicios de software a medida, inteligencia artificial aplicada, ciberseguridad, servicios cloud aws y azure, y servicios inteligencia de negocio. Si necesita una aplicación que integre reproducción avanzada de vídeo y procesamiento acelerado por GPU podemos diseñar la solución a medida que mejor encaje con su arquitectura. Conozca nuestros servicios de desarrollo de aplicaciones y software multiplataforma en desarrollo de aplicaciones a medida y descubra nuestras capacidades en IA y soluciones para empresas en inteligencia artificial para empresas.

Palabras clave: aplicaciones a medida, software a medida, inteligencia artificial, ciberseguridad, servicios cloud aws y azure, servicios inteligencia de negocio, ia para empresas, agentes IA, power bi. Si desea que le ayudemos a portar o optimizar un flujo similar en su proyecto, contacte con nosotros y le asesoramos sobre la mejor arquitectura y las opciones de integración según sus objetivos.

Conclusión: integrar FFmpeg con aceleración por hardware y Dawn/WGPU es factible aunque requiere tratar formatos específicos como NV12, gestionar permisos y flags de texturas y usar shaders de conversión. Este enfoque permite decodificar vídeo y usarlo como textura en aplicaciones WebGPU nativas con alto rendimiento y bajo coste CPU. Si busca un partner técnico para implementar esta clase de funcionalidades en su producto, Q2BSTUDIO puede acompañarle desde el diseño hasta la puesta en producción.