Pisanie aplikacji zdalnej holograficznej za pomocą interfejsu API OpenXR

Jeśli jesteś nowym użytkownikm holographic Remoting, możesz przeczytać nasze omówienie.

Ważne

W tym dokumencie opisano tworzenie aplikacji zdalnej dla zestawów słuchawkowych HoloLens 2 i Windows Mixed Reality przy użyciu interfejsu API OpenXR. Aplikacje zdalne dla urządzenia HoloLens (1. generacji) muszą używać pakietu NuGet w wersji 1.x.x. Oznacza to, że aplikacje zdalne napisane dla HoloLens 2 nie są zgodne z urządzeniem HoloLens 1 i odwrotnie. Dokumentację urządzenia HoloLens 1 można znaleźć tutaj.

Aplikacje Holographic Remoting mogą przesyłać strumieniowo zdalnie renderowaną zawartość do HoloLens 2 i Windows Mixed Reality immersywnych zestawów nagłownych. Możesz również uzyskać dostęp do większej liczby zasobów systemowych i zintegrować zdalne widoki immersyjne z istniejącym oprogramowaniem komputerowym. Aplikacja zdalna odbiera strumień danych wejściowych z HoloLens 2, renderuje zawartość w wirtualnym widoku immersywnym oraz przesyła ramki zawartości z powrotem do HoloLens 2. Połączenie jest nawiązywane przy użyciu standardowego sieci Wi-Fi. Holographic Remoting jest dodawany do aplikacji klasycznej lub uniwersalnej systemu Windows za pośrednictwem pakietu NuGet. Wymagany jest dodatkowy kod, który obsługuje połączenie i renderuje w widoku immersywnym. Typowe połączenie zdalnie będzie miało opóźnienie nawet 50 ms. Aplikacja odtwarzacza może zgłaszać opóźnienie w czasie rzeczywistym.

Cały kod na tej stronie i roboczych projektów można znaleźć w repozytorium GitHub przykładów holographic Remoting.

Wymagania wstępne

Dobrym punktem wyjścia jest działająca aplikacja klasyczna oparta na protokole OpenXR lub uwP. Aby uzyskać szczegółowe informacje, zobacz Wprowadzenie do programu OpenXR.

Ważne

Każda aplikacja korzystająca z komunikacji zdalnie holograficznej powinna być utworzona w celu korzystania z apartamentu wielowątkowego. Korzystanie z jednego wątkowego mieszkania jest obsługiwane, ale doprowadzi do nie optymalnej wydajności i ewentualnie zacinania podczas odtwarzania. W przypadku korzystania z C++/ WinRT winrt::init_apartment mieszkanie wielowątkowa jest ustawieniem domyślnym.

Pobieranie pakietu NuGet Holographic Remoting

Poniższe kroki są wymagane do dodania pakietu NuGet do projektu w programie Visual Studio.

  1. Otwórz projekt w programie Visual Studio.
  2. Kliknij prawym przyciskiem myszy węzeł projektu i wybierz polecenie Zarządzaj pakietami NuGet...
  3. W wyświetlonym panelu wybierz pozycję Przeglądaj , a następnie wyszukaj ciąg "Holographic Remoting".
  4. Wybierz pozycję Microsoft.Holographic.Remoting.OpenXr, a następnie upewnij się, że wybrano najnowszą wersję 2.x.x , a następnie wybierz pozycję Zainstaluj.
  5. Jeśli zostanie wyświetlone okno dialogowe Podgląd , wybierz przycisk OK.
  6. Wybierz pozycję Akceptuję , gdy pojawi się okno dialogowe umowy licencyjnej.
  7. Powtórz kroki od 3 do 6 dla następujących pakietów NuGet: OpenXR.Headers, OpenXR.Loader

Uwaga

Wersja 1.x pakietu NuGet jest nadal dostępna dla deweloperów, którzy chcą kierować urządzenie HoloLens 1. Aby uzyskać szczegółowe informacje, zobacz Add Holographic Remoting (HoloLens (1st gen))).

Wybieranie środowiska uruchomieniowego Holographic Remoting OpenXR

