最快的屏幕捕获方法
我想为Windows平台编写一个截屏方案,但我不确定如何捕获屏幕。 我知道的唯一方法是使用GDI,但我很好奇是否还有其他方法可以解决这个问题,并且如果有的话,哪些方法的开销最小? 速度是重中之重。
该屏幕录制计划将用于录制游戏画面,但如果这样做缩小了选项范围,我仍然乐意接受其他任何超出此范围的建议。 毕竟,知识并不坏。
编辑 :我遇到了这篇文章:捕获屏幕的各种方法。 它向我介绍了Windows Media API的实现方式以及DirectX的实现方式。 它在结论中提到,禁用硬件加速可以大大提高捕获应用程序的性能。 我很好奇这是为什么。 任何人都可以为我填写缺失的空白吗?
编辑 :我读了Camtasia等屏幕录像程序使用他们自己的捕捉驱动程序。 有人能给我一个深入的解释,说明它是如何工作的,为什么它更快? 我也可能需要关于实现类似的指导,但是我确定无论如何都存在现有的文档。
另外,我现在知道FRAPS如何记录屏幕。 它挂钩底层图形API以从后台缓冲区中读取。 据我所知,这比从前端缓冲区读取更快,因为您正在从系统RAM读取数据,而不是视频RAM。 你可以在这里读这篇文章。
这就是我用来收集单个帧的方法,但是如果你修改这个并且保持两个目标始终处于打开状态,那么你可以使用静态计数器将文件名“流”到磁盘。 - 我不记得我在哪里找到这个,但它已被修改,谢谢谁!
void dump_buffer()
{
IDirect3DSurface9* pRenderTarget=NULL;
IDirect3DSurface9* pDestTarget=NULL;
const char file[] = "Pickture.bmp";
// sanity checks.
if (Device == NULL)
return;
// get the render target surface.
HRESULT hr = Device->GetRenderTarget(0, &pRenderTarget);
// get the current adapter display mode.
//hr = pDirect3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT,&d3ddisplaymode);
// create a destination surface.
hr = Device->CreateOffscreenPlainSurface(DisplayMde.Width,
DisplayMde.Height,
DisplayMde.Format,
D3DPOOL_SYSTEMMEM,
&pDestTarget,
NULL);
//copy the render target to the destination surface.
hr = Device->GetRenderTargetData(pRenderTarget, pDestTarget);
//save its contents to a bitmap file.
hr = D3DXSaveSurfaceToFile(file,
D3DXIFF_BMP,
pDestTarget,
NULL,
NULL);
// clean up.
pRenderTarget->Release();
pDestTarget->Release();
}
编辑:我可以看到,这是在您的第一个编辑链接下列为“GDI方式”。 即使在该网站上的性能咨询,这仍然是一个体面的方式,你可以很容易地想到30fps。
从这个评论(我没有经验做这件事,我只是指一个人):
HDC hdc = GetDC(NULL); // get the desktop device context
HDC hDest = CreateCompatibleDC(hdc); // create a device context to use yourself
// get the height and width of the screen
int height = GetSystemMetrics(SM_CYVIRTUALSCREEN);
int width = GetSystemMetrics(SM_CXVIRTUALSCREEN);
// create a bitmap
HBITMAP hbDesktop = CreateCompatibleBitmap( hdc, width, height);
// use the previously created device context with the bitmap
SelectObject(hDest, hbDesktop);
// copy from the desktop device context to the bitmap device context
// call this once per 'frame'
BitBlt(hDest, 0,0, width, height, hdc, 0, 0, SRCCOPY);
// after the recording is done, release the desktop context you got..
ReleaseDC(NULL, hdc);
// ..and delete the context you created
DeleteDC(hDest);
我并不是说这是最快的,但如果您在兼容的设备上下文之间进行复制,则BitBlt
操作通常非常快。
作为参考,打开广播公司的软件实现这样的事情作为他们的“dc_capture”方法的一部分,但不是创建目标方面hDest
使用CreateCompatibleDC
他们使用IDXGISurface1
,这与DirectX 10+的作品。 如果没有对此的支持,它们将回退到CreateCompatibleDC
。
要将其更改为使用特定应用程序,您需要将第一行更改为GetDC(game)
,其中game
是游戏窗口的句柄,然后设置游戏窗口的正确height
和width
。
一旦你有像素在hDest / hbDesktop中,你仍然需要将它保存到一个文件,但如果你正在做屏幕捕捉,那么我会认为你会想要在内存中缓冲一定数量的像素并保存到视频文件在块中,所以我不会指向将静态图像保存到磁盘的代码。
我写了一个视频捕捉软件,类似于DirectX应用程序的FRAPS。 源代码可用,我的文章解释了一般技术。 看看http://blog.nektra.com/main/2013/07/23/instrumenting-direct3d-applications-to-capture-video-and-calculate-frames-per-second/
尊重与您的表现相关的问题,
除非你正在从非常缓慢的前缓冲区读取数据,否则DirectX应该比GDI更快。 我的方法与FRAPS类似(从backbuffer中读取)。 我拦截了Direct3D接口中的一组方法。
对于实时录像(对应用程序的影响最小),快速编解码器至关重要。 FRAPS使用它自己的无损视频编解码器。 Lagarith和HUFFYUV是为实时应用设计的通用无损视频编解码器。 如果你想输出视频文件,你应该看看它们。
录制屏幕录像的另一种方法是编写镜像驱动程序。 根据维基百科:当视频镜像处于活动状态时,每当系统在镜像区域内的某个位置处绘制到主视频设备时,实时在镜像视频设备上执行绘制操作的副本。 请参阅MSDN上的镜像驱动程序:http://msdn.microsoft.com/en-us/library/windows/hardware/ff568315(v=vs.85).aspx。
上一篇: Fastest method of screen capturing
下一篇: iOS Simulator, recording video and audio via the command line?