public override async Task OnEnteringState() { Debug.Assert(Context.PeerConnection == null); Context.VoipCoordinator.SetActiveIncomingCall(_message, _callRequest.VideoEnabled); var config = new RTCConfiguration { IceServers = WebRtcSettingsUtils.ToRTCIceServer(IceServerSettings.IceServers) }; Context.PeerConnection = new RTCPeerConnection(config); Context.LocalStream = await Context.Media.GetUserMedia(new RTCMediaStreamConstraints { videoEnabled = _callRequest.VideoEnabled, audioEnabled = true }); Context.PeerConnection.AddStream(Context.LocalStream); var tracks = Context.LocalStream.GetVideoTracks(); if (tracks.Count > 0) { #if WIN10 var source = Context.Media.CreateMediaSource(tracks[0], VoipContext.LocalMediaStreamId); #else var source = Context.Media.CreateMediaStreamSource(tracks[0], 30, VoipContext.LocalMediaStreamId); #endif Context.LocalVideoRenderer.SetupRenderer(Context.ForegroundProcessId, source, Context.LocalVideoControlSize); } }
public override async Task OnEnteringState() { Debug.Assert(Context.PeerConnection == null); Context.VoipCoordinator.StartOutgoingCall(_callRequest); var config = new RTCConfiguration { IceServers = WebRtcSettingsUtils.ToRTCIceServer(IceServerSettings.IceServers) }; Context.PeerConnection = new RTCPeerConnection(config); Context.LocalStream = await Context.Media.GetUserMedia(new RTCMediaStreamConstraints { videoEnabled = _callRequest.VideoEnabled, audioEnabled = true }); Context.PeerConnection.AddStream(Context.LocalStream); var sdpOffer = await Context.PeerConnection.CreateOffer(); var sdpString = sdpOffer.Sdp; SdpUtils.SelectCodecs(ref sdpString, DtoExtensions.FromDto(Context.GetAudioCodec()), DtoExtensions.FromDto(Context.GetVideoCodec())); sdpOffer.Sdp = sdpString; await Context.PeerConnection.SetLocalDescription(sdpOffer); var tracks = Context.LocalStream.GetVideoTracks(); if (tracks.Count > 0) { #if WIN10 var source = Context.Media.CreateMediaSource(tracks[0], VoipContext.LocalMediaStreamId); #else var source = Context.Media.CreateMediaStreamSource(tracks[0], 30, VoipContext.LocalMediaStreamId); #endif Context.LocalVideoRenderer.SetupRenderer(Context.ForegroundProcessId, source, Context.LocalVideoControlSize); } Context.SendToPeer(RelayMessageTags.SdpOffer, sdpOffer.Sdp); }
public override async Task OnEnteringStateAsync() { if (_reason == Reason.HoldCall) { Context.VoipHelper.SetCallHeld(); } else if (Context.VoipHelper.HasCall()) { Context.VoipHelper.SetCallActive(Context.PeerId, Context.IsVideoEnabled); } else { Context.VoipHelper.StartOutgoingCall(Context.PeerId, Context.IsVideoEnabled); } // If PeerConnection is not null, then this is an SDP renegotiation. if (Context.PeerConnection == null) { var config = new RTCConfiguration { IceServers = WebRtcSettingsUtils.ToRTCIceServer(IceServerSettings.IceServers) }; Context.PeerConnection = new RTCPeerConnection(config); } switch (_reason) { case Reason.HoldCall: { // Even for just a renegotiation, it's easier to just teardown the media capture and start over. if (Context.LocalStream != null) { Context.PeerConnection.RemoveStream(Context.LocalStream); } if (Context.RemoteStream != null) { Context.PeerConnection.RemoveStream(Context.RemoteStream); } foreach (var stream in Context.PeerConnection.GetLocalStreams()) { Debug.WriteLine("Streams remaining."); } Context.LocalStream?.Stop(); Context.LocalStream = null; Context.RemoteStream?.Stop(); Context.RemoteStream = null; Context.ResetRenderers(); break; } case Reason.EstablishCall: { Context.LocalStream?.Stop(); Context.LocalStream = null; Context.RemoteStream?.Stop(); Context.RemoteStream = null; Context.ResetRenderers(); Context.LocalStream = await RtcManager.Instance.Media.GetUserMedia(new RTCMediaStreamConstraints { videoEnabled = Context.IsVideoEnabled, audioEnabled = true }); Context.PeerConnection.AddStream(Context.LocalStream); // Setup the rendering of the local capture. var tracks = Context.LocalStream.GetVideoTracks(); if (tracks.Count > 0) { var source = RtcManager.Instance.Media.CreateMediaSource(tracks[0], CallContext.LocalMediaStreamId); Context.LocalVideoRenderer.SetupRenderer(Context.ForegroundProcessId, source, Context.LocalVideoControlSize); } break; } case Reason.SwitchCamera: { var videoDevice = await Context.MediaSettingsChannel.GetVideoDeviceAsync(); // We expect the camera we want to switch to is selected. if (videoDevice == null) { // This could happen only in an error scenario and would have the // effect of loosing the video. // Since will not be able to continue the video call, just end the call. await Context.SwitchState(new HangingUp()); return; } RtcManager.Instance.Media.SelectVideoDevice(videoDevice.FromDto()); // Remove old video track. var videoTracks = Context.LocalStream.GetVideoTracks(); bool videoTrackEnabled = true; if (videoTracks.Count > 0) { var oldVideoTrack = videoTracks[0]; videoTrackEnabled = oldVideoTrack.Enabled; oldVideoTrack.Stop(); Context.LocalStream.RemoveTrack(oldVideoTrack); } videoTracks.Clear(); Context.ResetLocalRenderer(); // Create new stream having a new video track. var newStream = await RtcManager.Instance.Media.GetUserMedia(new RTCMediaStreamConstraints { videoEnabled = true, audioEnabled = false }); // Move the new video track from new stream to old stream. var newVideoTrack = newStream.GetVideoTracks().First(); newVideoTrack.Enabled = videoTrackEnabled; Context.LocalStream.AddTrack(newVideoTrack); newStream.RemoveTrack(newVideoTrack); newStream.Stop(); var source = RtcManager.Instance.Media.CreateMediaSource(newVideoTrack, CallContext.LocalMediaStreamId); Context.LocalVideoRenderer.SetupRenderer(Context.ForegroundProcessId, source, Context.LocalVideoControlSize); break; } } var sdpOffer = await Context.PeerConnection.CreateOffer(); var sdpString = sdpOffer.Sdp; Org.WebRtc.CodecInfo videoCodecToUse = null; // In case of camera switch, try to use the codec from the call's first SDP negotiation. if (_reason == Reason.SwitchCamera && Context.VideoCodecUsed != null) { videoCodecToUse = Context.VideoCodecUsed; } else { videoCodecToUse = (await Hub.Instance.MediaSettingsChannel.GetVideoCodecAsync()).FromDto(); } SdpUtils.SelectCodecs(ref sdpString, (await Hub.Instance.MediaSettingsChannel.GetAudioCodecAsync()).FromDto(), videoCodecToUse); if (_reason == Reason.EstablishCall) { Context.VideoCodecUsed = videoCodecToUse; } sdpOffer.Sdp = sdpString; await Context.PeerConnection.SetLocalDescription(sdpOffer); Context.SendToPeer(RelayMessageTags.SdpOffer, sdpOffer.Sdp); }
public override async Task OnSdpOfferAsync(RelayMessage message) { bool isHold = SdpUtils.IsHold(message.Payload); if (isHold) { Context.VoipHelper.SetCallHeld(); } else { Context.VoipHelper.SetCallActive(Context.PeerId, Context.IsVideoEnabled); } // If PeerConnection is not null, then this is an SDP renegotiation. if (Context.PeerConnection == null) { var config = new RTCConfiguration { IceServers = WebRtcSettingsUtils.ToRTCIceServer(IceServerSettings.IceServers) }; Context.PeerConnection = new RTCPeerConnection(config); } if (isHold) { // Even for just a renegotiation, it's easier to just teardown the media capture and start over. if (Context.LocalStream != null) { Context.PeerConnection.RemoveStream(Context.LocalStream); } Context.LocalStream?.Stop(); Context.LocalStream = null; Context.RemoteStream?.Stop(); Context.RemoteStream = null; Context.ResetRenderers(); } MediaVideoTrack oldVideoTrack = Context.RemoteStream?.GetVideoTracks()?.FirstOrDefault(); await Context.PeerConnection.SetRemoteDescription(new RTCSessionDescription(RTCSdpType.Offer, message.Payload)); MediaVideoTrack newVideoTrack = Context.RemoteStream?.GetVideoTracks()?.FirstOrDefault(); bool videoTrackChanged = oldVideoTrack != null && newVideoTrack != null && oldVideoTrack.Id.CompareTo(newVideoTrack.Id) != 0; if (videoTrackChanged) { Context.ResetRemoteRenderer(); var source = RtcManager.Instance.Media.CreateMediaSource(newVideoTrack, CallContext.PeerMediaStreamId); Context.RemoteVideoRenderer.SetupRenderer(Context.ForegroundProcessId, source, Context.RemoteVideoControlSize); } else if (!isHold) { Context.LocalStream = await RtcManager.Instance.Media.GetUserMedia(new RTCMediaStreamConstraints { videoEnabled = Context.IsVideoEnabled, audioEnabled = true }); Context.PeerConnection.AddStream(Context.LocalStream); // Setup the rendering of the local capture. var tracks = Context.LocalStream.GetVideoTracks(); if (tracks.Count > 0) { var source = RtcManager.Instance.Media.CreateMediaSource(tracks[0], CallContext.LocalMediaStreamId); Context.LocalVideoRenderer.SetupRenderer(Context.ForegroundProcessId, source, Context.LocalVideoControlSize); } } var sdpAnswer = await Context.PeerConnection.CreateAnswer(); await Context.PeerConnection.SetLocalDescription(sdpAnswer); var sdpVideoCodecIds = SdpUtils.GetVideoCodecIds(message.Payload); if (sdpVideoCodecIds.Count > 0) { Context.VideoCodecUsed = Array.Find((await Hub.Instance.MediaSettingsChannel.GetVideoCodecsAsync())?.Codecs, it => it.Id == sdpVideoCodecIds.First())?.FromDto(); } Context.SendToPeer(RelayMessageTags.SdpAnswer, sdpAnswer.Sdp); if (isHold) { await Context.SwitchState(new Held()); } else { await Context.SwitchState(new Active()); } }