public RtpHeader(RtpHeader other, bool shouldDispose = true) : base(shouldDispose) { First16Bits = new RFC3550.CommonHeaderBits(other.First16Bits, shouldDispose); SegmentToLast10Bytes = new Common.MemorySegment(other.SegmentToLast10Bytes, shouldDispose); }
/// <summary> /// Creates a RtpPacket instance by copying data from the given buffer at the given offset. /// </summary> /// <param name="buffer">The buffer which contains the binary RtpPacket to decode</param> /// <param name="offset">The offset to start copying</param> public RtpPacket(byte[] buffer, int offset, int count) { if (buffer == null || buffer.Length == 0) { throw new ArgumentException("Must have data in a RtpPacket"); } //Read the header Header = new RtpHeader(buffer, offset); ShouldDispose = m_OwnsHeader = true; if (count > RtpHeader.Length && !Header.IsCompressed) { //Advance the pointer offset += RtpHeader.Length; count -= RtpHeader.Length; m_OwnedOctets = new byte[count]; Array.Copy(buffer, offset, m_OwnedOctets, 0, count); //Create a segment to the payload deleniated by the given offset and the constant Length of the RtpHeader. Payload = new MemorySegment(m_OwnedOctets, 0, count); } else { m_OwnedOctets = Media.Common.MemorySegment.EmptyBytes; //IsReadOnly should be false //Payload = new MemoryReference(m_OwnedOctets, 0, 0, m_OwnsHeader); Payload = new MemorySegment(0); } }
/// <summary> /// Creates a RtpPacket instance from an existing RtpHeader and payload. /// Check the IsValid property to see if the RtpPacket is well formed. /// </summary> /// <param name="header">The existing RtpHeader</param> /// <param name="payload">The data contained in the payload</param> public RtpPacket(RtpHeader header, MemorySegment payload, bool ownsHeader = true) { if (header == null) { throw new ArgumentNullException("header"); } Header = header; ShouldDispose = m_OwnsHeader = ownsHeader; Payload = payload; }
/// <summary> /// Creates an exact copy of the RtpHeader from the given RtpHeader /// </summary> /// <param name="other">The RtpHeader to copy</param> /// <param name="reference">A value indicating if the RtpHeader given should be referenced or copied.</param> public RtpHeader(RtpHeader other, bool reference) { if (reference) { First16Bits = other.First16Bits; Last10Bytes = other.Last10Bytes; PointerToLast10Bytes = other.PointerToLast10Bytes; } else { First16Bits = new Media.RFC3550.CommonHeaderBits(other.First16Bits); Last10Bytes = new byte[10]; PointerToLast10Bytes = new Common.MemorySegment(Last10Bytes, 0, 10); other.Last10Bytes.CopyTo(Last10Bytes, 0); } }
public RtpHeader(RtpHeader other, bool reference, bool shouldDispose = true) : base(shouldDispose) { if (reference) { First16Bits = other.First16Bits; Last10Bytes = other.Last10Bytes; SegmentToLast10Bytes = other.SegmentToLast10Bytes; } else { First16Bits = new Media.RFC3550.CommonHeaderBits(other.First16Bits); Last10Bytes = new byte[10]; SegmentToLast10Bytes = new Common.MemorySegment(Last10Bytes, 0, 10); other.Last10Bytes.CopyTo(Last10Bytes, 0); } }
public override bool Equals(object obj) { if (System.Object.ReferenceEquals(this, obj)) { return(true); } if (!(obj is RtpHeader)) { return(false); } RtpHeader other = obj as RtpHeader; return(other.First16Bits == First16Bits && other.SynchronizationSourceIdentifier == SynchronizationSourceIdentifier); }
/// <summary> /// Creates a RtpPacket instance by projecting the given sequence to an array which is subsequently owned by the instance. /// </summary> /// <param name="header">The header to utilize. When Dispose is called this header will be diposed.</param> /// <param name="octets">The octets to project</param> public RtpPacket(RtpHeader header, IEnumerable <byte> octets, bool ownsHeader = true) { if (header == null) { throw new ArgumentNullException("header"); } //Assign the header (maybe referenced elsewhere, when dispose is called the given header will be disposed.) Header = header; ShouldDispose = m_OwnsHeader = ownsHeader; //Project the octets in the sequence m_OwnedOctets = octets.ToArray(); //The Payload property must be assigned otherwise the properties will not function in the instance. Payload = new MemorySegment(m_OwnedOctets, 0, m_OwnedOctets.Length); }
/// <summary> /// Generates a sequence of bytes containing the RtpHeader and any data contained in Payload. /// (Including the SourceList and RtpExtension if present) /// </summary> /// <param name="other">The optional other RtpHeader to utilize in the preperation</param> /// <returns>The sequence created.</returns> public IEnumerable <byte> Prepare(RtpHeader other = null) { return(Enumerable.Concat <byte>(other ?? Header, Payload.Count > 0 ? Payload.Array.Skip(Payload.Offset).Take(Payload.Count) : Media.Common.MemorySegment.EmptyBytes)); }
/// <summary> /// Given a packet using the redundant audio format, the expanded rtp packets are derived from the contents. /// </summary> /// <param name="packet"></param> /// <param name="shouldDispose"></param> /// <returns></returns> public static System.Collections.Generic.IEnumerable <RtpPacket> GetPackets(RtpPacket packet, bool shouldDispose = true) { if (Common.IDisposedExtensions.IsNullOrDisposed(packet)) { yield break; } int headerOctets = packet.HeaderOctets, offset = packet.Payload.Offset + headerOctets, startOffset = offset, remaining = packet.Payload.Count - (headerOctets + packet.PaddingOctets), endHeaders = remaining, headersContained = 0; //If there are not enough bytes for the profile header break. if (remaining < Common.Binary.BytesPerInteger) { yield break; } byte toCheck; //Iterare from the offset of the end of the rtp header until the end of data in the payload while (remaining >= Common.Binary.BytesPerInteger) { // 0 1 2 3 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 //+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ //|F| block PT | timestamp offset | block length | //+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ toCheck = packet.Payload.Array[offset]; //Check for (F)irst bit if ((toCheck & 0x80) != 0) { //Store the offset of the last header. endHeaders = offset; //This byte does not belong to the data. --remaining; break; } //Increment for the header contained. ++headersContained; //Decrement for the header read. remaining -= Common.Binary.BytesPerInteger; //Move by 4 bytes beause the size of the header is 4 bytes. offset += Common.Binary.BytesPerInteger; } //Nothing more to return if (remaining < 0) { yield break; } Common.MemorySegment tempPayload; Rtp.RtpHeader tempHeader; RtpPacket tempResult; int tempPayloadType, tempTimestamp, tempBlockLen; bool marker = packet.Marker; //Start at the offset in bits of the end of header. if (headersContained > 0) { for (int headOffset = startOffset, i = 0, bitOffset = Common.Binary.BytesToBits(ref headOffset); i < headersContained; ++i) { //Read the payloadType out of the header tempPayloadType = (int)Common.Binary.ReadBitsMSB(packet.Payload.Array, Common.Binary.BytesToBits(ref headOffset) + 1, 7); //Read the timestamp offset from the header tempTimestamp = (int)Common.Binary.ReadBitsMSB(packet.Payload.Array, ref bitOffset, 10); //Read the blockLength from the header tempBlockLen = (int)Common.Binary.ReadBitsMSB(packet.Payload.Array, ref bitOffset, 14); //If there are less bytes in the payload than remain in the block stop //if (remaining < tempBlockLen) break; //Get the payload Common.MemorySegment payload = new Common.MemorySegment(packet.Payload.Array, Common.Binary.BitsToBytes(ref bitOffset), tempBlockLen, shouldDispose); //Create the header Rtp.RtpHeader header = new RtpHeader(packet.Version, false, false, marker, tempPayloadType, 0, packet.SynchronizationSourceIdentifier, packet.SequenceNumber, packet.Timestamp + tempTimestamp, shouldDispose); //Create the packet RtpPacket result = new RtpPacket(header, payload, shouldDispose); //Return the packet yield return(result); //Move the offset bitOffset += Common.Binary.BytesToBits(ref tempBlockLen); //Remove the blockLength from the count remaining -= tempBlockLen; } } //If there is anymore data it's values are defined in the header of the given packet. //Read the payloadType out of the headers area (1 bit after the end of headers) 7 bits in size tempPayloadType = (int)Common.Binary.ReadBitsMSB(packet.Payload.Array, Common.Binary.BytesToBits(ref startOffset) + 1, 7); //Get the payload of the temp packet, the blockLen is given by the count in this packet minus the tempPayload = new Common.MemorySegment(packet.Payload.Array, endHeaders, remaining, shouldDispose); //Create the header tempHeader = new RtpHeader(packet.Version, false, false, marker, tempPayloadType, 0, packet.SynchronizationSourceIdentifier, packet.SequenceNumber, packet.Timestamp, shouldDispose); //Create the packet tempResult = new RtpPacket(tempHeader, tempPayload, shouldDispose); //Return the packet yield return(tempResult); }
public bool Equals(RtpHeader other) { return(other.First16Bits.Equals(First16Bits) && other.SynchronizationSourceIdentifier.Equals(SynchronizationSourceIdentifier)); }