Pisanie niestandardowej aplikacji Holographic Remoting Player

Jeśli dopiero zaczynasz korzystać z usługi Holographic Remoting, możesz przeczytać nasze omówienie.

Ważne

W tym dokumencie opisano tworzenie niestandardowej aplikacji odtwarzacza dla HoloLens 2. Niestandardowe odtwarzacze napisane dla HoloLens 2 nie są zgodne z aplikacjami zdalnymi napisanymi dla urządzenia HoloLens 1. Oznacza to, że obie aplikacje muszą używać pakietu NuGet w wersji 2.x.x.

Tworząc niestandardową aplikację odtwarzacza Holographic Remoting, można utworzyć niestandardową aplikację umożliwiającą wyświetlanie widoków immersyjnych na komputerze zdalnym na HoloLens 2. Cały kod na tej stronie i roboczych projektach można znaleźć w repozytorium github przykładów Holographic Remoting.

Odtwarzacz Holographic Remoting umożliwia aplikacji wyświetlanie zawartości holograficznej renderowanej na komputerze stacjonarnym lub urządzeniu platformy UWP, na przykład konsoli Xbox One z dostępem do większej liczby zasobów systemowych. Aplikacja odtwarzacza Holographic Remoting przesyła strumieniowo dane wejściowe do aplikacji zdalnej Holographic Remoting i odbiera widok immersyjny jako strumień wideo i audio. Połączenie jest wykonywane przy użyciu standardowej sieci Wi-Fi. Aby utworzyć aplikację odtwarzacza, użyj pakietu NuGet, aby dodać aplikację Holographic Remoting do aplikacji platformy UWP. Następnie napisz kod do obsługi połączenia i wyświetlania widoku immersyjnego.

Wymagania wstępne

Dobrym punktem wyjścia jest działająca aplikacja platformy UWP oparta na directX, która jest już przeznaczona dla interfejsu API Windows Mixed Reality. Aby uzyskać szczegółowe informacje, zobacz Omówienie programowania w trybie DirectX. Jeśli nie masz istniejącej aplikacji i chcesz zacząć od podstaw szablon projektu holograficznego języka C++ jest dobrym punktem wyjścia.

Ważne

Każda aplikacja korzystająca z komunikacji automatycznej holograficznej powinna być autoryzowana do korzystania z wielowątkowego mieszkania. Korzystanie z mieszkania jednowątkowego jest obsługiwane, ale doprowadzi do nieoptymanej wydajności i ewentualnie stuttering podczas odtwarzania. W przypadku korzystania z języka C++/ WinRT winrt::init_apartment mieszkanie wielowątkowe jest wartością domyślną.

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, upewnij się, że wybierz najnowszą wersję 2.x.x i wybierz pozycję Zainstaluj.
  5. Jeśli zostanie wyświetlone okno dialogowe Podgląd , wybierz przycisk OK.
  6. Wybierz pozycję Akceptuję po wyświetleniu okna dialogowego umowy licencyjnej.

Ważne

Wewnątrz pakietu NuGet znajduje się szczegółowa build\native\include\HolographicAppRemoting\Microsoft.Holographic.AppRemoting.idl dokumentacja interfejsu API uwidoczniona przez usługę Holographic Remoting.

Modyfikowanie pliku Package.appxmanifest aplikacji

Aby aplikacja wiedziała o Microsoft.Holographic.AppRemoting.dll dodanym przez pakiet NuGet, należy wykonać następujące kroki w projekcie:

  1. W Eksplorator rozwiązań kliknij prawym przyciskiem myszy plik Package.appxmanifest i wybierz polecenie Otwórz za pomocą...
  2. Wybierz edytor XML (tekst) i wybierz przycisk OK
  3. Dodaj następujące wiersze do pliku i zapisz
  </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>

Tworzenie kontekstu odtwarzacza

W pierwszym kroku aplikacja powinna utworzyć kontekst odtwarzacza.

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

