我正在使用Windows桌面复制API在Windows 10中记录我的屏幕。但是,我在性能方面遇到了一些问题。使用谷歌浏览器播放视频并尝试记录屏幕录制时间从15毫秒波动到45毫秒。我希望能够至少以30fps的速度录制,并且我知道桌面复制api能够做到这一点。无论如何,这是我用来实际捕获屏幕的代码:
processor->hr = processor->lDeskDupl->AcquireNextFrame(0, &processor->lFrameInfo, &processor->lDesktopResource);
if (processor->hr == DXGI_ERROR_WAIT_TIMEOUT) {
processor->lDeskDupl->ReleaseFrame();
return false;
}
if (FAILED(processor->hr)) {
processor->lDeskDupl->ReleaseFrame();
return false;
}
// QI for ID3D11Texture2D
processor->hr = processor->lDesktopResource->QueryInterface(IID_PPV_ARGS(&processor->lAcquiredDesktopImage));
if (FAILED(processor->hr)) {
processor->lDeskDupl->ReleaseFrame();
return false;
}
processor->lDesktopResource.Release();
if (processor->lAcquiredDesktopImage == nullptr) {
processor->lDeskDupl->ReleaseFrame();
return false;
}
processor->lImmediateContext->CopyResource(processor->lGDIImage, processor->lAcquiredDesktopImage);
processor->lAcquiredDesktopImage.Release();
processor->lDeskDupl->ReleaseFrame();
// Copy image into CPU access texture
processor->lImmediateContext->CopyResource(processor->lDestImage, processor->lGDIImage);
// Copy from CPU access texture to bitmap buffer
D3D11_MAPPED_SUBRESOURCE resource;
processor->subresource = D3D11CalcSubresource(0, 0, 0);
processor->lImmediateContext->Map(processor->lDestImage, processor->subresource, D3D11_MAP_READ_WRITE, 0, &resource);
BYTE* sptr = reinterpret_cast<BYTE*>(resource.pData);
BYTE* dptr = processor->pBuf;
UINT lRowPitch = min(processor->lBmpRowPitch, resource.RowPitch);
for (int i = 0; i < processor->lOutputDuplDesc.ModeDesc.Height; i++) {
memcpy_s(dptr, processor->lBmpRowPitch, sptr, lRowPitch);
sptr += resource.RowPitch;
dptr += processor->lBmpRowPitch;
}
重要的是要注意,这是一个特定的部分,需要花费15ms-45ms的时间来完成每个周期。底部的memcpy循环通常占该时间的2毫秒左右,因此我知道这并不占用这里的时间。另外AcquireNextFrame的超时设置为零,因此几乎立即返回。任何帮助将不胜感激!此处粘贴的代码改编自:https://gist.github.com/Xirexel/a69ade44df0f70afd4a01c1c9d9e02cd
答案 0 :(得分:0)
您没有以最佳方式使用API。 Read remarks在ReleaseFrame API文档中:
出于性能原因,我们建议您在调用IDXGIOutputDuplication :: AcquireNextFrame方法以获取下一个帧之前释放该帧。当客户端不拥有框架时,操作系统会将所有桌面更新复制到表面。如果操作系统为每个出现的帧更新相同的区域,则可能导致GPU周期浪费。
您没有执行此处写的内容,而是在复制后立即释放框架。