RtpPacketFec is a forward error correction packet. It is used to provide error correction for data packets that may become lost. It has a fixed payload type PayloadType.FEC The normal Rtp Timestamp has been repurposed in order to save bytes. It is split into... FecIndex - the index of this packet within the fec packet[]. The size of the fec packet[] is either determined by the constant fec ratio, or the percent coverage across a chunk. DataRangeMin - the starting data packet sequence number for which this packet provides coverage. PacketsInFrame - how many packets are in a chunk. Used in the event that no data packets are received, but enough fec packets arrive to recover the data. 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.FEC | sequence number | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | DataRangeMin | PacketsInFrame | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | synchronization source (SSRC) identifier | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | FecIndex | +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
Inheritance: RtpPacketBase
Example #1
0
        private void ProcessPacketFec(RtpPacketFec packet)
        {
            pcFecPacketsLost += LostPackets(ref maxFecSeq, packet.Sequence);
            pcFecPackets++;
            pcFecBytes += packet.PayloadSize;

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

                int checksumFecIndex = packet.FecIndex;

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

                fecPxAct++;

                dataPx[dataPxExp + checksumFecIndex] = packet;
                data[dataPxExp + checksumFecIndex] = packet.Payload;

                recovery[recoveryIndex++] = getBufferHandler();
            }
        }
Example #2
0
        // Check to see if packet is inside the recovery range
        protected bool InRangeFec(RtpPacketFec packet)
        {
            bool inRange = true;

            if (rangeInitialized)
            {
                ushort minDiff = unchecked((ushort)(packet.DataRangeMin - minSeq));

                // Correct data range but not needed - late (chunk already complete)
                // OR Wrong data range - really late
                if ((minDiff == 0 && (dataPxAct + fecPxAct == 0)) || minDiff > HALF_USHORT_MAX)
                {
                    inRange = false;
                    pcFecPacketsLate++;
                    ReturnFecBuffer(packet.ReleaseBuffer());
                }
                else if (minDiff != 0) // Wrong data range - too new
                {
                    Undecodable();
                }
            }

            return inRange;
        }
Example #3
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);
                    }
                }
            }
        }