DX11VideoRenderer を解読して、VideoRenderer 要件を探る。
Microsoft のサンプルがあり参考になる。
これは結構がっつり作ってあるので、削って最低限必要な要素を探る。 IMFMediaSink を作る 手抜きして IMFActivate 抜きで。 https://github.com/Microsoft/Windows-classic-samples/blob/master/Samples/DX11VideoRenderer/c++/DX11VideoRenderer.h を参考に最低限を実装してみる。 guidgen.exe で guid を決めた。 CustomVideoRenderer.h
IMFStreamSink がひとつは必要 作る。
メソッドの中身は
return E_FAIL;
でお茶を濁した。
IMFMediaSink::AddStreamSink 実装 IMFMediaSink::GetStreamSinkById 実装 IMFMediaSink::GetStreamSinkByIndex 実装 IMFMediaSink::GetStreamSinkCount 実装 IMFMediaSink::RemoveStreamSink 実装 実行してみる。
デバッガで調べたら IMFStreamSink::GetMediaSink の直後にエラーになることがわかった。 IMFStreamSink::GetMediaSink 実装 たんたんとエラーを直していく。 IMFStreamSink::GetMediaTypeHandler 実装
IMFMediaTypeHandler が必要。 StreamSink に IMFMediaTypeHandler を実装 このインタフェースは StreamSink が処理できる MediaType を示すので必要。 サポートするフォーマットを決める。
Data Flow ここまでの実装で IMFSession::Start の呼び出しに応じて IMFClockStateSink::OnClockStart が呼ばれるようになった。 Data Flow
Media sinks use a pull model
MesiaSink 側からサンプルを取りに行かないといけない。
State Changes IMFClockStateSink の実装について。
In addition, stream sinks must send the following events when they have completed the state transitions:
OnClockStart, OnClockRestart: MEStreamSinkStarted event OnClockPause: MEStreamSinkPaused event OnClockStop: MEStreamSinkStopped event
なるほど。
ついに IMFStreamSink::ProcessSample がコールされた。 試しに下記のような実装にしてみたがこれでは Clock 無視で最速でフレームを消化してしまうのでだめ。
MEStreamSinkRequestSample をスケジューリングする
Scheduled Work Items
これを使ってみる。
DX11VideoRenderer::CScheduler を使えばよいと思う。 だいたい仕組みがわかった。 DX11VideoRenderer から引き算して最小限の構成にする(ProcessSample が何もしない)場合、 以下の部品を残す必要がありそう。
Scheduler StreamSink: IMFStreamSink, IMFMediaTypeHandler MesiaSink: IMFMediaSink, IMFClockStateSink