Пример #1
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="hardwareEncoder"></param>
 /// <param name="signaling"></param>
 /// <param name="handlers"></param>
 public void Run(
     bool?hardwareEncoder            = null,
     ISignaling signaling            = null,
     SignalingHandlerBase[] handlers = null)
 {
     _Run(null, hardwareEncoder, signaling, handlers);
 }
Пример #2
0
        public IEnumerator UnitySetUp()
        {
            WebRTC.WebRTC.Initialize();

            RTCConfiguration config     = default;
            RTCIceCandidate  candidate_ = null;

            config.iceServers = new[] { new RTCIceServer {
                                            urls = new[] { "stun:stun.l.google.com:19302" }
                                        } };

            var peer1 = new RTCPeerConnection(ref config);
            var peer2 = new RTCPeerConnection(ref config);

            peer1.OnIceCandidate = candidate => { candidate_ = candidate; };

            MediaStream stream = WebRTC.Audio.CaptureStream();

            peer1.AddTrack(stream.GetTracks().First());

            RTCOfferOptions offerOptions = new RTCOfferOptions();
            var             op1          = peer1.CreateOffer(ref offerOptions);

            yield return(op1);

            m_DescOffer = op1.Desc;
            var op2 = peer1.SetLocalDescription(ref m_DescOffer);

            yield return(op2);

            var op3 = peer2.SetRemoteDescription(ref m_DescOffer);

            yield return(op3);

            RTCAnswerOptions answerOptions = new RTCAnswerOptions();
            var op4 = peer2.CreateAnswer(ref answerOptions);

            yield return(op4);

            m_DescAnswer = op4.Desc;
            var op5 = peer2.SetLocalDescription(ref m_DescAnswer);

            yield return(op5);

            var op6 = peer1.SetRemoteDescription(ref m_DescAnswer);

            yield return(op6);

            yield return(new WaitUntil(() => candidate_ != null));

            m_candidate = candidate_;

            stream.Dispose();
            peer1.Close();
            peer2.Close();

            m_Context  = SynchronizationContext.Current;
            signaling1 = CreateSignaling(m_SignalingType, m_Context);
            signaling2 = CreateSignaling(m_SignalingType, m_Context);
        }
Пример #3
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="dependencies"></param>
        public RenderStreamingInternal(ref RenderStreamingDependencies dependencies)
        {
            if (dependencies.signaling == null)
            {
                throw new ArgumentException("Signaling instance is null.");
            }
            if (dependencies.startCoroutine == null)
            {
                throw new ArgumentException("Coroutine action instance is null.");
            }

            if (s_list.Count == 0)
            {
                WebRTC.WebRTC.Initialize(dependencies.encoderType);
            }

            _config                         = dependencies.config;
            _startCoroutine                 = dependencies.startCoroutine;
            _signaling                      = dependencies.signaling;
            _signaling.OnStart             += OnStart;
            _signaling.OnCreateConnection  += OnCreateConnection;
            _signaling.OnDestroyConnection += OnDestroyConnection;
            _signaling.OnOffer             += OnOffer;
            _signaling.OnAnswer            += OnAnswer;
            _signaling.OnIceCandidate      += OnIceCandidate;
            _signaling.Start();

            s_list.Add(this);
            _startCoroutine(WebRTC.WebRTC.Update());
        }
Пример #4
0
 void OnDisable()
 {
     if (this.m_signaling != null)
     {
         this.m_signaling.Stop();
         this.m_signaling = null;
     }
 }
Пример #5
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="conf"></param>
 /// <param name="hardwareEncoder"></param>
 /// <param name="signaling"></param>
 /// <param name="handlers"></param>
 /// <remarks> To use this method, Need to depend WebRTC package </remarks>
 public void Run(
     RTCConfiguration conf,
     bool?hardwareEncoder            = null,
     ISignaling signaling            = null,
     SignalingHandlerBase[] handlers = null
     )
 {
     _Run(conf, hardwareEncoder, signaling, handlers);
 }
 void OnStart(ISignaling signaling)
 {
     if (!_runningResendCoroutine)
     {
         _runningResendCoroutine = true;
         _startCoroutine(ResendOfferCoroutine());
     }
     onStart?.Invoke();
 }
