カスタム Holographic Remoting Player アプリの作成

Holographic Remoting を初めて使用する場合は、概要をお読みください。

重要

このドキュメントでは、HoloLens 2 用のカスタム プレーヤー アプリケーションの作成について説明します。 HoloLens 2 用に作成されたカスタム プレーヤーは、HoloLens 1 用に作成されたリモート アプリケーションと互換性がありません。 これは、どちらのアプリケーションも NuGet パッケージ バージョン 2.x.x を使用しなければならないことを意味します。

Holographic Remoting カスタム プレーヤー アプリを作成することにより、HoloLens 2 のリモート コンピューター上からイマーシブ ビューを表示できるカスタムアプリケーションを作成できます。 このページのすべてのコードと作業中のプロジェクトは、Holographic Remoting のサンプル github リポジトリにあります。

Holographic Remoting プレーヤーを使用すると、アプリは、デスクトップ PC または UWP デバイスにレンダリングされた Holographic コンテンツを、より多くのシステムリソースにアクセスできるように、Xbox One のように表示できます。 Holographic Remoting プレーヤー アプリは、入力データを Holographic Remoting リモート アプリケーションにストリーミングし、イマーシブ ビューをビデオおよびオーディオ ストリームとして受け取ります。 接続は標準の Wi-Fi を使用して行われます。 プレーヤーアプリを作成するには、NuGet パッケージを使用して Holographic Remoting を UWP アプリに追加します。 次に、接続を操作するためとイマーシブ ビューを表示するためのコードを記述します。

必須コンポーネント

正しい開始点は、動作中の DirectX ベース UWP アプリが既に Windows Mixed Reality API をターゲットにしていることです。 詳細については、DirectX 開発の概要をご覧ください。 既存のアプリがなく、最初からスタートしたい場合は、C++ holographic プロジェクトテンプレートを使用することをお勧めします。

重要

Holographic Remoting を使用するすべてのアプリは、マルチスレッド アパートメントを使用するように作成する必要があります。 シングルスレッド アパートメントの使用はサポートされていますが、パフォーマンスが低下し、再生中に途切れが生じる可能性があります。 C++/WinRT winrt::init_apartment を使用する場合は、マルチスレッド アパートメントが既定値です。

Holographic Remoting NuGet パッケージを取得する

Visual Studio で NuGet パッケージをプロジェクトに追加するには、次の手順を実行する必要があります。

  1. Visual Studio でプロジェクトを開きます。
  2. プロジェクト ノードを右クリックし、[NuGet パッケージの管理...] を選択します。
  3. 表示されるパネルで、[参照] を選択してから "Holographic Remoting" を検索します。
  4. Microsoft.Holographic.Remoting を選択し、最新の 2.x.x バージョンを選択して [インストール] を選択します。
  5. [プレビュー] ダイアログ ボックスが表示されたら、[OK] をクリックします。
  6. 使用許諾契約書ダイアログが表示されたら、[同意する] を選択します。

重要

NuGet パッケージ内の build\native\include\HolographicAppRemoting\Microsoft.Holographic.AppRemoting.idl には、Holographic Remoting により公開された API の詳細なドキュメントが含まれています。

アプリケーションの Package.appxmanifest を変更する

NuGet パッケージによって追加された Microsoft.Holographic.AppRemoting.dll をアプリケーションが認識できるようにするには、次の手順をプロジェクトで実行する必要があります。

  1. ソリューション エクスプローラーで、Package.appxmanifest ファイルを右クリックして [アプリケーションから開く...] を選択します
  2. [XML (テキスト) エディター] を選択し、[OK] をクリックします
  3. 次の行をファイルに追加して保存する
  </Capabilities>

  <!--Add lines below -->
  <Extensions>
    <Extension Category="windows.activatableClass.inProcessServer">
      <InProcessServer>
        <Path>Microsoft.Holographic.AppRemoting.dll</Path>
        <ActivatableClass ActivatableClassId="Microsoft.Holographic.AppRemoting.PlayerContext" ThreadingModel="both" />
      </InProcessServer>
    </Extension>
  </Extensions>
  <!--Add lines above -->