Ostrzeżenie

Gracz niestandardowy wprowadza warstwę pośrednią między aplikacją odtwarzacza a środowiskiem uruchomieniowym Windows Mixed Reality dostarczanym z systemem Windows. Odbywa się to podczas tworzenia kontekstu gracza. Z tego powodu każde wywołanie dowolnego interfejsu API Windows Mixed Reality przed utworzeniem kontekstu gracza może spowodować nieoczekiwane zachowanie. Zalecanym podejściem jest utworzenie kontekstu odtwarzacza tak wcześnie, jak to możliwe przed interakcją z dowolnym interfejsem API Mixed Reality. Nigdy nie mieszaj obiektów utworzonych ani pobieranych za pośrednictwem dowolnego interfejsu API Windows Mixed Reality przed wywołaniem metody PlayerContext::Create z obiektami utworzonymi lub pobranymi później.

Następnie można utworzyć holographicSpace, wywołując element HolographicSpace.CreateForCoreWindow.

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

Nawiązywanie połączenia z aplikacją zdalną

Gdy aplikacja odtwarzacza będzie gotowa do renderowania zawartości, można ustanowić połączenie z aplikacją zdalną.

Połączenie można ustanowić na jeden z następujących sposobów:

  1. Aplikacja odtwarzacza uruchomiona na HoloLens 2 łączy się z aplikacją zdalną.
  2. Aplikacja zdalna łączy się z aplikacją odtwarzacza uruchomioną na HoloLens 2.

Aby nawiązać połączenie z aplikacji odtwarzacza z aplikacją zdalną, wywołaj Connect metodę w kontekście odtwarzacza, określając nazwę hosta i port. Domyślny port to 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()
}

Ważne

Podobnie jak w przypadku dowolnego interfejsu API Connect C++/WinRT może zostać zgłoszony błąd winrt::hresult_error, który należy obsłużyć.

Nasłuchiwanie połączeń przychodzących w aplikacji odtwarzacza można wykonać przez wywołanie Listen metody . Podczas tego wywołania można określić zarówno port uzgadniania, jak i port transportu. Port uzgadniania jest używany do początkowego uzgadniania. Dane są następnie wysyłane za pośrednictwem portu transportu. Domyślnie używany jest numer portu 8265 i 8266 .

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

Uwidacznia PlayerContext trzy zdarzenia w celu monitorowania stanu połączenia

  1. OnConnected: wyzwalany po pomyślnym nawiązaniu połączenia z aplikacją zdalną.
m_onConnectedEventToken = m_playerContext.OnConnected([]() 
{
    // Handle connection successfully established
});
  1. OnDisconnected: wyzwolono, jeśli nawiązane połączenie zostało przerwane lub nie można nawiązać połączenia.
