GetBytes() public method

public GetBytes ( ) : byte[]
return byte[]
Example #1
0
        /// <summary>
        /// Does the actual sending of an RTP packet using the specified data nad header values.
        /// </summary>
        /// <param name="srcRtpSocket">Socket to send from.</param>
        /// <param name="dstRtpSocket">Destination to send to.</param>
        /// <param name="data">The RTP packet payload.</param>
        /// <param name="timestamp">The RTP header timestamp.</param>
        /// <param name="markerBit">The RTP header marker bit.</param>
        /// <param name="payloadType">The RTP header payload type.</param>
        private void SendRtpPacket(Socket srcRtpSocket, IPEndPoint dstRtpSocket, byte[] data, uint timestamp, int markerBit, int payloadType)
        {
            int srtpProtectionLength = (SrtpProtect != null) ? SRTP_AUTH_KEY_LENGTH : 0;

            RTPPacket rtpPacket = new RTPPacket(data.Length + srtpProtectionLength);

            rtpPacket.Header.SyncSource     = Ssrc;
            rtpPacket.Header.SequenceNumber = SeqNum;
            rtpPacket.Header.Timestamp      = timestamp;
            rtpPacket.Header.MarkerBit      = markerBit;
            rtpPacket.Header.PayloadType    = payloadType;

            Buffer.BlockCopy(data, 0, rtpPacket.Payload, 0, data.Length);

            var rtpBuffer = rtpPacket.GetBytes();

            int rtperr = SrtpProtect == null ? 0 : SrtpProtect(rtpBuffer, rtpBuffer.Length - srtpProtectionLength);

            if (rtperr != 0)
            {
                logger.LogError("SendDtmfEvent SRTP packet protection failed, result " + rtperr + ".");
            }
            else
            {
                srcRtpSocket.SendTo(rtpBuffer, dstRtpSocket);
            }
        }
Example #2
0
        public void SendAudioFrame(uint timestamp, byte[] buffer, int streamID = 0)
        {
            if (m_isClosed || m_rtpEventInProgress || DestinationEndPoint == null)
            {
                return;
            }

            try
            {
                RTPSessionStream sessionStream = m_sessionStreams.Where(x => x.ID == streamID).Single();

                for (int index = 0; index *RTP_MAX_PAYLOAD < buffer.Length; index++)
                {
                    sessionStream.SeqNum = (ushort)(sessionStream.SeqNum % UInt16.MaxValue);

                    int offset               = (index == 0) ? 0 : (index * RTP_MAX_PAYLOAD);
                    int payloadLength        = (offset + RTP_MAX_PAYLOAD < buffer.Length) ? RTP_MAX_PAYLOAD : buffer.Length - offset;
                    int srtpProtectionLength = (SrtpProtect != null) ? SRTP_AUTH_KEY_LENGTH : 0;

                    RTPPacket rtpPacket = new RTPPacket(payloadLength + srtpProtectionLength);
                    rtpPacket.Header.SyncSource     = sessionStream.Ssrc;
                    rtpPacket.Header.SequenceNumber = sessionStream.SeqNum++;
                    rtpPacket.Header.Timestamp      = timestamp;
                    // RFC3551 specifies that for audio the marker bit should always be 0 except for when returning
                    // from silence suppression. For video the marker bit DOES get set to 1 for the last packet
                    // in a frame.
                    rtpPacket.Header.MarkerBit   = 0;
                    rtpPacket.Header.PayloadType = sessionStream.PayloadTypeID;

                    Buffer.BlockCopy(buffer, offset, rtpPacket.Payload, 0, payloadLength);

                    OnRtpPacketSent?.Invoke(rtpPacket);

                    var rtpBuffer = rtpPacket.GetBytes();

                    int rtperr = SrtpProtect == null ? 0 : SrtpProtect(rtpBuffer, rtpBuffer.Length - srtpProtectionLength);
                    if (rtperr != 0)
                    {
                        logger.LogError("SendAudioFrame SRTP packet protection failed, result " + rtperr + ".");
                    }
                    else
                    {
                        RtpChannel.SendAsync(RTPChannelSocketsEnum.RTP, DestinationEndPoint, rtpBuffer);
                    }

                    m_lastRtpTimestamp = timestamp;
                }
            }
            catch (SocketException sockExcp)
            {
                logger.LogError("SocketException SendAudioFrame. " + sockExcp.Message);
            }
        }
Example #3
0
        public void SendVp8Frame(uint timestamp, byte[] buffer, int streamID = 0)
        {
            if (m_isClosed || m_rtpEventInProgress || DestinationEndPoint == null)
            {
                return;
            }

            try
            {
                RTPSessionStream sessionStream = m_sessionStreams.Where(x => x.ID == streamID).Single();

                for (int index = 0; index *RTP_MAX_PAYLOAD < buffer.Length; index++)
                {
                    sessionStream.SeqNum = (ushort)(sessionStream.SeqNum % UInt16.MaxValue);

                    int offset               = (index == 0) ? 0 : (index * RTP_MAX_PAYLOAD);
                    int payloadLength        = (offset + RTP_MAX_PAYLOAD < buffer.Length) ? RTP_MAX_PAYLOAD : buffer.Length - offset;
                    int srtpProtectionLength = (SrtpProtect != null) ? SRTP_AUTH_KEY_LENGTH : 0;

                    byte[] vp8HeaderBytes = (index == 0) ? new byte[] { 0x10 } : new byte[] { 0x00 };

                    RTPPacket rtpPacket = new RTPPacket(payloadLength + vp8HeaderBytes.Length + srtpProtectionLength);
                    rtpPacket.Header.SyncSource     = sessionStream.Ssrc;
                    rtpPacket.Header.SequenceNumber = sessionStream.SeqNum++;
                    rtpPacket.Header.Timestamp      = timestamp;
                    rtpPacket.Header.MarkerBit      = ((offset + payloadLength) >= buffer.Length) ? 1 : 0; // Set marker bit for the last packet in the frame.
                    rtpPacket.Header.PayloadType    = sessionStream.PayloadTypeID;

                    Buffer.BlockCopy(vp8HeaderBytes, 0, rtpPacket.Payload, 0, vp8HeaderBytes.Length);
                    Buffer.BlockCopy(buffer, offset, rtpPacket.Payload, vp8HeaderBytes.Length, payloadLength);

                    OnRtpPacketSent?.Invoke(rtpPacket);

                    var rtpBuffer = rtpPacket.GetBytes();

                    int rtperr = SrtpProtect == null ? 0 : SrtpProtect(rtpBuffer, rtpBuffer.Length - srtpProtectionLength);
                    if (rtperr != 0)
                    {
                        logger.LogError("SendVp8Frame SRTP packet protection failed, result " + rtperr + ".");
                    }
                    else
                    {
                        RtpChannel.SendAsync(RTPChannelSocketsEnum.RTP, DestinationEndPoint, rtpBuffer);
                    }

                    m_lastRtpTimestamp = timestamp;
                }
            }
            catch (SocketException sockExcp)
            {
                logger.LogError("SocketException SendVp8Frame. " + sockExcp.Message);
            }
        }
        public void SendVp8Frame(Socket srcRtpSocket, IPEndPoint dstRtpSocket, uint timestamp, byte[] buffer)
        {
            try
            {
                for (int index = 0; index *RTP_MAX_PAYLOAD < buffer.Length; index++)
                {
                    SeqNum = (ushort)(SeqNum % UInt16.MaxValue);

                    int offset               = (index == 0) ? 0 : (index * RTP_MAX_PAYLOAD);
                    int payloadLength        = (offset + RTP_MAX_PAYLOAD < buffer.Length) ? RTP_MAX_PAYLOAD : buffer.Length - offset;
                    int srtpProtectionLength = (SrtpProtect != null) ? SRTP_AUTH_KEY_LENGTH : 0;

                    byte[] vp8HeaderBytes = (index == 0) ? new byte[] { 0x10 } : new byte[] { 0x00 };

                    RTPPacket rtpPacket = new RTPPacket(payloadLength + vp8HeaderBytes.Length + srtpProtectionLength);
                    rtpPacket.Header.SyncSource     = Ssrc;
                    rtpPacket.Header.SequenceNumber = SeqNum++;
                    rtpPacket.Header.Timestamp      = timestamp;
                    rtpPacket.Header.MarkerBit      = ((offset + payloadLength) >= buffer.Length) ? 1 : 0; // Set marker bit for the last packet in the frame.
                    rtpPacket.Header.PayloadType    = PayloadType;

                    Buffer.BlockCopy(vp8HeaderBytes, 0, rtpPacket.Payload, 0, vp8HeaderBytes.Length);
                    Buffer.BlockCopy(buffer, offset, rtpPacket.Payload, vp8HeaderBytes.Length, payloadLength);

                    var rtpBuffer = rtpPacket.GetBytes();


                    int rtperr = SrtpProtect == null ? 0 : SrtpProtect(rtpBuffer, rtpBuffer.Length - srtpProtectionLength);
                    if (rtperr != 0)
                    {
                        logger.LogError("SendVp8Frame SRTP packet protection failed, result " + rtperr + ".");
                    }
                    else
                    {
                        srcRtpSocket.SendTo(rtpBuffer, dstRtpSocket);
                    }

                    PacketsSent++;
                    OctetsSent += (uint)payloadLength;
                }
            }
            catch (System.Net.Sockets.SocketException sockExcp)
            {
                logger.LogError("SocketException SendVp8Frame. " + sockExcp.Message);
            }
        }