</Package>

プレーヤーのコンテキストを作成する

最初の手順として、アプリケーションでプレーヤーコンテキストを作成する必要があります。

// class declaration:

#include <winrt/Microsoft.Holographic.AppRemoting.h>

...

private:
// PlayerContext used to connect with a Holographic Remoting remote app and display remotely rendered frames
winrt::Microsoft::Holographic::AppRemoting::PlayerContext m_playerContext = nullptr;
// class implementation:

// Create the player context
// IMPORTANT: This must be done before creating the HolographicSpace (or any other call to the Holographic API).
m_playerContext = winrt::Microsoft::Holographic::AppRemoting::PlayerContext::Create();

警告

カスタム プレーヤーは、プレーヤー アプリと Windows に付属する Windows Mixed Reality ランタイムの間に中間層を挿入します。 これは、プレーヤー コンテキストの作成時に行なわれます。 そのため、Windows Mixed Reality API を呼び出すのがプレーヤー コンテキストを作成する前だと、予期しない動作が起きる可能性があります。 推奨される方法は、あらゆる Mixed Reality API を操作する前に、可能な限り早くプレーヤー コンテキストを作成することです。 Windows Mixed Reality API を通じて作成または取得したオブジェクトの混在は、その後作成または取得したオブジェクトを使用して PlayerContext::Create を呼び出す前に行なわないでください。

次に、HolographicSpace.CreateForCoreWindow を呼び出して、HolographicSpace を作成します。

m_holographicSpace = winrt::Windows::Graphics::Holographic::HolographicSpace::CreateForCoreWindow(window);

リモート アプリへの接続

プレーヤー アプリでコンテンツをレンダリングする準備ができたら、リモート アプリへの接続を確立できます。

接続は、次のいずれかの方法で確立できます。

  1. HoloLens 2 で実行中のプレーヤー アプリは、リモート アプリに接続します。
  2. リモート アプリは、HoloLens 2 で実行中のプレーヤー アプリに接続します。

プレーヤー アプリからリモート アプリに接続するには、ホスト名とポートを指定して、プレーヤーのコンテキストで Connect メソッドを呼び出します。 既定ポートは 8265 です。

try
{
    m_playerContext.Connect(m_hostname, m_port);
}
catch(winrt::hresult_error& e)
{
    // Failed to connect. Get an error details via e.code() and e.message()
}

重要

C++/WinRT API と同様に、Connect がスローする winrt::hresult_error は、処理する必要があります。

プレーヤーアプリで着信接続をリッスンするには、Listen メソッドを呼び出します。 ハンドシェイク ポートとトランスポート ポートの両方を、この呼び出し中に指定できます。 ハンドシェイク ポートは、初期ハンドシェイクに使用されます。 データは、トランスポートポートを介して送信されます。 既定では、ポート番号 82658266 が使用されます。

try
{
    m_playerContext.Listen(L"0.0.0.0", m_port, m_port + 1);
}
catch(winrt::hresult_error& e)
{
    // Failed to listen. Get an error details via e.code() and e.message()
}

PlayerContext は、接続の状態を監視するために 3 つのイベントを公開します

  1. OnConnected: リモート アプリへの接続が正常に確立されたときにトリガーされます。
m_onConnectedEventToken = m_playerContext.OnConnected([]() 
{
    // Handle connection successfully established
});
  1. OnDisconnected: 確立された接続が終了した場合、または接続を確立できなかった場合にトリガーされます。
