Ich experimentierte mit Möglichkeiten, Bildschirm unter Windows zu erfassen und somit auf den schnellsten Weg zu entscheiden. Am gebräuchlichsten ist natürlich der GDI-Weg. Und es ist in der Leistung auch anständig. Abhängig von der Systemauslastung und dem statischen/nicht statischen Bildschirminhalt lag die Bildschirmaufzeichnungsrate zwischen 27 und 47 fps (Windows 7, Intel i5 @ 2,6 GHz, 8 GB RAM).Mit DirectX zu erfassen Bildschirm unter Windows
Jetzt, mit DirectX-Front-Puffer Ansatz (mit der GetFrontBufferData() API), war die Leistung vergleichbar, aber etwas auf der langsameren Seite (ich konnte nicht so hoch wie 48 fps erreichen).
Ich ging durch diesen Beitrag: Fastest method of screen capturing und die ausprobiert den Weg vorgeschlagen in der angenommenen Antwort mit getRenderTarget() und getRenderTargetData(), aber wie in den Kommentaren vorgeschlagen, alles, was ich bekomme ist ein schwarzes Bild. Hier ist mein vollständiger Code einschließlich Erstkonfigurationen für das Gerät:
IDirect3DSurface9* pRenderTarget=NULL;
IDirect3DSurface9* pDestTarget=NULL;
// sanity checks.
if (g_pd3dDevice == NULL){
return;
}
HRESULT hr;
// get the render target surface.
hr = g_pd3dDevice->GetRenderTarget(0, &pRenderTarget);
// get the current adapter display mode.
//hr = pDirect3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT,&d3ddisplaymode);
// create a destination surface.
hr = g_pd3dDevice->CreateOffscreenPlainSurface(1600, 900, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &pDestTarget, NULL);
//copy the render target to the destination surface.
hr = g_pd3dDevice->GetRenderTargetData(pRenderTarget, pDestTarget);
D3DLOCKED_RECT lockedRect;
hr =pDestTarget->LockRect(&lockedRect,NULL, D3DLOCK_NO_DIRTY_UPDATE|D3DLOCK_NOSYSLOCK|D3DLOCK_READONLY);
for(int i=0 ; i < 900 ; i++)
{
for(int j=0; j < 1600; j++){
memcpy((BYTE*) data + i * 1600 * 3 + j * 3, (BYTE*) lockedRect.pBits + i* lockedRect.Pitch + j * 4, 3);
}
}
pDestTarget->UnlockRect();
// clean up.
pRenderTarget->Release();
pDestTarget->Release();
Und für das Gerät Initialisierung Teil:
g_pDirect3D = Direct3DCreate9(D3D_SDK_VERSION);
D3DPRESENT_PARAMETERS PresentParams;
memset(&PresentParams, 0, sizeof(D3DPRESENT_PARAMETERS));
PresentParams.Windowed = TRUE;
PresentParams.SwapEffect =D3DSWAPEFFECT_DISCARD;
g_pDirect3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL ,GetDesktopWindow(),D3DCREATE_SOFTWARE_VERTEXPROCESSING, &PresentParams,&g_pd3dDevice);
Bitte weisen darauf hin, den Fehler in dem obigen Code. Irgendwelche Vorschläge sind willkommen. Ich versuchte auch die GetBackBuffer() API, aber ich konnte die Bilddaten nicht erhalten.
EDIT:
Mein Anwendungsfall war Desktop-Bildschirm zu erfassen, die nur mit GetFrontBufferData() über directX gemacht zu sein scheint. GetBackBuffer()/GetRenderTargetData() ist nicht die richtige API für diesen Fall aufrufen. Referenz: The desktop capture with DirectX does not work und How to get the screenshot of the desktop from back buffer with DirectX.
Allerdings sind alle Vorschläge für eine schnellere Methode zur Erfassung von Desktop-Bildschirm oder die Optimierung der GDI-Art willkommen.
Ich fühle mich wie 'GetRenderTarget' wird den Backbuffer für das Gerät zurückgeben. Vielleicht möchten Sie sich die Funktion 'GetFrontBufferData' anschauen. –
Ich habe GetFrontBufferData() wie in der Frage erwähnt verwendet, es funktioniert gut. Aber es gibt keinen Leistungsgewinn gegenüber der GDI-Methode. Ich war auf der Suche nach einem schnelleren Ansatz, wenn überhaupt. –
Ich schreibe auch eine Screencapture-Anwendung. [Hier] (http://stackoverflow.com/q/31286503/4794952) ist der Link zu meinem Problem. Ich erhalte einen schwarzen Bildschirm, wenn ich ein Spiel aufnehme, während es für jede andere Anwendung den richtigen Bildschirm zurückgibt. Gibt es eine Möglichkeit, es mit Vollbild-Spielen funktionieren zu lassen? – newbie2015