Aggiungere Holographic Remoting (prima generazione di HoloLens)

Se non si ha familiarità con Holographic Remoting, è possibile leggere la panoramica.

Importante

Questo documento descrive la creazione di un'applicazione host per HoloLens 1. L'applicazione host per HoloLens (prima generazione) deve usare la versione del pacchetto NuGet 1.x.x. Ciò implica che le applicazioni host scritte per HoloLens 1 non sono compatibili con HoloLens 2 e viceversa.

HoloLens 2

Gli sviluppatori HoloLens che usano Holographic Remoting dovranno aggiornare le app per renderle compatibili con HoloLens 2. Questa operazione richiede una nuova versione del pacchetto NuGet Holographic Remoting. Assicurarsi di usare la versione 2.0.0.0 o successiva del pacchetto NuGet Holographic Remoting durante la connessione a Holographic Remoting Player in HoloLens 2. In caso contrario, la connessione non riuscirà.

Nota

Le linee guida specifiche per HoloLens 2 sono disponibili qui.

Aggiungere la comunicazione remota olografica all'app desktop o UWP

Questa pagina descrive come aggiungere Holographic Remoting a un'app desktop o UWP.

La comunicazione remota holographic consente all'app di scegliere come destinazione un dispositivo HoloLens con contenuto olografico ospitato in un PC desktop o in un dispositivo UWP, ad esempio Xbox One. È anche possibile accedere a più risorse di sistema, rendendo possibile integrare visualizzazioni immersive remote nel software pc desktop esistente. Un'app host remota riceve un flusso di dati di input da holoLens, esegue il rendering del contenuto in una visualizzazione immersiva virtuale e trasmette i fotogrammi di contenuto a HoloLens. La connessione viene effettuata tramite Wi-Fi standard. Per usare la comunicazione remota, usa un pacchetto NuGet per aggiungere la comunicazione remota olografica alla tua app desktop o UWP, quindi scrivi codice per gestire la connessione ed eseguire il rendering di una visualizzazione immersiva. Le librerie helper sono incluse nell'esempio di codice che semplificano l'attività di gestione della connessione del dispositivo.

Una connessione remota tipica avrà un minimo di 50 ms di latenza. L'app lettore può segnalare la latenza in tempo reale.

Nota

I frammenti di codice in questo articolo illustrano attualmente l'uso di C++/CX anziché C++17 conforme a C++/WinRT come usato nel modello di progetto olografico C++. I concetti sono equivalenti per un progetto C++/WinRT, anche se è necessario tradurre il codice.

Ottenere i pacchetti NuGet remoti

Seguire questa procedura per ottenere il pacchetto NuGet per la comunicazione remota olografica e aggiungere un riferimento dal progetto:

  1. Passare al progetto in Visual Studio.
  2. Fare clic con il pulsante destro del mouse sul nodo del progetto e scegliere Gestisci pacchetti NuGet...
  3. Nel pannello visualizzato selezionare Sfoglia e quindi cercare "Holographic Remoting".
  4. Selezionare Microsoft.Holographic.Remoting e selezionare Installa.
  5. Se viene visualizzata la finestra di dialogo Anteprima , selezionare OK.
  6. Selezionare Accetto quando viene visualizzata la finestra di dialogo del contratto di licenza.

Creare HolographicStreamerHelpers

Prima di tutto, è necessario aggiungere un'istanza di HolographicStreamerHelpers alla classe che gestirà la comunicazione remota.

#include <HolographicStreamerHelpers.h>

   private:
       Microsoft::Holographic::HolographicStreamerHelpers^ m_streamerHelpers;

Sarà anche necessario tenere traccia dello stato di connessione. Se si vuole eseguire il rendering dell'anteprima, è necessario disporre di una trama in cui copiarlo. Sono necessari anche alcuni aspetti, ad esempio un blocco dello stato di connessione, un modo per archiviare l'indirizzo IP di HoloLens e così via.

private:
       Microsoft::Holographic::HolographicStreamerHelpers^ m_streamerHelpers;

       Microsoft::WRL::Wrappers::SRWLock                   m_connectionStateLock;

       RemotingHostSample::AppView^                        m_appView;
       Platform::String^                                   m_ipAddress;
       Microsoft::Holographic::HolographicStreamerHelpers^ m_streamerHelpers;

       Microsoft::WRL::Wrappers::CriticalSection           m_deviceLock;
       Microsoft::WRL::ComPtr<IDXGISwapChain1>             m_swapChain;
       Microsoft::WRL::ComPtr<ID3D11Texture2D>             m_spTexture;

