c ++ - Sådan får du adgang til pixeldata fra ID3D11Texture2D?

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg bruger Windows Desktop Duplication API til at lave min egen spejlsprotokol.
Jeg har dette stykke kode:


// Get new frame
HRESULT hr = m\_DeskDupl->AcquireNextFrame(500, &FrameInfo, &DesktopResource);
if (hr == DXGI\_ERROR\_WAIT\_TIMEOUT)
{
    *Timeout = true;
    return DUPL\_RETURN\_SUCCESS;
}


Her er strukturen FrameInfo:


`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;`


Jeg vil gerne udpakke pixelbufferen fra ID3D11Texture2D* Frame;
Hvordan kan jeg udvinde på en BYTE * eller unsigned char * og have en RGB-sekvens?
Tak skal du have !

Bedste reference


Du skal oprette en anden tekstur af samme størrelse med CPU-læsadgang ved hjælp af ID3D11Device::CreateTexture2D, kopier hele rammen eller bare opdaterede dele til denne tekstur på GPU ved hjælp af ID3D11DeviceContext::CopyResource eller ID3D11DeviceContext::CopySubresourceRegion (det er muligt for at hente de dele, der blev opdateret med IDXGIOutputDuplication::GetFrameDirtyRects og IDXGIOutputDuplication::GetFrameMoveRects), kort anden tekstur for at gøre den tilgængelig ved hjælp af CPU ved hjælp af ID3D11DeviceContext::Map, som giver dig D3D11\_MAPPED\_SUBRESOURCE struct indeholdende peger til buffer med ramme data og dets størrelse, det er det du leder efter.


Microsoft giver en temmelig detaljeret brugerprøve til brug af Duplication API, der implementerer alle ovenstående trin. [17]


Der er også en lige prøve, der viser, hvordan man redder ID3D11Texture2D data til fil. [18]

Andre referencer 1


Hej her er koden, der hjælper til dit krav. output vil være i UCHAR buffer g\_iMageBuffer


//Variable Declaration
IDXGIOutputDuplication* IDeskDupl;
IDXGIResource*          lDesktopResource = nullptr;
DXGI\_OUTDUPL\_FRAME\_INFO IFrameInfo;
ID3D11Texture2D*        IAcquiredDesktopImage;
ID3D11Texture2D*        lDestImage;
ID3D11DeviceContext*    lImmediateContext;
UCHAR*                  g\_iMageBuffer=nullptr;

//Screen capture start here
hr = lDeskDupl->AcquireNextFrame(20, &lFrameInfo, &lDesktopResource);

// >QueryInterface for ID3D11Texture2D
hr = lDesktopResource->QueryInterface(IID\_PPV\_ARGS(&lAcquiredDesktopImage));
lDesktopResource.Release();

// Copy image into GDI drawing texture
lImmediateContext->CopyResource(lDestImage,lAcquiredDesktopImage);
lAcquiredDesktopImage.Release();
lDeskDupl->ReleaseFrame();  

// Copy GPU Resource to CPU
D3D11\_TEXTURE2D\_DESC desc;
lDestImage->GetDesc(&desc);
D3D11\_MAPPED\_SUBRESOURCE resource;
UINT subresource = D3D11CalcSubresource(0, 0, 0);
lImmediateContext->Map(lDestImage, subresource, D3D11\_MAP\_READ\_WRITE, 0, &resource);

std::unique\_ptr<BYTE> pBuf(new BYTE[resource.RowPitch*desc.Height]);
UINT lBmpRowPitch = lOutputDuplDesc.ModeDesc.Width * 4;
BYTE* sptr = reinterpret\_cast<BYTE*>(resource.pData);
BYTE* dptr = pBuf.get() + resource.RowPitch*desc.Height - lBmpRowPitch;
UINT lRowPitch = std::min<UINT>(lBmpRowPitch, resource.RowPitch);

for (size\_t h = 0; h < lOutputDuplDesc.ModeDesc.Height; ++h)
{
    memcpy\_s(dptr, lBmpRowPitch, sptr, lRowPitch);
    sptr += resource.RowPitch;
    dptr -= lBmpRowPitch;
}

lImmediateContext->Unmap(lDestImage, subresource);
long g\_captureSize=lRowPitch*desc.Height;
g\_iMageBuffer= new UCHAR[g\_captureSize];
g\_iMageBuffer = (UCHAR*)malloc(g\_captureSize);

//Copying to UCHAR buffer 
memcpy(g\_iMageBuffer,pBuf,g\_captureSize);