Пример #1
0
        public void SendMidiMessage(MidiMessage message, long timestamp)
        {
            sequenceNumber++;
            long      currentTimeIn100Microseconds = RtpMidiSession.GetCurrentTimestamp();
            int       rtpTimestamp = ((int)currentTimeIn100Microseconds);
            RtpHeader rtpHeader    =
                new RtpHeader((byte)2, false, false, (byte)0, false, (byte)97, sequenceNumber, rtpTimestamp, Ssrc);

            Log.Debug("RtpMidi", "Sending RTP-Header: {}", rtpHeader);
            bool b = message.Length > 15;
            MidiCommandHeader midiCommandHeader =
                new MidiCommandHeader(b, false, false, false, (short)message.Length, rtpHeader);
            var commandCol = new List <MidiTimestampPair>();

            commandCol.Add(new MidiTimestampPair(0, message));
            RtpMidiMessage rtpMidiMessage = new RtpMidiMessage(midiCommandHeader, commandCol);

            try
            {
                RtpMidiMessageSender.Send(rtpMidiMessage, RtpMidiServer);
            }
            catch (IOException e)
            {
                Log.Error("RtpMidi", "Error sending MidiMessage to {}", RtpMidiServer, e);
            }
        }
Пример #2
0
        public void TestRtpHeader()
        {
            EndianReader reader = new EndianReader(ResourcesProvider.GetBytes("tcp_control_handshake.bin", ResourceType.Nano));
            RtpHeader    header = new RtpHeader();

            header.Deserialize(reader);

            Assert.NotNull(header);
            Assert.True(header.Padding);
            Assert.False(header.Extension);
            Assert.Equal <int>(0, header.CsrcCount);
            Assert.False(header.Marker);
            Assert.Equal <NanoPayloadType>(NanoPayloadType.ControlHandshake, header.PayloadType);
            Assert.Equal <ushort>(0, header.SequenceNumber);
            Assert.Equal <uint>(2847619159, header.Timestamp);
            Assert.Equal <ushort>(0, header.ConnectionId);
            Assert.Equal <ushort>(0, header.ChannelId);
        }
Пример #3
0
        public void Handle(byte[] data, RtpMidiServer rtpMidiServer)
        {
            DataInputStream dataInputStream = new DataInputStream(new MemoryStream(data));
            byte            header1         = (byte)dataInputStream.ReadByte();
            byte            version         = (byte)((header1 >> 6) & 0x03);
            bool            paddingFlag     = ((header1 >> 5) & 0x01) == 1;
            bool            extensionFlag   = ((header1 >> 4) & 0x01) == 1;
            byte            contributingSourceIdentifiersCount = (byte)(header1 & 0x0F);

            byte header2     = (byte)dataInputStream.ReadByte();
            bool markerFlag  = ((header2 >> 7) & 0x01) == 1;
            byte payloadType = (byte)(header2 & 0x7F);

            if (payloadType != RTP_MIDI)
            {
                return;
            }

            short sequenceNumber = dataInputStream.ReadShort();
            int   timestamp      = dataInputStream.ReadInt();
            int   ssrc           = dataInputStream.ReadInt();

            RtpHeader rtpHeader = new RtpHeader(version, paddingFlag, extensionFlag, contributingSourceIdentifiersCount, markerFlag,
                                                payloadType, sequenceNumber, timestamp, ssrc);

            byte midiCommandHeader1 = (byte)dataInputStream.ReadByte();
            bool b = ((midiCommandHeader1 >> 7) & 0x01) == 1;
            bool j = ((midiCommandHeader1 >> 6) & 0x01) == 1;
            bool z = ((midiCommandHeader1 >> 5) & 0x01) == 1;
            bool p = ((midiCommandHeader1 >> 4) & 0x01) == 1;
            // Header 2 octets
            short length;

            if (b)
            {
                byte midiCommandHeader2 = (byte)dataInputStream.ReadByte();
                length = (short)((midiCommandHeader1 << 8 | midiCommandHeader2) & 0x0FFF);
            }
            else
            {
                length = (short)(midiCommandHeader1 & 0x0F);
            }

            MidiCommandHeader midiCommandHeader = new MidiCommandHeader(b, j, z, p, length, rtpHeader);

            byte[] midiCommandBuffer    = new byte[length];
            int    midiCommandBytesRead = dataInputStream.Read(midiCommandBuffer);

            if (((short)midiCommandBytesRead) != length)
            {
                return;
            }

            List <MidiTimestampPair> messages = new List <MidiTimestampPair>();

            try
            {
                DataInputStream midiInputStream = new DataInputStream(new MemoryStream(midiCommandBuffer));
                messages.AddRange(ReadMidiMessages(midiCommandHeader, midiInputStream));
                HandleMessage(new RtpMidiMessage(midiCommandHeader, messages));
            }
            catch (System.IO.IOException e)
            {
                Log.Error("RtpMidi", "IOException while processing MIDI message", e);
            }
        }
