Freigeben über


Schreiben einer benutzerdefinierten Holographic Remoting Player-App

Wenn Sie noch nicht mit Holographic Remoting arbeiten, sollten Sie unsere Übersicht lesen.

Wichtig

In diesem Dokument wird die Erstellung einer benutzerdefinierten Playeranwendung für HoloLens 2 beschrieben. Benutzerdefinierte Spieler, die für HoloLens 2 geschrieben wurden, sind nicht mit Remoteanwendungen kompatibel, die für HoloLens 1 geschrieben wurden. Dies bedeutet, dass beide Anwendungen NuGet-Paketversion 2.x.x verwenden müssen.

Durch Erstellen einer benutzerdefinierten Holographic Remoting Player-App können Sie eine benutzerdefinierte Anwendung erstellen, die immersive Ansichten von einem Remotecomputer auf Ihrem HoloLens 2 anzeigen kann. Der gesamte Code auf dieser Seite und Arbeitsprojekte finden Sie im Github-Repository von Holographic Remoting-Beispielen.

Mit einem Holographic Remoting-Player kann Ihre App holografische Inhalte anzeigen, die auf einem Desktop-PC oder UWP-Gerät wie der Xbox One mit Zugriff auf weitere Systemressourcen gerendert werden . Eine Holographic Remoting Player-App streamt Eingabedaten an eine Holographic Remoting-Remoteanwendung und empfängt eine immersive Ansicht als Video- und Audiostream zurück. Die Verbindung erfolgt über standardmäßiges WLAN. Verwenden Sie zum Erstellen einer Player-App ein NuGet-Paket, um Ihrer UWP-App Holographic Remoting hinzuzufügen. Schreiben Sie dann Code zum Behandeln der Verbindung und zum Anzeigen einer immersiven Ansicht.

Voraussetzungen

Ein guter Ausgangspunkt ist eine funktionierende directX-basierte UWP-App, die bereits auf die Windows Mixed Reality-API ausgerichtet ist. Ausführliche Informationen finden Sie in der Übersicht über die DirectX-Entwicklung. Wenn Sie nicht über eine vorhandene App verfügen und von Grund auf neu beginnen möchten, ist die C++-Projektvorlage für holografische Grafiken ein guter Ausgangspunkt.

Wichtig

Jede App mit Holographic Remoting sollte erstellt werden, um ein Multithread-Apartment zu verwenden. Die Verwendung einer Singlethread-Wohnung wird unterstützt, führt aber zu einer suboptimalen Leistung und möglicherweise stuttern während der Wiedergabe. Bei Verwendung von C++/WinRT winrt::init_apartment ist ein Multithread-Apartment der Standard.

Abrufen des Holographic Remoting NuGet-Pakets

Die folgenden Schritte sind erforderlich, um das NuGet-Paket zu einem Projekt in Visual Studio hinzuzufügen.

  1. Öffnen Sie das Projekt in Visual Studio.
  2. Klicken Sie mit der rechten Maustaste auf den Projektknoten, und wählen Sie "NuGet-Pakete verwalten" aus ...
  3. Wählen Sie im daraufhin angezeigten Bereich "Durchsuchen" aus, und suchen Sie dann nach "Holographic Remoting".
  4. Wählen Sie "Microsoft.Holographic.Remoting" aus, stellen Sie sicher, dass Sie die neueste Version von 2.x.x auswählen und "Installieren" auswählen.
  5. Wenn das Dialogfeld "Vorschau" angezeigt wird, wählen Sie "OK" aus.
  6. Wählen Sie "Ich stimme zu " aus, wenn das Dialogfeld "Lizenzvertrag" angezeigt wird.

Wichtig

Das build\native\include\HolographicAppRemoting\Microsoft.Holographic.AppRemoting.idl Innerhalb des NuGet-Pakets enthält detaillierte Dokumentation für die API, die von Holographic Remoting verfügbar gemacht wird.

Ändern des Package.appxmanifests der Anwendung

