整个屏幕捕获和渲染在DirectX [性能] [英] Whole screen capture and render in DirectX [PERFORMANCE]

查看:916
本文介绍了整个屏幕捕获和渲染在DirectX [性能]的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要一些方法来获取屏幕数据,并将它们传递给DX9表面/纹理,并以至少 25fps 1600 * 900 的分辨率渲染,会更好。

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.

我试过BitBliting,但即使之后,我是在20fps,加载数据到纹理和渲染,我在11fps,这远远落后于我需要。

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.

GetFrontBufferData没有问题。

GetFrontBufferData is out of question.

这里 关于使用Windows Media API 的问题,但我不熟悉。示例正在将数据保存到文件中,也许可以设置为给您单独的框架,但是我没有找到足够好的文档来自己尝试。

Here is something about using Windows Media API, but I am not familiar with it. 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.

我的代码:

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

我发现对于512 * 512平方它运行在30fps(即490 * 450在20-25)所以我尝试分屏,但它似乎不能很好地工作。

I found out that for 512*512 square its running on 30fps (for i.e. 490*450 at 20-25) so I tried dividing screen, but it didn't seem to work well.

如果代码中缺少某些内容,请写信,不要投票。感谢

If there is something missing in code please write, don't vote down. Thanks

推荐答案

从Windows 8开始,有一个新的桌面复制API ,可用于捕获视频内存中的屏幕,包括鼠标光标更改和哪些部分屏幕实际改变或移动。这比任何GDI或D3D9方法的性能要好得多,并且真的非常适合做一些操作,例如将桌面编码为视频流,因为你不必将纹理拉出GPU内存。新API可通过枚举DXGI输出并调用 DuplicateOutput 在您要捕获的屏幕上。然后,您可以输入一个循环,等待屏幕更新并依次获取每个帧。

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. 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. The new API is available by enumerating DXGI outputs and calling DuplicateOutput on the screen you want to capture. Then you can enter a loop that waits for the screen to update and acquires each frame in turn.

要将帧编码为视频,我建议您查看在媒体基金会。请专门查看水槽作家对于编码视频帧的最简单的方法。基本上,你只需要将你为每个视频帧获得的D3D纹理包装到IMFSample对象中。这些可以直接传递到sink写入器中。请参见 MFCreateDXGISurfaceBuffer MFCreateVideoSampleFromSurface 函数以获取更多信息。为了获得最佳性能,通常您需要使用具有良好硬件编码支持(在大多数机器上)的H.264编解码器。

To encode the frames to a video, I'd recommend taking a look at Media Foundation. Take a look specifically at the Sink Writer for the simplest method of encoding the video frames. Basically, you just have to wrap the D3D textures you get for each video frame into IMFSample objects. These can be passed directly into the sink writer. See the MFCreateDXGISurfaceBuffer and MFCreateVideoSampleFromSurface functions for more information. For the best performance, typically you'll want to use a codec like H.264 that has good hardware encoding support (on most machines).

为了完全公开,我工作在拥有微软的桌面复制API的团队,我亲自编写的应用程序捕获桌面(和视频,游戏等)到60fps的视频文件使用这种技术,以及许多其他场景。这也用于做屏幕流,远程协助,以及更多的微软。

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. This is also used to do screen streaming, remote assistance, and lots more within Microsoft.

这篇关于整个屏幕捕获和渲染在DirectX [性能]的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