Example #5
0
        /// <summary>
        /// Helper method to send a low quality JPEG image over RTP. This method supports a very abbreviated version of RFC 2435 "RTP Payload Format for JPEG-compressed Video".
        /// It's intended as a quick convenient way to send something like a test pattern image over an RTSP connection. More than likely it won't be suitable when a high
        /// quality image is required since the header used in this method does not support quantization tables.
        /// </summary>
        /// <param name="jpegBytes">The raw encoded bytes of the JPEG image to transmit.</param>
        /// <param name="jpegQuality">The encoder quality of the JPEG image.</param>
        /// <param name="jpegWidth">The width of the JPEG image.</param>
        /// <param name="jpegHeight">The height of the JPEG image.</param>
        /// <param name="framesPerSecond">The rate at which the JPEG frames are being transmitted at. used to calculate the timestamp.</param>
        public void SendJpegFrame(uint timestamp, byte[] jpegBytes, int jpegQuality, int jpegWidth, int jpegHeight, int streamID = 0)
        {
            if (m_isClosed || m_rtpEventInProgress || DestinationEndPoint == null)
            {
                return;
            }

            try
            {
                //System.Diagnostics.Debug.WriteLine("Sending " + jpegBytes.Length + " encoded bytes to client, timestamp " + _timestamp + ", starting sequence number " + _sequenceNumber + ", image dimensions " + jpegWidth + " x " + jpegHeight + ".");

                RTPSessionStream sessionStream = m_sessionStreams.Where(x => x.ID == streamID).Single();

                for (int index = 0; index *RTP_MAX_PAYLOAD < jpegBytes.Length; index++)
                {
                    uint offset        = Convert.ToUInt32(index * RTP_MAX_PAYLOAD);
                    int  payloadLength = ((index + 1) * RTP_MAX_PAYLOAD < jpegBytes.Length) ? RTP_MAX_PAYLOAD : jpegBytes.Length - index * RTP_MAX_PAYLOAD;

                    byte[] jpegHeader = CreateLowQualityRtpJpegHeader(offset, jpegQuality, jpegWidth, jpegHeight);

                    List <byte> packetPayload = new List <byte>();
                    packetPayload.AddRange(jpegHeader);
                    packetPayload.AddRange(jpegBytes.Skip(index * RTP_MAX_PAYLOAD).Take(payloadLength));

                    RTPPacket rtpPacket = new RTPPacket(packetPayload.Count);
                    rtpPacket.Header.SyncSource     = sessionStream.Ssrc;
                    rtpPacket.Header.SequenceNumber = sessionStream.SeqNum++;
                    rtpPacket.Header.Timestamp      = timestamp;
                    rtpPacket.Header.MarkerBit      = ((index + 1) * RTP_MAX_PAYLOAD < jpegBytes.Length) ? 0 : 1;
                    rtpPacket.Header.PayloadType    = (int)SDPMediaFormatsEnum.JPEG;
                    rtpPacket.Payload = packetPayload.ToArray();

                    OnRtpPacketSent?.Invoke(rtpPacket);

                    byte[] rtpBytes = rtpPacket.GetBytes();

                    RtpChannel.SendAsync(RTPChannelSocketsEnum.RTP, DestinationEndPoint, rtpBytes);
                }
            }
            catch (SocketException sockExcp)
            {
                logger.LogError("SocketException SendJpegFrame. " + sockExcp.Message);
            }
        }
Example #6
0
        /// <summary>
        /// Does the actual sending of an RTP packet using the specified data and header values.
        /// </summary>
        /// <param name="rtpChannel">The RTP channel to send from.</param>
        /// <param name="dstRtpSocket">Destination to send to.</param>
        /// <param name="data">The RTP packet payload.</param>
        /// <param name="timestamp">The RTP header timestamp.</param>
        /// <param name="markerBit">The RTP header marker bit.</param>
        /// <param name="payloadType">The RTP header payload type.</param>
        private void SendRtpPacket(RTPChannel rtpChannel, IPEndPoint dstRtpSocket, byte[] data, uint timestamp, int markerBit, int payloadType, uint ssrc, ushort seqNum, RTCPSession rtcpSession)
        {
            if (IsSecure && !IsSecureContextReady)
            {
                logger.LogWarning("SendRtpPacket cannot be called on a secure session before calling SetSecurityContext.");
            }
            else
            {
                int srtpProtectionLength = (m_srtpProtect != null) ? SRTP_MAX_PREFIX_LENGTH : 0;

                RTPPacket rtpPacket = new RTPPacket(data.Length + srtpProtectionLength);
                rtpPacket.Header.SyncSource     = ssrc;
                rtpPacket.Header.SequenceNumber = seqNum;
                rtpPacket.Header.Timestamp      = timestamp;
                rtpPacket.Header.MarkerBit      = markerBit;
                rtpPacket.Header.PayloadType    = payloadType;

                Buffer.BlockCopy(data, 0, rtpPacket.Payload, 0, data.Length);

                var rtpBuffer = rtpPacket.GetBytes();

                if (m_srtpProtect == null)
                {
                    rtpChannel.SendAsync(RTPChannelSocketsEnum.RTP, dstRtpSocket, rtpBuffer);
                }
                else
                {
                    int outBufLen = 0;
                    int rtperr    = m_srtpProtect(rtpBuffer, rtpBuffer.Length - srtpProtectionLength, out outBufLen);
                    if (rtperr != 0)
                    {
                        logger.LogError("SendRTPPacket protection failed, result " + rtperr + ".");
                    }
                    else
                    {
                        rtpChannel.SendAsync(RTPChannelSocketsEnum.RTP, dstRtpSocket, rtpBuffer.Take(outBufLen).ToArray());
                    }
                }
                m_lastRtpTimestamp = timestamp;

                rtcpSession?.RecordRtpPacketSend(rtpPacket);
            }
        }
Example #7
0
        /// <summary>
        /// H264 frames need a two byte header when transmitted over RTP.
        /// </summary>
        /// <param name="frame">The H264 encoded frame to transmit.</param>
        /// <param name="payloadType">The payload type to set on the RTP packet.</param>
        public void SendH264Frame(byte[] frame, int payloadType)
        {
            try
            {
                if (_closed)
                {
                    logger.Warn("SendH264Frame cannot be called on a closed session.");
                }
                else if (_rtpSocketError != SocketError.Success)
                {
                    logger.Warn("SendH264Frame was called for an RTP socket in an error state of " + _rtpSocketError + ".");
                }
                else if (_remoteEndPoint == null)
                {
                    logger.Warn("SendH264Frame frame not sent as remote end point is not yet set.");
                }
                else
                {
                    RecalculateTimestampStep();

                    _timestamp += _timestampStep;

                    //System.Diagnostics.Debug.WriteLine("Sending " + frame.Length + " H264 encoded bytes to client, timestamp " + _timestamp + ", starting sequence number " + _sequenceNumber + ".");

                    for (int index = 0; index * RTP_MAX_PAYLOAD < frame.Length; index++)
                    {
                        uint offset = Convert.ToUInt32(index * RTP_MAX_PAYLOAD);
                        int payloadLength = ((index + 1) * RTP_MAX_PAYLOAD < frame.Length) ? RTP_MAX_PAYLOAD : frame.Length - index * RTP_MAX_PAYLOAD;

                        RTPPacket rtpPacket = new RTPPacket(payloadLength + H264_RTP_HEADER_LENGTH);
                        rtpPacket.Header.SyncSource = _syncSource;
                        rtpPacket.Header.SequenceNumber = _sequenceNumber++;
                        rtpPacket.Header.Timestamp = _timestamp;
                        rtpPacket.Header.MarkerBit = 0;
                        rtpPacket.Header.PayloadType = payloadType;

                        // Start RTP packet in frame 0x1c 0x89
                        // Middle RTP packet in frame 0x1c 0x09
                        // Last RTP packet in frame 0x1c 0x49

                        byte[] h264Header = new byte[] { 0x1c, 0x09 };

                        if (index == 0 && frame.Length < RTP_MAX_PAYLOAD)
                        {
                            // First and last RTP packet in the frame.
                            h264Header = new byte[] { 0x1c, 0x49 };
                            rtpPacket.Header.MarkerBit = 1;
                        }
                        else if (index == 0)
                        {
                            h264Header = new byte[] { 0x1c, 0x89 };
                        }
                        else if ((index + 1) * RTP_MAX_PAYLOAD > frame.Length)
                        {
                            h264Header = new byte[] { 0x1c, 0x49 };
                            rtpPacket.Header.MarkerBit = 1;
                        }

                        var h264Stream = frame.Skip(index * RTP_MAX_PAYLOAD).Take(payloadLength).ToList();
                        h264Stream.InsertRange(0, h264Header);
                        rtpPacket.Payload = h264Stream.ToArray();

                        byte[] rtpBytes = rtpPacket.GetBytes();

                        //System.Diagnostics.Debug.WriteLine(" offset " + (index * RTP_MAX_PAYLOAD) + ", payload length " + payloadLength + ", sequence number " + rtpPacket.Header.SequenceNumber + ", marker " + rtpPacket.Header .MarkerBit + ".");

                        //Stopwatch sw = new Stopwatch();
                        //sw.Start();

                        //_rtpSocket.SendTo(rtpBytes, rtpBytes.Length, SocketFlags.None,  _remoteEndPoint);
                        //SocketAsyncEventArgs socketSendArgs = new SocketAsyncEventArgs();
                        //socketSendArgs.SetBuffer(rtpBytes, 0, rtpBytes.Length);
                        //socketSendArgs.RemoteEndPoint = _remoteEndPoint;
                        //_rtpSocket.SendToAsync(socketSendArgs);

                        _rtpSocket.BeginSendTo(rtpBytes, 0, rtpBytes.Length, SocketFlags.None, _remoteEndPoint, null, null);

                        //sw.Stop();

                        //if (sw.ElapsedMilliseconds > 15)
                        //{
                        //    logger.Warn(" SendH264Frame offset " + offset + ", payload length " + payloadLength + ", sequence number " + rtpPacket.Header.SequenceNumber + ", marker " + rtpPacket.Header.MarkerBit + ", took " + sw.ElapsedMilliseconds + "ms.");
                        //}
                    }
                }
            }
            catch (Exception excp)
            {
                if (!_closed)
                {
                    logger.Warn("Exception RTSPSession.SendH264Frame attempting to send to the RTP socket at " + _remoteEndPoint + ". " + excp);

                    if (OnRTPSocketDisconnected != null)
                    {
                        OnRTPSocketDisconnected(_sessionID);
                    }
                }
            }
        }
