예제 #1
0
        public void TestNull()
        {
            //base class?
            //UnitTestBase
            Console.WriteLine(System.Reflection.MethodBase.GetCurrentMethod().Name);

            Media.Rtp.RtpClient rtpClient = default(Media.Rtp.RtpClient);

            try { rtpClient = Media.Rtp.RtpClient.FromSessionDescription(default(Media.Sdp.SessionDescription)); }
            catch { }

            System.Diagnostics.Debug.Assert(rtpClient == null, "Must not have created a RtpClient from a null SessionDescription");


            //Create a client
            using (rtpClient = new Media.Rtp.RtpClient())
            {
                //Attempt to find a context
                Media.Rtp.RtpClient.TransportContext contextAvailable = rtpClient.GetTransportContexts().FirstOrDefault();

                System.Diagnostics.Debug.Assert(contextAvailable == null, "Found a Context when there was no Session or Media Description");

                using (contextAvailable = new Media.Rtp.RtpClient.TransportContext(0, 1, 0))
                {
                    //Usually indicated by the profile
                    bool padding = false, extension = false;

                    //Create a RtpPacket from the
                    using (var rtpPacket = new Media.Rtp.RtpPacket(contextAvailable.Version, padding, extension, null))
                    {
                        System.Diagnostics.Debug.Assert(rtpClient.SendRtpPacket(rtpPacket) == 0, "Sent a packet when there was no Session or Media Description or TransportContext");
                    }
                }
            }
        }
예제 #2
0
                void ProcessRtpPacket(object sender, Media.Rtp.RtpPacket packet, Media.Rtp.RtpClient.TransportContext tc = null)
                {
                    ConsoleColor previousForegroundColor = Console.ForegroundColor;

                    Console.ForegroundColor = ConsoleColor.Magenta;
                    Console.WriteLine("ProcessRtpPacket(): SequenceNumber = " + packet.SequenceNumber +
                                      ", Payload.Offset = " + packet.Payload.Offset + ", Payload.Count = " + packet.Payload.Count);
                    Console.ForegroundColor = previousForegroundColor;
                }
예제 #3
0
            private static void Issue17245_Case2(int breakingPaketLength)
            {
                int sequenceNumber = 0x3030;   //  "00"

                System.Console.Clear();
                Console.WriteLine("TestProcessFrameData Issue17245_Case2(): Interleaved RTSPResponse");
                Console.WriteLine("breakingPaketLength = " + breakingPaketLength);
                Console.WriteLine("Correct output is 3 rows saying 'ProcessRtpPacket()...', 1 yellow row, and finaly a single row 'ProcessRtpPacket()...':");
                Console.WriteLine("");

                TestFramework tf = new TestFramework();

                //Console.WriteLine(line + sequenceNumber);
                byte[] buffer          = GeneratePayload(1400);
                Media.Rtp.RtpPacket p1 = new Media.Rtp.RtpPacket(2, false, false, false, 0, 0, _senderSSRC, sequenceNumber++, _timeStamp, buffer);
                buffer = p1.Prepare().ToArray();
                tf.Send(GenerateEncapsulatingHeader(buffer.Length));
                tf.Send(buffer);

                //Console.WriteLine(line + sequenceNumber);
                buffer = GeneratePayload(1400);
                Media.Rtp.RtpPacket p2 = new Media.Rtp.RtpPacket(2, false, false, false, 0, 0, _senderSSRC, sequenceNumber++, _timeStamp, buffer);
                buffer = p2.Prepare().ToArray();
                tf.Send(GenerateEncapsulatingHeader(buffer.Length));
                tf.Send(buffer);

                //Console.WriteLine(line + sequenceNumber);
                buffer = GeneratePayload(breakingPaketLength);
                Media.Rtp.RtpPacket p3 = new Media.Rtp.RtpPacket(2, false, false, false, 0, 0, _senderSSRC, sequenceNumber++, _timeStamp, buffer);
                buffer = p3.Prepare().ToArray();
                tf.Send(GenerateEncapsulatingHeader(buffer.Length));
                tf.Send(buffer);

                Media.Rtsp.RtspMessage keepAlive = new Media.Rtsp.RtspMessage(Media.Rtsp.RtspMessageType.Response);
                keepAlive.RtspStatusCode = Media.Rtsp.RtspStatusCode.OK;
                keepAlive.CSeq           = 34;
                keepAlive.SetHeader(Media.Rtsp.RtspHeaders.Session, "A9B8C7D6");
                keepAlive.SetHeader(Media.Rtsp.RtspHeaders.UserAgent, "Testing $UserAgent $009\r\n$\0:\0");
                keepAlive.SetHeader("Ignore", "$UserAgent $009\r\n$\0\0\aRTSP/1.0");
                keepAlive.SetHeader("$", string.Empty);
                keepAlive.SetHeader(Media.Rtsp.RtspHeaders.Date, DateTime.Now.ToUniversalTime().ToString("r"));
                buffer = keepAlive.Prepare().ToArray();
                tf.Send(buffer);

                //Console.WriteLine(line + sequenceNumber);
                buffer = GeneratePayload(1400);
                Media.Rtp.RtpPacket p4 = new Media.Rtp.RtpPacket(2, false, false, false, 0, 0, _senderSSRC, sequenceNumber++, _timeStamp, buffer);
                buffer = p4.Prepare().ToArray();
                tf.Send(GenerateEncapsulatingHeader(buffer.Length));
                tf.Send(buffer);

                //  Kick of the processing eventually ending up in RtpClient.ProcessFrameData()
                tf.HaveRtpClientWorkerThreadProcessSocketData();
            }
예제 #4
0
        private void RTSPClient_RtpPacketReceieved(object sender, Media.Rtp.RtpPacket packet = null, Media.Rtp.RtpClient.TransportContext tc = null)
        {
            if (InvokeRequired)
            {
                MethodInvoker del = delegate { RTSPClient_RtpPacketReceieved(sender, packet, tc); };
                Invoke(del);
            }
            else
            {
                if ((m_rtspClient != null))
                {
                    if (!m_rtspClient.LivePlay)
                    {
                        label2.Text = "Remaining: " +
                                      (DateTime.UtcNow - m_rtspClient.StartedPlaying.Value).Subtract(m_rtspClient.EndTime.Value).ToString();
                    }
                }
                RTSPMessagesTextBox.AppendText("RTSPClient_RtpPacketReceieved" + Environment.NewLine);
                RTSPMessagesTextBox.AppendText("@" + packet.Created.ToUniversalTime().ToString() + " - " + packet.ToString() + Environment.NewLine);

                RTSPMessagesTextBox.AppendText("IsComplete = " + packet.IsComplete.ToString() + ", ");
                RTSPMessagesTextBox.AppendText("IsCompressed = " + packet.IsCompressed.ToString() + ", ");
                RTSPMessagesTextBox.AppendText("Length = " + packet.Length.ToString() + ", ");
                RTSPMessagesTextBox.AppendText("SequenceNumber = " + packet.SequenceNumber.ToString() + ", ");
                RTSPMessagesTextBox.AppendText("PayloadType = " + packet.PayloadType.ToString() + ", " + Environment.NewLine);

#if DRIBBLE
                try
                {
                    int count     = 0;
                    int byteCount = 40;

                    foreach (byte payloadByte in packet.PayloadData)
                    {
                        RTSPMessagesTextBox.AppendText(String.Format("{0:X2}", payloadByte));
                        RTSPMessagesTextBox.AppendText(" ");
                        if (count++ > byteCount)
                        {
                            break;
                        }
                    }

                    RTSPMessagesTextBox.AppendText(Environment.NewLine);
                }
                catch (Exception ex)
                {
                    RTSPMessagesTextBox.AppendText("Image Exception:" + ex.Message + Environment.NewLine);
                }
#endif

                RTSPMessagesTextBox.AppendText(Environment.NewLine);
            }
        }
예제 #5
0
            private static void Issue17245_Case1(int breakingPaketLength)
            {
                int    sequenceNumber = 0x3030; //  "00"
                string line           = "Case1(): SequenceNumber = ";

                System.Console.Clear();
                Console.WriteLine("TestProcessFrameData Issue17245_Case1(): Discarding of Encapsulating Frame Header");
                Console.WriteLine("breakingPaketLength = " + breakingPaketLength);
                Console.WriteLine("Correct output is 5 rows saying 'Case1()...' and 5 rows 'ProcessRtpPacket()...'");
                Console.WriteLine("No yellow rows!!!");
                Console.WriteLine("");

                TestFramework tf = new TestFramework();

                Console.WriteLine(line + sequenceNumber);
                byte[] buffer          = GeneratePayload(1400);
                Media.Rtp.RtpPacket p1 = new Media.Rtp.RtpPacket(2, false, false, false, 0, 0, _senderSSRC, sequenceNumber++, _timeStamp, buffer);
                buffer = p1.Prepare().ToArray();
                tf.Send(GenerateEncapsulatingHeader(buffer.Length));
                tf.Send(buffer);

                Console.WriteLine(line + sequenceNumber);
                buffer = GeneratePayload(1400);
                Media.Rtp.RtpPacket p2 = new Media.Rtp.RtpPacket(2, false, false, false, 0, 0, _senderSSRC, sequenceNumber++, _timeStamp, buffer);
                buffer = p2.Prepare().ToArray();
                tf.Send(GenerateEncapsulatingHeader(buffer.Length));
                tf.Send(buffer);

                Console.WriteLine(line + sequenceNumber);
                buffer = GeneratePayload(breakingPaketLength); //  Length 1245 to 1247 looses packets and it does not recover
                Media.Rtp.RtpPacket p3 = new Media.Rtp.RtpPacket(2, false, false, false, 0, 0, _senderSSRC, sequenceNumber++, _timeStamp, buffer);
                buffer = p3.Prepare().ToArray();
                tf.Send(GenerateEncapsulatingHeader(buffer.Length));
                tf.Send(buffer);

                Console.WriteLine(line + sequenceNumber);
                buffer = GeneratePayload(1400);
                Media.Rtp.RtpPacket p4 = new Media.Rtp.RtpPacket(2, false, false, false, 0, 0, _senderSSRC, sequenceNumber++, _timeStamp, buffer);
                buffer = p4.Prepare().ToArray();
                tf.Send(GenerateEncapsulatingHeader(buffer.Length));
                tf.Send(buffer);

                Console.WriteLine(line + sequenceNumber);
                buffer = GeneratePayload(1400);
                Media.Rtp.RtpPacket p5 = new Media.Rtp.RtpPacket(2, false, false, false, 0, 0, _senderSSRC, sequenceNumber++, _timeStamp, buffer);
                buffer = p5.Prepare().ToArray();
                tf.Send(GenerateEncapsulatingHeader(buffer.Length));
                tf.Send(buffer);

                //  Kick of the processing eventually ending up in RtpClient.ProcessFrameData()
                tf.HaveRtpClientWorkerThreadProcessSocketData();
            }
