RtpPacket is based on RFC 1889. This class knows how to form a byte array for sending out over the network and how to turn a byte array into Rtp fields and a payload. It is meant to be used as a translation mechanism from bytes to structure and vice versa. This is a lower level class exposed only for use by applications that want intimate details about an individual Rtp packet or want to provide their own transport mechanism. Applications that simply want to send/receive real time data over IP Multicast should instead use RtpSender / RtpListener which handle all aspects of network transport and framing (AKA breaking/assembling large datasets into packet sized chunks). There is a small amount of Rtp protocol intelligence in the class when you use the Next methods. The Next methods assume you are working on RtpPackets in a series and will perform helper functions such as compare Sequence numbers for linearness and NextPayload increments the Sequence number between new packets. This implementation has no support for CSRC identifiers. The Rtp header has the following format: 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 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |V=2|P|X| CC |M| PT | sequence number | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | timestamp | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | synchronization source (SSRC) identifier | +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ | contributing source (CSRC) identifiers (if mixers used) | | .... | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ V = Version P = Padding X = Extensions CC = Count of Contributing Sources M = Marker PT = Payload Type
Inheritance: RtpPacketBase
Exemple #1
0
        private void Decode()
        {
            pcDecodePath++;

            try
            {
                fecDecoder.Decode(data, fecPxExp, recovery);
                dataPxAct = dataPxExp; // Trigger ForwardDataPacketsToBase

                // Cast BufferChunks back into RtpPackets
                int recoveryIndex = 0;
                for (int i = 0; i < dataPxExp; i++)
                {
                    if (dataPx[i] == null)
                    {
                        try
                        {
                            dataPx[i] = new RtpPacket(recovery[recoveryIndex]);
                        }
                        catch (InvalidRtpPacketException e)
                        {
                            //eventLog.WriteEntry(e.ToString(), EventLogEntryType.Error, (int)RtpEL.ID.InvalidPacket);
                            ReturnDataBuffer(recovery[recoveryIndex]);
                        }
                        finally
                        {
                            recovery[recoveryIndex] = null;
                            recoveryIndex++;
                        }
                    }
                }
            }
            catch (ThreadAbortException) { } // Because we catch a generic exception next
            catch (Exception e)
            {
                //eventLog.WriteEntry(e.ToString(), EventLogEntryType.Error, (int)RtpEL.ID.Error);

                // Return recovery packets
                for (int recoveryIndex = 0; recoveryIndex < fecPxAct; recoveryIndex++)
                {
                    ReturnDataBuffer(recovery[recoveryIndex]);
                    recovery[recoveryIndex] = null;
                }
            }
        }
Exemple #2
0
        private void ProcessPacketData(RtpPacket packet)
        {
            pcDataPacketsLost += LostPackets(ref maxDataSeq, packet.Sequence);
            pcDataPackets++;
            pcDataBytes += packet.PayloadSize;

            if (InRangeData(packet))
            {
                // New sequence of packets
                if (dataPxAct + fecPxAct == 0)
                {
                    ResetDecodingState(packet);
                }

                int dataFecIndex = packet.FecIndex;

                // Duplicate packet check for flaky networks
                if (dataPx[dataFecIndex] != null)
                {
                    //eventLog.WriteEntry(Strings.DuplicatePacketReceived, EventLogEntryType.Warning,
                    //    (int)RtpEL.ID.DuplicatePacketReceived);
                    return;
                }

                dataPxAct++;

                dataPx[dataFecIndex] = packet;
                data[dataFecIndex] = (BufferChunk)packet;
            }
        }
Exemple #3
0
        // Check to see if packet is inside the recovery range
        protected bool InRangeData(RtpPacket packet)
        {
            bool inRange = true;

            if (rangeInitialized)
            {
                ushort minDiff = unchecked((ushort)(packet.Sequence - minSeq));
                ushort maxDiff = unchecked((ushort)(maxSeq - packet.Sequence));

                if (minDiff > HALF_USHORT_MAX) // Wrong data range - too late
                {
                    inRange = false;
                    pcDataPacketsLate++;
                    base.ProcessPacket(packet);
                }
                else if (maxDiff > HALF_USHORT_MAX) // Wrong data range - too new
                {
                    Undecodable();
                }
            }

            return inRange;
        }
Exemple #4
0
        /// <summary>
        /// DistributePackets turns packets that came from the listener thread into
        /// RtpPackets, creating new RtpStreams if one doesn't exist for the RtpPacket's 
        /// SSRC, then calling RtpStream.newPacket(rtpPacket) to place the RtpPacket 
        /// into the RtpStream's Queue for processing.
        /// </summary>
        private void DistributePackets()
        {
            while (newPacket.WaitOne())
            {
                while(receivedPackets.Count > 0)
                {
                    //object[] ao = (object[])receivedPackets.Dequeue();
                    object[] ao = null;
                    if (!receivedPackets.TryDequeue(out ao))
                        continue;

                    BufferChunk bc = (BufferChunk)ao[0];
                    IPEndPoint ep = (IPEndPoint)ao[1];

                    try
                    {
                        //Turn the raw UDP packet data into an Rtp packet
                        RtpPacketBase packet = new RtpPacketBase(bc);
                        
                        // For now, we support 2 types of packets - RtpPacket and RtpPacketFec.  If
                        // the number of packet types grows, we may need to push the casting onto
                        // the streams, since they know what type of packets they expect.  For now
                        // we will handle the casting here. JVE 6/17/2004
                        if(packet.PayloadType == PayloadType.FEC)
                        {
                            packet = new RtpPacketFec(packet);
                        }
                        else
                        {
                            packet = new RtpPacket(packet);
                        }
                        
                        // Get the stream if it exists
                        RtpStream stream = rtpSession.GetStream(packet.SSRC, ep.Address);
                        
                        if (stream != null)
                        {
                            stream.ProcessPacket(packet);
                        }
                        else
                        {
                            // Otherwise return the packet to the pool
                            ReturnBuffer(bc);
                            unchecked{pcStreamlessPackets++;}
                        }
                    }
                    catch(ThreadAbortException){}
                    catch (InvalidRtpPacketException e)
                    {
                        HandleInvalidPacket(bc, ep, e.ToString());
                        ReturnBuffer(bc);
                    }
                    catch(PoolExhaustedException e)
                    {
                        //LogEvent(e.ToString(), EventLogEntryType.Error, (int)RtpEL.ID.UnboundedGrowth);
                        return; // Exit the thread gracefully
                    }
                    catch(Exception e)
                    {
                        ReturnBuffer(bc);
                        //LogEvent(e.ToString(), EventLogEntryType.Error, (int)RtpEL.ID.Error);
                    }
                }
            }
        }