OpenXR API を使用した Holographic リモート処理リモートアプリの作成Writing a Holographic Remoting remote app using the OpenXR API

重要

このドキュメントでは、 OPENXR APIを使用して HoloLens 2 および Windows Mixed Reality ヘッドセット用のリモートアプリケーションを作成する方法について説明します。This document describes the creation of a remote application for HoloLens 2 and Windows Mixed Reality headsets using the OpenXR API. HoloLens のリモートアプリケーション (第1世代) では、NuGet パッケージバージョン 1.x を使用する必要があります。Remote applications for HoloLens (1st gen) must use NuGet package version 1.x.x. これは、HoloLens 2 用に作成されたリモートアプリケーションが HoloLens 1 と互換性がないことを意味します。This implies that remote applications written for HoloLens 2 are not compatible with HoloLens 1 and vice versa. HoloLens 1 のドキュメントについては、 こちらを参照してください。The documentation for HoloLens 1 can be found here.

Holographic リモート処理アプリを使用すると、リモートでレンダリングされたコンテンツを HoloLens 2 および Windows Mixed Reality のイマーシブヘッドセットにストリーミングできます。Holographic Remoting apps can stream remotely rendered content to HoloLens 2 and Windows Mixed Reality immersive headsets. また、より多くのシステムリソースにアクセスしたり、既存のデスクトップ PC ソフトウェアにリモートの イマーシブビュー を統合したりすることもできます。You can also access more system resources and integrate remote immersive views into existing desktop PC software. リモートアプリは HoloLens 2 から入力データストリームを受け取り、仮想イマーシブビューでコンテンツをレンダリングし、コンテンツフレームを HoloLens 2 にストリームバックします。A remote app receives an input data stream from HoloLens 2, renders content in a virtual immersive view, and streams content frames back to HoloLens 2. 接続は標準の Wi-fi を使用して行われます。The connection is made using standard Wi-Fi. Holographic リモート処理は、NuGet パケット経由でデスクトップまたは UWP アプリに追加されます。Holographic Remoting is added to a desktop or UWP app via a NuGet packet. 接続を処理し、イマーシブビューでレンダリングする追加のコードが必要です。Additional code is required which handles the connection and renders in an immersive view. 一般的なリモート処理接続では、待機時間が50ミリ秒に抑えられます。A typical remoting connection will have as low as 50 ms of latency. プレーヤーアプリは、リアルタイムで待機時間を報告できます。The player app can report the latency in real time.

このページのすべてのコードと作業中のプロジェクトは、 Holographic リモート処理のサンプル github リポジトリにあります。All code on this page and working projects can be found in the Holographic Remoting samples github repository.

前提条件Prerequisites

開始点としては、OpenXR ベースのデスクトップまたは UWP アプリを使用することをお勧めします。A good starting point is a working OpenXR based Desktop or UWP app. 詳細については、「 OpenXR の概要」を参照してください。For details see Getting started with OpenXR.

重要

Holographic リモート処理を使用するすべてのアプリは、 マルチスレッドアパートメントを使用するように作成する必要があります。Any app using Holographic Remoting should be authored to use a multi-threaded apartment. シングルスレッドアパートメントの使用はサポートされていますが、パフォーマンスが低下し、再生中に途切れが生じる可能性があります。The use of a single-threaded apartment is supported but will lead to sub-optimal performance and possibly stuttering during playback. C++ を使用している場合、winrt winrt:: init_apartment 、マルチスレッドアパートメントが既定値です。When using C++/WinRT winrt::init_apartment a multi-threaded apartment is the default.

Holographic リモート処理 NuGet パッケージを取得するGet the Holographic Remoting NuGet package

Visual Studio で NuGet パッケージをプロジェクトに追加するには、次の手順を実行する必要があります。The following steps are required to add the NuGet package to a project in Visual Studio.

  1. Visual Studio でプロジェクトを開きます。Open the project in Visual Studio.
  2. プロジェクトノードを右クリックし、[ NuGet パッケージの管理... ] を選択します。Right-click the project node and select Manage NuGet Packages...
  3. 表示されるパネルで、[ 参照 ] を選択し、"Holographic Remoting" を検索します。In the panel that appears, select Browse and then search for "Holographic Remoting".
  4. [ Holographic] を選択して 、最新の 2.x バージョンを選択し、[ インストール] を選択します。Select Microsoft.Holographic.Remoting.OpenXr, ensure to pick the latest 2.x.x version and select Install.
  5. [ プレビュー ] ダイアログが表示されたら、[ OK] を選択します。If the Preview dialog appears, select OK.
  6. [使用許諾契約書] ダイアログボックスが表示されたら、[ 同意 する] を選択します。Select I Accept when the license agreement dialog pops up.
  7. 次の NuGet パッケージに対して手順 3. ~ 6. を繰り返します: OpenXR、OpenXRRepeat the steps 3 to 6 for the following NuGet Packages: OpenXR.Headers, OpenXR.Loader

注意

HoloLens 1 を対象とする開発者は、NuGet パッケージ のバージョン 1.x を引き続き利用できます。Version 1.x.x of the NuGet package is still available for developers who want to target HoloLens 1. 詳細については、「 Add Holographic Remoting (HoloLens (第1世代))」を参照してください。For details see Add Holographic Remoting (HoloLens (1st gen)).

Holographic Remoting OpenXR ランタイムを選択します。Select the Holographic Remoting OpenXR runtime

リモートアプリで行う必要がある最初の手順は、Holographic NuGet パッケージの一部である Holographic Remoting OpenXR runtime を選択することです。The first step you need to do in your remote app is to select the Holographic Remoting OpenXR runtime, which is part of the Microsoft.Holographic.Remoting.OpenXr NuGet package. これを行うには、 XR_RUNTIME_JSON 環境変数を、アプリ内のファイルの RemotingXR.jsのパスに設定します。You can do this by setting the XR_RUNTIME_JSON environment variable to the path of the RemotingXR.json file within your app. この環境変数は、システムの既定の OpenXR ランタイムを使用せずに、代わりに Holographic Remoting OpenXR runtime にリダイレクトするために OpenXR ローダーによって使用されます。This environment variable is used by the OpenXR loader to not use the system default OpenXR runtime but instead redirect to the Holographic Remoting OpenXR runtime. OpenXr NuGet パッケージを使用する場合、ファイルの RemotingXR.jsは、コンパイル時に出力フォルダーに自動的にコピーされます。 OpenXR ランタイムの選択は、通常、次のようになります。When using the Microsoft.Holographic.Remoting.OpenXr NuGet package the RemotingXR.json file is automatically copied during compilation to the output folder, the OpenXR runtime selection typically looks as follows.

bool EnableRemotingXR() {
    wchar_t executablePath[MAX_PATH];
    if (GetModuleFileNameW(NULL, executablePath, ARRAYSIZE(executablePath)) == 0) {
        return false;
    }
    
    std::filesystem::path filename(executablePath);
    filename = filename.replace_filename("RemotingXR.json");

    if (std::filesystem::exists(filename)) {
        SetEnvironmentVariableW(L"XR_RUNTIME_JSON", filename.c_str());
            return true;
        }

    return false;
}

Holographic Remoting 拡張機能を使用して XrInstance を作成するCreate XrInstance with Holographic Remoting Extension

一般的な OpenXR アプリの最初の手順は、OpenXR extensions を選択して XrInstance を作成することです。The first step a typical OpenXR app is supposed to do is to select OpenXR extensions and create an XrInstance. OpenXR core 仕様では、リモート処理固有の API は提供されません。The OpenXR core specification doesn't provide any remoting specific API. そのため、Holographic Remoting では、という名前の独自の OpenXR 拡張機能が導入さ XR_MSFT_holographic_remoting れています。For that reason Holographic Remoting introduces its own OpenXR extension named XR_MSFT_holographic_remoting. XrCreateInstance を呼び出したときに、 XR_MSFT_HOLOGRAPHIC_REMOTING_EXTENSION_NAME が XrInstanceCreateInfo に含まれていることを確認します。Ensure that when you call xrCreateInstance the XR_MSFT_HOLOGRAPHIC_REMOTING_EXTENSION_NAME is included in the XrInstanceCreateInfo.

