10

假设我有一个全屏运行的 OpenGL 游戏(Left 4 Dead 2)。我想以编程方式获取它的屏幕截图,然后将其写入视频文件。

我已经尝试过 GDI、D3D 和 OpenGL 方法(例如 glReadPixels),要么接收到空白屏幕,要么在捕获流中闪烁。

有任何想法吗?

就其价值而言,与我想要实现的目标类似的典型示例是 Fraps。

4

3 回答 3

13

有几种方法可以解决这个问题。它们中的大多数都是 icky,这完全取决于您想要定位哪种图形 API,以及目标应用程序使用哪些功能。大多数 DirectX、GDI+ 和 OpenGL 应用程序都是双重或三重缓冲的,因此它们都调用:

void SwapBuffers(HDC hdc)

在某一点。每当应绘制窗口时,它们还会在其消息队列中生成 WM_PAINT 消息。这为您提供了两种选择。

  • 您可以将全局挂钩或线程本地挂钩安装到目标进程中并捕获 WM_PAINT 消息。这允许您在绘制发生之前从设备上下文中复制内容。可以通过枚举系统上的所有进程并查找已知的窗口名称或已知的模块句柄来找到该进程。

  • 您可以将代码注入到目标进程的 SwapBuffers 本地副本中。在 Linux 上,这很容易通过 LD_PRELOAD 环境变量或显式调用 ld-linux.so.2 来完成,但在 Windows 上没有等效项。幸运的是,Microsoft Research 有一个框架可以为您执行此操作,称为Detours。你可以在这里找到这个:链接

演示场景组 Farbrausch 制作了一个名为 kkapture 的演示捕获工具,它利用了 Detours 库。然而,他们的工具针对不需要用户输入的应用程序,因此他们基本上通过挂钩所有可能的时间函数(如 timeGetTime()、GetTickCount() 和 QueryPerformanceCounter())以固定帧速率运行演示。这完全是拉德。可以在此处找到由 ryg(我认为?)撰写的关于 kkapture 内部的演示文稿。我认为你对此很感兴趣。

有关 Windows 挂钩的更多信息,请参阅此处此处

编辑:

这个想法引起了我的兴趣,所以我使用 Detours 来连接 OpenGL 应用程序并弄乱图形。这是添加了绿雾的 Quake 2: 雷神之锤 2 挂钩

关于 Detours 如何工作的更多信息,因为我现在已经亲身使用了它:

Detours 在两个层面上起作用。实际的挂钩仅在与目标进程相同的进程空间中起作用。因此,Detours 具有将 DLL 注入进程并强制其 DLLMain 也运行的函数,以及应该在该 DLL 中使用的函数。当 DLLMain 运行时,DLL 应该调用 DetourAttach() 来指定要挂钩的函数,以及“detour”函数,这是您要覆盖的代码。

所以它基本上是这样工作的:

  • 您有一个启动器应用程序,其唯一任务是调用 DetourCreateProcessWithDll()。它的工作方式与 CreateProcessW 相同,只是有一些额外的参数。这会将 DLL 注入进程并调用其 DllMain()。
  • 您实现一个调用 Detour 函数并设置蹦床函数的 DLL。这意味着调用 DetourTransactionBegin()、DetourUpdateThread()、DetourAttach(),然后是 DetourTransactionEnd()。
  • 使用启动器将您实现的 DLL 注入到进程中。

不过有一些警告。运行 DllMain 时,稍后使用 LoadLibrary() 导入的库尚不可见。因此,您不一定能在 DLL 附件事件期间设置所有内容。一种解决方法是跟踪到目前为止被覆盖的所有函数,并尝试在这些函数中初始化您已经可以调用的其他函数。这样,一旦 LoadLibrary 将新函数映射到进程的内存空间,您就会发现它们。我不太确定这对 wglGetProcAddress 有多好。(也许这里的其他人对此有想法?)

一些 LoadLibrary() 调用似乎失败了。我用 Quake 2 进行了测试,但 DirectSound 和 waveOut API 由于某种原因未能初始化。我还在调查这个。

于 2010-08-18T14:58:48.500 回答
0

我找到了一个名为 taksi 的 sourceforge 项目:

http://taksi.sourceforge.net/

不过,Taksi 不提供音频捕获功能。

于 2010-08-16T13:00:34.443 回答
0

我在过去(DirectX7-9 时代)写过屏幕抓取器。我发现旧的DirectDraw工作得非常好,并且可以可靠地抓取其他方法(D3D、GDI、OpenGL)似乎留下空白或乱码的硬件加速/视频屏幕内容。它也非常快。

于 2010-08-21T22:30:13.777 回答