由于D3DPOOL_SCRATCH的处理速度很慢,我编写了桌面捕获程序以引用Internet上的报告。然而,结果是漆黑图片。这是控制台程序的结果还是有其他原因?
#include <stdio.h>
#include <Windows.h>
#include <d3d9.h>
void main()
{
CoInitialize(NULL);
LPDIRECT3D9 d3d9;
LPDIRECT3DDEVICE9 d3ddev;
d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
int ww = GetSystemMetrics(SM_CXSCREEN);
int wh = GetSystemMetrics(SM_CYSCREEN);
HWND hwnd = GetDesktopWindow();
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
d3dpp.BackBufferCount = 1;
d3dpp.BackBufferWidth = ww;
d3dpp.BackBufferHeight = wh;
d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
d3dpp.MultiSampleQuality = 0;
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
d3dpp.hDeviceWindow = hwnd;
d3dpp.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
d3d9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &d3ddev);
IDirect3DSurface9* render;
IDirect3DSurface9* dest;
d3ddev->CreateOffscreenPlainSurface(ww, wh, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &dest, NULL);
d3ddev->GetRenderTarget(0, &render);
d3ddev->GetRenderTargetData(render, dest);
D3DLOCKED_RECT bits;
dest->LockRect(&bits, NULL, D3DLOCK_READONLY);
// If a capture is successful, colors other than black(0x00000000) should enter.
for(int i = 0; i < 100; i++){
printf("%02X ", *((BYTE*)bits.pBits + i));
}
dest->UnlockRect();
render->Release();
dest->Release();
d3ddev->Release();
d3d9->Release();
CoUninitialize();
}
答案 0 :(得分:5)
这与应用程序类型无关,如果要获取桌面图像的数据,则应使用以下函数
所以不要打电话
d3ddev->GetRenderTarget(0, &render);
d3ddev->GetRenderTargetData(render, dest);
你应该致电
d3ddev->GetFrontBufferData(0, dest);
答案 1 :(得分:4)
如果您在Windows 8之前的Windows版本上运行,则GetFrontBufferData API可正常工作,如另一个答案所示。但是,从Windows 8开始,有一个新的desktop duplication API可用于捕获视频内存中的桌面,包括鼠标光标更改以及屏幕的哪些部分实际更改或移动。这比D3D9方法更具性能,并且非常适合将桌面编码为视频流,因为您永远不必将纹理从GPU内存中拉出来。通过枚举DXGI输出并在要捕获的屏幕上调用DuplicateOutput,可以使用新的API。然后,您可以进入一个循环,等待屏幕更新并依次获取每个帧。
如果你想将帧编码为视频,我建议你看看Media Foundation而不是DirectShow,因为Media Foundation有更好的性能,可以使用D3D11而不是D3D9进行编码。它也更容易使用,具体取决于您的场景。请查看Media Foundation的Sink Writer,了解最简单的视频帧编码方法。
为了完全披露,我在微软拥有桌面复制API的团队工作,我个人使用这种技术编写了以60fps的速度将桌面(以及视频,游戏等)捕获到视频文件的应用程序,以及许多其他场景。