/// <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); }
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); }
/// <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()); }
void OnDisable() { if (this.m_signaling != null) { this.m_signaling.Stop(); this.m_signaling = null; } }
/// <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(); }
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)); }
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)); }
void OnCreateConnection(ISignaling signaling, string connectionId, bool peerExists) { var pc = CreatePeerConnection(signaling, connectionId, peerExists); if (!peerExists) { return; } AddTracks(connectionId, pc); }
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); }
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(); }
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; }
void OnCreateConnection(ISignaling signaling, string connectionId, bool peerExists) { CreatePeerConnection(connectionId, peerExists); if (peerExists) { onFoundConnection?.Invoke(connectionId); } else { onCreatedConnection?.Invoke(connectionId); } }
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); }
/// <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; }
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); }
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()); }
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)); }
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}."); } }
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(); }
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(); }
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(); }
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; } }
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); }
/// <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; }
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); }
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); }
void OnDestroyConnection(ISignaling signaling, string connectionId) { DeletePeerConnection(connectionId); onDeletedConnection?.Invoke(connectionId); }
void OnStart(ISignaling signaling) { onStart?.Invoke(); }