예제 #1
0
        private const byte PAYLOAD_TYPE_MASK = 0x7F;    // 01111111b

        /// <summary>
        /// Буфер для полезной нагрузки RTP пакетов
        /// </summary>
        //private byte[] buffer = new byte[ushort.MaxValue];

        /// <summary>
        /// Формирует структуру RtpPacket и вызывает событие CreatedRtpPacket
        /// </summary>
        /// <param name="data">Указатель на область памяти
        /// в неуправляемой куче, где содержится RTP пакет</param>
        /// <param name="count">Размер области памяти в байтах</param>
        unsafe public void HandleRtpPacket(IPEndPoint remoteEndPoint, IntPtr data, int count) //IntPtr data, int count)//
        {
            RtpPacket packet = new RtpPacket();

            int  offset    = 0;
            byte firstByte = *(byte *)(data + offset);

            offset++;
            byte secondByte = *(byte *)(data + offset);

            packet.Version      = (byte)(firstByte >> 6);
            packet.Padding      = (firstByte & PADDING_MASK) == PADDING_MASK;
            packet.HasExtension = (firstByte & EXTENSION_MASK) == EXTENSION_MASK;
            packet.CSRCCount    = (byte)(firstByte & CSRCCOUNT_MASK);
            packet.IsMarker     = (secondByte & IS_MARKER_MASK) == IS_MARKER_MASK;
            packet.PayloadType  = (byte)(secondByte & PAYLOAD_TYPE_MASK);
            offset++;
            packet.SequenceNumber = BigEndian.ReadUInt16((void *)(data + offset));
            offset          += 2;
            packet.Timestamp = BigEndian.ReadUInt32((void *)(data + offset));
            offset          += 4;
            packet.SSRC      = BigEndian.ReadUInt32((void *)(data + offset));

            if (packet.SSRC != SSRC)
            {
                return;                      // пакеты другой сессии
            }
            if (packet.HasExtension)
            {
                offset = 12 + packet.CSRCCount * 4 + 0;
                packet.HeaderExtensionProfile = BigEndian.ReadUInt16((void *)(data + offset));
                offset += 2;
                packet.HeaderExtensionLength = BigEndian.ReadUInt16((void *)(data + offset));
                offset += 2;
                packet.HeaderExtension = data + offset;
                offset += packet.HeaderExtensionLength;
                packet.PayloadLength = count - offset;
                packet.Payload       = data + offset;
            }
            else
            {
                offset = 12 + packet.CSRCCount * 4 + 0;
                packet.HeaderExtensionProfile = 0;
                packet.HeaderExtensionLength  = 0;
                packet.HeaderExtension        = IntPtr.Zero;
                packet.PayloadLength          = count - offset;
                packet.Payload = data + offset;
            }

            RtpPacketRecieved(packet);
        }
예제 #2
0
        /// <summary>
        /// Обрабатывает пришедшие данные и вызывает всякие события
        /// </summary>
        /// <param name="data">Указатель область памяти,
        /// где располагаются данные RTCP пакета</param>
        /// <param name="count">Размер области памяти в байтах</param>
        public void CreateRtcpPacket(IntPtr data, int count)
        {
            Marshal.Copy(data, buffer, 0, count);
            // сейчас в массиве buffer содержится один или более RTCP пакетов
            // их нужно обработать в цикле
            // сначала обрабатывается первый пакет, который находится в начале
            // буфера, потом данные в буфере сдвигаются к началу, и т. д.,
            // пока не будут обработаны все пакеты
            while (count > 0)
            {
                int version = buffer[0] >> 6;
                if (version != 2)
                {
                    return;
                }
                bool           padding    = (buffer[0] & _00100000) == _00100000;
                RtcpPacketType packetType = (RtcpPacketType)buffer[1];
                int            length     = (BigEndian.ReadUInt16(buffer, 2) + 1) * 4;

                switch (packetType)
                {
                case RtcpPacketType.SenderReport:
                    RtcpSenderReportPacket packet = new RtcpSenderReportPacket();
                    packet.Version = (byte)(buffer[0] >> 6);
                    packet.Padding = ((buffer[0] & _00100000) == _00100000);
                    packet.ReceptionReportCount = (byte)(buffer[0] & _00011111);
                    packet.PayloadType          = RtcpPacketType.SenderReport;
                    packet.SenderSSRC           = BigEndian.ReadUInt32(buffer, 4);
                    packet.TimestampMSW         = BigEndian.ReadUInt32(buffer, 8);
                    packet.TimestampLSW         = BigEndian.ReadUInt32(buffer, 12);
                    packet.RTPTimestamp         = BigEndian.ReadUInt32(buffer, 16);
                    packet.SenderPacketCount    = BigEndian.ReadUInt32(buffer, 20);
                    packet.SenderOctetCount     = BigEndian.ReadUInt32(buffer, 24);
                    CreatedRtcpSenderReport(packet);
                    break;

                case RtcpPacketType.ReceiverReport:
                    // ничего не делать, т. к. нам не будут приходить пакеты такого типа
                    break;

                case RtcpPacketType.SourceDescription:
                    // прочитать количество источников
                    int sourceCount = buffer[0] & _00011111;
                    int pos         = 4;

                    RtcpSourceDescription[] result = new RtcpSourceDescription[sourceCount];

                    for (int i = 0; i < sourceCount; i++)
                    {
                        result[i]      = new RtcpSourceDescription();
                        result[i].SSRC = BigEndian.ReadUInt32(buffer, pos);
                        pos           += 4;
                        List <RtcpSourceDescriptionItem> items = new List <RtcpSourceDescriptionItem>();
                        while (buffer[pos] != 0)
                        {
                            RtcpSourceDescriptionType type = (RtcpSourceDescriptionType)buffer[pos];
                            pos += 1;
                            int itemLength = buffer[pos];
                            pos += 1;
                            string itemText = Encoding.UTF8.GetString(buffer, pos, itemLength);
                            pos += itemLength;
                            items.Add(new RtcpSourceDescriptionItem()
                            {
                                Type = type,
                                Text = itemText
                            });
                        }
                        result[i].Items = items.ToArray();

                        // выравниваем по 4 байтам
                        while (pos % 4 != 0)
                        {
                            pos++;
                        }
                    }

                    CreatedRtcpSourceDescription(result);
                    break;

                case RtcpPacketType.Goodbye:
                    // ничего не делать
                    break;

                case RtcpPacketType.ApplicationDefined:
                    // ничего не делать
                    break;
                }
                // смещаем оставшиеся данные в буфере к началу
                for (int i = length; i < count; i++)
                {
                    buffer[i - length] = buffer[i];
                    buffer[i]          = 0;
                }
                count -= length;
            }
        }