예제 #6
0
 void ShowRtpPacket(object sender, Media.Rtp.RtpPacket packet, Media.Rtp.RtpClient.TransportContext tc = null)
 {
     try
     {
         if (this.InvokeRequired)
         {
             Invoke(new FillGridRtp(AddRtp), packet.Clone(true, true, true, true, true));
         }
         else
         {
             RTPPacketBinding.Add((IPacket)packet.Clone(true, true, true, true, true));
         }
     }
     catch { }
 }
예제 #7
0
 public void AddRtp(Media.Rtp.RtpPacket p)
 {
     if (Media.Common.IDisposedExtensions.IsNullOrDisposed(Client))
     {
         return;
     }
     try
     {
         RTPPacketBinding.Add(p);
         if (!Client.LivePlay)
         {
             label2.Text = "Remaining: " + (DateTime.UtcNow - Client.StartedPlaying.Value).Subtract(Client.EndTime.Value).ToString();
         }
         DrawBandwidth(Color.Blue);
     }
     catch { }
 }
예제 #8
0
    //Todo Seperate
    public void TestRtpPacket()
    {
        Console.WriteLine(System.Reflection.MethodBase.GetCurrentMethod().Name);

        //Create a RtpPacket instance
        Media.Rtp.RtpPacket p = new Media.Rtp.RtpPacket(new Media.Rtp.RtpHeader(0, false, false), Enumerable.Empty<byte>());

        //Set a few values
        p.Timestamp = 987654321;
        p.SequenceNumber = 7;
        p.ContributingSourceCount = 7;

        System.Diagnostics.Debug.Assert(p.SequenceNumber == 7, sequenceNumberException.Message);

        if (p.Timestamp != 987654321) throw timestampException;

        System.Diagnostics.Debug.Assert(p.ContributingSourceCount == 7, contributingSourceException.Message);

        //Recreate the packet from the bytes of the result of calling the methods ToArray on the Prepare instance method.
        p = new Media.Rtp.RtpPacket(p.Prepare().ToArray(), 0);

        //Perform the same tests. (Todo condense tests into seperate functions)

        if (p.SequenceNumber != 7) throw sequenceNumberException;

        System.Diagnostics.Debug.Assert(p.SequenceNumber == 7, sequenceNumberException.Message);

        if (p.ContributingSourceCount != 7) throw contributingSourceException;

        System.Diagnostics.Debug.Assert(p.ContributingSourceCount == 7, contributingSourceException.Message);

        System.Diagnostics.Debug.Assert(p.Timestamp == 987654321, timestampException.Message);

        //Cache a bitValue
        bool bitValue = false;

        //Permute every possible bit packed value that can be valid in the first and second octet
        for (int ibitValue = 0; ibitValue < 2; ++ibitValue)
        {
            //Make a bitValue after the 0th iteration
            if (ibitValue > 0) bitValue = Convert.ToBoolean(bitValue);

            //Show the bitValue 0 or 1
            //if (ibitValue <= 1) Console.WriteLine(string.Format(TestingFormat, "\tbitValue", bitValue + "\r\n"));

            //Permute every possible value within the 2 bit Version
            for (int VersionCounter = 0; VersionCounter <= Media.Common.Binary.TwoBitMaxValue; ++VersionCounter)
            {
                //Set the version
                p.Version = VersionCounter;

                //Write the version information to the console.
                //Console.Write(string.Format(TestingFormat, "\tVersionCounter", VersionCounter));
                //Console.Write(string.Format(TestingFormat, " Version", p.Version + "\r\n"));

                //Set the bit values in the first octet
                p.Extension = p.Padding = bitValue;

                //Check the version bits after modification
                System.Diagnostics.Debug.Assert(p.Version == VersionCounter, versionException.Message);

                //Check the Padding bit after modification
                System.Diagnostics.Debug.Assert(p.Padding == bitValue, paddingException.Message);

                //Check the Extension bit after modification
                System.Diagnostics.Debug.Assert(p.Extension == bitValue, extensionException.Message);

                //Permute every possible value in the 7 bit PayloadCounter
                for (int PayloadCounter = 0; PayloadCounter <= sbyte.MaxValue; ++PayloadCounter)
                {
                    //Set the 7 bit value in the second octet.
                    p.PayloadType = (byte)PayloadCounter;

                    //Write the value of the PayloadCounter to the console and the packet value to the Console.
                    //Console.Write(string.Format(TestingFormat, "\tPayloadCounter", PayloadCounter));
                    //Console.Write(string.Format(TestingFormat, " PayloadType", p.PayloadType + "\r\n"));

                    //Check the PayloadType
                    System.Diagnostics.Debug.Assert(p.PayloadType == PayloadCounter, payloadException.Message);

                    //Check the Padding bit after modification
                    System.Diagnostics.Debug.Assert(p.Padding == bitValue, paddingException.Message);

                    //Check the Extension bit after modification
                    System.Diagnostics.Debug.Assert(p.Extension == bitValue, extensionException.Message);

                    //Permute every combination for a nybble
                    for (int ContributingSourceCounter = byte.MinValue; ContributingSourceCounter <= Media.Common.Binary.FourBitMaxValue; ++ContributingSourceCounter)
                    {
                        ///////////////Set the CC nibble in the first Octet
                        p.ContributingSourceCount = (byte)ContributingSourceCounter;
                        /////////////

                        //Identify the Contributing Source Counter and the Packet's value
                        //Console.Write(string.Format(TestingFormat, "\tContributingSourceCounter", ContributingSourceCounter));
                        //Console.Write(string.Format(TestingFormat, " ContributingSourceCount", p.ContributingSourceCount + "\r\n"));

                        //Check the CC nibble in the first octet.
                        System.Diagnostics.Debug.Assert(p.ContributingSourceCount == ContributingSourceCounter, contributingSourceException.Message);

                        //Ensure the Version after modification
                        System.Diagnostics.Debug.Assert(p.Version == VersionCounter, versionException.Message);

                        //Check the Padding bit after modification
                        System.Diagnostics.Debug.Assert(p.Padding == bitValue, paddingException.Message);

                        //Check the Extension bit after modification
                        System.Diagnostics.Debug.Assert(p.Extension == bitValue, extensionException.Message);

                        ///////////////Serialize the packet
                        p = new Media.Rtp.RtpPacket(p.Prepare().ToArray(), 0);
                        /////////////

                        //Ensure the Version after modification
                        System.Diagnostics.Debug.Assert(p.Version == VersionCounter, versionException.Message);

                        //Check the Padding bit after modification
                        System.Diagnostics.Debug.Assert(p.Padding == bitValue, paddingException.Message);

                        //Check the Extension bit after modification
                        System.Diagnostics.Debug.Assert(p.Extension == bitValue, extensionException.Message);

                        //Check the CC nibble in the first octet.
                        System.Diagnostics.Debug.Assert(p.ContributingSourceCount == ContributingSourceCounter, contributingSourceException.Message);

                    }
                }
            }

            //Console.WriteLine(string.Format(TestingFormat, "\t*****Completed an iteration wih bitValue", bitValue + "*****"));
        }
    }
