简体   繁体   English

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

[英]Whole screen capture and render in DirectX [PERFORMANCE]

I need some way to get screen data and pass them to DX9 surface/texture in my aplication and render it at at least 25fps at 1600*900 resolution, 30 would be better. 我需要一些方法来获取屏幕数据并将其传递到我的应用程序中的DX9表面/纹理,并以1600 * 900分辨率以至少25fps渲染它,30会更好。

I tried BitBliting but even after that I am at 20fps and after loading data into texture and rendering it I am at 11fps which is far behind what I need. 我尝试了BitBliting,但即使在那之后,我的速度为20fps,在将数据加载到纹理并渲染后,我的速度为11fps,远远落后于我的需要。

GetFrontBufferData is out of question. GetFrontBufferData是不可能的。

Here is something about using Windows Media API , but I am not familiar with it. 以下使用Windows Media API的内容 ,但我不熟悉它。 Sample is saving data right into file, maybe it can be set up to give you individual frames, but I haven't found good enough documentation to try it on my own. 示例将数据保存到文件中,也许它可以设置为给你单独的帧,但我没有找到足够好的文档来自己尝试。

My code: 我的代码:

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

I found out that for 512*512 square its running on 30fps (for ie 490*450 at 20-25) so I tried dividing screen, but it didn't seem to work well. 我发现,对于512 * 512平方,它以30fps运行(即490 * 450,20-25),所以我尝试划分屏幕,但似乎效果不佳。

If there is something missing in code please write, don't vote down. 如果代码中缺少某些内容请写,不要拒绝投票。 Thanks 谢谢

Starting with Windows 8, there is a new desktop duplication API that can be used to capture the screen in video memory, including mouse cursor changes and which parts of the screen actually changed or moved. 从Windows 8开始,有一个新的桌面复制API ,可用于捕获视频内存中的屏幕,包括鼠标光标更改以及屏幕的哪些部分实际更改或移动。 This is far more performant than any of the GDI or D3D9 approaches out there and is really well-suited to doing things like encoding the desktop to a video stream, since you never have to pull the texture out of GPU memory. 这比任何GDI或D3D9方法都更加高效,并且非常适合将桌面编码为视频流,因为您永远不必将纹理从GPU内存中拉出来。 The new API is available by enumerating DXGI outputs and calling DuplicateOutput on the screen you want to capture. 通过枚举DXGI输出并在要捕获的屏幕上调用DuplicateOutput ,可以使用新的API。 Then you can enter a loop that waits for the screen to update and acquires each frame in turn. 然后,您可以进入等待屏幕更新的循环,并依次获取每个帧。

To encode the frames to a video, I'd recommend taking a look at Media Foundation . 要将帧编码为视频,我建议您查看Media Foundation Take a look specifically at the Sink Writer for the simplest method of encoding the video frames. 请特别注意Sink Writer ,了解最简单的视频帧编码方法。 Basically, you just have to wrap the D3D textures you get for each video frame into IMFSample objects. 基本上,您只需将每个视频帧的D3D纹理包装到IMFSample对象中。 These can be passed directly into the sink writer. 这些可以直接传递到接收器编写器。 See the MFCreateDXGISurfaceBuffer and MFCreateVideoSampleFromSurface functions for more information. 有关更多信息,请参阅MFCreateDXGISurfaceBufferMFCreateVideoSampleFromSurface函数。 For the best performance, typically you'll want to use a codec like H.264 that has good hardware encoding support (on most machines). 为了获得最佳性能,通常您需要使用具有良好硬件编码支持的H.264编解码器(在大多数计算机上)。

For full disclosure, I work on the team that owns the desktop duplication API at Microsoft, and I've personally written apps that capture the desktop (and video, games, etc.) to a video file at 60fps using this technique, as well as a lot of other scenarios. 为了完全披露,我在微软拥有桌面复制API的团队工作,我个人使用这种技术编写了以60fps的速度将桌面(以及视频,游戏等)捕获到视频文件的应用程序。像许多其他场景一样。 This is also used to do screen streaming, remote assistance, and lots more within Microsoft. 这也用于在微软内部进行屏幕流式传输,远程协助等。

If you don't like the FrontBuffer, try the BackBuffer: 如果您不喜欢FrontBuffer,请尝试BackBuffer:

LPDIRECT3DSURFACE9  surface;
surface = GetBackBufferImageSurface(&fmt);

to save it to a file use 将其保存到文件使用

D3DXSaveSurfaceToFile(filename, D3DXIFF_JPG, surface, NULL, NULL);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM