HoloLensで低遅延Mixed Reality Captureを使う方法

HoloLens利用者が見ている画面を共有するには、Device Portal経由でMixed Reality Capture(MRC)を使う方法が一般的です。ところが、MRC使うとかなりのタイムラグがあり、利用者と閲覧者の認識がずれてしまうことがよくあります。登壇発表したり、大事なデモをお披露目する時などはタイムラグを計算してかなり気を使わないといけません。

そこで、遅延なくMRCを使用する方法として、低遅延（Low Latency）Mixed Reality Captureが用意されています。また、内部的にはMedia Foundationが使用されていているので、様々な応用や拡張も可能になります。

ソースコードは、GitHubのMixedRealityCompanionKitに含まれています。
https://github.com/Microsoft/MixedRealityCompanionKit

その中の「Low Latency MRC」が今回の内容です。
https://github.com/Microsoft/MixedRealityCompanionKit/blob/master/MixedRemoteViewCompositor/Samples/LowLatencyMRC/README.md

※2017/12現在、上記の説明が古くなっていて、手順通り行ってもうまくいきません（例えば、unitypackageを入れる、と書いてありますが存在しません）。なので、導入メモを残しておきます。

まずは、MixedRealityCompanionKitをcloneしておきます。

#DLLのコンパイル
cloneしたMixedRealityCompanionKitにUnity用の各種アセットは含まれているのですが、実行に必要なDLLが含まれておらず、自分でコンパイルする必要があります。なので、下記のソリューションファイルをVisual Studioで開きます。

MixedRealityCompanionKit\MixedRemoteViewCompositor\Source 以下
MixedRemoteViewCompositor.sln

Visual Studioの環境が整っていないと幾つかエラーが出ますので、順次解決していきます。
### コンポーネントがインストールされていないケース
「C++によるデスクトップ開発」
「C++ユニバーサルWindowsプラットフォームツール」
が必要なのですが、普段HoloLensの開発には不要なので、追加でインストールが必要な場合が多いかもしれません。
ウィザードに従うか「インストールされていない機能のインストール」からインストールを行います。

