private static RTCPeerConnection Createpc(WebSocketContext context, SDPAudioVideoMediaFormat videoFormat) { var pc = new RTCPeerConnection(null); MediaStreamTrack videoTrack = new MediaStreamTrack(SDPMediaTypesEnum.video, false, new List <SDPAudioVideoMediaFormat> { videoFormat }, MediaStreamStatusEnum.SendOnly); pc.addTrack(videoTrack); pc.onicecandidateerror += (candidate, error) => logger.LogWarning($"Error adding remote ICE candidate. {error} {candidate}"); pc.oniceconnectionstatechange += (state) => logger.LogDebug($"ICE connection state change to {state}."); //pc.OnReceiveReport += (type, rtcp) => logger.LogDebug($"RTCP {type} report received."); pc.OnRtcpBye += (reason) => logger.LogDebug($"RTCP BYE receive, reason: {(string.IsNullOrWhiteSpace(reason) ? "<none>" : reason)}."); pc.OnRtpClosed += (reason) => logger.LogDebug($"Peer connection closed, reason: {(string.IsNullOrWhiteSpace(reason) ? "<none>" : reason)}."); pc.onicecandidate += (candidate) => { if (pc.signalingState == RTCSignalingState.have_local_offer || pc.signalingState == RTCSignalingState.have_remote_offer) { context.WebSocket.Send($"candidate:{candidate}"); } }; pc.onconnectionstatechange += (state) => { logger.LogDebug($"Peer connection state changed to {state}."); if (state == RTCPeerConnectionState.connected) { logger.LogDebug("Creating RTP session to receive ffmpeg stream."); _ffmpegListener.OnRtpPacketReceived += (ep, media, rtpPkt) => { if (media == SDPMediaTypesEnum.video && pc.VideoDestinationEndPoint != null) { //logger.LogDebug($"Forwarding {media} RTP packet to webrtc peer timestamp {rtpPkt.Header.Timestamp}."); pc.SendRtpRaw(media, rtpPkt.Payload, rtpPkt.Header.Timestamp, rtpPkt.Header.MarkerBit, rtpPkt.Header.PayloadType); } }; } }; return(pc); }
public async Task <RTCSessionDescriptionInit> GotOffer(RTCSessionDescriptionInit offer) { _logger.LogDebug($"SDP offer received."); _logger.LogTrace($"Offer SDP:\n{offer.sdp}"); var pc = new RTCPeerConnection(); if (_publicIPv4 != null) { var rtpPort = pc.GetRtpChannel().RTPPort; var publicIPv4Candidate = new RTCIceCandidate(RTCIceProtocol.udp, _publicIPv4, (ushort)rtpPort, RTCIceCandidateType.host); pc.addLocalIceCandidate(publicIPv4Candidate); } if (_publicIPv6 != null) { var rtpPort = pc.GetRtpChannel().RTPPort; var publicIPv6Candidate = new RTCIceCandidate(RTCIceProtocol.udp, _publicIPv6, (ushort)rtpPort, RTCIceCandidateType.host); pc.addLocalIceCandidate(publicIPv6Candidate); } MediaStreamTrack audioTrack = new MediaStreamTrack(SDPMediaTypesEnum.audio, false, new List <SDPAudioVideoMediaFormat> { new SDPAudioVideoMediaFormat(SDPWellKnownMediaFormatsEnum.PCMU) }, MediaStreamStatusEnum.SendRecv); pc.addTrack(audioTrack); MediaStreamTrack videoTrack = new MediaStreamTrack(new VideoFormat(VideoCodecsEnum.VP8, VP8_PAYLOAD_ID), MediaStreamStatusEnum.SendRecv); pc.addTrack(videoTrack); pc.OnRtpPacketReceived += (IPEndPoint rep, SDPMediaTypesEnum media, RTPPacket rtpPkt) => { pc.SendRtpRaw(media, rtpPkt.Payload, rtpPkt.Header.Timestamp, rtpPkt.Header.MarkerBit, rtpPkt.Header.PayloadType); //_logger.LogDebug($"RTP {media} pkt received, SSRC {rtpPkt.Header.SyncSource}, SeqNum {rtpPkt.Header.SequenceNumber}."); }; //peerConnection.OnReceiveReport += RtpSession_OnReceiveReport; //peerConnection.OnSendReport += RtpSession_OnSendReport; pc.OnTimeout += (mediaType) => _logger.LogWarning($"Timeout for {mediaType}."); pc.onconnectionstatechange += (state) => { _logger.LogDebug($"Peer connection state changed to {state}."); if (state == RTCPeerConnectionState.failed) { pc.Close("ice failure"); } }; var setResult = pc.setRemoteDescription(offer); if (setResult == SetDescriptionResultEnum.OK) { var offerSdp = pc.createOffer(null); await pc.setLocalDescription(offerSdp); var answer = pc.createAnswer(null); await pc.setLocalDescription(answer); _logger.LogTrace($"Answer SDP:\n{answer.sdp}"); return(answer); } else { return(null); } }
public async Task <RTCSessionDescriptionInit> GotOffer(RTCSessionDescriptionInit offer) { logger.LogTrace($"SDP offer received."); logger.LogTrace(offer.sdp); var pc = new RTCPeerConnection(); if (_presetIceAddresses != null) { foreach (var addr in _presetIceAddresses) { var rtpPort = pc.GetRtpChannel().RTPPort; var publicIPv4Candidate = new RTCIceCandidate(RTCIceProtocol.udp, addr, (ushort)rtpPort, RTCIceCandidateType.host); pc.addLocalIceCandidate(publicIPv4Candidate); } } MediaStreamTrack audioTrack = new MediaStreamTrack(SDPWellKnownMediaFormatsEnum.PCMU); pc.addTrack(audioTrack); MediaStreamTrack videoTrack = new MediaStreamTrack(new VideoFormat(VideoCodecsEnum.VP8, VP8_PAYLOAD_ID)); pc.addTrack(videoTrack); pc.OnRtpPacketReceived += (IPEndPoint rep, SDPMediaTypesEnum media, RTPPacket rtpPkt) => { pc.SendRtpRaw(media, rtpPkt.Payload, rtpPkt.Header.Timestamp, rtpPkt.Header.MarkerBit, rtpPkt.Header.PayloadType); }; pc.OnTimeout += (mediaType) => logger.LogWarning($"Timeout for {mediaType}."); pc.oniceconnectionstatechange += (state) => logger.LogInformation($"ICE connection state changed to {state}."); pc.onsignalingstatechange += () => logger.LogInformation($"Signaling state changed to {pc.signalingState}."); pc.onconnectionstatechange += (state) => { logger.LogInformation($"Peer connection state changed to {state}."); if (state == RTCPeerConnectionState.failed) { pc.Close("ice failure"); } }; var setResult = pc.setRemoteDescription(offer); if (setResult == SetDescriptionResultEnum.OK) { var offerSdp = pc.createOffer(null); await pc.setLocalDescription(offerSdp); var answer = pc.createAnswer(null); logger.LogTrace($"SDP answer created."); logger.LogTrace(answer.sdp); return(answer); } else { logger.LogWarning($"Failed to set remote description {setResult}."); return(null); } }