ヒント

既定では、アプリのレンダリングされたコンテンツは、HoloLens 2 または Windows Mixed Reality ヘッドセットで実行されている Holographic リモート処理プレーヤーにのみストリーミングされます。By default the rendered content of your app is only streamed to the Holographic Remoting player either running on a HoloLens 2 or on a Windows Mixed Reality headsets. また、レンダリングされたコンテンツをリモート PC に表示するために、ウィンドウのスワップチェーンを使用して、Holographic リモート処理には、という名前の2つ目の OpenXR 拡張機能が用意されて XR_MSFT_holographic_remoting_frame_mirroring います。To also display the rendered content on the remote PC, via a swap-chain of a window for instance, Holographic Remoting provides a second OpenXR extension named XR_MSFT_holographic_remoting_frame_mirroring. また、この機能を使用する場合は、を使用してこの拡張機能を有効にし XR_MSFT_HOLOGRAPHIC_REMOTING_FRAME_MIRRORING_EXTENSION_NAME ます。Ensure to also enable this extension using XR_MSFT_HOLOGRAPHIC_REMOTING_FRAME_MIRRORING_EXTENSION_NAME in case you want to use that functionality.

重要

Holographic Remoting OpenXR extension API の詳細については、 Holographic リモート処理のサンプル github リポジトリに記載されている仕様を確認してください。To learn about the Holographic Remoting OpenXR extension API, check out the specification which can be found in the Holographic Remoting samples github repository.

デバイスへの接続Connect to the device

リモートアプリによって XrInstance が作成され、xrGetSystem 経由で XrSystemId に照会された後、プレーヤーデバイスへの接続を確立できます。After your remote app has created the XrInstance and queried the XrSystemId via xrGetSystem a connection to the player device can be established.

警告

Holographic Remoting OpenXR ランタイムは、接続が確立された後に、ビュー構成や環境 blend モードなどのデバイス固有のデータのみを提供できます。The Holographic Remoting OpenXR runtime is only able to provide device specific data such as view configurations or environment blend modes after a connection has been established. xrEnumerateViewConfigurationsxrEnumerateViewConfigurationViewsxrGetViewConfigurationPropertiesxrEnumerateEnvironmentBlendModes 、およびで xrGetSystemProperties は、既定値が使用されます。これは通常、HoloLens 2 で実行されているプレーヤーに接続してから完全に接続する場合に使用するものと一致します。xrEnumerateViewConfigurations, xrEnumerateViewConfigurationViews, xrGetViewConfigurationProperties, xrEnumerateEnvironmentBlendModes, and xrGetSystemProperties will give you default values, matching what you would typically get if you connect to a player running on a HoloLens 2, before being fully connected. 接続が確立される前に、これらのメソッドを呼び出さないことを強くお勧めします。It is strongly recommended to not call these methods before a connection has been established. 提案は、XrSession が正常に作成され、セッション状態が少なくとも XR_SESSION_STATE_READY になった後に、これらのメソッドで使用されます。The suggestion is used these methods after the XrSession has been successfully created and the session state is at least XR_SESSION_STATE_READY.

最大ビットレート、オーディオ対応、ビデオコーデック、深度バッファーストリーム解像度などの一般的なプロパティは、次のようにを使用して構成でき xrRemotingSetContextPropertiesMSFT ます。General properties such as max bitrate, audio enabled, video codec, or depth buffer stream resolution can be configured via xrRemotingSetContextPropertiesMSFT as follows.

