Пример #1
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;
            }
        }
Пример #2
0
        /// <summary>
        /// RTP Payload Format for JPEG-compressed Video
        /// http://tools.ietf.org/html/rfc2435
        /// </summary>
        /// <param name="packet">RTP пакет для обработки</param>
        unsafe override public void HandleRtpPacket(RtpPacket packet)
        {
            int payloadLength = packet.PayloadLength;

            int offset = 0;

            byte typeSpecific = *(byte *)(packet.Payload + offset);

            offset++;

            int fragmentOffset = BigEndian.ReadInt24((byte *)(packet.Payload + offset));

            offset += 3;

            if (expectingOffset != fragmentOffset)
            {
                corrupted = true;
            }

            byte type = *(byte *)(packet.Payload + offset);

            offset++;

            byte q = *(byte *)(packet.Payload + offset);

            offset++;

            ushort width = (ushort)((*(byte *)(packet.Payload + offset)) * 8);

            offset++;

            ushort height = (ushort)((*(byte *)(packet.Payload + offset)) * 8);

            offset++;

            if (type >= 64 && type <= 127)
            {
                offset += 4;
            }

            byte   qmbz = 0, qprecizion = 0;
            ushort qlength = 0;

            if (q >= 128 && q <= 255 && fragmentOffset == 0)
            {
                qmbz = *(byte *)(packet.Payload + offset);
                offset++;

                qprecizion = *(byte *)(packet.Payload + offset);
                offset++;

                qlength = BigEndian.ReadUInt16((void *)(packet.Payload + offset));
                offset += 2;

                if (qlength == 128)
                {
                    BigEndian.WriteUInt16(buffer, HEIGHT_OFFSET, height);
                    BigEndian.WriteUInt16(buffer, WIDTH_OFFSET, width);

                    Marshal.Copy(packet.Payload + offset, buffer, QUANT_1_OFFSET, 64);
                    offset += 64;

                    Marshal.Copy(packet.Payload + offset, buffer, QUANT_2_OFFSET, 64);
                    offset += 64;
                }
            }

            int jpgLength = payloadLength - offset;

            Marshal.Copy(packet.Payload + offset, buffer, DATA_OFFSET + fragmentOffset, jpgLength);
            bufferOffset = DATA_OFFSET + fragmentOffset + jpgLength;

            expectingOffset = fragmentOffset + jpgLength;

            if (packet.IsMarker)
            {
                if (!corrupted)
                {
                    IntPtr jpg = Marshal.AllocHGlobal(bufferOffset);
                    Marshal.Copy(buffer, 0, jpg, bufferOffset);

                    currentPacketTimeStamp = packet.Timestamp;

                    if (currentPacketTimeStamp <= lastPacketTimeStamp)
                    {
                        Logger.Write(String.Format("{0}<={1}", currentPacketTimeStamp, lastPacketTimeStamp), EnumLoggerType.DebugLog);
                    }

                    OnFrameReceived(jpg, bufferOffset, true, packet.Timestamp);

                    lastPacketTimeStamp = currentPacketTimeStamp;

                    Marshal.FreeHGlobal(jpg);
                }
                corrupted       = false;
                expectingOffset = 0;
            }
        }