예제 #9
0
        public static void TestExampleExtensions()
        {
            //Console.WriteLine(System.Reflection.MethodBase.GetCurrentMethod().Name);

            //Test TestOnvifRTPExtensionHeader (Thanks to Wuffles@codeplex)

            byte[] m_SamplePacketBytes = new byte[]
            {
                0x90, 0x60, 0x94, 0x63,                           // RTP Header
                0x0D, 0x19, 0x60, 0xC9,                           // .
                0xA6, 0x20, 0x13, 0x44,                           // .

                0xAB, 0xAC, 0x00, 0x03,                           // Extension Header
                0xD4, 0xBB, 0x8A, 0x43,                           // Extension Data
                0xFE, 0x7A, 0xC8, 0x1E,                           // Extension Data
                0x00, 0xD3, 0x00, 0x00,                           // Extension Data

                0x5C, 0x81, 0x9B, 0xC0,                           // RTP Payload start
                0x1C, 0x02, 0x38, 0x8E,                           // .
                0x2B, 0xC0, 0x01, 0x09,                           // .
                0x55, 0x77, 0x49, 0x99,                           // .
                0x62, 0xFF, 0xBA, 0xC9,                           // .
                0x8E, 0xCE, 0x23, 0x96,                           // .
                0x6A, 0xCC, 0xF5, 0x5F,                           // .
                0xA0, 0x08, 0xD9, 0x37,                           // .
                0xCF, 0xFA, 0xA5, 0x4D,                           // .
                0x16, 0x6C, 0x78, 0x61,                           // .
                0xFA, 0x7F, 0xC8, 0x7E,                           // .
                0xA1, 0x15, 0xF6, 0x5F,                           // .
                0xA3, 0x2F, 0x82, 0xC7,                           // .
                0x45, 0x0A, 0x87, 0x75,                           // .
                0xEC, 0x5B, 0x7D, 0xDE,                           // .
                0x82, 0x31, 0xD0, 0xE9,                           // .
                0xBE, 0xE5, 0x39, 0x8D,                           // etc.
            };

            Media.Rtp.RtpPacket testPacket = new Media.Rtp.RtpPacket(m_SamplePacketBytes, 0);

            if (false == testPacket.Extension)
            {
                throw new Exception("Unexpected Header.Extension");
            }

            using (Media.Rtp.RtpExtension rtpExtension = testPacket.GetExtension())
            {
                if (rtpExtension == null)
                {
                    throw new Exception("Extension is null");
                }

                if (false == rtpExtension.IsComplete)
                {
                    throw new Exception("Extension is not complete");
                }

                // The extension data length is (3 words / 12 bytes)
                // This property exposes the length of the ExtensionData in bytes including the flags and length bytes themselves
                //In cases where the ExtensionLength = 4 the ExtensionFlags should contain the only needed information
                if (rtpExtension.Size != 16)
                {
                    throw new Exception("Expected ExtensionLength not found");
                }
                //else Console.WriteLine("Found LengthInWords: " + rtpExtension.LengthInWords);

                // Check extension values are what we expected.
                if (rtpExtension.Flags != 0xABAC)
                {
                    throw new Exception("Expected Extension Flags Not Found");
                }
                //else Console.WriteLine("Found ExtensionFlags: " + rtpExtension.Flags.ToString("X"));

                // Test the extension data is correct
                byte[] expected = { 0xD4, 0xBB, 0x8A, 0x43, 0xFE, 0x7A, 0xC8, 0x1E, 0x00, 0xD3, 0x00, 0x00 };
                if (false == rtpExtension.Data.SequenceEqual(expected))
                {
                    throw new Exception("Extension data was not as expected");
                }
                //else Console.WriteLine("Found ExtensionData: " + BitConverter.ToString(rtpExtension.Data.ToArray()));
            }

            byte[] output = testPacket.Prepare().ToArray();

            if (output.Length != m_SamplePacketBytes.Length || false == output.SequenceEqual(m_SamplePacketBytes))
            {
                throw new Exception("Packet was not the same");
            }

            m_SamplePacketBytes = new byte[]
            {
                //RTP Header
                0x90, 0x1a, 0x01, 0x6d, 0xf3, 0xff, 0x40, 0x58, 0xf0, 0x00, 0x9c, 0x5b,
                //Extension FF FF, Length = 0
                0xff, 0xff, 0x00, 0x00

                , 0x00, 0x00, 0x15, 0x1c, 0x01, 0xff, 0xa0, 0x5a, 0x13, 0xd2, 0xa9, 0xf5, 0xeb, 0x49, 0x52, 0xdb
                , 0x65, 0xa8, 0xd8, 0x40, 0x36, 0xa8, 0x03, 0x81, 0x41, 0xf7, 0xa5, 0x34, 0x52, 0x28, 0x4f, 0x7a
                , 0x29, 0x79, 0xf5, 0xa4, 0xa0, 0x02, 0x8a, 0x5a, 0x4a, 0x00, 0x28, 0xed, 0x45, 0x14, 0x0c, 0x28
                , 0xef, 0x45, 0x1c, 0xd0, 0x20, 0xa3, 0x34, 0x51, 0x40, 0xc4, 0xcd, 0x2d, 0x14, 0x7e, 0x34, 0x00
                , 0x7f, 0x5a, 0x4a, 0x5a, 0x29, 0x00, 0x94, 0x52, 0xd0, 0x72, 0x69, 0x88, 0x4e, 0x68, 0xa3, 0x9a
                , 0x5a, 0x43, 0x12, 0x8a, 0x39, 0xa0, 0x73, 0x4c, 0x02, 0x8a, 0x5a, 0x29, 0x00, 0x63, 0x8e, 0x28
                , 0xa5, 0xcf, 0x14, 0x94, 0x00, 0x51, 0x45, 0x14, 0x08, 0x4a, 0x51, 0x9a, 0x5c, 0x52, 0x00, 0x68
                , 0x01, 0x40, 0xa4, 0xa7, 0x04, 0x62, 0x78, 0xa9, 0x52, 0x06, 0x6e, 0xd4, 0x01, 0x12, 0x8e, 0x7d
                , 0x69, 0x36, 0x92, 0x71, 0x8a, 0xd0, 0x83, 0x4f, 0x91, 0xfa, 0x29, 0x35, 0x7a, 0x1d, 0x25, 0xb3
                , 0xf3, 0xfc, 0xa3, 0xde, 0x9d, 0x85, 0x73, 0x11, 0x62, 0x63, 0x56, 0x63, 0xb3, 0x76, 0xc6, 0x14
                , 0xd6, 0xc9, 0x86, 0xca, 0xd8, 0x66, 0x49, 0x41, 0x3e, 0x82, 0xaa, 0x4f, 0xad, 0xdb, 0xdb, 0xf1
                , 0x12, 0x8e, 0x3b, 0x9a, 0x05, 0x71, 0xb1, 0x69, 0x72, 0x1e, 0x48, 0xc0, 0xf7, 0xa9, 0x8d, 0xa5
                , 0xbc, 0x03, 0x32, 0x48, 0x3f, 0x0a, 0xc4, 0xbd, 0xf1, 0x2c, 0x8f, 0x90, 0x1f, 0x03, 0xd0, 0x56
                , 0x35, 0xce, 0xaf, 0x2c, 0x87, 0xef, 0x53, 0xb0, 0x1d, 0x54, 0xd7, 0xf6, 0xb0, 0x70, 0x80, 0x1f
                , 0x73, 0x59, 0xb7, 0x9a, 0xde, 0x54, 0x85, 0x60, 0x3e, 0x95, 0xcc, 0x4d, 0x79, 0x23, 0xf5, 0x63
                , 0x55, 0xda, 0x56, 0x27, 0x92, 0x69, 0xf2, 0xdc, 0x2e, 0x5f, 0x97, 0x54, 0x91, 0xdc, 0xe5, 0x89
                , 0xaa, 0x57, 0x77, 0x4e, 0xea, 0x70, 0x6a, 0x0e, 0x73, 0x9a, 0x8d, 0xbe, 0xb5, 0x56, 0x44, 0xb6
                , 0x46, 0x8e, 0x59, 0xdb, 0x2d, 0x9c, 0x76, 0xf4, 0xa7, 0xfe, 0x95, 0x1a, 0x9c, 0x12, 0x79, 0xa7
                , 0x82, 0x4d, 0x50, 0x8f, 0x41, 0xa0, 0x52, 0xd2, 0x71, 0x59, 0x1a, 0x00, 0x34, 0xef, 0x73, 0x49
                , 0x9a, 0x3e, 0xa6, 0x80, 0x0a, 0x28, 0xe2, 0x8e, 0xf4, 0x00, 0x01, 0x4b, 0x41, 0x22, 0x90, 0x30
                , 0xcf, 0x51, 0x45, 0xc4, 0x07, 0x9a, 0x51, 0xd6, 0x93, 0x7a, 0xff, 0x00, 0x78, 0x7e, 0x74, 0x82
                , 0x44, 0x1d, 0x58, 0x50, 0x31, 0xc3, 0x39, 0x39, 0xa3, 0x34, 0x82, 0x58, 0xc7, 0xf1, 0x8f, 0xce
                , 0x93, 0xcf, 0x8b, 0xfb, 0xe2, 0x8b, 0x88, 0x7d, 0x2e, 0x0d, 0x45, 0xf6, 0x88, 0xfb, 0xb8, 0xfc
                , 0xe8, 0xfb, 0x54, 0x3f, 0xf3, 0xd0, 0x51, 0x70, 0x25, 0xa2, 0xa1, 0xfb, 0x5c, 0x3d, 0xdc, 0x50
                , 0x2e, 0xe1, 0xcf, 0xdf, 0x14, 0x5c, 0x64, 0xe0, 0x51, 0xc8, 0xa4, 0x57, 0x57, 0xe4, 0x10, 0x69
                , 0xc7, 0x91, 0x40, 0x84, 0xa5, 0xa0, 0x76, 0x34, 0x50, 0x01, 0x8c, 0x9a, 0x29, 0x7a, 0x52, 0xfb
                , 0xd0, 0x03, 0x40, 0xce, 0x73, 0x4b, 0xb7, 0x8a, 0x5e, 0x94, 0x84, 0xd0, 0x03, 0x31, 0xcd, 0x14
                , 0xe3, 0x49, 0x8c, 0xd0, 0x31, 0x41, 0xa7, 0x0f, 0x5a, 0x8f, 0xbd, 0x3d, 0x78, 0x34, 0x08, 0x7f
                , 0x5e, 0xb4, 0x62, 0x8c, 0x64, 0xd2, 0xe3, 0xd6, 0x80, 0x12, 0x81, 0x4b, 0x8c, 0xfb, 0x51, 0xc5
                , 0x00, 0x14, 0x87, 0x91, 0x4a, 0x4d, 0x1e, 0xbc, 0xd0, 0x21, 0xb9, 0xcd, 0x3b, 0xde, 0x8f, 0xad
                , 0x28, 0xa0, 0x05, 0xf4, 0xa3, 0xa9, 0xa3, 0x14, 0x94, 0x80, 0x05, 0x07, 0xda, 0x8a, 0x5a, 0x60
                , 0x27, 0x7a, 0x3b, 0xe6, 0x96, 0x8e, 0xb4, 0x80, 0x4e, 0xb4, 0x84, 0x77, 0xa5, 0xe4, 0x52, 0x1a
                , 0x00, 0x6e, 0xda, 0x8c, 0x8e, 0xb5, 0x2d, 0x30, 0xe7, 0xad, 0x03, 0x18, 0x6a, 0x39, 0x33, 0x52
                , 0x53, 0x25, 0xe9, 0xd6, 0x81, 0x94, 0xe5, 0xe9, 0x55, 0x24, 0xfb, 0xc3, 0xeb, 0x56, 0xe4, 0xe9
                , 0x55, 0x1b, 0xef, 0x0a, 0x68, 0x0b, 0x30, 0xf2, 0xcb, 0xf5, 0xae, 0x93, 0x53, 0xe3, 0x4a, 0x1f
                , 0x85, 0x73, 0x90, 0x0f, 0xde, 0x2f, 0xd6, 0xba, 0x4d, 0x57, 0x8d, 0x2c, 0x1f, 0xa5, 0x0f, 0x63
                , 0x2a, 0xbf, 0x09, 0x8d, 0x6b, 0x7d, 0x2d, 0xba, 0xed, 0x5c, 0x11, 0x5a, 0xb6, 0x9a, 0xcb, 0xa9
                , 0x1b, 0x93, 0x35, 0x84, 0xbe, 0xb5, 0x62, 0x2e, 0xbc, 0x57, 0x34, 0x99, 0xca, 0xa7, 0x25, 0xb1
                , 0xdb, 0xd8, 0x6b, 0xaa, 0x17, 0xee, 0x10, 0xd5, 0xbb, 0xa3, 0x6a, 0xcc, 0x26, 0xcc, 0x8d, 0x95
                , 0x6e, 0xa2, 0xbc, 0xfe, 0xd1, 0xb6, 0xe3, 0x9a, 0xdc, 0xb2, 0x9f, 0x18, 0xe6, 0xb8, 0xaa, 0x26
                , 0x3f, 0xac, 0x4e, 0xeb, 0x53, 0xd3, 0x81, 0x59, 0x10, 0x11, 0x82, 0xa6, 0xa1, 0x91, 0x30, 0xd8
                , 0x27, 0x22, 0xa9, 0xf8, 0x7e, 0x7f, 0x36, 0xc8, 0x6e, 0x39, 0xc1, 0xa4, 0xbe, 0xbb, 0x09, 0x70
                , 0x57, 0x3d, 0x2a, 0x66, 0xd3, 0x8a, 0xee, 0x74, 0xd6, 0xd6, 0x0a, 0x45, 0xcf, 0x2d, 0x4d, 0x21
                , 0x88, 0x55, 0x05, 0xbd, 0x1e, 0xb5, 0x28, 0xbc, 0x07, 0xbd, 0x61, 0x76, 0x71, 0x68, 0x5b, 0xfb
                , 0x28, 0x23, 0x34, 0xf8, 0x20, 0x11, 0x12, 0x7d, 0x6a, 0x18, 0x2e, 0xd4, 0xf0, 0xc6, 0xae, 0x03
                , 0x9e, 0x6b, 0xb7, 0x0f, 0x0a, 0x73, 0xdd, 0xea, 0x8e, 0xca, 0x50, 0x83, 0xf7, 0x96, 0xe4, 0x77
                , 0x11, 0xf9, 0xb1, 0x32, 0xd6, 0x4c, 0x96, 0x27, 0xba, 0x9a, 0xda, 0xa6, 0x4b, 0x22, 0xc6, 0x3e
                , 0x63, 0xf8, 0x56, 0x98, 0x9a, 0x51, 0x4d, 0xce, 0xe3, 0xad, 0x4a, 0x32, 0xd5, 0xb3, 0x9e, 0x96
                , 0xcf, 0xda, 0xa8, 0xdc, 0x59, 0xe3, 0x27, 0x15, 0xd0, 0x3b, 0x2b, 0x12, 0x6a, 0xad, 0xc0, 0x52
                , 0x0d, 0x79, 0xe9, 0x9e, 0x7b, 0x8a, 0x28, 0xe9, 0xb6, 0xf8, 0xb5, 0x6e, 0x3b, 0xd5, 0x5b, 0xc4
                , 0xc6, 0x45, 0x6e, 0x59, 0x28, 0xfb, 0x23, 0x1f, 0x7a, 0xc8, 0xd4, 0x78, 0x26, 0xbb, 0xe9, 0x3b
                , 0xa3, 0xd8, 0xa4, 0xad, 0x49, 0x18, 0x53, 0x8e, 0x6b, 0x1b, 0x59, 0x1f, 0xe8, 0xad, 0x5b, 0x33
                , 0x9e, 0x6b, 0x1b, 0x59, 0x39, 0xb5, 0x35, 0xd9, 0xd0, 0xc6, 0xaf, 0xc2, 0xca, 0x9e, 0x1d, 0x1c
                , 0xc9, 0xf5, 0xab, 0x77, 0x03, 0x13, 0xb7, 0xd7, 0xad, 0x56, 0xf0, 0xef, 0x59, 0x3e, 0xb5, 0x6e
                , 0xe0, 0x66, 0x67, 0xf5, 0xcd, 0x69, 0x1d, 0x8c, 0xa1, 0xb2, 0x22, 0x23, 0xde, 0x9b, 0x4e, 0xa3
                , 0x03, 0xad, 0x05, 0x89, 0x40, 0xcf, 0x7a, 0x5e, 0xd9, 0xa4, 0xef, 0x40, 0x06, 0x38, 0x34, 0x63
                , 0x1e, 0xf4, 0x1e, 0x07, 0xd6, 0x8f, 0x4a, 0x63, 0x0f, 0xeb, 0x48, 0x07, 0xad, 0x3b, 0x81, 0x4b
                , 0xd7, 0x14, 0x80, 0x6f, 0x4c, 0xe6, 0x93, 0x8c, 0x75, 0xa5, 0x23, 0xae, 0x68, 0xc7, 0x38, 0xa6
                , 0x21, 0x31, 0xda, 0x93, 0x18, 0xa7, 0xe0, 0x77, 0x34, 0x98, 0xcd, 0x00, 0x34, 0xf7, 0xed, 0x49
                , 0x8a, 0x7e, 0x33, 0x48, 0x45, 0x00, 0x34, 0x77, 0xa3, 0x93, 0x4b, 0x4a, 0x7d, 0x28, 0x01, 0x33
                , 0x8a, 0x30, 0x71, 0xcf, 0x39, 0xa2, 0x97, 0x1e, 0xd4, 0x00, 0x2f, 0xd2, 0x9e, 0x29, 0x00, 0xa7
                , 0x7b, 0x66, 0x81, 0x09, 0x8f, 0x6a, 0x43, 0x9c, 0x1e, 0x29, 0xe4, 0x66, 0x9a, 0x72, 0x38, 0xa4
                , 0x52, 0x2b, 0xc8, 0x0f, 0x3d, 0xaa, 0xb4, 0xb9, 0x1f, 0x4a, 0xb5, 0x27, 0x7a, 0xad, 0x21, 0xea
                , 0x2a, 0x59, 0x48, 0xa8, 0xfe, 0xb5, 0x03, 0x70, 0x6a, 0xc4, 0x83, 0x15, 0x5c, 0xf5, 0xa0, 0xa1
                , 0x56, 0xb6, 0x3c, 0x3d, 0xff, 0x00, 0x1f, 0xa9, 0x58, 0xe3, 0xde, 0xb6, 0x7c, 0x3d, 0xff, 0x00
                , 0x1f, 0x89, 0x42, 0x14, 0xb6, 0x3b, 0x1a, 0x43, 0x41, 0x6e, 0x29, 0x33, 0x56, 0x66, 0x14, 0xbf
                , 0x53, 0x4d, 0xcd, 0x26, 0xf1, 0xeb, 0x40, 0x0e, 0x34, 0xdf, 0xad, 0x30, 0xca, 0xa3, 0xa9, 0xa8
                , 0x24, 0xbc, 0x8d, 0x7a, 0x9a, 0x57, 0x0b, 0x12, 0xc9, 0x55, 0x49, 0x1d, 0xcd, 0x55, 0xbb, 0xd5
                , 0x02, 0xa9, 0xd8, 0xb9, 0xfa, 0xd6, 0x3c, 0xd7, 0xf3, 0x4d, 0x9c, 0xb6, 0x07, 0xa0, 0xa3, 0x98
                , 0x7c, 0xac, 0xda, 0x9a, 0xea, 0x18, 0xb3, 0xb9, 0xc7, 0xe1, 0x59, 0xd3, 0xea, 0xc3, 0x27, 0xca
                , 0x4e, 0x7d, 0x4d, 0x66, 0x33, 0x13, 0xc9, 0x24, 0xd3, 0x0f, 0xeb, 0x4b, 0x99, 0xb1, 0xa8, 0xa2
                , 0x69, 0xee, 0xe7, 0x9b, 0xef, 0x39, 0xc7, 0xa0, 0xaa, 0xc7, 0x9e, 0xf4, 0xa6, 0x9a, 0x69, 0x17
                , 0x61, 0x0d, 0x25, 0x2f, 0xd6, 0x83, 0x40, 0xc6, 0x9a, 0x28, 0xeb, 0x41, 0x14, 0x00, 0x94, 0x1a
                , 0x28, 0xa0, 0x04, 0xf7, 0xa5, 0xa2, 0x92, 0x90, 0x05, 0x1d, 0x28, 0xa5, 0xa0, 0x62, 0x73, 0x45
                , 0x14, 0x62, 0x80, 0x0a, 0x3d, 0x68, 0xa2, 0x80, 0x0a, 0x28, 0xc5, 0x2d, 0x30, 0x0e, 0x94, 0x7d
                , 0x69, 0x69, 0x29, 0x00, 0x94, 0xb8, 0xcf, 0x5a, 0x31, 0x4b, 0xed, 0x40, 0x08, 0x0d, 0x18, 0xe2
                , 0x8a, 0x28, 0x10, 0x9c, 0xd1, 0x4b, 0x46, 0x28, 0x01, 0x39, 0xcd, 0x14, 0x51, 0x8a, 0x00, 0x31
                , 0x49, 0x9e, 0x69, 0xe4, 0x52, 0x00, 0x73, 0xcd, 0x03, 0x12, 0x8a, 0x90, 0x46, 0xc7, 0xb5, 0x4f
                , 0x1d, 0xa3, 0xb9, 0xc0, 0x52, 0x68, 0x11, 0x57, 0x06, 0x9c, 0xa8, 0xc6, 0xb5, 0xe0, 0xd1, 0xe5
                , 0x6e, 0x59, 0x71, 0xf5, 0xab, 0x8b, 0x63, 0x69, 0x6e, 0x33, 0x34, 0xcb, 0xc7, 0x61, 0x4e, 0xc2
                , 0xb9, 0x84, 0x96, 0xce, 0xc7, 0xa1, 0xab, 0x90, 0x69, 0x72, 0xbf, 0x45, 0x38, 0xab, 0xd2, 0x6a
                , 0x76, 0x36, 0xdc, 0x46, 0x81, 0x8f, 0xa9, 0xac, 0xeb, 0xbf, 0x11, 0xb6, 0x08, 0x56, 0x0a, 0x3d
                , 0xa9, 0x0b, 0x53, 0x4a, 0x3d, 0x29, 0x13, 0xfd, 0x6b, 0xaa, 0x8f, 0xad, 0x2b, 0xcf, 0xa7, 0xda
                , 0xf7, 0xde, 0xc2, 0xb9, 0x1b, 0x9d, 0x71, 0xdf, 0x3f, 0x39, 0x3f, 0x8d, 0x66, 0x4f, 0xa8, 0xca
                , 0xfd, 0x0d, 0x52, 0xb8, 0x1d, 0xa5, 0xc7, 0x88, 0xd2, 0x20, 0x44, 0x4a, 0xab, 0x58, 0x97, 0x7e
                , 0x23, 0x95, 0xc9, 0xc3, 0x93, 0x5c, 0xdb, 0xca, 0xef, 0xc9, 0x63, 0x4c, 0xc9, 0x34, 0xf9, 0x3b
                , 0x8a, 0xe8, 0xd0, 0xb8, 0xd5, 0x66, 0x94, 0x9c, 0xb1, 0xaa, 0x6f, 0x71, 0x23, 0xe7, 0x2c, 0x6a
            };

            testPacket = new Media.Rtp.RtpPacket(m_SamplePacketBytes, 0);

            if (false == testPacket.Extension)
            {
                throw new Exception("Unexpected Header.Extension");
            }

            using (Media.Rtp.RtpExtension rtpExtension = testPacket.GetExtension())
            {
                if (rtpExtension == null)
                {
                    throw new Exception("Extension is null");
                }

                if (false == rtpExtension.IsComplete)
                {
                    throw new Exception("Extension is not complete");
                }

                // The extension data length is (3 words / 12 bytes)
                // This property exposes the length of the ExtensionData in bytes including the flags and length bytes themselves
                //In cases where the ExtensionLength = 4 the ExtensionFlags should contain the only needed information
                if (rtpExtension.Size != Binary.BytesPerInteger)
                {
                    throw new Exception("Expected ExtensionLength not found");
                }
                //else Console.WriteLine("Found LengthInWords: " + rtpExtension.LengthInWords);

                // Check extension values are what we expected.
                if (rtpExtension.Flags != ushort.MaxValue)
                {
                    throw new Exception("Expected Extension Flags Not Found");
                }
                //else Console.WriteLine("Found ExtensionFlags: " + rtpExtension.Flags.ToString("X"));

                // Test the extension data is correct
                if (rtpExtension.Data.Any() || false == rtpExtension.Data.SequenceEqual(Media.Common.MemorySegment.EmptyBytes))
                {
                    throw new Exception("Extension data was not as expected");
                }
                //else Console.WriteLine("Found ExtensionData: " + BitConverter.ToString(rtpExtension.Data.ToArray()));
            }
        }
