diff --git a/Runtime/Prefabs/Render Streaming Services.prefab b/Runtime/Prefabs/Render Streaming Services.prefab index fe7f92f..31a455d 100644 --- a/Runtime/Prefabs/Render Streaming Services.prefab +++ b/Runtime/Prefabs/Render Streaming Services.prefab @@ -662,7 +662,7 @@ GameObject: m_Component: - component: {fileID: 1793859183747734309} - component: {fileID: 1793859183747734314} - - component: {fileID: 1793859183747734308} + - component: {fileID: 48972029} m_Layer: 0 m_Name: RenderStreaming m_TagString: Untagged @@ -707,9 +707,9 @@ MonoBehaviour: interval: 5 hardwareEncoderSupport: 1 handlers: - - {fileID: 1793859183747734308} + - {fileID: 48972029} runOnAwake: 1 ---- !u!114 &1793859183747734308 +--- !u!114 &48972029 MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -718,7 +718,7 @@ MonoBehaviour: m_GameObject: {fileID: 1793859183747734311} m_Enabled: 1 m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: c2307e7ad91222841b562bebd81a69a0, type: 3} + m_Script: {fileID: 11500000, guid: 31b94e633688a294abc5410d3190b6f5, type: 3} m_Name: m_EditorClassIdentifier: streams: diff --git a/Runtime/Scripts/VRBroadcast.cs b/Runtime/Scripts/VRBroadcast.cs new file mode 100644 index 0000000..58440a3 --- /dev/null +++ b/Runtime/Scripts/VRBroadcast.cs @@ -0,0 +1,97 @@ +/** + * Copyright 2021 Vasanth Mohan. All rights and licenses reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +using System.Collections.Generic; +using System.Linq; +using UnityEngine; +using Unity.RenderStreaming; + +namespace FusedVR.VRStreaming { + /// + /// VRBroadcast is very similar to the Broadcast script included with Render Streaming. + /// This script is responsible for listening for offers from the client and choosing when to respond. + /// + public class VRBroadcast : SignalingHandlerBase, + IOfferHandler, IAddChannelHandler, IDisconnectHandler, IDeletedConnectionHandler { + + /// + /// Streams (video, audio, data) that need to be sent to the client + /// + [SerializeField] + private List streams = new List(); + + /// + /// List of all connectionIds that are connected + /// + private List connectionIds = new List(); + + #region Disconnect + public void OnDeletedConnection(SignalingEventData eventData) { + Disconnect(eventData.connectionId); + } + + public void OnDisconnect(SignalingEventData eventData) { + Disconnect(eventData.connectionId); + } + + private void Disconnect(string connectionId) { + if (!connectionIds.Contains(connectionId)) + return; + connectionIds.Remove(connectionId); + + foreach (var source in streams.OfType()) { + source.SetSender(connectionId, null); + } + foreach (var receiver in streams.OfType()) { + receiver.SetReceiver(connectionId, null); + } + foreach (var channel in streams.OfType()) { + channel.SetChannel(connectionId, null); + } + } + #endregion + + /// + /// Event that is called when an Offer is made by a client + /// Determines whether to accept offer and if so that to apply sources and submit answer + /// + public void OnOffer(SignalingEventData data) { + if (connectionIds.Count >= 1) { //if there is more than 1 connection, let's skip this offer + Debug.Log($"Already answered this connectionId : {connectionIds[0]}"); + return; + } + + if (connectionIds.Contains(data.connectionId)) { //if connection is already connected, skip offer + Debug.Log($"Already answered this connectionId : {data.connectionId}"); + return; + } + connectionIds.Add(data.connectionId); //confirm we will use this connection + + foreach (var source in streams.OfType()) { + var transceiver = AddTrack(data.connectionId, source.Track); + source.SetSender(data.connectionId, transceiver.Sender); + } + foreach (var channel in streams.OfType().Where(c => c.IsLocal)) { + var _channel = CreateChannel(data.connectionId, channel.Label); + channel.SetChannel(data.connectionId, _channel); + } + SendAnswer(data.connectionId); //accept offer with an answer + } + + /// + /// Apply Data Channel + /// + public void OnAddChannel(SignalingEventData data) { + var channel = streams.OfType(). + FirstOrDefault(r => r.Channel == null && !r.IsLocal); + channel?.SetChannel(data.connectionId, data.channel); + } + } +} diff --git a/Runtime/Scripts/VRBroadcast.cs.meta b/Runtime/Scripts/VRBroadcast.cs.meta new file mode 100644 index 0000000..917872b --- /dev/null +++ b/Runtime/Scripts/VRBroadcast.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 31b94e633688a294abc5410d3190b6f5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: