Escritura de una aplicación de reproductor de control remoto de holografías personalizadaWriting a custom Holographic Remoting player app

Importante

En este documento se describe la creación de una aplicación de reproductor personalizada para HoloLens 2.This document describes the creation of a custom player application for HoloLens 2. Los reproductores personalizados escritos para HoloLens 2 no son compatibles con las aplicaciones remotas escritas para HoloLens 1.Custom players written for HoloLens 2 are not compatible with remote applications written for HoloLens 1. Esto implica que ambas aplicaciones deben usar el paquete NuGet versión 2. x. x.This implies that both applications must use NuGet package version 2.x.x.

Mediante la creación de una aplicación de reproductor de comunicación remota holográfica personalizada, puede crear una aplicación personalizada capaz de mostrar vistas envolventes desde en una máquina remota de HoloLens 2.By creating a custom Holographic Remoting player app, you can create a custom application capable of displaying immersive views from on a remote machine on your 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 la comunicación remota de Holographic.All code on this page and working projects can be found in the Holographic Remoting samples github repository.

Un reproductor remoto holográfica permite que la aplicación muestre el contenido holográfica representado en un equipo de escritorio o un dispositivo UWP como la Xbox One con acceso a más recursos del sistema.A Holographic Remoting player lets your app display holographic content rendered on a desktop PC or UWP device like the Xbox One with access to more system resources. Una aplicación de reproductor de comunicación remota holográfica transmite datos de entrada a una aplicación remota de Holographic Remoting y recibe una vista envolvente como flujo de audio y vídeo.A Holographic Remoting player app streams input data to a Holographic Remoting remote application and receives back an immersive view as video and audio stream. La conexión se realiza mediante Wi-Fi estándar.The connection is made using standard Wi-Fi. Para crear una aplicación de reproductor, use un paquete NuGet para agregar la comunicación remota holográfica a la aplicación de UWP.To create a player app, use a NuGet package to add Holographic Remoting to your UWP app. A continuación, escriba el código para controlar la conexión y mostrar una vista envolvente.Then write code to handle the connection and to display an immersive view.

Requisitos previosPrerequisites

Un buen punto de partida es una aplicación UWP basada en DirectX que ya tiene como destino la API de Windows Mixed Reality.A good starting point is a working DirectX based UWP app that already targets the Windows Mixed Reality API. Para obtener más información, vea Introducción al desarrollo de DirectX.For details see DirectX development overview. Si no tiene una aplicación existente y desea comenzar desde el principio, la plantilla de proyecto de C++ Holographic es un buen punto de partida.If you don't have an existing app and want to start from scratch the C++ holographic project template is a good starting point.

Importante

Cualquier aplicación que use la comunicación remota de Holographic debe crearse para usar un Apartamento multiproceso.Any app using Holographic Remoting should be authored to use a multi-threaded apartment. Se admite el uso de un apartamento de un solo subproceso , pero se producirá un rendimiento poco óptimo y posiblemente se produzca una intermitencia durante la reproducción.The use of a single-threaded apartment is supported but will lead to sub-optimal performance and possibly stuttering during playback. Al usar C++/WinRT WinRT:: init_apartment un apartamento multiproceso es el valor predeterminado.When using C++/WinRT winrt::init_apartment a multi-threaded apartment is the default.

Obtención del paquete NuGet de Holographic RemotingGet the Holographic Remoting NuGet package

Los pasos siguientes son necesarios para agregar el paquete NuGet a un proyecto en Visual Studio.The following steps are required to add the NuGet package to a project in Visual Studio.

  1. Abra el proyecto en Visual Studio.Open the project in Visual Studio.
  2. Haga clic con el botón derecho en el nodo del proyecto y seleccione administrar paquetes NuGet...Right-click the project node and select Manage NuGet Packages...
  3. En el panel que aparece, seleccione examinar y busque "Holographic Remoting".In the panel that appears, select Browse and then search for "Holographic Remoting".
  4. Seleccione Microsoft. Holographic. Remoting, asegúrese de elegir la versión 2. x. x más reciente y seleccione instalar.Select Microsoft.Holographic.Remoting, ensure to pick the latest 2.x.x version and select Install.
  5. Si aparece el cuadro de diálogo vista previa , seleccione Aceptar.If the Preview dialog appears, select OK.
  6. Seleccione acepto cuando aparezca el cuadro de diálogo contrato de licencia.Select I Accept when the license agreement dialog appears.

Importante

build\native\include\HolographicAppRemoting\Microsoft.Holographic.AppRemoting.idlEn el paquete NuGet se incluye documentación detallada para la API expuesta por la comunicación remota holográfica.The build\native\include\HolographicAppRemoting\Microsoft.Holographic.AppRemoting.idl inside the NuGet package contains detailed documentation for the API exposed by Holographic Remoting.