예제 #10
0
            /// <summary>
            /// /// <summary>
            /// Todo, break down logic, ParseHeaders, ParseAuxiliaryData, ParseAccessUnits(header)
            /// Todo, Test in BigEndian, ensure that BitReader is not needed or at least the BitOrder overload which can detect the BitOrder the system is before reading the value in reverse of the way they should be.
            /// </summary>
            /// <param name="parsedAccessUnits"></param>
            /// <param name="remainsInAu"></param>
            /// <param name="headersPresent"></param>
            /// <param name="profileId"></param>
            /// <param name="channelConfiguration"></param>
            /// <param name="frequencyIndex"></param>
            /// <param name="sizeLength"></param>
            /// <param name="indexLength"></param>
            /// <param name="indexDeltaLength"></param>
            /// <param name="CTSDeltaLength"></param>
            /// <param name="DTSDeltaLength"></param>
            /// <param name="auxDataSizeLength"></param>
            /// <param name="randomAccessIndication"></param>
            /// <param name="streamStateIndication"></param>
            /// <param name="defaultAuSize"></param>
            /// <param name="frameHeader"></param>
            /// <param name="addPadding"></param>
            /// <param name="includeAuHeaders"></param>
            /// <param name="includeAuxData"></param>
            public void Depacketize(Media.Rtp.RtpPacket packet, out int parsedAccessUnits, out int remainsInAu, bool headersPresent = true, int profileId = 0, int channelConfiguration = 0,
                                    int frequencyIndex = 0, int sizeLength                 = 0, int indexLength = 0, int indexDeltaLength = 0, int CTSDeltaLength = 0,
                                    int DTSDeltaLength = 0, int auxDataSizeLength          = 0, bool randomAccessIndication = false, int streamStateIndication = 0,
                                    int constantAuSize = 0, IEnumerable <byte> frameHeader = null,
                                    bool addPadding    = false, bool includeAuHeaders      = false, bool includeAuxData = false)
            {
                remainsInAu = parsedAccessUnits = 0;

                if (Common.IDisposedExtensions.IsNullOrDisposed(packet))
                {
                    return;
                }

                //This key is based on the SequenceNumber in signed form
                //int packetKey = GetPacketKey(packet.SequenceNumber);

                int packetKey = Depacketized.Count; //(short)packet.SequenceNumber;

                //Since the auIndex may be stored in highest 16 bits we could mask them out.

                //0xffff, but would require unsigned key in Depacketized.

                //There is also no reason to think that some other implementation wouldn't use more than 16 bits for the index and delta.

                //if (Depacketized.ContainsKey(packetKey)) return;

                //I thought about adding the key for this packet with Empty bytes which woudln't effect the stream and would keep it from being repacketized.
                //Depacketized.Add(packetKey, null);

                //From the beginning of the data in the actual payload
                int offset             = packet.Payload.Offset,
                    headerOctets       = packet.HeaderOctets,
                    padding            = packet.PaddingOctets,
                    max                = packet.Payload.Count - (padding + headerOctets),
                    auIndex            = 0, //Indicates the serial number of the associated Access Unit
                    auHeadersAvailable = 0; //The amount of Au Headers in the Au Header section

                #region  3.2.  RTP Payload Structure

                /*
                 *
                 *
                 *  3.2.1.  The AU Header Section
                 *
                 *      When present, the AU Header Section consists of the AU-headers-length
                 *      field, followed by a number of AU-headers, see Figure 2.
                 *
                 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- .. -+-+-+-+-+-+-+-+-+-+
                 |AU-headers-length|AU-header|AU-header|      |AU-header|padding|
                 |                 |   (1)   |   (2)   |      |   (n)   | bits  |
                 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- .. -+-+-+-+-+-+-+-+-+-+
                 |
                 |                      Figure 2: The AU Header Section
                 |
                 |      1) The AU-headers are configured using MIME format parameters and MAY be
                 |      empty.  If the AU-header is configured empty, the AU-headers-length
                 |      field SHALL NOT be present and consequently the AU Header Section is
                 |      empty.  If the AU-header is not configured empty, then the AU-
                 |      headers-length is a two octet field that specifies the length in bits
                 |      of the immediately following AU-headers, excluding the padding bits.
                 |
                 |      2) Each AU-header is associated with a single Access Unit (fragment)
                 |      contained in the Access Unit Data Section in the same RTP packet.
                 |
                 |      3) For each contained Access Unit (fragment), there is exactly one AU-
                 |      header.  Within the AU Header Section, the AU-headers are bit-wise
                 |      concatenated in the order in which the Access Units are contained in
                 |      the Access Unit Data Section.  Hence, the n-th AU-header refers to
                 |      the n-th AU (fragment).  If the concatenated AU-headers consume a
                 |      non-integer number of octets, up to 7 zero-padding bits MUST be
                 |      inserted at the end in order to achieve octet-alignment of the AU
                 |      Header Section.
                 */

                #endregion

                #region Reference

                //http://www.netmite.com/android/mydroid/donut/external/opencore/protocols/rtp_payload_parser/rfc_3640/src/rfc3640_payload_parser.cpp

                /*  https://gstrtpmp4adepay.c#L189
                 * Parse StreamMuxConfig according to ISO/IEC 14496-3:
                 *
                 * audioMuxVersion           == 0 (1 bit)
                 * allStreamsSameTimeFraming == 1 (1 bit)
                 * numSubFrames              == rtpmp4adepay->numSubFrames (6 bits)
                 * numProgram                == 0 (4 bits)
                 * numLayer                  == 0 (3 bits)
                 *
                 * We only require audioMuxVersion == 0;
                 *
                 * The remaining bit of the second byte and the rest of the bits are used
                 * for audioSpecificConfig which we need to set in codec_info.
                 */

                //Object Type 5 Bits.

                //SampleRate Index 4 Bits.

                //Channels 4 Bits

                //If SampleRate Index == 15, 24 Bits of SampleRate

                //For object types 1-7 Then Parse the Frame Flags. (Which indicate a frameLength of 960?)

                #endregion

                //Determine the AU Headers Length (in bits)
                int auHeaderLengthBits = headersPresent ? Common.Binary.ReadU16(packet.Payload.Array, ref offset, Common.Binary.IsLittleEndian) : 0,
                //It will then be converted to bytes.
                    auHeaderLengthBytes = 0,
                //AU-Size And the length of the underlying Elementary Stream Data for that access unit
                    auSize = 0,
                //The offset of current the au Header being parsed
                    auHeaderOffset = offset,
                //The offset of the auxiliary data if present
                    auxHeaderOffset = 0,
                //The length of the auxiliary data if present
                    auxLengthBytes = 0,
                //The absolute offset in the bitstream of the packet payload
                    bitOffset = Media.Common.Binary.BytesToBits(ref offset),
                //The amount of bytes required to read the sizeLength bit field
                    sizeLengthBytes       = Media.Common.Binary.BitsToBytes(sizeLength),
                    indexLengthBytes      = Media.Common.Binary.BitsToBytes(indexLength),
                    indexDeltaLengthBytes = Media.Common.Binary.BitsToBytes(indexDeltaLength);

                //If there are any auHeaders indicated
                if (auHeaderLengthBits > 0)
                {
                    //Convert bits to bytes
                    auHeaderLengthBytes = Media.Common.Binary.BitsToBytes(auHeaderLengthBits);

                    //Check enough bytes are available (2 is the size of the RFC Profile Header read above)
                    if (auHeaderLengthBytes >= max - 2)
                    {
                        throw new InvalidOperationException("Invalid Rfc Headers?");
                    }

                    //This many bits in each auAuheader + more if CTS or DTS is present.
                    int usedBits = sizeLength + indexDeltaLength;

                    //Throw an error if the length indicated is not equal to the amount of bits in use by the profile
                    if (auHeaderLengthBits != usedBits)
                    {
                        throw new InvalidOperationException("Invalid Au Headers?");
                    }

                    //Determine the amount of AU Headers possibly contained in the header section
                    auHeadersAvailable = 1 + (auHeaderLengthBits - usedBits) / usedBits;

                    //padding should be tracked here
                    //int lastHeaderPadding;
                    //auHeadersAvailable = Math.DivRem(1 + (auHeaderLengthBits - usedBits), usedBits, out lastHeaderPadding);
                }

                #region No AU Headers Length

                // The AU Headers Length is either not present or known..
                //{
                //    //Read the 'ES_ID'
                //    //ushort esId = Common.Binary.ReadU16(rtp.Payload, offset, Common.Binary.IsLittleEndian);

                //    //if (esId == 16) //This is AAC Audio 00 10?
                //}

                #endregion

                //The length in bytes of all auHeaders is known, the last auHeader may have padding to achieve Octet alignment.

                //Parse AU Headers should be seperate logic, probably in Audio.Aac

                //Create a sorted list to allow the de-interleaving of access units if required.
                //SortedList<int, IEnumerable<byte>> accessUnits = new SortedList<int, IEnumerable<byte>>();

                //Should occur only after the last AU Header but before the individual payloads.
                #region Parse Auxiliary Data

                //Now skip over the aux data region.
                if (0 != auxDataSizeLength)
                {
                    //Store the offset where the auxData occurs
                    //This should be after all AuHeaders... e.g. @ auHeaderLengthBytes
                    auxHeaderOffset = offset;

                    //Note that when used in a BigEndian system that the Media.Common.Binary.ReadBigEndianInteger should be used.

                    //Read the size in bits of that section
                    int auxDataSizeBits = (int)Media.Common.Binary.ReadBitsMSB(packet.Payload.Array, ref bitOffset, auxDataSizeLength);

                    if (auxDataSizeBits > 0)
                    {
                        //Calculate the amount of bytes in the auxillary data section
                        auxLengthBytes = (int)Media.Common.Binary.BitsToBytes(ref auxDataSizeBits);

                        //Ensure the amount of bytes indicated in the section are present in the contained data
                        if (max - offset < auxLengthBytes)
                        {
                            throw new InvalidOperationException("Invalid Au Aux Data?");
                        }

                        //Skip the bits indicated
                        bitOffset += auxDataSizeBits;
                    }

                    // as per 3) skip padding
                    //if (bitOffset > 0)
                    //{
                    //    bitOffset = 0;
                    //    ++offset;
                    //}
                }

                //Default auxData
                Common.MemorySegment auxillaryData = Common.MemorySegment.Empty;

                //If there was any auxillary data
                if (auxLengthBytes > 0)
                {
                    //Get the auxData
                    auxillaryData = new Common.MemorySegment(packet.Payload.Array, auxHeaderOffset, auxLengthBytes);
                }

                #endregion

                //Look for Access Units in the packet
                //Must also track offset.
                while (Common.Binary.BitsToBytes(ref bitOffset) < max)
                {
                    //Should read from auHeaderOffset
                    #region ParseAuHeader

                    #region AU-size

                    /*
                     *    AU-size: Indicates the size in octets of the associated Access Unit
                     *    in the Access Unit Data Section in the same RTP packet.  When the
                     *    AU-size is associated with an AU fragment, the AU size indicates
                     *    the size of the entire AU and not the size of the fragment.  In
                     *    this case, the size of the fragment is known from the size of the
                     *    AU data section.  This can be exploited to determine whether a
                     *    packet contains an entire AU or a fragment, which is particularly
                     *    useful after losing a packet carrying the last fragment of an AU.
                     */

                    if (sizeLength > 0)
                    {
                        //Ensure there are enough bytes required to read the auSize
                        if (sizeLengthBytes > (remainsInAu = (max - offset) - 1))
                        {
                            offset = max;

                            continue;
                        }

                        //Read the bits for the size and the index to align the read.
                        auSize = (int)Media.Common.Binary.ReadBitsMSB(packet.Payload.Array, ref bitOffset, sizeLength);

                        //auSize can never be greater than max.
                        if (auSize >= max)
                        {
                            throw new InvalidOperationException("auSize is larger than expected.");
                        }
                    }
                    else
                    {
                        auSize = constantAuSize;
                    }

                    #endregion

                    //Check for auSize == 0 because there is nothing to consume
                    if (auSize == 0)
                    {
                        //Todo, offset didn't move for the bits just read...

                        continue;
                    }

                    #region AU-Index / AU-Index-delta

                    /*
                     *   AU-Index-delta: The AU-Index-delta field is an unsigned integer that
                     *    specifies the serial number of the associated AU as the difference
                     *    with respect to the serial number of the previous Access Unit.
                     *    Hence, for the n-th (n>1) AU, the serial number is found from:
                     *
                     *    AU-Index(n) = AU-Index(n-1) + AU-Index-delta(n) + 1
                     *
                     *    If the AU-Index field is present in the first AU-header in the AU
                     *    Header Section, then the AU-Index-delta field MUST be present in
                     *    any subsequent (non-first) AU-header.  When the AU-Index-delta is
                     *    coded with the value 0, it indicates that the Access Units are
                     *    consecutive in decoding order.  An AU-Index-delta value larger
                     *    than 0 signals that interleaving is applied.
                     */

                    //This should check that if indexLength == 0 and indexDeltaLength == 0 there is an invalid operation exception
                    //This can be done before we even read into the packet.

                    if (Depacketized.Count == 0 && indexLength > 0)
                    {
                        //Ensure enough data is present to read the bit field
                        if (indexLength > (remainsInAu = (max - offset) - 1))
                        {
                            offset = max;

                            continue;
                        }

                        //Notes that this should be read out of the Au Headers Section for the Au being parsed
                        auIndex = (int)Media.Common.Binary.ReadBitsMSB(packet.Payload.Array, ref bitOffset, indexLength);
                    }
                    else if (indexDeltaLength > 0)//Must be present... should check.
                    {
                        //If Depacketized.Count == 0 this should not occur...

                        //Ensure enough data is present to read the bit field
                        if (indexDeltaLength > (remainsInAu = (max - offset) - 1))
                        {
                            offset = max;

                            bitOffset = Common.Binary.BytesToBits(ref max);

                            continue;
                        }

                        //Notes that this should be read out of the Au Headers Section for the Au being parsed
                        auIndex = (int)Media.Common.Binary.ReadBitsMSB(packet.Payload.Array, ref bitOffset, indexDeltaLength);

                        //An AU-Index-delta value larger than 0 signals that interleaving is applied.

                        if (auIndex == 0)
                        {
                            auIndex = Depacketized.Count + 1;
                        }
                    }

                    #endregion

                    #region CTSDeltaLength

                    //From RFC3640: "The CTS-flag field MUST be present in each AU-header
                    //               if the length of the CTS-delta field is signaled to
                    //               be larger than zero."
                    if (0 != CTSDeltaLength)
                    {
                        bool CTSFlag = Media.Common.Binary.ReadBitsMSB(packet.Payload.Array, ref bitOffset, 1) > 0;
                        if (CTSFlag)
                        {
                            int CTSDelta = (int)Media.Common.Binary.ReadBitsMSB(packet.Payload.Array, ref bitOffset, CTSDeltaLength);
                        }
                    }

                    #endregion

                    #region DTSDeltaLength

                    if (0 != DTSDeltaLength)
                    {
                        bool DTSFlag = Media.Common.Binary.ReadBitsMSB(packet.Payload.Array, ref bitOffset, 1) > 0;
                        if (DTSFlag)
                        {
                            int DTSDelta = (int)Media.Common.Binary.ReadBitsMSB(packet.Payload.Array, ref bitOffset, DTSDeltaLength);
                        }
                    }

                    #endregion

                    #region randomAccessIndication

                    if (randomAccessIndication)
                    {
                        bool RAPFlag = Media.Common.Binary.ReadBitsMSB(packet.Payload.Array, ref bitOffset, 1) > 0;
                    }

                    #endregion

                    #region StreamState

                    //StreamState
                    //https://www.ietf.org/proceedings/54/slides/avt-6.pdf
                    if (0 != streamStateIndication)
                    {
                        //number of bits for Stream-State
                        int streamState = (int)Media.Common.Binary.ReadBitsMSB(packet.Payload.Array, ref bitOffset, streamStateIndication);

                        //Read that many more bits
                        //Media.Common.Binary.ReadBinaryInteger(rtp.Payload.Array, ref offset, ref bitOffset, streamState, Common.Binary.IsLittleEndian);
                        bitOffset += streamState;
                    }

                    #endregion

                    //Might not need to skip padding, this should be determined by auHeaderLengthBits % 8
                    // as per 3) skip padding
                    int localPadding = (bitOffset & 7);
                    if (localPadding > 0) //Common.Binary.Align (bitOffset), ref, out byteOffset
                    {
                        bitOffset += localPadding;
                    }

                    #endregion

                    //Get the header which corresponds to this access unit (note that this should be done in ParseAuHeader)
                    //This should also take into account that the last auHeader may be padded with up to 7 '0' bits.
                    using (var accessUnitHeader = new Common.MemorySegment(packet.Payload.Array, auHeaderOffset, auHeaderLengthBytes, false == includeAuHeaders))
                    {
                        //Use a  auHeader from the header section, if there is more then one move the offset to the next header
                        if (--auHeadersAvailable > 0)
                        {
                            auHeaderOffset += auHeaderLengthBytes;
                        }

                        //Determine how much data remains in the payload
                        int remains = max - (offset - packet.Payload.Offset);

                        //If the size of the accessUnit is greater than what remains
                        if (auSize > remains)
                        {
                            //Indicate that much remains
                            remainsInAu = auSize - remains;

                            //Truncated or Fragmented?

                            //Make auSize equal to what actually remains.
                            auSize = remains;
                        }
                        else
                        {
                            remainsInAu = 0;  //Nothing else remains if the auSize indicated was completely contained in the payload
                        }
                        //Project the data in the payload from the offset of the access unit until its declared size.
                        using (Common.MemorySegment accessUnitData = new Common.MemorySegment(packet.Payload.Array, Common.Binary.BitsToBytes(ref bitOffset), auSize, false))  //offset, auSize))
                        {
                            //Prepend the accessUnitHeaer with the data to create a depacketized au if the option was specified
                            //var depacketizedAccessUnit = includeAuHeaders ? Enumerable.Concat(accessUnitHeader, accessUnitData) : accessUnitData;

                            if (includeAuHeaders)
                            {
                                Depacketized.Add(auIndex++, accessUnitHeader);
                            }

                            //If there aux data then add it after the Au header we just added if the option was specified
                            if (includeAuxData && auxLengthBytes > 0)
                            {
                                //Add the auxillary data
                                //depacketizedAccessUnit = Enumerable.Concat(depacketizedAccessUnit, auxillaryData);

                                Depacketized.Add(auIndex++, auxillaryData);
                            }

                            #region Todo allow partial data from previous parsing, (needs bitOffset to be ref)

                            //If data exists from the previous packet which is not part of the payload
                            //if (previouslyIncompleteAccessUnitWithAuxHeaderAndData != null)
                            //{
                            //    //May have to write the length in the frameData
                            //    depacketizedAccessUnit = Enumerable.Concat(frameHeader, depacketizedAccessUnit);

                            //    previouslyIncompleteAccessUnitWithAuxHeaderAndData = null;
                            //}
                            //else
                            //{
                            //    //Could just update the length but
                            //    //This is a bit field though and needs to have the WriteBits methods available then
                            //    //Media.Common.Binary.Write16(adtsHeader, 6, false, (short)auSize);

                            //    //Create the header for the frame, (should only be done once and the length should be updated each time)
                            //    //Should also have the ADTS header only 1 time, and only after the frameLength is known.
                            //    depacketizedAccessUnit = Enumerable.Concat(CreateADTSHeader(profileId, frequencyIndex, channelConfiguration, auSize), depacketizedAccessUnit);
                            //}

                            #endregion

                            //Add padding if required.. ?Allow custom
                            if (addPadding)
                            {
                                int required = max - offset;

                                //if (required > 0) depacketizedAccessUnit = Enumerable.Concat(depacketizedAccessUnit, Enumerable.Repeat<byte>(byte.MinValue, required));

                                if (required > 0)
                                {
                                    Depacketized.Add(auIndex++, new Common.MemorySegment(Enumerable.Repeat <byte>(byte.MinValue, required).ToArray()));
                                }
                            }

                            //Add the Access Unit to the list (copies memory)
                            if (auSize > 1)
                            {
                                Depacketized.Add(auIndex++, accessUnitData);
                            }

                            //Move the byte offset leaving the bit offset in tact
                            offset += auSize;

                            bitOffset += Common.Binary.BytesToBits(ref auSize);

                            //Keep track of the amount of access units parsed
                            ++parsedAccessUnits;
                        }
                    }
                }

                //Return the access units in decoding order from the lamda, which will be written to the buffer
                return;
            }
