Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

from-dtx/D3D11TextureMediaSink

Open more actions menu

Repository files navigation

D3D11TextureMediaSink

D3D11TexutreMediaSink は、Direct3D11テクスチャ(ID3D11Texture2D)の形で動画を出力する、MediaSession 用のカスタム MediaSink です。 Microsoft の DX11VideoRenderer サンプル を元にして作りました。

  • MediaSession を構築する際に D3D11TextureMediaSink をビデオレンダラとして登録すると、動画の再生時に、フレーム画像を含んだ IMFSample COM オブジェクトを取得することができます。この IMFSample のメディアバッファには ID3D11Texture2D リソースが含まれています。
  • テクスチャのフォーマットは DXGI_FORMAT_B8G8R8A8_UNorm で固定です。
  • スケジューラでキャッシュすることができる出力テクスチャは、最大5枚です。
  • デコード後のビデオ処理(インタレース解除や色変換)には D3D11/DXVA2.0 を使用します。XVP (Media Foundation Transcode Video Processor) には対応していません。
  • IMFActivate には対応していません。
  • レジストリへの登録には対応していません。

ソリューション構成

  • D3D11TextureMediaSink プロジェクト(C++)

    • D3D11TextureMediaSink.lib/dll を生成します。
  • D3D11TextureMediaSinkDemo プロジェクト(C++)

    • D3D11TextureMediaSink.lib/dll を使って動画を再生するサンプルです。
  • D3D11TextureMediaSinkDemoCShart プロジェクト(C#)

    • D3D11TextureMediaSink.dll を使って動画を再生するサンプルのC#版です。
    • C# で DirectX と Media Foundation を扱うために、ビルド時に SharpDXMediaFoundation を NuGet から取得します。

開発/動作要件

  • Windows 10 October 2018 Update (1809)
  • DirectX 11.0
  • Visual Studio Community 2017 Version 15.9.7
    • C++
      • Windows 10 SDK for October 2018 Update (10.0.17763.0)
      • Visual Studio 2017 (v141) Toolset
    • C#
      • Visual C# 7.0
      • .NET Framework 4.7.1

ライセンス

  • MIT Licence

使い方

(1) 初期化

  • 初めに、アプリ側で、ID3D11DeviceIMFDXGIDeviceManager を作成しておきます。

    • D3D11TextureMediaSink は、IMFDXGIDeviceManager の lock 機能を使用せず、渡された ID3D11Device をそのまま使います。
      そのため、ID3D11Device には ID3D10Multithread::SetMultithreadProtected(TRUE) を設定しておく必要があります。
  • D3D11TextureMediaSink の CreateD3D11TextureMediaSink 関数で IMFMediaSink オブジェクトを生成します。
    引数には、アプリ側で生成した IMFDXGIDeviceManager オブジェクトと ID3D11Device オブジェクトを渡します。

// D3D11TextureMediaSink オブジェクトを生成し、IMFMediaSink インターフェースで受け取ります。
HRESULT hr;
hr = CreateD3D11TextureMediaSink(
  IID_IMFMediaSink,
  (void**)&m_pMediaSink, // IMFMediaSink* m_pMediaSink
  m_pDXGIDeviceManager,  // 作成済みの IMFDXGIDeviceManager
  m_pD3DDevice);         // 作成済みの ID3D11Device
  • D3D11TextureMediaSink から、動画フレームの受け取りに必要となる IMFAttributes も取得しておきます。
hr = m_pMediaSink->QueryInterface(
  IID_IMFAttributes, 
  (void**)&m_pMediaSinkAttributes); // IMFAttributes* m_pMediaSinkAttributes

(2) MediaSession の構築

  • MediaSession を構築します。
  • 部分トポロジーを作る際、ビデオの出力ノード(IMFTopologyNode)に、D3D11TextureMediaSink から取得できる最初の IMFStreamSink オブジェクトを割り当てます。
// IMFMediaSink から、ID 0(固定値)の IMFStreamSink を取得します。
IMFStreamSink* pStreamSink;
hr = pMediaSink->GetStreamSinkById(0, &pStreamSink);

// IMFStreamSink を、出力ノードに割り当てます。
hr = pOutputNode->SetObject(pStreamSink); // IMFTopologyNode* pOutputNode;

(3) 動画フレームの取得と描画

  • MediaSession の再生を開始します。
  • 動画のフレーム(IMFSample)を、D3D11TextureMediaSink の TMS_SAMPLE 属性から取得します。
hr = m_pMediaSinkAttributes->GetUnknown(
  TMS_SAMPLE,         // D3D11TextureMediaSink.h で定義されているGUID
  IID_IMFSample,
  (void**)&pSample);  // IMFSample* pSample
  • 取得した IMFSample から、ID3D11Texture2D を取得します。
// IMFSample からメディアバッファを取得します。
IMFMediaBuffer* pMediaBuffer;
hr = pSample->GetBufferByIndex(0, &pMediaBuffer);

// メディアバッファからDXGIバッファを取得します。
IMFDXGIBuffer* pDXGIBuffer;
hr = pMediaBuffer->QueryInterface(IID_IMFDXGIBuffer, (void**)&pDXGIBuffer);

// DXGIバッファから Texture2D を取得します。
ID3D11Texture2D* pTexture2D;
hr = pDXGIBuffer->GetResource(IID_ID3D11Texture2D, (void**)&pTexture2D);

// Texture2D のサブリソースインデックスを取得します。
UINT subIndex;
hr = pDXGIBuffer->GetSubresourceIndex(&subIndex);
  • 取得した ID3D11Texture2D リソースを、アプリ側の好みの方法で描画します。
(略)
  • 描画が終わったら、IMFSample を解放します。
pTexture2D->Release();
pDXGIBuffer->Release();
pMediaBufer->Release();
pSample->Release();
hr = m_pMediaSinkAttributes->SetUnknown(TMS_SAMPLE, NULL);
  • 注意:
    D3D11TextureMediaSink は、内部のスケジューラに従い、常に、TMS_SAMPLE 属性で提供する IMFSample を、現在表示すべき最新のものに入れ替えていきます。
    アプリが TMS_SAMPLE 属性に対して IMFAttributes::GetUnknown() を呼び出すと、D3D11TextureMediaSink は、この IMFSample の入れ替え作業をいったん保留(ロック)します。
    アプリは、IMFSample の描画を終えてこれが不要になったら、IMFAttributes::SetUnknown() を呼び出して、解放を宣言してください。これが呼び出されると、D3D11TexutreMediaSink は、スケジュールによる最新の IMFSample の入れ替え作業を再開します。

  • さらに注意:
    IMFSample の入れ替え作業は、長時間保留されるべきではありません。
    例えば、IMFSample から取得した ID3D11Texture2D リソースをピクセルシェーダに設定する場合には、シェーダーが実行されるまでそれを維持する必要があります。
    このような場合には、別のリソースに画像をコピーして利用することをお勧めします。

About

A custom media sink that renders video output to a Direct3D11 texture.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Morty Proxy This is a proxified and sanitized view of the page, visit original site.