Captura de tela do vídeo do jogo

8

Eu gostaria de "enganchar" um jogo de corrida, digamos Mario Bros, e capturar cada quadro renderizado ... salvando esse quadro em um arquivo de imagem. Um bom exemplo de algo semelhante é o FRAPS. --Nota: não quero capturar a tela inteira / área de trabalho. Eu quero capturar uma janela direcionada.

Eu dei uma olhada no OBS (Open Broadcasting Software), mas não é particularmente rápido. Não me interpretem mal, é um ótimo software, mas infelizmente não existe documentação ruim / ruim, tornando um projeto enorme escrito em c e c ++ quase inacessível para um programador novo em c ++.

Também dei uma olhada no GamingAnywhere , mas, infelizmente, não consigo fazê-lo funcionar, há muito pouca / nenhuma documentação, é executada apenas no VS2010 e é confusa (com pouca nomeação de variáveis). No entanto, é um projeto de pesquisa e, portanto, é compreensivelmente indocumentado e confuso.

Sei que isso pode ser feito com OpenGL, GDI e Direct3D, mas não consigo encontrar bons exemplos na rede.

Li que glReadlPixels (usando OpenGL) pode ser usado e li a documentação , mas o post não mencionou nada sobre conectar-se a gráficos de jogos / aplicativos em execução.

Questões:

  1. Posso conectar-me aos gráficos de um jogo desenvolvido com OpenGL, usando, por exemplo, o Direct3D? A biblioteca usada para conectar tem que ser a mesma usada pelo jogo?

  2. Como conectar nos quadros renderizados do jogo para que eu possa produzir esses quadros em arquivos de imagem ou em um arquivo de vídeo? (Apenas alguns links ou uma breve explicação do que eu preciso fazer seriam ótimos)

  3. BackBuffer - Eu li que é muito rápido acessar o BackBuffer para recuperar os quadros. Alguém tem um exemplo para mim sobre como fazer isso com as bibliotecas mais recentes? Eu descobri que a maioria dos exemplos está desatualizada.

  4. Para meus propósitos, há claramente "isso é mais rápido que isso"? O que quero dizer é que, digamos, o OpenGL, seria mais rápido para meus propósitos?

Se alguém souber de um projeto de código aberto (que faz essencialmente o que eu preciso) que esteja ativamente desenvolvido e bem documentado, eu adoraria saber sobre ele.

pookie
fonte
Agora, isso parece ser apenas para Mac, o que pode não funcionar para você com o Direct3D, mas o Siphon Inject, que o OBS usa no Mac, pode capturar janelas de jogos que usam OpenGL muito mais rápido que a captura de vídeo padrão. O sifão "permite que os aplicativos compartilhem quadros - vídeos com taxa de quadros total ou fotos - em tempo real" para citar o site.
Gliderman
@ Gliderman Obrigado, vou verificar isso!
Pookie

Respostas:

7

É possível fazer o que você descreve, mas receio que não seja um processo trivial. Na verdade, isso estará muito ligado aos sistemas operacionais que você está alvejando e possivelmente também exigirá ajustes específicos para o jogo / aplicativo em questão.

Eu começaria a examinar as técnicas de injeção de DLL , que deveriam permitir, por exemplo, interceptar chamadas para as APIs Direct3D (Windows) ou OpenGL, que você pode usar para copiar os buffers de quadros do aplicativo. Uma rápida pesquisa na Internet mostra isso e isso com explicações detalhadas.

Certa vez, escrevi um interceptor OpenGL de pequena escala no MacOS injetando um módulo compartilhado personalizado, mas ele estava sob circunstâncias muito controladas e com várias suposições, como ter privilégios de root no sistema; portanto, para uma ferramenta de produção, seria muito mais complicado. Você pode encontrar outro projeto muito interessante aqui sobre interceptar a API do D3D para instalar um bot automatizado de IA no Starcraft, que deve abordar conceitos muito semelhantes aos que você está procurando.

Depois de conseguir interceptar a API de renderização subjacente, talvez você possa conectar seu código a cada SwapBufferschamada ou equivalente para copiar o buffer de quadros anterior antes da troca e salvá-lo (é aí que algo como glReadPixelsentraria em jogo).

Copiar e salvar o buffer de estrutura de maneira eficiente também é um desafio. A maneira mais fácil é despejar cada quadro como uma imagem RGB descompactada, mas você terá centenas de gigabytes de dados por apenas alguns minutos de jogo, a menos que você tenha um bom HDD na esquina da Na sua mesa ;), você precisará compactar os quadros de alguma forma.

A desvantagem de compactar os quadros agora é que é preciso muito processamento, portanto, uma abordagem ingênua pode transformar o aplicativo interativo que você está tentando gravar em uma apresentação interativa :(. Portanto, nesse estágio, você terá que começar a pensar em otimizações.

Não conheço nenhum projeto por aí que forneça uma biblioteca para captura eficiente de quadros para jogos, mas isso certamente seria algo bom de se ter! Eu acho que uma coisa que pode estar atrasando esse projeto é, como mencionei no começo, que isso depende muito do sistema; portanto, os casos de uso provavelmente serão limitados a uma única plataforma ou sistema operacional.

glampert
fonte
Obrigado pela resposta. Penso que, em última análise, em vez de salvar imagens, transmito-as para uma máquina remota, portanto, copiar o buffer de quadros pode ser o caminho a seguir. Você parece ter um pouco de experiência com essas coisas. Você é capaz de expandir qualquer uma das perguntas que eu fiz? Obrigado pela ajuda!
Pookie
11
@pookie Hey! Claro, eu posso expandir isso. Há algo específico que você gostaria que eu comente? Para suas perguntas, acho que o 1 e o 2 podem ser feitos com os ganchos DLL, por isso não deixe de ler os links que incluí (especialmente o sobre starcraft). 3 e 4 serão específicos da API, mas no OpenGL, você pode começar com o glReadPixels e trabalhar a partir daí se achar muito lento. A minha experiência é de gravação de quadros de meus próprios jogos mais algum DLL hacking feito no passado, mas nunca combinado tanto na tentativa de gravar imagens de um aplicativo de terceiros;)
glampert
Obrigado! Verifiquei os links - a injeção de DLL do Windows e o link de starcraft (bastante impressionantes) parecem ser bons pontos de partida. Também analisarei o glReadPixels. Na sua opinião, com quem você achou mais fácil trabalhar e com quem achou mais rápido: DirectX ou OpenGL?
Pookie
@ pookie, se você tem alguma experiência em programação, acho que o Direct3D será muito mais fácil de usar, as bibliotecas são melhor projetadas. O OpenGL também pode ter "arestas" na minha opinião (isso vem de alguém que usa o OpenGL mais que o D3D). O D3D é apenas para Windows, portanto isso pode ser negativo para você, não sei. Em termos de desempenho, acho que não fará muita diferença qual deles você usa. O melhor conselho que provavelmente posso lhe dar é: primeiro descubra como fazê-lo funcionar e depois se preocupe com as otimizações.
glampert
11
Ah, ok, se você estiver familiarizado com a programação OOP, o D3D será definitivamente mais fácil. O OpenGL é todo processual e usa um monte de estado global, foi o que eu quis dizer sobre arestas. Boa sorte para você!
Glampert