Example #8
0
        private static void RelayRTP(UdpClient rtpClient)
        {
            try
            {
                DateTime lastCleanup = DateTime.Now;
                //_newRTPReceiverSRTP = new SRTPManaged(Convert.FromBase64String(_sourceSRTPKey));
                //_newRTPReceiverSRTP = new SRTPManaged();

                IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
                byte[] buffer = rtpClient.Receive(ref remoteEndPoint);

                StreamWriter sw = new StreamWriter("rtpPackets.txt");
                byte[] frame = new byte[1000000];
                int framePosition = 0;
                int sampleCount = 0;
                DateTime lastReceiveTime = DateTime.Now;

                while (buffer != null && buffer.Length > 0 && !m_exit)
                {
                    int packetSpacingMilli = Convert.ToInt32(DateTime.Now.Subtract(lastReceiveTime).TotalMilliseconds);
                    Console.WriteLine("Packet spacing " + packetSpacingMilli + "ms.");
                    lastReceiveTime = DateTime.Now;

                    if (_webRTCClients.Count != 0)
                    {
                        RTPPacket triggerRTPPacket = new RTPPacket(buffer);
                        RTPVP8Header vp8Header = RTPVP8Header.GetVP8Header(triggerRTPPacket.Payload);

                        if (sampleCount < 1000)
                        {
                            sw.WriteLine(triggerRTPPacket.Header.Timestamp + "," + triggerRTPPacket.Header.MarkerBit + "," + Convert.ToBase64String(triggerRTPPacket.Payload));

                            //if (triggerRTPPacket.Header.MarkerBit == 1 && vp8Header.StartOfVP8Partition == true)
                            //{
                            //    // This is a single packet frame.
                            //    sw.WriteLine(Convert.ToBase64String(vp8Header.GetBytes()) + "," + Convert.ToBase64String(triggerRTPPacket.Payload, vp8Header.Length, triggerRTPPacket.Payload.Length - vp8Header.Length));
                            //}
                            //else if (vp8Header.StartOfVP8Partition == true)
                            //{
                            //    // This is a first packet in a multi-packet frame.
                            //    sw.Write(Convert.ToBase64String(vp8Header.GetBytes()) + ",");
                            //    Buffer.BlockCopy(triggerRTPPacket.Payload, vp8Header.Length, frame, 0, triggerRTPPacket.Payload.Length - vp8Header.Length);
                            //    framePosition = triggerRTPPacket.Payload.Length - vp8Header.Length;
                            //}
                            //else if (triggerRTPPacket.Header.MarkerBit == 1)
                            //{
                            //    // This is the last continuation frame.
                            //    Buffer.BlockCopy(triggerRTPPacket.Payload, vp8Header.Length, frame, framePosition, triggerRTPPacket.Payload.Length - vp8Header.Length);
                            //    framePosition += triggerRTPPacket.Payload.Length - vp8Header.Length;
                            //    sw.WriteLine(Convert.ToBase64String(frame, 0, framePosition));
                            //    framePosition = 0;
                            //}
                            //else
                            //{
                            //    // This is a middle continuation packet
                            //    Buffer.BlockCopy(triggerRTPPacket.Payload, vp8Header.Length, frame, framePosition, triggerRTPPacket.Payload.Length - vp8Header.Length);
                            //    framePosition += triggerRTPPacket.Payload.Length - vp8Header.Length;
                            //}

                            sampleCount++;

                            if (sampleCount == 1000)
                            {
                                Console.WriteLine("Sample collection complete.");
                                sw.Close();
                            }
                        }

                        lock (_webRTCClients)
                        {
                            foreach (var client in _webRTCClients.Where(x => x.STUNExchangeComplete))
                            {
                                try
                                {
                                    if (client.LastTimestamp == 0)
                                    {
                                        client.LastTimestamp = RTSPSession.DateTimeToNptTimestamp32(DateTime.Now);
                                    }
                                    else if (vp8Header.StartOfVP8Partition)
                                    {
                                        client.LastTimestamp += 11520;
                                    }

                                    RTPPacket rtpPacket = new RTPPacket(triggerRTPPacket.Payload.Length + SRTP_AUTH_KEY_LENGTH);
                                    rtpPacket.Header.SyncSource = client.SSRC;
                                    rtpPacket.Header.SequenceNumber = client.SequenceNumber++;
                                    rtpPacket.Header.Timestamp = client.LastTimestamp; //triggerRTPPacket.Header.Timestamp; // client.LastTimestamp;
                                    rtpPacket.Header.MarkerBit = triggerRTPPacket.Header.MarkerBit;
                                    rtpPacket.Header.PayloadType = 100;

                                    Buffer.BlockCopy(triggerRTPPacket.Payload, 0, rtpPacket.Payload, 0, triggerRTPPacket.Payload.Length);

                                    var rtpBuffer = rtpPacket.GetBytes();

                                    _webRTCReceiverClient.Send(rtpBuffer, rtpBuffer.Length - SRTP_AUTH_KEY_LENGTH, _wiresharpEP);

                                    if (vp8Header.IsKeyFrame)
                                    {
                                        Console.WriteLine("key frame.");
                                    }

                                    //int rtperr = _newRTPReceiverSRTP.ProtectRTP(rtpBuffer, rtpBuffer.Length - 10);
                                    int rtperr = client.SrtpContext.ProtectRTP(rtpBuffer, rtpBuffer.Length - SRTP_AUTH_KEY_LENGTH);
                                    if (rtperr != 0)
                                    {
                                        logger.Debug("New RTP packet protect result " + rtperr + ".");
                                    }

                                    logger.Debug("Sending RTP " + rtpBuffer.Length + " bytes to " + client.SocketAddress + ", timestamp " + rtpPacket.Header.Timestamp + ", trigger timestamp " + triggerRTPPacket.Header.Timestamp + ", marker bit " + rtpPacket.Header.MarkerBit + ".");
                                    _webRTCReceiverClient.Send(rtpBuffer, rtpBuffer.Length, client.SocketAddress);
                                }
                                catch (Exception sendExcp)
                                {
                                    logger.Error("RelayRTP exception sending to " + client.SocketAddress + ". " + sendExcp.Message);
                                }
                            }
                        }
                    }

                    buffer = rtpClient.Receive(ref remoteEndPoint);
                }
            }
            catch (Exception excp)
            {
                logger.Error("Exception  RelayRTP. " + excp);
            }
        }
Example #9
0
        private static void SendRTPFromCamera()
        {
            try
            {
                unsafe
                {
                    SIPSorceryMedia.MFVideoSampler videoSampler = new SIPSorceryMedia.MFVideoSampler();

                    //List<VideoMode> webcamModes = new List<VideoMode>();
                    //int deviceCount = videoSampler.GetVideoDevices(ref webcamModes);
                    //foreach (var videoMode in webcamModes)
                    //{
                    //    Console.WriteLine(videoMode.DeviceFriendlyName + " " + (videoMode.VideoSubTypeFriendlyName ?? videoMode.VideoSubType.ToString()) + " " + videoMode.Width + "x" + videoMode.Height + ".");
                    //}

                    videoSampler.Init(_webcamIndex, _webcamVideoSubType, _webcamWidth, _webcamHeight);

                    SIPSorceryMedia.VPXEncoder vpxEncoder = new VPXEncoder();
                    vpxEncoder.InitEncoder(_webcamWidth, _webcamHeight);

                    SIPSorceryMedia.ImageConvert colorConverter = new ImageConvert();

                    byte pictureID = 0x1;
                    byte[] sampleBuffer = null;
                    byte[] encodedBuffer = new byte[4096];

                    while (true)
                    {
                        if (_webRTCClients.Any(x => x.STUNExchangeComplete == true && x.IsDtlsNegotiationComplete == true))
                        {
                            int result = videoSampler.GetSample(ref sampleBuffer);
                            if (result != 0)
                            {
                                Console.WriteLine("Video sampler returned a null sample.");
                            }
                            else
                            {
                                //Console.WriteLine("Got managed sample " + sample.Buffer.Length + ", is key frame " + sample.IsKeyFrame + ".");

                                fixed (byte* p = sampleBuffer)
                                {
                                    byte[] convertedFrame = null;
                                    colorConverter.ConvertToI420(p, _webcamVideoSubType, Convert.ToInt32(_webcamWidth), Convert.ToInt32(_webcamHeight), ref convertedFrame);

                                    //int encodeResult = vpxEncoder.Encode(p, sampleBuffer.Length, 1, ref encodedBuffer);
                                    fixed (byte* q = convertedFrame)
                                    {
                                        int encodeResult = vpxEncoder.Encode(q, sampleBuffer.Length, 1, ref encodedBuffer);

                                        if (encodeResult != 0)
                                        {
                                            Console.WriteLine("VPX encode of video sample failed.");
                                            continue;
                                        }
                                    }
                                }

                                lock (_webRTCClients)
                                {
                                    foreach (var client in _webRTCClients.Where(x => x.STUNExchangeComplete && x.IsDtlsNegotiationComplete == true))
                                    {
                                        try
                                        {
                                            //if (client.LastRtcpSenderReportSentAt == DateTime.MinValue)
                                            //{
                                            //    logger.Debug("Sending RTCP report to " + client.SocketAddress + ".");

                                            //    // Send RTCP report.
                                            //    RTCPPacket rtcp = new RTCPPacket(client.SSRC, 0, 0, 0, 0);
                                            //    byte[] rtcpBuffer = rtcp.GetBytes();
                                            //    _webRTCReceiverClient.BeginSend(rtcpBuffer, rtcpBuffer.Length, client.SocketAddress, null, null);
                                            //    //int rtperr = client.SrtpContext.ProtectRTP(rtcpBuffer, rtcpBuffer.Length - SRTP_AUTH_KEY_LENGTH);
                                            //}

                                            //Console.WriteLine("Sending VP8 frame of " + encodedBuffer.Length + " bytes to " + client.SocketAddress + ".");

                                            client.LastTimestamp = (client.LastTimestamp == 0) ? RTSPSession.DateTimeToNptTimestamp32(DateTime.Now) : client.LastTimestamp + TIMESTAMP_SPACING;

                                            for (int index = 0; index * RTP_MAX_PAYLOAD < encodedBuffer.Length; index++)
                                            {
                                                int offset = (index == 0) ? 0 : (index * RTP_MAX_PAYLOAD);
                                                int payloadLength = (offset + RTP_MAX_PAYLOAD < encodedBuffer.Length) ? RTP_MAX_PAYLOAD : encodedBuffer.Length - offset;

                                                byte[] vp8HeaderBytes = (index == 0) ? new byte[] { 0x10 } : new byte[] { 0x00 };

                                                RTPPacket rtpPacket = new RTPPacket(payloadLength + SRTP_AUTH_KEY_LENGTH + vp8HeaderBytes.Length);
                                                rtpPacket.Header.SyncSource = client.SSRC;
                                                rtpPacket.Header.SequenceNumber = client.SequenceNumber++;
                                                rtpPacket.Header.Timestamp = client.LastTimestamp;
                                                rtpPacket.Header.MarkerBit = ((offset + payloadLength) >= encodedBuffer.Length) ? 1 : 0; // Set marker bit for the last packet in the frame.
                                                rtpPacket.Header.PayloadType = PAYLOAD_TYPE_ID;

                                                Buffer.BlockCopy(vp8HeaderBytes, 0, rtpPacket.Payload, 0, vp8HeaderBytes.Length);
                                                Buffer.BlockCopy(encodedBuffer, offset, rtpPacket.Payload, vp8HeaderBytes.Length, payloadLength);

                                                var rtpBuffer = rtpPacket.GetBytes();

                                                //_webRTCReceiverClient.Send(rtpBuffer, rtpBuffer.Length, _wiresharpEP);

                                                int rtperr = client.SrtpContext.ProtectRTP(rtpBuffer, rtpBuffer.Length - SRTP_AUTH_KEY_LENGTH);
                                                if (rtperr != 0)
                                                {
                                                    logger.Warn("SRTP packet protection failed, result " + rtperr + ".");
                                                }
                                                else
                                                {
                                                    //logger.Debug("Sending RTP, offset " + offset + ", frame bytes " + payloadLength + ", vp8 header bytes " + vp8HeaderBytes.Length + ", timestamp " + rtpPacket.Header.Timestamp + ", seq # " + rtpPacket.Header.SequenceNumber + " to " + client.SocketAddress + ".");

                                                    //_webRTCReceiverClient.Send(rtpBuffer, rtpBuffer.Length, client.SocketAddress);

                                                    _webRTCReceiverClient.BeginSend(rtpBuffer, rtpBuffer.Length, client.SocketAddress, null, null);
                                                }
                                            }
                                        }
                                        catch (Exception sendExcp)
                                        {
                                            logger.Error("SendRTP exception sending to " + client.SocketAddress + ". " + sendExcp.Message);
                                        }
                                    }
                                }

                                pictureID++;

                                if (pictureID > 127)
                                {
                                    pictureID = 1;
                                }

                                encodedBuffer = null;
                                sampleBuffer = null;
                            }
                        }
                    }
                }
            }
            catch (Exception excp)
            {
                Console.WriteLine("Exception SendRTP. " + excp);
            }
        }
