public async Task BeforeConnect() { // Add local video track channel to #1 var settings = new PeerConnection.LocalVideoTrackSettings(); LocalVideoTrack track1 = await pc1_.AddLocalVideoTrackAsync(settings); Assert.NotNull(track1); Assert.AreEqual(pc1_, track1.PeerConnection); // Wait for local SDP re-negotiation on #1. // This will not create an offer, since we're not connected yet. Assert.True(renegotiationEvent1_.Wait(TimeSpan.FromSeconds(60.0))); // Connect Assert.True(pc1_.CreateOffer()); WaitForSdpExchangeCompleted(); Assert.True(pc1_.IsConnected); Assert.True(pc2_.IsConnected); // Remove the track from #1 renegotiationEvent1_.Reset(); pc1_.RemoveLocalVideoTrack(track1); Assert.IsNull(track1.PeerConnection); track1.Dispose(); // Wait for local SDP re-negotiation on #1 Assert.True(renegotiationEvent1_.Wait(TimeSpan.FromSeconds(60.0))); // Confirm remote track was removed from #2 Assert.True(trackRemovedEvent2_.Wait(TimeSpan.FromSeconds(60.0))); // Wait until SDP renegotiation finished WaitForSdpExchangeCompleted(); }
private void StartLocalVideoClicked(object sender, RoutedEventArgs e) { // Toggle between start and stop local video feed //< TODO dssStatsTimer.IsEnabled used for toggle, but dssStatsTimer should be // used also for remote statistics display (so even when no local video active) if (dssStatsTimer.IsEnabled) { StopLocalVideo(); dssStatsTimer.Stop(); localLoadText.Text = "Load: -"; localPresentText.Text = "Present: -"; localSkipText.Text = "Skip: -"; localLateText.Text = "Late: -"; remoteLoadText.Text = "Load: -"; remotePresentText.Text = "Present: -"; remoteSkipText.Text = "Skip: -"; remoteLateText.Text = "Late: -"; startLocalVideo.Content = "Start local video"; } else { LogMessage("Opening local A/V stream..."); // TODO - HACK: support multi-webcams locally for testing //_peerConnection.HACK_VideoDeviceIndex = HACK_GetVideoDeviceIndex(); var uiThreadScheduler = TaskScheduler.FromCurrentSynchronizationContext(); _peerConnection.AddLocalAudioTrackAsync().ContinueWith(addAudioTask => { // Continue on worker thread here if (addAudioTask.Exception != null) { LogMessage(addAudioTask.Exception.Message); return; } _peerConnection.AddLocalVideoTrackAsync().ContinueWith(addVideoTask => { // Continue inside UI thread here if (addVideoTask.Exception != null) { LogMessage(addVideoTask.Exception.Message); return; } dssStatsTimer.Interval = TimeSpan.FromSeconds(1.0); dssStatsTimer.Start(); startLocalVideo.Content = "Stop local video"; var idx = HACK_GetVideoDeviceIndex(); //< HACK localPeerUidTextBox.Text = GetDeviceUniqueIdLikeUnity((byte)idx); //< HACK remotePeerUidTextBox.Text = GetDeviceUniqueIdLikeUnity((byte)(1 - idx)); //< HACK localVideoSourceName.Text = $"({VideoCaptureDevices[idx].DisplayName})"; //< HACK localVideo.MediaPlayer.Play(); lock (_isLocalVideoPlayingLock) { _isLocalVideoPlaying = true; } }, uiThreadScheduler); }); } }
static async Task Main() { try { Console.WriteLine("Starting..."); ClientWebSocket ws = new ClientWebSocket(); CancellationTokenSource cts = new CancellationTokenSource(); // Set up the peer connection. var pc = new PeerConnection(); pc.LocalSdpReadytoSend += async(string type, string sdp) => { Console.WriteLine($"Local SDP ready {type}"); //Console.WriteLine(sdp); // Send out SDP offer to the remote peer. await ws.SendAsync(Encoding.UTF8.GetBytes(sdp), WebSocketMessageType.Text, true, cts.Token); }; var config = new PeerConnectionConfiguration(); await pc.InitializeAsync(config); Console.WriteLine("Peer connection initialized."); await pc.AddLocalAudioTrackAsync(); await pc.AddLocalVideoTrackAsync(new PeerConnection.LocalVideoTrackSettings()); await ws.ConnectAsync(new Uri(WEBSOCKET_SERVER_URI), cts.Token); pc.CreateOffer(); // Wait for the SDP answer to arrive from the remote peer. byte[] answerSdpBuffer = new byte[8192]; var recvRes = await ws.ReceiveAsync(answerSdpBuffer, cts.Token); string answerSdp = Encoding.UTF8.GetString(answerSdpBuffer, 0, recvRes.Count); //Console.WriteLine($"answer sdp: {answerSdp}"); pc.SetRemoteDescription("answer", answerSdp); // Don't need the web socket anymore. await ws.CloseAsync(WebSocketCloseStatus.NormalClosure, null, cts.Token); Console.WriteLine("Press any key to exit..."); Console.ReadLine(); } catch (Exception e) { Console.WriteLine(e.Message); } }
private async void OnLoaded(object sender, RoutedEventArgs e) { // Request access to microphone and camera var settings = new MediaCaptureInitializationSettings(); settings.StreamingCaptureMode = StreamingCaptureMode.AudioAndVideo; var capture = new MediaCapture(); await capture.InitializeAsync(settings); // Retrieve a list of available video capture devices (webcams). List <VideoCaptureDevice> deviceList = await PeerConnection.GetVideoCaptureDevicesAsync(); // Get the device list and, for example, print them to the debugger console foreach (var device in deviceList) { // This message will show up in the Output window of Visual Studio Debugger.Log(0, "", $"Webcam {device.name} (id: {device.id})\n"); } _peerConnection = new PeerConnection(); var config = new PeerConnectionConfiguration { IceServers = new List <IceServer> { new IceServer { Urls = { "stun:stun.l.google.com:19302" } } } }; await _peerConnection.InitializeAsync(config); Debugger.Log(0, "", "Peer connection initialized successfully.\n"); await _peerConnection.AddLocalAudioTrackAsync(); if (Settings.m_showLocal) { //LocalVideoTrack _localVideoTrack; await _peerConnection.AddLocalVideoTrackAsync(); _peerConnection.I420LocalVideoFrameReady += Peer_LocalI420AFrameReady; await _peerConnection.AddLocalAudioTrackAsync(); remoteVideoPlayerElement.Visibility = Visibility.Visible; } else { _peerConnection.Connected += () => { Debugger.Log(0, "", "PeerConnection: connected.\n"); }; _peerConnection.IceStateChanged += (IceConnectionState newState) => { Debugger.Log(0, "", $"ICE state: {newState}\n"); }; _peerConnection.I420RemoteVideoFrameReady += Peer_RemoteI420AFrameReady; _peerConnection.LocalSdpReadytoSend += Peer_LocalSdpReadytoSend; _peerConnection.IceCandidateReadytoSend += Peer_IceCandidateReadytoSend; // Initialize the signaler _signaler = new NodeDssSignaler() { HttpServerAddress = "http://10.44.160.22:3000/", LocalPeerId = "DINF-D60015-43A", RemotePeerId = "HOLOLENS-RO2J0", }; _signaler.OnMessage += (NodeDssSignaler.Message msg) => { switch (msg.MessageType) { case NodeDssSignaler.Message.WireMessageType.Offer: _peerConnection.SetRemoteDescription("offer", msg.Data); _peerConnection.CreateAnswer(); break; case NodeDssSignaler.Message.WireMessageType.Answer: _peerConnection.SetRemoteDescription("answer", msg.Data); break; case NodeDssSignaler.Message.WireMessageType.Ice: var parts = msg.Data.Split(new string[] { msg.IceDataSeparator }, StringSplitOptions.RemoveEmptyEntries); // Note the inverted arguments for historical reasons. // 'candidate' is last in AddIceCandidate(), but first in the message. string sdpMid = parts[2]; int sdpMlineindex = int.Parse(parts[1]); string candidate = parts[0]; _peerConnection.AddIceCandidate(sdpMid, sdpMlineindex, candidate); break; } }; _signaler.StartPollingAsync(); } // Interactions Debug.WriteLine("[Playback::start] Waiting for a connection..."); m_dsUdpSocket = new DatagramSocket(); m_dsUdpSocket.MessageReceived += Socket_MessageReceived; // Initialization UDP communication try { await m_dsUdpSocket.ConnectAsync(new EndpointPair(new HostName(Settings.m_sIPLocalUDP), Settings.m_sPortLocalUDP, new HostName(Settings.m_sIPRemoteUDP), Settings.m_sPortRemoteUDP)); m_output = new DataWriter(m_dsUdpSocket.OutputStream); Debug.WriteLine("[Playback::start] UDP connection initialization ok"); } catch (Exception) { Debug.WriteLine("[Playback::start] Error - UDP connection initialization "); } }
static async Task Main(string[] args) { try { bool needVideo = Array.Exists(args, arg => (arg == "-v") || (arg == "--video")); bool needAudio = Array.Exists(args, arg => (arg == "-a") || (arg == "--audio")); // Asynchronously retrieve a list of available video capture devices (webcams). var deviceList = await PeerConnection.GetVideoCaptureDevicesAsync(); // For example, print them to the standard output foreach (var device in deviceList) { Console.WriteLine($"Found webcam {device.name} (id: {device.id})"); } // Create a new peer connection automatically disposed at the end of the program using var pc = new PeerConnection(); // Initialize the connection with a STUN server to allow remote access var config = new PeerConnectionConfiguration { IceServers = new List <IceServer> { new IceServer { Urls = { "stun:stun.l.google.com:19302" } } } }; await pc.InitializeAsync(config); Console.WriteLine("Peer connection initialized."); // Record video from local webcam, and send to remote peer if (needVideo) { Console.WriteLine("Opening local webcam..."); await pc.AddLocalVideoTrackAsync(); } // Record audio from local microphone, and send to remote peer if (needAudio) { Console.WriteLine("Opening local microphone..."); await pc.AddLocalAudioTrackAsync(); } // Setup signaling Console.WriteLine("Starting signaling..."); var signaler = new NamedPipeSignaler.NamedPipeSignaler(pc, "testpipe"); signaler.SdpMessageReceived += (string type, string sdp) => { pc.SetRemoteDescription(type, sdp); if (type == "offer") { pc.CreateAnswer(); } }; signaler.IceCandidateReceived += (string sdpMid, int sdpMlineindex, string candidate) => { pc.AddIceCandidate(sdpMid, sdpMlineindex, candidate); }; await signaler.StartAsync(); // Start peer connection pc.Connected += () => { Console.WriteLine("PeerConnection: connected."); }; pc.IceStateChanged += (IceConnectionState newState) => { Console.WriteLine($"ICE state: {newState}"); }; int numFrames = 0; pc.I420RemoteVideoFrameReady += (I420AVideoFrame frame) => { ++numFrames; if (numFrames % 60 == 0) { Console.WriteLine($"Received video frames: {numFrames}"); } }; if (signaler.IsClient) { Console.WriteLine("Connecting to remote peer..."); pc.CreateOffer(); } else { Console.WriteLine("Waiting for offer from remote peer..."); } Console.WriteLine("Press a key to stop recording..."); Console.ReadKey(true); signaler.Stop(); } catch (Exception e) { Console.WriteLine(e.Message); } Console.WriteLine("Program termined."); }
//Loaded-EventHandler of ui: executes after ui-loading private async void OnLoaded(object sender, RoutedEventArgs e) { //Request access to mic and cam MediaCaptureInitializationSettings settings = new MediaCaptureInitializationSettings(); settings.StreamingCaptureMode = StreamingCaptureMode.AudioAndVideo; MediaCapture capture = new MediaCapture(); await capture.InitializeAsync(settings); //Get list of cams camList = await PeerConnection.GetVideoCaptureDevicesAsync(); //Print list to log foreach (var cam in camList) { Debugger.Log(0, "", $"Webcam: {cam.name} (id: {cam.id})\n"); } //Ask user for ids (show MessageBox) await ShowIdInputBoxAsync(); //New PeerConnection (Access to WebRTC) peerConnection = new PeerConnection(); //Create PeerConnection-config PeerConnectionConfiguration config = new PeerConnectionConfiguration() { IceServers = new List <IceServer>() { //Using google stun server for testing new IceServer() { Urls = { "stun:stun.l.google.com:19302" } } } }; //Initialize PeerContection await peerConnection.InitializeAsync(config); //Event fires, when local video frame is captured and ready for rendering peerConnection.I420LocalVideoFrameReady += Peer_LocalI420FrameReady; //Event fires, when remote video frame is receved and ready for rendering peerConnection.I420RemoteVideoFrameReady += Peer_RemoteI420FrameReady; //Events fires, when SdpMessage is ready for sending peerConnection.LocalSdpReadytoSend += Peer_LocalSdpReadytoSend; //Event fires, when IceCandidate is ready for sending peerConnection.IceCandidateReadytoSend += Peer_IceCandidateReadytoSend; //Set DebuggingLog-messages peerConnection.Connected += () => Debugger.Log(0, "", "PeerConnection: connected\n"); peerConnection.IceStateChanged += (IceConnectionState newState) => Debugger.Log(0, "", $"ICE state: {newState}\n"); Debugger.Log(0, "", "Peer conection initialized successfully\n"); //Adds cam-tracks from standart (first) devices [add parameter to specify cam-device or -specifications] await peerConnection.AddLocalVideoTrackAsync(new PeerConnection.LocalVideoTrackSettings() { videoDevice = cam }); //Same for mic [no specifications possible: always uses the first mic in list] await peerConnection.AddLocalAudioTrackAsync(); //Initialize the signaler (Properties from MessageBox) signaler = new NodeDssSignaler() { HttpServerAddress = nodeDssServerIp, LocalPeerId = localId, RemotePeerId = remoteId }; signaler.OnMessage += (NodeDssSignaler.Message msg) => { switch (msg.MessageType) { case NodeDssSignaler.Message.WireMessageType.Offer: peerConnection.SetRemoteDescription("offer", msg.Data); peerConnection.CreateAnswer(); break; case NodeDssSignaler.Message.WireMessageType.Answer: peerConnection.SetRemoteDescription("answer", msg.Data); break; case NodeDssSignaler.Message.WireMessageType.Ice: string[] parts = msg.Data.Split(new string[] { msg.IceDataSeparator }, StringSplitOptions.RemoveEmptyEntries); //Changing order of parts string sdpMid = parts[2]; int sdpMlineindex = int.Parse(parts[1]); string candidate = parts[0]; peerConnection.AddIceCandidate(sdpMid, sdpMlineindex, candidate); break; } }; signaler.StartPollingAsync(); }