Captura de pantalla del video del juego

8

Me gustaría "enganchar" en un juego en ejecución, digamos Mario Bros, y capturar cada fotograma renderizado ... guardando ese fotograma en un archivo de imagen. Un buen ejemplo de algo similar es FRAPS. --Nota: no quiero capturar toda la pantalla / escritorio. Quiero capturar una ventana específica.

He echado un vistazo a OBS (Open Broadcasting Software) pero no es particularmente rápido. No me malinterpreten, es un gran software, pero desafortunadamente no hay / hay poca documentación, lo que hace que un proyecto masivo escrito en c y c ++ sea casi inaccesible para un programador nuevo en c ++.

También he echado un vistazo a GamingAnywhere , pero desafortunadamente, no puedo hacer que funcione, hay muy poca / ninguna documentación, solo se ejecuta en VS2010 y es desordenado (con una mala denominación variable). Sin embargo, es un proyecto de investigación, por lo que es comprensiblemente indocumentado y desordenado.

Sé que esto se puede hacer con OpenGL, GDI y con Direct3D, pero no puedo encontrar algunos buenos ejemplos en la red.

Leí que se puede usar glReadlPixels (usando OpenGL) y he leído la documentación , pero la publicación no mencionó nada sobre conectar a un juego / gráficos en ejecución.

Preguntas:

  1. ¿Puedo conectarme a los gráficos de un juego desarrollado con OpenGL, usando, por ejemplo, Direct3D? ¿La biblioteca utilizada para enganchar tiene que ser la misma que la utilizada por el juego?

  2. ¿Cómo me engancho a los cuadros renderizados del juego para poder enviar esos cuadros a archivos de imagen o de video? (Solo algunos enlaces o una breve explicación de lo que necesito hacer sería genial)

  3. BackBuffer: leí que es muy rápido acceder a BackBuffer para recuperar los marcos. ¿Alguien tiene un ejemplo para mí sobre cómo hacer esto con las últimas bibliotecas? He descubierto que la mayoría de los ejemplos están desactualizados.

  4. Para mis propósitos, ¿hay claramente "esto es más rápido que eso"? Lo que quiero decir es, ¿sería, por ejemplo, OpenGL, más rápido para mis propósitos?

Si alguien sabe de un proyecto de código abierto (que hace esencialmente lo que necesito) que está activamente desarrollado y bien documentado, me encantaría saberlo.

pookie
fuente
Ahora parece ser solo Mac, que puede no funcionar para usted con Direct3D, pero Siphon Inject que OBS usa en Mac puede capturar ventanas de juegos que usan OpenGL mucho más rápido que la captura de video estándar. Syphon "permite que las aplicaciones compartan fotogramas (video o imágenes fijas a velocidad de fotograma completo) entre sí en tiempo real" para citar el sitio web.
Gliderman
@Gliderman ¡Gracias, lo comprobaré!
pookie

Respuestas:

7

Es posible hacer lo que usted describe, pero me temo que no es un proceso trivial. En realidad, esto estará muy vinculado a los sistemas operativos a los que se dirige y posiblemente también requiera ajustes específicos para el juego / aplicación en cuestión.

Comenzaría a buscar técnicas de inyección de DLL , que deberían permitir, por ejemplo, interceptar llamadas a las API de Direct3D (Windows) u OpenGL, que luego puede usar para copiar los framebuffers de la aplicación. Una búsqueda rápida en Internet muestra esto y esto con una explicación detallada.

Una vez escribí un interceptor OpenGL a pequeña escala en MacOS inyectando un módulo compartido personalizado, pero estaba bajo circunstancias muy controladas y hacía muchas suposiciones, como tener privilegios de root en el sistema, por lo que para una herramienta de producción, sería Mucho más complicado. Puede encontrar otro proyecto muy interesante aquí sobre la interceptación de la API D3D para instalar un robot de IA automatizado en Starcraft, que debe tocar conceptos muy similares a lo que está buscando.

Una vez que logre interceptar la API de representación subyacente, tal vez podría enganchar su código en cada SwapBuffersllamada o una llamada equivalente para copiar el framebuffer anterior antes del intercambio, y luego guardarlo (aquí es donde glReadPixelsentraría en juego algo así ).

Copiar y guardar el framebuffer de manera eficiente también es un desafío. La manera fácil es simplemente volcar cada cuadro como una imagen RGB sin comprimir, pero luego terminarás con cientos de gigabytes de datos por solo un par de minutos de juego, a menos que tengas una buena matriz de HDD en la esquina de en su mesa ;), tendrá que buscar comprimir los marcos de alguna manera.

La desventaja de comprimir los cuadros ahora es que requiere mucho procesamiento, por lo que un enfoque ingenuo podría convertir la aplicación interactiva que intenta grabar en una presentación interactiva :(. Entonces, en esta etapa, tendría que comenzar a pensar en optimizaciones.

No conozco ningún proyecto que ofrezca una biblioteca para capturar cuadros de manera eficiente para los juegos, ¡pero esto sería algo agradable de tener! Creo que una cosa que podría estar frenando dicho proyecto es, como mencioné al principio, que esto es muy dependiente del sistema, por lo que los casos de uso probablemente se limitarán a una sola plataforma o sistema operativo.

glampert
fuente
Gracias por la respuesta. Creo que, en última instancia, en lugar de guardar imágenes, las transmitiré a una máquina remota, por lo que copiar el framebuffer puede ser el camino a seguir. Parece que tienes bastante experiencia con estas cosas. ¿Puede ampliar alguna de las preguntas que planteé? ¡Gracias por la ayuda!
pookie
1
@pookie ¡Hola! Claro, puedo ampliar esto. ¿Hay algo en particular que le gustaría que comente? Para sus preguntas, creo que 1 y 2 se pueden hacer con los ganchos de DLL, así que asegúrese de leer los enlaces que he incluido (especialmente el de Starcraft). 3 y 4 serán específicos de la API, pero en OpenGL, puede comenzar con glReadPixels y trabajar desde allí si lo encuentra demasiado lento. Mi experiencia es de la grabación de cuadros de mis propios juegos, además de algunos hackeo de DLL realizados en el pasado, pero nunca he combinado ambos en el intento de grabar cuadros de una aplicación de terceros;)
glampert
¡Gracias! He comprobado los enlaces: la inyección de DLL de Windows y el enlace de StarCraft (bastante impresionante) parecen ser buenos puntos de partida. También echaré un vistazo a glReadPixels. En su opinión, ¿con cuál le resultó más fácil trabajar y cuál encontró más rápido: DirectX u OpenGL?
pookie
@pookie, si tienes algo de experiencia en programación, creo que Direct3D será mucho más fácil de usar, las bibliotecas están mejor diseñadas. OpenGL también puede tener "bordes ásperos" en mi opinión (esto viene de alguien que usa OpenGL más que D3D). D3D es solo para Windows, por lo que puede ser negativo para usted, no lo sé. En cuanto al rendimiento, no creo que vaya a hacer una gran diferencia cuál usas. El mejor consejo que probablemente pueda darle es: primero descubra cómo hacerlo funcionar, luego preocúpese por las optimizaciones.
glampert
1
Ah, está bien, si estás familiarizado con la programación OOP, entonces D3D definitivamente será más fácil. OpenGL es todo de procedimiento y utiliza un montón de estado global, eso es principalmente lo que quise decir sobre bordes irregulares. ¡La mejor de las suertes para ti!
glampert