I use Desktop Duplication API to take screenshots of the desktop. It works fine, except the first 5 minutes after I restart my computer. In these first 5 minutes lFrameInfo.LastPresentTime.HighPart is always 0, so the CaptureScreen() function exits without taking a screenshot. If I take out the if with the lFrameInfo.LastPresentTime.HighPart == 0 check, then the code works, but it takes a screenshot at every mouse movement, even if the screen does not changed.

According to the documentation for LastPresentTime: "a zero value indicates that the desktop image was not updated since an application last called the IDXGIOutputDuplication::AcquireNextFrame method to acquire the next frame of the desktop image." But this is not true for me, even if I watch a 60fps youtube video, LastPresentTime is 0 for the first 5 minutes after a computer restart.

My system: Win10 x64, 13900k, RTX 4700

Here is the code:

bool DXGIScreenCapture::CaptureScreen()
{
    HRESULT hr(E_FAIL);
    IDXGIResource* lDesktopResource = nullptr;
    DXGI_OUTDUPL_FRAME_INFO lFrameInfo;

    hr = _lDeskDupl->AcquireNextFrame(500, &lFrameInfo, &lDesktopResource);
    if (FAILED(hr))
        return false;

    if (lFrameInfo.LastPresentTime.HighPart == 0) // not interested in just mouse updates, which can happen much faster than 60fps if you really shake the mouse
    {
        hr = _lDeskDupl->ReleaseFrame();
        return false;
    }

    // QI for ID3D11Texture2D
    hr = lDesktopResource->QueryInterface(__uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&_lAcquiredDesktopImage));
    lDesktopResource->Release();
    lDesktopResource = nullptr;
    if (FAILED(hr))
    {
        hr = _lDeskDupl->ReleaseFrame();
        return false;
    }

    _lImmediateContext->CopyResource(currTexture, _lAcquiredDesktopImage);
    UINT subresource = D3D11CalcSubresource(0, 0, 0);
    _lImmediateContext->Map(currTexture, subresource, D3D11_MAP_READ, 0, &_resource);
    _lImmediateContext->Unmap(currTexture, 0);
    hr = _lDeskDupl->ReleaseFrame();

    return true;
}
1

There are 1 answers

0
YangXiaoPo-MSFT On

According to DXGI_OUTDUPL_FRAME_INFO structure,

The operating system calls the QueryPerformanceCounter function to obtain the value.

And according to Acquiring high-resolution time stamps,

QueryPerformanceCounter reads the performance counter and returns the total number of ticks that have occurred since the Windows operating system was started, including the time when the machine was in a sleep state such as standby, hibernate, or connected standby.

So, it's correct that the HighPart of the ticks is 0 since the Windows operating system was started. To use the LARGE_INTEGER union,

If your compiler has built-in support for 64-bit integers, use the QuadPart member to store the 64-bit integer. Otherwise, use the LowPart and HighPart members to store the 64-bit integer.