예제 #1
0
        public RtpHeader(RtpHeader other, bool shouldDispose = true)
            : base(shouldDispose)
        {
            First16Bits = new RFC3550.CommonHeaderBits(other.First16Bits, shouldDispose);

            SegmentToLast10Bytes = new Common.MemorySegment(other.SegmentToLast10Bytes, shouldDispose);
        }
예제 #2
0
        /// <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);
            }
        }
예제 #3
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;
        }
예제 #4
0
 /// <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);
     }
 }
예제 #5
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);
     }
 }
예제 #6
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);
        }
예제 #7
0
        /// <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);
        }
예제 #8
0
 /// <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));
 }
예제 #9
0
        /// <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);
        }
예제 #10
0
 public bool Equals(RtpHeader other)
 {
     return(other.First16Bits.Equals(First16Bits)
            &&
            other.SynchronizationSourceIdentifier.Equals(SynchronizationSourceIdentifier));
 }