5

D3DPOOL_SCRATCH で処理が遅くなったので、デスクトップキャプチャープログラムを書いてインターネット上のレポートを参考にしました。しかし、結果は真っ暗な絵。これはコンソール プログラムの結果ですか、それとも他の原因がありますか?

#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();
}
4

2 に答える 2

5

これはアプリケーションの種類には関係ありません。デスクトップ イメージのデータを取得する場合は、次の関数を使用する必要があります。

GetFrontBufferData

だから電話する代わりに

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

あなたは電話するべきです

d3ddev->GetFrontBufferData(0, dest);
于 2012-10-12T16:14:28.730 に答える
4

Windows 8 より前のバージョンの Windows で実行している場合、別の回答で示されているように、GetFrontBufferData API は正常に動作します。ただし、Windows 8 以降では、マウス カーソルの変化や、画面のどの部分が実際に変化または移動したかなど、デスクトップをビデオ メモリにキャプチャするために使用できる新しいデスクトップ複製 APIがあります。これは、D3D9 アプローチよりもはるかにパフォーマンスが高く、GPU メモリからテクスチャを引き出す必要がないため、デスクトップをビデオ ストリームにエンコードするなどの作業に非常に適しています。新しい API は、DXGI 出力を列挙し、キャプチャする画面でDuplicateOutputを呼び出すことで利用できます。次に、画面が更新されるのを待って各フレームを順番に取得するループに入ることができます。

フレームをビデオにエンコードする場合は、DirectShow ではなくMedia Foundationを検討することをお勧めします。これは、Media Foundation の方がパフォーマンスが優れており、D3D9 ではなく D3D11 を使用してエンコードを行うことができるためです。シナリオによっては、少し使いやすくなります。ビデオ フレームをエンコードする最も簡単な方法については、Media Foundation のSink Writerを参照してください。

完全な開示のために、私はマイクロソフトのデスクトップ複製 API を所有するチームで働いており、この手法を使用して、デスクトップ (およびビデオ、ゲームなど) をビデオ ファイルに 60 fps でキャプチャするアプリを個人的に作成しました。他の多くのシナリオとして。

于 2014-03-06T07:41:04.450 に答える