diff --git a/.appveyor.yml b/.appveyor.yml index 2bcefb4f5..f6be44588 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -10,7 +10,7 @@ environment: access_token: # Token for github pages publishing. secure: 21m76jAVvcu7oACAHFnfCBltcwon+r5ZI3avfRmrNFAqJMn6RfLXwpBhPcJ617tD -image: Visual Studio 2019 +image: Visual Studio 2019 Preview configuration: Release before_build: - cmd: nuget restore -DisableParallelProcessing src\SIPSorcery.sln diff --git a/examples/WebRTCExamples/WebRTCRenegotiateAudio/Program.cs b/examples/WebRTCExamples/WebRTCRenegotiateAudio/Program.cs new file mode 100644 index 000000000..c181fbfcc --- /dev/null +++ b/examples/WebRTCExamples/WebRTCRenegotiateAudio/Program.cs @@ -0,0 +1,127 @@ +//----------------------------------------------------------------------------- +// Filename: Program.cs +// +// Description: An example WebRTC server application that serves a sine wave +// audio stream to a WebRTC enabled browser. +// +// Author(s): +// Aaron Clauson (aaron@sipsorcery.com) +// +// History: +// 28 Jul 2020 Aaron Clauson Created, Dublin, Ireland. +// +// License: +// BSD 3-Clause "New" or "Revised" License, see included LICENSE.md file. +//----------------------------------------------------------------------------- + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Serilog; +using Serilog.Extensions.Logging; +using SIPSorcery.Net; +using SIPSorcery.Media; +using SIPSorceryMedia.Windows; +using WebSocketSharp.Server; + +namespace demo +{ + class Program + { + private const int WEBSOCKET_PORT = 8081; + private const string STUN_URL = "stun:stun.sipsorcery.com"; + + private static Microsoft.Extensions.Logging.ILogger logger = NullLogger.Instance; + + static void Main() + { + Console.WriteLine("WebRTC Audio Server Example Program"); + + logger = AddConsoleLogger(); + + // Start web socket. + Console.WriteLine("Starting web socket server..."); + var webSocketServer = new WebSocketServer(IPAddress.Any, WEBSOCKET_PORT); + webSocketServer.AddWebSocketService("/", (peer) => peer.CreatePeerConnection = CreatePeerConnection); + webSocketServer.Start(); + + Console.WriteLine($"Waiting for browser web socket connection to {webSocketServer.Address}:{webSocketServer.Port}..."); + + Console.WriteLine("Press ctrl-c to exit."); + ManualResetEvent exitMre = new ManualResetEvent(false); + 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(); + } + + private static Task CreatePeerConnection() + { + RTCConfiguration config = new RTCConfiguration + { + iceServers = new List { 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); + } + + /// + /// Adds a console logger. Can be omitted if internal SIPSorcery debug and warning messages are not required. + /// + private static Microsoft.Extensions.Logging.ILogger AddConsoleLogger() + { + var serilogLogger = new LoggerConfiguration() + .Enrich.FromLogContext() + .MinimumLevel.Is(Serilog.Events.LogEventLevel.Debug) + .WriteTo.Console() + .CreateLogger(); + var factory = new SerilogLoggerFactory(serilogLogger); + SIPSorcery.LogFactory.Set(factory); + return factory.CreateLogger(); + } + } +} diff --git a/examples/WebRTCExamples/WebRTCRenegotiateAudio/WebRTCRenegotiateAudio.csproj b/examples/WebRTCExamples/WebRTCRenegotiateAudio/WebRTCRenegotiateAudio.csproj new file mode 100644 index 000000000..df247ebdf --- /dev/null +++ b/examples/WebRTCExamples/WebRTCRenegotiateAudio/WebRTCRenegotiateAudio.csproj @@ -0,0 +1,22 @@ + + + + Exe + netcoreapp3.1 + + + + true + + + + + + + + + + + + + diff --git a/examples/WebRTCExamples/WebRTCRenegotiateAudio/webrtc.html b/examples/WebRTCExamples/WebRTCRenegotiateAudio/webrtc.html new file mode 100644 index 000000000..d7b744a28 --- /dev/null +++ b/examples/WebRTCExamples/WebRTCRenegotiateAudio/webrtc.html @@ -0,0 +1,59 @@ + + + + + + + + + + +
+ + + +
+ + + + \ No newline at end of file