/// <summary> /// Creates a new RTP session. The synchronisation source and sequence number are initialised to /// pseudo random values. /// </summary> /// <param name="formatTypeID">The format type ID for the media. It's what gets set in the payload /// type ID field in the RTP header. A default media announcement will be created.</param> /// <param name="srtpProtect">Optional secure DTLS context for encrypting RTP packets.</param> /// <param name="srtcpProtect">Optional secure DTLS context for encrypting RTCP packets.</param> /// <param name="rtpEventSupport">True if RTP event sending and receiving should be supported.</param> /// <param name="addrFamily">Determines whether the RTP channel will use an IPv4 or IPv6 socket.</param> public RTPSession(int formatTypeID, ProtectRtpPacket srtpProtect, ProtectRtpPacket srtcpProtect, bool rtpEventSupport, AddressFamily addrFamily) { MediaFormat = new SDPMediaFormat(formatTypeID); MediaAnnouncement = new SDPMediaAnnouncement { Media = SDPMediaTypesEnum.audio, MediaFormats = new List <SDPMediaFormat> { MediaFormat }, MediaStreamStatus = MediaStreamStatusEnum.SendRecv }; if (rtpEventSupport) { int clockRate = MediaFormat.GetClockRate(); SDPMediaFormat rtpEventFormat = new SDPMediaFormat(DTMF_EVENT_PAYLOAD_ID); rtpEventFormat.SetFormatAttribute($"{TELEPHONE_EVENT_ATTRIBUTE}/{clockRate}"); rtpEventFormat.SetFormatParameterAttribute("0-16"); MediaAnnouncement.MediaFormats.Add(rtpEventFormat); } m_rtpEventSupport = rtpEventSupport; FormatTypeID = formatTypeID; SrtpProtect = srtpProtect; Initialise(addrFamily, srtcpProtect); }
/// <summary> /// Creates an answer to an SDP offer from a remote peer. /// </summary> /// <remarks> /// As specified in https://www.w3.org/TR/webrtc/#dom-rtcpeerconnection-createanswer and /// https://tools.ietf.org/html/rfc3264#section-6.1. /// </remarks> /// <param name="options">Optional. If supplied the options will be used to apply additional /// controls over the generated answer SDP.</param> public RTCSessionDescriptionInit createAnswer(RTCAnswerOptions options) { if (remoteDescription == null) { throw new ApplicationException("The remote SDP must be set before an SDP answer can be created."); } else { var audioCapabilities = (AudioLocalTrack != null && AudioRemoteTrack != null) ? SDPMediaFormat.GetCompatibleFormats(AudioLocalTrack.Capabilities, AudioRemoteTrack.Capabilities) : null; var videoCapabilities = (VideoLocalTrack != null && VideoRemoteTrack != null) ? SDPMediaFormat.GetCompatibleFormats(VideoLocalTrack.Capabilities, VideoRemoteTrack.Capabilities) : null; List <MediaStreamTrack> localTracks = GetLocalTracks(); var answerSdp = createBaseSdp(localTracks, audioCapabilities, videoCapabilities); if (answerSdp.Media.Any(x => x.Media == SDPMediaTypesEnum.audio)) { var audioAnnouncement = answerSdp.Media.Where(x => x.Media == SDPMediaTypesEnum.audio).Single(); audioAnnouncement.AddExtra($"{ICE_SETUP_ATTRIBUTE}{IceRole}"); } if (answerSdp.Media.Any(x => x.Media == SDPMediaTypesEnum.video)) { var videoAnnouncement = answerSdp.Media.Where(x => x.Media == SDPMediaTypesEnum.video).Single(); videoAnnouncement.AddExtra($"{ICE_SETUP_ATTRIBUTE}{IceRole}"); } RTCSessionDescriptionInit initDescription = new RTCSessionDescriptionInit { type = RTCSdpType.answer, sdp = answerSdp.ToString() }; return(initDescription); } }