Escritura de una aplicación de Holographic Remoting Player personalizada

Si no está familiarizado con la comunicación remota holográfica, es posible que quiera leer nuestra información general.

Importante

En este documento se describe la creación de una aplicación de reproductor personalizada para HoloLens 2. Los reproductores personalizados escritos para HoloLens 2 no son compatibles con las aplicaciones remotas escritas para HoloLens 1. Esto implica que ambas aplicaciones deben usar la versión 2.x.x del paquete NuGet.

Mediante la creación de una aplicación de reproductor de holographic Remoting personalizada, puede crear una aplicación personalizada capaz de mostrar vistas inmersivas desde en una máquina remota en HoloLens 2. Todo el código de esta página y los proyectos de trabajo se pueden encontrar en el repositorio de github de ejemplos de comunicación remota holográfica.

Un reproductor de comunicación remota holográfica permite a la aplicación mostrar contenido holográfico representado en un equipo de escritorio o dispositivo UWP como Xbox One con acceso a más recursos del sistema. Una aplicación de reproductor de comunicación remota holográfica transmite datos de entrada a una aplicación remota de comunicación remota holográfica y recibe una vista inmersiva como secuencia de vídeo y audio. La conexión se realiza mediante Wi-Fi estándar. Para crear una aplicación de reproductor, usa un paquete NuGet para agregar la comunicación remota holográfica a tu aplicación para UWP. A continuación, escriba código para controlar la conexión y mostrar una vista inmersiva.

Requisitos previos

Un buen punto de partida es una aplicación para UWP basada en DirectX que ya tiene como destino la API de Windows Mixed Reality. Para obtener más información, consulte Introducción al desarrollo de DirectX. Si no tiene una aplicación existente y desea empezar desde cero, la plantilla de proyecto holográfica de C++ es un buen punto de partida.

Importante

Cualquier aplicación que use la comunicación remota holográfica debe crearse para usar un apartamento multiproceso. Se admite el uso de un apartamento de un solo subproceso, pero dará lugar a un rendimiento óptimo y, posiblemente, a la reproducción. Cuando se usa C++/WinRT winrt::init_apartment un apartamento multiproceso es el valor predeterminado.

Obtención del paquete NuGet de comunicación remota holográfica

Los pasos siguientes son necesarios para agregar el paquete NuGet a un proyecto en Visual Studio.

  1. Abra el proyecto en Visual Studio.
  2. Haga clic con el botón derecho en el nodo del proyecto y seleccione Administrar paquetes NuGet...
  3. En el panel que aparece, seleccione Examinar y busque "Comunicación remota holográfica".
  4. Seleccione Microsoft.Holographic.Remoting, asegúrese de elegir la versión 2.x.x más reciente y seleccione Instalar.
  5. Si aparece el cuadro de diálogo Vista previa , seleccione Aceptar.
  6. Seleccione Acepto cuando aparezca el cuadro de diálogo contrato de licencia.

Importante

El build\native\include\HolographicAppRemoting\Microsoft.Holographic.AppRemoting.idl elemento dentro del paquete NuGet contiene documentación detallada sobre la API expuesta por la comunicación remota holográfica.

Modificar package.appxmanifest de la aplicación

Para que la aplicación tenga en cuenta el Microsoft.Holographic.AppRemoting.dll agregado por el paquete NuGet, es necesario realizar los pasos siguientes en el proyecto:

  1. En el Explorador de soluciones, haga clic con el botón derecho en el archivo Package.appxmanifest y seleccione Abrir con...
  2. Seleccione Editor XML (texto) y seleccione Aceptar.
  3. Agregue las líneas siguientes al archivo y guarde
  </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>

Creación del contexto del reproductor

Como primer paso, la aplicación debe crear un contexto de reproductor.

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

Advertencia

Un reproductor personalizado inserta una capa intermedia entre la aplicación del reproductor y el entorno de ejecución de Windows Mixed Reality incluido con Windows. Esto se hace durante la creación del contexto del jugador. Por ese motivo, cualquier llamada en cualquier API de Windows Mixed Reality antes de crear el contexto del reproductor puede dar lugar a un comportamiento inesperado. El enfoque recomendado es crear el contexto del jugador lo antes posible antes de la interacción con cualquier API de Mixed Reality. Nunca combine objetos creados o recuperados a través de cualquier API de Windows Mixed Reality antes de la llamada a PlayerContext::Create con objetos creados o recuperados posteriormente.

A continuación, se puede crear holographicSpace mediante una llamada a HolographicSpace.CreateForCoreWindow.

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

Conexión a la aplicación remota

Una vez que la aplicación del reproductor esté lista para representar contenido, se puede establecer una conexión a la aplicación remota.

La conexión se puede establecer de una de las maneras siguientes:

  1. La aplicación del reproductor que se ejecuta en HoloLens 2 se conecta a la aplicación remota.
  2. La aplicación remota se conecta a la aplicación del reproductor que se ejecuta en HoloLens 2.

Para conectarse desde la aplicación del reproductor a la aplicación remota, llame al Connect método en el contexto del reproductor especificando el nombre de host y el puerto. El puerto predeterminado es 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()
}

Importante

Al igual que con cualquier API Connect de C++/WinRT, podría producir un winrt::hresult_error que se debe controlar.

La escucha de conexiones entrantes en la aplicación del reproductor se puede realizar mediante una llamada al Listen método . Tanto el puerto de protocolo de enlace como el puerto de transporte se pueden especificar durante esta llamada. El puerto del protocolo de enlace se usa para el protocolo de enlace inicial. A continuación, los datos se envían a través del puerto de transporte. De forma predeterminada, se usan el número de puerto 8265 y 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()
}

PlayerContext expone tres eventos para supervisar el estado de la conexión.

  1. OnConnected: se desencadena cuando se ha establecido correctamente una conexión a la aplicación remota.
m_onConnectedEventToken = m_playerContext.OnConnected([]() 
{
    // Handle connection successfully established
});
  1. OnDisconnected: se desencadena si se finaliza una conexión establecida o no se pudo establecer una conexión.