![install.PNG](https://qiita-image-store.s3.amazonaws.com/0/31032/5d485f03-9546-21de-b3de-c9919b8b147b.png)

また、「Win10SDK_10.0.10586.212」を入れていない場合も同様に追加でインストールします。

### Visual Studioのバージョンが合わないケース
Visual Studio 2017で開いていると、「v140のビルドツールが見つかりません」というエラーが出ます。「Win32」「WSA」の2つのプロジェクトのプロパティを開き、それぞれプラットフォームツールセットをVisual Studio 2017に変更します。

![v140.PNG](https://qiita-image-store.s3.amazonaws.com/0/31032/96a6bee9-4674-1321-fe7d-78613c5e135b.png)

### Windows.Winmdが見つからないケース

マシンによっては下記のエラーが出てビルドできないケースもありました。
```Failed to load a dependency file. Windows.Winmd (Invalid path for /metadata_dir switch - "C:\Program Files (x86)\Windows Kits\10\References\windows.foundation.foundationcontract\1.0.0.0")
```

これは、プロジェクトのプロパティのMIDLを開いて、「追加のメタデータディレクトリ」をマクロ変数でなく手動で設定したら解消しました。（ここはもっといい解決方法があるかもしれません）
```C:\Program Files (x86)\Windows Kits\10\References\windows.foundation.foundationcontract\2.0.0.0
```

![win10_metadata.PNG](https://qiita-image-store.s3.amazonaws.com/0/31032/1d0c86ba-6c09-38d0-804f-03bf8df7716f.png)

その他にも環境によりエラーが発生するケースがありそうです。

そしてビルドが通ると、下記の場所にMixedRemoteViewCompositor.dllが生成されます。

Samples\LowLatencyMRC\Unity\Assets\AddOns\MixedRemoteViewCompositor\Plugins\WSA\x86
Samples\LowLatencyMRC\Unity\Assets\AddOns\MixedRemoteViewCompositor\Plugins\x86

それぞれ、UWP用とUnityEditor（x86環境）のDLLとなります。

ここでもう1つ作業を行います。上記で作成したx86用のDLLは、x64環境のPCでは動作しないようです。なので、x64用のDLLもビルドしてしまいます。

構成マネージャーを開き、Win32プロジェクトの「プラットフォーム」のプルダウンから「新規」を選び、新しいプラットフォームとして「x64」を指定します。設定のコピー元はそのままWin32にします。
これを行ってからビルドを行うと、
Samples\LowLatencyMRC\Unity\Assets\AddOns\MixedRemoteViewCompositor\Plugins\x64
の下にMixedRemoteViewCompositor.dllが生成されます。

![x64.PNG](https://qiita-image-store.s3.amazonaws.com/0/31032/ab2c0437-e652-4762-d535-a9d8d60b3ed9.png)

ここはもともとのMixedRealityCompanionKitにもディレクトリ自体がないので、何か別の回避方法があるのかもしれません（情報求む）

# Unityへの組み込み
DLLが生成されたら、Samples\LowLatencyMRC\Unity\Assets以下をLow Latency MRCを組み込みたいUnityプロジェクトにインポートします。

「WSA/x86」「x86」以下のMixedRemoteViewCompositor.dllについてはもともとmetaファイルが存在するのでいいのですが、新たに追加した「x64」以下のDLLについては、インポート設定を下記のように変更します。

![unity_x64.PNG](https://qiita-image-store.s3.amazonaws.com/0/31032/217b03bd-8fbb-0d1b-af29-7af2e7f905d2.png)

これでEditorでも実行できるはずですので、TestSceneに入っているLowLatencyMrcシーンを開いて実行してみてください。

ポイントになるのは、MrvcManagerのプロパティです。

![manager.PNG](https://qiita-image-store.s3.amazonaws.com/0/31032/605daca7-7da7-9641-7b8f-2ae12b698277.png)

Selected Listenerは「Playback Device」「Capture Device」から選択できますが、HoloLens側は「Capture Device」になり、「Playback Device」からの接続をListenする状態となります。

また、Capabilityは下記のように設定します。
![Capabilities.PNG](https://raw.githubusercontent.com/Microsoft/MixedRealityCompanionKit/master/MixedRemoteViewCompositor/images/Capabilities.png)

これでBuildしてHoloLens実機で動けばHoloLens側の準備は完了です。HoloLensのIPアドレスを控えておいてください。

※Unity2017.2以降ははVR.WSA名前空間がなくなったのでその部分の修正で動くと思います（今後検証予定）
→追記：rhikosさんに検証いただきました（コメント欄）

# Viewerアプリのコンパイル

HoloLensが見ている内容のストリーミング先となるUWPのViewerアプリをコンパイルします。

Samples\LowLatencyMRC\UWP以下にプロジェクトファイルがあるので、Viewer.slnを開きます。
すると、参照の「MixedRemoteViewCompositor」に警告マークがついて、参照が切れている状態となります。
なので、先ほどコンパイルしたDLLに参照を通すのですが、DLLそのものではなく、winmdファイルが対象となります。
Samplesと同じ階層にBuildディレクトリが生成されているはずですので、WSA\x86以下のMixedRemoteViewCompositor.winmdを指定します。

![winmd.PNG](https://qiita-image-store.s3.amazonaws.com/0/31032/8fd49242-da98-99d6-37b7-677b76b85667.png)

コンパイルが通ると、UWPアプリができますので、起動します。
Viewerは「Playback Mode」を選択して、先ほど控えたHoloLensのIPアドレスを入力し、Connect Toをクリックします。接続ができたら、Start MRC Playbackボタンが有効になるので、クリックするとストリーミングが始まります。

![viewer.PNG](https://qiita-image-store.s3.amazonaws.com/0/31032/7046f88b-86b0-9141-5e59-c5a12e2684de.png)

全画面化もできますので、デモなどにお役立てください。