Full screen capture and rendering in DirectX [PERFORMANCE]

I need to somehow get the screen data and transfer it to the DX9 surface / texture in my application and make it at least 25 frames per second with a resolution of 1600 * 900 , 30 would be better.

I tried BitBliting, but even after that I am at a speed of 20 frames per second, and after loading the data into the texture and rendering, I am at 11fps, which is far behind what I need.

GetFrontBufferData is out of the question.

Here is something about using the Windows Media API , but I'm not familiar with it. The sample saves the data directly to a file, maybe it can be configured to provide you with individual frames, but I did not find enough documentation for self-checking.

My code is:

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 squares it works at 30 frames per second (for example, 490 * 450 at 20-25), so I tried the splitter screen, but it did not work fine.

If there is something missing in the code, write, do not run it. Thanks

+5
source share
2 answers

Starting with Windows 8, there is a new desktop duplication API that can be used to capture the screen in video memory, including changes to the mouse cursor and which parts of the screen are actually resized or moved. This is a much more efficient approach than any of the GDI or D3D9 approaches, and it is really well suited for things like coding your desktop to a video stream, since you never have to pull the texture out of the GPU's memory. The new API is available by listing the DXGI outputs and calling DuplicateOutput on the screen you want to capture. You can then enter a loop waiting for the screen to refresh, and it acquires each frame in turn.

To encode frames on video, I recommend taking a look at the Media Foundation . Take a specific look at Sink Writer for the easiest way to encode video frames. Basically, you just need to wrap the D3D textures that you get for each video clip in IMFSample objects. They can be transmitted directly to the receiver device. See the MFCreateDXGISurfaceBuffer and MFCreateVideoSampleFromSurface functions for more information . To achieve maximum performance, it is usually required to use an H.264 codec with good hardware encoding support (on most machines).

For full disclosure, I'm working on a team that owns the Microsoft Desktop Duplication API, and I personally write applications that capture the desktop (and videos, games, etc.) for a video file at 60 frames per second using this technique, as well as many other scenarios. It is also used to create screen streams, remote assistance, and more at Microsoft.

+9
source

If you don't like FrontBuffer, try BackBuffer:

 LPDIRECT3DSURFACE9 surface; surface = GetBackBufferImageSurface(&fmt); 

to save it to a file

 D3DXSaveSurfaceToFile(filename, D3DXIFF_JPG, surface, NULL, NULL); 
+1
source

All Articles