2012-10-12 115 views
5

Como el procesamiento fue lento con D3DPOOL_SCRATCH, escribí el programa de captura de escritorio para hacer referencia al informe en Internet. Sin embargo, el resultado es una imagen de tono negro. ¿Es esto el resultado de un programa de consola o hay alguna otra causa?La captura de escritorio con DirectX no funciona

#include <stdio.h> 
#include <Windows.h> 
#include <d3d9.h> 

void main() 
{ 
    CoInitialize(NULL); 

    LPDIRECT3D9 d3d9; 
    LPDIRECT3DDEVICE9 d3ddev; 
    d3d9 = Direct3DCreate9(D3D_SDK_VERSION); 

    int ww = GetSystemMetrics(SM_CXSCREEN); 
    int wh = GetSystemMetrics(SM_CYSCREEN); 

    HWND hwnd = GetDesktopWindow(); 
    D3DPRESENT_PARAMETERS d3dpp; 
    ZeroMemory(&d3dpp, sizeof(d3dpp)); 
    d3dpp.Windowed = TRUE; 
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; 
    d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; 
    d3dpp.BackBufferCount = 1; 
    d3dpp.BackBufferWidth = ww; 
    d3dpp.BackBufferHeight = wh; 
    d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE; 
    d3dpp.MultiSampleQuality = 0; 
    d3dpp.EnableAutoDepthStencil = TRUE; 
    d3dpp.AutoDepthStencilFormat = D3DFMT_D16; 
    d3dpp.hDeviceWindow = hwnd; 
    d3dpp.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER; 
    d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT; 
    d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; 

    d3d9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &d3ddev); 

    IDirect3DSurface9* render; 
    IDirect3DSurface9* dest; 
    d3ddev->CreateOffscreenPlainSurface(ww, wh, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &dest, NULL); 
    d3ddev->GetRenderTarget(0, &render); 
    d3ddev->GetRenderTargetData(render, dest); 

    D3DLOCKED_RECT bits; 
    dest->LockRect(&bits, NULL, D3DLOCK_READONLY); 

    // If a capture is successful, colors other than black(0x00000000) should enter. 
    for(int i = 0; i < 100; i++){ 
     printf("%02X ", *((BYTE*)bits.pBits + i)); 
    } 

    dest->UnlockRect(); 

    render->Release(); 
    dest->Release(); 
    d3ddev->Release(); 
    d3d9->Release(); 

    CoUninitialize(); 
} 
+0

He intentado ejecutar su código. Obtuve los siguientes errores: 1> Source.obj: error LNK2019: símbolo externo sin resolver _Direct3DCreate9 @ 4 al que se hace referencia en la función _main 1> MSVCRTD.lib (crtexew.obj): error LNK2019: símbolo externo sin resolver _WinMain @ 16 al que se hace referencia en la función ___tmainCRTStartup No entiendo lo que significan. Soy nuevo en DirectX y estoy tratando de construir un programa de captura de pantalla. ¿Pueden ayudarme con dónde me estoy equivocando o en qué dirección debo ir? – newbie2015

Respuesta

5

Esto no es nada relacionado con el tipo de aplicación, si desea obtener los datos de imagen del escritorio de, usted debe usar la siguiente función

GetFrontBufferData

Así que en lugar de llamar

d3ddev->GetRenderTarget(0, &render); 
d3ddev->GetRenderTargetData(render, dest); 

Debe llamar al

d3ddev->GetFrontBufferData(0, dest); 
+0

Pero, el título de la pregunta decía captura de escritorio, creo que debería cambiar el título para que coincida con su solicitud y recurrir a DirectShow para la captura de video. – zdd

+0

¿La captura de pantalla del escritorio puede obtenerse mediante DirectShow? – Tank2005

+0

Si captura un video en vivo reproducido con Overlay Surface, no obtendrá nada, ya que las tecnologías comunes no pueden capturar la superficie de superposición. necesitas un gancho, eso es también lo que estoy buscando. – zdd

4

Si está ejecutando una versión de Windows antes de Windows 8, la API GetFrontBufferData funciona bien, como se indica en otra respuesta. Sin embargo, comenzando con Windows 8, hay un nuevo desktop duplication API que se puede usar para capturar el escritorio en la memoria de video, incluidos los cambios del cursor del mouse y qué partes de la pantalla realmente se cambiaron o movieron. Esto es mucho más eficaz que el enfoque D3D9 y es muy adecuado para hacer cosas como codificar el escritorio en un flujo de video, ya que nunca tiene que sacar la textura de la memoria de la GPU. La nueva API está disponible enumerando las salidas DXGI y llamando al DuplicateOutput en la pantalla que desea capturar. Luego puede ingresar un bucle que espera que la pantalla se actualice y adquiera cada fotograma por turno.

Si desea codificar los fotogramas de un video, le recomiendo echar un vistazo a Media Foundation en lugar de DirectShow, ya que Media Foundation tiene un rendimiento mucho mejor y puede usar D3D11 en lugar de D3D9 para hacer la codificación. También es un poco más fácil de usar, dependiendo de su escenario. Eche un vistazo a Sink Writer de Media Foundation para conocer el método más simple de codificación de los marcos de video.

Para una divulgación completa, trabajo en el equipo que posee la API de duplicación de escritorio en Microsoft, y he escrito aplicaciones que capturan el escritorio (y video, juegos, etc.) en un archivo de video a 60 fps usando técnica, así como muchos otros escenarios.

Cuestiones relacionadas