DuplicatorInfo CDuplicateOutputDx11::GetNewFrame(ID3D11Texture2D** p2dTexture) { DXGI_OUTDUPL_FRAME_INFO frameInfo; IDXGIResource* pDesktopResource = nullptr; HRESULT hr = S_OK; hr = m_pOutputDuplication->AcquireNextFrame(15, &frameInfo, &pDesktopResource); if (hr == DXGI_ERROR_ACCESS_LOST) { return DuplicatorInfo_Lost; } else if (hr == DXGI_ERROR_WAIT_TIMEOUT) { return DuplicatorInfo_Timeout; } else if (hr == DXGI_ERROR_INVALID_CALL) { return DuplicatorInfo_InvalidCall; } else if (FAILED(hr)) { return DuplicatorInfo_Error; } if (FAILED(hr = pDesktopResource->QueryInterface(__uuidof(ID3D11Texture2D), reinterpret_cast<void**>(p2dTexture)))) { SAFE_RELEASE(pDesktopResource); DOLOG(" pDesktopResource->QueryInterface failed"); return DuplicatorInfo_Error; } SAFE_RELEASE(pDesktopResource); return DuplicatorInfo_Acquired; }
ID3D11Texture2D* DesktopDuplication::acquireNextFrame(DXGI_OUTDUPL_FRAME_INFO& frameInfoOut) { IDXGIResource* frameResource; hr = outputDuplication->AcquireNextFrame(acquireTimeout, &frameInfoOut, &frameResource); if (hr != S_OK) { reinitialize(); // Second chance to recover adapter failure. std::cout << "Next frame acquisition failed: " << hr << ". Reinitializing DXGI subsystems..." << std::endl; CHECKED(hr, outputDuplication->AcquireNextFrame(acquireTimeout, &frameInfoOut, &frameResource)); } ID3D11Texture2D* frameTex; CHECKED(hr, frameResource->QueryInterface(__uuidof(ID3D11Texture2D), reinterpret_cast<void **>(&frameTex))); frameResource->Release(); ID3D11Texture2D* frameStagingTex = copyToStaging(frameTex); frameTex->Release(); CHECKED(hr, outputDuplication->ReleaseFrame()); return frameStagingTex; }
DUPL_RETURN DUPLICATIONMANAGER::GetFrame(_Out_ FRAME_DATA* Data, _Out_ bool* Timeout) { IDXGIResource* DesktopResource = nullptr; DXGI_OUTDUPL_FRAME_INFO FrameInfo; // Get new frame HRESULT hr = m_DeskDupl->AcquireNextFrame(500, &FrameInfo, &DesktopResource); if (hr == DXGI_ERROR_WAIT_TIMEOUT) { *Timeout = true; return DUPL_RETURN_SUCCESS; } *Timeout = false; if (FAILED(hr)) { return ProcessFailure(m_Device, L"Failed to acquire next frame in DUPLICATIONMANAGER", L"Error", hr, FrameInfoExpectedErrors); } // If still holding old frame, destroy it if (m_AcquiredDesktopImage) { m_AcquiredDesktopImage->Release(); m_AcquiredDesktopImage = nullptr; } // QI for IDXGIResource hr = DesktopResource->QueryInterface(__uuidof(ID3D11Texture2D), reinterpret_cast<void **>(&m_AcquiredDesktopImage)); DesktopResource->Release(); DesktopResource = nullptr; if (FAILED(hr)) { return ProcessFailure(nullptr, L"Failed to QI for ID3D11Texture2D from acquired IDXGIResource in DUPLICATIONMANAGER", L"Error", hr); } // Get metadata if (FrameInfo.TotalMetadataBufferSize) { // Old buffer too small if (FrameInfo.TotalMetadataBufferSize > m_MetaDataSize) { if (m_MetaDataBuffer) { delete [] m_MetaDataBuffer; m_MetaDataBuffer = nullptr; } m_MetaDataBuffer = new (std::nothrow) BYTE[FrameInfo.TotalMetadataBufferSize]; if (!m_MetaDataBuffer) { m_MetaDataSize = 0; Data->MoveCount = 0; Data->DirtyCount = 0; return ProcessFailure(nullptr, L"Failed to allocate memory for metadata in DUPLICATIONMANAGER", L"Error", E_OUTOFMEMORY); } m_MetaDataSize = FrameInfo.TotalMetadataBufferSize; } UINT BufSize = FrameInfo.TotalMetadataBufferSize; // Get move rectangles hr = m_DeskDupl->GetFrameMoveRects(BufSize, reinterpret_cast<DXGI_OUTDUPL_MOVE_RECT*>(m_MetaDataBuffer), &BufSize); if (FAILED(hr)) { Data->MoveCount = 0; Data->DirtyCount = 0; return ProcessFailure(nullptr, L"Failed to get frame move rects in DUPLICATIONMANAGER", L"Error", hr, FrameInfoExpectedErrors); } Data->MoveCount = BufSize / sizeof(DXGI_OUTDUPL_MOVE_RECT); BYTE* DirtyRects = m_MetaDataBuffer + BufSize; BufSize = FrameInfo.TotalMetadataBufferSize - BufSize; // Get dirty rectangles hr = m_DeskDupl->GetFrameDirtyRects(BufSize, reinterpret_cast<RECT*>(DirtyRects), &BufSize); if (FAILED(hr)) { Data->MoveCount = 0; Data->DirtyCount = 0; return ProcessFailure(nullptr, L"Failed to get frame dirty rects in DUPLICATIONMANAGER", L"Error", hr, FrameInfoExpectedErrors); } Data->DirtyCount = BufSize / sizeof(RECT); Data->MetaData = m_MetaDataBuffer; } Data->Frame = m_AcquiredDesktopImage; Data->FrameInfo = FrameInfo; return DUPL_RETURN_SUCCESS; }