Создание удаленного приложения holographic с удаленным взаимодействием с помощью API ОпенксрWriting a Holographic Remoting remote app using the OpenXR API

Важно!

В этом документе описывается создание удаленного приложения для головных телефонов HoloLens 2 и Windows Mixed Reality с помощью API опенкср.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. 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.

В приложениях с удаленным взаимодействием можно потокировать удаленно визуализированное содержимое в HoloLens 2 и впечатляющие головные гарнитуры Windows Mixed Reality.Holographic Remoting apps can stream remotely rendered content to HoloLens 2 and Windows Mixed Reality immersive headsets. Вы также можете получить доступ к дополнительным системным ресурсам и интегрировать удаленные иммерсивное представления в имеющееся программное обеспечение для настольного ПК.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 удаленное взаимодействие добавляется в приложение для настольных систем или UWP через пакет NuGet.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.

Весь код на этой странице и рабочих проектах можно найти в репозитории GitHub с примерами удаленного взаимодействия.All code on this page and working projects can be found in the Holographic Remoting samples github repository.

Предварительные требованияPrerequisites

Хорошей отправной точкой является работающая Рабочая станция или приложение UWP на основе Опенкср.A good starting point is a working OpenXR based Desktop or UWP app. Дополнительные сведения см. в статье Приступая к работе с опенкср.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.

Получение пакета NuGet для удаленного взаимодействия с holographicGet the Holographic Remoting NuGet package

Чтобы добавить пакет NuGet в проект в Visual Studio, необходимо выполнить следующие действия.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. На появившейся панели нажмите кнопку Обзор и выполните поиск по фразе "удаленное взаимодействие".In the panel that appears, select Browse and then search for "Holographic Remoting".
  4. Выберите Microsoft. Holographic. Remoting. опенкср, выберите последнюю версию 2. x. x и нажмите кнопку установить.Select Microsoft.Holographic.Remoting.OpenXr, ensure to pick the latest 2.x.x version and select Install.
  5. Если отображается диалоговое окно Предварительный просмотр , нажмите кнопку ОК.If the Preview dialog appears, select OK.
  6. Выберите я принимаю , когда появится диалоговое окно Лицензионное соглашение.Select I Accept when the license agreement dialog pops up.
  7. Повторите шаги 3 – 6 для следующих пакетов NuGet: Опенкср. Headers, Опенкср. Loader.Repeat the steps 3 to 6 for the following NuGet Packages: OpenXR.Headers, OpenXR.Loader

Примечание

Версия 1. x. x пакета NuGet по-прежнему доступна для разработчиков, желающих выбрать HoloLens 1.Version 1.x.x of the NuGet package is still available for developers who want to target HoloLens 1. Дополнительные сведения см. в разделе Добавление удаленного взаимодействия holographic (HoloLens (1-й общий)).For details see Add Holographic Remoting (HoloLens (1st gen)).

Выберите среду выполнения Опенкср для удаленного взаимодействия с holographicSelect the Holographic Remoting OpenXR runtime

Первым шагом, который необходимо сделать в удаленном приложении, является выбор среды выполнения Опенкср holographic Remoting, которая является частью пакета NuGet Microsoft. Holographic. Remoting. Опенкср.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. Эта переменная среды используется загрузчиком Опенкср для того, чтобы не использовать системную среду Опенкср по умолчанию, а вместо этого перенаправлять в среду выполнения Опенкср удаленного взаимодействия Holographic.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. При использовании RemotingXR.jsпакета NuGet Microsoft. Holographic. Remoting. Опенкср для файла, который автоматически копируется во время компиляции в выходную папку, выбор среды выполнения Опенкср обычно выглядит следующим образом.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 для удаленного взаимодействияCreate XrInstance with Holographic Remoting Extension

Первым шагом является типичное приложение Опенкср — выбор расширений Опенкср и создание Ксринстанце.The first step a typical OpenXR app is supposed to do is to select OpenXR extensions and create an XrInstance. Спецификация ядра Опенкср не предоставляет API для удаленного взаимодействия.The OpenXR core specification doesn't provide any remoting specific API. По этой причине holographic удаленное взаимодействие вводит собственное расширение Опенкср с именем XR_MSFT_holographic_remoting .For that reason Holographic Remoting introduces its own OpenXR extension named XR_MSFT_holographic_remoting. Убедитесь, что при вызове Ксркреатеинстанце, XR_MSFT_HOLOGRAPHIC_REMOTING_EXTENSION_NAME включенном в ксринстанцекреатеинфо.Ensure that when you call xrCreateInstance the XR_MSFT_HOLOGRAPHIC_REMOTING_EXTENSION_NAME is included in the XrInstanceCreateInfo.

Совет

По умолчанию отображаемое содержимое приложения передается только в поток удаленного взаимодействия holographic, который работает в HoloLens 2 или на гарнитурах Windows Mixed Reality.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. Чтобы отобразить содержимое, подготовленное на удаленном компьютере, с помощью цепочки подкачки окна для экземпляра, то удаленное взаимодействие удаленного взаимодействия предоставляет второе расширение Опенкср с именем 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.

Важно!

Чтобы узнать об 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

После создания удаленного приложения Ксринстанце и запроса Ксрсистемид через Ксржетсистем можно установить подключение к устройству проигрывателя.After your remote app has created the XrInstance and queried the XrSystemId via xrGetSystem a connection to the player device can be established.

Предупреждение

Среда выполнения Опенкср с holographic удаленное взаимодействие может предоставлять данные только для конкретных устройств, такие как конфигурации представления или режимы смешения среды после установки соединения.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. xrEnumerateViewConfigurations,,, xrEnumerateViewConfigurationViews xrGetViewConfigurationProperties xrEnumerateEnvironmentBlendModes и 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. Предложение используется в следующих методах после успешного создания Ксрсессион и состояния сеанса по крайней мере 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);

Соединение может быть выполнено одним из двух способов.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. Состояние подключения можно получить в любой момент после создания Ксринстанце и запроса для Ксрсистемид с помощью 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``````xrRemotingListenMSFTметод или должен быть вызван перед попыткой создать ксрсессион через ксркреатесессион.xrRemotingConnectMSFT or xrRemotingListenMSFT must be called before trying to create a XrSession via xrCreateSession. Если вы попытаетесь создать Ксрсессион, а состояние соединения — 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. Если подключение может быть установлено в течение этого времени, создание Ксрсессион будет продолжено, а состояние сеанса будет перенесено в 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.

Как правило, соединение имеет состояние Ксрсессион.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

Среда выполнения Опенкср с удаленным взаимодействием предоставляет три события, которые важны для отслеживания состояния соединения.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.

Эти события помещаются в очередь, и удаленное приложение должно считывать данные из очереди с регулярным использованием через 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. С помощью этого расширения можно отправить текстуру в Ксрендфраме, используя объект 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 и представление окна сразу после вызова Ксрендфраме.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