2012-10-12 27 views
5

由於D3DPOOL_SCRATCH處理速度較慢,因此我編寫了桌面捕獲程序以引用Internet上的報告。然而,結果是一張黑色的照片。這是控制檯程序的結果還是有其他原因?使用DirectX進行桌面捕獲不起作用

#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

我試着運行你的代碼。我遇到以下錯誤:1> Source.obj:錯誤LNK2019:無法解析的外部符號_Direct3DCreate9 @ 4在函數_main中引用1> MSVCRTD.lib(crtexew.obj):錯誤LNK2019:無法解析的外部符號_WinMain @ 16在函數中引用___tmainCRTStartup 我不明白他們的意思。我是DirectX的新手,並且正在嘗試構建一個屏幕捕獲程序。你能幫我解決我的錯在哪裏,或者我該走什麼方向? – newbie2015

回答

5

這沒有什麼相關的應用程序類型,如果你想獲得桌面圖像的數據,你應該使用下面的函數

GetFrontBufferData

因此而不是調用

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

您應該致電

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

但問題標題說的是桌面捕捉,我認爲你應該改變標題以符合你的要求,然後轉向DirectShow進行視頻捕捉。 – zdd

+0

是否可以通過DirectShow獲取桌面的屏幕截圖? – Tank2005

+0

如果您捕捉使用Overlay Surface播放的實況視頻,您將無法獲得任何內容,因爲Overlay surface無法被常用技術捕獲。你需要一些鉤子,這也是我正在尋找的。 – zdd

4

如果您在Windows 8之前的Windows版本上運行,GetFrontBufferData API可以正常工作,正如另一個答案所給出的。但是,從Windows 8開始,有一個新的desktop duplication API可用於捕獲視頻內存中的桌面,包括鼠標光標更改以及實際更改或移動屏幕的哪些部分。這比D3D9方法更具性能,非常適合將桌面編碼爲視頻流,因爲您無需從GPU內存中提取紋理。新的API可通過枚舉DXGI輸出並在要捕獲的屏幕上調用DuplicateOutput來獲得。然後你可以進入一個循環,等待屏幕更新並依次獲取每一幀。

如果您想將幀編碼爲視頻,我建議您查看Media Foundation而不是DirectShow,因爲Media Foundation具有更好的性能,可以使用D3D11而不是D3D9來編碼。根據您的場景,使用起來也更容易一些。請查看媒體基金會的Sink Writer,瞭解編碼視頻幀的最簡單方法。

爲了充分披露,我在微軟擁有桌面重複API的團隊工作,並且我親自編寫了以60fps格式捕獲桌面(以及視頻,遊戲等)到視頻文件的應用程序技術,以及許多其他場景。