m_onDisconnectedEventToken = m_playerContext.OnDisconnected([](ConnectionFailureReason failureReason)
{
    switch (failureReason)
    {
        // Handle connection failed or terminated.
        // See ConnectionFailureReason for possible reasons.
    }
}

Uwaga

Możliwe ConnectionFailureReason wartości są udokumentowane w Microsoft.Holographic.AppRemoting.idlpliku.

  1. OnListening: Podczas nasłuchiwania połączeń przychodzących rozpoczyna się.
m_onListeningEventToken = m_playerContext.OnListening([]()
{
    // Handle start listening for incoming connections
});

Ponadto można wykonywać zapytania dotyczące stanu połączenia przy użyciu ConnectionState właściwości w kontekście odtwarzacza.

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

Wyświetlanie zdalnie renderowanej ramki

Aby wyświetlić zdalnie renderowaną zawartość, wywołaj funkcję PlayerContext::BlitRemoteFrame podczas renderowania elementu HolographicFrame.

BlitRemoteFrame wymaga, aby bufor wsteczny dla bieżącego elementu HolographicFrame był powiązany jako element docelowy renderowania. Bufor wsteczny można odebrać z właściwości HolographicCameraRenderingParameters za pośrednictwem właściwości Direct3D11BackBuffer .

Po wywołaniu BlitRemoteFrame kopiuje najnowszą odebraną ramkę z aplikacji zdalnej do elementu BackBuffer elementu HolographicFrame. Ponadto zestaw punktów koncentracji uwagi jest ustawiony, jeśli aplikacja zdalna określiła punkt koncentracji uwagi podczas renderowania ramki zdalnej.

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

Uwaga

PlayerContext::BlitRemoteFrame potencjalnie zastępuje punkt koncentracji uwagi dla bieżącej ramki.

W przypadku powodzenia BlitRemoteFrame zwraca wartość BlitResult::Success_Color. W przeciwnym razie zwraca przyczynę błędu:

  • BlitResult::Failed_NoRemoteFrameAvailable: Niepowodzenie, ponieważ nie jest dostępna żadna ramka zdalna.
  • BlitResult::Failed_NoCamera: Nie powiodło się, ponieważ nie ma obecnej kamery.
  • BlitResult::Failed_RemoteFrameTooOld: Niepowodzenie, ponieważ ramka zdalna jest zbyt stara (zobacz właściwość PlayerContext::BlitRemoteFrameTimeout).

Ważne

Począwszy od wersji 2.1.0 , można użyć niestandardowego odtwarzacza do ponownego projektu głębokości za pośrednictwem komunikacji zdalnie holograficznej.

BlitResult może również wrócić BlitResult::Success_Color_Depth w następujących warunkach:

Jeśli te warunki zostaną spełnione, BlitRemoteFrame spowoduje rozbicie głębokości zdalnej do obecnie powiązanego lokalnego buforu głębokości. Następnie możesz renderować dodatkową zawartość lokalną, która będzie miała skrzyżowanie głębokości ze zdalną renderowaną zawartością. Ponadto możesz zatwierdzić lokalny bufor głębokości za pośrednictwem holographicCameraRenderingParameters.CommitDirect3D11DepthBuffer w odtwarzaczu niestandardowym, aby uzyskać szczegółowe odwzorowanie zawartości renderowanej zdalnie i lokalnie.

Tryb przekształcania projekcji

Jednym z problemów, który występuje podczas korzystania z reprojektowania głębokości za pośrednictwem komunikacji zdalnej, jest to, że zawartość zdalna może być renderowana z inną transformacją projekcji niż zawartość lokalna renderowana bezpośrednio przez aplikację odtwarzacza niestandardowego. Typowym przypadkiem użycia jest określenie różnych wartości dla bliskiej i dalekiej płaszczyzny (za pośrednictwem HolographicCamera::SetNearPlaneDistance i HolographicCamera::SetFarPlaneDistance) po stronie odtwarzacza i po stronie zdalnej. W tym przypadku nie jest jasne, czy transformacja projekcji po stronie odtwarzacza powinna odzwierciedlać odległe odległości bliskie/dalekie płaszczyzny lub lokalne.

Począwszy od wersji 2.1.0 , możesz kontrolować tryb przekształcania projekcji za pomocą polecenia PlayerContext::ProjectionTransformConfig. Obsługiwane wartości to:

  • Local - HolographicCameraPose::P rojectionTransform zwraca transformację projekcji, która odzwierciedla odległości bliskie/dalekie płaszczyzny ustawione przez niestandardową aplikację odtwarzacza na holographicCamera.
  • Remote - Transformacja projekcji odzwierciedla odległości bliskiej/dalekiej płaszczyzny określonej przez aplikację zdalną.
  • Merged - Odległość w pobliżu/dalekiego samolotu od aplikacji zdalnej i scalania niestandardowej aplikacji odtwarzacza. Domyślnie odbywa się to przez pobranie minimalnej odległości bliskiej płaszczyzny i maksymalnej odległości dalekiej płaszczyzny. W przypadku, gdy zdalna lub lokalna strona są odwrócone, powiedzmy daleko < w pobliżu, zdalne odległości w pobliżu/dalekiej płaszczyzny są przerzucane.

Opcjonalnie: ustaw parametr BlitRemoteFrameTimeout

Ważne

PlayerContext::BlitRemoteFrameTimeout program jest obsługiwany od wersji 2.0.9.

Właściwość PlayerContext::BlitRemoteFrameTimeout określa czas ponownego użycia ramki zdalnej, jeśli nie odebrano nowej ramki zdalnej.

Typowym przypadkiem użycia jest włączenie limitu czasu elementu BlitRemoteFrame w celu wyświetlenia pustego ekranu, jeśli nie odebrano żadnych nowych ramek przez określony czas. Po włączeniu typu zwracanego BlitRemoteFrame metody można również użyć do przełączenia do lokalnie renderowanej zawartości rezerwowej.

Aby włączyć limit czasu, ustaw wartość właściwości na czas równy lub większy niż 100 ms. Aby wyłączyć limit czasu, ustaw właściwość na zero czasu trwania. Jeśli limit czasu jest włączony i nie zostanie odebrana żadna ramka zdalna przez ustawiony czas trwania, element BlitRemoteFrame zakończy się niepowodzeniem i powróci Failed_RemoteFrameTooOld do momentu odebrania nowej ramki zdalnej.

using namespace std::chrono_literals;

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

Opcjonalnie: Pobieranie statystyk dotyczących ostatniej ramki zdalnej

Aby zdiagnozować problemy z wydajnością lub siecią, statystyki dotyczące ostatniej ramki zdalnej można pobrać za pośrednictwem PlayerContext::LastFrameStatistics właściwości . Statystyki są aktualizowane podczas wywołania elementu HolographicFrame::P resentUsingCurrentPrediction.

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

Aby uzyskać więcej informacji, zobacz dokumentację PlayerFrameStatisticsMicrosoft.Holographic.AppRemoting.idl w pliku.

Opcjonalnie: niestandardowe kanały danych

Niestandardowe kanały danych mogą służyć 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.

Opcjonalnie: Over-Rendering

Holographic Remoting przewiduje, gdzie głowa użytkownika będzie w momencie wyświetlania renderowanych obrazów na ekranach. Jednak to przewidywanie jest przybliżeniem. W związku z tym przewidywanych widoków w aplikacji zdalnej i późniejsze rzeczywistego widoku w aplikacji odtwarzacza mogą się różnić. Silniejsze odchylenia (na przykład z powodu nieprzewidywalnego ruchu) mogą powodować czarne regiony na granicach frustum oglądania. Począwszy od wersji 2.6.0 , można użyć Over-Rendering, aby zmniejszyć czarne regiony i zwiększyć jakość wizualizacji, sztucznie zwiększając widok poza frustum wyświetlania.

Over-Rendering można włączyć za pomocą polecenia PlayerContext::ConfigureOverRendering.

Określa OverRenderingConfig ułamkowe zwiększenie rozmiaru do rzeczywistegoportu widoku, dzięki czemu przewidywaneporty widoku stają się większe i mniejsze. Dzięki zwiększonemu rozmiarowi wyświetlania gęstość pikseli zmniejsza się, więc funkcja OverRenderingConfig umożliwia również zwiększenie rozdzielczości. Jeśli wzrost widoku jest równy rozdzielczości, zwiększ gęstość pikseli pozostaje taka sama. OverRenderingConfig jest definiowany jako:

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

Opcjonalnie: Synchronizacja systemu współrzędnych

Począwszy od wersji 2.7.0 synchronizacji systemu współrzędnych można użyć do wyrównania danych przestrzennych między odtwarzaczem a aplikacją zdalną. Aby uzyskać więcej informacji, zobacz Temat Synchronizacja systemu współrzędnych za pomocą komunikacji zdalnie holograficznej — omówienie.

Zobacz też