Um die Anwendung auf die vom NuGet-Paket hinzugefügten Microsoft.Holographic.AppRemoting.dll aufmerksam zu machen, müssen die folgenden Schritte für das Projekt ausgeführt werden:

  1. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf die Datei "Package.appxmanifest", und wählen Sie "Öffnen mit" aus...
  2. Wählen Sie DEN XML-Editor (Text) aus, und wählen Sie "OK" aus .
  3. Fügen Sie der Datei die folgenden Zeilen hinzu, und speichern Sie sie.
  </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>

Erstellen des Spielerkontexts

Im ersten Schritt sollte die Anwendung einen Playerkontext erstellen.

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

Warnung

Ein benutzerdefinierter Player fügt eine Zwischenebene zwischen der Player-App und der windows Mixed Reality-Runtime ein, die mit Windows ausgeliefert wird. Dies geschieht während der Erstellung des Spielerkontexts. Aus diesem Grund kann jeder Aufruf jeder Windows Mixed Reality-API vor dem Erstellen des Playerkontexts zu unerwartetem Verhalten führen. Der empfohlene Ansatz besteht darin, den Spielerkontext so früh wie möglich zu erstellen, bevor eine Interaktion mit einer Mixed Reality-API erfolgt. Mischen Sie niemals Objekte, die über eine Beliebige Windows Mixed Reality-API erstellt oder abgerufen wurden, bevor der Aufruf PlayerContext::Create mit objekten erstellt oder danach abgerufen wurde.

Als Nächstes kann holographicSpace erstellt werden, indem HolographicSpace.CreateForCoreWindow aufgerufen wird.

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

Herstellen einer Verbindung mit der Remote-App

Sobald die Player-App zum Rendern von Inhalten bereit ist, kann eine Verbindung mit der Remote-App hergestellt werden.

Die Verbindung kann auf eine der folgenden Arten hergestellt werden:

  1. Die Player-App, die auf HoloLens 2 ausgeführt wird, stellt eine Verbindung mit der Remote-App bereit.
  2. Die Remote-App stellt eine Verbindung mit der Player-App auf HoloLens 2 bereit.

Um eine Verbindung von der Player-App mit der Remote-App herzustellen, rufen Sie die Connect Methode im Spielerkontext auf, die den Hostnamen und den Port angibt. Der Standardport ist 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()
}

Wichtig

Wie bei jeder C++/WinRT-API Connect kann ein winrt::hresult_error ausgelöst werden, das behandelt werden muss.

Die Überwachung eingehender Verbindungen in der Player-App kann durch Aufrufen der Listen Methode erfolgen. Sowohl der Handshake-Port als auch der Transportport können während dieses Anrufs angegeben werden. Der Handshake-Port wird für den ersten Handshake verwendet. Die Daten werden dann über den Transportport gesendet. Standardmäßig werden Portnummer 8265 und 8266 verwendet.

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

Die PlayerContext drei Ereignisse werden verfügbar gemacht, um den Status der Verbindung zu überwachen.

  1. OnConnected: Wird ausgelöst, wenn eine Verbindung mit der Remote-App erfolgreich hergestellt wurde.
m_onConnectedEventToken = m_playerContext.OnConnected([]() 
{
    // Handle connection successfully established
});
  1. OnDisconnected: Wird ausgelöst, wenn eine hergestellte Verbindung beendet wird oder eine Verbindung nicht hergestellt werden konnte.
