// =============================== // Helper Method // =============================== private Task GetAudioCodecs() { var task = Task.Run(() => { #if NETFX_CORE lock (_audioLock) { foreach (var codec in WebRTC.GetAudioCodecs()) { AudioCodecs.Add(codec); } } #endif }); return(task); }
/// <summary> /// WARNING! :-) /// Heavily borrowed from the original sample with some mods - the original sample also did /// some work to pick a specific video codec and also to move VP8 to the head of the list /// but I've not done that yet. /// /// Additionally, at some point it seems that the CodecInfo structure lost its ID property /// which the original code was using so now it only has a NAME property. This made it /// harder for me to leave the original code alone and I had to modify it some more and /// add in the GetCodecId() method above to try and reproduce what was originally happening /// in the code that I took from the sample. I don't think what I've done is *perfect* /// though so I wouldn't be surprised if at some point this code started causing someone /// a problem and it needed revisiting. /// </summary> /// <param name="originalSdp"></param> /// <param name="audioCodecs"></param> /// <returns></returns> public static string FilterToSupportedCodecs(string originalSdp) { var filteredSdp = originalSdp; string[] incompatibleAudioCodecs = new string[] { "CN32000", "CN16000", "CN8000", "red8000", "telephone-event8000" }; var compatibleCodecs = WebRTC.GetAudioCodecs().Where( codec => !incompatibleAudioCodecs.Contains(codec.Name + codec.ClockRate) && !string.IsNullOrEmpty(GetCodecId(codec))); Regex mfdRegex = new Regex("\r\nm=audio.*RTP.*?( .\\d*)+\r\n"); Match mfdMatch = mfdRegex.Match(filteredSdp); List <string> mfdListToErase = new List <string>(); //mdf = media format descriptor bool audioMediaDescFound = mfdMatch.Groups.Count > 1; //Group 0 is whole match if (audioMediaDescFound) { for (int groupCtr = 1 /*Group 0 is whole match*/; groupCtr < mfdMatch.Groups.Count; groupCtr++) { for (int captureCtr = 0; captureCtr < mfdMatch.Groups[groupCtr].Captures.Count; captureCtr++) { mfdListToErase.Add(mfdMatch.Groups[groupCtr].Captures[captureCtr].Value.TrimStart()); } } mfdListToErase.RemoveAll( entry => compatibleCodecs.Any(c => GetCodecId(c) == entry)); // Alter audio entry Regex audioRegex = new Regex("\r\n(m=audio.*RTP.*?)( .\\d*)+"); // TODO: same comment as before filteredSdp = audioRegex.Replace( filteredSdp, "\r\n$1 " + string.Join(" ", compatibleCodecs.Select(c => GetCodecId(c)))); } // Remove associated rtp mapping, format parameters, feedback parameters Regex removeOtherMdfs = new Regex("a=(rtpmap|fmtp|rtcp-fb):(" + String.Join("|", mfdListToErase) + ") .*\r\n"); filteredSdp = removeOtherMdfs.Replace(filteredSdp, ""); return(filteredSdp); }
public void Initialize() { WebRTC.Initialize(_uiDispatcher); Conductor.Instance.ETWStatsEnabled = false; Cameras = new ObservableCollection <MediaDevice>(); Microphones = new ObservableCollection <MediaDevice>(); AudioPlayoutDevices = new ObservableCollection <MediaDevice>(); // WebRTCUWP M58 library does not support audio capture/playout devices //foreach (MediaDevice audioCaptureDevice in Conductor.Instance.Media.GetAudioCaptureDevices()) //{ // Microphones.Add(audioCaptureDevice); //} //foreach (MediaDevice audioPlayoutDevice in Conductor.Instance.Media.GetAudioPlayoutDevices()) //{ // AudioPlayoutDevices.Add(audioPlayoutDevice); //} // HACK Remove Automatic Device Assignment if (SelectedCamera == null && Cameras.Count > 0) { SelectedCamera = Cameras.First(); } if (SelectedMicrophone == null && Microphones.Count > 0) { SelectedMicrophone = Microphones.First(); } Debug.WriteLine("Device Status: SelectedCamera: {0} - SelectedMic: {1}", SelectedCamera == null ? "NULL" : "OK", SelectedMicrophone == null ? "NULL" : "OK"); if (SelectedAudioPlayoutDevice == null && AudioPlayoutDevices.Count > 0) { SelectedAudioPlayoutDevice = AudioPlayoutDevices.First(); } Conductor.Instance.Media.OnMediaDevicesChanged += OnMediaDevicesChanged; Conductor.Instance.Signaller.OnPeerConnected += (peerId, peerName) => { RunOnUiThread(() => { if (Peers == null) { Peers = new ObservableCollection <Peer>(); Conductor.Instance.Peers = Peers; } Peers.Add(new Peer { Id = peerId, Name = peerName }); }); }; Conductor.Instance.Signaller.OnPeerDisconnected += peerId => { RunOnUiThread(() => { var peerToRemove = Peers?.FirstOrDefault(p => p.Id == peerId); if (peerToRemove != null) { Peers.Remove(peerToRemove); } }); }; Conductor.Instance.Signaller.OnSignedIn += () => { RunOnUiThread(() => { IsConnected = true; IsMicrophoneEnabled = false; IsCameraEnabled = false; IsConnecting = false; OnStatusMessageUpdate?.Invoke("Signed-In"); }); }; Conductor.Instance.Signaller.OnServerConnectionFailure += (Exception ex) => { RunOnUiThread(() => { IsConnecting = false; OnStatusMessageUpdate?.Invoke("Server Connection Failure: " + ex.Message + "\n" + ex.StackTrace); }); }; Conductor.Instance.Signaller.OnDisconnected += () => { RunOnUiThread(() => { IsConnected = false; IsMicrophoneEnabled = false; IsCameraEnabled = false; IsDisconnecting = false; Peers?.Clear(); OnStatusMessageUpdate?.Invoke("Disconnected"); }); }; Conductor.Instance.Signaller.OnMessageFromPeer += (id, message) => { RunOnUiThread(() => { // TODO: Handles All Peer Messages (Signal Channel) }); }; Conductor.Instance.Signaller.OnPeerConnected += (id, name) => { RunOnUiThread(() => { SelectedPeer = Peers.First(x => x.Id == id); OnStatusMessageUpdate?.Invoke(string.Format("Connected Peer: {0}-{1}", SelectedPeer.Id, SelectedPeer.Name)); }); }; // TODO: Restore Event Handler in Utility Wrapper // Implemented in Unity Consumer due to Event Handling Issue // Conductor.Instance.OnAddRemoteStream += Conductor_OnAddRemoteStream does not propagate Conductor.Instance.OnRemoveRemoteStream += Conductor_OnRemoveRemoteStream; Conductor.Instance.OnAddLocalStream += Conductor_OnAddLocalStream; Conductor.Instance.OnConnectionHealthStats += Conductor_OnPeerConnectionHealthStats; Conductor.Instance.OnPeerConnectionCreated += () => { RunOnUiThread(() => { IsReadyToConnect = false; IsConnectedToPeer = true; IsReadyToDisconnect = false; IsMicrophoneEnabled = false; OnStatusMessageUpdate?.Invoke("Peer Connection Created"); }); }; Conductor.Instance.OnPeerConnectionClosed += () => { RunOnUiThread(() => { IsConnectedToPeer = false; _peerVideoTrack = null; _selfVideoTrack = null; IsMicrophoneEnabled = false; IsCameraEnabled = false; // TODO: Clean-up References //GC.Collect(); // Ensure all references are truly dropped. OnStatusMessageUpdate?.Invoke("Peer Connection Closed"); }); }; Conductor.Instance.OnPeerMessageDataReceived += (peerId, message) => { OnPeerMessageDataReceived?.Invoke(peerId, message); }; // DATA Channel Setup Conductor.Instance.OnPeerMessageDataReceived += (i, s) => { }; Conductor.Instance.OnReadyToConnect += () => { RunOnUiThread(() => { IsReadyToConnect = true; }); }; IceServers = new ObservableCollection <IceServer>(); NewIceServer = new IceServer(); AudioCodecs = new ObservableCollection <CodecInfo>(); var audioCodecList = WebRTC.GetAudioCodecs(); string[] incompatibleAudioCodecs = new string[] { "CN32000", "CN16000", "CN8000", "red8000", "telephone-event8000" }; VideoCodecs = new ObservableCollection <CodecInfo>(); // TODO: REMOVE DISPLAY LIST SUPPORT var videoCodecList = WebRTC.GetVideoCodecs().OrderBy(codec => { switch (codec.Name) { case "VP8": return(1); case "VP9": return(2); case "H264": return(3); default: return(99); } }); RunOnUiThread(() => { foreach (var audioCodec in audioCodecList) { if (!incompatibleAudioCodecs.Contains(audioCodec.Name + audioCodec.ClockRate)) { AudioCodecs.Add(audioCodec); } } if (AudioCodecs.Count > 0) { SelectedAudioCodec = AudioCodecs.FirstOrDefault(x => x.Name.Contains("PCMU")); } foreach (var videoCodec in videoCodecList) { VideoCodecs.Add(videoCodec); } if (VideoCodecs.Count > 0) { SelectedVideoCodec = VideoCodecs.FirstOrDefault(x => x.Name.Contains("H264")); } }); RunOnUiThread(() => { OnInitialized?.Invoke(); }); }
public async Task ConfigureRtcAsync() { var settings = ApplicationData.Current.LocalSettings; var videoDeviceId = string.Empty; if (settings.Values.ContainsKey(MediaSettingsIds.VideoDeviceSettings)) { videoDeviceId = (string)settings.Values[MediaSettingsIds.VideoDeviceSettings]; } var videoDevices = Media.GetVideoCaptureDevices(); var selectedVideoDevice = videoDevices.FirstOrDefault(d => d.Id.Equals(videoDeviceId)); selectedVideoDevice = selectedVideoDevice ?? videoDevices.FirstOrDefault(); if (selectedVideoDevice != null) { Media.SelectVideoDevice(selectedVideoDevice); } if (settings.Values.ContainsKey(MediaSettingsIds.AudioDeviceSettings)) { var audioDeviceId = (string)settings.Values[MediaSettingsIds.AudioDeviceSettings]; var audioDevices = Media.GetAudioCaptureDevices(); var selectedAudioDevice = audioDevices.FirstOrDefault(d => d.Id.Equals(audioDeviceId)); if (selectedAudioDevice == null) { settings.Values.Remove(MediaSettingsIds.AudioDeviceSettings); } Media.SelectAudioCaptureDevice(selectedAudioDevice); } else { Media.SelectAudioCaptureDevice(null); } if (settings.Values.ContainsKey(MediaSettingsIds.AudioPlayoutDeviceSettings)) { var audioPlayoutDeviceId = (string)settings.Values[MediaSettingsIds.AudioPlayoutDeviceSettings]; var audioPlayoutDevices = Media.GetAudioPlayoutDevices(); var selectedAudioPlayoutDevice = audioPlayoutDevices.FirstOrDefault(d => d.Id.Equals(audioPlayoutDeviceId)); if (selectedAudioPlayoutDevice == null) { settings.Values.Remove(MediaSettingsIds.AudioPlayoutDeviceSettings); } Media.SelectAudioPlayoutDevice(selectedAudioPlayoutDevice); } else { Media.SelectAudioPlayoutDevice(null); } var videoCodecId = int.MinValue; if (settings.Values.ContainsKey(MediaSettingsIds.VideoCodecSettings)) { videoCodecId = (int)settings.Values[MediaSettingsIds.VideoCodecSettings]; } var videoCodecs = WebRTC.GetVideoCodecs(); var selectedVideoCodec = videoCodecs.FirstOrDefault(c => c.Id.Equals(videoCodecId)); await Hub.Instance.MediaSettingsChannel.SetVideoCodecAsync( (selectedVideoCodec ?? videoCodecs.FirstOrDefault()).ToDto()); var audioCodecId = int.MinValue; if (settings.Values.ContainsKey(MediaSettingsIds.AudioCodecSettings)) { audioCodecId = (int)settings.Values[MediaSettingsIds.AudioCodecSettings]; } var audioCodecs = WebRTC.GetAudioCodecs(); var selectedAudioCodec = audioCodecs.FirstOrDefault(c => c.Id.Equals(audioCodecId)); await Hub.Instance.MediaSettingsChannel.SetAudioCodecAsync( (selectedAudioCodec ?? audioCodecs.FirstOrDefault()).ToDto()); if (settings.Values.ContainsKey(MediaSettingsIds.PreferredVideoCaptureWidth) && settings.Values.ContainsKey(MediaSettingsIds.PreferredVideoCaptureHeight) && settings.Values.ContainsKey(MediaSettingsIds.PreferredVideoCaptureFrameRate)) { WebRTC.SetPreferredVideoCaptureFormat( (int)settings.Values[MediaSettingsIds.PreferredVideoCaptureWidth], (int)settings.Values[MediaSettingsIds.PreferredVideoCaptureHeight], (int)settings.Values[MediaSettingsIds.PreferredVideoCaptureFrameRate]); } }
public DtoCodecInfos GetAudioCodecs() { return(DtoExtensions.ToDto(WebRTC.GetAudioCodecs().ToArray())); }
/// <summary> /// On Win10 in a background task, WebRTC initialization has to be done /// when we have access to the resources. That's inside an active /// voip call. /// This function must be called after VoipCoordinator.StartVoipTask() /// </summary> /// <returns></returns> public void InitializeRTC() { if (Media == null) { WebRTC.Initialize(_dispatcher); Media = WebRTCMedia.CreateMedia(); WebRTCMedia.SetDisplayOrientation(_displayOrientation); // Uncomment the following line to enable WebRTC logging. // Logs are: // - Saved to local storage. Log folder location can be obtained using WebRTC.LogFolder() // - Sent over network if client is connected to TCP port 47003 //WebRTC.EnableLogging(LogLevel.LOGLVL_INFO); } if (DisplayOrientations.None != _displayOrientation) { WebRTCMedia.SetDisplayOrientation(_displayOrientation); } string videoDeviceId = string.Empty; if (_localSettings.Values.ContainsKey(MediaSettingsIds.VideoDeviceSettings)) { videoDeviceId = (string)_localSettings.Values[MediaSettingsIds.VideoDeviceSettings]; } var videoDevices = Media.GetVideoCaptureDevices(); var selectedVideoDevice = videoDevices.FirstOrDefault(d => d.Id.Equals(videoDeviceId)); selectedVideoDevice = selectedVideoDevice ?? videoDevices.FirstOrDefault(); if (selectedVideoDevice != null) { Media.SelectVideoDevice(selectedVideoDevice); } string audioDeviceId = string.Empty; if (_localSettings.Values.ContainsKey(MediaSettingsIds.AudioDeviceSettings)) { audioDeviceId = (string)_localSettings.Values[MediaSettingsIds.AudioDeviceSettings]; } var audioDevices = Media.GetAudioCaptureDevices(); var selectedAudioDevice = audioDevices.FirstOrDefault(d => d.Id.Equals(audioDeviceId)); selectedAudioDevice = selectedAudioDevice ?? audioDevices.FirstOrDefault(); if (selectedAudioDevice != null) { Media.SelectAudioDevice(selectedAudioDevice); } string audioPlayoutDeviceId = string.Empty; if (_localSettings.Values.ContainsKey(MediaSettingsIds.AudioPlayoutDeviceSettings)) { audioPlayoutDeviceId = (string)_localSettings.Values[MediaSettingsIds.AudioPlayoutDeviceSettings]; } var audioPlayoutDevices = Media.GetAudioPlayoutDevices(); var selectedAudioPlayoutDevice = audioPlayoutDevices.FirstOrDefault(d => d.Id.Equals(audioPlayoutDeviceId)); selectedAudioPlayoutDevice = selectedAudioPlayoutDevice ?? audioPlayoutDevices.FirstOrDefault(); if (selectedAudioPlayoutDevice != null) { Media.SelectAudioPlayoutDevice(selectedAudioPlayoutDevice); } int videoCodecId = int.MinValue; if (_localSettings.Values.ContainsKey(MediaSettingsIds.VideoCodecSettings)) { videoCodecId = (int)_localSettings.Values[MediaSettingsIds.VideoCodecSettings]; } var videoCodecs = WebRTC.GetVideoCodecs(); var selectedVideoCodec = videoCodecs.FirstOrDefault(c => c.Id.Equals(videoCodecId)); SetVideoCodec(DtoExtensions.ToDto(selectedVideoCodec ?? videoCodecs.FirstOrDefault())); int audioCodecId = int.MinValue; if (_localSettings.Values.ContainsKey(MediaSettingsIds.AudioCodecSettings)) { audioCodecId = (int)_localSettings.Values[MediaSettingsIds.AudioCodecSettings]; } var audioCodecs = WebRTC.GetAudioCodecs(); var selectedAudioCodec = audioCodecs.FirstOrDefault(c => c.Id.Equals(audioCodecId)); SetAudioCodec(DtoExtensions.ToDto(selectedAudioCodec ?? audioCodecs.FirstOrDefault())); if (_localSettings.Values.ContainsKey(MediaSettingsIds.PreferredVideoCaptureWidth) && _localSettings.Values.ContainsKey(MediaSettingsIds.PreferredVideoCaptureHeight) && _localSettings.Values.ContainsKey(MediaSettingsIds.PreferredVideoCaptureFrameRate)) { WebRTC.SetPreferredVideoCaptureFormat((int)_localSettings.Values[MediaSettingsIds.PreferredVideoCaptureWidth], (int)_localSettings.Values[MediaSettingsIds.PreferredVideoCaptureHeight], (int)_localSettings.Values[MediaSettingsIds.PreferredVideoCaptureFrameRate]); } ResolutionHelper.ResolutionChanged += (id, width, height) => { if (id == LocalMediaStreamId) { LocalVideoRenderer.ResolutionChanged(width, height); } else if (id == PeerMediaStreamId) { RemoteVideoRenderer.ResolutionChanged(width, height); } }; FrameCounterHelper.FramesPerSecondChanged += (id, frameRate) => { if (id == LocalMediaStreamId) { LocalVideo_FrameRateUpdate(frameRate); } else if (id == PeerMediaStreamId) { RemoteVideo_FrameRateUpdate(frameRate); } }; }
public void SetWindow(CoreWindow window) { ApplicationView.GetForCurrentView().TryEnterFullScreenMode(); // Initializes DirectX. _appCallbacks.SetWindow(window); // Initializes webrtc. WebRTC.Initialize(CoreApplication.MainView.CoreWindow.Dispatcher); Conductor.Instance.ETWStatsEnabled = false; Conductor.Instance.Signaller.OnPeerConnected += (peerId, peerName) => { Conductor.Instance.Peers.Add( _selectedPeer = new Peer { Id = peerId, Name = peerName }); }; Conductor.Instance.Signaller.OnPeerDisconnected += peerId => { var peerToRemove = Conductor.Instance.Peers?.FirstOrDefault(p => p.Id == peerId); if (peerToRemove != null) { Conductor.Instance.Peers.Remove(peerToRemove); } }; Conductor.Instance.OnAddRemoteStream += Conductor_OnAddRemoteStream; Conductor.Instance.OnRemoveRemoteStream += Conductor_OnRemoveRemoteStream; Conductor.Instance.OnAddLocalStream += Conductor_OnAddLocalStream; if (Conductor.Instance.Peers == null) { Conductor.Instance.Peers = new ObservableCollection <Peer>(); } Task.Run(() => { var videoCodecList = WebRTC.GetVideoCodecs().OrderBy(codec => { switch (codec.Name) { case "VP8": return(1); case "VP9": return(2); case "H264": return(3); default: return(99); } }); //Conductor.Instance.VideoCodec = videoCodecList.FirstOrDefault(x => x.Name.Contains("VP8")); Conductor.Instance.VideoCodec = videoCodecList.FirstOrDefault(x => x.Name.Contains("H264")); var audioCodecList = WebRTC.GetAudioCodecs(); string[] incompatibleAudioCodecs = new string[] { "CN32000", "CN16000", "CN8000", "red8000", "telephone-event8000" }; var audioCodecs = new List <CodecInfo>(); foreach (var audioCodec in audioCodecList) { if (!incompatibleAudioCodecs.Contains(audioCodec.Name + audioCodec.ClockRate)) { audioCodecs.Add(audioCodec); } } if (audioCodecs.Count > 0) { Conductor.Instance.AudioCodec = audioCodecs.FirstOrDefault(x => x.Name.Contains("PCMU")); } Conductor.Instance.DisableLocalVideoStream(); Conductor.Instance.MuteMicrophone(); }); }
public IAsyncOperation <DtoCodecInfos> GetAudioCodecsAsync() { RtcManager.Instance.EnsureRtcIsInitialized(); return(Task.FromResult(WebRTC.GetAudioCodecs().ToArray().ToDto()).AsAsyncOperation()); }