AcquireNextFrame不起作用(桌面复制API和D3D11) [英] AcquireNextFrame not working (Desktop Duplication API & D3D11)
问题描述
我将这段代码组合在一起,该代码获取了桌面的屏幕快照,并将其映射为原始像素数据访问,但是输出全为零.我不知道我做错了什么.在在线查看了许多桌面复制Api示例之后,我发现它们与我的之间没有任何区别.
I've put together this code that takes a screenshot of the desktop and maps it for raw pixel data access, but the output is all zeros. I have no idea what i've done wrong. After looking at many examples of the Desktop Duplication Api online I don't see any differences between them and mine.
这是我初始化所有内容的方法,并且不会引发任何错误.
This is my method to initialize everything, and no errors are raised.
BOOL init()
{
CHECKHR(D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, 0, gFeatureLevels, gNumFeatureLevels, D3D11_SDK_VERSION, &lDevice, &FeatureLevel, &lImmediateContext))
IDXGIDevice* lDxgiDevice;
CHECKHR(lDevice->QueryInterface(IID_PPV_ARGS(&lDxgiDevice)))
IDXGIAdapter* lDxgiAdapter;
CHECKHR(lDxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void**)&lDxgiAdapter))
lDxgiDevice->Release();
IDXGIOutput* lDxgiOutput;
CHECKHR(lDxgiAdapter->EnumOutputs(0, &lDxgiOutput))
lDxgiAdapter->Release();
CHECKHR(lDxgiOutput->GetDesc(&OutputDesc))
IDXGIOutput1* lDxgiOutput1;
CHECKHR(lDxgiOutput->QueryInterface(IID_PPV_ARGS(&lDxgiOutput1)))
lDxgiOutput->Release();
CHECKHR(lDxgiOutput1->DuplicateOutput(lDevice, &lDeskDupl))
lDxgiOutput1->Release();
lDeskDupl->GetDesc(&OutputDuplDesc);
D3D11_TEXTURE2D_DESC desc;
desc.Width = OutputDuplDesc.ModeDesc.Width;
desc.Height = OutputDuplDesc.ModeDesc.Height;
desc.Format = OutputDuplDesc.ModeDesc.Format;
desc.ArraySize = 1;
desc.BindFlags = 0;
desc.MiscFlags = 0;
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.MipLevels = 1;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
desc.Usage = D3D11_USAGE_STAGING;
CHECKHR(lDevice->CreateTexture2D(&desc, NULL, &lDestImage))
return TRUE;
}
我正在使用的CHECKHR宏已经过我的测试并且可以正常工作,只是为了说明这不是问题.
the CHECKHR macro i'm using was tested by me and works, just to clarify that it is not the problem.
这是我用来实际抓取框架的代码:
This is the code that I use to actually grab the frame:
int main()
{
init();
HRESULT hr;
IDXGIResource* lDesktopResource;
ID3D11Texture2D* lAcquiredDesktopImage;
DXGI_OUTDUPL_FRAME_INFO FrameInfo;
while (true)
{
if (SUCCEEDED(lDeskDupl->AcquireNextFrame(INFINITE, &FrameInfo, &lDesktopResource)))
{
break;
}
}
hr = lDesktopResource->QueryInterface(IID_PPV_ARGS(&lAcquiredDesktopImage));
if (FAILED(hr))
{
cout << "QueryInterface failed!" << endl;
system("pause");
}
lDesktopResource->Release();
lImmediateContext->CopyResource(lDestImage, lAcquiredDesktopImage);
lAcquiredDesktopImage->Release();
lDeskDupl->ReleaseFrame();
D3D11_MAPPED_SUBRESOURCE resource;
UINT subresource = D3D11CalcSubresource(0, 0, 0);
hr = lImmediateContext->Map(lDestImage, subresource, D3D11_MAP_READ_WRITE, 0, &resource);
if (FAILED(hr))
{
cout << "Map failed!" << endl;
system("pause");
}
BYTE* pb = (BYTE*)(resource.pData);
for (int i = 0; i < 2000000; i++)
{
cout << (int)pb[i] << endl;
}
system("pause");
return 0;
}
所有发生的事情是将2000000个零打印到控制台.我有什么我想念的东西吗?
All that happens is 2000000 zeros get printed to the console. Is there something i'm missing or that I cant see?
推荐答案
首先,针对特定适配器调用D3D11CreateDevice
,该适配器您将要复制的输出:
First, call D3D11CreateDevice
against specific adapter which output you are about to duplicate:
BOOL init()
{
IDXGIFactory* lDxgiFactory;
CHECKHR(CreateDXGIFactory1(__uuidof(IDXGIFactory), (void**)&lDxgiFactory))
IDXGIAdapter* lDxgiAdapter;
CHECKHR(lDxgiFactory->EnumAdapters(0, &lDxgiAdapter))
lDxgiFactory->Release();
CHECKHR(D3D11CreateDevice(lDxgiAdapter, D3D_DRIVER_TYPE_UNKNOWN, nullptr, 0, gFeatureLevels, gNumFeatureLevels, D3D11_SDK_VERSION, &lDevice, &FeatureLevel, &lImmediateContext))
IDXGIDevice* lDxgiDevice;
CHECKHR(lDevice->QueryInterface(IID_PPV_ARGS(&lDxgiDevice)))
//IDXGIAdapter* lDxgiAdapter;
//CHECKHR(lDxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void**)&lDxgiAdapter))
lDxgiDevice->Release();
IDXGIOutput* lDxgiOutput;
CHECKHR(lDxgiAdapter->EnumOutputs(0, &lDxgiOutput))
lDxgiAdapter->Release();
CHECKHR(lDxgiOutput->GetDesc(&OutputDesc))
IDXGIOutput1* lDxgiOutput1;
CHECKHR(lDxgiOutput->QueryInterface(IID_PPV_ARGS(&lDxgiOutput1)))
lDxgiOutput->Release();
CHECKHR(lDxgiOutput1->DuplicateOutput(lDevice, &lDeskDupl))
// ...
然后,您的代码在AcquireNextFrame
附近不太准确.您需要等待实际的帧,然后在跳过时在循环中执行ReleaseFrame
.
Then, your code is not quite accurate around AcquireNextFrame
. You need to wait for actual frame and do ReleaseFrame
in the loop while you are skipping.
// ...
while (true)
{
if (SUCCEEDED(lDeskDupl->AcquireNextFrame(INFINITE, &FrameInfo, &lDesktopResource)) && FrameInfo.LastPresentTime.QuadPart)
{
break;
}
lDeskDupl->ReleaseFrame();
}
// ...
这篇关于AcquireNextFrame不起作用(桌面复制API和D3D11)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!