m_onDisconnectedEventToken = m_playerContext.OnDisconnected([](ConnectionFailureReason failureReason)
{
    switch (failureReason)
    {
        // Handle connection failed or terminated.
        // See ConnectionFailureReason for possible reasons.
    }
}

Hinweis

Mögliche ConnectionFailureReason Werte sind in der Microsoft.Holographic.AppRemoting.idl Datei dokumentiert.

  1. OnListening: Wenn die Überwachung eingehender Verbindungen gestartet wird.
m_onListeningEventToken = m_playerContext.OnListening([]()
{
    // Handle start listening for incoming connections
});

Darüber hinaus kann der Verbindungszustand mithilfe der ConnectionState Eigenschaft im Playerkontext abgefragt werden.

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

Remote gerenderter Frame anzeigen

Um den remote gerenderten Inhalt anzuzeigen, rufen Sie PlayerContext::BlitRemoteFrame beim Rendern eines HolographicFrame auf.

BlitRemoteFrame erfordert, dass der Hintergrundpuffer für den aktuellen HolographicFrame als Renderziel gebunden ist. Der Hintergrundpuffer kann über die Direct3D11BackBuffer-Eigenschaft von holographicCameraRenderingParameters empfangen werden.

Kopiert beim Aufruf BlitRemoteFrame den neuesten empfangenen Frame aus der Remoteanwendung in den BackBuffer des HolographicFrame. Darüber hinaus wird der Fokuspunktsatz festgelegt, wenn die Remoteanwendung beim Rendern des Remoteframes einen Fokuspunkt angegeben hat.

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

Hinweis

PlayerContext::BlitRemoteFrame Der Fokuspunkt für den aktuellen Frame wird möglicherweise überschrieben.

Gibt bei Erfolg BlitRemoteFrame die Rückgabe zurück BlitResult::Success_Color. Andernfalls wird der Fehlergrund zurückgegeben:

  • BlitResult::Failed_NoRemoteFrameAvailable: Fehler, da kein Remoteframe verfügbar ist.
  • BlitResult::Failed_NoCamera: Fehler, weil keine Kamera vorhanden ist.
  • BlitResult::Failed_RemoteFrameTooOld: Fehler, da der Remoteframe zu alt ist (siehe PlayerContext::BlitRemoteFrameTimeout-Eigenschaft).

Wichtig

Ab Version 2.1.0 ist es mit einem benutzerdefinierten Player möglich, die Tiefenneuprojektion über Holographic Remoting zu verwenden.

BlitResult kann auch unter den folgenden Bedingungen zurückgegeben werden BlitResult::Success_Color_Depth :

Wenn diese Bedingungen erfüllt sind, BlitRemoteFrame wird die Remotetiefe in den aktuell gebundenen lokalen Tiefenpuffer eingeblitzt. Anschließend können Sie zusätzliche lokale Inhalte rendern, die eine Tiefe schnittmenge mit dem remote gerenderten Inhalt aufweisen. Darüber hinaus können Sie den lokalen Tiefenpuffer über HolographicCameraRenderingParameters.CommitDirect3D11DepthBuffer in Ihrem benutzerdefinierten Player übernehmen, um eine tiefenReprojection für Remote- und lokale gerenderte Inhalte zu erhalten.

Projektionstransformationsmodus

Ein Problem, das bei verwendung der Tiefenneuprojektion über Holographic Remoting angezeigt wird, besteht darin, dass der Remoteinhalt mit einer anderen Projektionstransformation gerendert werden kann als lokale Inhalte, die direkt von Ihrer benutzerdefinierten Player-App gerendert werden. Ein gängiger Anwendungsfall besteht darin, unterschiedliche Werte für nahe und weit ebene (über HolographicCamera::SetNearPlaneDistance und HolographicCamera::SetFarPlaneDistance) auf der Spielerseite und der Remoteseite anzugeben. In diesem Fall ist es nicht klar, ob die Projektionstransformation auf der Spielerseite die entfernungen nahe/weit entfernten Ebenen oder die lokalen widerspiegelt.

Ab Version 2.1.0 können Sie den Projektionstransformationsmodus über PlayerContext::ProjectionTransformConfig. Diese Werte werden unterstützt:

  • Local - HolographicCameraPose::P rojectionTransform gibt eine Projektionstransformation zurück, die die nahe/weit entfernten Entfernungen der benutzerdefinierten Spieler-App auf der HolographicCamera widerspiegelt.
  • Remote - Die Projektionstransformation spiegelt die nahe/weit entfernten Entfernungen wider, die von der Remote-App angegeben werden.
  • Merged – Nah-/Weit-Entfernungen von Ihrer Remote-App und der benutzerdefinierten Player-App werden zusammengeführt. Dies geschieht standardmäßig mit dem Mindestmaß der Entfernungen in der Nähe des Flugzeugs und dem Höchstwert der weit entfernten Flugzeugabstände. Falls entweder die remote oder die lokale Seite umgekehrt ist, sagen Wir, weit < in der Nähe, werden die entfernten Entfernungen in der Nähe/Weitebene gekippt.

Optional: BlitRemoteFrameTimeout festlegen

Wichtig

PlayerContext::BlitRemoteFrameTimeout wird ab Version 2.0.9 unterstützt.

Die PlayerContext::BlitRemoteFrameTimeout Eigenschaft gibt an, wie lange ein Remoteframe wiederverwendet wird, wenn kein neuer Remoteframe empfangen wird.

Ein gängiger Anwendungsfall besteht darin, das BlitRemoteFrame-Timeout so zu aktivieren, dass ein leerer Bildschirm angezeigt wird, wenn keine neuen Frames für einen bestimmten Zeitraum empfangen werden. Wenn der Rückgabetyp der BlitRemoteFrame Methode aktiviert ist, kann auch verwendet werden, um zu einem lokal gerenderten Fallbackinhalt zu wechseln.

Um das Timeout zu aktivieren, legen Sie den Eigenschaftswert auf eine Dauer gleich oder größer als 100 ms fest. Um das Timeout zu deaktivieren, legen Sie die Eigenschaft auf null Dauer fest. Wenn das Timeout aktiviert ist und kein Remoteframe für die festgelegte Dauer empfangen wird, schlägt BlitRemoteFrame fehl und gibt zurück Failed_RemoteFrameTooOld , bis ein neuer Remoteframe empfangen wird.

using namespace std::chrono_literals;

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

Optional: Abrufen von Statistiken zum letzten Remoteframe

Um Leistungs- oder Netzwerkprobleme zu diagnostizieren, können Statistiken zum letzten Remoteframe über die PlayerContext::LastFrameStatistics Eigenschaft abgerufen werden. Statistiken werden während des Aufrufs von HolographicFrame::P resentUsingCurrentPrediction aktualisiert.

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

Weitere Informationen finden Sie in der PlayerFrameStatistics Dokumentation in der Microsoft.Holographic.AppRemoting.idl Datei.

Optional: Benutzerdefinierte Datenkanäle

Benutzerdefinierte Datenkanäle können verwendet werden, um Benutzerdaten über die bereits bestehende Remotingverbindung zu senden. Weitere Informationen finden Sie unter benutzerdefinierten Datenkanälen.

Optional: Over-Rendering

Holographic Remoting prognostiziert, wo der Kopf des Benutzers zu dem Zeitpunkt angezeigt wird, zu dem die gerenderten Bilder auf den Displays angezeigt werden. Diese Vorhersage ist jedoch eine Annäherung. Daher kann sich der vorhergesagte Viewport in der Remote-App und der spätere tatsächliche Viewport in der Player-App unterscheiden. Stärkere Abweichungen (z. B. aufgrund unvorhersehbarer Bewegung) können schwarze Bereiche am Rand des Sichtfrstums verursachen. Ab Version 2.6.0 können Sie over-Rendering verwenden, um die schwarzen Bereiche zu reduzieren und die visuelle Qualität zu verbessern, indem Sie den Viewport über das Ansichts-Frustum hinaus künstlich erhöhen.

Over-Rendering kann über PlayerContext::ConfigureOverRendering.

Die OverRenderingConfig Specifies a fractional size increase to the actual viewport, so that the predicted viewport is larger and less cutting occurs. Mit einer erhöhten Viewportgröße verringert sich die Pixeldichte, sodass Sie auch die Auflösung über die OverRenderingConfig erhöhen können. Wenn die Viewporterhöhung gleich der Auflösung ist, bleibt die Pixeldichte gleich. OverRenderingConfig wird folgendermaßen definiert:

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

Optional: Koordinieren der Systemsynchronisierung

Ab Version 2.7.0 kann die Koordinatensystemsynchronisierung verwendet werden, um räumliche Daten zwischen dem Player und der Remote-App auszurichten. Weitere Informationen finden Sie unter Koordinatensystemsynchronisierung mit Holographic Remoting Overview.

Weitere Informationen