2013-07-23 13 views
5

Eksperymentowałem ze sposobami przechwytywania ekranu w oknach i w konsekwencji decydowania o najszybszym sposobie. Najbardziej powszechny jest oczywiście sposób GDI. I jest przyzwoity także pod względem wydajności. W zależności od obciążenia systemu i statycznej/niestatycznej zawartości ekranu szybkość przechwytywania ekranu wynosiła od 27-47 fps (Windows 7, Intel [email protected] GHz, 8 GB RAM).Używanie DirectX do przechwytywania ekranu w systemie Windows

Teraz, stosując metodę DirectX Front Buffer (wykorzystującą API GetFrontBufferData()), wydajność była porównywalna, ale nieznacznie wolniejsza (nie mogłem osiągnąć nawet 48 fps).

Przeszedłem przez ten post: Fastest method of screen capturing i wypróbowałem sposób sugerowany w zaakceptowanej odpowiedzi za pomocą getRenderTarget() i getRenderTargetData(), ale jak zasugerowano w komentarzach, dostaję tylko czarny obraz. Oto mój pełny kod w tym wstępne konfiguracje urządzenia:

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(); 

oraz za część inicjalizacji urządzenie:

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

Proszę zwrócić uwagę na błąd w powyższym kodzie. Wszelkie sugestie są mile widziane. Próbowałem również funkcji API GetBackBuffer(), ale nie udało mi się uzyskać danych obrazu.

EDIT:

Mój przypadek użycia było przechwytywanie ekranu pulpitu, który wydaje się być dokonana jedynie za pomocą GetFrontBufferData() poprzez DirectX. GetBackBuffer()/GetRenderTargetData() nie jest właściwym interfejsem API do wywoływania tego przypadku. Odniesienia: The desktop capture with DirectX does not work i How to get the screenshot of the desktop from back buffer with DirectX.

Jednak wszelkie sugestie dotyczące szybszej metody przechwytywania ekranu pulpitu lub optymalizacji sposobu GDI są mile widziane.

+1

Czuję, że 'GetRenderTarget' zwróci bufor zwrotny dla urządzenia. Możesz zajrzeć do funkcji 'GetFrontBufferData'. –

+0

Użyłem GetFrontBufferData(), jak wspomniano w pytaniu, działa dobrze. Ale nie ma poprawy wydajności w stosunku do GDI. Szukałem szybszego podejścia, jeśli w ogóle. –

+0

Piszę również aplikację screencapture. [Here] (http://stackoverflow.com/q/31286503/4794952) jest linkiem do mojego problemu. Dostaję czarny ekran, gdy przechwytywam jakąkolwiek grę, podczas gdy dla każdej innej aplikacji zwraca ona właściwy przechwycony ekran. Czy jest jakiś sposób, aby działał z pełnoekranowymi grami? – newbie2015

Odpowiedz

2

Czy renderowałeś coś przed zrobieniem zrzutu ekranu?

  • GetFrontBufferData - funkcja uzyskać dane na ekranie
  • GetRenderTargetData - funkcja uzyskać dane z renderowanie TARGET

więc jeśli nie czynią nic, na pewno będzie dostaje pusty obraz.

+0

Jestem prawdopodobnie poza kontekstem tutaj. Moim przypadkiem użycia jest uzyskanie danych z ekranu pulpitu. Sugerujesz, że GetRenderTargetData() nie jest właściwym interfejsem API do połączenia. Czy możesz rozwinąć część renderującą? –

+0

Sprawdziłem odpowiedź tutaj http://stackoverflow.com/questions/12859894/the-desktop-capture-with-directx-does-not-work/12863143#12863143 .. tak, GetFrontBufferData() jest jedynym API, który ma być służy do przechwytywania pulpitu przez DirectX. –

+1

Tak, metoda GetRenderTargetData() została użyta do pobrania danych z docelowego renderowania aplikacji, a nie pulpitu. – zdd

Powiązane problemy