예제 #11
0
        /// <summary>
        /// Handles the receiving of UDP packets from the RTP stream
        /// </summary>
        /// <param name="ar">Contains packet data</param>
        private void ReceiveCallback()
        {
            // Begin looking for the next packet
            Console.WriteLine("[RTPServer:ReceiveCallback] Stopwatch is hi res = " + Stopwatch.IsHighResolution);
            int    packetsSentInTimer = 0;
            int    bytesSentInTimer   = 0;
            int    packetsToSend      = 1;
            bool   catchup            = true;
            int    bytesToSend;
            double maxBuffer = SAMPLES_PER_SECOND + 400 * BYTES_PER_MS;
            double minBuffer = SAMPLES_PER_SECOND + 300 * BYTES_PER_MS;

            Console.WriteLine("[RTPServer:] minBuffer: " + minBuffer + " maxBuffer: " + maxBuffer);
            Thread.Sleep(11000);
            packetTimer.Start();
            TimeSpan lastElapsed = packetTimer.Elapsed;

            while (listening)
            {
                if (true)//(packetsToSend > packetsSentInTimer)
                {
                    if (catchup)
                    {
                        bytesToSend = BYTES_PER_PACKET * 4;
                    }
                    else
                    {
                        bytesToSend = BYTES_PER_PACKET;
                    }
                    // Read from the stream
                    byte[] buffer = new byte[bytesToSend];
                    for (int i = 0; i < bytesToSend; i = i + 2)
                    {
                        buffer[i + 1] = Convert.ToByte(0x01);
                        buffer[i]     = Convert.ToByte(0x00);
                    }
                    int bytesRead = audioStream.Read(buffer, 0, bytesToSend);

                    //check if there was a timeout and bytes read is zero. (If timeout but some bytes read just send them)

/*                    if (bytesRead == 0) //will still send the packet to keep pi stream alive
 *                  {
 *
 *                  }
 */
                    //check if blocked on reading from audio stream because there was no audio (over 1 second)
                    //if so reset timer and all packet counts

/*                    if ((packetTimer.ElapsedMilliseconds - lastElapsed.TotalMilliseconds) > 1000)
 *                  {
 *                      Console.WriteLine("[RTPServer]: Reseting packet Timer: time elapsed while listening for packets. pktTimer: " +
 *                          packetTimer.ElapsedMilliseconds + " lastElapsed: " + lastElapsed.TotalMilliseconds);
 *                      packetTimer.Restart();
 *                      lastElapsed = packetTimer.Elapsed;
 *                      packetsSentInTimer = 0; //will increment to 1 after this current packet is sent
 *                      bytesSentInTimer = 0; //will increment after current packet is sent;
 *                      packetsToSend = 1;
 *                  }
 *                  else
 *                  {
 * //                        Console.WriteLine("    sending packet " + packetsSentInTimer + " pktTimer.Elapsed: " + packetTimer.Elapsed);
 * //                        lastElapsed = packetTimer.Elapsed;
 *                  }
 */
                    byte[] newbuff = SwapEndianness(buffer, 2);

                    Media.Rtp.RtpPacket rtpPacket = new Media.Rtp.RtpPacket();
                    rtpPacket.SequenceNumber = mySeqNum;
                    rtpPacket.SynchronizationSourceIdentifier = 0x07070707;
                    rtpPacket.PayloadType = 0x0b;
                    rtpPacket.TimeStamp   = timestamp;
                    rtpPacket.Channel     = 0;
                    rtpPacket.Payload     = newbuff;


                    // Write the bytes to the UDP socket
                    byte[] pkt = rtpPacket.ToBytes();
                    client.Send(pkt, pkt.Length);
                    //Console.WriteLine("read " + pkt.Length + " bytes");

                    mySeqNum++;
                    timestamp = timestamp + Convert.ToUInt32(bytesToSend / 2);
                    packetsSentInTimer++;
                    bytesSentInTimer = bytesSentInTimer + bytesToSend;
                }

/*                else
 *              {
 *                  if ((packetTimer.ElapsedMilliseconds - lastElapsed.TotalMilliseconds) > 1000)
 *                  {
 *                      Console.WriteLine("[RTPServer]: resetting timer in else condition because too much time elapsed pktTimer: " +
 *                          packetTimer.ElapsedMilliseconds + " lastElapsed: " + lastElapsed.TotalMilliseconds);
 *                      packetTimer.Restart();
 *                      lastElapsed = packetTimer.Elapsed;
 *                      packetsSentInTimer = 0; //will increment to 1 after this current packet is sent
 *                      packetsToSend = 1;
 *                  }
 *                  else
 *                  {
 *                      Console.Write(" lastElapsed: " + lastElapsed + " pktTimer.Elapsed: " + packetTimer.Elapsed + " ");
 *                      lastElapsed = packetTimer.Elapsed;
 *                      packetsToSend = Convert.ToInt32(Math.Round(lastElapsed.TotalMilliseconds * BYTES_PER_MS / BYTES_PER_PACKET));
 *                      //packetsToSend = packetsToSendInTimer - packetsSentInTimer;
 *                      Console.WriteLine("lastElapsed(ms): " + lastElapsed.TotalMilliseconds +
 *                          " packetsSentInTimer: " + packetsSentInTimer + " packetsToSend: " + packetsToSend);
 *                  }
 *              }*/

                //if number of bytes sent is greater than .75 seconds more than elapsed time then sleep a little to slow down
                double shouldSend = (packetTimer.ElapsedMilliseconds * BYTES_PER_MS);
                //int bytesSent = packetsSentInTimer*BYTES_PER_PACKET;
//                Console.WriteLine("[RTPServer]: checking for sleep elapsed(ms): " + packetTimer.ElapsedMilliseconds + /*" pktTimer: " + packetTimer.Elapsed +*/
//                    " so should send " + shouldSend  + " bytes so with maxBuffer: " + (shouldSend + maxBuffer) + ". Bytes sent: " + bytesSentInTimer +
//                    " in " + packetsSentInTimer + " packets");
                while ((shouldSend + maxBuffer) < bytesSentInTimer) //as long as we've sent over our max buffer wait
                {
//                                        Console.WriteLine("     [RTPServer]: sleeping ... ");
                    Thread.Sleep(5);
                    //Thread.Sleep(Convert.ToInt32(Math.Round(BYTES_PER_PACKET / BYTES_PER_MS)));
                    //catchup = false;
                    shouldSend = (packetTimer.ElapsedMilliseconds * BYTES_PER_MS);
                }
                if ((shouldSend + minBuffer) > bytesSentInTimer) //if we've dipped below our minBuffer catch up
                {
//                    Console.WriteLine("      [RTPServer}: catchup true");
                    catchup = true;
                }
                else
                {
//                    Console.WriteLine("      [RTPServer}: catchup false");
                    catchup = false;
                }
            }
        }
