Ejemplo n.º 1
0
        public virtual int CompleteFrom(System.Net.Sockets.Socket socket, 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, ABS is weird and not required since paycount is checked to be less
                octetsRemaining = sourceListOctets - payloadCount; //Binary.Abs(payloadCount - sourceListOctets);

                //octetsRemaining = Binary.Min(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 = 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 = 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 && false == 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 = 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)
            {
                //Double check this math
                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 = 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 MemorySegment(m_OwnedOctets, Payload.Offset, m_OwnedOctets.Length);

            //RtpPacket is complete

            return(recieved);
        }
Ejemplo n.º 2
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 includePayloadData, bool selfReference, bool shouldDispose = true)
        {
            //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 && includePadding && includePayloadData)
            {
                return selfReference ? new RtpPacket(Header, Payload, shouldDispose)
                       {
                           Transferred = Transferred
                       }
            }
            : new RtpPacket(Prepare().ToArray(), 0, Length, shouldDispose)
            {
                Transferred = Transferred
            };

            IEnumerable <byte> binarySequence = MemorySegment.EmptyBytes;

            bool hasSourceList = ContributingSourceCount > 0;

            //If the source list is included then include it.
            if (includeSourceList && hasSourceList)
            {
                RFC3550.SourceList sourceList = GetSourceList();

                if (false.Equals(IDisposedExtensions.IsNullOrDisposed(sourceList)))
                {
                    binarySequence = sourceList.GetBinaryEnumerable();
                }
                else
                {
                    binarySequence = 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 (false.Equals(IDisposedExtensions.IsNullOrDisposed(extension)))
                    {
                        binarySequence = binarySequence.Concat(extension);
                    }
                }
            }

            //if the video data is required in the clone then include it
            if (includePayloadData)
            {
                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, shouldDispose)
            {
                Transferred = Transferred
            });
        }