Pierwszym krokiem, który należy wykonać w aplikacji zdalnej, jest wybranie środowiska uruchomieniowego OpenXR Holographic Remoting, które jest częścią pakietu NuGet Microsoft.Holographic.Remoting.OpenXr. Możesz to zrobić, ustawiając zmienną XR_RUNTIME_JSON środowiskową na ścieżkę pliku RemotingXR.json w aplikacji. Ta zmienna środowiskowa jest używana przez moduł ładujący OpenXR, aby nie używać domyślnego środowiska uruchomieniowego OpenXR systemu, ale zamiast tego przekierowuje do środowiska uruchomieniowego OpenXR Holographic Remoting. W przypadku korzystania z pakietu NuGet Microsoft.Holographic.Remoting.OpenXr plik RemotingXR.json jest automatycznie kopiowany podczas kompilacji do folderu wyjściowego, wybór środowiska uruchomieniowego OpenXR zwykle wygląda następująco.

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;
}

Tworzenie wystąpienia XrInstance za pomocą rozszerzenia Holographic Remoting

Pierwsze akcje typowej aplikacji OpenXR należy wykonać, to wybranie rozszerzeń OpenXR i utworzenie wystąpienia XrInstance. Specyfikacja rdzenia OpenXR nie zapewnia żadnego interfejsu API komunikacji zdalniej. Z tego powodu holographic Remoting wprowadza własne rozszerzenie OpenXR o nazwie XR_MSFT_holographic_remoting. Upewnij się, że XR_MSFT_HOLOGRAPHIC_REMOTING_EXTENSION_NAME element znajduje się w wywołaniu XrInstanceCreateInfo wywołania xrCreateInstance.

Porada

Domyślnie renderowana zawartość aplikacji jest przesyłana strumieniowo tylko do odtwarzacza Holographic Remoting uruchomionego na HoloLens 2 lub na zestawach nagłownych Windows Mixed Reality. Aby również wyświetlić renderowaną zawartość na komputerze zdalnym, za pośrednictwem łańcucha wymiany okna, na przykład Holographic Remoting zapewnia drugie rozszerzenie OpenXR o nazwie XR_MSFT_holographic_remoting_frame_mirroring. Upewnij się również, że to rozszerzenie jest włączone w XR_MSFT_HOLOGRAPHIC_REMOTING_FRAME_MIRRORING_EXTENSION_NAME przypadku, gdy chcesz używać tej funkcji.

Ważne

Aby dowiedzieć się więcej o interfejsie API rozszerzenia OpenXR holographic Remoting, zapoznaj się ze specyfikacją , którą można znaleźć w repozytorium GitHub przykładów holographic Remoting.

Nawiązywanie połączenia z urządzeniem

Po utworzeniu klasy XrInstance przez aplikację zdalną i zapytaniu o identyfikator XrSystemId za pośrednictwem elementu xrGetSystem można nawiązać połączenie z urządzeniem odtwarzacza.

Ostrzeżenie

Środowisko uruchomieniowe Holographic Remoting OpenXR może dostarczać tylko dane specyficzne dla urządzenia, takie jak konfiguracje widoku lub tryby mieszania środowiska po nawiązaniu połączenia. xrEnumerateViewConfigurations, , xrEnumerateViewConfigurationViewsxrGetViewConfigurationProperties, xrEnumerateEnvironmentBlendModesi xrGetSystemProperties daje wartości domyślne, pasujące do tego, co zwykle uzyskuje się w przypadku nawiązania połączenia z graczem uruchomionym na HoloLens 2, przed pełnym połączeniem. Zdecydowanie zaleca się, aby nie wywoływać tych metod przed nawiązaniem połączenia. Sugestia ta jest używana po pomyślnym utworzeniu sesji XrSession, a stan sesji jest co najmniej XR_SESSION_STATE_READY.

Ogólne właściwości, takie jak maksymalna szybkość transmisji bitów, włączona obsługa audio, koder-dekoder wideo lub rozdzielczość strumienia buforu głębokości, można skonfigurować w xrRemotingSetContextPropertiesMSFT następujący sposób.

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);

Połączenie można wykonać na jeden z dwóch sposobów.

  1. Aplikacja zdalna łączy się z odtwarzaczem uruchomionym na urządzeniu.
  2. Odtwarzacz uruchomiony na urządzeniu łączy się z aplikacją zdalną.