예제 #12
0
        public void TestNull()
        {
            //base class?
            //UnitTestBase
            Console.WriteLine(System.Reflection.MethodBase.GetCurrentMethod().Name);

            Media.Rtp.RtpClient rtpClient = default(Media.Rtp.RtpClient);

            try { rtpClient = Media.Rtp.RtpClient.FromSessionDescription(default(Media.Sdp.SessionDescription)); }
            catch { }

            System.Diagnostics.Debug.Assert(rtpClient == null, "Must not have created a RtpClient from a null SessionDescription");

            //Create a client
            using (rtpClient = new Media.Rtp.RtpClient())
            {
                //Attempt to find a context
                Media.Rtp.RtpClient.TransportContext contextAvailable = rtpClient.GetTransportContexts().FirstOrDefault();

                System.Diagnostics.Debug.Assert(contextAvailable == null, "Found a Context when there was no Session or Media Description");

                using (contextAvailable = new Media.Rtp.RtpClient.TransportContext(0, 1, 0))
                {
                    //Usually indicated by the profile
                    bool padding = false, extension = false;

                    //Create a RtpPacket from the
                    using (var rtpPacket = new Media.Rtp.RtpPacket(contextAvailable.Version, padding, extension, null))
                    {
                        System.Diagnostics.Debug.Assert(rtpClient.SendRtpPacket(rtpPacket) == 0, "Sent a packet when there was no Session or Media Description or TransportContext");
                    }
                }
            }
        }
