private static SDP GetSDP(IPEndPoint rtpSocket, RTPPayloadTypesEnum audioPayloadType) { int samplingFrequency = RTPPayloadTypes.GetSamplingFrequency(audioPayloadType); var sdp = new SDP() { SessionId = Crypto.GetRandomInt(5).ToString(), Address = rtpSocket.Address.ToString(), SessionName = "sipsorcery", Timing = "0 0", Connection = new SDPConnectionInformation(rtpSocket.Address.ToString()), }; var audioAnnouncement = new SDPMediaAnnouncement() { Media = SDPMediaTypesEnum.audio, MediaFormats = new List <SDPMediaFormat>() { new SDPMediaFormat((int)audioPayloadType, "PCMU", samplingFrequency) } }; audioAnnouncement.Port = rtpSocket.Port; audioAnnouncement.ExtraAttributes.Add("a=sendrecv"); audioAnnouncement.ExtraAttributes.Add($"a=rtpmap:{DTMF_EVENT_PAYLOAD_ID} telephone-event/{samplingFrequency}"); audioAnnouncement.ExtraAttributes.Add($"a=fmtp:{DTMF_EVENT_PAYLOAD_ID} 0-15"); sdp.Media.Add(audioAnnouncement); return(sdp); }
/// <summary> /// Sends the sounds of silence. If the destination is on the other side of a NAT this is useful to open /// a pinhole and hopefully get the remote RTP stream through. /// </summary> /// <param name="rtpSocket">The socket we're using to send from.</param> /// <param name="rtpSendSession">Our RTP sending session.</param> /// <param name="cts">Cancellation token to stop the call.</param> private static async void SendRtp(Socket rtpSocket, RTPSession rtpSendSession, CancellationTokenSource cts) { int samplingFrequency = RTPPayloadTypes.GetSamplingFrequency((RTPPayloadTypesEnum)rtpSendSession.PayloadType); uint rtpTimestampStep = (uint)(samplingFrequency * SILENCE_SAMPLE_PERIOD / 1000); uint bufferSize = (uint)SILENCE_SAMPLE_PERIOD; uint rtpSendTimestamp = 0; uint packetSentCount = 0; uint bytesSentCount = 0; while (cts.IsCancellationRequested == false) { if (_remoteRtpEndPoint != null) { if (!_dtmfEvents.IsEmpty) { // Check if there are any DTMF events to send. _dtmfEvents.TryDequeue(out var rtpEvent); if (rtpEvent != null) { await rtpSendSession.SendDtmfEvent(rtpSocket, _remoteRtpEndPoint, rtpEvent, rtpSendTimestamp, (ushort)SILENCE_SAMPLE_PERIOD, (ushort)rtpTimestampStep, cts); } rtpSendTimestamp += rtpEvent.TotalDuration + rtpTimestampStep; } else { // If there are no DTMF events to send we'll send silence. byte[] sample = new byte[bufferSize / 2]; int sampleIndex = 0; for (int index = 0; index < bufferSize; index += 2) { sample[sampleIndex] = PCMU_SILENCE_BYTE_ZERO; sample[sampleIndex + 1] = PCMU_SILENCE_BYTE_ONE; } rtpSendSession.SendAudioFrame(rtpSocket, _remoteRtpEndPoint, rtpSendTimestamp, sample); rtpSendTimestamp += rtpTimestampStep; packetSentCount++; bytesSentCount += (uint)sample.Length; } } await Task.Delay(SILENCE_SAMPLE_PERIOD); } }