XrRemotingRemoteContextPropertiesMSFT contextProperties;
contextProperties = XrRemotingRemoteContextPropertiesMSFT{static_cast<XrStructureType>(XR_TYPE_REMOTING_REMOTE_CONTEXT_PROPERTIES_MSFT)};
contextProperties.enableAudio = false;
contextProperties.maxBitrateKbps = 20000;
contextProperties.videoCodec = XR_REMOTING_VIDEO_CODEC_H265_MSFT;
contextProperties.depthBufferStreamResolution = XR_REMOTING_DEPTH_BUFFER_STREAM_RESOLUTION_HALF_MSFT;
xrRemotingSetContextPropertiesMSFT(m_instance.Get(), m_systemId, &contextProperties);

接続は、次の2つの方法のいずれかで実行できます。The connection can be done in one of two ways.

  1. リモートアプリは、デバイスで実行されているプレーヤーに接続します。The remote app connects to the player running on the device.
  2. デバイスで実行されているプレーヤーは、リモートアプリに接続します。The player running on the device connects to the remote app.

リモートアプリからプレーヤーデバイスへの接続を確立するには、 xrRemotingConnectMSFT 構造体を介してホスト名とポートを指定するメソッドを呼び出し XrRemotingConnectInfoMSFT ます。To establish a connection from the remote app to the player device call the xrRemotingConnectMSFT method specifying the hostname and port via the XrRemotingConnectInfoMSFT structure. Holographic リモート処理プレーヤーによって使用されるポートは 8265 です。The port used by the Holographic Remoting Player is 8265.

XrRemotingConnectInfoMSFT connectInfo{static_cast<XrStructureType>(XR_TYPE_REMOTING_CONNECT_INFO_MSFT)};
connectInfo.remoteHostName = "192.168.x.x";
connectInfo.remotePort = 8265;
connectInfo.secureConnection = false;
xrRemotingConnectMSFT(m_instance.Get(), m_systemId, &connectInfo);

リモートアプリでの着信接続のリッスンは、メソッドを呼び出すことによって行うことができ xrRemotingListenMSFT ます。Listening for incoming connections on the remote app can be done by calling the xrRemotingListenMSFT method. ハンドシェイクポートとトランスポートポートの両方を構造体を使用して指定でき XrRemotingListenInfoMSFT ます。Both the handshake port and transport port can be specified via the XrRemotingListenInfoMSFT structure. ハンドシェイクポートは、初期ハンドシェイクに使用されます。The handshake port is used for the initial handshake. データは、トランスポートポートを介して送信されます。The data is then sent over the transport port. 既定では、 8265 および 8266 が使用されます。By default 8265 and 8266 are used.

XrRemotingListenInfoMSFT listenInfo{static_cast<XrStructureType>(XR_TYPE_REMOTING_LISTEN_INFO_MSFT)};
listenInfo.listenInterface = "0.0.0.0";
listenInfo.handshakeListenPort = 8265;
listenInfo.transportListenPort = 8266;
listenInfo.secureConnection = false;
xrRemotingListenMSFT(m_instance.Get(), m_systemId, &listenInfo);

またはを呼び出すと、接続状態が切断される必要があり xrRemotingConnectMSFT xrRemotingListenMSFT ます。The connection state must be disconnected when you call xrRemotingConnectMSFT or xrRemotingListenMSFT. XrInstance を作成し、経由で XrSystemId に対してクエリを実行した後、いつでも接続状態を取得でき xrRemotingGetConnectionStateMSFT ます。You can get the connection state at any point after you have created an XrInstance and queried for the XrSystemId via xrRemotingGetConnectionStateMSFT.

XrRemotingConnectionStateMSFT connectionState;
xrRemotingGetConnectionStateMSFT(m_instance.Get(), m_systemId, &connectionState, nullptr);

使用できる接続状態は次のとおりです。Available connection states are:

  • XR_REMOTING_CONNECTION_STATE_DISCONNECTED_MSFTXR_REMOTING_CONNECTION_STATE_DISCONNECTED_MSFT
  • XR_REMOTING_CONNECTION_STATE_CONNECTING_MSFTXR_REMOTING_CONNECTION_STATE_CONNECTING_MSFT
  • XR_REMOTING_CONNECTION_STATE_CONNECTED_MSFTXR_REMOTING_CONNECTION_STATE_CONNECTED_MSFT

