static async Task Main() { Console.WriteLine("SIPSorcery Getting Started Demo"); AddConsoleLogger(); var sipTransport = new SIPTransport(); var userAgent = new SIPUserAgent(sipTransport, null); var winAudio = new WindowsAudioEndPoint(new AudioEncoder()); var voipMediaSession = new VoIPMediaSession(new MediaEndPoints { AudioSink = winAudio, AudioSource = winAudio }); // Place the call and wait for the result. bool callResult = await userAgent.Call(DESTINATION, null, null, voipMediaSession); Console.WriteLine($"Call result {((callResult) ? "success" : "failure")}."); Console.WriteLine("press any key to exit..."); Console.Read(); if (userAgent.IsCallActive) { Console.WriteLine("Hanging up."); userAgent.Hangup(); } // Clean up. sipTransport.Shutdown(); }
static void Main() { Console.WriteLine("SIPSorcery Getting Started Demo"); Log = AddConsoleLogger(); _waveFile = new WaveFileWriter("output.mp3", _waveFormat); _sipTransport = new SIPTransport(); _sipTransport.AddSIPChannel(new SIPUDPChannel(new IPEndPoint(IPAddress.Any, SIP_LISTEN_PORT))); var userAgent = new SIPUserAgent(_sipTransport, null, true); userAgent.ServerCallCancelled += (uas) => Log.LogDebug("Incoming call cancelled by remote party."); userAgent.OnCallHungup += (dialog) => _waveFile?.Close(); userAgent.OnIncomingCall += async(ua, req) => { WindowsAudioEndPoint winAudioEP = new WindowsAudioEndPoint(new AudioEncoder()); VoIPMediaSession voipMediaSession = new VoIPMediaSession(winAudioEP.ToMediaEndPoints()); voipMediaSession.AcceptRtpFromAny = true; voipMediaSession.OnRtpPacketReceived += OnRtpPacketReceived; var uas = userAgent.AcceptCall(req); await userAgent.Answer(uas, voipMediaSession); }; Console.WriteLine("press any key to exit..."); Console.Read(); // Clean up. _sipTransport.Shutdown(); }
static async Task Main() { Console.WriteLine("SIPSorcery Getting Started Demo"); AddConsoleLogger(); _waveFile = new WaveFileWriter("output.mp3", _waveFormat); var sipTransport = new SIPTransport(); var userAgent = new SIPUserAgent(sipTransport, null); userAgent.ClientCallFailed += (uac, err, resp) => { Console.WriteLine($"Call failed {err}"); _waveFile?.Close(); }; userAgent.OnCallHungup += (dialog) => _waveFile?.Close(); WindowsAudioEndPoint winAudioEP = new WindowsAudioEndPoint(new AudioEncoder()); VoIPMediaSession voipSession = new VoIPMediaSession(winAudioEP.ToMediaEndPoints()); voipSession.OnRtpPacketReceived += OnRtpPacketReceived; // Ctrl-c will gracefully exit the call at any point. Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e) { e.Cancel = true; if (userAgent.IsCallActive) { Console.WriteLine("Hanging up."); userAgent.Hangup(); } else { Console.WriteLine("Cancelling call"); userAgent.Cancel(); } }; // Place the call and wait for the result. bool callResult = await userAgent.Call(DESTINATION, null, null, voipSession); Console.WriteLine($"Call result {((callResult) ? "success" : "failure")}."); Console.WriteLine("press any key to exit..."); Console.Read(); if (userAgent.IsCallActive) { Console.WriteLine("Hanging up."); userAgent.Hangup(); } // Clean up. sipTransport.Shutdown(); }
private static async Task <RTCPeerConnection> SendSDPOffer(WebSocketContext context) { logger.LogDebug($"Web socket client connection from {context.UserEndPoint}."); var peerConnection = new RTCPeerConnection(null); // Sink (speaker) only audio end point. WindowsAudioEndPoint windowsAudioEP = new WindowsAudioEndPoint(new AudioEncoder(), -1, -1, true, false); MediaStreamTrack audioTrack = new MediaStreamTrack(windowsAudioEP.GetAudioSinkFormats(), MediaStreamStatusEnum.RecvOnly); peerConnection.addTrack(audioTrack); peerConnection.OnAudioFormatsNegotiated += (audioFormats) => windowsAudioEP.SetAudioSinkFormat(audioFormats.First()); peerConnection.OnReceiveReport += RtpSession_OnReceiveReport; peerConnection.OnSendReport += RtpSession_OnSendReport; peerConnection.OnTimeout += (mediaType) => logger.LogDebug($"Timeout on media {mediaType}."); peerConnection.oniceconnectionstatechange += (state) => logger.LogDebug($"ICE connection state changed to {state}."); peerConnection.onconnectionstatechange += async(state) => { logger.LogDebug($"Peer connection connected changed to {state}."); if (state == RTCPeerConnectionState.connected) { await windowsAudioEP.StartAudio(); } else if (state == RTCPeerConnectionState.closed || state == RTCPeerConnectionState.failed) { peerConnection.OnReceiveReport -= RtpSession_OnReceiveReport; peerConnection.OnSendReport -= RtpSession_OnSendReport; await windowsAudioEP.CloseAudio(); } }; peerConnection.OnRtpPacketReceived += (IPEndPoint rep, SDPMediaTypesEnum media, RTPPacket rtpPkt) => { //logger.LogDebug($"RTP {media} pkt received, SSRC {rtpPkt.Header.SyncSource}."); if (media == SDPMediaTypesEnum.audio) { windowsAudioEP.GotAudioRtp(rep, rtpPkt.Header.SyncSource, rtpPkt.Header.SequenceNumber, rtpPkt.Header.Timestamp, rtpPkt.Header.PayloadType, rtpPkt.Header.MarkerBit == 1, rtpPkt.Payload); } }; var offerSdp = peerConnection.createOffer(null); await peerConnection.setLocalDescription(offerSdp); logger.LogDebug($"Sending SDP offer to client {context.UserEndPoint}."); logger.LogDebug(offerSdp.sdp); context.WebSocket.Send(offerSdp.sdp); return(peerConnection); }
private static Task <RTCPeerConnection> CreatePeerConnection() { RTCConfiguration config = new RTCConfiguration { iceServers = new List <RTCIceServer> { new RTCIceServer { urls = STUN_URL } } }; var pc = new RTCPeerConnection(config); //AudioExtrasSource audioSource = new AudioExtrasSource(new AudioEncoder(), new AudioSourceOptions { AudioSource = AudioSourcesEnum.SineWave }); //audioSource.OnAudioSourceEncodedSample += pc.SendAudio; WindowsAudioEndPoint audioSource = new WindowsAudioEndPoint(new AudioEncoder()); audioSource.OnAudioSourceEncodedSample += pc.SendAudio; MediaStreamTrack audioTrack = new MediaStreamTrack(audioSource.GetAudioSourceFormats(), MediaStreamStatusEnum.SendOnly); pc.addTrack(audioTrack); pc.OnAudioFormatsNegotiated += (audioFormats) => audioSource.SetAudioSourceFormat(audioFormats.First()); pc.onconnectionstatechange += async(state) => { logger.LogDebug($"Peer connection state change to {state}."); if (state == RTCPeerConnectionState.connected) { await audioSource.StartAudio(); } else if (state == RTCPeerConnectionState.failed) { pc.Close("ice disconnection"); } else if (state == RTCPeerConnectionState.closed) { await audioSource.CloseAudio(); } }; // Diagnostics. pc.OnReceiveReport += (re, media, rr) => logger.LogDebug($"RTCP Receive for {media} from {re}\n{rr.GetDebugSummary()}"); pc.OnSendReport += (media, sr) => logger.LogDebug($"RTCP Send for {media}\n{sr.GetDebugSummary()}"); pc.GetRtpChannel().OnStunMessageReceived += (msg, ep, isRelay) => logger.LogDebug($"STUN {msg.Header.MessageType} received from {ep}."); pc.oniceconnectionstatechange += (state) => logger.LogDebug($"ICE connection state change to {state}."); return(Task.FromResult(pc)); }
static async Task Main() { Console.WriteLine("SIP Get Started"); var userAgent = new SIPUserAgent(); var winAudio = new WindowsAudioEndPoint(new AudioEncoder()); var voipMediaSession = new VoIPMediaSession(winAudio.ToMediaEndPoints()); voipMediaSession.AcceptRtpFromAny = true; // Place the call and wait for the result. bool callResult = await userAgent.Call(DESTINATION, null, null, voipMediaSession); Console.WriteLine($"Call result {((callResult) ? "success" : "failure")}."); Console.WriteLine("Press any key to hangup and exit."); Console.ReadLine(); }
/// <summary> /// Creates the media session to use with the SIP call. /// </summary> /// <param name="audioSrcOpts">The audio source options to set when the call is first /// answered. These options can be adjusted afterwards to do things like put play /// on hold music etc.</param> /// <returns>A new media session object.</returns> private VoIPMediaSession CreateMediaSession() { var windowsAudioEndPoint = new WindowsAudioEndPoint(new AudioEncoder(), m_audioOutDeviceIndex); var windowsVideoEndPoint = new WindowsVideoEndPoint(); MediaEndPoints mediaEndPoints = new MediaEndPoints { AudioSink = windowsAudioEndPoint, AudioSource = windowsAudioEndPoint, VideoSink = windowsVideoEndPoint, VideoSource = windowsVideoEndPoint, }; var voipMediaSession = new VoIPMediaSession(mediaEndPoints); voipMediaSession.AcceptRtpFromAny = true; return(voipMediaSession); }
/// <summary> /// Creates the media session to use with the SIP call. /// </summary> /// <param name="audioSrcOpts">The audio source options to set when the call is first /// answered. These options can be adjusted afterwards to do things like put play /// on hold music etc.</param> /// <returns>A new media session object.</returns> private VoIPMediaSession CreateMediaSession() { var windowsAudioEndPoint = new WindowsAudioEndPoint(new AudioEncoder(), m_audioOutDeviceIndex); var windowsVideoEndPoint = new WindowsVideoEndPoint(); MediaEndPoints mediaEndPoints = new MediaEndPoints { AudioSink = windowsAudioEndPoint, AudioSource = windowsAudioEndPoint, VideoSink = windowsVideoEndPoint, VideoSource = windowsVideoEndPoint, }; // Fallback video source if a Windows webcam cannot be accessed. var testPatternSource = new VideoTestPatternSource(new VideoEncoder()); var voipMediaSession = new VoIPMediaSession(mediaEndPoints, testPatternSource); // voipMediaSession.OnRtpPacketReceived += OnRtpPacketReceived; return(voipMediaSession); }
static void Main() { Console.WriteLine("SIPSorcery Call Hold and Blind Transfer example."); Console.WriteLine("Press 'c' to initiate a call to the default destination."); Console.WriteLine("Press 'h' to place an established call on and off hold."); Console.WriteLine("Press 'H' to hangup an established call."); Console.WriteLine("Press 't' to request a blind transfer on an established call."); Console.WriteLine("Press 'q' or ctrl-c to exit."); // Plumbing code to facilitate a graceful exit. CancellationTokenSource exitCts = new CancellationTokenSource(); // Cancellation token to stop the SIP transport and RTP stream. Log = AddConsoleLogger(); // Set up a default SIP transport. var sipTransport = new SIPTransport(); sipTransport.AddSIPChannel(new SIPUDPChannel(new IPEndPoint(IPAddress.Any, SIP_LISTEN_PORT))); Console.WriteLine($"Listening for incoming calls on: {sipTransport.GetSIPChannels().First().ListeningEndPoint}."); EnableTraceLogs(sipTransport); var winAudio = new WindowsAudioEndPoint(new AudioEncoder()); winAudio.RestrictCodecs(new List <AudioCodecsEnum> { AudioCodecsEnum.PCMU }); // Create a client/server user agent to place a call to a remote SIP server along with event handlers for the different stages of the call. var userAgent = new SIPUserAgent(sipTransport, null, true); userAgent.RemotePutOnHold += () => Log.LogInformation("Remote call party has placed us on hold."); userAgent.RemoteTookOffHold += () => Log.LogInformation("Remote call party took us off hold."); userAgent.OnIncomingCall += async(ua, req) => { Log.LogInformation($"Incoming call from {req.Header.From.FriendlyDescription()} at {req.RemoteSIPEndPoint}."); var uas = userAgent.AcceptCall(req); if (userAgent?.IsCallActive == true) { // If we are already on a call return a busy response. Log.LogWarning($"Busy response returned for incoming call request."); uas.Reject(SIPResponseStatusCodesEnum.BusyHere, null); } else { var voipSession = new VoIPMediaSession(winAudio.ToMediaEndPoints()); voipSession.AcceptRtpFromAny = true; var answerResult = await userAgent.Answer(uas, voipSession); } }; // At this point the call has been initiated and everything will be handled in an event handler. Task.Run(async() => { try { while (!exitCts.Token.WaitHandle.WaitOne(0)) { var keyProps = Console.ReadKey(); if (keyProps.KeyChar == 'c') { if (!userAgent.IsCallActive) { var voipSession = new VoIPMediaSession(winAudio.ToMediaEndPoints()); voipSession.AcceptRtpFromAny = true; bool callResult = await userAgent.Call(DEFAULT_DESTINATION_SIP_URI, SIP_USERNAME, SIP_PASSWORD, voipSession); Log.LogInformation($"Call attempt {((callResult) ? "successfull" : "failed")}."); } else { Log.LogWarning("There is already an active call."); } } else if (keyProps.KeyChar == 'h') { // Place call on/off hold. if (userAgent.IsCallActive) { if (userAgent.IsOnLocalHold) { Log.LogInformation("Taking the remote call party off hold."); (userAgent.MediaSession as VoIPMediaSession).TakeOffHold(); userAgent.TakeOffHold(); } else { Log.LogInformation("Placing the remote call party on hold."); await(userAgent.MediaSession as VoIPMediaSession).PutOnHold(); userAgent.PutOnHold(); } } else { Log.LogWarning("There is no active call to put on hold."); } } else if (keyProps.KeyChar == 'H') { if (userAgent.IsCallActive) { Log.LogInformation("Hanging up call."); userAgent.Hangup(); } } else if (keyProps.KeyChar == 't') { // Initiate a blind transfer to the remote call party. if (userAgent.IsCallActive) { var transferURI = SIPURI.ParseSIPURI(TRANSFER_DESTINATION_SIP_URI); bool result = await userAgent.BlindTransfer(transferURI, TimeSpan.FromSeconds(TRANSFER_TIMEOUT_SECONDS), exitCts.Token); if (result) { // If the transfer was accepted the original call will already have been hungup. // Wait a second for the transfer NOTIFY request to arrive. await Task.Delay(1000); exitCts.Cancel(); } else { Log.LogWarning($"Transfer to {TRANSFER_DESTINATION_SIP_URI} failed."); } } else { Log.LogWarning("There is no active call to transfer."); } } else if (keyProps.KeyChar == 'q') { // Quit application. exitCts.Cancel(); } } } catch (Exception excp) { Log.LogError($"Exception Key Press listener. {excp.Message}."); } }); // Ctrl-c will gracefully exit the call at any point. Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e) { e.Cancel = true; exitCts.Cancel(); }; // Wait for a signal saying the call failed, was cancelled with ctrl-c or completed. exitCts.Token.WaitHandle.WaitOne(); #region Cleanup. Log.LogInformation("Exiting..."); if (userAgent != null) { if (userAgent.IsCallActive) { Log.LogInformation($"Hanging up call to {userAgent?.CallDescriptor?.To}."); userAgent.Hangup(); } // Give the BYE or CANCEL request time to be transmitted. Log.LogInformation("Waiting 1s for call to clean up..."); Task.Delay(1000).Wait(); } if (sipTransport != null) { Log.LogInformation("Shutting down SIP transport..."); sipTransport.Shutdown(); } #endregion }
static void Main(string[] args) { Console.WriteLine("SIPSorcery client user agent example."); Console.WriteLine("Press ctrl-c to exit."); // Plumbing code to facilitate a graceful exit. ManualResetEvent exitMre = new ManualResetEvent(false); bool isCallHungup = false; bool hasCallFailed = false; Log = AddConsoleLogger(); SIPURI callUri = SIPURI.ParseSIPURI(DEFAULT_DESTINATION_SIP_URI); if (args != null && args.Length > 0) { if (!SIPURI.TryParse(args[0], out callUri)) { Log.LogWarning($"Command line argument could not be parsed as a SIP URI {args[0]}"); } } Log.LogInformation($"Call destination {callUri}."); // Set up a default SIP transport. var sipTransport = new SIPTransport(); EnableTraceLogs(sipTransport); var audioSession = new WindowsAudioEndPoint(new AudioEncoder()); var rtpSession = new VoIPMediaSession(audioSession.ToMediaEndPoints()); var offerSDP = rtpSession.CreateOffer(null); // Create a client user agent to place a call to a remote SIP server along with event handlers for the different stages of the call. var uac = new SIPClientUserAgent(sipTransport); uac.CallTrying += (uac, resp) => Log.LogInformation($"{uac.CallDescriptor.To} Trying: {resp.StatusCode} {resp.ReasonPhrase}."); uac.CallRinging += async(uac, resp) => { Log.LogInformation($"{uac.CallDescriptor.To} Ringing: {resp.StatusCode} {resp.ReasonPhrase}."); if (resp.Status == SIPResponseStatusCodesEnum.SessionProgress) { await rtpSession.Start(); } }; uac.CallFailed += (uac, err, resp) => { Log.LogWarning($"Call attempt to {uac.CallDescriptor.To} Failed: {err}"); hasCallFailed = true; }; uac.CallAnswered += async(iuac, resp) => { if (resp.Status == SIPResponseStatusCodesEnum.Ok) { Log.LogInformation($"{uac.CallDescriptor.To} Answered: {resp.StatusCode} {resp.ReasonPhrase}."); var result = rtpSession.SetRemoteDescription(SdpType.answer, SDP.ParseSDPDescription(resp.Body)); if (result == SetDescriptionResultEnum.OK) { await rtpSession.Start(); } else { Log.LogWarning($"Failed to set remote description {result}."); uac.Hangup(); } } else { Log.LogWarning($"{uac.CallDescriptor.To} Answered: {resp.StatusCode} {resp.ReasonPhrase}."); } }; // The only incoming request that needs to be explicitly handled for this example is if the remote end hangs up the call. sipTransport.SIPTransportRequestReceived += async(SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPRequest sipRequest) => { if (sipRequest.Method == SIPMethodsEnum.BYE) { SIPResponse okResponse = SIPResponse.GetResponse(sipRequest, SIPResponseStatusCodesEnum.Ok, null); await sipTransport.SendResponseAsync(okResponse); if (uac.IsUACAnswered) { Log.LogInformation("Call was hungup by remote server."); isCallHungup = true; exitMre.Set(); } } }; // Start the thread that places the call. SIPCallDescriptor callDescriptor = new SIPCallDescriptor( SIPConstants.SIP_DEFAULT_USERNAME, null, callUri.ToString(), SIPConstants.SIP_DEFAULT_FROMURI, callUri.CanonicalAddress, null, null, null, SIPCallDirection.Out, SDP.SDP_MIME_CONTENTTYPE, offerSDP.ToString(), null); uac.Call(callDescriptor, null); uac.ServerTransaction.TransactionTraceMessage += (tx, msg) => Log.LogInformation($"UAC tx trace message. {msg}"); // Ctrl-c will gracefully exit the call at any point. Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e) { e.Cancel = true; exitMre.Set(); }; // Wait for a signal saying the call failed, was cancelled with ctrl-c or completed. exitMre.WaitOne(); Log.LogInformation("Exiting..."); rtpSession.Close(null); if (!isCallHungup && uac != null) { if (uac.IsUACAnswered) { Log.LogInformation($"Hanging up call to {uac.CallDescriptor.To}."); uac.Hangup(); } else if (!hasCallFailed) { Log.LogInformation($"Cancelling call to {uac.CallDescriptor.To}."); uac.Cancel(); } // Give the BYE or CANCEL request time to be transmitted. Log.LogInformation("Waiting 1s for call to clean up..."); Task.Delay(1000).Wait(); } if (sipTransport != null) { Log.LogInformation("Shutting down SIP transport..."); sipTransport.Shutdown(); } }
static async Task Main() { Console.WriteLine("SIPSorcery Send DTMF Tones example."); Console.WriteLine("Press ctrl-c to exit."); // Plumbing code to facilitate a graceful exit. CancellationTokenSource rtpCts = new CancellationTokenSource(); // Cancellation token to stop the RTP stream. Log = AddConsoleLogger(); var sipTransport = new SIPTransport(); var userAgent = new SIPUserAgent(sipTransport, null); var winAudioEP = new WindowsAudioEndPoint(new AudioEncoder()); var voipMediaSession = new VoIPMediaSession(winAudioEP.ToMediaEndPoints()); Console.WriteLine($"Calling {DEFAULT_DESTINATION_SIP_URI}."); // Place the call and wait for the result. bool callResult = await userAgent.Call(DEFAULT_DESTINATION_SIP_URI, null, null, voipMediaSession); // Ctrl-c will gracefully exit the call at any point. Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e) { e.Cancel = true; rtpCts.Cancel(); }; if (callResult) { Console.WriteLine("Call attempt successful."); // Give the call some time to answer. await Task.Delay(1000); // Send the DTMF tones. await userAgent.SendDtmf(0x05); await Task.Delay(2000); await userAgent.SendDtmf(0x09); await Task.Delay(2000); await userAgent.SendDtmf(0x02); await Task.Delay(2000); if (userAgent.IsCallActive) { Console.WriteLine("Hanging up."); rtpCts.Cancel(); userAgent.Hangup(); } } else { Console.WriteLine("Call attempt failed."); } Log.LogInformation("Exiting..."); // Clean up. sipTransport.Shutdown(); }
static async Task Main() { Console.WriteLine("SIPSorcery Play Sounds Demo"); AddConsoleLogger(); CancellationTokenSource exitCts = new CancellationTokenSource(); var sipTransport = new SIPTransport(); EnableTraceLogs(sipTransport); var userAgent = new SIPUserAgent(sipTransport, OUTBOUND_PROXY); userAgent.ClientCallFailed += (uac, error, sipResponse) => Console.WriteLine($"Call failed {error}."); userAgent.ClientCallFailed += (uac, error, sipResponse) => exitCts.Cancel(); userAgent.OnCallHungup += (dialog) => exitCts.Cancel(); var windowsAudio = new WindowsAudioEndPoint(new AudioEncoder()); //windowsAudio.RestrictFormats(format => format.Codec == AudioCodecsEnum.PCMU); var voipMediaSession = new VoIPMediaSession(windowsAudio.ToMediaEndPoints()); voipMediaSession.AcceptRtpFromAny = true; //voipMediaSession.AudioExtrasSource.AudioSamplePeriodMilliseconds = 20; //voipMediaSession.AudioLocalTrack.Capabilities.Clear(); //voipMediaSession.AudioLocalTrack.Capabilities.Add( // new SDPAudioVideoMediaFormat(new AudioFormat(AudioCodecsEnum.L16, 118, 8000))); Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e) { e.Cancel = true; if (userAgent != null) { if (userAgent.IsCalling || userAgent.IsRinging) { Console.WriteLine("Cancelling in progress call."); userAgent.Cancel(); } else if (userAgent.IsCallActive) { Console.WriteLine("Hanging up established call."); userAgent.Hangup(); } } ; exitCts.Cancel(); }; // Place the call and wait for the result. var callTask = userAgent.Call(DESTINATION, null, null, voipMediaSession); Console.WriteLine("press ctrl-c to exit..."); bool callResult = await callTask; if (callResult) { Console.WriteLine($"Call to {DESTINATION} succeeded."); await windowsAudio.PauseAudio(); try { await voipMediaSession.AudioExtrasSource.StartAudio(); //Console.WriteLine("Sending welcome message from 8KHz sample."); await voipMediaSession.AudioExtrasSource.SendAudioFromStream(new FileStream(WELCOME_8K, FileMode.Open), AudioSamplingRatesEnum.Rate8KHz); await Task.Delay(200, exitCts.Token); Console.WriteLine("Sending sine wave."); voipMediaSession.AudioExtrasSource.SetSource(AudioSourcesEnum.SineWave); await Task.Delay(5000, exitCts.Token); Console.WriteLine("Sending white noise signal."); voipMediaSession.AudioExtrasSource.SetSource(AudioSourcesEnum.WhiteNoise); await Task.Delay(2000, exitCts.Token); Console.WriteLine("Sending pink noise signal."); voipMediaSession.AudioExtrasSource.SetSource(AudioSourcesEnum.PinkNoise); await Task.Delay(2000, exitCts.Token); Console.WriteLine("Sending silence."); voipMediaSession.AudioExtrasSource.SetSource(AudioSourcesEnum.Silence); await Task.Delay(2000, exitCts.Token); Console.WriteLine("Playing music."); voipMediaSession.AudioExtrasSource.SetSource(AudioSourcesEnum.Music); await Task.Delay(5000, exitCts.Token); Console.WriteLine("Sending goodbye message from 16KHz sample."); await voipMediaSession.AudioExtrasSource.SendAudioFromStream(new FileStream(GOODBYE_16K, FileMode.Open), AudioSamplingRatesEnum.Rate16KHz); voipMediaSession.AudioExtrasSource.SetSource(AudioSourcesEnum.None); await voipMediaSession.AudioExtrasSource.PauseAudio(); await Task.Delay(200, exitCts.Token); } catch (System.Threading.Tasks.TaskCanceledException) { } // Switch to the external microphone input source. await windowsAudio.ResumeAudio(); exitCts.Token.WaitHandle.WaitOne(); } else { Console.WriteLine($"Call to {DESTINATION} failed."); } Console.WriteLine("Exiting..."); if (userAgent?.IsHangingUp == true) { Console.WriteLine("Waiting 1s for the call hangup or cancel to complete..."); await Task.Delay(1000); } // Clean up. sipTransport.Shutdown(); }
private static SIPEndPoint OUTBOUND_PROXY = null; // SIPEndPoint.ParseSIPEndPoint("udp:192.168.0.148:5060"); static async Task Main() { Console.WriteLine("SIPSorcery Getting Started Demo"); AddConsoleLogger(); CancellationTokenSource exitCts = new CancellationTokenSource(); var sipTransport = new SIPTransport(); EnableTraceLogs(sipTransport); var userAgent = new SIPUserAgent(sipTransport, OUTBOUND_PROXY); userAgent.ClientCallFailed += (uac, error, sipResponse) => Console.WriteLine($"Call failed {error}."); userAgent.OnCallHungup += (dialog) => exitCts.Cancel(); var windowsAudio = new WindowsAudioEndPoint(new AudioEncoder()); var voipMediaSession = new VoIPMediaSession(windowsAudio.ToMediaEndPoints()); voipMediaSession.AcceptRtpFromAny = true; // Place the call and wait for the result. var callTask = userAgent.Call(DESTINATION, null, null, voipMediaSession); Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e) { e.Cancel = true; if (userAgent != null) { if (userAgent.IsCalling || userAgent.IsRinging) { Console.WriteLine("Cancelling in progress call."); userAgent.Cancel(); } else if (userAgent.IsCallActive) { Console.WriteLine("Hanging up established call."); userAgent.Hangup(); } } ; exitCts.Cancel(); }; Console.WriteLine("press ctrl-c to exit..."); bool callResult = await callTask; if (callResult) { Console.WriteLine($"Call to {DESTINATION} succeeded."); exitCts.Token.WaitHandle.WaitOne(); } else { Console.WriteLine($"Call to {DESTINATION} failed."); } Console.WriteLine("Exiting..."); if (userAgent?.IsHangingUp == true) { Console.WriteLine("Waiting 1s for the call hangup or cancel to complete..."); await Task.Delay(1000); } // Clean up. sipTransport.Shutdown(); }
static void Main() { Console.WriteLine("SIPSorcery Attended Transfer example."); Console.WriteLine("Press 'c' to place a call to the default destination."); Console.WriteLine("Place two simultaneous SIP calls to this program and then press 't'."); Console.WriteLine("Press 'q' or ctrl-c to exit."); // Plumbing code to facilitate a graceful exit. CancellationTokenSource exitCts = new CancellationTokenSource(); // Cancellation token to stop the SIP transport and RTP stream. Log = AddConsoleLogger(); // Set up a default SIP transport. var sipTransport = new SIPTransport(); sipTransport.AddSIPChannel(new SIPUDPChannel(new IPEndPoint(IPAddress.Any, SIP_LISTEN_PORT))); //EnableTraceLogs(sipTransport); // Create two user agents. Each gets configured to answer an incoming call. var userAgent1 = new SIPUserAgent(sipTransport, null); var userAgent2 = new SIPUserAgent(sipTransport, null); userAgent1.OnCallHungup += (dialog) => Log.LogInformation($"UA1: Call hungup by remote party."); userAgent1.ServerCallCancelled += (uas) => Log.LogInformation("UA1: Incoming call cancelled by caller."); userAgent2.OnCallHungup += (dialog) => Log.LogInformation($"UA2: Call hungup by remote party."); userAgent2.ServerCallCancelled += (uas) => Log.LogInformation("UA2: Incoming call cancelled by caller."); userAgent2.OnTransferNotify += (sipFrag) => { if (!string.IsNullOrEmpty(sipFrag)) { Log.LogInformation($"UA2: Transfer status update: {sipFrag.Trim()}."); if (sipFrag?.Contains("SIP/2.0 200") == true) { // The transfer attempt got a successful answer. Can hangup the call. userAgent2.Hangup(); exitCts.Cancel(); } } }; sipTransport.SIPTransportRequestReceived += async(localEndPoint, remoteEndPoint, sipRequest) => { if (sipRequest.Header.From != null && sipRequest.Header.From.FromTag != null && sipRequest.Header.To != null && sipRequest.Header.To.ToTag != null) { // This is an in-dialog request that will be handled directly by a user agent instance. } else if (sipRequest.Method == SIPMethodsEnum.INVITE) { if (!userAgent1.IsCallActive || !userAgent2.IsCallActive) { SIPUserAgent activeAgent = (!userAgent1.IsCallActive) ? userAgent1 : userAgent2; string agentDesc = (!userAgent1.IsCallActive) ? "UA1" : "UA2"; Log.LogInformation($"{agentDesc}: Incoming call request from {remoteEndPoint}: {sipRequest.StatusLine}."); var incomingCall = activeAgent.AcceptCall(sipRequest); WindowsAudioEndPoint winAudio = new WindowsAudioEndPoint(new AudioEncoder()); var voipMediaSession = new VoIPMediaSession(winAudio.ToMediaEndPoints()); await activeAgent.Answer(incomingCall, voipMediaSession); Log.LogInformation($"{agentDesc}: Answered incoming call from {sipRequest.Header.From.FriendlyDescription()} at {remoteEndPoint}."); } else { // If both user agents are already on a call return a busy response. Log.LogWarning($"Busy response returned for incoming call request from {remoteEndPoint}: {sipRequest.StatusLine}."); UASInviteTransaction uasTransaction = new UASInviteTransaction(sipTransport, sipRequest, null); SIPResponse busyResponse = SIPResponse.GetResponse(sipRequest, SIPResponseStatusCodesEnum.BusyHere, null); uasTransaction.SendFinalResponse(busyResponse); } } else { Log.LogDebug($"SIP {sipRequest.Method} request received but no processing has been set up for it, rejecting."); SIPResponse notAllowedResponse = SIPResponse.GetResponse(sipRequest, SIPResponseStatusCodesEnum.MethodNotAllowed, null); await sipTransport.SendResponseAsync(notAllowedResponse); } }; // At this point the call has been initiated and everything will be handled in an event handler. Task.Run(async() => { try { while (!exitCts.Token.WaitHandle.WaitOne(0)) { var keyProps = Console.ReadKey(); if (keyProps.KeyChar == 'c') { // Place an outgoing call using the first free user agent. SIPUserAgent freeAgent = (!userAgent1.IsCallActive) ? userAgent1 : (!userAgent2.IsCallActive) ? userAgent2 : null; if (freeAgent != null) { WindowsAudioEndPoint winAudio = new WindowsAudioEndPoint(new AudioEncoder()); var voipMediaSession = new VoIPMediaSession(winAudio.ToMediaEndPoints()); bool callResult = await freeAgent.Call(DEFAULT_DESTINATION_SIP_URI, null, null, voipMediaSession); Log.LogInformation($"Call attempt {((callResult) ? "successfull" : "failed")}."); } else { Log.LogWarning("Both user agents are already on calls."); } } if (keyProps.KeyChar == 't') { // Initiate the attended transfer. if (userAgent1.IsCallActive && userAgent2.IsCallActive) { bool result = await userAgent2.AttendedTransfer(userAgent1.Dialogue, TimeSpan.FromSeconds(TRANSFER_TIMEOUT_SECONDS), exitCts.Token); if (!result) { Log.LogWarning($"Attended transfer failed."); } } else { Log.LogWarning("There need to be two active calls before the attended transfer can occur."); } } else if (keyProps.KeyChar == 'q') { // Quit application. exitCts.Cancel(); } } } catch (Exception excp) { Log.LogError($"Exception Key Press listener. {excp.Message}."); } }); // Ctrl-c will gracefully exit the call at any point. Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e) { e.Cancel = true; exitCts.Cancel(); }; // Wait for a signal saying the call failed, was cancelled with ctrl-c or completed. exitCts.Token.WaitHandle.WaitOne(); #region Cleanup. Log.LogInformation("Exiting..."); userAgent1?.Hangup(); userAgent2?.Hangup(); // Give any BYE or CANCEL requests time to be transmitted. Log.LogInformation("Waiting 1s for calls to be cleaned up..."); Task.Delay(1000).Wait(); if (sipTransport != null) { Log.LogInformation("Shutting down SIP transport..."); sipTransport.Shutdown(); } #endregion }
static async Task Main(string[] args) { Console.WriteLine("SIPSorcery Video Phone Command Line Demo"); Console.WriteLine("Press ctrl-c to exit."); Log = AddConsoleLogger(); ManualResetEvent exitMRE = new ManualResetEvent(false); ManualResetEvent waitForCallMre = new ManualResetEvent(false); var parseResult = Parser.Default.ParseArguments <Options>(args); _options = (parseResult as Parsed <Options>)?.Value; if (parseResult.Tag != ParserResultType.NotParsed) { if (_options.ListCameras) { #region List webcams. var webcams = await WindowsVideoEndPoint.GetVideoCatpureDevices(); if (webcams == null || webcams.Count == 0) { Console.WriteLine("No webcams were found."); } else { var index = 0; foreach (var webcam in webcams) { Console.WriteLine($"{index}: \"{webcam.Name}\", use --cam={index}."); index++; } } #endregion } else if (_options.ListFormats != null) { #region List webcam formats. var webcams = await WindowsVideoEndPoint.GetVideoCatpureDevices(); if (webcams == null || webcams.Count == 0) { Console.WriteLine("No webcams were found."); } else if (_options.ListFormats >= webcams.Count) { Console.WriteLine($"No webcam available for index {_options.ListFormats}."); } else { string webcamName = webcams[_options.ListFormats.Value].Name; var formats = await WindowsVideoEndPoint.GetDeviceFrameFormats(webcamName); Console.WriteLine($"Video frame formats for {webcamName}."); foreach (var vidFmt in formats) { float vidFps = vidFmt.MediaFrameFormat.FrameRate.Numerator / vidFmt.MediaFrameFormat.FrameRate.Denominator; string pixFmt = vidFmt.MediaFrameFormat.Subtype == WindowsVideoEndPoint.MF_I420_PIXEL_FORMAT ? "I420" : vidFmt.MediaFrameFormat.Subtype; Console.WriteLine($"{vidFmt.Width}x{vidFmt.Height} {vidFps:0.##}fps {pixFmt}"); } } #endregion } else { string webcamName = null; if (_options.WebcamIndex != null) { var webcams = await WindowsVideoEndPoint.GetVideoCatpureDevices(); if (webcams == null || webcams.Count == 0) { Console.WriteLine("No webcams were found."); Application.Exit(); } else if (webcams.Count < _options.WebcamIndex) { Console.WriteLine($"No webcam available for index {_options.WebcamIndex}."); Application.Exit(); } else { webcamName = webcams[_options.WebcamIndex.Value].Name; Console.WriteLine($"Using webcam {webcamName}."); } } _sipTransport = new SIPTransport(); if (string.IsNullOrEmpty(_options.CallDestination)) { // We haven't been asked to place a call so we're listening. IPAddress listenAddress = (System.Net.Sockets.Socket.OSSupportsIPv6) ? IPAddress.IPv6Any : IPAddress.Any; var listenEndPoint = new IPEndPoint(listenAddress, SIP_PORT_DEFAULT); try { SIPUDPChannel udpChannel = new SIPUDPChannel(listenEndPoint, true); _sipTransport.AddSIPChannel(udpChannel); } catch (ApplicationException appExcp) { Console.WriteLine($"Failed to create UDP SIP channel on {listenEndPoint}, error {appExcp.Message}."); SIPUDPChannel udpChannel = new SIPUDPChannel(new IPEndPoint(listenAddress, 0), true); _sipTransport.AddSIPChannel(udpChannel); } var listeningEP = _sipTransport.GetSIPChannels().First().ListeningSIPEndPoint; Console.WriteLine($"Listening for incoming call on {listeningEP}."); } EnableTraceLogs(_sipTransport); // Open a window to display the video feed from the remote SIP party. _form = new Form(); _form.Text = string.IsNullOrEmpty(_options.CallDestination) ? "Listener" : "Caller"; _form.AutoSize = true; _form.BackgroundImageLayout = ImageLayout.Center; _localVideoPicBox = new PictureBox { Size = new Size(VIDEO_FRAME_WIDTH, VIDEO_FRAME_HEIGHT), Location = new Point(0, 0), Visible = true }; _remoteVideoPicBox = new PictureBox { Size = new Size(VIDEO_FRAME_WIDTH, VIDEO_FRAME_HEIGHT), Location = new Point(0, VIDEO_FRAME_HEIGHT), Visible = true }; _form.Controls.Add(_localVideoPicBox); _form.Controls.Add(_remoteVideoPicBox); var userAgent = new SIPUserAgent(_sipTransport, null, true); userAgent.OnCallHungup += (dialog) => exitMRE.Set(); WindowsAudioEndPoint windowsAudioEndPoint = null; if (!_options.NoAudio) { windowsAudioEndPoint = new WindowsAudioEndPoint(new AudioEncoder()); windowsAudioEndPoint.RestrictFormats(x => x.Codec == AudioCodecsEnum.G722); } MediaEndPoints mediaEndPoints = null; if (_options.TestPattern && _options.WebcamIndex == null) { var testPattern = new VideoTestPatternSource(new FFmpegVideoEncoder()); var decoderSink = new DecoderVideoSink(new FFmpegVideoEncoder()); //var decoderSink = new DecoderVideoSink(new VpxVideoEncoder()); testPattern.RestrictFormats(format => format.Codec == VIDEO_CODEC); decoderSink.RestrictFormats(format => format.Codec == VIDEO_CODEC); mediaEndPoints = new MediaEndPoints { AudioSink = windowsAudioEndPoint, AudioSource = windowsAudioEndPoint, VideoSink = decoderSink, VideoSource = testPattern, }; } else { WindowsVideoEndPoint windowsVideoEndPoint = webcamName switch { null => new WindowsVideoEndPoint(new FFmpegVideoEncoder()), _ => new WindowsVideoEndPoint(new FFmpegVideoEncoder(), webcamName), }; windowsVideoEndPoint.RestrictFormats(format => format.Codec == VIDEO_CODEC); mediaEndPoints = new MediaEndPoints { AudioSink = windowsAudioEndPoint, AudioSource = windowsAudioEndPoint, VideoSink = windowsVideoEndPoint, VideoSource = windowsVideoEndPoint, }; } mediaEndPoints.VideoSource.OnVideoSourceRawSample += (uint durationMilliseconds, int width, int height, byte[] sample, VideoPixelFormatsEnum pixelFormat) => { if (_isFormActivated) { _form?.BeginInvoke(new Action(() => { if (_form.Handle != IntPtr.Zero) { int stride = width * 3; if (pixelFormat == VideoPixelFormatsEnum.I420) { sample = PixelConverter.I420toBGR(sample, width, height, out stride); } if (_localVideoPicBox.Width != width || _localVideoPicBox.Height != height) { Log.LogDebug($"Adjusting local video display from {_localVideoPicBox.Width}x{_localVideoPicBox.Height} to {width}x{height}."); _localVideoPicBox.Width = width; _localVideoPicBox.Height = height; } unsafe { fixed(byte *s = sample) { System.Drawing.Bitmap bmpImage = new System.Drawing.Bitmap(width, height, stride, System.Drawing.Imaging.PixelFormat.Format24bppRgb, (IntPtr)s); _localVideoPicBox.Image = bmpImage; } } } })); } }; Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e) { e.Cancel = true; Log.LogInformation("Exiting..."); waitForCallMre.Set(); exitMRE.Set(); }; if (string.IsNullOrEmpty(_options.CallDestination)) { ActivateForm(); userAgent.OnIncomingCall += async(ua, req) => { var voipMediaSession = new VoIPMediaSession(mediaEndPoints); voipMediaSession.AcceptRtpFromAny = true; if (voipMediaSession.VideoLocalTrack != null) { voipMediaSession.VideoLocalTrack.MaximumBandwidth = MAXIMUM_VIDEO_BANDWIDTH; } var uas = userAgent.AcceptCall(req); await userAgent.Answer(uas, voipMediaSession); Console.WriteLine("Starting local video source..."); await mediaEndPoints.VideoSource.StartVideo().ConfigureAwait(false); waitForCallMre.Set(); }; Console.WriteLine("Waiting for incoming call..."); waitForCallMre.WaitOne(); } else { var voipMediaSession = new VoIPMediaSession(mediaEndPoints); voipMediaSession.AcceptRtpFromAny = true; if (voipMediaSession.VideoLocalTrack != null) { voipMediaSession.VideoLocalTrack.MaximumBandwidth = MAXIMUM_VIDEO_BANDWIDTH; } ActivateForm(); Console.WriteLine("Starting local video source..."); await mediaEndPoints.VideoSource.StartVideo().ConfigureAwait(false); // Place the call and wait for the result. Task <bool> callTask = userAgent.Call(_options.CallDestination, null, null, voipMediaSession); callTask.Wait(CALL_TIMEOUT_SECONDS * 1000); } if (userAgent.IsCallActive) { Log.LogInformation("Call attempt successful."); mediaEndPoints.VideoSink.OnVideoSinkDecodedSample += (byte[] bmp, uint width, uint height, int stride, VideoPixelFormatsEnum pixelFormat) => { if (_isFormActivated) { _form?.BeginInvoke(new Action(() => { if (_form.Handle != IntPtr.Zero) { unsafe { if (_remoteVideoPicBox.Width != (int)width || _remoteVideoPicBox.Height != (int)height) { Log.LogDebug($"Adjusting remote video display from {_remoteVideoPicBox.Width}x{_remoteVideoPicBox.Height} to {width}x{height}."); _remoteVideoPicBox.Width = (int)width; _remoteVideoPicBox.Height = (int)height; } fixed(byte *s = bmp) { System.Drawing.Bitmap bmpImage = new System.Drawing.Bitmap((int)width, (int)height, stride, System.Drawing.Imaging.PixelFormat.Format24bppRgb, (IntPtr)s); _remoteVideoPicBox.Image = bmpImage; } } } })); } }; } else { Log.LogWarning("Call attempt failed."); Console.WriteLine("Press ctrl-c to exit."); } exitMRE.WaitOne(); if (userAgent.IsCallActive) { Log.LogInformation("Hanging up."); userAgent.Hangup(); } Task.Delay(1000).Wait(); // Clean up. if (_form.Handle != IntPtr.Zero) { _form.BeginInvoke(new Action(() => _form.Close())); } _sipTransport.Shutdown(); } } }
private static Task <RTCPeerConnection> CreatePeerConnection() { var peerConnection = new RTCPeerConnection(null); var videoEP = new SIPSorceryMedia.Encoders.VideoEncoderEndPoint(); //var videoEP = new SIPSorceryMedia.Windows.WindowsEncoderEndPoint(); //var videoEP = new FFmpegVideoEndPoint(); videoEP.RestrictFormats(format => format.Codec == VideoCodecsEnum.VP8); videoEP.OnVideoSinkDecodedSample += (byte[] bmp, uint width, uint height, int stride, VideoPixelFormatsEnum pixelFormat) => { _form.BeginInvoke(new Action(() => { unsafe { fixed(byte *s = bmp) { Bitmap bmpImage = new Bitmap((int)width, (int)height, (int)(bmp.Length / height), PixelFormat.Format24bppRgb, (IntPtr)s); _picBox.Image = bmpImage; } } })); }; // Sink (speaker) only audio end point. WindowsAudioEndPoint windowsAudioEP = new WindowsAudioEndPoint(new AudioEncoder(), -1, -1, true, false); MediaStreamTrack audioTrack = new MediaStreamTrack(windowsAudioEP.GetAudioSinkFormats(), MediaStreamStatusEnum.RecvOnly); peerConnection.addTrack(audioTrack); MediaStreamTrack videoTrack = new MediaStreamTrack(videoEP.GetVideoSinkFormats(), MediaStreamStatusEnum.RecvOnly); peerConnection.addTrack(videoTrack); peerConnection.OnVideoFrameReceived += videoEP.GotVideoFrame; peerConnection.OnVideoFormatsNegotiated += (formats) => videoEP.SetVideoSinkFormat(formats.First()); peerConnection.OnAudioFormatsNegotiated += (formats) => windowsAudioEP.SetAudioSinkFormat(formats.First()); peerConnection.OnTimeout += (mediaType) => logger.LogDebug($"Timeout on media {mediaType}."); peerConnection.oniceconnectionstatechange += (state) => logger.LogDebug($"ICE connection state changed to {state}."); peerConnection.onconnectionstatechange += async(state) => { logger.LogDebug($"Peer connection connected changed to {state}."); if (state == RTCPeerConnectionState.connected) { await windowsAudioEP.StartAudio(); } else if (state == RTCPeerConnectionState.closed || state == RTCPeerConnectionState.failed) { await windowsAudioEP.CloseAudio(); } }; //peerConnection.GetRtpChannel().OnStunMessageReceived += (msg, ep, isRelay) => //{ // bool hasUseCandidate = msg.Attributes.Any(x => x.AttributeType == STUNAttributeTypesEnum.UseCandidate); // Console.WriteLine($"STUN {msg.Header.MessageType} received from {ep}, use candidate {hasUseCandidate}."); //}; peerConnection.OnRtpPacketReceived += (IPEndPoint rep, SDPMediaTypesEnum media, RTPPacket rtpPkt) => { //logger.LogDebug($"RTP {media} pkt received, SSRC {rtpPkt.Header.SyncSource}."); if (media == SDPMediaTypesEnum.audio) { windowsAudioEP.GotAudioRtp(rep, rtpPkt.Header.SyncSource, rtpPkt.Header.SequenceNumber, rtpPkt.Header.Timestamp, rtpPkt.Header.PayloadType, rtpPkt.Header.MarkerBit == 1, rtpPkt.Payload); } }; return(Task.FromResult(peerConnection)); }
static async Task Main() { Console.WriteLine("SIPSorcery Getting Started Video Call Demo"); Console.WriteLine("Press ctrl-c to exit."); Log = AddConsoleLogger(); ManualResetEvent exitMRE = new ManualResetEvent(false); _sipTransport = new SIPTransport(); EnableTraceLogs(_sipTransport); // Open a window to display the video feed from the remote SIP party. _form = new Form(); _form.AutoSize = true; _form.BackgroundImageLayout = ImageLayout.Center; _localVideoPicBox = new PictureBox { Size = new Size(VIDEO_FRAME_WIDTH, VIDEO_FRAME_HEIGHT), Location = new Point(0, 0), Visible = true }; _remoteVideoPicBox = new PictureBox { Size = new Size(VIDEO_FRAME_WIDTH, VIDEO_FRAME_HEIGHT), Location = new Point(0, VIDEO_FRAME_HEIGHT), Visible = true }; _form.Controls.Add(_localVideoPicBox); _form.Controls.Add(_remoteVideoPicBox); Application.EnableVisualStyles(); ThreadPool.QueueUserWorkItem(delegate { Application.Run(_form); }); ManualResetEvent formMre = new ManualResetEvent(false); _form.Activated += (object sender, EventArgs e) => formMre.Set(); Console.WriteLine("Waiting for form activation."); formMre.WaitOne(); _sipTransport.SIPTransportRequestReceived += OnSIPTransportRequestReceived; string executableDir = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); var userAgent = new SIPUserAgent(_sipTransport, null, true); userAgent.OnCallHungup += (dialog) => exitMRE.Set(); var windowsAudioEndPoint = new WindowsAudioEndPoint(new AudioEncoder()); windowsAudioEndPoint.RestrictFormats(format => format.Codec == AudioCodecsEnum.PCMU); var windowsVideoEndPoint = new WindowsVideoEndPoint(new VpxVideoEncoder()); // Fallback to a test pattern source if accessing the Windows webcam fails. var testPattern = new VideoTestPatternSource(new VpxVideoEncoder()); MediaEndPoints mediaEndPoints = new MediaEndPoints { AudioSink = windowsAudioEndPoint, AudioSource = windowsAudioEndPoint, VideoSink = windowsVideoEndPoint, VideoSource = windowsVideoEndPoint, }; var voipMediaSession = new VoIPMediaSession(mediaEndPoints, testPattern); voipMediaSession.AcceptRtpFromAny = true; windowsVideoEndPoint.OnVideoSourceRawSample += (uint durationMilliseconds, int width, int height, byte[] sample, VideoPixelFormatsEnum pixelFormat) => { _form?.BeginInvoke(new Action(() => { unsafe { fixed(byte *s = sample) { System.Drawing.Bitmap bmpImage = new System.Drawing.Bitmap(width, height, width * 3, System.Drawing.Imaging.PixelFormat.Format24bppRgb, (IntPtr)s); _localVideoPicBox.Image = bmpImage; } } })); }; Console.WriteLine("Starting local video source..."); await windowsVideoEndPoint.StartVideo().ConfigureAwait(false); // Place the call and wait for the result. Task <bool> callTask = userAgent.Call(DESTINATION, null, null, voipMediaSession); callTask.Wait(CALL_TIMEOUT_SECONDS * 1000); if (callTask.Result) { Log.LogInformation("Call attempt successful."); windowsVideoEndPoint.OnVideoSinkDecodedSample += (byte[] bmp, uint width, uint height, int stride, VideoPixelFormatsEnum pixelFormat) => { _form?.BeginInvoke(new Action(() => { unsafe { fixed(byte *s = bmp) { System.Drawing.Bitmap bmpImage = new System.Drawing.Bitmap((int)width, (int)height, stride, System.Drawing.Imaging.PixelFormat.Format24bppRgb, (IntPtr)s); _remoteVideoPicBox.Image = bmpImage; } } })); }; windowsAudioEndPoint.PauseAudio().Wait(); voipMediaSession.AudioExtrasSource.SetSource(AudioSourcesEnum.Music); } else { Log.LogWarning("Call attempt failed."); Console.WriteLine("Press ctrl-c to exit."); } Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e) { e.Cancel = true; Log.LogInformation("Exiting..."); exitMRE.Set(); }; exitMRE.WaitOne(); if (userAgent.IsCallActive) { Log.LogInformation("Hanging up."); userAgent.Hangup(); Task.Delay(1000).Wait(); } // Clean up. _form.BeginInvoke(new Action(() => _form.Close())); _sipTransport.Shutdown(); }
static async Task Main() { Console.WriteLine("SIPSorcery Getting Started Demo"); AddConsoleLogger(); CancellationTokenSource exitCts = new CancellationTokenSource(); var sipTransport = new SIPTransport(); EnableTraceLogs(sipTransport); var userAgent = new SIPUserAgent(sipTransport, OUTBOUND_PROXY); userAgent.ClientCallFailed += (uac, error, sipResponse) => Console.WriteLine($"Call failed {error}."); userAgent.OnCallHungup += (dialog) => exitCts.Cancel(); var windowsAudio = new WindowsAudioEndPoint(new AudioEncoder()); var voipMediaSession = new VoIPMediaSession(windowsAudio.ToMediaEndPoints()); voipMediaSession.AcceptRtpFromAny = true; voipMediaSession.OnRtpPacketReceived += OnRtpPacketReceived; string fromHeader = (new SIPFromHeader(USERNAME, new SIPURI(USERNAME, DOMAIN, null), null)).ToString(); SIPCallDescriptor callDescriptor = new SIPCallDescriptor(USERNAME, PASSWORD, DESTINATION, fromHeader, null, null, null, null, SIPCallDirection.Out, SDP.SDP_MIME_CONTENTTYPE, null, null); //callDescriptor.CallId = "16152412565"; //callDescriptor.AuthUsername = USERNAME; // Place the call and wait for the result. var callTask = userAgent.Call(callDescriptor, voipMediaSession); Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e) { e.Cancel = true; if (userAgent != null) { if (userAgent.IsCalling || userAgent.IsRinging) { Console.WriteLine("Cancelling in progress call."); userAgent.Cancel(); } else if (userAgent.IsCallActive) { Console.WriteLine("Hanging up established call."); userAgent.Hangup(); _waveFile.Dispose(); } } ; exitCts.Cancel(); }; Console.WriteLine("press ctrl-c to exit..."); bool callResult = await callTask; if (callResult) { Console.WriteLine("Enter digits one after another"); string meetingNo = "1711622132"; Console.WriteLine("Enter meetingno ?"); Console.ReadLine(); foreach (var item in meetingNo) { await userAgent.SendDtmf(byte.Parse(item.ToString())); Console.WriteLine("Sending DTMF - " + byte.Parse(item.ToString())); Thread.Sleep(2000); } Thread.Sleep(2000); await userAgent.SendDtmf(Encoding.ASCII.GetBytes("#")[0]); Thread.Sleep(13000); Console.WriteLine("Sending AttendeeID ?"); /*string attendeeId = "635619"; * foreach (var item in attendeeId) * { * await userAgent.SendDtmf(byte.Parse(item.ToString())); * Console.WriteLine("Sending DTMF - " + byte.Parse(item.ToString())); * Thread.Sleep(2000); * }*/ await userAgent.SendDtmf(Encoding.ASCII.GetBytes("#")[0]); Console.ReadLine(); await userAgent.SendDtmf(Encoding.ASCII.GetBytes("#")[0]); Console.WriteLine($"Call to {DESTINATION} succeeded."); exitCts.Token.WaitHandle.WaitOne(); } else { Console.WriteLine($"Call to {DESTINATION} failed."); } Console.WriteLine("Exiting..."); if (userAgent?.IsHangingUp == true) { Console.WriteLine("Waiting 1s for the call hangup or cancel to complete..."); await Task.Delay(1000); } // Clean up. sipTransport.Shutdown(); }