c++ - programa - grabar pantalla windows 7
Captura de video desde una ventana de OpenGL en Windows (4)
Aquí hay dos preguntas diferentes: cómo tomar fotogramas de una aplicación OpenGL y cómo convertirlos en un archivo de película.
La primera pregunta es bastante fácil; simplemente agarra cada cuadro con glReadPixels () (a través de un PBO si necesita el rendimiento).
La segunda pregunta es un poco más difícil ya que las soluciones multiplataforma (ffmpeg) tienden a ser GPL''d o LGPL''d. ¿Es LGPL aceptable para su proyecto? La forma de hacerlo de Windows (DirectShow) es un poco dolor de cabeza para usar.
Editar: como LGPL está bien y puedes usar ffmpeg, mira aquí para ver un ejemplo de cómo codificar video.
Se supone que debo proporcionar a mis usuarios una forma muy simple de capturar videoclips de la ventana principal de mi aplicación OpenGL. Estoy pensando en agregar botones y / o atajos de teclado para iniciar y detener la captura; al comenzar, podría pedir un nombre de archivo y otras opciones, si las hay. Tiene que ejecutarse en Windows (XP / Vista), pero tampoco me gustaría cerrar la puerta de Linux que hasta ahora he podido mantener abierta.
La aplicación utiliza programas de fragmentos y sombreadores de OpenGL, cuyos efectos absolutamente necesito tener en los videos eventuales.
Me parece que podría haber incluso varios enfoques diferentes que podrían cumplir mis requisitos (pero realmente no sé dónde debería comenzar):
Una biblioteca de codificación con funciones como startRecording (filename), stopRecording y captureFrame. Podría llamar a captureFrame () después de cada fotograma procesado (o cada segundo / tercer / lo que sea). Si hacerlo hace que mi programa funcione más lento, no es realmente un problema.
Un programa externo independiente que se puede controlar mediante programación desde mi aplicación. Después de todo, un programa independiente que no se puede controlar casi hace lo que necesito ... Pero como se dijo, debería ser realmente simple para los usuarios operar, y agradecería la uniformidad también; mi aplicación generalmente se ejecuta en pantalla completa. Además, debería ser posible distribuirlo como parte del paquete de instalación para mi aplicación, que actualmente preparo usando NSIS.
Use la API de Windows para capturar capturas de pantalla cuadro por cuadro, luego emplee (por ejemplo) una de las bibliotecas mencionadas aquí . Parece ser bastante fácil encontrar ejemplos de cómo capturar capturas de pantalla en Windows; sin embargo, me encantaría una solución que realmente no me obligue a poner mis manos sucias en el nivel de WinAPI.
Use OpenGL para renderizar en un destino fuera de pantalla, luego use una biblioteca para producir el video. No sé si esto es posible, y me temo que, de todos modos, podría no ser el camino de menor dolor. En particular, no me gustaría que el renderizado real tome una ruta de ejecución diferente dependiendo de si el video se está capturando o no. Además, evitaría cualquier cosa que pueda disminuir la velocidad de cuadros en el modo normal sin captura.
Si la solución fuera gratuita en cualquier sentido de la palabra, sería genial, pero en realidad no es un requisito absoluto. En general, cuanto menos hinchazón haya, mejor. Por otro lado, por razones que van más allá de esta pregunta, lamentablemente no puedo vincular ningún código de GPL.
En cuanto al formato de archivo, no puedo esperar que mis usuarios comiencen a buscar en Google los códecs, pero siempre y cuando mostrar los videos sea lo suficientemente fácil para un usuario de Windows de nivel básico, realmente no me importa cuál es el formato. Sin embargo, sería genial si fuera posible controlar la calidad de compresión de la salida.
Solo para aclarar: no necesito capturar video desde un dispositivo externo como la videocámara, ni estoy realmente interesado en los movimientos del mouse, aunque tampoco daña. No hay requisitos con respecto al audio; la aplicación no hace ruido en absoluto.
Escribo C ++ usando Visual Studio 2008, para esta misma aplicación que también se beneficia de GLUT y GLUI. Tengo una comprensión sólida con respecto a C ++ y la vinculación en bibliotecas y ese tipo de cosas, pero por otro lado OpenGL es bastante nuevo para mí: hasta ahora, realmente solo he aprendido las partes necesarias para hacer mi trabajo.
No necesito una solución súper urgente, así que no dude en tomarse su tiempo :)
La opción más fácil es guardar cada fotograma procesado desde su aplicación y luego fusionarlos en un AVI. Cuando tienes el AVI, hay muchas bibliotecas disponibles que pueden convertirlo en un formato más óptimo, o posiblemente omitir el paso de AVI por completo.
En términos de obtener cada fotograma, puede lograr esto ya sea convirtiendo en una textura fuera de pantalla como sugiere o utilizando el backbuffer directamente como fuente si su hardware lo admite. Hacer cualquiera de estos (y guardar cada fotograma) va a ser difícil sin una gran penalización en el framerate.
Siempre que su aplicación sea determinista, podría "registrar" las acciones de los usuarios como una serie de entradas y luego tener un modo de exportación que las transfiera secuencialmente a una superficie fuera de pantalla para generar el AVI.
Esto se ve bastante relevante para fusionarse en un AVI (como lo sugirió Andrew), sin embargo, realmente esperaba evitar los LPBITMAPINFOHEADER, etc.
Gracias por las respuestas, informaré sobre el éxito si va a haber alguno :)
Mientras tanto, se agradecerían sugerencias adicionales para codificar los cuadros brutos de glReadPixels
en video clips.
Editar: Hasta ahora, ffmpeg sugerido por Mike F parece ser el camino a seguir. Sin embargo, todavía no me metí en la implementación real, pero espero que eso cambie en el futuro cercano.
Tuve que crear un proyecto de demostración para grabar un renderizado de OpenGL en un video. Utilicé glReadPixels
para obtener los datos de píxeles y creé el video con cvWriteFrame
de OpenCV. OpenCV le permite escribir en divx o incluso x264 / vp8 (con ffmpeg compilado).
Tengo un informe más detallado en mi blog junto con un proyecto de muestra. http://tommy.chheng.com/2013/09/09/encode-opengl-to-video-with-opencv/