private Task <SIPSorcery.Net.RTCPeerConnection> CreatePeerConnection() { var pc = new SIPSorcery.Net.RTCPeerConnection(null); // Set up sources and hook up send events to peer connection. AudioExtrasSource audioSrc = new AudioExtrasSource(new AudioEncoder(), new AudioSourceOptions { AudioSource = AudioSourcesEnum.None }); audioSrc.OnAudioSourceEncodedSample += pc.SendAudio; //var testPatternSource = new VideoTestPatternSource(); //testPatternSource.SetMaxFrameRate(true); //testPatternSource.OnVideoSourceRawSample += VideoEncoderEndPoint.ExternalVideoSourceRawSample; VideoEncoderEndPoint.OnVideoSourceEncodedSample += pc.SendVideo; // Add tracks. var audioTrack = new SIPSorcery.Net.MediaStreamTrack(audioSrc.GetAudioSourceFormats(), SIPSorcery.Net.MediaStreamStatusEnum.SendOnly); pc.addTrack(audioTrack); var videoTrack = new SIPSorcery.Net.MediaStreamTrack(VideoEncoderEndPoint.GetVideoSourceFormats(), SIPSorcery.Net.MediaStreamStatusEnum.SendOnly); pc.addTrack(videoTrack); // Handlers to set the codecs to use on the sources once the SDP negotiation is complete. pc.OnVideoFormatsNegotiated += (sdpFormat) => VideoEncoderEndPoint.SetVideoSourceFormat(SIPSorcery.Net.SDPMediaFormatInfo.GetVideoCodecForSdpFormat(sdpFormat.First().FormatCodec)); pc.OnAudioFormatsNegotiated += (sdpFormat) => audioSrc.SetAudioSourceFormat(SIPSorcery.Net.SDPMediaFormatInfo.GetAudioCodecForSdpFormat(sdpFormat.First().FormatCodec)); pc.OnTimeout += (mediaType) => logger.LogDebug($"Timeout on media {mediaType}."); pc.oniceconnectionstatechange += (state) => logger.LogDebug($"ICE connection state changed to {state}."); pc.onconnectionstatechange += async(state) => { logger.LogDebug($"Peer connection connected changed to {state}."); if (state == SIPSorcery.Net.RTCPeerConnectionState.connected) { await audioSrc.StartAudio(); //await testPatternSource.StartVideo(); } else if (state == SIPSorcery.Net.RTCPeerConnectionState.closed || state == SIPSorcery.Net.RTCPeerConnectionState.failed) { await audioSrc.CloseAudio(); //await testPatternSource.CloseVideo(); } }; pc.GetRtpChannel().OnStunMessageReceived += (msg, ep, isRelay) => { bool hasUseCandidate = msg.Attributes.Any(x => x.AttributeType == SIPSorcery.Net.STUNAttributeTypesEnum.UseCandidate); logger.LogDebug($"STUN {msg.Header.MessageType} received from {ep}, use candidate {hasUseCandidate}."); }; return(Task.FromResult(pc)); }