Пример #7
0
 void OnAnswer(ISignaling signaling, DescData e)
 {
     if (!_mapConnectionIdAndPeer.TryGetValue(e.connectionId, out var pc))
     {
         Debug.Log($"connectionId:{e.connectionId}, peerConnection not exist");
         return;
     }
     _startCoroutine(GotAnswerCoroutine(e.connectionId, pc, e.sdp));
 }
Пример #8
0
        void OnOffer(ISignaling signaling, DescData e)
        {
            var connectionId = e.connectionId;

            if (!_mapConnectionIdAndPeer.TryGetValue(connectionId, out var pc))
            {
                pc = CreatePeerConnection(connectionId, false);
            }
            _startCoroutine(GotOfferCoroutine(connectionId, pc, e.sdp));
        }
Пример #9
0
        void OnCreateConnection(ISignaling signaling, string connectionId, bool peerExists)
        {
            var pc = CreatePeerConnection(signaling, connectionId, peerExists);

            if (!peerExists)
            {
                return;
            }

            AddTracks(connectionId, pc);
        }
Пример #10
0
        void OnDestroyConnection(ISignaling signaling, string connectionId)
        {
            if (m_mapConnectionIdAndPeer.TryGetValue(connectionId, out var pc))
            {
                RemoveTracks(connectionId, pc);
                m_mapPeerAndChannelDictionary.Remove(pc);
                pc.Dispose();
            }

            m_mapConnectionIdAndPeer.Remove(connectionId);
        }
Пример #11
0
 void OnEnable()
 {
     if (this.m_signaling == null)
     {
         Type     t    = Type.GetType(signalingType);
         object[] args = { urlSignaling, interval };
         this.m_signaling                 = (ISignaling)Activator.CreateInstance(t, args);
         this.m_signaling.OnOffer        += OnOffer;
         this.m_signaling.OnIceCandidate += OnIceCandidate;
     }
     this.m_signaling.Start();
 }
Пример #12
0
        private void _Run(
            RTCConfiguration?conf           = null,
            bool?hardwareEncoder            = null,
            ISignaling signaling            = null,
            SignalingHandlerBase[] handlers = null
            )
        {
            RTCConfiguration _conf =
                conf.GetValueOrDefault(new RTCConfiguration {
                iceServers = iceServers
            });

            if (hardwareEncoder != null)
            {
                hardwareEncoderSupport = hardwareEncoder.Value;
            }
            var encoderType = hardwareEncoderSupport ? EncoderType.Hardware : EncoderType.Software;

            if (signaling != null)
            {
                signalingType = signaling.GetType().FullName;

                //todo:: This property is not needed by FurioosSignaling.
                urlSignaling = signaling.Url;
                interval     = signaling.Interval;
            }
            ISignaling _signaling = signaling ?? CreateSignaling(
                signalingType, urlSignaling, interval, SynchronizationContext.Current);
            RenderStreamingDependencies dependencies = new RenderStreamingDependencies
            {
                config              = _conf,
                encoderType         = encoderType,
                signaling           = _signaling,
                startCoroutine      = StartCoroutine,
                resentOfferInterval = interval,
            };
            var _handlers = (handlers ?? this.handlers.AsEnumerable()).Where(_ => _ != null);

            if (_handlers.Count() == 0)
            {
                throw new InvalidOperationException("Handler list is empty.");
            }

            m_instance = new RenderStreamingInternal(ref dependencies);
            m_provider = new SignalingEventProvider(m_instance);

            foreach (var handler in _handlers)
            {
                handler.SetHandler(m_instance);
                m_provider.Subscribe(handler);
            }
            m_running = true;
        }
Пример #13
0
        void OnCreateConnection(ISignaling signaling, string connectionId, bool peerExists)
        {
            CreatePeerConnection(connectionId, peerExists);

            if (peerExists)
            {
                onFoundConnection?.Invoke(connectionId);
            }
            else
            {
                onCreatedConnection?.Invoke(connectionId);
            }
        }