Aby nawiązać połączenie z aplikacji zdalnej z urządzeniem odtwarzacza, wywołaj xrRemotingConnectMSFT metodę określającą nazwę hosta i port za pośrednictwem XrRemotingConnectInfoMSFT struktury. Port używany przez Holographic Remoting Player to 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);

Nasłuchiwanie połączeń przychodzących w aplikacji zdalnej można wykonać przez wywołanie xrRemotingListenMSFT metody . Zarówno port uzgadniania, jak i port transportowy można określić za pośrednictwem XrRemotingListenInfoMSFT struktury. Port uzgadniania jest używany do początkowego uzgadniania. Dane są następnie wysyłane za pośrednictwem portu transportowego. Domyślnie używane są 8265 i 8266 .

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);

Stan połączenia musi zostać rozłączony po wywołaniu metody xrRemotingConnectMSFT lub xrRemotingListenMSFT. Stan połączenia można uzyskać w dowolnym momencie po utworzeniu klasy XrInstance i zapytaniu o identyfikator XrSystemId za pośrednictwem polecenia xrRemotingGetConnectionStateMSFT.

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

Dostępne stany połączeń to:

  • XR_REMOTING_CONNECTION_STATE_DISCONNECTED_MSFT
  • XR_REMOTING_CONNECTION_STATE_CONNECTING_MSFT
  • XR_REMOTING_CONNECTION_STATE_CONNECTED_MSFT

Ważne

xrRemotingConnectMSFT lub xrRemotingListenMSFT musi być wywoływany przed próbą utworzenia rozszerzenia XrSession za pomocą polecenia xrCreateSession. Jeśli spróbujesz utworzyć sesję XrSession, gdy stan połączenia to XR_REMOTING_CONNECTION_STATE_DISCONNECTED_MSFT tworzenie sesji zakończy się pomyślnie, ale stan sesji zostanie natychmiast przeniesiony do XR_SESSION_STATE_LOSS_PENDING.

Holographic Remoting implementacji xrCreateSession obsługuje oczekiwanie na nawiązanie połączenia. Możesz wywołać xrRemotingConnectMSFT metodę lub xrRemotingListenMSFT natychmiast nawiązać połączenie xrCreateSessionz usługą , które zablokuje połączenie i zaczeka na nawiązanie połączenia. Limit czasu z parametrem xrRemotingConnectMSFT jest stały do 10 sekund i jest nieograniczony z wartością xrRemotingListenMSFT. Jeśli w tym czasie można nawiązać połączenie, tworzenie XrSession zakończy się pomyślnie, a stan sesji zmieni się na XR_SESSION_STATE_READY. Jeśli nie można ustanowić połączenia, tworzenie sesji również zakończy się pomyślnie, ale natychmiast przechodzi do XR_SESSION_STATE_LOSS_PENDING.

Ogólnie rzecz biorąc, stan połączenia jest powiązany ze stanem XrSession. Każda zmiana stanu połączenia również wpływa na stan sesji. Jeśli na przykład stan połączenia zmieni się z XR_REMOTING_CONNECTION_STATE_CONNECTED_MSFT na XR_REMOTING_CONNECTION_STATE_DISCONNECTED_MSFT stan sesji, zmieni się również na XR_SESSION_STATE_LOSS_PENDING.

Obsługa komunikacji zdalniej określonych zdarzeń

Środowisko uruchomieniowe Holographic Remoting OpenXR uwidacznia trzy zdarzenia, które są ważne do monitorowania stanu połączenia.

  1. XR_TYPE_REMOTING_EVENT_DATA_CONNECTED_MSFT: wyzwalane po pomyślnym nawiązaniu połączenia z urządzeniem.
  2. XR_TYPE_REMOTING_EVENT_DATA_DISCONNECTED_MSFT: wyzwolony, jeśli nawiązane połączenie jest zamknięte lub nie można nawiązać połączenia.
  3. XR_TYPE_REMOTING_EVENT_DATA_LISTENING_MSFT: Podczas nasłuchiwania połączeń przychodzących rozpoczyna się.

Te zdarzenia są umieszczane w kolejce, a aplikacja zdalna musi odczytywać z kolejki z regularnością za pośrednictwem metody 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;
	}
}

Podgląd zawartości przesyłanej strumieniowo lokalnie

Aby wyświetlić tę samą zawartość w aplikacji zdalnej, która jest wysyłana do urządzenia, XR_MSFT_holographic_remoting_frame_mirroring można użyć rozszerzenia. Dzięki temu rozszerzeniu można przesłać teksturę do elementu xrEndFrame, używając elementu XrRemotingFrameMirrorImageInfoMSFT , który nie jest w łańcuchu do elementu XrFrameEndInfo w następujący sposób.

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();

W powyższym przykładzie użyto tekstury łańcucha wymiany DX11 i przedstawia okno bezpośrednio po wywołaniu elementu xrEndFrame. Użycie nie jest ograniczone do zamiany tekstur łańcuchowych. Ponadto nie jest wymagana żadna dodatkowa synchronizacja procesora GPU. Aby uzyskać szczegółowe informacje na temat użycia i ograniczeń, zapoznaj się ze specyfikacją rozszerzenia. Jeśli aplikacja zdalna korzysta z rozszerzenia DX12, użyj elementu XrRemotingFrameMirrorImageD3D12MSFT zamiast XrRemotingFrameMirrorImageD3D11MSFT.

Opcjonalnie: Niestandardowe kanały danych

Począwszy od wersji 2.5.0, niestandardowe kanały danych mogą być używane z interfejsem API OpenXR do wysyłania danych użytkownika za pośrednictwem już ustanowionego połączenia komunikacji wirtualnej. Aby uzyskać więcej informacji, zobacz Niestandardowe kanały danych za pomocą interfejsu API OpenXR.

Opcjonalnie: Mowa

Począwszy od wersji 2.6.0, XR_MSFT_holographic_remoting_speech rozszerzenie umożliwia aplikacji zdalnej reagowanie na polecenia mowy wykryte przez aplikację odtwarzacza za pomocą interfejsu API OpenXR.

[! WAŻNE] Szczegółową specyfikację można znaleźć w repozytorium GitHub przykładów holographic Remoting.

Aby zainicjować rozpoznawanie mowy w aplikacji odtwarzacza, aplikacja zdalna może wywołać metodę xrInitializeRemotingSpeechMSFT. To wywołanie przesyła parametry inicjowania mowy, które składają się z języka, słownika fraz i zawartości pliku gramatycznego do aplikacji odtwarzacza.

Uwaga

Przed wersją 2.6.1 rozpoznawanie mowy musi zostać zainicjowane tylko raz na .XrSession

Jeśli tworzenie aparatu rozpoznawania mowy zakończyło się pomyślnie, zgodnie ze XR_TYPE_EVENT_DATA_REMOTING_SPEECH_RECOGNIZER_STATE_CHANGED_MSFT zdarzeniem, aplikacja zdalna zostanie powiadomiona o wygenerowaniu wyniku rozpoznawania mowy w aplikacji odtwarzacza. Struktura XrEventDataRemotingSpeechRecognizerStateChangedMSFT zdarzeń jest umieszczana w kolejce zdarzeń po zmianie stanu aparatu rozpoznawania mowy po stronie gracza.

XrRemotingSpeechRecognizerStateMSFT definiuje wszystkie możliwe stany rozpoznawania mowy po stronie odtwarzacza, a XrEventDataRemotingSpeechRecognizedMSFT struktura zdarzeń jest umieszczana w kolejce zdarzeń, jeśli rozpoznawanie mowy po stronie odtwarzacza ma rozpoznaną frazę. Gdy aplikacja zdalna zostanie powiadomiona o rozpoznanej frazie, może pobrać rozpoznaną frazę, wywołując metodę xrRetrieveRemotingSpeechRecognizedTextMSFT.

Uwaga

Jest XrRemotingSpeechRecognitionConfidenceMSFT to bezpośrednie mapowanie wyliczenia SpeechRecognitionConfidence zwrócone z wynikiem rozpoznawania mowy przez interfejs API rozpoznawania mowy systemu Windows.

Opcjonalnie: Synchronizacja systemu współrzędnych

Począwszy od wersji 2.7.0, synchronizacja systemu współrzędnych może służyć do wyrównania danych przestrzennych między odtwarzaczem a aplikacją zdalną. Aby uzyskać więcej informacji, zobacz Koordynowanie synchronizacji systemu z Holographic Remoting Overview.

Zobacz też