DXGI捕获桌面

2022-01-13  本文已影响0人  上官宏竹

DXGI与D3D关系

DXGI 为未来的图形组件提供了一个通用框架。
DXGI 的目的是与内核模式驱动程序和系统硬件进行通信,如下图所示。


image.png

DXGI捕获桌面图像流程

  1. 创建d3d设备,并通过d3d设备查询到DXGI设备
  2. 通过DXGI设备获取DXGI适配器IDXGIAdapter
  3. 通过DXGI适配器IDXGIAdapter,获取DXGI IDXGIOutputIDXGIOutput1
  4. 然后获取DXGI IDXGIOutputDuplication
  5. 通过IDXGIOutputDuplication的接口AcquireNextFrame获取桌面图像帧资源IDXGIResource
  6. 查询到桌面图像帧资源的纹理数据(数据类型是RGB数据)
  7. 释放帧ReleaseFrame

获取DXGI适配器IDXGIAdapter

// 为抓取桌面图像创建DXGI设备
// 2.创建DXGI设备
hr = m_device->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&m_dxgiDevice));
if (FAILED(hr)) {
    return false;
}

// 3.获取DXGI适配器
hr = m_dxgiDevice->GetParent(__uuidof(IDXGIAdapter), reinterpret_cast<void**>(&m_dxgiAdapter));
if (FAILED(hr)) {
    return false;
}

枚举显示器

// 3.1 枚举所有显示器
for (int i = 0; i < 6; i++) {
    IDXGIOutput* dxgiOutput;
    HRESULT hr = m_dxgiAdapter->EnumOutputs(i, &dxgiOutput);
    if (FAILED(hr)) {           
        break;
    }
    DXGI_OUTPUT_DESC desc;
    dxgiOutput->GetDesc(&desc);
}

获取DXGI IDXGIOutputDuplication

// 4.获取DXGI output
IDXGIOutput* dxgiOutput;
HRESULT hr = dxgiAdapter->EnumOutputs(monitorIdx, &dxgiOutput);
if (FAILED(hr)) {
    Log(LOG_ERROR, "failed for get EnumOutputs");
    return false;
}     

// 5.获取DXGI output1  
IDXGIOutput1* dxgiOutput1;
hr = dxgiOutput->QueryInterface(__uuidof(IDXGIOutput1), reinterpret_cast<void**>(&dxgiOutput1));
if (FAILED(hr)) {
    Log(LOG_ERROR, "failed for get IDXGIOutput1");
    return false;
}

// 6.获取DXGI OutputDuplication    
IDXGIOutputDuplication* outputDup;
hr = dxgiOutput1->DuplicateOutput(device, &outputDup);
if (FAILED(hr)) {
    Log(LOG_ERROR, "failed for DuplicateOutput");
    if (hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE) {
        Log(LOG_ERROR, "DXGI_ERROR_NOT_CURRENTLY_AVAILABLE");
    }
    return false;
}

获取图像帧

// 7. 获取桌面图像
DXGI_OUTDUPL_FRAME_INFO frameInfo;
IDXGIResource* idxgiRes;
HRESULT hr = m_outputDupV[idx]->AcquireNextFrame(1000, &frameInfo, &idxgiRes);

ID3D11Texture2D* desktopTexture2d;
hr = idxgiRes->QueryInterface(__uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&desktopTexture2d));

D3D11_TEXTURE2D_DESC desktopDesc;
desktopTexture2d->GetDesc(&desktopDesc);

捕获光标

使用Windows API GetCursorInfo将捕获到光标数据。

DXGI捕获桌面及光标处理
NVENC编码

NVENC编码

NVENC 视频编码器 API 编程指南

上一篇下一篇

猜你喜欢

热点阅读