0

Windows API からデスクトップ複製を使用しています。次のフレームにアクセスし、前のフレームから変更されたピクセルの四角形を取得するコードを次に示します。

//
// Get next frame and write it into Data
//
_Success_(*Timeout == false && return == DUPL_RETURN_SUCCESS)
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(10000, &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;

//Here I would like to access pixel data from Data->Frame. A buffer of RGBA pixel

return DUPL_RETURN_SUCCESS;
}

ここにFrame_Data構造があります

typedef struct _FRAME_DATA
{
ID3D11Texture2D* Frame;
DXGI_OUTDUPL_FRAME_INFO FrameInfo;
_Field_size_bytes_((MoveCount * sizeof(DXGI_OUTDUPL_MOVE_RECT)) + (DirtyCount * sizeof(RECT))) BYTE* MetaData;
UINT DirtyCount;
UINT MoveCount;
} FRAME_DATA;

から変更されたピクセル バッファ データにアクセスすることは可能ですか?Data->Frame

データにアクセスするための私のコードは次のとおりです。

BYTE* DISPLAYMANAGER::GetImageData(ID3D11Texture2D* texture2D, D3D11_TEXTURE2D_DESC Desc)
{
if (texture2D != NULL)
{
    D3D11_TEXTURE2D_DESC description;
    texture2D->GetDesc(&description);
    description.BindFlags = 0;
    description.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
    description.Usage = D3D11_USAGE_STAGING;
    description.Format = DXGI_FORMAT_B8G8R8A8_UNORM;

    ID3D11Texture2D* texTemp = NULL;
    HRESULT hr = m_Device->CreateTexture2D(&description, NULL, &texTemp);
    if (FAILED(hr))
    {
        if (texTemp)
        {
            texTemp->Release();
            texTemp = NULL;
        }
        return NULL;
    }
    m_DeviceContext->CopyResource(texTemp, texture2D);

    D3D11_MAPPED_SUBRESOURCE mapped;
    unsigned int subresource = D3D11CalcSubresource(0, 0, 0);
    hr = m_DeviceContext->Map(texTemp, subresource, D3D11_MAP_READ_WRITE, 0, &mapped);
    if (FAILED(hr))
    {
        texTemp->Release();
        texTemp = NULL;
        return NULL;
    }

    unsigned char *captureData = new unsigned char[Desc.Width * Desc.Height * 4];
    RtlZeroMemory(captureData, Desc.Width * Desc.Height * 4);
    const int pitch = mapped.RowPitch;
    unsigned char *source = static_cast<unsigned char*>(mapped.pData);
    unsigned char *dest = captureData;
    for (int i = 0; i < Desc.Height; i++) {
        memcpy(captureData, source, Desc.Width * 4);
        source += pitch;
        captureData += Desc.Width * 4;
    }
    for (int i = 0; i < Desc.Width * Desc.Height * 4; i++) {
        //trace(L"Pixel[%d] = %x\n", i, dest[i]);
    }

    m_DeviceContext->Unmap(texTemp, 0);
    return dest;
}
else
    return NULL;
}

ご協力ありがとうございました!

4

1 に答える 1