Modificar el paquete. appxmanifest de la aplicaciónModify the Package.appxmanifest of the application

Para que la aplicación tenga en cuenta los Microsoft.Holographic.AppRemoting.dll agregados por el paquete de NuGet, es necesario realizar los siguientes pasos en el proyecto:To make the application aware of the Microsoft.Holographic.AppRemoting.dll added by the NuGet package, the following steps need to be taken on the project:

  1. En el Explorador de soluciones haga clic con el botón derecho en el archivo Package. appxmanifest y seleccione abrir con. ..In the Solution Explorer right-click on the Package.appxmanifest file and select Open With...
  2. Seleccione Editor XML (texto) y haga clic en Aceptar .Select XML (Text) Editor and select OK
  3. Agregue las líneas siguientes al archivo y guárdelaAdd the following lines to the file and save
  </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>

Crear el contexto del reproductorCreate the player context

Como primer paso, la aplicación debe crear un contexto de reproductor.As a first step the application should create a player context.

// 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

Holographic Remoting funciona reemplazando el tiempo de ejecución de Windows Mixed Reality, que forma parte de Windows con un tiempo de ejecución específico de comunicación remota.Holographic Remoting works by replacing the Windows Mixed Reality runtime which is part of Windows with a remoting specific runtime. Esto se realiza durante la creación del contexto del reproductor.This is done during the creation of the player context. Por ese motivo, cualquier llamada en cualquier API de Windows Mixed Reality antes de crear el contexto del reproductor puede producir un comportamiento inesperado.For that reason any call on any Windows Mixed Reality API before creating the player context can result in unexpected behavior. El enfoque recomendado es crear el contexto del reproductor tan pronto como sea posible antes de la interacción con cualquier API de realidad mixta.The recommended approach is to create the player context as early as possible before interaction with any Mixed Reality API. Nunca mezcle objetos creados o recuperados a través de cualquier API de realidad mixta de Windows antes de la llamada a PlayerContext::Create con objetos creados o recuperados después.Never mix objects created or retrieved through any Windows Mixed Reality API before the call to PlayerContext::Create with objects created or retrieved afterwards.

A continuación, se puede crear el HolographicSpace llamando a HolographicSpace. CreateForCoreWindow.Next the HolographicSpace can be created, by calling HolographicSpace.CreateForCoreWindow.

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

Conexión a la aplicación remotaConnect to the remote app

Una vez que la aplicación de reproducción está lista para la representación de contenido, se puede establecer una conexión con la aplicación remota.Once the player app is ready for rendering content a connection to the remote app can be established.

La conexión se puede establecer de una de las siguientes maneras:The connection can be established in one of the following ways:

  1. La aplicación de reproducción que se ejecuta en HoloLens 2 se conecta a la aplicación remota.The player app running on HoloLens 2 connects to the remote app.
  2. La aplicación remota se conecta a la aplicación de reproductor que se ejecuta en HoloLens 2.The remote app connects to the player app running on HoloLens 2.

Para conectarse desde la aplicación de reproducción a la aplicación remota, llame al Connect método en el contexto del reproductor y especifique el nombre de host y el puerto.To connect from the player app to the remote app call the Connect method on the player context specifying the hostname and port. El puerto predeterminado es 8265.The default port is 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

Como con cualquier API de C++/WinRT, Connect puede producir una excepción WinRT:: hresult_error que debe controlarse.As with any C++/WinRT API Connect might throw an winrt::hresult_error which needs to be handled.

La escucha de conexiones entrantes en la aplicación del reproductor puede realizarse mediante una llamada al Listen método.Listening for incoming connections on the player app can be done by calling the Listen method. El puerto de enlace y el puerto de transporte se pueden especificar durante esta llamada.Both the handshake port and transport port can be specified during this call. El puerto de enlace se usa para el protocolo de enlace inicial.The handshake port is used for the initial handshake. A continuación, los datos se envían a través del puerto de transporte.The data is then sent over the transport port. De forma predeterminada, se usan el número de puerto 8265 y 8266 .By default port number 8265 and 8266 are used.

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

PlayerContextExpone tres eventos para supervisar el estado de la conexión.The PlayerContext exposes three events to monitor the state of the connection

  1. OnConnection: se desencadena cuando se ha establecido correctamente una conexión con la aplicación remota.OnConnected: Triggered when a connection to the remote app has been successfully established.
m_onConnectedEventToken = m_playerContext.OnConnected([]() 
{
    // Handle connection successfully established
});
  1. OnDisconnection: se desencadena si se termina una conexión establecida o no se pudo establecer una conexión.OnDisconnected: Triggered if an established connection is terminated or a connection couldn't be established.
