DXGI API:AcquireNextFrame() 从不抓取更新的图像,始终为空白

Posted

技术标签:

【中文标题】DXGI API:AcquireNextFrame() 从不抓取更新的图像,始终为空白【英文标题】:DXGI API: AcquireNextFrame() never grabs an updated image, always blank 【发布时间】:2019-01-11 21:30:15 【问题描述】:

我一直在使用其他人的实现 DXGI 桌面复制 API 的代码,但遇到了一个奇怪的问题。这是我正在使用的代码的 github 链接。

https://github.com/diederickh/screen_capture/blob/master/src/test/test_win_api_directx_research.cpp

所有代码都可以正常工作,直到我尝试查看 D3D11_MAPPED_SUBRESOURCE map.pData 中的内容,我得到的只是一个空白屏幕,特别是它是一组重复的 0xFF000000,全 alpha 为黑色。在寻找其他解决方案时,我发现有人使用 while 循环来检查框架何时成功更新,从而解决了这个问题。

while (true)

    hr = duplication->AcquireNextFrame(INFINITE, &frame_info, &desktop_resource);
    if (hr && frame_info.LastPresentTime.QuadPart)
    
        break;
    

但是,当我运行此代码时,控制台永远不会退出并继续永远运行。显然,根据 frame_info.LastPresentTime.QuadPart,框架永远不会更新。这可能是什么原因造成的?是否存在可能导致这种情况的已知情况?

【问题讨论】:

【参考方案1】:

IDXGIOutputDuplication::AcquireNextFrame 有充分的理由在没有框架的情况下返回。因此,确实您可能需要进行几次尝试并检查LastPresentTime 是否为非零。

代码sn-p有两个问题:

    hr 零校验不太准确 ReleaseFrame 没有匹配成功的AcquireNextFrame 调用

原来如此:

while (true)

    hr = duplication->AcquireNextFrame(INFINITE, &frame_info, &desktop_resource);
    if (FAILED(hr))
    
        // TODO: Handle error
    
    if (frame_info.LastPresentTime.QuadPart)
    
        break;
    
    duplication->ReleaseFrame(); // TODO: check returned value here as well

【讨论】:

我按照你的描述实现了循环,但我仍然得到一个空白帧。如果这很重要,我正在通过在 d3d_context->Map() 调用之后将像素数据保存在 24 位位图中进行检查。奇怪的是,每次我运行程序时,我都会从 duplication->ReleaseFrame() 结果中得到一个 printf 警报。 (时间阈值机会?)如果您想查看,我可以粘贴我正在使用的代码。 当然,您可能在代码中遇到其他问题。这只是给你一个有效的纹理。您可能想要复制到 staging 然后映射(原始 link here 的代码所做的),所以那里可能还有其他问题。 事实证明,当我使用适合屏幕的桌面背景时,我确实获得了像素数据。可能与屏幕上的更新区域有关? 您将获得一个纹理将完整复制桌面(在多显示器系统上属于特定显示器的部分)。

以上是关于DXGI API:AcquireNextFrame() 从不抓取更新的图像,始终为空白的主要内容,如果未能解决你的问题,请参考以下文章

AcquireNextFrame 不工作(桌面复制 API 和 D3D11)

DXGI EnumOutputs - 没有 DXGI_OUTPUT_DESC 和空显示模式数组

DXGI 1.5 DuplicateOutput1 因 DXGI_ERROR_UNSUPPORTED (0x887a0004) 而失败

DXGI:尝试从输出(监视器)中获取正确的显示模式

DXGI 1.4的新特性

Direct3D 和 DXGI 之间的区别