예제 #13
0
            private static void Issue17245_Case2(int breakingPaketLength)
            {
                int sequenceNumber = 0x3030;   //  "00"

                System.Console.Clear();
                Console.WriteLine("TestProcessFrameData Issue17245_Case2(): Interleaved RTSPResponse");
                Console.WriteLine("breakingPaketLength = " + breakingPaketLength);
                Console.WriteLine("Correct output is 3 rows saying 'ProcessRtpPacket()...', 1 yellow row, and finaly a single row 'ProcessRtpPacket()...':");
                Console.WriteLine("");

                TestFramework tf = new TestFramework();
                //Console.WriteLine(line + sequenceNumber);
                byte[] buffer = GeneratePayload(1400);
                Media.Rtp.RtpPacket p1 = new Media.Rtp.RtpPacket(2, false, false, false, 0, 0, _senderSSRC, sequenceNumber++, _timeStamp, buffer);
                buffer = p1.Prepare().ToArray();
                tf.Send(GenerateEncapsulatingHeader(buffer.Length));
                tf.Send(buffer);

                //Console.WriteLine(line + sequenceNumber);
                buffer = GeneratePayload(1400);
                Media.Rtp.RtpPacket p2 = new Media.Rtp.RtpPacket(2, false, false, false, 0, 0, _senderSSRC, sequenceNumber++, _timeStamp, buffer);
                buffer = p2.Prepare().ToArray();
                tf.Send(GenerateEncapsulatingHeader(buffer.Length));
                tf.Send(buffer);

                //Console.WriteLine(line + sequenceNumber);
                buffer = GeneratePayload(breakingPaketLength);
                Media.Rtp.RtpPacket p3 = new Media.Rtp.RtpPacket(2, false, false, false, 0, 0, _senderSSRC, sequenceNumber++, _timeStamp, buffer);
                buffer = p3.Prepare().ToArray();
                tf.Send(GenerateEncapsulatingHeader(buffer.Length));
                tf.Send(buffer);

                Media.Rtsp.RtspMessage keepAlive = new Media.Rtsp.RtspMessage(Media.Rtsp.RtspMessageType.Response);
                keepAlive.StatusCode = Media.Rtsp.RtspStatusCode.OK;
                keepAlive.CSeq = 34;
                keepAlive.SetHeader(Media.Rtsp.RtspHeaders.Session, "A9B8C7D6");
                keepAlive.SetHeader(Media.Rtsp.RtspHeaders.UserAgent, "Testing $UserAgent $009\r\n$\0:\0");
                keepAlive.SetHeader("Ignore", "$UserAgent $009\r\n$\0\0\aRTSP/1.0");
                keepAlive.SetHeader("$", string.Empty);
                keepAlive.SetHeader(Media.Rtsp.RtspHeaders.Date, DateTime.Now.ToUniversalTime().ToString("r"));
                buffer = keepAlive.Prepare().ToArray();
                tf.Send(buffer);

                //Console.WriteLine(line + sequenceNumber);
                buffer = GeneratePayload(1400);
                Media.Rtp.RtpPacket p4 = new Media.Rtp.RtpPacket(2, false, false, false, 0, 0, _senderSSRC, sequenceNumber++, _timeStamp, buffer);
                buffer = p4.Prepare().ToArray();
                tf.Send(GenerateEncapsulatingHeader(buffer.Length));
                tf.Send(buffer);

                //  Kick of the processing eventually ending up in RtpClient.ProcessFrameData()
                tf.HaveRtpClientWorkerThreadProcessSocketData();
            }