Пример #14
0
        IEnumerator OnOffer(ISignaling signaling, DescData e)
        {
            var connectionId     = e.connectionId;
            RTCPeerConnection pc = null;

            if (!m_mapConnectionIdAndPeer.TryGetValue(connectionId, out pc))
            {
                pc = CreatePeerConnection(signaling, connectionId, false);
            }

            RTCSessionDescription _desc;

            _desc.type = RTCSdpType.Offer;
            _desc.sdp  = e.sdp;

            var opRemoteDesc = pc.SetRemoteDescription(ref _desc);

            yield return(opRemoteDesc);

            if (opRemoteDesc.IsError)
            {
                Debug.LogError($"Network Error: {opRemoteDesc.Error.message}");
                yield break;
            }

            AddTracks(connectionId, pc);

            RTCAnswerOptions options = default;
            var op = pc.CreateAnswer(ref options);

            yield return(op);

            if (op.IsError)
            {
                Debug.LogError($"Network Error: {op.Error.message}");
                yield break;
            }

            var desc        = op.Desc;
            var opLocalDesc = pc.SetLocalDescription(ref desc);

            yield return(opLocalDesc);

            if (opLocalDesc.IsError)
            {
                Debug.LogError($"Network Error: {opLocalDesc.Error.message}");
                yield break;
            }

            signaling.SendAnswer(connectionId, desc);
        }
Пример #15
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="conf"></param>
        /// <param name="hardwareEncoder"></param>
        /// <param name="signaling"></param>
        /// <param name="handlers"></param>
        public void Run(
            RTCConfiguration?conf           = null,
            bool?hardwareEncoder            = null,
            ISignaling signaling            = null,
            SignalingHandlerBase[] handlers = null
            )
        {
            RTCConfiguration _conf =
                conf.GetValueOrDefault(new RTCConfiguration {
                iceServers = iceServers
            });

            if (hardwareEncoder != null)
            {
                hardwareEncoderSupport = hardwareEncoder.Value;
            }
            var encoderType = hardwareEncoderSupport ? EncoderType.Hardware : EncoderType.Software;

            if (signaling != null)
            {
                signalingType = signaling.GetType().FullName;

                //todo:: This property is not needed by FurioosSignaling.
                urlSignaling = signaling.Url;
                interval     = signaling.Interval;
            }
            ISignaling _signaling = signaling ?? CreateSignaling(
                signalingType, urlSignaling, interval, SynchronizationContext.Current);
            RenderStreamingDependencies dependencies = new RenderStreamingDependencies
            {
                config              = _conf,
                encoderType         = encoderType,
                signaling           = _signaling,
                startCoroutine      = StartCoroutine,
                resentOfferInterval = interval,
            };

            m_instance = new RenderStreamingInternal(ref dependencies);
            m_provider = new SignalingEventProvider(m_instance);

            SignalingHandlerBase[] _handlers = handlers ?? this.handlers.ToArray();

            foreach (var source in _handlers)
            {
                source.SetHandler(m_instance);
                m_provider.Subscribe(source);
            }
            m_running = true;
        }
Пример #16
0
        void OnIceCandidate(ISignaling signaling, CandidateData e)
        {
            if (!m_mapConnectionIdAndPeer.TryGetValue(e.connectionId, out var pc))
            {
                return;
            }

            RTCIceCandidate​ _candidate = default;

            _candidate.candidate     = e.candidate;
            _candidate.sdpMLineIndex = e.sdpMLineIndex;
            _candidate.sdpMid        = e.sdpMid;

            pc.AddIceCandidate(ref _candidate);
        }
Пример #17
0
        void Awake()
        {
            if (!runOnAwake || m_running)
            {
                return;
            }

            RTCConfiguration conf = new RTCConfiguration {
                iceServers = iceServers
            };
            ISignaling signaling = CreateSignaling(
                signalingType, urlSignaling, interval, SynchronizationContext.Current);

            Run(conf, hardwareEncoderSupport, signaling, handlers.ToArray());
        }
Пример #18
0
        void OnIceCandidate(ISignaling signaling, CandidateData e)
        {
            if (!m_mapConnectionIdAndPeer.TryGetValue(e.connectionId, out var pc))
            {
                return;
            }

            RTCIceCandidateInit option = new RTCIceCandidateInit
            {
                candidate     = e.candidate,
                sdpMLineIndex = e.sdpMLineIndex,
                sdpMid        = e.sdpMid
            };

            pc.AddIceCandidate(new RTCIceCandidate(option));
        }
