Escritura de una aplicación de Holographic Remoting Player personalizada

Si no está familiarizado con la comunicación remota holográfica, puede que quiera leer nuestra introducción.

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.

Al crear una aplicación personalizada de reproductor de holographic Remoting, puedes crear una aplicación personalizada capaz de mostrar vistas inmersivas desde en un equipo remoto en tu 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 Holographic Remoting.

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 del 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 envolvente 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 envolvente.

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 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 Holographic Remoting 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 dentro del paquete NuGet contiene documentación detallada de la API expuesta por La comunicación remota holográfica.

Modificar package.appxmanifest de la aplicación

Para que la aplicación sea consciente del 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 siguientes líneas 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 enviado 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 mezcle 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 llamando 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, puede iniciar una winrt::hresult_error que debe controlarse.

La escucha de las conexiones entrantes en la aplicación del reproductor se puede realizar llamando 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.idlarchivo.

  1. OnListening: al escuchar las conexiones entrantes se inicia.
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 para el 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: no se pudo realizar porque no hay ningún marco remoto disponible.
  • BlitResult::Failed_NoCamera: no se pudo realizar porque no hay ninguna cámara presente.
  • BlitResult::Failed_RemoteFrameTooOld: error porque el marco remoto es demasiado antiguo (vea 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 siguientes condiciones:

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 una 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 de reproductor personalizada. 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/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 de plano casi lejanas 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 - Distancias cercanas o lejanas del plano desde la aplicación remota y la aplicación de reproductor personalizada se combinan. De forma predeterminada, esto se realiza 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, se voltean las distancias remotas del plano cercano o lejano.

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 nuevo marco remoto.

Un caso de uso común es permitir que el tiempo de espera de BlitRemoteFrame muestre una pantalla en blanco si no se reciben fotogramas nuevos durante un determinado período de tiempo. 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 cero duración. 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 de 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.idlarchivo .

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: Over-Rendering

La comunicación remota holográfica predice dónde estará la cabeza del usuario en el momento en que las imágenes representadas aparecen en las pantallas. Sin embargo, esta predicción es una aproximación. Por lo tanto, la ventanilla prevista 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 causar 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.

Over-Rendering se puede habilitar a través de PlayerContext::ConfigureOverRendering.

OverRenderingConfig especifica un aumento de tamaño fraccionado en la ventanilla real, de modo que la ventanilla prevista se haga más grande 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, vea Coordenadas de sincronización del sistema con información general sobre la comunicación remota holográfica.

Consulte también