Example #10
0
        /// <summary>
        /// H264 frames need a two byte header when transmitted over RTP.
        /// </summary>
        /// <param name="frame">The H264 encoded frame to transmit.</param>
        /// <param name="frameSpacing">The increment to add to the RTP timestamp for each new frame.</param>
        /// <param name="payloadType">The payload type to set on the RTP packet.</param>
        public void SendH264Frame(uint timestamp, byte[] frame, uint frameSpacing, int payloadType)
        {
            if (m_rtpEventInProgress || DestinationEndPoint == null)
            {
                return;
            }

            try
            {
                //System.Diagnostics.Debug.WriteLine("Sending " + frame.Length + " H264 encoded bytes to client, timestamp " + _timestamp + ", starting sequence number " + _sequenceNumber + ".");

                for (int index = 0; index *RTP_MAX_PAYLOAD < frame.Length; index++)
                {
                    uint offset        = Convert.ToUInt32(index * RTP_MAX_PAYLOAD);
                    int  payloadLength = ((index + 1) * RTP_MAX_PAYLOAD < frame.Length) ? RTP_MAX_PAYLOAD : frame.Length - index * RTP_MAX_PAYLOAD;

                    RTPPacket rtpPacket = new RTPPacket(payloadLength + H264_RTP_HEADER_LENGTH);
                    rtpPacket.Header.SyncSource     = Ssrc;
                    rtpPacket.Header.SequenceNumber = SeqNum++;
                    rtpPacket.Header.Timestamp      = timestamp;
                    rtpPacket.Header.MarkerBit      = 0;
                    rtpPacket.Header.PayloadType    = payloadType;

                    // Start RTP packet in frame 0x1c 0x89
                    // Middle RTP packet in frame 0x1c 0x09
                    // Last RTP packet in frame 0x1c 0x49

                    byte[] h264Header = new byte[] { 0x1c, 0x09 };

                    if (index == 0 && frame.Length < RTP_MAX_PAYLOAD)
                    {
                        // First and last RTP packet in the frame.
                        h264Header = new byte[] { 0x1c, 0x49 };
                        rtpPacket.Header.MarkerBit = 1;
                    }
                    else if (index == 0)
                    {
                        h264Header = new byte[] { 0x1c, 0x89 };
                    }
                    else if ((index + 1) * RTP_MAX_PAYLOAD > frame.Length)
                    {
                        h264Header = new byte[] { 0x1c, 0x49 };
                        rtpPacket.Header.MarkerBit = 1;
                    }

                    var h264Stream = frame.Skip(index * RTP_MAX_PAYLOAD).Take(payloadLength).ToList();
                    h264Stream.InsertRange(0, h264Header);
                    rtpPacket.Payload = h264Stream.ToArray();

                    OnRtpPacketSent?.Invoke(rtpPacket);

                    byte[] rtpBytes = rtpPacket.GetBytes();

                    RtpChannel.SendAsync(RTPChannelSocketsEnum.RTP, DestinationEndPoint, rtpBytes);
                }
            }
            catch (SocketException sockExcp)
            {
                logger.LogError("SocketException SendH264Frame. " + sockExcp.Message);
            }
        }
Example #11
0
        /// <summary>
        /// Sends a dynamically sized frame. The RTP marker bit will be set for the last transmitted packet in the frame.
        /// </summary>
        /// <param name="frame">The frame to transmit.</param>
        /// <param name="frameSpacing">The increment to add to the RTP timestamp for each new frame.</param>
        /// <param name="payloadType">The payload type to set on the RTP packet.</param>
        public void SendVP8Frame(byte[] frame, uint frameSpacing, int payloadType)
        {
            try
            {
                if (_isClosed)
                {
                    logger.Warn("SendVP8Frame cannot be called on a closed RTP channel.");
                }
                else if (_rtpSocketError != SocketError.Success)
                {
                    logger.Warn("SendVP8Frame was called for an RTP socket in an error state of " + _rtpSocketError + ".");
                }
                else
                {
                    _timestamp = (_timestamp == 0) ? DateTimeToNptTimestamp32(DateTime.Now) : (_timestamp + frameSpacing) % UInt32.MaxValue;

                    //System.Diagnostics.Debug.WriteLine("Sending " + frame.Length + " encoded bytes to client, timestamp " + _timestamp + ", starting sequence number " + _sequenceNumber + ".");

                    for (int index = 0; index * RTP_MAX_PAYLOAD < frame.Length; index++)
                    {
                        //byte[] vp8HeaderBytes = (index == 0) ? new byte[VP8_RTP_HEADER_LENGTH] { 0x90, 0x80, (byte)(_sequenceNumber % 128) } : new byte[VP8_RTP_HEADER_LENGTH] { 0x80, 0x80, (byte)(_sequenceNumber % 128) };
                        byte[] vp8HeaderBytes = (index == 0) ? new byte[VP8_RTP_HEADER_LENGTH] { 0x10 } : new byte[VP8_RTP_HEADER_LENGTH] { 0x00 };

                        int offset = index * RTP_MAX_PAYLOAD;
                        int payloadLength = ((index + 1) * RTP_MAX_PAYLOAD < frame.Length) ? RTP_MAX_PAYLOAD : frame.Length - index * RTP_MAX_PAYLOAD;

                        // RTPPacket rtpPacket = new RTPPacket(payloadLength + VP8_RTP_HEADER_LENGTH + ((_srtp != null) ? SRTP_SIGNATURE_LENGTH : 0));
                        RTPPacket rtpPacket = new RTPPacket(payloadLength + VP8_RTP_HEADER_LENGTH);
                        rtpPacket.Header.SyncSource = _syncSource;
                        rtpPacket.Header.SequenceNumber = _sequenceNumber++;
                        rtpPacket.Header.Timestamp = _timestamp;
                        rtpPacket.Header.MarkerBit = (offset + payloadLength >= frame.Length) ? 1 : 0;
                        rtpPacket.Header.PayloadType = payloadType;

                        Buffer.BlockCopy(vp8HeaderBytes, 0, rtpPacket.Payload, 0, vp8HeaderBytes.Length);
                        Buffer.BlockCopy(frame, offset, rtpPacket.Payload, vp8HeaderBytes.Length, payloadLength);

                        byte[] rtpBytes = rtpPacket.GetBytes();

                        //if (_srtp != null)
                        //{
                        //    int rtperr = _srtp.ProtectRTP(rtpBytes, rtpBytes.Length - SRTP_SIGNATURE_LENGTH);
                        //    if (rtperr != 0)
                        //    {
                        //        logger.Warn("An error was returned attempting to sign an SRTP packet for " + _remoteEndPoint + ", error code " + rtperr + ".");
                        //    }
                        //}

                        //System.Diagnostics.Debug.WriteLine(" offset " + (index * RTP_MAX_PAYLOAD) + ", payload length " + payloadLength + ", sequence number " + rtpPacket.Header.SequenceNumber + ", marker " + rtpPacket.Header .MarkerBit + ".");

                        //Stopwatch sw = new Stopwatch();
                        //sw.Start();

                        _rtpSocket.SendTo(rtpBytes, rtpBytes.Length, SocketFlags.None, _remoteEndPoint);

                        //sw.Stop();

                        //if (sw.ElapsedMilliseconds > 15)
                        //{
                        //    logger.Warn(" SendVP8Frame offset " + offset + ", payload length " + payloadLength + ", sequence number " + rtpPacket.Header.SequenceNumber + ", marker " + rtpPacket.Header.MarkerBit + ", took " + sw.ElapsedMilliseconds + "ms.");
                        //}
                    }
                }
            }
            catch (Exception excp)
            {
                if (!_isClosed)
                {
                    logger.Warn("Exception RTPChannel.SendVP8Frame attempting to send to the RTP socket at " + _remoteEndPoint + ". " + excp);

                    if (OnRTPSocketDisconnected != null)
                    {
                        OnRTPSocketDisconnected();
                    }
                }
            }
        }
Example #12
0
        /// <summary>
        /// Sends an audio frame where the payload size is less than the maximum RTP packet payload size.
        /// </summary>
        /// <param name="payload">The audio payload to transmit.</param>
        /// <param name="frameSpacing">The increment to add to the RTP timestamp for each new frame.</param>
        /// <param name="payloadType">The payload type to set on the RTP packet.</param>
        public void SendAudioFrame(byte[] payload, uint frameSpacing, int payloadType)
        {
            try
            {
                if (_isClosed)
                {
                    logger.Warn("SendAudioFrame cannot be called on a closed RTP channel.");
                }
                else if (_rtpSocketError != SocketError.Success)
                {
                    logger.Warn("SendAudioFrame was called for an RTP socket in an error state of " + _rtpSocketError + ".");
                }
                else
                {
                    _timestamp = (_timestamp == 0) ? DateTimeToNptTimestamp32(DateTime.Now) : (_timestamp + frameSpacing) % UInt32.MaxValue;

                    RTPPacket rtpPacket = new RTPPacket(payload.Length);
                    rtpPacket.Header.SyncSource = _syncSource;
                    rtpPacket.Header.SequenceNumber = _sequenceNumber++;
                    rtpPacket.Header.Timestamp = _timestamp;
                    rtpPacket.Header.MarkerBit = 1;
                    rtpPacket.Header.PayloadType = payloadType;

                    Buffer.BlockCopy(payload, 0, rtpPacket.Payload, 0, payload.Length);

                    byte[] rtpBytes = rtpPacket.GetBytes();

                    //Stopwatch sw = new Stopwatch();
                    //sw.Start();

                    _rtpSocket.SendTo(rtpBytes, rtpBytes.Length, SocketFlags.None, _remoteEndPoint);

                    //sw.Stop();

                    //if (sw.ElapsedMilliseconds > 15)
                    //{
                    //    logger.Warn(" SendAudioFrame offset " + offset + ", payload length " + payloadLength + ", sequence number " + rtpPacket.Header.SequenceNumber + ", marker " + rtpPacket.Header.MarkerBit + ", took " + sw.ElapsedMilliseconds + "ms.");
                    //}
                }
            }
            catch (Exception excp)
            {
                if (!_isClosed)
                {
                    logger.Warn("Exception RTPChannel.SendAudioFrame attempting to send to the RTP socket at " + _remoteEndPoint + ". " + excp);

                    if (OnRTPSocketDisconnected != null)
                    {
                        OnRTPSocketDisconnected();
                    }
                }
            }
        }
        private void SendRTPPacket(string sourceSocket, string destinationSocket)
        {
            try
            {
                //logger.Debug("Attempting to send RTP packet from " + sourceSocket + " to " + destinationSocket + ".");
                Log("Attempting to send RTP packet from " + sourceSocket + " to " + destinationSocket + ".");

                IPEndPoint sourceEP = IPSocket.GetIPEndPoint(sourceSocket);
                IPEndPoint destEP = IPSocket.GetIPEndPoint(destinationSocket);

                RTPPacket rtpPacket = new RTPPacket(80);
                rtpPacket.Header.SequenceNumber = (UInt16)6500;
                rtpPacket.Header.Timestamp = 100000;

                UDPPacket udpPacket = new UDPPacket(sourceEP.Port, destEP.Port, rtpPacket.GetBytes());
                IPv4Header ipHeader = new IPv4Header(ProtocolType.Udp, Crypto.GetRandomInt(6), sourceEP.Address, destEP.Address);
                IPv4Packet ipPacket = new IPv4Packet(ipHeader, udpPacket.GetBytes());

                byte[] data = ipPacket.GetBytes();

                Socket rawSocket = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.IP);
                rawSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.HeaderIncluded, 1);

                rawSocket.SendTo(data, destEP);
            }
            catch (Exception excp)
            {
                logger.Error("Exception SendRTPPacket. " + excp.Message);
            }
        }