Пример #19
0
        IEnumerator OnNegotiationNeeded(ISignaling signaling, string connectionId, bool isOffer)
        {
            if (!isOffer)
            {
                yield break;
            }

            if (!m_mapConnectionIdAndPeer.TryGetValue(connectionId, out var pc))
            {
                Debug.LogError($"connectionId: {connectionId}, did not created peerConnection");
                yield break;
            }

            RTCOfferOptions option = new RTCOfferOptions
            {
                offerToReceiveAudio = true,
                offerToReceiveVideo = true
            };
            var offerOp = pc.CreateOffer(ref option);

            yield return(offerOp);

            if (offerOp.IsError)
            {
                Debug.LogError($"Network Error: {offerOp.Error.message}");
                yield break;
            }

            if (pc.SignalingState != RTCSignalingState.Stable)
            {
                Debug.LogError($"peerConnection's signaling state is not stable.");
                yield break;
            }

            var desc        = offerOp.Desc;
            var setLocalSdp = pc.SetLocalDescription(ref desc);

            yield return(setLocalSdp);

            if (setLocalSdp.IsError)
            {
                Debug.LogError($"Network Error: {setLocalSdp.Error.message}");
                yield break;
            }

            signaling.SendOffer(connectionId, desc);
        }
        void OnIceCandidate(ISignaling signaling, CandidateData e)
        {
            if (!_mapConnectionIdAndPeer.TryGetValue(e.connectionId, out var pc))
            {
                return;
            }

            RTCIceCandidateInit option = new RTCIceCandidateInit
            {
                candidate = e.candidate, sdpMLineIndex = e.sdpMLineIndex, sdpMid = e.sdpMid
            };

            if (!pc.peer.AddIceCandidate(new RTCIceCandidate(option)) && !pc.ignoreOffer)
            {
                Debug.LogWarning($"{pc} this candidate can't accept current signaling state {pc.peer.SignalingState}.");
            }
        }
Пример #21
0
        void OnEnable()
        {
            if (this.m_signaling == null)
            {
                Type     t    = Type.GetType(signalingType);
                object[] args = { urlSignaling, interval, m_mainThreadContext };
                this.m_signaling                      = (ISignaling)Activator.CreateInstance(t, args);
                this.m_signaling.OnStart             += signaling => signaling.OpenConnection(Guid.NewGuid().ToString());
                this.m_signaling.OnCreateConnection  += OnCreateConnection;
                this.m_signaling.OnDestroyConnection += OnDestroyConnection;
                this.m_signaling.OnOffer             += (signaling, data) => StartCoroutine(OnOffer(signaling, data));
                this.m_signaling.OnAnswer            += (signaling, data) => StartCoroutine(OnAnswer(signaling, data));
                this.m_signaling.OnIceCandidate      += OnIceCandidate;
            }

            this.m_signaling.Start();
        }
Пример #22
0
        void OnEnable()
        {
            if (this.m_signaling == null)
            {
                if (urlSignaling.StartsWith("ws"))
                {
                    this.m_signaling = new WebSocketSignaling(urlSignaling, interval);
                }
                else
                {
                    this.m_signaling = new HttpSignaling(urlSignaling, interval);
                }

                this.m_signaling.OnOffer        += OnOffer;
                this.m_signaling.OnIceCandidate += OnIceCandidate;
            }
            this.m_signaling.Start();
        }
Пример #23
0
 void OnEnable()
 {
     if (this.m_signaling == null)
     {
         Type     t    = Type.GetType(signalingType);
         object[] args = { urlSignaling, interval, m_mainThreadContext };
         this.m_signaling                     = (ISignaling)Activator.CreateInstance(t, args);
         this.m_signaling.OnStart            += signaling => signaling.CreateConnection();
         this.m_signaling.OnCreateConnection += (signaling, id) =>
         {
             m_connectionId = id;
             CreatePeerConnection(signaling, m_connectionId, true);
         };
         this.m_signaling.OnOffer        += (signaling, data) => StartCoroutine(OnOffer(signaling, data));
         this.m_signaling.OnAnswer       += (signaling, data) => StartCoroutine(OnAnswer(signaling, data));
         this.m_signaling.OnIceCandidate += OnIceCandidate;
     }
     this.m_signaling.Start();
 }
