Esempio n. 1
0
        /// <summary>
        /// Assembles the RtpFrame into a byte[] by combining the ExtensionBytes and Payload of all contained RtpPackets into a single byte array (excluding the RtpHeader)
        /// </summary>
        /// <returns>The byte array containing the assembled frame</returns>
        public virtual IEnumerable <byte> Assemble(bool useExtensions    = false,
                                                   int profileHeaderSize = 0)
        {
            //The sequence
            IEnumerable <byte> sequence = Enumerable.Empty <byte>();

            //Iterate the packets
            foreach (RtpPacket packet in this)
            {
                //Should be handled by derived implementation because it is known if the flags are relevent to the data.
                if (useExtensions && packet.Extension)
                {
                    using (RtpExtension extension = packet.GetExtension())
                    {
                        if (extension != null)
                        {
                            /*if (extension.IsComplete) */
                            sequence = sequence.Concat(extension.Data);
                        }
                    }
                }

                //Should chyeck PayloadData is > profileHeaderSize ?

                sequence = sequence.Concat(packet.PayloadData.Skip(profileHeaderSize));
            }

            return(sequence);
        }
Esempio n. 2
0
        public virtual int CompleteFrom(System.Net.Sockets.Socket socket, Common.MemorySegment buffer)
        {
            if (IsReadOnly)
            {
                throw new InvalidOperationException("Cannot modify a RtpPacket when IsReadOnly is false.");
            }

            //If the packet is complete then return
            if (IsDisposed || IsComplete)
            {
                return(0);
            }

            // Cache the size of the original payload
            int payloadCount     = Payload.Count,
                octetsRemaining  = payloadCount,                                    //Cache how many octets remain in the payload
                offset           = Payload.Offset,                                  //Cache the offset in parsing
                sourceListOctets = ContributingSourceListOctets,                    //Cache the amount of octets required in the ContributingSourceList.
                extensionSize    = Header.Extension ? RtpExtension.MinimumSize : 0, //Cache the amount of octets required to read the ExtensionHeader
                recieved         = 0;

            //If the ContributingSourceList is not complete
            if (payloadCount < sourceListOctets)
            {
                //Calulcate the amount of octets to receive
                octetsRemaining = Math.Abs(payloadCount - sourceListOctets);

                //Allocte the memory for the required data
                if (m_OwnedOctets == null)
                {
                    m_OwnedOctets = new byte[octetsRemaining];
                }
                else
                {
                    m_OwnedOctets = m_OwnedOctets.Concat(new byte[octetsRemaining]).ToArray();
                }

                System.Net.Sockets.SocketError error;

                //Read from the stream, decrementing from octetsRemaining what was read.
                while (octetsRemaining > 0)
                {
                    //Receive octetsRemaining or less
                    int justReceived = Media.Common.Extensions.Socket.SocketExtensions.AlignedReceive(m_OwnedOctets, offset, octetsRemaining, socket, out error);

                    //Move the offset
                    offset += justReceived;

                    //Decrement how many octets were receieved
                    octetsRemaining -= justReceived;

                    recieved += justReceived;
                }
            }

            //At the end of the sourceList
            offset = sourceListOctets;

            //ContribuingSourceList is now Complete

            //If there is a RtpExtension indicated by the RtpHeader
            if (Header.Extension)
            {
                //Determine if the extension header was read
                octetsRemaining = RtpExtension.MinimumSize - (payloadCount - offset);

                //If the extension header is not yet read
                if (octetsRemaining > 0)
                {
                    //Allocte the memory for the extension header
                    if (m_OwnedOctets == null)
                    {
                        m_OwnedOctets = new byte[octetsRemaining];
                    }
                    else
                    {
                        m_OwnedOctets = m_OwnedOctets.Concat(new byte[octetsRemaining]).ToArray();
                    }

                    System.Net.Sockets.SocketError error;

                    //Read from the socket, decrementing from octetsRemaining what was read.
                    while (octetsRemaining > 0)
                    {
                        //Receive octetsRemaining or less
                        int justReceived = Media.Common.Extensions.Socket.SocketExtensions.AlignedReceive(m_OwnedOctets, offset, octetsRemaining, socket, out error);

                        //Move the offset
                        offset += justReceived;

                        //Decrement how many octets were receieved
                        octetsRemaining -= justReceived;

                        recieved += justReceived;
                    }
                }

                //at least 4 octets are now present in Payload @ Payload.Offset

                //Use a RtpExtension instance to read the Extension Header and data.
                using (RtpExtension extension = GetExtension())
                {
                    if (extension != null && !extension.IsComplete)
                    {
                        //Cache the size of the RtpExtension (not including the Flags and LengthInWords [The Extension Header])
                        extensionSize = extension.Size - RtpExtension.MinimumSize;

                        //The amount of octets required for for completion are indicated by the Size property of the RtpExtension.
                        //Calulcate the amount of octets to receive
                        octetsRemaining = (payloadCount - offset) - RtpExtension.MinimumSize;

                        if (octetsRemaining > 0 && octetsRemaining < extensionSize)
                        {
                            //Allocte the memory for the required data
                            if (m_OwnedOctets == null)
                            {
                                m_OwnedOctets = new byte[octetsRemaining];
                            }
                            else
                            {
                                m_OwnedOctets = m_OwnedOctets.Concat(new byte[octetsRemaining]).ToArray();
                            }

                            System.Net.Sockets.SocketError error;

                            //Read from the stream, decrementing from octetsRemaining what was read.
                            while (octetsRemaining > 0)
                            {
                                //Receive octetsRemaining or less
                                int justReceived = Media.Common.Extensions.Socket.SocketExtensions.AlignedReceive(m_OwnedOctets, offset, octetsRemaining, socket, out error);

                                //Move the offset
                                offset += justReceived;

                                //Decrement how many octets were receieved
                                octetsRemaining -= justReceived;

                                recieved += justReceived;
                            }
                        }
                    }
                }
            }

            //RtpExtension is now Complete

            //If the header indicates the payload has padding
            if (Header.Padding)
            {
                octetsRemaining = PaddingOctets - payloadCount;

                if (octetsRemaining > 0)
                {
                    //Allocte the memory for the required data
                    if (m_OwnedOctets == null)
                    {
                        m_OwnedOctets = new byte[octetsRemaining];
                    }
                    else
                    {
                        m_OwnedOctets = m_OwnedOctets.Concat(new byte[octetsRemaining]).ToArray();
                    }

                    offset = payloadCount;

                    //If the amount of bytes read in the padding is NOT equal to the last byte in the segment the RtpPacket is NOT complete
                    while (octetsRemaining > 0)
                    {
                        System.Net.Sockets.SocketError error;

                        //Receive 1 byte
                        //Receive octetsRemaining or less
                        int justReceived = Media.Common.Extensions.Socket.SocketExtensions.AlignedReceive(m_OwnedOctets, offset, octetsRemaining, socket, out error);

                        //Move the offset
                        offset += justReceived;

                        recieved += justReceived;

                        octetsRemaining -= justReceived;
                    }
                }
            }

            //Padding is now complete

            //Re allocate the payload segment to include any completed data
            Payload = new Common.MemorySegment(m_OwnedOctets, Payload.Offset, m_OwnedOctets.Length);

            //RtpPacket is complete

            return(recieved);
        }
