SystemOverview - HexagramNM/NM_WindowCaptureVirtualCamera GitHub Wiki

システムの概要

構成

NM_WindowCaptureVirtualCameraは以下の4つから構成されており、図のようにつながっています。

  • NM_WindowCaptureVirtualCamera(WPFアプリケーション)
  • NM_WindowCapture(ウィンドウキャプチャやトリミングを行うDLL)
  • NM_WCVCam_DS(DirectShowを使用した仮想カメラ)
  • NM_WCVCam_MF(MediaFoundationを使用した仮想カメラ)

SystemFlow.jpg

役割

それぞれのアプリケーションやDLLは以下の通りです。

昔に書いたQiita記事の内容からの変更点

  • DirectShowのインクルードファイルのリポジトリ

    こちらの記事では、DirectShow開発に必要なインクルードファイルなど含むソースコードを、ミラーリングされたリポジトリから取得しておりました。

    DirectShowで仮想カメラを自作しよう

    この記事のコメントで教えていただきましたが、Microsoftさんが公式でそれらのファイルのリポジトリを出していたので、そのリポジトリにあるファイルを使用するように変更しました。

    microsoft/Windows-classic-samples

  • ウィンドウキャプチャと仮想カメラの分離

    こちらの記事では、仮想カメラのコードとウィンドウキャプチャのコードをひとまとめにしており、DirectShowの仮想カメラからキャプチャ処理を呼び出していました。

    WinRTのWindowsGraphicsCaptureAPIでキャプチャしたウィンドウをDirectShowで自作した仮想カメラに映そう

    しかし以下の点から、ウィンドウキャプチャのコードと仮想カメラのコードは分離したほうが良いと判断しております。

    • MediaFoundationの仮想カメラの処理はセッション0上で呼び出され、そもそもユーザのデスクトップ上にあるウィンドウハンドルを取得したり、ウィンドウをキャプチャすることができない

    • DirectShowとWinRTのコードを併用しようとすると、ライブラリが競合してしまい、解決するのにひと手間かける必要がある

    この分離により、結果としてピッカーの起動処理も仮想カメラから分離されることになりました。また、元々の記事ではピッカーを開く時に新たにウィンドウを作り、ピッカーと紐づけておりました。しかし、今回のNM_WindowCaptureVirtualCameraにはGUIウィンドウがあるため、新たにウィンドウを作ることはせず、このGUIウィンドウをピッカーに紐づけております。

    分離とは関係ない修正ですが、元々の記事ではGraphicsCapturePicker.PickSingleItemからの返り値を受け取り、タスクの状態確認や選択されたウィンドウの取得を仮想カメラ側のメインループ(FillBufferメソッド)で独自に行っていました。今回、選択されたウィンドウをco_awaitで受け取るようにし、独自実装していた処理は除去しました。(当時も適切に排他処理すれば、co_awaitで対応できたように思います。)co_awaitが使用できるように、Visual Studioのプロジェクト側で/awaitのオプションを追加しております。

  • オフスクリーンレンダリングと仮想カメラの分離

    こちらの記事では、位置調整やトリミングのためのオフスクリーンレンダリングをMediaFoundationの仮想カメラから行っていました。

    DirectXとMediaFoundation仮想カメラとの効率の良い連携

    しかし、以下の理由からオフスクリーンレンダリングの処理と仮想カメラは分離し、オフスクリーンレンダリング後の画像を共有テクスチャとして渡したほうが良いと判断しております。 (オフスクリーンレンダリング処理はNM_WindowCaptureにウィンドウキャプチャ処理とまとめています。)

    • オフスクリーンレンダリングの処理をそれぞれの仮想カメラに重複して書く必要がなくなる。

    • オフスクリーンレンダリング後の画像だけ共有テクスチャで送ればよくなり、トリミング情報など仮想カメラに送る必要のあるものが減る。

      • 仮想カメラ側でオフスクリーンレンダリングしてしまうと、映像の左右反転やトリミングなどの情報を仮想カメラに送る手段が別に必要になる。
    • キャプチャできるウィンドウサイズの制限がなくなる。

      • キャプチャされるウィンドウはDirectXのテクスチャとして取得できるが、大きさが変わりうる。

      • 仮想カメラでオフスクリーンレンダリングする場合は、大きさ変更に対応するため、あらかじめ大きなテクスチャを作成し、そこにキャプチャされたウィンドウをコピーしていた。 しかし、この場合はキャプチャできるウィンドウの上限があらかじめ作成する大きなテクスチャのサイズに制限されてしまう。

      • ウィンドウキャプチャのタイミングでオフスクリーンレンダリングする場合は、取得されたテクスチャをそのままオフスクリーンレンダリングで使用すればよく、 あらかじめ大きなテクスチャを作成する必要はなくなった。結果として、キャプチャできるウィンドウサイズの制限を回避できるようになった。

戻る