Custom Holographic Remoting data channels

Note

This guidance is specific to Holographic Remoting on HoloLens 2.

Use custom data channels to send custom data over an established remoting connection.

Important

Custom data channels require a custom remote app and a custom player app, as it allows for communication between the two custom apps.

Tip

A simple ping-pong example can be found in the remote and player samples inside the Holographic Remoting samples github repository. Uncomment #define ENABLE_CUSTOM_DATA_CHANNEL_SAMPLE inside the SampleRemoteMain.h / SamplePlayerMain.h files to enable the sample code.

Create a custom data channel

To create a custom data channel, the following fields are required:

std::recursive_mutex m_customDataChannelLock;
winrt::Microsoft::Holographic::AppRemoting::IDataChannel m_customDataChannel = nullptr;
winrt::Microsoft::Holographic::AppRemoting::IDataChannel::OnDataReceived_revoker m_customChannelDataReceivedEventRevoker;
winrt::Microsoft::Holographic::AppRemoting::IDataChannel::OnClosed_revoker m_customChannelClosedEventRevoker;

After a connection is successfully established, you can create new data channels from either the remote side, the player side, or both. Both the RemoteContext and the PlayerContext provide a CreateDataChannel() method for creating data channels. The first parameter is the channel ID, which is used to identify the data channel in subsequent operations. The second parameter is the priority, which specifies the priority with which data of this channel is transferred to the other side. Valid channel IDs on the remote side are from 0 up to and including 63, and 64 up to and including 127 for the player side. Valid priorities are Low, Medium, or High (on both sides).

To start the creation of a data channel on the remote side:

// Valid channel ids for channels created on the remote side are 0 up to and including 63
m_remoteContext.CreateDataChannel(0, DataChannelPriority::Low);

To start the creation of a data channel on the player side:

// Valid channel ids for channels created on the player side are 64 up to and including 127
m_playerContext.CreateDataChannel(64, DataChannelPriority::Low);

Note

To create a new custom data channel, only one side (either remote or player) needs to call the CreateDataChannel method.

Handling custom data channel events

To establish a custom data channel, the OnDataChannelCreated event needs to be handled (on both the player and the remote side). It triggers when a user data channel has been created by either side and provides a IDataChannel object, which can be used to send and receive data over this channel.

To register a listener on the OnDataChannelCreated event:

m_onDataChannelCreatedEventRevoker = m_remoteContext.OnDataChannelCreated(winrt::auto_revoke,
    [this](const IDataChannel& dataChannel, uint8_t channelId)
    {
        std::lock_guard lock(m_customDataChannelLock);
        m_customDataChannel = dataChannel;

        // Register to OnDataReceived and OnClosed event of the data channel here, see below...
    });

To get notified when data is received, register to the OnDataReceived event on the IDataChannel object provided by the OnDataChannelCreated handler. Register to the OnClosed event, to get notified when the data channel has been closed.

m_customChannelDataReceivedEventRevoker = m_customDataChannel.OnDataReceived(winrt::auto_revoke, 
    [this]()
    {
        // React on data received via the custom data channel here.
    });

m_customChannelClosedEventRevoker = m_customDataChannel.OnClosed(winrt::auto_revoke,
    [this]()
    {
        // React on data channel closed here.

        std::lock_guard lock(m_customDataChannelLock);
        if (m_customDataChannel)
        {
            m_customDataChannel = nullptr;
        }
    });

Sending data

To send data over a custom data channel, use the IDataChannel::SendData() method. The first parameter is a winrt::array_view<const uint8_t> to the data that should be send. The second parameter specifies where the data should be resend, until the other side acknowledge the reception.

Important

In case of bad network conditions, the same data packet might arrive more than once. The receiving code must be able to handle this situation.

uint8_t data[] = {1};
m_customDataChannel.SendData(data, true);

Closing a custom data channel

To close a custom data channel, use the IDataChannel::Close() method. Both sides will be notified by the OnClosed event once the custom data channel has been closed.

m_customDataChannel.Close();

See Also