全屏时使用DirectX11 DXGI捕获屏幕

时间:2018-04-01 12:58:31

标签: c++ opencv directx-11 dxgi

我正在尝试开发一个个人项目,根据计算机屏幕上发生的情况点亮LED。

我已经尝试了几种解决方案来捕获我的屏幕,而带有DXGI的DirectX11是我发现具有良好FPS速率的最快方式。

我唯一的问题如下:当全屏显示时(例如,观看Netflix trogh Win10应用程序或全屏播放任何游戏),似乎没有捕获任何内容。我有两个功能(一个用于设置,另一个用于捕获帧:

设置功能:

 bool DXGIScreenCapturer::Init() {
    int lresult(-1);

    D3D_FEATURE_LEVEL lFeatureLevel;

    HRESULT hr(E_FAIL);
    hr = D3D11CreateDevice(
        nullptr,
        D3D_DRIVER_TYPE_HARDWARE,
        nullptr,
        0,
        gFeatureLevels,
        gNumFeatureLevels,
        D3D11_SDK_VERSION,
        &_lDevice,
        &lFeatureLevel,
        &_lImmediateContext);

    if (FAILED(hr))
        return false;

    if (!_lDevice)
        return false;

    // Get DXGI device
    ComPtr<IDXGIDevice> lDxgiDevice;
    hr = _lDevice.As(&lDxgiDevice);

    if (FAILED(hr))
        return false;

    // Get DXGI adapter
    ComPtr<IDXGIAdapter> lDxgiAdapter;
    hr = lDxgiDevice->GetParent(__uuidof(IDXGIAdapter), &lDxgiAdapter);

    if (FAILED(hr))
        return false;

    lDxgiDevice.Reset();

    UINT Output = 0;

    // Get output
    ComPtr<IDXGIOutput> lDxgiOutput;
    hr = lDxgiAdapter->EnumOutputs(Output, &lDxgiOutput);

    if (FAILED(hr))
        return false;

    lDxgiAdapter.Reset();

    hr = lDxgiOutput->GetDesc(&_lOutputDesc);

    if (FAILED(hr))
        return false;

    // QI for Output 1
    ComPtr<IDXGIOutput1> lDxgiOutput1;
    hr = lDxgiOutput.As(&lDxgiOutput1);

    if (FAILED(hr))
        return false;

    lDxgiOutput.Reset();

    // Create desktop duplication
    hr = lDxgiOutput1->DuplicateOutput(_lDevice.Get(), &_lDeskDupl);

    if (FAILED(hr))
        return false;

    lDxgiOutput1.Reset();

    // Create GUI drawing texture
    _lDeskDupl->GetDesc(&_lOutputDuplDesc);
    // Create CPU access texture
    _desc.Width = _lOutputDuplDesc.ModeDesc.Width;
    _desc.Height = _lOutputDuplDesc.ModeDesc.Height;
    _desc.Format = _lOutputDuplDesc.ModeDesc.Format;
    std::cout << _desc.Width << "x" << _desc.Height << "\n\n\n";

    _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_FLAG::D3D11_CPU_ACCESS_READ;
    _desc.Usage = D3D11_USAGE::D3D11_USAGE_STAGING;

    while (!CaptureScreen(_result));
    _result = cv::Mat(_desc.Height, _desc.Width, CV_8UC4, _resource.pData);
    return true;
}

捕捉功能:

bool DXGIScreenCapturer::CaptureScreen(cv::Mat& output)
{
    HRESULT hr(E_FAIL);
    ComPtr<IDXGIResource> lDesktopResource = nullptr;
    DXGI_OUTDUPL_FRAME_INFO lFrameInfo;
    ID3D11Texture2D* currTexture = NULL;

    hr = _lDeskDupl->AcquireNextFrame(999, &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;
    }

    //int accum_frames = lFrameInfo.AccumulatedFrames;
    //if (accum_frames > 1) {// && current_frame != 1) {
    //                     // TOO MANY OF THESE is the problem
    //                     // especially after having to wait >17ms in AcquireNextFrame()
    //}

    // QI for ID3D11Texture2D
    hr = lDesktopResource.As(&_lAcquiredDesktopImage);

    // Copy image into a newly created CPU access texture
    hr = _lDevice->CreateTexture2D(&_desc, NULL, &currTexture);
    if (FAILED(hr))
    {
        hr = _lDeskDupl->ReleaseFrame();
        return false;
    }
    if (!currTexture)
    {
        hr = _lDeskDupl->ReleaseFrame();
        return false;
    }

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

    output = _result;
    return true;
}

0 个答案:

没有答案