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;
}
예제 #2
0
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;
}