5

画面データを取得してアプリケーションの DX9 サーフェス/テクスチャに渡し、解像度1600*900で少なくとも25 fpsでレンダリングする方法が必要です。30 の方がよいでしょう。

BitBliting を試してみましたが、その後も 20 fps で、データをテクスチャにロードしてレンダリングした後は 11 fps になり、必要なものよりもはるかに遅れています。

GetFrontBufferData は論外です。

これはWindows Media API の使用に関するものですが、私はそれに慣れていません。サンプルはデータをファイルに直接保存しています。おそらく、個々のフレームを提供するように設定できますが、自分で試すのに十分なドキュメントが見つかりません.

私のコード:

m_memDC.BitBlt(0, 0, m_Rect.Width(),m_Rect.Height(), //m_Rect is area to be captured
               &m_dc, m_Rect.left, m_Rect.top, SRCCOPY); 
      //at 20-25fps after this if I comment out the rest

//DC,HBITMAP setup and memory alloc is done once at the begining
GetDIBits( m_hDc, (HBITMAP)m_hBmp.GetSafeHandle(),
    0L,             // Start scan line
    (DWORD)m_Rect.Height(),     // # of scan lines
    m_lpData,                   // LPBYTE
    (LPBITMAPINFO)m_bi,     // address of bitmapinfo
    (DWORD)DIB_RGB_COLORS);     // Use RGB for color table
     //at 17-20fps

IDirect3DSurface9 *tmp;
m_pImageBuffer[0]->GetSurfaceLevel(0,&tmp); //m_pImageBuffer is Texture of same 
                                            //size as bitmap to prevent stretching
hr= D3DXLoadSurfaceFromMemory(tmp,NULL,NULL,
                             (LPVOID)m_lpData,
                             D3DFMT_X8R8G8B8,
                             m_Rect.Width()*4,
                             NULL,
                             &r,                 //SetRect(&r,0,0,m_Rect.Width(),m_Rect.Height();
                             D3DX_DEFAULT,0);
 //12-14fps
IDirect3DSurface9 *frameS;
hr=m_pFrameTexture->GetSurfaceLevel(0,&frameS); // Texture of that is rendered
pd3dDevice->StretchRect(tmp,NULL,frameS,NULL,D3DTEXF_NONE);
//11fps

512*512 の正方形の場合、30fps で実行されることがわかったので (つまり、20-25 で 490*450 の場合)、画面を分割しようとしましたが、うまくいかないようでした。

コードに欠けているものがある場合は、書き留めてください。反対票を投じないでください。ありがとう

4

2 に答える 2

12

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

フレームをビデオにエンコードするには、Media Foundationをご覧になることをお勧めします。ビデオ フレームをエンコードする最も簡単な方法については、特にSink Writerを参照してください。基本的には、ビデオ フレームごとに取得した D3D テクスチャを IMFSample オブジェクトにラップするだけです。これらは、シンク ライターに直接渡すことができます。詳細については、MFCreateDXGISurfaceBufferおよびMFCreateVideoSampleFromSurface関数を参照してください。最高のパフォーマンスを得るには、通常、(ほとんどのマシンで) ハードウェア エンコーディングを適切にサポートする H.264 などのコーデックを使用することをお勧めします。

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

于 2014-03-06T08:38:50.543 に答える
1

FrontBuffer が気に入らない場合は、BackBuffer を試してください。

LPDIRECT3DSURFACE9  surface;
surface = GetBackBufferImageSurface(&fmt);

ファイルに保存するには

D3DXSaveSurfaceToFile(filename, D3DXIFF_JPG, surface, NULL, NULL);
于 2013-01-28T11:42:14.920 に答える