Пример #24
0
        IEnumerator OnAnswer(ISignaling signaling, DescData e)
        {
            if (!m_mapConnectionIdAndPeer.TryGetValue(e.connectionId, out var pc))
            {
                Debug.Log($"connectiondId:{e.connectionId}, peerConnection not exist");
                yield break;
            }

            var desc = new RTCSessionDescription();

            desc.type = RTCSdpType.Answer;
            desc.sdp  = e.sdp;
            var opRemoteSdp = pc.SetRemoteDescription(ref desc);

            yield return(opRemoteSdp);

            if (opRemoteSdp.IsError)
            {
                Debug.LogError($"Network Error: {opRemoteSdp.Error.message}");
                yield break;
            }
        }
Пример #25
0
        RTCPeerConnection CreatePeerConnection(ISignaling signaling, string connectionId, bool isOffer)
        {
            if (m_mapConnectionIdAndPeer.TryGetValue(connectionId, out var peer))
            {
                peer.Close();
            }

            var pc = new RTCPeerConnection();

            m_mapConnectionIdAndPeer[connectionId] = pc;

            pc.OnDataChannel = new DelegateOnDataChannel(channel => { OnDataChannel(pc, channel); });
            pc.SetConfiguration(ref m_conf);
            pc.OnIceCandidate = new DelegateOnIceCandidate(candidate =>
            {
                signaling.SendCandidate(connectionId, candidate);
            });
            pc.OnIceConnectionChange = new DelegateOnIceConnectionChange(state =>
            {
                if (state == RTCIceConnectionState.Disconnected)
                {
                    pc.Close();
                    m_mapConnectionIdAndPeer.Remove(connectionId);
                }
            });

            pc.OnTrack = trackEvent =>
            {
                foreach (var viewer in m_listVideoReceiveViewer)
                {
                    viewer.AddTrack(connectionId, trackEvent.Track);
                }
            };

            pc.OnNegotiationNeeded = () => StartCoroutine(OnNegotiationNeeded(signaling, connectionId, isOffer));
            return(pc);
        }
Пример #26
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="conf"></param>
        /// <param name="hardwareEncoder"></param>
        /// <param name="signaling"></param>
        /// <param name="handlers"></param>
        public void Run(
            RTCConfiguration?conf           = null,
            bool?hardwareEncoder            = null,
            ISignaling signaling            = null,
            SignalingHandlerBase[] handlers = null
            )
        {
            RTCConfiguration _conf =
                conf.GetValueOrDefault(new RTCConfiguration {
                iceServers = iceServers
            });
            bool _hardwareEncoder =
                hardwareEncoder.GetValueOrDefault(hardwareEncoderSupport);
            var        encoderType = _hardwareEncoder ? EncoderType.Hardware : EncoderType.Software;
            ISignaling _signaling  = signaling ?? CreateSignaling(
                signalingType, urlSignaling, interval, SynchronizationContext.Current);
            RenderStreamingDependencies dependencies = new RenderStreamingDependencies
            {
                config         = _conf,
                encoderType    = encoderType,
                signaling      = _signaling,
                startCoroutine = StartCoroutine
            };

            m_instance = new RenderStreamingInternal(ref dependencies);
            m_provider = new SignalingEventProvider(m_instance);

            SignalingHandlerBase[] _handlers = handlers ?? this.handlers.ToArray();

            foreach (var source in _handlers)
            {
                source.SetHandler(m_instance);
                m_provider.Subscribe(source);
            }
            m_running = true;
        }
