public static Task <RTCMediaStreamTrackConfiguration> GetTrackConfigurationForCapabilities(RTCRtpCapabilities sourceCapabilities, RTCRtpCodecCapability preferredCodec) { if (preferredCodec == null) { throw new ArgumentNullException(nameof(preferredCodec)); } return(Task.Run(() => { var capabilities = RTCRtpCapabilities.Clone(sourceCapabilities); // scoope: move prefered codec to be first in the list { var itemsToRemove = capabilities.Codecs.Where(x => x.PreferredPayloadType == preferredCodec.PreferredPayloadType).ToList(); if (itemsToRemove.Count > 0) { RTCRtpCodecCapability codecCapability = itemsToRemove.First(); var modifyList = capabilities.Codecs.ToList(); if (codecCapability != null && modifyList.IndexOf(codecCapability) > 0) { modifyList.Remove(codecCapability); modifyList.Insert(0, codecCapability); } capabilities.Codecs = modifyList; } } RTCMediaStreamTrackConfiguration configuration = new RTCMediaStreamTrackConfiguration() { Capabilities = capabilities }; return configuration; })); }
public Task <IList <ICodec> > GetCodecsAsync(MediaKind kind) { IList <ICodec> videoCodecsList = new List <ICodec>(); IList <ICodec> audioCodecsList = new List <ICodec>(); if (kind == MediaKind.AudioCodec) { return(Task.Run(() => { RTCRtpCapabilities audioCapabilities = RTCRtpSender.GetCapabilities(new WebRtcFactory(new WebRtcFactoryConfiguration()), "audio"); IReadOnlyList <RTCRtpCodecCapability> audioCodecs = audioCapabilities.Codecs; foreach (var item in audioCodecs) { string payload = item.PreferredPayloadType.ToString(); Codec audioCodec = new Codec(); audioCodec.SetMediaKind(MediaKind.AudioCodec); audioCodec.SetId(payload); audioCodec.SetDisplayName(item.Name + " " + payload); audioCodec.SetRate((int)item.ClockRate); audioCodecsList.Add(audioCodec); } return audioCodecsList; })); } if (kind == MediaKind.VideoCodec) { return(Task.Run(() => { RTCRtpCapabilities videoCapabilities = RTCRtpSender.GetCapabilities(new WebRtcFactory(new WebRtcFactoryConfiguration()), "video"); IReadOnlyList <RTCRtpCodecCapability> videoCodecs = videoCapabilities.Codecs; foreach (var item in videoCodecs) { string payload = item.PreferredPayloadType.ToString(); Codec videoCodec = new Codec(); videoCodec.SetMediaKind(MediaKind.VideoCodec); videoCodec.SetId(payload); videoCodec.SetDisplayName(item.Name + " " + payload); videoCodec.SetRate((int)item.ClockRate); videoCodecsList.Add(videoCodec); } return videoCodecsList; })); } else { return(null); } }
public void ReceiverGetAudioCapabilities() { RTCRtpCapabilities capabilities = RTCRtpReceiver.GetCapabilities(TrackKind.Audio); Assert.NotNull(capabilities); Assert.NotNull(capabilities.codecs); Assert.IsNotEmpty(capabilities.codecs); Assert.NotNull(capabilities.headerExtensions); Assert.IsNotEmpty(capabilities.headerExtensions); foreach (var codec in capabilities.codecs) { Assert.NotNull(codec); Assert.IsNotEmpty(codec.mimeType); } foreach (var extensions in capabilities.headerExtensions) { Assert.NotNull(extensions); Assert.IsNotEmpty(extensions.uri); } }
/// <summary> /// Creates a peer connection. /// </summary> /// <returns>True if connection to a peer is successfully created.</returns> private async Task <bool> CreatePeerConnection(CancellationToken cancelationToken) { Debug.Assert(_peerConnection == null); if (cancelationToken.IsCancellationRequested) { return(false); } var config = new RTCConfiguration() { BundlePolicy = RTCBundlePolicy.Balanced, #if ORTCLIB SignalingMode = _signalingMode, GatherOptions = new RTCIceGatherOptions() { IceServers = new List <RTCIceServer>(_iceServers), } #else IceTransportPolicy = RTCIceTransportPolicy.All, IceServers = _iceServers #endif }; Debug.WriteLine("Conductor: Creating peer connection."); _peerConnection = new RTCPeerConnection(config); if (_peerConnection == null) { throw new NullReferenceException("Peer connection is not created."); } #if !ORTCLIB _peerConnection.EtwStatsEnabled = _etwStatsEnabled; _peerConnection.ConnectionHealthStatsEnabled = _peerConnectionStatsEnabled; #endif if (cancelationToken.IsCancellationRequested) { return(false); } #if ORTCLIB OrtcStatsManager.Instance.Initialize(_peerConnection); #endif OnPeerConnectionCreated?.Invoke(); _peerConnection.OnIceCandidate += PeerConnection_OnIceCandidate; #if ORTCLIB _peerConnection.OnTrack += PeerConnection_OnAddTrack; _peerConnection.OnTrackGone += PeerConnection_OnRemoveTrack; _peerConnection.OnIceConnectionStateChange += () => { Debug.WriteLine("Conductor: Ice connection state change, state=" + (null != _peerConnection ? _peerConnection.IceConnectionState.ToString() : "closed")); }; #else _peerConnection.OnAddStream += PeerConnection_OnAddStream; _peerConnection.OnRemoveStream += PeerConnection_OnRemoveStream; _peerConnection.OnConnectionHealthStats += PeerConnection_OnConnectionHealthStats; #endif Debug.WriteLine("Conductor: Getting user media."); RTCMediaStreamConstraints mediaStreamConstraints = new RTCMediaStreamConstraints { // Always include audio/video enabled in the media stream, // so it will be possible to enable/disable audio/video if // the call was initiated without microphone/camera audioEnabled = true, videoEnabled = true }; if (cancelationToken.IsCancellationRequested) { return(false); } #if ORTCLIB var tracks = await _media.GetUserMedia(mediaStreamConstraints); if (tracks != null) { RTCRtpCapabilities audioCapabilities = RTCRtpSender.GetCapabilities("audio"); RTCRtpCapabilities videoCapabilities = RTCRtpSender.GetCapabilities("video"); _mediaStream = new MediaStream(tracks); Debug.WriteLine("Conductor: Adding local media stream."); IList <MediaStream> mediaStreamList = new List <MediaStream>(); mediaStreamList.Add(_mediaStream); foreach (var mediaStreamTrack in tracks) { //Create stream track configuration based on capabilities RTCMediaStreamTrackConfiguration configuration = null; if (mediaStreamTrack.Kind == MediaStreamTrackKind.Audio && audioCapabilities != null) { configuration = await Helper.GetTrackConfigurationForCapabilities(audioCapabilities, AudioCodec); } else if (mediaStreamTrack.Kind == MediaStreamTrackKind.Video && videoCapabilities != null) { configuration = await Helper.GetTrackConfigurationForCapabilities(videoCapabilities, VideoCodec); } if (configuration != null) { _peerConnection.AddTrack(mediaStreamTrack, mediaStreamList, configuration); } } } #else _mediaStream = await _media.GetUserMedia(mediaStreamConstraints); #endif if (cancelationToken.IsCancellationRequested) { return(false); } #if !ORTCLIB Debug.WriteLine("Conductor: Adding local media stream."); _peerConnection.AddStream(_mediaStream); #endif OnAddLocalStream?.Invoke(new MediaStreamEvent() { Stream = _mediaStream }); if (cancelationToken.IsCancellationRequested) { return(false); } return(true); }