Esempio n. 1
0
        /// <summary>
        /// Sends an RTP event for a DTMF tone as per RFC2833. Sending the event requires multiple packets to be sent.
        /// This method will hold onto the socket until all the packets required for the event have been sent. The send
        /// can be cancelled using the cancellation token.
        /// </summary>
        /// <param name="srcRtpSocket">The local RTP socket to send the event from.</param>
        /// <param name="dstRtpSocket">The remote RTP socket to send the event to.</param>
        /// <param name="rtpEvent">The RTP event to send.</param>
        /// <param name="startTimestamp">The RTP timestamp at the start of the event.</param>
        /// <param name="samplePeriod">The sample period in milliseconds being used for the media stream that the event
        /// is being inserted into. Should be set to 50ms if main media stream is dynamic or sample period is unknown.</param>
        /// <param name="timestampStep">The RTP timestamp step corresponding to the sampling period. This can change depending
        /// on the codec being used. For example using PCMU with a sampling frequency of 8000Hz the timestamp step
        /// for a sample period of 50ms is 400 (8000 / (1000 / 50)). For a sample period of 20ms it's 160 (8000 / (1000 / 20)).</param>
        /// <param name="cts">Token source to allow the operation to be cancelled prematurely.</param>
        public async Task SendDtmfEvent(Socket srcRtpSocket,
                                        IPEndPoint dstRtpSocket,
                                        RTPEvent rtpEvent,
                                        uint startTimestamp,
                                        ushort samplePeriod,
                                        ushort timestampStep,
                                        CancellationTokenSource cts)
        {
            try
            {
                // If only the minimum number of packets are being sent then they are both the start and end of the event.
                rtpEvent.EndOfEvent = (rtpEvent.TotalDuration <= timestampStep);
                rtpEvent.Duration   = timestampStep;

                // Send the start of event packets.
                for (int i = 0; i < RTPEvent.DUPLICATE_COUNT && !cts.IsCancellationRequested; i++)
                {
                    byte[] buffer = rtpEvent.GetEventPayload();

                    int markerBit = (i == 0) ? 1 : 0;  // Set marker bit for the first packet in the event.
                    SendRtpPacket(srcRtpSocket, dstRtpSocket, buffer, startTimestamp, markerBit, rtpEvent.PayloadTypeID);

                    SeqNum++;
                    PacketsSent++;
                }

                await Task.Delay(samplePeriod, cts.Token);

                if (!rtpEvent.EndOfEvent)
                {
                    // Send the progressive event packets
                    while ((rtpEvent.Duration + timestampStep) < rtpEvent.TotalDuration && !cts.IsCancellationRequested)
                    {
                        rtpEvent.Duration += timestampStep;
                        byte[] buffer = rtpEvent.GetEventPayload();

                        SendRtpPacket(srcRtpSocket, dstRtpSocket, buffer, startTimestamp, 0, rtpEvent.PayloadTypeID);

                        PacketsSent++;
                        SeqNum++;

                        await Task.Delay(samplePeriod, cts.Token);
                    }

                    // Send the end of event packets.
                    for (int j = 0; j < RTPEvent.DUPLICATE_COUNT && !cts.IsCancellationRequested; j++)
                    {
                        rtpEvent.EndOfEvent = true;
                        rtpEvent.Duration   = rtpEvent.TotalDuration;
                        byte[] buffer = rtpEvent.GetEventPayload();

                        SendRtpPacket(srcRtpSocket, dstRtpSocket, buffer, startTimestamp, 0, rtpEvent.PayloadTypeID);

                        SeqNum++;
                        PacketsSent++;
                    }
                }
            }
            catch (System.Net.Sockets.SocketException sockExcp)
            {
                logger.LogError("SocketException SendDtmfEvent. " + sockExcp.Message);
            }
            catch (System.Threading.Tasks.TaskCanceledException)
            {
                logger.LogWarning("SendDtmfEvent was cancelled by caller.");
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Sends an RTP event for a DTMF tone as per RFC2833. Sending the event requires multiple packets to be sent.
        /// This method will hold onto the socket until all the packets required for the event have been sent. The send
        /// can be cancelled using the cancellation token.
        /// </summary>
        /// <param name="rtpEvent">The RTP event to send.</param>
        ///  <param name="cancellationToken">CancellationToken to allow the operation to be cancelled prematurely.</param>
        public async Task SendDtmfEvent(
            RTPEvent rtpEvent,
            CancellationToken cancellationToken)
        {
            if (m_rtpEventInProgress == true || DestinationEndPoint == null)
            {
                logger.LogWarning("SendDtmfEvent request ignored as an RTP event is already in progress.");
            }

            try
            {
                m_rtpEventInProgress = true;
                uint startTimestamp = m_lastRtpTimestamp;

                // The sample period in milliseconds being used for the media stream that the event
                // is being inserted into. Should be set to 50ms if main media stream is dynamic or
                // sample period is unknown.
                int samplePeriod = RTP_EVENT_DEFAULT_SAMPLE_PERIOD_MS;

                int clockRate = MediaFormat.ClockRate;

                // If the clock rate is unknown or dynamic cross our fingers and use 8KHz.
                if (clockRate == 0)
                {
                    clockRate = DEFAULT_AUDIO_CLOCK_RATE;
                }

                // The RTP timestamp step corresponding to the sampling period. This can change depending
                // on the codec being used. For example using PCMU with a sampling frequency of 8000Hz and a sample period of 50ms
                // the timestamp step is 400 (8000 / (1000 / 50)). For a sample period of 20ms it's 160 (8000 / (1000 / 20)).
                ushort rtpTimestampStep = (ushort)(clockRate * samplePeriod / 1000);

                // If only the minimum number of packets are being sent then they are both the start and end of the event.
                rtpEvent.EndOfEvent = (rtpEvent.TotalDuration <= rtpTimestampStep);
                // The DTMF tone is generally multiple RTP events. Each event has a duration of the RTP timestamp step.
                rtpEvent.Duration = rtpTimestampStep;

                // Send the start of event packets.
                for (int i = 0; i < RTPEvent.DUPLICATE_COUNT && !cancellationToken.IsCancellationRequested; i++)
                {
                    byte[] buffer = rtpEvent.GetEventPayload();

                    int markerBit = (i == 0) ? 1 : 0;  // Set marker bit for the first packet in the event.
                    SendRtpPacket(RtpChannel, DestinationEndPoint, buffer, startTimestamp, markerBit, rtpEvent.PayloadTypeID);

                    SeqNum++;
                }

                await Task.Delay(samplePeriod, cancellationToken);

                if (!rtpEvent.EndOfEvent)
                {
                    // Send the progressive event packets
                    while ((rtpEvent.Duration + rtpTimestampStep) < rtpEvent.TotalDuration && !cancellationToken.IsCancellationRequested)
                    {
                        rtpEvent.Duration += rtpTimestampStep;
                        byte[] buffer = rtpEvent.GetEventPayload();

                        SendRtpPacket(RtpChannel, DestinationEndPoint, buffer, startTimestamp, 0, rtpEvent.PayloadTypeID);

                        SeqNum++;

                        await Task.Delay(samplePeriod, cancellationToken);
                    }

                    // Send the end of event packets.
                    for (int j = 0; j < RTPEvent.DUPLICATE_COUNT && !cancellationToken.IsCancellationRequested; j++)
                    {
                        rtpEvent.EndOfEvent = true;
                        rtpEvent.Duration   = rtpEvent.TotalDuration;
                        byte[] buffer = rtpEvent.GetEventPayload();

                        SendRtpPacket(RtpChannel, DestinationEndPoint, buffer, startTimestamp, 0, rtpEvent.PayloadTypeID);

                        SeqNum++;
                    }
                }
            }
            catch (SocketException sockExcp)
            {
                logger.LogError("SocketException SendDtmfEvent. " + sockExcp.Message);
            }
            catch (TaskCanceledException)
            {
                logger.LogWarning("SendDtmfEvent was cancelled by caller.");
            }
            finally
            {
                m_rtpEventInProgress = false;
            }
        }