2012-10-12 9 views
5

Poiché l'elaborazione è stata lenta da D3DPOOL_SCRATCH, ho scritto il programma di acquisizione desktop come riferimento per il report su Internet. Tuttavia, un risultato è un'immagine nera come la pece. È questo il risultato di un programma di console o c'è qualche altra causa?L'acquisizione desktop con DirectX non funziona

#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

Ho provato a eseguire il codice. Ho ricevuto i seguenti errori: 1> Source.obj: errore LNK2019: simbolo esterno non risolto _Direct3DCreate9 @ 4 di riferimento nella funzione _main 1> MSVCRTD.lib (crtexew.obj): errore LNK2019: simbolo esterno non risolto _WinMain @ 16 di riferimento nella funzione ___tmainCRTStartup Non capisco cosa intendano. Sono nuovo di DirectX e sto cercando di creare un programma di cattura dello schermo. Puoi aiutarmi con dove sto sbagliando o in quale direzione devo entrare? – newbie2015

risposta

5

Questo è nulla legato al tipo di applicazione, se si desidera ottenere i dati di immagine del desktop di, si dovrebbe usare la seguente funzione

GetFrontBufferData

Così, invece di chiamare

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

È necessario chiamare

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

Ma, il titolo della domanda ha detto di acquisizione del desktop, penso che dovresti cambiare il titolo per abbinare la tua richiesta e passare a DirectShow per l'acquisizione video. – zdd

+0

La schermata del desktop è ottenibile tramite DirectShow? – Tank2005

+0

Se acquisisci un video live riprodotto con Overlay Surface, non otterrai nulla, poiché la superficie Overlay non può essere catturata dalle tecnologie comuni. hai bisogno di un gancio, è anche quello che sto cercando. – zdd

4

Se si esegue una versione di Windows precedente a Windows 8, l'API GetFrontBufferData funziona correttamente, come indicato da un'altra risposta. Tuttavia, a partire da Windows 8, è disponibile un nuovo desktop duplication API che può essere utilizzato per acquisire il desktop nella memoria video, comprese le modifiche al cursore del mouse e le parti dello schermo effettivamente modificate o spostate. Questo è molto più performante rispetto all'approccio D3D9 ed è particolarmente adatto per eseguire operazioni come la codifica del desktop in un flusso video, dal momento che non è necessario estrarre la texture dalla memoria della GPU. La nuova API è disponibile enumerando le uscite DXGI e chiamando lo DuplicateOutput sullo schermo che si desidera acquisire. Quindi è possibile inserire un ciclo che attende lo schermo per aggiornare e acquisisce ogni fotogramma a turno.

Se si desidera codificare i frame su un video, si consiglia di dare un'occhiata a Media Foundation anziché a DirectShow, poiché Media Foundation offre prestazioni molto migliori e può utilizzare D3D11 anziché D3D9 per eseguire la codifica. È anche un po 'più facile da usare, a seconda del tuo scenario. Dai uno sguardo a Media Foundation Sink Writer per il metodo più semplice di codifica dei frame video.

Per la divulgazione completa, lavoro con il team proprietario dell'API di duplicazione desktop in Microsoft e ho personalmente scritto app che catturano il desktop (e video, giochi, ecc.) In un file video a 60fps utilizzando questo tecnica, così come molti altri scenari.