예제 #14
0
            private static void Issue17245_Case1(int breakingPaketLength)
            {
                int sequenceNumber = 0x3030;   //  "00"
                string line = "Case1(): SequenceNumber = ";

                System.Console.Clear();
                Console.WriteLine("TestProcessFrameData Issue17245_Case1(): Discarding of Encapsulating Frame Header");
                Console.WriteLine("breakingPaketLength = " + breakingPaketLength);
                Console.WriteLine("Correct output is 5 rows saying 'Case1()...' and 5 rows 'ProcessRtpPacket()...'");
                Console.WriteLine("No yellow rows!!!");
                Console.WriteLine("");

                TestFramework tf = new TestFramework();

                Console.WriteLine(line + sequenceNumber);
                byte[] buffer = GeneratePayload(1400);
                Media.Rtp.RtpPacket p1 = new Media.Rtp.RtpPacket(2, false, false, false, 0, 0, _senderSSRC, sequenceNumber++, _timeStamp, buffer);
                buffer = p1.Prepare().ToArray();
                tf.Send(GenerateEncapsulatingHeader(buffer.Length));
                tf.Send(buffer);

                Console.WriteLine(line + sequenceNumber);
                buffer = GeneratePayload(1400);
                Media.Rtp.RtpPacket p2 = new Media.Rtp.RtpPacket(2, false, false, false, 0, 0, _senderSSRC, sequenceNumber++, _timeStamp, buffer);
                buffer = p2.Prepare().ToArray();
                tf.Send(GenerateEncapsulatingHeader(buffer.Length));
                tf.Send(buffer);

                Console.WriteLine(line + sequenceNumber);
                buffer = GeneratePayload(breakingPaketLength); //  Length 1245 to 1247 looses packets and it does not recover
                Media.Rtp.RtpPacket p3 = new Media.Rtp.RtpPacket(2, false, false, false, 0, 0, _senderSSRC, sequenceNumber++, _timeStamp, buffer);
                buffer = p3.Prepare().ToArray();
                tf.Send(GenerateEncapsulatingHeader(buffer.Length));
                tf.Send(buffer);

                Console.WriteLine(line + sequenceNumber);
                buffer = GeneratePayload(1400);
                Media.Rtp.RtpPacket p4 = new Media.Rtp.RtpPacket(2, false, false, false, 0, 0, _senderSSRC, sequenceNumber++, _timeStamp, buffer);
                buffer = p4.Prepare().ToArray();
                tf.Send(GenerateEncapsulatingHeader(buffer.Length));
                tf.Send(buffer);

                Console.WriteLine(line + sequenceNumber);
                buffer = GeneratePayload(1400);
                Media.Rtp.RtpPacket p5 = new Media.Rtp.RtpPacket(2, false, false, false, 0, 0, _senderSSRC, sequenceNumber++, _timeStamp, buffer);
                buffer = p5.Prepare().ToArray();
                tf.Send(GenerateEncapsulatingHeader(buffer.Length));
                tf.Send(buffer);

                //  Kick of the processing eventually ending up in RtpClient.ProcessFrameData()
                tf.HaveRtpClientWorkerThreadProcessSocketData();
            }