Example #14
0
        /// <summary>
        /// Helper method to send a low quality JPEG image over RTP. This method supports a very abbreviated version of RFC 2435 "RTP Payload Format for JPEG-compressed Video".
        /// It's intended as a quick convenient way to send something like a test pattern image over an RTSP connection. More than likely it won't be suitable when a high
        /// quality image is required since the header used in this method does not support quantization tables.
        /// </summary>
        /// <param name="jpegBytes">The raw encoded bytes of the JPEG image to transmit.</param>
        /// <param name="jpegQuality">The encoder quality of the JPEG image.</param>
        /// <param name="jpegWidth">The width of the JPEG image.</param>
        /// <param name="jpegHeight">The height of the JPEG image.</param>
        public void SendJpegFrame(byte[] jpegBytes, int jpegQuality, int jpegWidth, int jpegHeight)
        {
            try
            {
                if (_closed)
                {
                    logger.Warn("SendJpegFrame cannot be called on a closed session.");
                }
                else if (_rtpSocketError != SocketError.Success)
                {
                    logger.Warn("SendJpegFrame was called for an RTP socket in an error state of " + _rtpSocketError + ".");
                }
                else if (_remoteEndPoint == null)
                {
                    logger.Warn("SendJpegFrame frame not sent as remote end point is not yet set.");
                }
                else
                {
                    //_timestamp = (_timestamp == 0) ? DateTimeToNptTimestamp32(DateTime.Now) : (_timestamp + (uint)(RFC_2435_FREQUENCY_BASELINE / DEFAULT_INITAL_FRAME_RATE)) % UInt32.MaxValue;

                    RecalculateTimestampStep();

                    _timestamp += _timestampStep;

                    //System.Diagnostics.Debug.WriteLine("Sending " + jpegBytes.Length + " encoded bytes to client, timestamp " + _timestamp + ", starting sequence number " + _sequenceNumber + ", image dimensions " + jpegWidth + " x " + jpegHeight + ".");

                    for (int index = 0; index * RTP_MAX_PAYLOAD < jpegBytes.Length; index++)
                    {
                        uint offset = Convert.ToUInt32(index * RTP_MAX_PAYLOAD);
                        int payloadLength = ((index + 1) * RTP_MAX_PAYLOAD < jpegBytes.Length) ? RTP_MAX_PAYLOAD : jpegBytes.Length - index * RTP_MAX_PAYLOAD;

                        byte[] jpegHeader = CreateLowQualityRtpJpegHeader(offset, jpegQuality, jpegWidth, jpegHeight);

                        List<byte> packetPayload = new List<byte>();
                        packetPayload.AddRange(jpegHeader);
                        packetPayload.AddRange(jpegBytes.Skip(index * RTP_MAX_PAYLOAD).Take(payloadLength));

                        RTPPacket rtpPacket = new RTPPacket(packetPayload.Count);
                        rtpPacket.Header.SyncSource = _syncSource;
                        rtpPacket.Header.SequenceNumber = _sequenceNumber++;
                        rtpPacket.Header.Timestamp = _timestamp;
                        rtpPacket.Header.MarkerBit = ((index + 1) * RTP_MAX_PAYLOAD < jpegBytes.Length) ? 0 : 1;
                        rtpPacket.Header.PayloadType = (int)SDPMediaFormatsEnum.JPEG;
                        rtpPacket.Payload = packetPayload.ToArray();

                        byte[] rtpBytes = rtpPacket.GetBytes();

                        //System.Diagnostics.Debug.WriteLine(" offset " + offset + ", payload length " + payloadLength + ", sequence number " + rtpPacket.Header.SequenceNumber + ", marker " + rtpPacket.Header.MarkerBit + ".");

                        //Stopwatch sw = new Stopwatch();
                        //sw.Start();

                        _rtpSocket.SendTo(rtpBytes, _remoteEndPoint);

                        //sw.Stop();

                        //if (sw.ElapsedMilliseconds > 15)
                        //{
                        //    logger.Warn(" SendJpegFrame offset " + offset + ", payload length " + payloadLength + ", sequence number " + rtpPacket.Header.SequenceNumber + ", marker " + rtpPacket.Header.MarkerBit + ", took " + sw.ElapsedMilliseconds + "ms.");
                        //}
                    }

                    //sw.Stop();
                    //System.Diagnostics.Debug.WriteLine("SendJpegFrame took " + sw.ElapsedMilliseconds + ".");
                }
            }
            catch (Exception excp)
            {
                if (!_closed)
                {
                    logger.Warn("Exception RTPSession.SendJpegFrame attempting to send to the RTP socket at " + _remoteEndPoint + ". " + excp);
                    //_rtpSocketError = SocketError.SocketError;

                    if (OnRTPSocketDisconnected != null)
                    {
                        OnRTPSocketDisconnected(_sessionID);
                    }
                }
            }
        }
Example #15
0
        private static void SendRTPFromVP8FramesFile(string file)
        {
            try
            {
                StreamReader sr = new StreamReader(file);
                List<string> samples = new List<string>();
                while (!sr.EndOfStream)
                {
                    string sample = sr.ReadLine();
                    samples.Add(sample);

                    //Console.WriteLine(sample);

                    //string[] sampleFields = sample.Split(',');
                    //RTPVP8Header frameVP8Header = RTPVP8Header.GetVP8Header(Convert.FromBase64String(sampleFields[0]));
                    //byte[] rtpPaylaod = Convert.FromBase64String(sampleFields[1]);

                    //Console.WriteLine((frameVP8Header.IsKeyFrame) ? "K" : "." + " " + frameVP8Header.FirstPartitionSize + " " + rtpPaylaod.Length + ".");
                }
                sr.Close();
                logger.Debug(samples.Count + " encoded samples loaded.");

                //_newRTPReceiverSRTP = new SRTPManaged(Convert.FromBase64String(_sourceSRTPKey));
                //_newRTPReceiverSRTP = new SRTPManaged();
                int sampleIndex = 0;

                while (true)
                {
                    if (_webRTCClients.Count != 0)
                    {
                        var sampleItem = samples[sampleIndex];
                        string[] sampleFields = sampleItem.Split(',');

                        RTPVP8Header frameVP8Header = RTPVP8Header.GetVP8Header(Convert.FromBase64String(sampleFields[0]));
                        byte[] sample = Convert.FromBase64String(sampleFields[1]);

                        if (frameVP8Header.IsKeyFrame)
                        {
                            Console.WriteLine("Key frame.");
                        }

                        lock (_webRTCClients)
                        {
                            foreach (var client in _webRTCClients.Where(x => x.STUNExchangeComplete))
                            {
                                try
                                {
                                    if (client.LastTimestamp == 0)
                                    {
                                        client.LastTimestamp = RTSPSession.DateTimeToNptTimestamp32(DateTime.Now);
                                    }

                                    for (int index = 0; index * RTP_MAX_PAYLOAD < sample.Length; index++)
                                    {
                                        int offset = (index == 0) ? 0 : (index * RTP_MAX_PAYLOAD);
                                        int payloadLength = (offset + RTP_MAX_PAYLOAD < sample.Length) ? RTP_MAX_PAYLOAD : sample.Length - offset;

                                        RTPVP8Header packetVP8Header = new RTPVP8Header()
                                        {
                                            ExtendedControlBitsPresent = true,
                                            IsPictureIDPresent = true,
                                            ShowFrame = true,
                                        };

                                        if (index == 0)
                                        {
                                            packetVP8Header.StartOfVP8Partition = true;
                                            //packetVP8Header.FirstPartitionSize = frameVP8Header.FirstPartitionSize;
                                            packetVP8Header.IsKeyFrame = frameVP8Header.IsKeyFrame;
                                            packetVP8Header.PictureID = (frameVP8Header.IsKeyFrame) ? (byte)0x00 : frameVP8Header.PictureID;
                                        }

                                        byte[] vp8HeaderBytes = packetVP8Header.GetBytes();

                                        RTPPacket rtpPacket = new RTPPacket(packetVP8Header.Length + payloadLength + SRTP_AUTH_KEY_LENGTH);
                                        rtpPacket.Header.SyncSource = client.SSRC;
                                        rtpPacket.Header.SequenceNumber = client.SequenceNumber++;
                                        rtpPacket.Header.Timestamp = client.LastTimestamp;
                                        rtpPacket.Header.MarkerBit = ((offset + payloadLength) >= sample.Length) ? 1 : 0;
                                        rtpPacket.Header.PayloadType = 100;

                                        Buffer.BlockCopy(vp8HeaderBytes, 0, rtpPacket.Payload, 0, packetVP8Header.Length);
                                        Buffer.BlockCopy(sample, offset, rtpPacket.Payload, packetVP8Header.Length, payloadLength);

                                        var rtpBuffer = rtpPacket.GetBytes();

                                        _webRTCReceiverClient.Send(rtpBuffer, rtpBuffer.Length - SRTP_AUTH_KEY_LENGTH, _wiresharpEP);

                                        int rtperr = client.SrtpContext.ProtectRTP(rtpBuffer, rtpBuffer.Length - SRTP_AUTH_KEY_LENGTH);
                                        if (rtperr != 0)
                                        {
                                            logger.Debug("New RTP packet protect result " + rtperr + ".");
                                        }

                                        logger.Debug("Sending RTP " + sample.Length + " bytes to " + client.SocketAddress + ", timestamp " + client.LastTimestamp + ", marker " + rtpPacket.Header.MarkerBit + ".");

                                        _webRTCReceiverClient.Send(rtpBuffer, rtpBuffer.Length, client.SocketAddress);
                                    }

                                    client.LastTimestamp += TIMESTAMP_SPACING;
                                }
                                catch (Exception sendExcp)
                                {
                                    logger.Error("SendRTPFromVP8FramesFile exception sending to " + client.SocketAddress + ". " + sendExcp.Message);
                                }
                            }
                        }

                        sampleIndex++;
                        if (sampleIndex >= samples.Count - 1)
                        {
                            sampleIndex = 0;
                        }

                        Thread.Sleep(30);
                    }
                }
            }
            catch (Exception excp)
            {
                Console.WriteLine("Exception SendRTPFromVP8FramesFile. " + excp);
            }
        }
