DirectX中的整个屏幕捕获和渲染[性能]

Leo*_*sCZ 5 c++ directx winapi ms-media-foundation

我需要一些方法来获取屏幕数据并将其传递到我的应用程序中的DX9表面/纹理,并以1600*900分辨率以至少25fps渲染它,30会更好.

我尝试了BitBliting,但即使在那之后,我的速度为20fps,在将数据加载到纹理并渲染后,我的速度为11fps,远远落后于我的需要.

GetFrontBufferData是不可能的.

以下使用Windows Media API的内容,但我不熟悉它.示例将数据保存到文件中,也许它可以设置为给你单独的帧,但我没有找到足够好的文档来自己尝试.

我的代码:

m_memDC.BitBlt(0, 0, m_Rect.Width(),m_Rect.Height(), //m_Rect is area to be captured
               &m_dc, m_Rect.left, m_Rect.top, SRCCOPY); 
      //at 20-25fps after this if I comment out the rest

//DC,HBITMAP setup and memory alloc is done once at the begining
GetDIBits( m_hDc, (HBITMAP)m_hBmp.GetSafeHandle(),
    0L,             // Start scan line
    (DWORD)m_Rect.Height(),     // # of scan lines
    m_lpData,                   // LPBYTE
    (LPBITMAPINFO)m_bi,     // address of bitmapinfo
    (DWORD)DIB_RGB_COLORS);     // Use RGB for color table
     //at 17-20fps

IDirect3DSurface9 *tmp;
m_pImageBuffer[0]->GetSurfaceLevel(0,&tmp); //m_pImageBuffer is Texture of same 
                                            //size as bitmap to prevent stretching
hr= D3DXLoadSurfaceFromMemory(tmp,NULL,NULL,
                             (LPVOID)m_lpData,
                             D3DFMT_X8R8G8B8,
                             m_Rect.Width()*4,
                             NULL,
                             &r,                 //SetRect(&r,0,0,m_Rect.Width(),m_Rect.Height();
                             D3DX_DEFAULT,0);
 //12-14fps
IDirect3DSurface9 *frameS;
hr=m_pFrameTexture->GetSurfaceLevel(0,&frameS); // Texture of that is rendered
pd3dDevice->StretchRect(tmp,NULL,frameS,NULL,D3DTEXF_NONE);
//11fps
Run Code Online (Sandbox Code Playgroud)

我发现,对于512*512平方,它以30fps运行(即490*450,20-25),所以我尝试划分屏幕,但似乎效果不佳.

如果代码中缺少某些内容请写,不要拒绝投票.谢谢

zhu*_*SFT 10

从Windows 8开始,有一个新的桌面复制API,可用于捕获视频内存中的屏幕,包括鼠标光标更改以及屏幕的哪些部分实际更改或移动.这比任何GDI或D3D9方法都更加高效,并且非常适合将桌面编码为视频流,因为您永远不必将纹理从GPU内存中拉出来.通过枚举DXGI输出并在要捕获的屏幕上调用DuplicateOutput,可以使用新的API .然后,您可以进入等待屏幕更新的循环,并依次获取每个帧.

要将帧编码为视频,我建议您查看Media Foundation.请特别注意Sink Writer,了解最简单的视频帧编码方法.基本上,您只需将每个视频帧的D3D纹理包装到IMFSample对象中.这些可以直接传递到接收器编写器.有关更多信息,请参阅MFCreateDXGISurfaceBufferMFCreateVideoSampleFromSurface函数.为了获得最佳性能,通常您需要使用具有良好硬件编码支持的H.264编解码器(在大多数计算机上).

为了完全披露,我在微软拥有桌面复制API的团队工作,我个人使用这种技术编写了以60fps的速度将桌面(以及视频,游戏等)捕获到视频文件的应用程序.像许多其他场景一样.这也用于在微软内部进行屏幕流式传输,远程协助等.

  • 你能举例说明如何从dxgi表面连接到文件编写器接收器(或任何实用的),它在GPU上进行H.264压缩,只使用CPU写入流吗?互联网上似乎没有有效的样本.毫无疑问,这是一个快速的api,但如果没有一个简单的样本,需要几个月的时间来解决这 (6认同)

5an*_*dr0 1

如果您不喜欢 FrontBuffer,请尝试 BackBuffer:

LPDIRECT3DSURFACE9  surface;
surface = GetBackBufferImageSurface(&fmt);
Run Code Online (Sandbox Code Playgroud)

将其保存到文件中使用

D3DXSaveSurfaceToFile(filename, D3DXIFF_JPG, surface, NULL, NULL);
Run Code Online (Sandbox Code Playgroud)