Пример #27
0
        IEnumerator OnOffer(ISignaling signaling, DescData e)
        {
            var connectionId = e.connectionId;

            if (m_mapConnectionIdAndPeer.ContainsKey(connectionId))
            {
                Debug.LogError($"connection:{connectionId} peerConnection already exist");
                yield break;
            }

            var pc = CreatePeerConnection(signaling, connectionId, false);

            RTCSessionDescription _desc;

            _desc.type = RTCSdpType.Offer;
            _desc.sdp  = e.sdp;

            var opRemoteDesc = pc.SetRemoteDescription(ref _desc);

            yield return(opRemoteDesc);

            if (opRemoteDesc.IsError)
            {
                Debug.LogError($"Network Error: {opRemoteDesc.Error.message}");
                yield break;
            }

            // ToDo: need webrtc package version 2.3
            // foreach (var transceiver in pc.GetTransceivers()
            //     .Where(x => x.Receiver.Track.Kind == TrackKind.Video)
            //     .Select((x, index) => new {x, index})
            //     .Take(m_listVideoStreamTrack.Count))
            // {
            //     RTCRtpSender sender = transceiver.x.Sender;
            //     VideoStreamTrack track = m_listVideoStreamTrack[transceiver.index];
            //     transceiver.x.Sender.ReplaceTrack(track);
            //     transceiver.x.Direction = RTCRtpTransceiverDirection.SendOnly;
            //
            //     if (!m_mapTrackAndSenderList.TryGetValue(track, out List<RTCRtpSender> list))
            //     {
            //         list = new List<RTCRtpSender>();
            //         m_mapTrackAndSenderList.Add(track, list);
            //     }
            //
            //     list.Add(sender);
            // }

            foreach (var track in m_listVideoStreamTrack)
            {
                RTCRtpSender sender = pc.AddTrack(track);
                if (!m_mapTrackAndSenderList.TryGetValue(track, out List <RTCRtpSender> list))
                {
                    list = new List <RTCRtpSender>();
                    m_mapTrackAndSenderList.Add(track, list);
                }
                list.Add(sender);
            }

            foreach (var track in m_audioStream.GetTracks())
            {
                RTCRtpSender sender = pc.AddTrack(track);
                if (!m_mapTrackAndSenderList.TryGetValue(track, out List <RTCRtpSender> list))
                {
                    list = new List <RTCRtpSender>();
                    m_mapTrackAndSenderList.Add(track, list);
                }
                list.Add(sender);
            }

            RTCAnswerOptions options = default;
            var op = pc.CreateAnswer(ref options);

            yield return(op);

            if (op.IsError)
            {
                Debug.LogError($"Network Error: {op.Error.message}");
                yield break;
            }

            var desc        = op.Desc;
            var opLocalDesc = pc.SetLocalDescription(ref desc);

            yield return(opLocalDesc);

            if (opLocalDesc.IsError)
            {
                Debug.LogError($"Network Error: {opLocalDesc.Error.message}");
                yield break;
            }

            signaling.SendAnswer(connectionId, desc);
        }
Пример #28
0
        void OnOffer(ISignaling signaling, DescData e)
        {
            RTCSessionDescription _desc;

            _desc.type = RTCSdpType.Offer;
            _desc.sdp  = e.sdp;
            var connectionId = e.connectionId;

            if (m_mapConnectionIdAndPeer.ContainsKey(connectionId))
            {
                return;
            }
            var pc = new RTCPeerConnection();

            m_mapConnectionIdAndPeer.Add(e.connectionId, pc);

            pc.OnDataChannel = new DelegateOnDataChannel(channel => { OnDataChannel(pc, channel); });
            pc.SetConfiguration(ref m_conf);
            pc.OnIceCandidate = new DelegateOnIceCandidate(candidate =>
            {
                signaling.SendCandidate(e.connectionId, candidate);
            });
            pc.OnIceConnectionChange = new DelegateOnIceConnectionChange(state =>
            {
                if (state == RTCIceConnectionState.Disconnected)
                {
                    pc.Close();
                    m_mapConnectionIdAndPeer.Remove(e.connectionId);
                }
            });

            pc.SetRemoteDescription(ref _desc);
            foreach (var track in m_listVideoStreamTrack.Concat(m_audioStream.GetTracks()))
            {
                RTCRtpSender sender = pc.AddTrack(track);
                if (!m_mapTrackAndSenderList.TryGetValue(track, out List <RTCRtpSender> list))
                {
                    list = new List <RTCRtpSender>();
                    m_mapTrackAndSenderList.Add(track, list);
                }
                list.Add(sender);
            }

            RTCAnswerOptions options = default;
            var op = pc.CreateAnswer(ref options);

            while (op.MoveNext())
            {
            }
            if (op.IsError)
            {
                Debug.LogError($"Network Error: {op.Error}");
                return;
            }

            var desc        = op.Desc;
            var opLocalDesc = pc.SetLocalDescription(ref desc);

            while (opLocalDesc.MoveNext())
            {
            }
            if (opLocalDesc.IsError)
            {
                Debug.LogError($"Network Error: {opLocalDesc.Error}");
                return;
            }

            signaling.SendAnswer(connectionId, desc);
        }
Пример #29
0
 void OnDestroyConnection(ISignaling signaling, string connectionId)
 {
     DeletePeerConnection(connectionId);
     onDeletedConnection?.Invoke(connectionId);
 }
Пример #30
0
 void OnStart(ISignaling signaling)
 {
     onStart?.Invoke();
 }