Example #16
0
        private static void SendRTPFromRawRTPFile(string file)
        {
            try
            {
                StreamReader sr = new StreamReader(file);
                List<string> samples = new List<string>();
                while (!sr.EndOfStream)
                {
                    samples.Add(sr.ReadLine());
                }
                sr.Close();
                logger.Debug(samples.Count + " encoded samples loaded.");

                //_newRTPReceiverSRTP = new SRTPManaged(Convert.FromBase64String(_sourceSRTPKey));
                //_newRTPReceiverSRTP = new SRTPManaged();
                int sampleIndex = 0;

                while (true)
                {
                    if (_webRTCClients.Count != 0)
                    {
                        var sampleItem = samples[sampleIndex];
                        string[] sampleFields = sampleItem.Split(',');

                        uint timestamp = Convert.ToUInt32(sampleFields[0]);
                        int markerBit = Convert.ToInt32(sampleFields[1]);
                        byte[] sample = Convert.FromBase64String(sampleFields[2]);

                        lock (_webRTCClients)
                        {
                            foreach (var client in _webRTCClients.Where(x => x.STUNExchangeComplete))
                            {
                                try
                                {
                                    if (client.LastTimestamp == 0)
                                    {
                                        client.LastTimestamp = RTSPSession.DateTimeToNptTimestamp32(DateTime.Now);
                                    }

                                    //for (int index = 0; index * RTP_MAX_PAYLOAD < sample.Length; index++)
                                    //{
                                    //    int offset = (index == 0) ? 0 : (index * RTP_MAX_PAYLOAD) - 1;
                                    //    int payloadLength = (offset + RTP_MAX_PAYLOAD < sample.Length - 1) ? RTP_MAX_PAYLOAD : sample.Length - 1 - offset;

                                    RTPPacket rtpPacket = new RTPPacket(sample.Length + SRTP_AUTH_KEY_LENGTH);
                                    rtpPacket.Header.SyncSource = client.SSRC;
                                    rtpPacket.Header.SequenceNumber = client.SequenceNumber++;
                                    rtpPacket.Header.Timestamp = client.LastTimestamp;
                                    rtpPacket.Header.MarkerBit = markerBit;
                                    rtpPacket.Header.PayloadType = 100;

                                    //if (offset + RTP_MAX_PAYLOAD > sample.Length - 1)
                                    //{
                                    //     Last packet in the frame.
                                    //    rtpPacket.Header.MarkerBit = 1;
                                    //}

                                    Buffer.BlockCopy(sample, 0, rtpPacket.Payload, 0, sample.Length);

                                    var rtpBuffer = rtpPacket.GetBytes();
                                    int rtperr = client.SrtpContext.ProtectRTP(rtpBuffer, rtpBuffer.Length - SRTP_AUTH_KEY_LENGTH);
                                    if (rtperr != 0)
                                    {
                                        logger.Debug("New RTP packet protect result " + rtperr + ".");
                                    }

                                    //logger.Debug("Sending RTP " + sample.Length + " bytes to " + client.SocketAddress + ", timestamp " + client.LastTimestamp + ", marker " + rtpPacket.Header.MarkerBit + ".");

                                    _webRTCReceiverClient.Send(rtpBuffer, rtpBuffer.Length, client.SocketAddress);

                                    if (markerBit == 1)
                                    {
                                        client.LastTimestamp += TIMESTAMP_SPACING;
                                    }
                                    //}
                                }
                                catch (Exception sendExcp)
                                {
                                    logger.Error("SendRTPFromFile exception sending to " + client.SocketAddress + ". " + sendExcp.Message);
                                }
                            }
                        }

                        sampleIndex++;
                        if (sampleIndex >= samples.Count - 1)
                        {
                            sampleIndex = 0;
                        }

                        //Thread.Sleep(30);
                    }
                }
            }
            catch (Exception excp)
            {
                Console.WriteLine("Exception SendRTPFromFile. " + excp);
            }
        }
Example #17
0
        public void Send(byte[] buffer)
        {
            try
            {
                Peer.LastTimestamp = (Peer.LastTimestamp == 0) ? RTSPSession.DateTimeToNptTimestamp32(DateTime.Now) : Peer.LastTimestamp + TIMESTAMP_SPACING;

                for (int index = 0; index * RTP_MAX_PAYLOAD < buffer.Length; index++)
                {
                    int offset = (index == 0) ? 0 : (index * RTP_MAX_PAYLOAD);
                    int payloadLength = (offset + RTP_MAX_PAYLOAD < buffer.Length) ? RTP_MAX_PAYLOAD : buffer.Length - offset;

                    byte[] vp8HeaderBytes = (index == 0) ? new byte[] { 0x10 } : new byte[] { 0x00 };

                    RTPPacket rtpPacket = new RTPPacket(payloadLength + SRTP_AUTH_KEY_LENGTH + vp8HeaderBytes.Length);
                    rtpPacket.Header.SyncSource = Peer.SSRC;
                    rtpPacket.Header.SequenceNumber = Peer.SequenceNumber++;
                    rtpPacket.Header.Timestamp = Peer.LastTimestamp;
                    rtpPacket.Header.MarkerBit = ((offset + payloadLength) >= buffer.Length) ? 1 : 0; // Set marker bit for the last packet in the frame.
                    rtpPacket.Header.PayloadType = PAYLOAD_TYPE_ID;

                    Buffer.BlockCopy(vp8HeaderBytes, 0, rtpPacket.Payload, 0, vp8HeaderBytes.Length);
                    Buffer.BlockCopy(buffer, offset, rtpPacket.Payload, vp8HeaderBytes.Length, payloadLength);

                    var rtpBuffer = rtpPacket.GetBytes();

                    int rtperr = SrtpContext.ProtectRTP(rtpBuffer, rtpBuffer.Length - SRTP_AUTH_KEY_LENGTH);
                    if (rtperr != 0)
                    {
                        logger.Warn("SRTP packet protection failed, result " + rtperr + ".");
                    }
                    else
                    {
                        var connectedIceCandidate = Peer.LocalIceCandidates.Where(y => y.RemoteRtpEndPoint != null).First();
                        connectedIceCandidate.LocalRtpSocket.SendTo(rtpBuffer, connectedIceCandidate.RemoteRtpEndPoint);
                    }
                }
            }
            catch (Exception sendExcp)
            {
                // logger.Error("SendRTP exception sending to " + client.SocketAddress + ". " + sendExcp.Message);
            }
        }
Example #18
0
        private void Send()
        {
            try
            {
                int       payloadSize = RTPPacketSendSize;
                RTPPacket rtpPacket   = new RTPPacket(RTPPacketSendSize);
                byte[]    rtpBytes    = rtpPacket.GetBytes();

                RTPHeader rtpHeader = new RTPHeader();
                rtpHeader.SequenceNumber = (UInt16)65000;  //Convert.ToUInt16(Crypto.GetRandomInt(0, UInt16.MaxValue));
                uint   sendTimestamp     = uint.MaxValue - 5000;
                uint   lastSendTimestamp = sendTimestamp;
                UInt16 lastSeqNum        = 0;

                logger.Debug("RTP send stream starting to " + IPSocket.GetSocketString(m_streamEndPoint) + " with payload size " + payloadSize + " bytes.");

                Sending            = true;
                m_startRTPSendTime = DateTime.MinValue;
                m_lastRTPSentTime  = DateTime.MinValue;
                m_sampleStartSeqNo = rtpHeader.SequenceNumber;

                DateTime lastRTPSendAttempt = DateTime.Now;

                while (m_udpListener != null && !StopListening)
                {
                    // This may be changed by the listener so it needs to be set each iteration.
                    IPEndPoint dstEndPoint = m_streamEndPoint;

                    //logger.Info("Sending RTP packet to " + dstEndPoint.Address + ":"  + dstEndPoint.Port);

                    if (payloadSize != m_rtpPacketSendSize)
                    {
                        payloadSize = m_rtpPacketSendSize;
                        logger.Info("Changing RTP payload to " + payloadSize);
                        rtpPacket = new RTPPacket(RTP_HEADER_SIZE + m_rtpPacketSendSize);
                        rtpBytes  = rtpPacket.GetBytes();
                    }

                    try
                    {
                        if (m_startRTPSendTime == DateTime.MinValue)
                        {
                            m_startRTPSendTime  = DateTime.Now;
                            rtpHeader.MarkerBit = 0;

                            logger.Debug("RTPSink Send SyncSource=" + rtpPacket.Header.SyncSource + ".");
                        }
                        else
                        {
                            lastSendTimestamp = sendTimestamp;
                            double milliSinceLastSend = DateTime.Now.Subtract(m_lastRTPSentTime).TotalMilliseconds;
                            sendTimestamp = Convert.ToUInt32((lastSendTimestamp + (milliSinceLastSend * TIMESTAMP_FACTOR)) % uint.MaxValue);

                            if (lastSendTimestamp > sendTimestamp)
                            {
                                logger.Error("RTP Sender previous timestamp (" + lastSendTimestamp + ") > timestamp (" + sendTimestamp + ") ms since last send=" + milliSinceLastSend + ", lastseqnum=" + lastSeqNum + ", seqnum=" + rtpHeader.SequenceNumber + ".");
                            }

                            if (DateTime.Now.Subtract(m_lastRTPSentTime).TotalMilliseconds > 75)
                            {
                                logger.Debug("delayed send: " + rtpHeader.SequenceNumber + ", time since last send " + DateTime.Now.Subtract(m_lastRTPSentTime).TotalMilliseconds + "ms.");
                            }
                        }

                        rtpHeader.Timestamp = sendTimestamp;
                        byte[] rtpHeaderBytes = rtpHeader.GetBytes();
                        Array.Copy(rtpHeaderBytes, 0, rtpBytes, 0, rtpHeaderBytes.Length);

                        // Send RTP packets and any extra channels required to emulate mutliple calls.
                        for (int channelCount = 0; channelCount < m_channels; channelCount++)
                        {
                            //logger.Debug("Send rtp getting wallclock timestamp for " + DateTime.Now.ToString("dd MMM yyyy HH:mm:ss:fff"));
                            //DateTime sendTime = DateTime.Now;
                            //rtpHeader.Timestamp = RTPHeader.GetWallclockUTCStamp(sendTime);
                            //logger.Debug(rtpHeader.SequenceNumber + "," + rtpHeader.Timestamp);

                            m_udpListener.Send(rtpBytes, rtpBytes.Length, dstEndPoint);
                            m_lastRTPSentTime = DateTime.Now;

                            m_packetsSent++;
                            m_bytesSent += rtpBytes.Length;

                            if (m_packetsSent % 500 == 0)
                            {
                                logger.Debug("Total packets sent to " + dstEndPoint.ToString() + " " + m_packetsSent + ", bytes " + NumberFormatter.ToSIByteFormat(m_bytesSent, 2) + ".");
                            }

                            //sendLogger.Info(m_lastRTPSentTime.ToString("dd MMM yyyy HH:mm:ss:fff") + "," + m_lastRTPSentTime.Subtract(m_startRTPSendTime).TotalMilliseconds.ToString("0") + "," + rtpHeader.SequenceNumber + "," + rtpBytes.Length);

                            //sendLogger.Info(rtpHeader.SequenceNumber + "," + DateTime.Now.ToString("dd MMM yyyy HH:mm:ss:fff"));

                            if (DataSent != null)
                            {
                                try
                                {
                                    DataSent(m_streamId, rtpBytes, dstEndPoint);
                                }
                                catch (Exception excp)
                                {
                                    logger.Error("Exception RTPSink DataSent. " + excp.Message);
                                }
                            }

                            lastSeqNum = rtpHeader.SequenceNumber;
                            if (rtpHeader.SequenceNumber == UInt16.MaxValue)
                            {
                                //logger.Debug("RTPSink looping  the sequence number in sample.");
                                rtpHeader.SequenceNumber = 0;
                            }
                            else
                            {
                                rtpHeader.SequenceNumber++;
                            }
                        }
                    }
                    catch (Exception excp)
                    {
                        logger.Error("Exception RTP Send. " + excp.GetType() + ". " + excp.Message);

                        if (excp.GetType() == typeof(SocketException))
                        {
                            logger.Error("socket exception errorcode=" + ((SocketException)excp).ErrorCode + ".");
                        }

                        logger.Warn("Remote socket closed on send. Last RTP recevied " + m_lastRTPReceivedTime.ToString("dd MMM yyyy HH:mm:ss") + ", last RTP successfull send " + m_lastRTPSentTime.ToString("dd MMM yyyy HH:mm:ss") + ".");
                    }

                    Thread.Sleep(RTPFrameSize);

                    #region Check for whether the stream has timed out on a send or receive and if so shut down the stream.

                    double noRTPRcvdDuration = (m_lastRTPReceivedTime != DateTime.MinValue) ? DateTime.Now.Subtract(m_lastRTPReceivedTime).TotalSeconds : 0;
                    double noRTPSentDuration = (m_lastRTPSentTime != DateTime.MinValue) ? DateTime.Now.Subtract(m_lastRTPSentTime).TotalSeconds : 0;
                    double testDuration      = DateTime.Now.Subtract(m_startRTPSendTime).TotalSeconds;

                    if ((
                            noRTPRcvdDuration > NO_RTP_TIMEOUT ||
                            noRTPSentDuration > NO_RTP_TIMEOUT ||
                            (m_lastRTPReceivedTime == DateTime.MinValue && testDuration > NO_RTP_TIMEOUT)) && // If the test request comes from a private or unreachable IP address then no RTP will ever be received.
                        StopIfNoData)
                    {
                        logger.Warn("Disconnecting RTP stream on " + m_localEndPoint.Address.ToString() + ":" + m_localEndPoint.Port + " due to not being able to send any RTP for " + NO_RTP_TIMEOUT + "s.");
                        StopListening = true;
                    }

                    // Shutdown the socket even if there is still RTP but the stay alive limit has been exceeded.
                    if (RTPMaxStayAlive > 0 && DateTime.Now.Subtract(m_startRTPSendTime).TotalSeconds > RTPMaxStayAlive)
                    {
                        logger.Warn("Shutting down RTPSink due to passing RTPMaxStayAlive time.");
                        Shutdown();
                        StopListening = true;
                    }

                    #endregion
                }
            }
            catch (Exception excp)
            {
                logger.Error("Exception Send RTPSink: " + excp.Message);
            }
            finally
            {
                #region Shut down socket.

                Shutdown();

                if (SenderClosed != null)
                {
                    try
                    {
                        SenderClosed(m_streamId, m_callDescriptorId);
                    }
                    catch (Exception excp)
                    {
                        logger.Error("Exception RTPSink SenderClosed. " + excp.Message);
                    }
                }

                #endregion
            }
        }
