示例#1
0
        // ===============================
        // 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);
        }
示例#2
0
        /// <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);
        }
示例#3
0
        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();
            });
        }
示例#4
0
        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);
                }
            };
        }
示例#7
0
        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());
 }