猿问

Windows上最快的屏幕捕获方法

Windows上最快的屏幕捕获方法

我想为Windows平台编写一个截屏程序,但我不确定如何捕获屏幕。我所知道的唯一方法就是使用GDI,但我很好奇是否还有其他方法可以解决这个问题,如果有的话,会产生最少的开销?速度是一个优先事项。

屏幕录像程序将用于录制游戏镜头,但是,如果这确实缩小了选项范围,我仍然可以接受任何其他超出此范围的建议。毕竟知识还不错。

编辑:我遇到过这篇文章:捕获屏幕的各种方法。它向我介绍了Windows Media API的实现方式以及DirectX的实现方式。它在结论中提到,禁用硬件加速可以极大地提高捕获应用程序的性能。我很好奇为什么会这样。任何人都可以为我填补遗失的空白吗?

编辑:我读过像Camtasia这样的截屏程序使用他们自己的捕获驱动程序。有人能给我一个深入的解释它是如何工作的,以及为什么它更快?我可能还需要有关实现此类内容的指导,但我确信无论如何都有现有的文档。

此外,我现在知道FRAPS如何记录屏幕。它挂钩底层图形API以从后台缓冲区读取。根据我的理解,这比从前端缓冲区读取更快,因为您是从系统RAM而不是视频RAM读取的。你可以在这里阅读这篇文章。


绝地无双
浏览 1728回答 3
3回答

潇潇雨雨

这是我用来收集单帧的内容,但是如果你修改它并保持两个目标一直打开,那么你可以使用文件名的静态计数器将它“流”到磁盘。 - 我不记得我在哪里发现了这个,但它已被修改,多亏了谁!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 contextHDC hDest = CreateCompatibleDC(hdc); // create a device context to use yourself// get the height and width of the screenint height = GetSystemMetrics(SM_CYVIRTUALSCREEN);int width = GetSystemMetrics(SM_CXVIRTUALSCREEN);// create a bitmapHBITMAP hbDesktop = CreateCompatibleBitmap( hdc, width, height);// use the previously created device context with the bitmapSelectObject(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);// ..delete the bitmap you were using to capture frames..DeleteObject(hbDesktop);// ..and delete the context you createdDeleteDC(hDest);我不是说这是最快的,但BitBlt如果你在兼容的设备上下文之间进行复制,操作通常会非常快。作为参考,Open Broadcaster Software实现了类似这样的东西作为“dc_capture” 方法的一部分,尽管不是hDest使用CreateCompatibleDC它们创建目标上下文,而是使用IDXGISurface1与DirectX 10+ 一起使用的目标上下文。如果没有对此的支持,他们就会回归CreateCompatibleDC。要改变它使用一个特定的应用程序,您需要更改的第一行到GetDC(game)这里game是游戏的窗口的句柄,然后设置权height和width游戏的窗口太多。一旦你有hDest / hbDesktop中的像素,你仍然需要将它保存到一个文件,但如果你正在进行屏幕捕获,那么我认为你会想要在内存中缓冲一定数量的像素并保存到视频文件中在块中,所以我不会指向将静态图像保存到磁盘的代码。
随时随地看视频慕课网APP
我要回答