m_onDisconnectedEventToken = m_playerContext.OnDisconnected([](ConnectionFailureReason failureReason)
{
    switch (failureReason)
    {
        // Handle connection failed or terminated.
        // See ConnectionFailureReason for possible reasons.
    }
}

Nota

Los ConnectionFailureReason valores posibles se documentan en el Microsoft.Holographic.AppRemoting.idl archivo.Possible ConnectionFailureReason values are documented in the Microsoft.Holographic.AppRemoting.idl file.

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

Además, se puede consultar el estado de la conexión utilizando la ConnectionState propiedad en el contexto del reproductor.Additionally the connection state can be queried using the ConnectionState property on the player context.

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

Mostrar el marco representado de forma remotaDisplay the remotely rendered frame

Para mostrar el contenido representado de forma remota, llame a PlayerContext::BlitRemoteFrame mientras representa un HolographicFrame.To display the remotely rendered content, call PlayerContext::BlitRemoteFrame while rendering a HolographicFrame.

BlitRemoteFrame requiere que el búfer de reserva del HolographicFrame actual esté enlazado como destino de representación.BlitRemoteFrame requires that the back buffer for the current HolographicFrame is bound as render target. El búfer de reserva se puede recibir desde HolographicCameraRenderingParameters a través de la propiedad Direct3D11BackBuffer .The back buffer can be received from the HolographicCameraRenderingParameters via the Direct3D11BackBuffer property.

Cuando se llama, BlitRemoteFrame copia el último fotograma recibido de la aplicación remota en el búfer de reserva del HolographicFrame.When called, BlitRemoteFrame copies the latest received frame from the remote application into the BackBuffer of the 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.Additionally the focus point set is set, if the remote application has specified a focus point during the rendering of the remote frame.

// 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 para el marco actual.PlayerContext::BlitRemoteFrame potentially overwrites the focus point for the current frame.

Si se ejecuta correctamente, BlitRemoteFrame devuelve BlitResult::Success_Color .On success, BlitRemoteFrame returns BlitResult::Success_Color. En caso contrario, devuelve el motivo del error:Otherwise it returns the failure reason:

  • BlitResult::Failed_NoRemoteFrameAvailable: No se pudo ejecutar porque no hay ningún marco remoto disponible.BlitResult::Failed_NoRemoteFrameAvailable: Failed because no remote frame is available.
  • BlitResult::Failed_NoCamera: No se pudo realizar porque no hay ninguna cámara presente.BlitResult::Failed_NoCamera: Failed because no camera present.
  • BlitResult::Failed_RemoteFrameTooOld: No se pudo completar porque el marco remoto es demasiado antiguo (consulte la propiedad PlayerContext:: BlitRemoteFrameTimeout).BlitResult::Failed_RemoteFrameTooOld: Failed because remote frame is too old (see PlayerContext::BlitRemoteFrameTimeout property).

Importante

A partir de la versión 2.1.0 , es posible que un reproductor personalizado use la reproyección de profundidad mediante la comunicación remota de Holographic.Starting with version 2.1.0 it is possible with a custom player to use depth reprojection via Holographic Remoting.

BlitResult también puede devolver BlitResult::Success_Color_Depth en las siguientes condiciones:BlitResult can also return BlitResult::Success_Color_Depth under the following conditions:

Si se cumplen estas condiciones BlitRemoteFrame , la profundidad remota se convertirá en el búfer de profundidad local actualmente enlazado.If these conditions are met BlitRemoteFrame will blit the remote depth into the currently bound local depth buffer. Después, puede representar contenido local adicional, que tendrá una intersección de profundidad con el contenido representado remoto.You can then render additional local content, which will have depth intersection with the remote rendered content. Además, puede confirmar el búfer de profundidad local a través de HolographicCameraRenderingParameters. CommitDirect3D11DepthBuffer en el reproductor personalizado para tener una reproyección de profundidad para el contenido representado de forma local y remota.Additionally you can commit the local depth buffer via HolographicCameraRenderingParameters.CommitDirect3D11DepthBuffer in your custom player to have depth reprojection for remote and local rendered content. Consulte reproyección de profundidad para obtener más información.See Depth Reprojection for details.

Modo de transformación de proyecciónProjection Transform Mode

Un problema, que se muestra al usar la reproyección de profundidad a través de la comunicación remota de Holographic, es que el contenido remoto se puede representar con una transformación de proyección diferente que el contenido local que representa directamente la aplicación de reproductor personalizada.One problem, which surfaces when using depth reprojection via Holographic Remoting is that the remote content can be rendered with a different projection transform than local content directly rendered by your custom player app. Un caso de uso común es especificar valores diferentes para el plano Near y Far (a través de HolographicCamera:: SetNearPlaneDistance y HolographicCamera:: SetFarPlaneDistance) en el lado del reproductor y en el lado remoto.A common use-case is to specify different values for near and far plane (via HolographicCamera::SetNearPlaneDistance and HolographicCamera::SetFarPlaneDistance) on the player side and the remote side. En este caso, no está claro si la transformación de proyección en el lado del reproductor debe reflejar las distancias de plano Near/Far remoto o las locales.In this case, it's not clear if the projection transform on the player side should reflect the remote near/far plane distances or the local ones.

A partir de la versión 2.1.0 , puede controlar el modo de transformación de proyección a través de PlayerContext::ProjectionTransformConfig .Starting with version 2.1.0 you can control the projection transform mode via PlayerContext::ProjectionTransformConfig. Los valores admitidos son:Supported values are:

  • Local - HolographicCameraPose::P rojectiontransform devuelve una transformación de proyección, que refleja las distancias de plano Near/Far establecidas por la aplicación de reproductor personalizada en el HolographicCamera.Local - HolographicCameraPose::ProjectionTransform returns a projection transform, which reflects the near/far plane distances set by your custom player app on the HolographicCamera.
  • Remote -La transformación de proyección refleja las distancias de plano Near y Far especificadas por la aplicación remota.Remote - Projection transform reflects the near/far plane distances specified by the remote app.
  • Merged -Las distancias de plano Near y Far desde la aplicación remota y la aplicación de reproductor personalizada se combinan.Merged - Near/Far plane distances from your remote app and your custom player app are merged. De forma predeterminada, esto se realiza tomando el mínimo de las distancias de plano cercanos y el máximo de las distancias de plano lejano.By default this is done by taking the minimum of the near plane distances and the maximum of the far plane distances. En caso de que se invierta el lado remoto o el local, por ejemplo, < Near, se voltean las distancias de plano Near/Far remoto.In case either the remote or local side are inverted, say far < near, the remote near/far plane distances are flipped.

Opcional: establecer BlitRemoteFrameTimeout Optional: Set BlitRemoteFrameTimeout

Importante

PlayerContext::BlitRemoteFrameTimeout se admite a partir de la versión 2.0.9.PlayerContext::BlitRemoteFrameTimeout is supported starting with version 2.0.9.

La PlayerContext::BlitRemoteFrameTimeout propiedad especifica la cantidad de tiempo que se reutiliza un marco remoto si no se recibe un nuevo marco remoto.The PlayerContext::BlitRemoteFrameTimeout property specifies the amount of time a remote frame is reused if no new remote frame is received.

Un caso de uso común es habilitar el tiempo de espera de BlitRemoteFrame para mostrar una pantalla en blanco si no se recibe ningún fotograma nuevo durante un período de tiempo determinado.A common use-case is to enable the BlitRemoteFrame timeout to display a blank screen if no new frames are received for a certain amount of time. Cuando está habilitado, el tipo de valor devuelto del BlitRemoteFrame método también se puede utilizar para cambiar a un contenido de reserva representado localmente.When enabled the return type of the BlitRemoteFrame method can also be used to switch to a locally rendered fallback content.

Para habilitar el tiempo de espera, establezca el valor de la propiedad en una duración igual o mayor que 100 ms.To enable the timeout, set the property value to a duration equal or greater than 100 ms. Para deshabilitar el tiempo de espera, establezca la propiedad en cero Duration.To disable the timeout, set the property to zero duration. Si el tiempo de espera está habilitado y no se recibe ningún marco remoto durante el tiempo establecido, BlitRemoteFrame producirá un error y devolverá Failed_RemoteFrameTooOld hasta que se reciba un nuevo marco remoto.If the timeout is enabled and no remote frame is received for the set duration, BlitRemoteFrame will fail and return Failed_RemoteFrameTooOld until a new remote frame is received.

using namespace std::chrono_literals;

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

Opcional: obtener estadísticas sobre el último marco remotoOptional: Get statistics about the last remote frame

Para diagnosticar problemas de rendimiento o de red, se pueden recuperar estadísticas sobre el último marco remoto a través de la PlayerContext::LastFrameStatistics propiedad.To diagnose performance or network issues, statistics about the last remote frame can be retrieved via the PlayerContext::LastFrameStatistics property. Las estadísticas se actualizan durante la llamada a HolographicFrame::P resentusingcurrentprediction.Statistics are updated during the call to HolographicFrame::PresentUsingCurrentPrediction.

// 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.For more information, see the PlayerFrameStatistics documentation in the Microsoft.Holographic.AppRemoting.idl file.

Opcional: canales de datos personalizadosOptional: Custom data channels

Los canales de datos personalizados se pueden usar para enviar datos de usuario a través de la conexión remota ya establecida.Custom data channels can be used to send user data over the already established remoting connection. Vea canales de datos personalizados para obtener más información.See custom data channels for more information.

Consulte tambiénSee Also