m_onDisconnectedEventToken = m_playerContext.OnDisconnected([](ConnectionFailureReason failureReason)
{
    switch (failureReason)
    {
        // Handle connection failed or terminated.
        // See ConnectionFailureReason for possible reasons.
    }
}

Nota:

Los valores posibles ConnectionFailureReason se documentan en el Microsoft.Holographic.AppRemoting.idl archivo .

  1. OnListening: cuando se inicia la escucha de conexiones entrantes.
m_onListeningEventToken = m_playerContext.OnListening([]()
{
    // Handle start listening for incoming connections
});

Además, se puede consultar el estado de conexión mediante la ConnectionState propiedad en el contexto del reproductor.

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

Mostrar el marco representado de forma remota

Para mostrar el contenido representado de forma remota, llame a PlayerContext::BlitRemoteFrame mientras representa un HolographicFrame.

BlitRemoteFrame requiere que el búfer de reserva del holographicFrame actual esté enlazado como destino de representación. El búfer de reserva se puede recibir desde HolographicCameraRenderingParameters a través de la propiedad Direct3D11BackBuffer .

Cuando se llama a , BlitRemoteFrame copia el fotograma recibido más reciente de la aplicación remota en backBuffer del holographicFrame. Además, se establece el conjunto de puntos de enfoque, si la aplicación remota ha especificado un punto de enfoque durante la representación del marco remoto.

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

Nota:

PlayerContext::BlitRemoteFrame potencialmente sobrescribe el punto de enfoque del marco actual.

Si se ejecuta correctamente, BlitRemoteFrame devuelve BlitResult::Success_Color. De lo contrario, devuelve el motivo del error:

  • BlitResult::Failed_NoRemoteFrameAvailable: error porque no hay ningún marco remoto disponible.
  • BlitResult::Failed_NoCamera: error porque no hay ninguna cámara presente.
  • BlitResult::Failed_RemoteFrameTooOld: error porque el marco remoto es demasiado antiguo (consulte la propiedad PlayerContext::BlitRemoteFrameTimeout).

Importante

A partir de la versión 2.1.0 , es posible que un reproductor personalizado use la reproyecto de profundidad a través de la comunicación remota holográfica.

BlitResult también puede devolverse BlitResult::Success_Color_Depth en las condiciones siguientes:

Si se cumplen estas condiciones, BlitRemoteFrame blitá la profundidad remota en el búfer de profundidad local enlazado actualmente. A continuación, puede representar contenido local adicional, que tendrá una intersección de profundidad con el contenido representado remotamente. Además, puede confirmar el búfer de profundidad local a través de HolographicCameraRenderingParameters.CommitDirect3D11DepthBuffer en el reproductor personalizado para tener reproyecto de profundidad para contenido representado local y remoto.

Modo de transformación de proyección

Un problema, que se muestra al usar la reproyecto de profundidad a través de la comunicación remota holográfica es que el contenido remoto se puede representar con una transformación de proyección diferente que el contenido local representado directamente por la aplicación del reproductor personalizado. Un caso de uso común es especificar valores diferentes para plano cercano y lejano (a través de HolographicCamera::SetNearPlaneDistance y HolographicCamera::SetFarPlaneDistance) en el lado del jugador y en el lado remoto. En este caso, no está claro si la transformación de proyección en el lado del jugador debe reflejar las distancias remotas del plano cercano y lejano o las locales.

A partir de la versión 2.1.0 , puede controlar el modo de transformación de proyección a través PlayerContext::ProjectionTransformConfigde . Los valores admitidos son:

  • Local - HolographicCameraPose::P rojectionTransform devuelve una transformación de proyección, que refleja las distancias del plano cercano y lejano establecidas por la aplicación de reproductor personalizada en HolographicCamera.
  • Remote - La transformación de proyección refleja las distancias del plano cercano y lejano especificadas por la aplicación remota.
  • Merged - Las distancias de plano cercano y lejano desde la aplicación remota y la aplicación del reproductor personalizado se combinan. De forma predeterminada, esto se hace tomando el mínimo de las distancias del plano cercano y el máximo de las distancias del plano lejano. En caso de que el lado remoto o local se invierten, por ejemplo, muy < cerca, las distancias remotas del plano cercano o lejano se voltean.

Opcional: Establecer BlitRemoteFrameTimeout

Importante

PlayerContext::BlitRemoteFrameTimeout se admite a partir de la versión 2.0.9.

La PlayerContext::BlitRemoteFrameTimeout propiedad especifica la cantidad de tiempo que se reutiliza un marco remoto si no se recibe ningún marco remoto nuevo.

Un caso de uso común es permitir que el tiempo de espera BlitRemoteFrame muestre una pantalla en blanco si no se reciben nuevos fotogramas durante un período de tiempo determinado. Cuando se habilita el tipo de valor devuelto del BlitRemoteFrame método también se puede usar para cambiar a un contenido de reserva representado localmente.

Para habilitar el tiempo de espera, establezca el valor de la propiedad en una duración igual o mayor que 100 ms. Para deshabilitar el tiempo de espera, establezca la propiedad en una duración cero. Si el tiempo de espera está habilitado y no se recibe ningún fotograma remoto durante la duración establecida, se producirá un error en BlitRemoteFrame y se devolverá Failed_RemoteFrameTooOld hasta que se reciba un nuevo fotograma remoto.

using namespace std::chrono_literals;

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

Opcional: Obtener estadísticas sobre el último fotograma remoto

Para diagnosticar problemas de rendimiento o red, se pueden recuperar estadísticas sobre el último fotograma remoto a través de la PlayerContext::LastFrameStatistics propiedad . Las estadísticas se actualizan durante la llamada a HolographicFrame::P resentUsingCurrentPrediction.

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

Para obtener más información, consulte la PlayerFrameStatistics documentación del Microsoft.Holographic.AppRemoting.idl archivo .

Opcional: Canales de datos personalizados

Los canales de datos personalizados se pueden usar para enviar datos de usuario a través de la conexión remota ya establecida. Para más información, consulte canales de datos personalizados.

Opcional: Representación excesiva

La comunicación remota holográfica predice dónde estará la cabeza del usuario en el momento en que aparecen las imágenes representadas en las pantallas. Sin embargo, esta predicción es una aproximación. Por lo tanto, la ventanilla predicha en la aplicación remota y la ventanilla real posterior en la aplicación del reproductor puede diferir. Las desviaciones más fuertes (por ejemplo, debido a un movimiento impredecible) podrían provocar regiones negras en los bordes del frustum de visualización. A partir de la versión 2.6.0 , puede usar Over-Rendering para reducir las regiones negras y mejorar la calidad visual aumentando artificialmente la ventanilla más allá del frustum de visualización.

La representación excesiva se puede habilitar a través de PlayerContext::ConfigureOverRendering.

OverRenderingConfig especifica un aumento de tamaño fraccionario a la ventanilla real, de modo que la ventanilla prevista sea mayor y se produzca menos corte. Con un mayor tamaño de ventanilla, la densidad de píxeles disminuye, por lo que OverRenderingConfig también le permite aumentar la resolución. Si el aumento de la ventanilla es igual al aumento de la resolución, la densidad de píxeles sigue siendo la misma. OverRenderingConfig se define como:

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

Opcional: Sincronización del sistema de coordenadas

A partir de la versión 2.7.0 , la sincronización del sistema de coordenadas se puede usar para alinear los datos espaciales entre el reproductor y la aplicación remota. Para obtener más información, consulte Coordinate System Synchronization with Holographic Remoting Overview (Sincronización del sistema de coordenadas con información general sobre la comunicación remota holográfica).

Consulte también