Example #19
0
        public void Send(byte[] buffer, uint samplePeriod)
        {
            if (m_remoteEndPoint == null)
            {
                logger.Warn("RTP packet could not be sent as remote end point has not yet been set.");
            }
            else
            {
                m_sendRTPHeader.SequenceNumber++;
                m_sendRTPHeader.Timestamp += samplePeriod;

                RTPPacket rtpPacket = new RTPPacket()
                {
                    Header = m_sendRTPHeader,
                    Payload = buffer
                };

                logger.Debug("Sending RTP packet to " + m_remoteEndPoint + ", seq# " + rtpPacket.Header.SequenceNumber + ", timestamp " + rtpPacket.Header.Timestamp + ".");

                byte[] rtpOut = rtpPacket.GetBytes();
                m_rtpListener.Send(m_remoteEndPoint, rtpOut);
            }
        }
Example #20
0
        private static void SendRTPFromRawRTPFileNewVP8Header(string file)
        {
            try
            {
                StreamReader sr = new StreamReader(file);
                List<string> samples = new List<string>();
                while (!sr.EndOfStream)
                {
                    samples.Add(sr.ReadLine());
                }
                sr.Close();
                logger.Debug(samples.Count + " encoded samples loaded.");

                //_newRTPReceiverSRTP = new SRTPManaged(Convert.FromBase64String(_sourceSRTPKey));
                //_newRTPReceiverSRTP = new SRTPManaged();
                int sampleIndex = 0;

                while (true)
                {
                    if (_webRTCClients.Count != 0)
                    {
                        var sampleItem = samples[sampleIndex];
                        string[] sampleFields = sampleItem.Split(',');

                        //uint timestamp = Convert.ToUInt32(sampleFields[0]);
                        int markerBit = Convert.ToInt32(sampleFields[1]);
                        byte[] sample = Convert.FromBase64String(sampleFields[2]);

                        lock (_webRTCClients)
                        {
                            foreach (var client in _webRTCClients.Where(x => x.STUNExchangeComplete))
                            {
                                try
                                {
                                    if (client.LastTimestamp == 0)
                                    {
                                        client.LastTimestamp = RTSPSession.DateTimeToNptTimestamp32(DateTime.Now);
                                    }

                                    RTPVP8Header origVP8Header = RTPVP8Header.GetVP8Header(sample);

                                    if (origVP8Header.IsKeyFrame)
                                    {
                                        Console.WriteLine("Key frame");
                                    }

                                    RTPPacket rtpPacket = new RTPPacket(sample.Length + SRTP_AUTH_KEY_LENGTH);
                                    rtpPacket.Header.SyncSource = client.SSRC;
                                    rtpPacket.Header.SequenceNumber = client.SequenceNumber++;
                                    rtpPacket.Header.Timestamp = client.LastTimestamp;
                                    rtpPacket.Header.MarkerBit = markerBit;
                                    rtpPacket.Header.PayloadType = 100;

                                    if (origVP8Header.StartOfVP8Partition && markerBit == 1)
                                    {
                                        Console.WriteLine("My VP8 Header    : " + BitConverter.ToString(origVP8Header.GetBytes()) + ".");
                                        Console.WriteLine("Sample VP8 Header: " + BitConverter.ToString(sample, 0, 6) + ".");

                                        Buffer.BlockCopy(origVP8Header.GetBytes(), 0, rtpPacket.Payload, 0, origVP8Header.Length);
                                        Buffer.BlockCopy(sample, origVP8Header.Length, rtpPacket.Payload, origVP8Header.Length, sample.Length - origVP8Header.Length);
                                    }
                                    else
                                    {
                                        Buffer.BlockCopy(sample, 0, rtpPacket.Payload, 0, sample.Length);
                                    }

                                    var rtpBuffer = rtpPacket.GetBytes();

                                    _webRTCReceiverClient.Send(rtpBuffer, rtpBuffer.Length - SRTP_AUTH_KEY_LENGTH, _wiresharpEP);

                                    int rtperr = client.SrtpContext.ProtectRTP(rtpBuffer, rtpBuffer.Length - SRTP_AUTH_KEY_LENGTH);
                                    if (rtperr != 0)
                                    {
                                        logger.Debug("New RTP packet protect result " + rtperr + ".");
                                    }

                                    logger.Debug("Sending RTP " + sample.Length + " bytes to " + client.SocketAddress + ", timestamp " + client.LastTimestamp + ", marker " + rtpPacket.Header.MarkerBit + ".");

                                    _webRTCReceiverClient.Send(rtpBuffer, rtpBuffer.Length, client.SocketAddress);

                                    if (markerBit == 1)
                                    {
                                        client.LastTimestamp += TIMESTAMP_SPACING;
                                    }
                                    //}
                                }
                                catch (Exception sendExcp)
                                {
                                    logger.Error("SendRTPFromFile exception sending to " + client.SocketAddress + ". " + sendExcp.Message);
                                }
                            }
                        }

                        sampleIndex++;
                        if (sampleIndex >= samples.Count - 1)
                        {
                            sampleIndex = 0;
                        }

                        //Thread.Sleep(30);
                    }
                }
            }
            catch (Exception excp)
            {
                Console.WriteLine("Exception SendRTPFromFile. " + excp);
            }
        }