Inizializzare HolographicStreamerHelpers e connettersi a HoloLens

Per connettersi a un dispositivo HoloLens, creare un'istanza di HolographicStreamerHelpers e connettersi all'indirizzo IP di destinazione. Sarà necessario impostare le dimensioni dei fotogrammi video in modo che corrispondano alla larghezza e all'altezza dello schermo di HoloLens, perché la libreria Holographic Remoting prevede che le risoluzioni del codificatore e del decodificatore corrispondano esattamente.

m_streamerHelpers = ref new HolographicStreamerHelpers();
       m_streamerHelpers->CreateStreamer(m_d3dDevice);

       // We currently need to stream at 720p because that's the resolution of our remote display.
       // There is a check in the holographic streamer that makes sure the remote and local
       // resolutions match. The default streamer resolution is 1080p.
       m_streamerHelpers->SetVideoFrameSize(1280, 720);

       try
       {
           m_streamerHelpers->Connect(m_ipAddress->Data(), 8001);
       }
       catch (Platform::Exception^ ex)
       {
           DebugLog(L"Connect failed with hr = 0x%08X", ex->HResult);
       }

La connessione del dispositivo è asincrona. L'app deve fornire gestori eventi per eventi di connessione, disconnessione e invio di fotogrammi.

L'evento OnConnected può aggiornare l'interfaccia utente, avviare il rendering e così via. Nell'esempio di codice desktop viene aggiornato il titolo della finestra con un messaggio "connesso".

m_streamerHelpers->OnConnected += ref new ConnectedEvent(
           [this]()
           {
               UpdateWindowTitle();
           });

L'evento OnDisconnected può gestire la riconnessione, gli aggiornamenti dell'interfaccia utente e così via. In questo esempio viene riconnessa se si verifica un errore temporaneo.

Platform::WeakReference streamerHelpersWeakRef = Platform::WeakReference(m_streamerHelpers);
       m_streamerHelpers->OnDisconnected += ref new DisconnectedEvent(
           [this, streamerHelpersWeakRef](_In_ HolographicStreamerConnectionFailureReason failureReason)
           {
               DebugLog(L"Disconnected with reason %d", failureReason);
               UpdateWindowTitle();

               // Reconnect if this is a transient failure.
               if (failureReason == HolographicStreamerConnectionFailureReason::Unreachable ||
                   failureReason == HolographicStreamerConnectionFailureReason::ConnectionLost)
               {
                   DebugLog(L"Reconnecting...");

                   try
                   {
                       auto helpersResolved = streamerHelpersWeakRef.Resolve<HolographicStreamerHelpers>();
                       if (helpersResolved)
                       {
                           helpersResolved->Connect(m_ipAddress->Data(), 8001);
                       }
                       else
                       {
                           DebugLog(L"Failed to reconnect because a disconnect has already occurred.\n");
                       }
                   }
                   catch (Platform::Exception^ ex)
                   {
                       DebugLog(L"Connect failed with hr = 0x%08X", ex->HResult);
                   }
               }
               else
               {
                   DebugLog(L"Disconnected with unrecoverable error, not attempting to reconnect.");
               }
           });

Quando il componente di comunicazione remota è pronto per inviare un frame, l'app ha la possibilità di crearne una copia in SendFrameEvent. In questo caso, il frame viene copiato in una catena di scambio in modo da poterlo visualizzare in una finestra di anteprima.

m_streamerHelpers->OnSendFrame += ref new SendFrameEvent(
           [this](_In_ const ComPtr<ID3D11Texture2D>& spTexture, _In_ FrameMetadata metadata)
           {
               if (m_showPreview)
               {
                   ComPtr<ID3D11Device1> spDevice = m_appView->GetDeviceResources()->GetD3DDevice();
                   ComPtr<ID3D11DeviceContext> spContext = m_appView->GetDeviceResources()->GetD3DDeviceContext();

                   ComPtr<ID3D11Texture2D> spBackBuffer;
                   ThrowIfFailed(m_swapChain->GetBuffer(0, IID_PPV_ARGS(&spBackBuffer)));

                   spContext->CopySubresourceRegion(
                       spBackBuffer.Get(), // dest
                       0,                  // dest subresource
                       0, 0, 0,            // dest x, y, z
                       spTexture.Get(),    // source
                       0,                  // source subresource
                       nullptr);           // source box, null means the entire resource

                   DXGI_PRESENT_PARAMETERS parameters = { 0 };
                   ThrowIfFailed(m_swapChain->Present1(1, 0, &parameters));
               }
           });