Пример #4
0
 public RtpPacket(RtpHeader header)
 {
     Header = header;
 }
Пример #5
0
 public RtpPacket(RtpPayloadType payloadType)
 {
     Header             = new RtpHeader();
     Header.PayloadType = payloadType;
 }
Пример #6
0
 public RtpPacket(RtpPayloadType payloadType, ISerializableLE payload)
 {
     Header             = new RtpHeader();
     Header.PayloadType = payloadType;
     Payload            = payload;
 }
Пример #7
0
 public RtpPacket()
 {
     Header = new RtpHeader();
 }
Пример #8
0
        /// <summary>
        /// Used to handle Tcp framing
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="offset"></param>
        /// <param name="count"></param>
        /// <param name="socket"></param>
        /// <returns></returns>
        protected internal virtual int ProcessFrameData(byte[] buffer, int offset, int count, Socket socket)
        {
            if (count == 0) return 0;

            //If there is no buffer use our own buffer.
            if (buffer == null) buffer = m_Buffer.Array;

            //Determine which TransportContext will receive the data incoming
            TransportContext relevent = null;

            //The channel of the data
            byte frameChannel = 0;

            //Get the length of the given buffer (Should actually use m_Buffer.Count when using our own buffer)
            int bufferLength = buffer.Length,
                //The indicates length of the data
                frameLength = 0,
                //The amount of data remaining in the buffer
                remainingInBuffer = Media.Common.Extensions.Math.MathExtensions.Clamp(count, count, bufferLength - offset),
                //The amount of data received (which is already equal to what is remaining in the buffer)
                recievedTotal = remainingInBuffer;

            //Determine if Rtp or Rtcp is coming in or some other type (could be combined with expectRtcp and expectRtp == false)
            bool expectRtp = false, expectRtcp = false, incompatible = true, raisedEvent = false;

            //If anything remains on the socket the value will be calulcated.
            int remainingOnSocket = 0;

            //TODO handle receiving when no $ and Channel is presenent... e.g. RFC4571
            //Would only be 2 then...

            //if (GetContextBySocket(socket).MediaDescription.MediaProtocol.StartsWith("TCP", StringComparison.OrdinalIgnoreCase))
            //{
            //    //independent = true;
            //}

            int sessionRequired = InterleavedOverhead;

            //While not disposed and there is data remaining (within the buffer)
            while (false == IsDisposed &&
                remainingInBuffer > 0 &&
                offset >= m_Buffer.Offset)
            {
                //Assume not rtp or rtcp and that the data is compatible with the session
                expectRtp = expectRtcp = incompatible = false;

                //If a header can be read
                if (remainingInBuffer >= sessionRequired)
                {
                    //Determine if an event was raised each time there was at least the required amount of data.
                    raisedEvent = false;

                    //Parse the frameLength from the given buffer, take changes to the offset through the function.
                    frameLength = ReadApplicationLayerFraming(remainingInBuffer, out frameChannel, out relevent, ref offset, out raisedEvent, buffer);

                    //If a frame was found (Including the null packet)
                    if (frameLength >= 0)
                    {
                        //If there WAS a context
                        if (relevent != null)
                        {
                            //Verify minimum and maximum packet sizes allowed by context. (taking into account the amount of bytes in the ALF)
                            if (frameLength < relevent.MinimumPacketSize + sessionRequired ||
                                frameLength > relevent.MaximumPacketSize + sessionRequired)
                            {
                                //mark as incompatible
                                incompatible = true;

                                //ToDo
                                //Make CreateLogString function

                                Media.Common.ILoggingExtensions.Log(Logger, ToString() + "@ProcessFrameData - Irregular Packet of " + frameLength + " for Channel " + frameChannel + " remainingInBuffer=" + remainingInBuffer);

                                //jump
                                goto CheckPacketAttributes;
                            }

                            //TODO Independent framing... (e.g. no $)[ only 4 bytes not 6 ]
                            //If all that remains is the frame header then receive more data. 6 comes from (InterleavedOverhead + CommonHeaderBits.Size)
                            //We need more data to be able to verify the frame.
                            if (remainingInBuffer <= 6)
                            {
                                //Remove the context
                                relevent = null;

                                goto CheckRemainingData;

                                ////Only receive this many more bytes for now.
                                //remainingOnSocket = X - remainingInBuffer;

                                ////Receive the rest of the data indicated by frameLength. (Should probably only receive up to X more bytes then make another receive if needed)
                                //goto GetRemainingData;
                            }

                            //Use CommonHeaderBits on the data after the Interleaved Frame Header
                            using (var common = new Media.RFC3550.CommonHeaderBits(buffer[offset + sessionRequired], buffer[offset + sessionRequired + 1]))
                            {
                                //Check the version...
                                incompatible = common.Version != relevent.Version;

                                //If this is a valid context there must be at least a RtpHeader's worth of data in the buffer.
                                //If this was a RtcpPacket with only 4 bytes it wouldn't have a ssrc and wouldn't be valid to be sent.
                                if (false == incompatible &&
                                    (frameChannel == relevent.DataChannel &&
                                    remainingInBuffer <= Rtp.RtpHeader.Length + sessionRequired)
                                    ||
                                    (frameChannel == relevent.ControlChannel &&
                                    remainingInBuffer <= Rtcp.RtcpHeader.Length + sessionRequired))
                                {
                                    //Remove the context
                                    relevent = null;

                                    //Mark as incompatible
                                    incompatible = true;

                                    goto EndUsingHeader;

                                    ////Only receive this many more bytes for now.
                                    //remainingOnSocket = 16 - remainingInBuffer;

                                    ////Receive the rest of the data indicated by frameLength. (Should probably only receive up to 6 more bytes then make another receive if needed)
                                    //goto GetRemainingData;
                                }

                                //Perform a set of checks and set weather or not Rtp or Rtcp was expected.
                                if (false == incompatible)
                                {
                                    //Determine if the packet is Rtcp by looking at the found channel and the relvent control channel
                                    if (frameChannel == relevent.ControlChannel)
                                    {
                                        //Rtcp

                                        if (remainingInBuffer <= sessionRequired + Rtcp.RtcpHeader.Length)
                                        {
                                            //Remove the context
                                            relevent = null;

                                            goto CheckRemainingData;
                                        }

                                        //Store any rtcp length so we can verify its not 0 and then additionally ensure its value is not larger then the frameLength
                                        int rtcpLen;

                                        //use a rtcp header to extract the information in the packet
                                        using (Rtcp.RtcpHeader header = new RtcpHeader(buffer, offset + sessionRequired))
                                        {
                                            //Get the length in 'words' (by adding one)
                                            //A length of 0 means 1 word
                                            //A length of 65535 means only the header (no ssrc [or payload])
                                            ushort lengthInWordsPlusOne = (ushort)(header.LengthInWordsMinusOne + 1);

                                            //Convert to bytes
                                            rtcpLen = lengthInWordsPlusOne * 4;

                                            //Check that the supposed  amount of contained words is greater than or equal to the frame length conveyed by the application layer framing
                                            //it must also be larger than the buffer
                                            incompatible = rtcpLen > frameLength && rtcpLen > bufferLength;

                                            //if rtcpLen >= ushort.MaxValue the packet may possibly span multiple segments unless a large buffer is used.

                                            if (false == incompatible && //It was not already ruled incomaptible
                                                lengthInWordsPlusOne > 0 && //If there is supposed to be SSRC in the packet
                                                header.Size > Rtcp.RtcpHeader.Length && //The header ACTUALLY contains enough bytes to have a SSRC
                                                false == relevent.InDiscovery)//The remote context knowns the identity of the remote stream
                                            {
                                                //Determine if Rtcp is expected
                                                //Perform another lookup and check compatibility
                                                expectRtcp = !(incompatible = (GetContextBySourceId(header.SendersSynchronizationSourceIdentifier)) == null);
                                            }
                                        }
                                    }

                                    //May be mixing channels...
                                    if (false == expectRtcp)
                                    {
                                        //Rtp
                                        if (remainingInBuffer <= sessionRequired + Rtp.RtpHeader.Length)
                                        {
                                            //Remove the context
                                            relevent = null;

                                            goto CheckRemainingData;
                                        }

                                        //the context by payload type is null is not discovering the identity check the SSRC.
                                        if (GetContextByPayloadType(common.RtpPayloadType) == null && false == relevent.InDiscovery)
                                        {
                                            using (Rtp.RtpHeader header = new RtpHeader(buffer, offset + InterleavedOverhead))
                                            {
                                                //The context was obtained by the frameChannel
                                                //Use the SSRC to determine where it should be handled.
                                                //If there is no context the packet is incompatible
                                                expectRtp = !(incompatible = (GetContextBySourceId(header.SynchronizationSourceIdentifier)) == null);

                                                //(Could also check SequenceNumber to prevent duplicate packets from being processed.)

                                                ////Verify extensions (handled by ValidatePacket)
                                                //if (header.Extension)
                                                //{

                                                //}

                                            }
                                        }
                                        else incompatible = false;
                                    }
                                }
                            EndUsingHeader:
                                ;
                            }
                        }

                        //Log state.
                    //if (relevent == null) Media.Common.ILoggingExtensions.Log(Logger, InternalId + "-ProcessFrameData - No Context for Channel " + frameChannel + " frameLength=" + frameLength + " remainingInBuffer=" + remainingInBuffer);
                    //else Media.Common.ILoggingExtensions.Log(Logger, InternalId + "ProcessFrameData " + frameChannel + " frameLength=" + frameLength + " remainingInBuffer=" + remainingInBuffer);

                    CheckPacketAttributes:

                        if (incompatible)
                        {
                            //If there was a context then incrment for failed receptions
                            if (relevent != null)
                            {
                                if (expectRtp) ++relevent.m_FailedRtpReceptions;

                                if (expectRtcp) ++relevent.m_FailedRtcpReceptions;
                            }

                            Media.Common.ILoggingExtensions.Log(Logger, InternalId + "ProcessFrameData - Incompatible Packet frameLength=" + frameLength + " for Channel " + frameChannel + " remainingInBuffer=" + remainingInBuffer);
                        }
                        //If frameLength was 0 or the frame was larger than we can store then interleave the header for handling if required
                        //incompatible may not be true here.
                        else if (frameLength == 0 || frameLength > bufferLength)
                        {
                            //Could check incompatible to determine if to should move further.

                            //Just because there is no assoicated context on the client does not mean the packet is not useful elsewhere in Transport.

                            //TODO It may be possible to let the event reiever known how much is available here.
                            if (frameLength == 0)
                            {
                                Media.Common.ILoggingExtensions.Log(Logger, InternalId + "ProcessFrameData - Null Packet for Channel " + frameChannel + " remainingInBuffer=" + remainingInBuffer);
                            }
                            else //If there was a context then increment for failed receptions only for large packets
                            {
                                if (expectRtp) ++relevent.m_FailedRtpReceptions;

                                if (expectRtcp) ++relevent.m_FailedRtcpReceptions;

                                if (expectRtp || expectRtcp) Media.Common.ILoggingExtensions.Log(Logger, InternalId + "ProcessFrameData - Large Packet of " + frameLength + " for Channel " + frameChannel + " remainingInBuffer=" + remainingInBuffer);
                            }
                        }
                        else goto CheckRemainingData;

                        //The packet was incompatible or larger than the buffer

                        //Determine how much we can move
                        int toMove = Math.Min(remainingInBuffer, sessionRequired);

                        //TODO It may be possible to let the event reiever known how much is available here.

                        //Indicate what was received if not already done
                        if (false == raisedEvent) OnInterleavedData(buffer, offset, toMove);

                        //Move the offset
                        offset += toMove;

                        //Decrease by the length
                        remainingInBuffer -= toMove;

                        //Do another pass
                        continue;

                    }//else there was a frameLength of -1 this indicates there is not enough bytes for a header.
                }
                else//There is not enough data in the buffer as defined by sessionRequired.
                {
                    //unset the frameLength read
                    frameLength = -1;

                    //unset the context read
                    relevent = null;
                }

            //At this point there may be either less sessionRequired or not enough for a complete frame.
            CheckRemainingData:

                //See how many more bytes are required from the wire
                //If the frameLength is less than 0 AND there are less then are sessionRequired remaining in the buffer
                remainingOnSocket = frameLength < 0 && remainingInBuffer < sessionRequired ?
                    sessionRequired - remainingInBuffer //Receive enough to complete the header
                        : //Otherwise if the frameLength larger then what remains in the buffer allow for the buffer to be filled or nothing else remains.
                    frameLength > remainingInBuffer ? frameLength - remainingInBuffer : 0;

                //GetRemainingData:

                //If there is anymore data remaining on the wire
                if (remainingOnSocket > 0)
                {
                    //Align the buffer if anything remains on the socket.
                    Array.Copy(buffer, offset, buffer, m_Buffer.Offset, remainingInBuffer);

                    //Set the correct offset either way.
                    offset = m_Buffer.Offset + remainingInBuffer;

                    //Store the error if any
                    SocketError error = SocketError.SocketError;

                    //Get all the remaining data
                    while (false == IsDisposed && remainingOnSocket > 0)
                    {
                        //Recieve from the wire the amount of bytes required (up to the length of the buffer)
                        int recievedFromWire = socket == null ? 0 : Media.Common.Extensions.Socket.SocketExtensions.AlignedReceive(buffer, offset, remainingOnSocket, socket, out error);

                        //Check for an error and then the allowed continue condition
                        if (error != SocketError.Success && error != SocketError.TryAgain) break;

                        //If nothing was recieved try again.
                        if (recievedFromWire <= 0) continue;

                        //Decrease what is remaining from the wire by what was received
                        remainingOnSocket -= recievedFromWire;

                        //Move the offset
                        offset += recievedFromWire;

                        //Increment received
                        recievedTotal += recievedFromWire;

                        //Incrment remaining in buffer for what was recieved.
                        remainingInBuffer += recievedFromWire;
                    }

                    //If a socket error occured remove the context so no parsing occurs
                    if (error != SocketError.Success)
                    {
                        OnInterleavedData(buffer, offset - remainingInBuffer, remainingInBuffer);

                        return recievedTotal;
                    }

                    //Move back to where the frame started
                    offset -= remainingInBuffer;
                }

                //If there was data unrelated to a frame
                if (raisedEvent)
                {
                    if (relevent == null)
                    {
                        offset += frameLength;

                        remainingInBuffer -= frameLength;
                    }

                    continue;
                }
                else if (false == IsDisposed && frameLength > 0)
                {
                    //Parse the data in the buffer
                    using (var memory = new Common.MemorySegment(buffer, offset + InterleavedOverhead, frameLength - InterleavedOverhead))
                        ParseAndCompleteData(memory, expectRtcp, expectRtp, memory.Count);

                    //Decrease remaining in buffer
                    remainingInBuffer -= frameLength;

                    //Move the offset
                    offset += frameLength;

                    //Ensure large frames are completely received by receiving the rest of the frame now. (this only occurs for packets being skipped)
                    if (frameLength > bufferLength)
                    {
                        //Remove the context
                        relevent = null;

                        //Determine how much remains
                        remainingOnSocket = frameLength - bufferLength;

                        //If there is anything left
                        if (remainingOnSocket > 0)
                        {
                            //Set the new length of the frame based on the length of the buffer
                            frameLength -= bufferLength;

                            //Set what is remaining
                            remainingInBuffer = 0;

                            //Use all the buffer
                            offset = m_Buffer.Offset;

                            //go to receive it
                            goto CheckRemainingData;
                        }
                    }
                }
            }

            //Handle any data which remains if not already
            if (false == raisedEvent && remainingInBuffer > 0)
            {
                OnInterleavedData(buffer, offset, remainingInBuffer);
            }

            //Return the number of bytes recieved
            return recievedTotal;
        }
Пример #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);
        }