Example #21
0
        /// <summary>
        /// Sends a dynamically sized frame. The RTP marker bit will be set for the last transmitted packet in the frame.
        /// </summary>
        /// <param name="frame">The frame to transmit.</param>
        /// <param name="payloadType">The payload type to set on the RTP packet.</param>
        public void SendVP8Frame(byte[] frame, int payloadType)
        {
            try
            {
                if (_closed)
                {
                    logger.Warn("SendVP8Frame cannot be called on a closed session.");
                }
                else if (_rtpSocketError != SocketError.Success)
                {
                    logger.Warn("SendVP8Frame was called for an RTP socket in an error state of " + _rtpSocketError + ".");
                }
                else if (_remoteEndPoint == null)
                {
                    logger.Warn("SendVP8Frame frame not sent as remote end point is not yet set.");
                }
                else
                {
                    RecalculateTimestampStep();

                    _timestamp += _timestampStep;

                    //System.Diagnostics.Debug.WriteLine("Sending " + frame.Length + " encoded bytes to client, timestamp " + _timestamp + ", starting sequence number " + _sequenceNumber + ".");

                    for (int index = 0; index * RTP_MAX_PAYLOAD < frame.Length; index++)
                    {
                        byte[] vp8HeaderBytes = (index == 0) ? new byte[VP8_RTP_HEADER_LENGTH] { 0x90, 0x80, (byte)(_sequenceNumber % 128) } : new byte[VP8_RTP_HEADER_LENGTH] { 0x80, 0x80, (byte)(_sequenceNumber % 128) };

                        int offset = index * RTP_MAX_PAYLOAD;
                        int payloadLength = ((index + 1) * RTP_MAX_PAYLOAD < frame.Length) ? RTP_MAX_PAYLOAD : frame.Length - index * RTP_MAX_PAYLOAD;

                        //RTPPacket rtpPacket = new RTPPacket(payloadLength + VP8_RTP_HEADER_LENGTH + ((_srtp != null) ? SRTP_SIGNATURE_LENGTH : 0));
                        RTPPacket rtpPacket = new RTPPacket(payloadLength + VP8_RTP_HEADER_LENGTH);
                        rtpPacket.Header.SyncSource = _syncSource;
                        rtpPacket.Header.SequenceNumber = _sequenceNumber++;
                        rtpPacket.Header.Timestamp = _timestamp;
                        rtpPacket.Header.MarkerBit = (offset + payloadLength >= frame.Length) ? 1 : 0;
                        rtpPacket.Header.PayloadType = payloadType;

                        Buffer.BlockCopy(vp8HeaderBytes, 0, rtpPacket.Payload, 0, vp8HeaderBytes.Length);
                        Buffer.BlockCopy(frame, offset, rtpPacket.Payload, vp8HeaderBytes.Length, payloadLength);

                        byte[] rtpBytes = rtpPacket.GetBytes();

                        if (RtpProtect != null)
                        {
                            rtpBytes = RtpProtect(rtpBytes);
                        }

                        //System.Diagnostics.Debug.WriteLine(" offset " + (index * RTP_MAX_PAYLOAD) + ", payload length " + payloadLength + ", sequence number " + rtpPacket.Header.SequenceNumber + ", marker " + rtpPacket.Header .MarkerBit + ".");

                        //Stopwatch sw = new Stopwatch();
                        //sw.Start();

                        // _rtpSocket.SendTo(rtpBytes, rtpBytes.Length, SocketFlags.None, _remoteEndPoint);

                        //SocketAsyncEventArgs socketSendArgs = new SocketAsyncEventArgs();
                        //socketSendArgs.SetBuffer(rtpBytes, 0, rtpBytes.Length);
                        //socketSendArgs.RemoteEndPoint = _remoteEndPoint;
                        //_rtpSocket.SendToAsync(socketSendArgs);

                        _rtpSocket.BeginSendTo(rtpBytes, 0, rtpBytes.Length, SocketFlags.None, _remoteEndPoint, null, null);
                        //sw.Stop();

                        //if (sw.ElapsedMilliseconds > 15)
                        //{
                        //    logger.Warn(" SendVP8Frame offset " + offset + ", payload length " + payloadLength + ", sequence number " + rtpPacket.Header.SequenceNumber + ", marker " + rtpPacket.Header.MarkerBit + ", took " + sw.ElapsedMilliseconds + "ms.");
                        //}
                    }
                }
            }
            catch (Exception excp)
            {
                if (!_closed)
                {
                    logger.Warn("Exception RTSPSession.SendVP8Frame attempting to send to the RTP socket at " + _remoteEndPoint + ". " + excp);

                    if (OnRTPSocketDisconnected != null)
                    {
                        OnRTPSocketDisconnected(_sessionID);
                    }
                }
            }
        }
Example #22
0
		private void Send()
		{
            try
            {
                int payloadSize = RTPPacketSendSize;
                RTPPacket rtpPacket = new RTPPacket(RTPPacketSendSize);
                byte[] rtpBytes = rtpPacket.GetBytes();

                RTPHeader rtpHeader = new RTPHeader();
                rtpHeader.SequenceNumber = (UInt16)65000;  //Convert.ToUInt16(Crypto.GetRandomInt(0, UInt16.MaxValue));
                uint sendTimestamp = uint.MaxValue - 5000;
                uint lastSendTimestamp = sendTimestamp;
                UInt16 lastSeqNum = 0;

                logger.Debug("RTP send stream starting to " + IPSocket.GetSocketString(m_streamEndPoint) + " with payload size " + payloadSize + " bytes.");

                Sending = true;
                m_startRTPSendTime = DateTime.MinValue;
                m_lastRTPSentTime = DateTime.MinValue;
                m_sampleStartSeqNo = rtpHeader.SequenceNumber;

                DateTime lastRTPSendAttempt = DateTime.Now;

                while (m_udpListener != null && !StopListening)
                {
                    // This may be changed by the listener so it needs to be set each iteration.
                    IPEndPoint dstEndPoint = m_streamEndPoint;

                    //logger.Info("Sending RTP packet to " + dstEndPoint.Address + ":"  + dstEndPoint.Port);

                    if (payloadSize != m_rtpPacketSendSize)
                    {
                        payloadSize = m_rtpPacketSendSize;
                        logger.Info("Changing RTP payload to " + payloadSize);
                        rtpPacket = new RTPPacket(RTP_HEADER_SIZE + m_rtpPacketSendSize);
                        rtpBytes = rtpPacket.GetBytes();
                    }

                    try
                    {
                        if (m_startRTPSendTime == DateTime.MinValue)
                        {
                            m_startRTPSendTime = DateTime.Now;
                            rtpHeader.MarkerBit = 0;

                            logger.Debug("RTPSink Send SyncSource=" + rtpPacket.Header.SyncSource + ".");
                        }
                        else
                        {
                            lastSendTimestamp = sendTimestamp;
                            double milliSinceLastSend = DateTime.Now.Subtract(m_lastRTPSentTime).TotalMilliseconds;
                            sendTimestamp = Convert.ToUInt32((lastSendTimestamp + (milliSinceLastSend * TIMESTAMP_FACTOR)) % uint.MaxValue);

                            if (lastSendTimestamp > sendTimestamp)
                            {
                                logger.Error("RTP Sender previous timestamp (" + lastSendTimestamp + ") > timestamp (" + sendTimestamp + ") ms since last send=" + milliSinceLastSend  + ", lastseqnum=" + lastSeqNum + ", seqnum=" + rtpHeader.SequenceNumber + ".");
                            }

                            if (DateTime.Now.Subtract(m_lastRTPSentTime).TotalMilliseconds > 75)
                            {
                                logger.Debug("delayed send: " + rtpHeader.SequenceNumber + ", time since last send " + DateTime.Now.Subtract(m_lastRTPSentTime).TotalMilliseconds + "ms.");
                            }
                        }

                        rtpHeader.Timestamp = sendTimestamp;
                        byte[] rtpHeaderBytes = rtpHeader.GetBytes();
                        Array.Copy(rtpHeaderBytes, 0, rtpBytes, 0, rtpHeaderBytes.Length);

                        // Send RTP packets and any extra channels required to emulate mutliple calls.
                        for (int channelCount = 0; channelCount < m_channels; channelCount++)
                        {
                            //logger.Debug("Send rtp getting wallclock timestamp for " + DateTime.Now.ToString("dd MMM yyyy HH:mm:ss:fff"));
                            //DateTime sendTime = DateTime.Now;
                            //rtpHeader.Timestamp = RTPHeader.GetWallclockUTCStamp(sendTime);
                            //logger.Debug(rtpHeader.SequenceNumber + "," + rtpHeader.Timestamp);

                            m_udpListener.Send(rtpBytes, rtpBytes.Length, dstEndPoint);
                            m_lastRTPSentTime = DateTime.Now;

                            m_packetsSent++;
                            m_bytesSent += rtpBytes.Length;

                            if (m_packetsSent % 500 == 0)
                            {
                                logger.Debug("Total packets sent to " + dstEndPoint.ToString() + " " + m_packetsSent + ", bytes " + NumberFormatter.ToSIByteFormat(m_bytesSent, 2) + ".");
                            }

                            //sendLogger.Info(m_lastRTPSentTime.ToString("dd MMM yyyy HH:mm:ss:fff") + "," + m_lastRTPSentTime.Subtract(m_startRTPSendTime).TotalMilliseconds.ToString("0") + "," + rtpHeader.SequenceNumber + "," + rtpBytes.Length);

                            //sendLogger.Info(rtpHeader.SequenceNumber + "," + DateTime.Now.ToString("dd MMM yyyy HH:mm:ss:fff"));

                            if (DataSent != null)
                            {
                                try
                                {
                                    DataSent(m_streamId, rtpBytes, dstEndPoint);
                                }
                                catch (Exception excp)
                                {
                                    logger.Error("Exception RTPSink DataSent. " + excp.Message);
                                }
                            }

                            lastSeqNum = rtpHeader.SequenceNumber;
                            if (rtpHeader.SequenceNumber == UInt16.MaxValue)
                            {
                                //logger.Debug("RTPSink looping  the sequence number in sample.");
                                rtpHeader.SequenceNumber = 0;
                            }
                            else
                            {
                                rtpHeader.SequenceNumber++;
                            }
                        }
                    }
                    catch (Exception excp)
                    {
                        logger.Error("Exception RTP Send. " + excp.GetType() + ". " + excp.Message);

                        if (excp.GetType() == typeof(SocketException))
                        {
                            logger.Error("socket exception errorcode=" + ((SocketException)excp).ErrorCode + ".");
                        }

                        logger.Warn("Remote socket closed on send. Last RTP recevied " + m_lastRTPReceivedTime.ToString("dd MMM yyyy HH:mm:ss") + ", last RTP successfull send " + m_lastRTPSentTime.ToString("dd MMM yyyy HH:mm:ss") + ".");
                    }

                    Thread.Sleep(RTPFrameSize);

                    #region Check for whether the stream has timed out on a send or receive and if so shut down the stream.

                    double noRTPRcvdDuration = (m_lastRTPReceivedTime != DateTime.MinValue) ? DateTime.Now.Subtract(m_lastRTPReceivedTime).TotalSeconds : 0;
                    double noRTPSentDuration = (m_lastRTPSentTime != DateTime.MinValue) ? DateTime.Now.Subtract(m_lastRTPSentTime).TotalSeconds : 0;
                    double testDuration = DateTime.Now.Subtract(m_startRTPSendTime).TotalSeconds;

                    if ((
                        noRTPRcvdDuration > NO_RTP_TIMEOUT || 
                        noRTPSentDuration > NO_RTP_TIMEOUT || 
                        (m_lastRTPReceivedTime == DateTime.MinValue && testDuration > NO_RTP_TIMEOUT)) // If the test request comes from a private or unreachable IP address then no RTP will ever be received. 
                        && StopIfNoData)
                    {
                        logger.Warn("Disconnecting RTP stream on " + m_localEndPoint.Address.ToString() + ":" + m_localEndPoint.Port + " due to not being able to send any RTP for " + NO_RTP_TIMEOUT + "s.");
                        StopListening = true;
                    }

                    // Shutdown the socket even if there is still RTP but the stay alive limit has been exceeded.
                    if (RTPMaxStayAlive > 0 && DateTime.Now.Subtract(m_startRTPSendTime).TotalSeconds > RTPMaxStayAlive)
                    {
                        logger.Warn("Shutting down RTPSink due to passing RTPMaxStayAlive time.");
                        Shutdown();
                        StopListening = true;
                    }

                    #endregion
                }
            }
            catch (Exception excp)
            {
                logger.Error("Exception Send RTPSink: " + excp.Message);
            }
            finally
            {
                #region Shut down socket.

                Shutdown();

                if (SenderClosed != null)
                {
                    try
                    {
                        SenderClosed(m_streamId, m_callDescriptorId);
                    }
                    catch (Exception excp)
                    {
                        logger.Error("Exception RTPSink SenderClosed. " + excp.Message);
                    }
                }

                #endregion
            }
		}