Rendering del contenuto olografico

Per eseguire il rendering del contenuto tramite la comunicazione remota, configura un IFrameworkView virtuale all'interno dell'app desktop o UWP ed elabora fotogrammi olografici dalla comunicazione remota. Tutte le API di Windows Holographic vengono usate allo stesso modo da questa visualizzazione, ma è impostata in modo leggermente diverso.

Invece di crearli manualmente, gli spazi olografici e i componenti vocali provengono dalla classe HolographicRemotingHelpers:

m_appView->Initialize(m_streamerHelpers->HolographicSpace, m_streamerHelpers->RemoteSpeech);

Anziché usare un ciclo di aggiornamento in un metodo Run, fornisci aggiornamenti di graduazione dal ciclo principale dell'app desktop o UWP. Ciò consente all'app desktop o UWP di rimanere in controllo dell'elaborazione dei messaggi.

void DesktopWindow::Tick()
   {
       auto lock = m_deviceLock.Lock();
       m_appView->Tick();

       // display preview, etc.
   }

Il metodo Tick() della visualizzazione dell'app olografica completa un'iterazione del ciclo update, draw, present.

void AppView::Tick()
   {
       if (m_main)
       {
           // When running on Windows Holographic, we can use the holographic rendering system.
           HolographicFrame^ holographicFrame = m_main->Update();

           if (holographicFrame && m_main->Render(holographicFrame))
           {
               // The holographic frame has an API that presents the swap chain for each
               // holographic camera.
               m_deviceResources->Present(holographicFrame);
           }
       }
   }

L'aggiornamento, il rendering e il ciclo di visualizzazione dell'app olografica sono esattamente uguali a quelli in esecuzione in HoloLens, ad eccezione del fatto che si ha accesso a una quantità molto maggiore di risorse di sistema nel PC desktop. È possibile eseguire il rendering di molti più triangoli, avere più passaggi di disegno, fare più fisica e usare i processi x64 per caricare il contenuto che richiede più di 2 GB di RAM.

Disconnettere e terminare la sessione remota

Per disconnettersi, ad esempio quando l'utente fa clic su un pulsante dell'interfaccia utente per disconnettersi, chiamare Disconnect() in HolographicStreamerHelpers e rilasciare l'oggetto.

void DesktopWindow::DisconnectFromRemoteDevice()
   {
       // Disconnecting from the remote device can change the connection state.
       auto exclusiveLock = m_connectionStateLock.LockExclusive();

       if (m_streamerHelpers != nullptr)
       {
           m_streamerHelpers->Disconnect();

           // Reset state
           m_streamerHelpers = nullptr;
       }
   }

Ottenere il lettore remoto

Il lettore di comunicazione remota Windows Holographic viene offerto in Windows App Store come endpoint per la connessione alle app host remoti. Per ottenere il lettore di comunicazione remota windows Holographic, visitare l'app Store di Windows da HoloLens, cercare Remoting e scaricare l'app. Il lettore remoto include una funzionalità per visualizzare statistiche sullo schermo, che possono essere utili durante il debug delle app host remoti.

Note e risorse

La visualizzazione dell'app olografica richiederà un modo per fornire all'app il dispositivo Direct3D, che deve essere usato per inizializzare lo spazio olografico. L'app deve usare questo dispositivo Direct3D per copiare e visualizzare il frame di anteprima.

internal:
       const std::shared_ptr<DX::DeviceResources>& GetDeviceResources()
       {
           return m_deviceResources;
       }

Esempio di codice: È disponibile un esempio di codice Holographic Remoting completo, che include una visualizzazione dell'applicazione olografica compatibile con i progetti host remoti e remoti per desktop Win32, UWP DirectX e UWP con XAML.

Nota di debug: La libreria Holographic Remoting può generare eccezioni first-chance. Queste eccezioni possono essere visibili nelle sessioni di debug, a seconda delle impostazioni delle eccezioni di Visual Studio attive al momento. Queste eccezioni vengono rilevate internamente dalla libreria Holographic Remoting e possono essere ignorate.

Vedere anche