public override void HandleRtpPacket(RtpPacket packet) { if (packet.IsMarker==false) { if ((Marshal.ReadByte(packet.Payload, 0) == 0 && Marshal.ReadByte(packet.Payload, 1) == 0 && Marshal.ReadByte(packet.Payload, 2) == 1) && (Marshal.ReadByte(packet.Payload, 3) == (byte)0xb6 || Marshal.ReadByte(packet.Payload, 3) == (byte)0xb0)) // начало фрейма {0,0,0,1,b6} или {0,0,0,1,b0} { bufferOffset=0; } isKeyFrame=(((Marshal.ReadByte(packet.Payload, 4) & 0xc0) >> 6) == 0)?true:false; //ключевой кадр Marshal.Copy(packet.Payload, buffer, bufferOffset, packet.PayloadLength); bufferOffset+=packet.PayloadLength; return; } if (packet.IsMarker==true) //последний пакет фрейма { Marshal.Copy(packet.Payload, buffer, bufferOffset, packet.PayloadLength); bufferOffset += packet.PayloadLength; IntPtr ptr = Marshal.AllocHGlobal(bufferOffset); Marshal.Copy(buffer, 0, ptr, bufferOffset); OnFrameReceived(ptr, bufferOffset, isKeyFrame, packet.Timestamp); Marshal.FreeHGlobal(ptr); return; } }
//public event AudioDataReceivedHandler AudioDataReceived; //public delegate void AudioDataReceivedHandler(byte [] data); //G711Decoder g711Decoder = new G711Decoder(); public override void HandleRtpPacket(RtpPacket packet) { //int length = packet.PayloadLength; //byte[] payload = new byte[length]; //Marshal.Copy(packet.Payload, payload, 0, length); //byte[] outWav = g711Decoder.Decode(payload); //AudioDataReceived(outWav); OnFrameReceived(packet.Payload, packet.PayloadLength, false, packet.Timestamp); }
/// <summary> /// Обрабатывает RTP пакет с видео или звуком /// </summary> /// <param name="packet">RTP пакет с видео или звуком</param> public void HandleRtpPacket(RtpPacket packet) { lock (locker) { if (initTimestamp == 0) { initTimestamp = packet.Timestamp; } if (senderSSRC == 0) { senderSSRC = packet.SSRC; } if (receivedRtpPackets != 0) { if (packet.Timestamp != prevRtpTimestamp) { DateTime time = DateTime.Now; uint timestamp = packet.Timestamp; DateTime rtpTime = startRtpSessionTime + TimeSpan.FromMilliseconds((double)(timestamp - initTimestamp) * 1000 / (double)sampleFrequency); OnRtpTimeReporting(rtpTime); double reciever = (time - prevRtpTime).TotalSeconds; double sender = (double)(timestamp - prevRtpTimestamp) / (double)sampleFrequency; jitter += (1.0 / 16.0) * (Math.Abs(reciever - sender) - jitter); prevRtpTime = time; prevRtpTimestamp = timestamp; } } else { prevRtpTime = DateTime.Now; prevRtpTimestamp = packet.Timestamp; } receivedRtpPackets++; } }
/// <summary> /// RTP Payload Format for JPEG-compressed Video /// http://tools.ietf.org/html/rfc2435 /// </summary> /// <param name="packet">RTP пакет для обработки</param> public unsafe override 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; } }
public unsafe override void HandleRtpPacket(RtpPacket packet) { int payloadLength = packet.PayloadLength; if (payloadLength == 0) return; int startSequenceLength = 4; byte* startSequence = stackalloc byte[startSequenceLength]; startSequence[0] = 0; startSequence[1] = 0; startSequence[2] = 0; startSequence[3] = 1; byte firstByte = *(byte*)(packet.Payload + 0); byte unitType = (byte)(firstByte & 0x1f); if (unitType >= 1 && unitType <= 23)// не фрагметнированный пакет как правило AUD, SPS, PPS, SEI, { Marshal.Copy((IntPtr)startSequence, buffer, bufferOffset, startSequenceLength); bufferOffset += startSequenceLength;//startSequence.Length; Marshal.Copy(packet.Payload, buffer, bufferOffset, payloadLength); bufferOffset += payloadLength; return; } if (unitType == 28) // фрагментированный пакет FU-A (IDR, non-IDR) { if (payloadLength > 1) { byte secondByte=*(byte*)(packet.Payload + 1); byte startBit = (byte)(secondByte >> 7); byte endBit = (byte)((secondByte & 0x40) >> 6); byte nalUnitType = (byte)(secondByte & 0x1f); // идентификатор пакета int payloadDataOffset = 2;// смещение 2 байта firstByte+secondByte if (startBit == 1 && endBit == 0) //начало фрагмента { Marshal.Copy((IntPtr)startSequence, buffer, bufferOffset, startSequenceLength); bufferOffset += startSequenceLength; buffer[bufferOffset] = (byte)((firstByte & 0xe0) | nalUnitType); bufferOffset++; Marshal.Copy(packet.Payload + payloadDataOffset, buffer, bufferOffset, payloadLength - payloadDataOffset); bufferOffset += payloadLength - payloadDataOffset; return; } if (startBit == 0 && endBit == 0) //середина { Marshal.Copy(packet.Payload + payloadDataOffset, buffer, bufferOffset, payloadLength - payloadDataOffset); bufferOffset += payloadLength - payloadDataOffset; return; } if (startBit == 0 && endBit == 1) //конец { Marshal.Copy(packet.Payload + payloadDataOffset, buffer, bufferOffset, payloadLength - payloadDataOffset); bufferOffset += payloadLength - payloadDataOffset; IntPtr ptr = Marshal.AllocHGlobal(bufferOffset); Marshal.Copy(buffer, 0, ptr, bufferOffset); bool flag = (nalUnitType == 5) ? true : false;// ключевой кадр OnFrameReceived(ptr, bufferOffset, flag, packet.Timestamp); Marshal.FreeHGlobal(ptr); bufferOffset = 0; } } return; } // Эти пакеты приходить не должны !!! if (unitType == 24) // STAP-A { //... Logger.Write(String.Format("STAP-A unitType=={0}",unitType), EnumLoggerType.DebugLog); return; } if (unitType == 29)//FU-B { //... Logger.Write(String.Format("FU-B unitType=={0}", unitType), EnumLoggerType.DebugLog); return; } if (unitType == 25 || unitType == 26 || unitType == 27) // STAP-B ,MTAP-16, MTAP-24 return; if (unitType == 0 || unitType == 30 || unitType == 31) // undefined return; }
public void PlayFromRtpPacket(RtpPacket packet) { PlayFromMemory(packet.Payload, packet.PayloadLength); }
//IntPtr data, int count)// /// <summary> /// Буфер для полезной нагрузки RTP пакетов /// </summary> //private byte[] buffer = new byte[ushort.MaxValue]; /// <summary> /// Формирует структуру RtpPacket и вызывает событие CreatedRtpPacket /// </summary> /// <param name="data">Указатель на область памяти /// в неуправляемой куче, где содержится RTP пакет</param> /// <param name="count">Размер области памяти в байтах</param> public unsafe void HandleRtpPacket(IPEndPoint remoteEndPoint, 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); }
public abstract void HandleRtpPacket(RtpPacket packet);