private static async Task StartFfmpegListener(string sdpPath, CancellationToken cancel) { while (!File.Exists(FFMPEG_SDP_FILE) && !cancel.IsCancellationRequested) { await Task.Delay(500); } if (!cancel.IsCancellationRequested) { var sdp = SDP.ParseSDPDescription(File.ReadAllText(FFMPEG_SDP_FILE)); // The SDP is only expected to contain a single video media announcement. var videoAnn = sdp.Media.Single(x => x.Media == SDPMediaTypesEnum.video); _ffmpegVideoFormat = videoAnn.MediaFormats.Values.First(); _ffmpegListener = new RTPSession(false, false, false, IPAddress.Loopback, FFMPEG_DEFAULT_RTP_PORT); _ffmpegListener.AcceptRtpFromAny = true; MediaStreamTrack videoTrack = new MediaStreamTrack(SDPMediaTypesEnum.video, false, new List <SDPAudioVideoMediaFormat> { _ffmpegVideoFormat }, MediaStreamStatusEnum.RecvOnly); _ffmpegListener.addTrack(videoTrack); _ffmpegListener.SetRemoteDescription(SIP.App.SdpType.answer, sdp); // Set a dummy destination end point or the RTP session will end up sending RTCP reports // to itself. var dummyIPEndPoint = new IPEndPoint(IPAddress.Loopback, 0); _ffmpegListener.SetDestination(SDPMediaTypesEnum.video, dummyIPEndPoint, dummyIPEndPoint); await _ffmpegListener.Start(); } }
private static RTPSession CreateRtpSession(List <SDPAudioVideoMediaFormat> audioFormats, List <SDPAudioVideoMediaFormat> videoFormats) { var rtpSession = new RTPSession(false, false, false, IPAddress.Loopback); bool hasAudio = false; bool hasVideo = false; if (audioFormats != null && audioFormats.Count > 0) { MediaStreamTrack audioTrack = new MediaStreamTrack(SDPMediaTypesEnum.audio, false, audioFormats, MediaStreamStatusEnum.SendRecv); rtpSession.addTrack(audioTrack); hasAudio = true; } if (videoFormats != null && videoFormats.Count > 0) { MediaStreamTrack videoTrack = new MediaStreamTrack(SDPMediaTypesEnum.video, false, videoFormats, MediaStreamStatusEnum.SendRecv); rtpSession.addTrack(videoTrack); hasVideo = true; } var sdpOffer = rtpSession.CreateOffer(null); // Because the SDP being written to the file is the input to ffplay the connection ports need to be changed // to the ones ffplay will be listening on. if (hasAudio) { sdpOffer.Media.Single(x => x.Media == SDPMediaTypesEnum.audio).Port = FFPLAY_DEFAULT_AUDIO_PORT; } if (hasVideo) { sdpOffer.Media.Single(x => x.Media == SDPMediaTypesEnum.video).Port = FFPLAY_DEFAULT_VIDEO_PORT; } Console.WriteLine(sdpOffer); using (StreamWriter sw = new StreamWriter(FFPLAY_DEFAULT_SDP_PATH)) { sw.Write(sdpOffer); } string ffplayCommand = String.Format(FFPLAY_DEFAULT_COMMAND, FFPLAY_DEFAULT_SDP_PATH); Console.WriteLine($"Start ffplay using the command below:"); Console.WriteLine(ffplayCommand); Console.WriteLine($"To request the remote peer to send a video key frame press 'k'"); rtpSession.Start(); rtpSession.SetDestination(SDPMediaTypesEnum.audio, new IPEndPoint(IPAddress.Loopback, FFPLAY_DEFAULT_AUDIO_PORT), new IPEndPoint(IPAddress.Loopback, FFPLAY_DEFAULT_AUDIO_PORT + 1)); rtpSession.SetDestination(SDPMediaTypesEnum.video, new IPEndPoint(IPAddress.Loopback, FFPLAY_DEFAULT_VIDEO_PORT), new IPEndPoint(IPAddress.Loopback, FFPLAY_DEFAULT_VIDEO_PORT + 1)); return(rtpSession); }