public Task StartVideo() { if (!_isStarted) { _isStarted = true; _externalSource?.StartVideo(); } return(Task.CompletedTask); }
static private Task <RTCPeerConnection> CreatePeerConnection() { RTCConfiguration config = new RTCConfiguration { iceServers = new List <RTCIceServer> { new RTCIceServer { urls = STUN_URL } } }; PeerConnection = new RTCPeerConnection(config); switch (VideoSourceType) { case VIDEO_SOURCE.FILE_OR_STREAM: // Do we use same file for Audio ? if ((AudioSourceType == AUDIO_SOURCE.FILE_OR_STREAM) && (AudioSourceFile == VideoSourceFile)) { SIPSorceryMedia.FFmpeg.FFmpegFileSource fileSource = new SIPSorceryMedia.FFmpeg.FFmpegFileSource(VideoSourceFile, RepeatVideoFile, new AudioEncoder(), true); fileSource.OnEndOfFile += () => PeerConnection.Close("source eof"); videoSource = fileSource as IVideoSource; audioSource = fileSource as IAudioSource; } else { SIPSorceryMedia.FFmpeg.FFmpegFileSource fileSource = new SIPSorceryMedia.FFmpeg.FFmpegFileSource(VideoSourceFile, RepeatVideoFile, new AudioEncoder(), true); fileSource.OnEndOfFile += () => PeerConnection.Close("source eof"); videoSource = fileSource as IVideoSource; } break; case VIDEO_SOURCE.CAMERA: List <SIPSorceryMedia.FFmpeg.Camera>?cameras = SIPSorceryMedia.FFmpeg.FFmpegCameraManager.GetCameraDevices(); SIPSorceryMedia.FFmpeg.Camera?camera = null; if (cameras?.Count > 0) { // Get last one camera = cameras.Last(); } if (camera != null) { videoSource = new SIPSorceryMedia.FFmpeg.FFmpegCameraSource(camera.Path); } else { throw new NotSupportedException($"Cannot find adequate camera ..."); } break; case VIDEO_SOURCE.SCREEN: List <SIPSorceryMedia.FFmpeg.Monitor>?monitors = SIPSorceryMedia.FFmpeg.FFmpegMonitorManager.GetMonitorDevices(); SIPSorceryMedia.FFmpeg.Monitor? primaryMonitor = null; if (monitors?.Count > 0) { foreach (SIPSorceryMedia.FFmpeg.Monitor monitor in monitors) { if (monitor.Primary) { primaryMonitor = monitor; break; } } if (primaryMonitor == null) { primaryMonitor = monitors[0]; } } if (primaryMonitor != null) { videoSource = new SIPSorceryMedia.FFmpeg.FFmpegScreenSource(primaryMonitor.Path, primaryMonitor.Rect, 10); } else { throw new NotSupportedException($"Cannot find adequate monitor ..."); } break; } if (audioSource == null) { switch (AudioSourceType) { case AUDIO_SOURCE.FILE_OR_STREAM: SIPSorceryMedia.FFmpeg.FFmpegFileSource fileSource = new SIPSorceryMedia.FFmpeg.FFmpegFileSource(AudioSourceFile, RepeatAudioFile, new AudioEncoder(), false); fileSource.OnEndOfFile += () => PeerConnection.Close("source eof"); audioSource = fileSource as IAudioSource; break; case AUDIO_SOURCE.MICROPHONE: audioSource = new SIPSorceryMedia.FFmpeg.FFmpegMicrophoneSource(MicrophoneDevicePath, new AudioEncoder()); break; } } if (videoSource != null) { videoSource.RestrictFormats(x => x.Codec == VideoCodec); MediaStreamTrack videoTrack = new MediaStreamTrack(videoSource.GetVideoSourceFormats(), MediaStreamStatusEnum.SendRecv); PeerConnection.addTrack(videoTrack); videoSource.OnVideoSourceEncodedSample += PeerConnection.SendVideo; PeerConnection.OnVideoFormatsNegotiated += (videoFormats) => videoSource.SetVideoSourceFormat(videoFormats.First()); } if (audioSource != null) { audioSource.RestrictFormats(x => x.Codec == AudioCodec); MediaStreamTrack audioTrack = new MediaStreamTrack(audioSource.GetAudioSourceFormats(), MediaStreamStatusEnum.SendRecv); PeerConnection.addTrack(audioTrack); audioSource.OnAudioSourceEncodedSample += AudioSource_OnAudioSourceEncodedSample; PeerConnection.OnAudioFormatsNegotiated += (audioFormats) => audioSource.SetAudioSourceFormat(audioFormats.First()); } PeerConnection.onconnectionstatechange += async(state) => { logger.LogDebug($"Peer connection state change to {state}."); if (state == RTCPeerConnectionState.failed) { PeerConnection.Close("ice disconnection"); } else if (state == RTCPeerConnectionState.closed) { if (videoSource != null) { await videoSource.CloseVideo(); } if (audioSink != null) { await audioSink.CloseAudioSink(); } if (audioSource != null) { await audioSource.CloseAudio(); } } else if (state == RTCPeerConnectionState.connected) { if (videoSource != null) { await videoSource.StartVideo(); } if (audioSink != null) { await audioSink.StartAudioSink(); } if (audioSource != null) { await audioSource.StartAudio(); } } }; // 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}."); PeerConnection.oniceconnectionstatechange += (state) => logger.LogDebug($"ICE connection state change to {state}."); return(Task.FromResult(PeerConnection)); }