Esempio n. 3
0
        /// <summary>
        /// Provides the logic for cloning a RtpPacket instance.
        /// The RtpPacket class does not have a Copy Constructor because of the variations in which a RtpPacket can be cloned.
        /// </summary>
        /// <param name="includeSourceList">Indicates if the SourceList should be copied.</param>
        /// <param name="includeExtension">Indicates if the Extension should be copied.</param>
        /// <param name="includePadding">Indicates if the Padding should be copied.</param>
        /// <param name="selfReference">Indicates if the new instance should reference the data contained in this instance.</param>
        /// <returns>The RtpPacket cloned as result of calling this function</returns>
        public RtpPacket Clone(bool includeSourceList, bool includeExtension, bool includePadding, bool includeCoeffecients, bool selfReference)
        {
            //Get the bytes which correspond to the header
            IEnumerable <byte> binarySequence = Enumerable.Empty <byte>();

            //If the sourcelist and extensions are to be included and selfReference is true then return the new instance using the a reference to the data already contained.
            if (includeSourceList && includeExtension && selfReference)
            {
                return(new RtpPacket(Header.Clone(), Payload));
            }

            bool hasSourceList = ContributingSourceCount > 0;

            //If the source list is included then include it.
            if (includeSourceList && hasSourceList)
            {
                var sourceList = GetSourceList();
                if (sourceList != null)
                {
                    binarySequence = GetSourceList().AsBinaryEnumerable();
                }
                else
                {
                    binarySequence = Media.Common.MemorySegment.EmptyBytes;
                }
            }

            //Determine if the clone should have extenison
            bool hasExtension = Header.Extension;

            //If there is a header extension to be included in the clone
            if (hasExtension && includeExtension)
            {
                //Get the Extension
                using (RtpExtension extension = GetExtension())
                {
                    //If an extension could be obtained include it
                    if (extension != null)
                    {
                        binarySequence = binarySequence.Concat(extension);
                    }
                }
            }

            //if the video data is required in the clone then include it
            if (includeCoeffecients)
            {
                binarySequence = binarySequence.Concat(PayloadData);                      //Add the binary data to the packet except any padding
            }
            //Determine if padding is present
            bool hasPadding = Header.Padding;

            //if padding is to be included in the clone then obtain the original padding directly from the packet
            if (hasPadding && includePadding)
            {
                binarySequence = binarySequence.Concat(Payload.Array.Skip(Payload.Offset + Payload.Count - PaddingOctets));                               //If just the padding is required the skip the Coefficients
            }
            //Return the result of creating the new instance with the given binary
            return(new RtpPacket(new RtpHeader(Header.Version, includePadding && hasPadding, includeExtension && hasExtension)
            {
                Timestamp = Header.Timestamp,
                SequenceNumber = Header.SequenceNumber,
                SynchronizationSourceIdentifier = Header.SynchronizationSourceIdentifier,
                PayloadType = Header.PayloadType,
                ContributingSourceCount = includeSourceList ? Header.ContributingSourceCount : 0
            }.Concat(binarySequence).ToArray(), 0)
            {
                Transferred = this.Transferred
            });
        }