m_onDisconnectedEventToken = m_playerContext.OnDisconnected([](ConnectionFailureReason failureReason)
{
    switch (failureReason)
    {
        // Handle connection failed or terminated.
        // See ConnectionFailureReason for possible reasons.
    }
}

Note

指定できる ConnectionFailureReason 値は Microsoft.Holographic.AppRemoting.idlファイルに記載されています。

  1. OnListening: 着信接続のリッスンが開始するときです。
m_onListeningEventToken = m_playerContext.OnListening([]()
{
    // Handle start listening for incoming connections
});

さらに、プレーヤーのコンテキストで ConnectionState プロパティを使用して接続状態を照会することができます。

winrt::Microsoft::Holographic::AppRemoting::ConnectionState state = m_playerContext.ConnectionState();

リモートでレンダリングされたフレームを表示する

リモートでレンダリングされるコンテンツを表示するには、HolographicFrame のレンダリング中に PlayerContext::BlitRemoteFrame を呼び出します。

BlitRemoteFrame で現在の HolographicFrame のバックバッファーがレンダーターゲットとしてバインドされている必要があります。 バック バッファーは、Direct3D11BackBuffer プロパティを介して HolographicCameraRenderingParameters から受け取ることができます。

呼び出されると、BlitRemoteFrame がリモート アプリケーションから最後に受信したフレームを HolographicFrame の BackBuffer にコピーします。 さらに、リモート アプリケーションがリモート フレームのレンダリング中にフォーカス ポイントを指定している場合は、フォーカス ポイント セットが設定されます。

// Blit the remote frame into the backbuffer for the HolographicFrame.
winrt::Microsoft::Holographic::AppRemoting::BlitResult result = m_playerContext.BlitRemoteFrame();

Note

PlayerContext::BlitRemoteFrame が現在のフレームのフォーカス ポイントを上書きする可能性があります。

成功すると、BlitRemoteFrameBlitResult::Success_Color を返します。 それ以外の場合は、エラーの理由を返します。

  • BlitResult::Failed_NoRemoteFrameAvailable: 使用可能なリモートフレームがないため、失敗しました。
  • BlitResult::Failed_NoCamera: カメラが存在しないために失敗しました。
  • BlitResult::Failed_RemoteFrameTooOld: リモートフレームが古すぎるため失敗しました (PlayerContext::BlitRemoteFrameTimeout プロパティを参照してください)。

重要

バージョン 2.1.0 以降では、カスタムプレーヤーで Holographic Remoting による深さの再投影を使用できます。

BlitResultBlitResult::Success_Color_Depth を、次のような条件下でスローする可能性があります。

これらの条件が満たされると、BlitRemoteFrame がリモートの深さを現在バインドされているローカル深度バッファーに blit します。 その後に追加のローカル コンテンツをレンダリングできますが、その場合はリモートでレンダリングされるコンテンツとの深さ交差があります。 さらに、カスタムプレーヤーで HolographicCameraRenderingParameters.CommitDirect3D11DepthBuffer を使用してローカル深度バッファーをコミットし、リモートおよびローカルでレンダリングされるコンテンツの深さを再予測することができます。

射影トランスフォーム モード

Holographic Remoting を介して深さの再投影を使用しているとき浮上する 1 つの問題が、カスタム プレーヤー アプリによって直接レンダリングされるローカル コンテンツとは異なる射影トランスフォームを使用してリモート コンテンツをレンダリングできるということです。 一般的なユースケースでは、プレーヤー側とリモート側で (HolographicCamera::SetNearPlaneDistanceHolographicCamera::SetFarPlaneDistance を使用して) 近平面および遠平面に対して異なる値を指定します。 この場合、プレーヤー側の射影トランスフォームにリモートの近/遠平面距離またはローカルの距離が反映されるかどうかは明確ではありません。

バージョン 2.1.0 以降では、PlayerContext::ProjectionTransformConfig を使用して射影トランスフォーム モードを制御できます。 サポートされる値は次のとおりです。

  • Local - HolographicCameraPose::ProjectionTransform は、HolographicCamera 上のカスタムプレーヤーアプリによって設定された近/遠平面距離を反映する射影トランスフォームを返します。
  • Remote - 射影トランスフォームは、リモート アプリによって指定された近/遠平面距離を反映します。
  • Merged - リモート アプリとカスタム プレーヤー アプリとの間の近/遠平面距離がマージされます。 既定では、これは、近平面距離の最小値と遠平面距離の最大値を取得することで行なわれます。 リモート側とローカル側のどちらか一方が逆の場合、遠 < 近であれば、リモートの近/遠平面距離が反転しています。

省略可能: Set BlitRemoteFrameTimeout

重要

PlayerContext::BlitRemoteFrameTimeout をバージョン 2.0.9 以降でサポート。

PlayerContext::BlitRemoteFrameTimeout プロパティは、新しいリモートフレームが受信されなかった場合に、リモートフレームが再利用される時間を指定します。

一般的なユースケースでは、BlitRemoteFrame タイムアウトを有効にして、新しいフレームが一定の時間に受信されなかった場合に空白の画面が表示されるようにします。 有効にすると、BlitRemoteFrame メソッドの戻り値の型を使用して、ローカルにレンダリングされるフォールバック コンテンツに切り替えることもできます。

タイムアウトを有効にするには、プロパティ値を 100 ミリ秒以上の期間に設定します。 タイムアウトを無効にするには、プロパティをゼロ期間に設定します。 タイムアウトが有効になっていてリモート フレームが設定した期間受信されない場合、BlitRemoteFrame が失敗して、Failed_RemoteFrameTooOld を新しいリモート フレームが受信されるまで返します。

using namespace std::chrono_literals;

// Set the BlitRemoteFrame timeout to 0.5s
m_playerContext.BlitRemoteFrameTimeout(500ms);

省略可能: 最後のリモート フレームに関する統計を取得する

パフォーマンスまたはネットワークの問題を診断するために、PlayerContext::LastFrameStatistics プロパティを使用して最後のリモート フレームに関する統計を取得できます。 統計は HolographicFrame::PresentUsingCurrentPrediction の呼び出し中に更新されます。

// Get statistics for the last presented frame.
winrt::Microsoft::Holographic::AppRemoting::PlayerFrameStatistics statistics = m_playerContext.LastFrameStatistics();

詳細については、Microsoft.Holographic.AppRemoting.idl ファイルPlayerFrameStatistics ドキュメントをご覧ください。

省略可能: カスタム データ チャネル

カスタム データ チャネルを使用して、既に確立されているリモート処理接続を介してユーザー データを送信することができます。 詳細については、カスタム データ チャネルに関するページを参照してください。

省略可能: オーバーレンダリング

Holographic Remoting は、レンダリングされたイメージがディスプレイに表示されるときユーザーの頭がどこにあるかを予測します。 ただし、この予測はおおよそです。 したがって、リモート アプリ上で予測されたビューポートと、プレーヤー アプリ上のその後の実際のビューポートは異なる場合があります。 逸脱がより強くなる (たとえば、予測不可能な動きによる) ことが原因で、視野錐台の境界が黒い領域になる可能性があります。 バージョン 2.6.0 以降では、Over-Rendering を使用して黒い領域を小さくし、ビューポートを人為的に視野錐台より大きく増やして視覚の品質を向上させることができます。

Over-Rendering は、PlayerContext::ConfigureOverRendering を使用して有効にすることができます。

OverRenderingConfig は、実際のビューポートに対して小数部のサイズを増やすことを指定します。これにより、予測されたビューポートが大きくなり、切削が減少します。 ビューポートのサイズを大きくすると、ピクセル密度が低下するため、OverRenderingConfig でも解像度を上げることができます。 ビューポートの増加が解像度の増加と同じ場合、ピクセル密度は変わりません。 OverRenderingConfig は次のように定義します。

struct OverRenderingConfig
{
    float HorizontalViewportIncrease; // The fractional horizontal viewport increase. (e.g. 10% -> 0.1).
    float VerticalViewportIncrease; // The fractional vertical viewport increase. (e.g. 10% -> 0.1).
                
    float HorizontalResolutionIncrease; // The fractional horizontal resolution increase. (e.g. 10% -> 0.1).
    float VerticalResolutionIncrease; // The fractional vertical resolution increase. (e.g. 10% -> 0.1).
};

省略可能: 座標系の同期

バージョン 2.7.0 では、座標系同期を使用して、プレーヤーとリモート アプリの間の空間データを揃えることができます。 詳細については、「Holographic Remoting を使用した座標系同期の概要」をご覧ください。

参照