重要

xrRemotingConnectMSFT``````xrRemotingListenMSFTxrCreateSession を介して XrSession を作成する前に、またはを呼び出す必要があります。xrRemotingConnectMSFT or xrRemotingListenMSFT must be called before trying to create a XrSession via xrCreateSession. 接続状態がのときに XrSession を作成しようとすると、 XR_REMOTING_CONNECTION_STATE_DISCONNECTED_MSFT セッションの作成は成功しますが、セッションの状態は直ちに XR_SESSION_STATE_LOSS_PENDING に移行されます。If you try to create a XrSession while the connection state is XR_REMOTING_CONNECTION_STATE_DISCONNECTED_MSFT the session creation will succeed but the session state will immediately transition to XR_SESSION_STATE_LOSS_PENDING.

Holographic リモート処理の実装では xrCreateSession 、接続が確立されるのを待機できます。Holographic Remoting's implementation of xrCreateSession supports waiting for a connection to be established. またはを呼び出して、を呼び出すことができ xrRemotingConnectMSFT xrRemotingListenMSFT ます。この呼び出しはブロックされ、接続が確立されるまで待機します。You can call xrRemotingConnectMSFT or xrRemotingListenMSFT immediately followed by a call to, which will block and wait for a connection to be established. タイムアウトは10秒に固定されています。The timeout is fixed to 10 seconds. この時間内に接続を確立できる場合、XrSession の作成は成功し、セッションの状態は XR_SESSION_STATE_READY に移行されます。If a connection can be established within this time the XrSession creation will succeed and the session state will transition to XR_SESSION_STATE_READY. 接続を確立できない場合は、セッションの作成も成功しますが、直ちに XR_SESSION_STATE_LOSS_PENDING に移行されます。In case no connection can be established the session creation also succeeds but immediately transitions to XR_SESSION_STATE_LOSS_PENDING.

一般に、接続状態は XrSession 状態になります。In general, the connection state is couple with the XrSession state. 接続状態の変更は、セッションの状態にも影響します。Any change to the connection state also affects the session state. たとえば、接続状態をからに切り替えた場合、 XR_REMOTING_CONNECTION_STATE_CONNECTED_MSFT XR_REMOTING_CONNECTION_STATE_DISCONNECTED_MSFT セッション状態は XR_SESSION_STATE_LOSS_PENDING にも移行します。For instance, if the connection state switches from XR_REMOTING_CONNECTION_STATE_CONNECTED_MSFT to XR_REMOTING_CONNECTION_STATE_DISCONNECTED_MSFT the session state will transition to XR_SESSION_STATE_LOSS_PENDING as well.

リモート処理固有のイベントの処理Handling Remoting specific events

Holographic Remoting OpenXR runtime は、接続の状態を監視するために重要な3つのイベントを公開します。The Holographic Remoting OpenXR runtime exposes three events, which are important to monitor the state of a connection.

  1. XR_TYPE_REMOTING_EVENT_DATA_CONNECTED_MSFT: デバイスへの接続が正常に確立されたときにトリガーされます。XR_TYPE_REMOTING_EVENT_DATA_CONNECTED_MSFT: Triggered when a connection to the device has been successfully established.
  2. XR_TYPE_REMOTING_EVENT_DATA_DISCONNECTED_MSFT: 確立された接続が閉じられた場合、または接続が確立できなかった場合にトリガーされます。XR_TYPE_REMOTING_EVENT_DATA_DISCONNECTED_MSFT: Triggered if an established connection is closed or a connection couldn't be established.
  3. XR_TYPE_REMOTING_EVENT_DATA_LISTENING_MSFT: 受信接続のリッスンが開始されたとき。XR_TYPE_REMOTING_EVENT_DATA_LISTENING_MSFT: When listening for incoming connections starts.

