简体   繁体   English

Windows桌面复制API需要很长时间

[英]Windows Desktop Duplication API taking a long time

I am using the windows desktop duplication API to record my screen in windows 10. I am however having some issues with performance. 我正在使用Windows桌面复制API在Windows 10中记录我的屏幕。但是,我在性能方面遇到了一些问题。 When playing a video using google chrome and attempting to record the time it takes to record the screen fluctuates from 15ms to 45ms. 使用谷歌浏览器播放视频并尝试记录屏幕录制时间从15毫秒波动到45毫秒。 I wanted to be able to record at at least 30fps, and I know the desktop duplication api is capable of doing it. 我希望能够至少以30fps的速度录制,并且我知道桌面复制api能够做到这一点。 Anyways here is the code I used to actually capture the screen: 无论如何,这里是我用来实际捕获屏幕的代码:

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;
    }

It is important to note that this is the specific section that is taking 15ms-45ms to complete every cycle. 重要的是要注意,这是一个特定的部分,每个周期需要15ms-45ms的时间来完成。 The memcpy loop at the bottom accounts for about 2ms of that time usually so I know that that is not responsible for the time it is taking here. 底部的memcpy循环通常占该时间的2毫秒左右,因此我知道这并不占用这里的时间。 Also AcquireNextFrame's timeout is set to zero so it returns nearly immediately. 另外AcquireNextFrame的超时设置为零,因此几乎立即返回。 Any help would be greatly appreciated! 任何帮助将不胜感激! The code pasted here was adapted from this: https://gist.github.com/Xirexel/a69ade44df0f70afd4a01c1c9d9e02cd 粘贴在此处的代码改编自此: https : //gist.github.com/Xirexel/a69ade44df0f70afd4a01c1c9d9e02cd

You're not using the API in optimal way. 您没有以最佳方式使用API​​。 Read remarks in ReleaseFrame API documentation: 阅读 ReleaseFrame API文档中的备注

For performance reasons, we recommend that you release the frame just before you call the IDXGIOutputDuplication::AcquireNextFrame method to acquire the next frame. 出于性能原因,我们建议您在调用IDXGIOutputDuplication :: AcquireNextFrame方法以获取下一个帧之前释放该帧。 When the client does not own the frame, the operating system copies all desktop updates to the surface. 当客户端不拥有框架时,操作系统会将所有桌面更新复制到表面。 This can result in wasted GPU cycles if the operating system updates the same region for each frame that occurs. 如果操作系统为每个出现的帧更新相同的区域,则可能导致GPU周期浪费。

You are not doing what's written there, you release frames as soon as you copy. 您没有执行此处写的内容,而是在复制后立即释放框架。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM