Écriture d’une application holographique à distance à distance à l’aide de l’API OpenXR

Si vous débutez avec Holographic Remoting, vous pouvez lire notre vue d’ensemble.

Important

Ce document décrit la création d’une application distante pour les casques HoloLens 2 et Windows Mixed Reality à l’aide de l’API OpenXR. Les applications distantes pour HoloLens (1ère génération) doivent utiliser le package NuGet version 1.x.x. Cela implique que les applications distantes écrites pour HoloLens 2 ne sont pas compatibles avec HoloLens 1 et vice versa. La documentation relative à HoloLens 1 est disponible ici.

Les applications holographiques de communication à distance peuvent diffuser du contenu rendu à distance vers HoloLens 2 et Windows Mixed Reality casques immersifs. Vous pouvez également accéder à d’autres ressources système et intégrer des vues immersives à distance dans un logiciel PC de bureau existant. Une application distante reçoit un flux de données d’entrée de HoloLens 2, affiche le contenu dans une vue immersive virtuelle et retransit les trames de contenu vers HoloLens 2. La connexion s’effectue à l’aide d’une connexion Wi-Fi standard. La communication à distance holographique est ajoutée à une application de bureau ou UWP via un paquet NuGet. Un code supplémentaire est nécessaire pour gérer la connexion et le rendu dans une vue immersive. Une connexion de communication à distance classique a une latence de 50 ms. L’application lecteur peut signaler la latence en temps réel.

Tout le code de cette page et les projets de travail se trouvent dans le référentiel github d’exemples holographiques de communication à distance.

Prérequis

Un bon point de départ est une application de bureau ou UWP basée sur OpenXR. Pour plus d’informations , consultez Prise en main d’OpenXR.

Important

Toute application utilisant holographique Remoting doit être créée pour utiliser un appartement multithread. L’utilisation d’un appartement monothread est prise en charge, mais entraîne des performances sous-optimales et peut-être un bégaiement pendant la lecture. Lorsque vous utilisez C++/WinRT winrt::init_apartment un appartement multithread est la valeur par défaut.

Obtenir le package NuGet de communication à distance holographique

Les étapes suivantes sont requises pour ajouter le package NuGet à un projet dans Visual Studio.

  1. Ouvrez le projet dans Visual Studio.
  2. Cliquez avec le bouton droit sur le nœud du projet et sélectionnez Gérer les packages NuGet...
  3. Dans le panneau qui s’affiche, sélectionnez Parcourir , puis recherchez « Holographic Remoting ».
  4. Sélectionnez Microsoft.Holographic.Remoting.OpenXr, vérifiez que la dernière version 2.x.x est sélectionnée, puis sélectionnez Installer.
  5. Si la boîte de dialogue Aperçu s’affiche, sélectionnez OK.
  6. Sélectionnez J’accepte lorsque la boîte de dialogue contrat de licence s’affiche.
  7. Répétez les étapes 3 à 6 pour les packages NuGet suivants : OpenXR.Headers, OpenXR.Loader

Notes

La version 1.x.x du package NuGet est toujours disponible pour les développeurs qui souhaitent cibler HoloLens 1. Pour plus d’informations, consultez Ajouter une communication à distance holographique (HoloLens (1ère génération)).

Sélectionnez le runtime Holographic Remoting OpenXR

La première étape que vous devez faire dans votre application distante consiste à sélectionner le runtime Holographic Remoting OpenXR, qui fait partie du package NuGet Microsoft.Holographic.Remoting.OpenXr. Pour ce faire, définissez la XR_RUNTIME_JSON variable d’environnement sur le chemin du fichier RemotingXR.json dans votre application. Cette variable d’environnement est utilisée par le chargeur OpenXR pour ne pas utiliser le runtime OpenXR par défaut du système, mais plutôt pour rediriger vers le runtime Holographic Remoting OpenXR. Lorsque vous utilisez le package NuGet Microsoft.Holographic.Remoting.OpenXr, le fichier RemotingXR.json est automatiquement copié pendant la compilation dans le dossier de sortie, la sélection du runtime OpenXR se présente généralement comme suit.

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

Créer XrInstance avec l’extension de communication à distance holographique

Les premières actions qu’une application OpenXR classique doit effectuer sont de sélectionner des extensions OpenXR et de créer une XrInstance. La spécification de base OpenXR ne fournit pas d’API spécifique de communication à distance. Pour cette raison, Holographic Remoting introduit sa propre extension OpenXR nommée XR_MSFT_holographic_remoting. Vérifiez que XR_MSFT_HOLOGRAPHIC_REMOTING_EXTENSION_NAME est inclus dans le XrInstanceCreateInfo de l’appel xrCreateInstance.

Conseil

Par défaut, le contenu rendu de votre application est uniquement diffusé sur le lecteur holographique à distance, soit sur un HoloLens 2, soit sur un casque Windows Mixed Reality. Pour afficher également le contenu rendu sur le PC distant, via une chaîne d’échange d’une fenêtre pour instance, Holographic Remoting fournit une deuxième extension OpenXR nommée XR_MSFT_holographic_remoting_frame_mirroring. Veillez également à activer cette extension en utilisant XR_MSFT_HOLOGRAPHIC_REMOTING_FRAME_MIRRORING_EXTENSION_NAME dans le cas où vous souhaitez utiliser cette fonctionnalité.

Important

Pour en savoir plus sur l’API d’extension Holographic Remoting OpenXR, case activée la spécification qui se trouve dans le référentiel github d’exemples de communication à distance holographiques.

Se connecter à l’appareil

Une fois que votre application distante a créé le XrInstance et interrogé le XrSystemId via xrGetSystem, une connexion à l’appareil lecteur peut être établie.

Avertissement

Le runtime Holographic Remoting OpenXR n’est en mesure de fournir des données spécifiques à l’appareil, telles que des configurations d’affichage ou des modes de fusion d’environnement, qu’après l’établissement d’une connexion. xrEnumerateViewConfigurations, xrEnumerateViewConfigurationViews, xrGetViewConfigurationProperties, xrEnumerateEnvironmentBlendModes, et xrGetSystemProperties vous donnent des valeurs par défaut, correspondant à ce que vous obtiendrez généralement si vous vous connectez à un lecteur exécutant un HoloLens 2, avant d’être entièrement connecté. Il est vivement recommandé de ne pas appeler ces méthodes avant l’établissement d’une connexion. La suggestion est utilisée avec ces méthodes une fois que la XrSession a été créée et que l’état de session est au moins XR_SESSION_STATE_READY.

Les propriétés générales telles que le débit maximal, l’audio activé, le codec vidéo ou la résolution de flux de mémoire tampon de profondeur peuvent être configurées comme xrRemotingSetContextPropertiesMSFT suit.

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

La connexion peut être effectuée de l’une des deux manières suivantes.

  1. L’application distante se connecte au lecteur en cours d’exécution sur l’appareil.
  2. Le lecteur en cours d’exécution sur l’appareil se connecte à l’application distante.

Pour établir une connexion entre l’application distante et l’appareil lecteur, appelez la xrRemotingConnectMSFT méthode spécifiant le nom d’hôte et le port via la XrRemotingConnectInfoMSFT structure. Le port utilisé par le lecteur de communication à distance holographique est 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);

Vous pouvez écouter les connexions entrantes sur l’application distante en appelant la xrRemotingListenMSFT méthode . Le port de négociation et le port de transport peuvent être spécifiés via la XrRemotingListenInfoMSFT structure. Le port d’établissement d’une négociation est utilisé pour la négociation initiale. Les données sont ensuite envoyées via le port de transport. Par défaut , 8265 et 8266 sont utilisés.

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

L’état de connexion doit être déconnecté lorsque vous appelez xrRemotingConnectMSFT ou xrRemotingListenMSFT. Vous pouvez obtenir l’état de connexion à tout moment après avoir créé une XrInstance et interrogé pour le XrSystemId via xrRemotingGetConnectionStateMSFT.

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

Les états de connexion disponibles sont les suivants :

  • XR_REMOTING_CONNECTION_STATE_DISCONNECTED_MSFT
  • XR_REMOTING_CONNECTION_STATE_CONNECTING_MSFT
  • XR_REMOTING_CONNECTION_STATE_CONNECTED_MSFT

Important

xrRemotingConnectMSFT ou xrRemotingListenMSFT doit être appelé avant d’essayer de créer une XrSession via xrCreateSession. Si vous essayez de créer une XrSession alors que l’état de connexion est XR_REMOTING_CONNECTION_STATE_DISCONNECTED_MSFT l’état de la session réussit, mais l’état de session passe immédiatement à XR_SESSION_STATE_LOSS_PENDING.

L’implémentation par Holographic Remoting de xrCreateSession prend en charge l’attente d’une connexion. Vous pouvez appeler xrRemotingConnectMSFT ou xrRemotingListenMSFT immédiatement suivi d’un appel à xrCreateSession, qui bloquera et attendra qu’une connexion soit établie. Le délai d’attente avec xrRemotingConnectMSFT est fixé à 10 secondes et illimité avec xrRemotingListenMSFT. Si une connexion peut être établie dans ce délai, la création de XrSession réussit et l’état de session passe à XR_SESSION_STATE_READY. Si aucune connexion ne peut être établie, la création de session réussit également, mais passe immédiatement à XR_SESSION_STATE_LOSS_PENDING.

En général, l’état de connexion est associé à l’état XrSession. Toute modification de l’état de connexion affecte également l’état de session. Par instance, si l’état de connexion passe de à XR_REMOTING_CONNECTION_STATE_DISCONNECTED_MSFT l’état de XR_REMOTING_CONNECTION_STATE_CONNECTED_MSFT session, il passe également à XR_SESSION_STATE_LOSS_PENDING.

Gestion des événements spécifiques de communication à distance

Le runtime Holographic Remoting OpenXR expose trois événements, qui sont importants pour surveiller l’état d’une connexion.

  1. XR_TYPE_REMOTING_EVENT_DATA_CONNECTED_MSFT: déclenché lorsqu’une connexion à l’appareil a été établie avec succès.
  2. XR_TYPE_REMOTING_EVENT_DATA_DISCONNECTED_MSFT: déclenché si une connexion établie est fermée ou si une connexion n’a pas pu être établie.
  3. XR_TYPE_REMOTING_EVENT_DATA_LISTENING_MSFT: lors du démarrage de l’écoute des connexions entrantes.

Ces événements sont placés dans une file d’attente et votre application distante doit lire la file d’attente avec régularité 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;
	}
}

Aperçu du contenu diffusé localement

Pour afficher le même contenu dans l’application distante envoyée à l’appareil, l’extension XR_MSFT_holographic_remoting_frame_mirroring peut être utilisée. Avec cette extension, vous pouvez envoyer une texture à xrEndFrame en utilisant le XrRemotingFrameMirrorImageInfoMSFT qui n’est pas chaîné au XrFrameEndInfo comme suit.

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

L’exemple ci-dessus utilise une texture de chaîne d’échange DX11 et présente la fenêtre immédiatement après l’appel à xrEndFrame. L’utilisation n’est pas limitée aux textures de chaîne d’échange. En outre, aucune synchronisation GPU supplémentaire n’est requise. Pour plus d’informations sur l’utilisation et les contraintes, case activée la spécification de l’extension. Si votre application distante utilise DX12, utilisez XrRemotingFrameMirrorImageD3D12MSFT au lieu de XrRemotingFrameMirrorImageD3D11MSFT.

Facultatif : canaux de données personnalisés

À compter de la version 2.5.0, les canaux de données personnalisés peuvent être utilisés avec l’API OpenXR pour envoyer des données utilisateur via la connexion de communication à distance déjà établie. Pour plus d’informations, consultez Canaux de données personnalisés avec l’API OpenXR.

Facultatif : Speech

À compter de la version 2.6.0, l’extension XR_MSFT_holographic_remoting_speech permet à l’application distante de réagir aux commandes vocales détectées par l’application de lecteur avec l’API OpenXR.

[! IMPORTANT] La spécification détaillée se trouve dans le référentiel github des exemples holographiques de communication à distance.

Pour initialiser un module de reconnaissance vocale sur l’application lecteur, l’application distante peut appeler xrInitializeRemotingSpeechMSFT. Cet appel transmet les paramètres d’initialisation vocale, qui se composent d’une langue, d’un dictionnaire d’expressions et du contenu d’un fichier de grammaire, à l’application lecteur.

Notes

Avant la version 2.6.1 , le module de reconnaissance vocale ne doit être initialisé qu’une seule fois par XrSession.

Si la création du module de reconnaissance vocale a réussi, comme indiqué par l’événement XR_TYPE_EVENT_DATA_REMOTING_SPEECH_RECOGNIZER_STATE_CHANGED_MSFT , l’application distante est avertie lorsqu’un résultat de reconnaissance vocale a été généré sur l’application lecteur. La XrEventDataRemotingSpeechRecognizerStateChangedMSFT structure d’événements est placée dans la file d’attente d’événements lorsque l’état du module de reconnaissance vocale côté joueur change.

XrRemotingSpeechRecognizerStateMSFT définit tous les états possibles du module de reconnaissance vocale côté joueur et la structure de l’événement XrEventDataRemotingSpeechRecognizedMSFT est placée dans la file d’attente d’événements si le module de reconnaissance vocale côté joueur a une expression reconnue. Une fois que l’application distante a été informée d’une expression reconnue, elle peut récupérer l’expression reconnue en appelant xrRetrieveRemotingSpeechRecognizedTextMSFT.

Notes

est XrRemotingSpeechRecognitionConfidenceMSFT un mappage direct de l’énumération SpeechRecognitionConfidence retournée avec le résultat de la reconnaissance vocale par l’API Reconnaissance vocale Windows.

Facultatif : Synchronisation du système de coordonnées

À compter de la version 2.7.0, la synchronisation du système de coordonnées peut être utilisée pour aligner les données spatiales entre le lecteur et l’application distante. Pour plus d’informations, consultez Coordination de la synchronisation du système avec vue d’ensemble de la communication à distance holographique.

Voir aussi