これらのイベントはキューに配置され、リモートアプリは定期的 via を使用してキューから読み取る必要があり xrPollEvent ます。These events are placed in a queue and your remote app must read from the queue with regularity via xrPollEvent.

auto pollEvent = [&](XrEventDataBuffer& eventData) -> bool {
    eventData.type = XR_TYPE_EVENT_DATA_BUFFER;
    eventData.next = nullptr;
    return CHECK_XRCMD(xrPollEvent(m_instance.Get(), &eventData)) == XR_SUCCESS;
};

XrEventDataBuffer eventData{};
while (pollEvent(eventData)) {
    switch (eventData.type) {
    
    ...
    
    case XR_TYPE_REMOTING_EVENT_DATA_LISTENING_MSFT: {
        DEBUG_PRINT("Holographic Remoting: Listening on port %d",
                    reinterpret_cast<const XrRemotingEventDataListeningMSFT*>(&eventData)->listeningPort);
        break;
    }
    case XR_TYPE_REMOTING_EVENT_DATA_CONNECTED_MSFT: {
        DEBUG_PRINT("Holographic Remoting: Connected.");
        break;
    }
    case XR_TYPE_REMOTING_EVENT_DATA_DISCONNECTED_MSFT: {
        DEBUG_PRINT("Holographic Remoting: Disconnected - Reason: %d",
                    reinterpret_cast<const XrRemotingEventDataDisconnectedMSFT*>(&eventData)->disconnectReason);
        break;
    }
}

ストリーミングされるコンテンツをローカルでプレビューするPreview streamed content locally

デバイスに送信されたのと同じコンテンツをリモートアプリで表示するには、 XR_MSFT_holographic_remoting_frame_mirroring 拡張機能を使用できます。To display the same content in the remote app that is sent to the device the XR_MSFT_holographic_remoting_frame_mirroring extension can be used. この拡張機能では、次のように、XrFrameEndInfo にチェーンされていないを使用して、xrEndFrame にテクスチャを送信でき XrRemotingFrameMirrorImageInfoMSFT ます。With this extension, you can submit a texture to xrEndFrame by using the XrRemotingFrameMirrorImageInfoMSFT that isn't chained to the XrFrameEndInfo as follows.

XrFrameEndInfo frameEndInfo{XR_TYPE_FRAME_END_INFO};
...

XrRemotingFrameMirrorImageD3D11MSFT mirrorImageD3D11{
    static_cast<XrStructureType>(XR_TYPE_REMOTING_FRAME_MIRROR_IMAGE_D3D11_MSFT)};
mirrorImageD3D11.texture = m_window->GetNextSwapchainTexture();

XrRemotingFrameMirrorImageInfoMSFT mirrorImageEndInfo{
    static_cast<XrStructureType>(XR_TYPE_REMOTING_FRAME_MIRROR_IMAGE_INFO_MSFT)};
mirrorImageEndInfo.image = reinterpret_cast<const XrRemotingFrameMirrorImageBaseHeaderMSFT*>(&mirrorImageD3D11);

frameEndInfo.next = &mirrorImageEndInfo;

xrEndFrame(m_session.Get(), &frameEndInfo);

m_window->PresentSwapchain();

上の例では、DX11 のスワップチェーンテクスチャを使用して、xrEndFrame の呼び出しの直後にウィンドウを表示します。The example above uses a DX11 swap-chain texture and presents the window immediately after the call to xrEndFrame. 使用量はスワップチェーンテクスチャに限定されておらず、追加の GPU 同期は必要ありません。The usage isn't restricted to swap-chain textures and no additional GPU synchronization is required. 使用法と制約の詳細については、 拡張機能の仕様を確認してください。For details on usage and constraints check out the extension specification. リモートアプリで DX12 を使用している場合は、XrRemotingFrameMirrorImageD3D11MSFT ではなく XrRemotingFrameMirrorImageD3D12MSFT を使用します。If your remote app is using DX12 use XrRemotingFrameMirrorImageD3D12MSFT instead of XrRemotingFrameMirrorImageD3D11MSFT.

参照See Also