Beispiel #1
0
        internal override void SendPacket(RtpPacket rtpPacket)
        {
            // Set the FecIndex of the packet
            rtpPacket.FecIndex = dataFecIndex;

            // Store the packet in 2 formats
            dataPx[dataFecIndex] = rtpPacket;
            data[dataFecIndex] = (BufferChunk)rtpPacket;

            dataFecIndex++;

            // The packet is still valid after the Send
            base.SendPacket(rtpPacket);

            // See if we have reached the time to send FEC packets
            if(dataFecIndex == cDataPx)
            {
                dataFecIndex = 0;
                dataRangeMin = dataPx[0].Sequence;

                fecEncoder.Encode(data, checksum);
                SendPacketsFec();
            }
        }
Beispiel #2
0
        /// <summary>
        /// DistributePackets is responsible for receiving all incoming packets on the Rtp Listener,
        /// casting them 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();
                    
                    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);
                        }
                        
                    
                        #region Fault Injection
                        #if FaultInjection
                        if(rtpSession.DropPacketsPercent > 0 )
                        {
                            if (rtpSession.Rnd.Next(1,100) <= rtpSession.DropPacketsPercent)
                            {
                                if(packet.PayloadType == PayloadType.FEC)
                                {
                                    RtpPacketFec fecPacket = (RtpPacketFec)packet;

                                    string msg = string.Format(
                                        "Dropping fec packet: {0}, FecIndex: {1}, DataRangeMin: {2}",
                                        fecPacket.Sequence, fecPacket.FecIndex, fecPacket.DataRangeMin);

                                    Trace.WriteLine(msg);

                                    pcDroppedFecPackets++;
                                    pcDroppedFecBytes += packet.PayloadSize;
                                }
                                else
                                {
                                    RtpPacket dataPacket = (RtpPacket)packet;

                                    string msg = string.Format(
                                        "Dropping data packet: {0}, FecIndex: {1}, FrameIndex: {2}, TS: {3}",
                                        dataPacket.Sequence, dataPacket.FecIndex, dataPacket.FrameIndex, dataPacket.TimeStamp);

                                    Trace.WriteLine(msg);

                                    pcDroppedDataPackets++;
                                    pcDroppedDataBytes += packet.PayloadSize;
                                }

                                ReturnBuffer(bc);
                                continue;
                            }
                        }
                        #endif
                        #endregion Fault Injection

                        // 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);
                    }
                }
            }
        }
Beispiel #3
0
        internal virtual void SendPacket(RtpPacket rtpPacket)
        {
            rtpPacket.SSRC = ssrc;
            rtpPacket.Sequence = seq++;

            rtpNetworkSender.Send((BufferChunk)rtpPacket);
        }
Beispiel #4
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;
                }
            }
        }
Beispiel #5
0
        /// <summary>
        /// newPacket is how RtpListener sends an incoming RtpPacket who's SSRC matches this
        /// RtpStream into the RtpStream's queue for processing
        /// 
        /// This method assumes there is only one thread calling newPacket
        /// </summary>
        internal virtual void ProcessPacket(RtpPacket packet)
        {
            int frame_Index = 0;
            int packets_Size = 0;

            #region Mark this stream and its participant as not stale
            stale = 0;
            // TODO - trade SdesData for Participant JVE
            // TODO - mark participant or we will destory and recreate streams JVE
//            if (participant != null)
//            {
//                participant.stale = 0;
//            }
            #endregion

            // Mark raw packet received
            packetsLost += LostPackets(ref maxSeq, packet.Sequence);
            packetsReceived++;
            bytesReceived += packet.PayloadSize;

            #region Reject Late Packets

            uint packetTS = packet.TimeStamp;
            uint deltaTS = 0;

            if (packetsReceived != 1) // Skip this test if we're in a startup state
            {
                deltaTS = unchecked(packetTS - currentFrameTS);

                if (deltaTS > HALF_UINT_MAX)
                {
                    packetsReceivedLate++;
                    returnBufferHandler(packet.ReleaseBuffer());
                    return;
                }
            }

            #endregion

            // A packet from a future frame has been received, so send out the incomplete current frame
            // Note we cannot check for deltaTS == 1 because we may miss more than 1 frame
            if (deltaTS > 0)
            {
                if(frame != null)
                {
                    frame.Dispose();
                    frame = null;
                }

                RtpRetransmit.FrameIncomplete(this, (int)deltaTS);
            }

            // We're receiving the first packet for a new frame
            if (frame == null) 
            {
                frame = new RtpFrame(128, packetTS, returnBufferHandler);
                currentFrameTS = packetTS;
            }

            try
            {
                // Store the packet
                // payload type is jpeg
                frame_Index = packet.JpgOffset/packet.MaxPayloadSize;
                frame.ApproximatePacketsInFrame((uint)frame_Index + 1);
                frame[frame_Index] = packet;
            }
            catch(DuplicatePacketException)
            {
                // Note: We have already updated the performance counters for these bytes / this packet
                // and we are rejecting it now.  So pcs could be higher than expected.
                eventLog.WriteEntry("Duplicate packet received in RtpStream - " + packet.ToString(), 
                    EventLogEntryType.Error, (int)RtpEL.ID.DuplicatePacketReceived);

                return;
            }

            // We've received the correct number of data packets, so we can now re-create the frame
            //if (frame.Complete)
            if (packet.Marker)
            {
                packets_Size = frame_Index + 1;
                frame.PacketsInFrame = (uint)packets_Size;
            }

            if (frame.Complete)
            {
                // Raise the event
                OnFrameReceivedEvent(frame.Data);

                // Clean up frame - like returning packets to RtpListener
                frame.Dispose();
                frame = null;

                // CXP RtpSenders increment by 1, to do otherwise is a signal from the Sender
                // which means the stream needs to know what the signal means
                currentFrameTS++; 
            }
        }
Beispiel #6
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;
        }
Beispiel #7
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("Duplicate packet received!", EventLogEntryType.Warning,
                        (int)RtpEL.ID.DuplicatePacketReceived);
                    return;
                }

                dataPxAct++;

                dataPx[dataFecIndex] = packet;
                data[dataFecIndex] = (BufferChunk)packet;
            }
        }
Beispiel #8
0
        private RtpPacket GetPacket(int index)
        {
            RtpPacket rtpPacket = pool[index];

            if(rtpPacket == null)
            {
                rtpPacket = new RtpPacket((int)packetSize);
                rtpPacket.PayloadType = payloadType;
                rtpPacket.SSRC = streamSsrc;

                pool[index] = rtpPacket;

                packetsInFramePool = (uint)index + 1;
            }
            rtpPacket.Marker = false; // allway reset

            return rtpPacket;
        }
Beispiel #9
0
        private void GrowPool(uint packets)
        {
            // Use a local so that we don't change the member variable until everything is committed
            uint localPoolLength = poolLength;

            // Startup condition
            if(localPoolLength == 0)
            {
                localPoolLength = poolInitialSize;
            }

            // Determine amount of growth necessary
            while(packets > localPoolLength)
            {
                poolGrows++;

                if(poolGrows > poolGrowsMax)
                {
                    throw new FrameTooLargeException();
                }

                localPoolLength *= poolGrowthFactor;
            }

            // Copy old packets
            RtpPacket[] clone = new RtpPacket[localPoolLength];

            for(int i = 0; i < packetsInFramePool; i++)
            {
                clone[i] = pool[i];
            }

            pool = clone;
            poolLength = localPoolLength;
        }
Beispiel #10
0
        /// <summary>
        /// newPacket is how RtpListener sends an incoming RtpPacket who's SSRC matches this
        /// RtpStream into the RtpStream's queue for processing
        ///
        /// This method assumes there is only one thread calling newPacket
        /// </summary>
        internal virtual void ProcessPacket(RtpPacket packet)
        {
            int frame_Index  = 0;
            int packets_Size = 0;

            #region Mark this stream and its participant as not stale
            stale = 0;
            // TODO - trade SdesData for Participant JVE
            // TODO - mark participant or we will destory and recreate streams JVE
//            if (participant != null)
//            {
//                participant.stale = 0;
//            }
            #endregion

            // Mark raw packet received
            packetsLost += LostPackets(ref maxSeq, packet.Sequence);
            packetsReceived++;
            bytesReceived += packet.PayloadSize;

            #region Reject Late Packets

            uint packetTS = packet.TimeStamp;
            uint deltaTS  = 0;

            if (packetsReceived != 1) // Skip this test if we're in a startup state
            {
                deltaTS = unchecked (packetTS - currentFrameTS);

                if (deltaTS > HALF_UINT_MAX)
                {
                    packetsReceivedLate++;
                    returnBufferHandler(packet.ReleaseBuffer());
                    return;
                }
            }

            #endregion

            // A packet from a future frame has been received, so send out the incomplete current frame
            // Note we cannot check for deltaTS == 1 because we may miss more than 1 frame
            if (deltaTS > 0)
            {
                if (frame != null)
                {
                    frame.Dispose();
                    frame = null;
                }

                RtpRetransmit.FrameIncomplete(this, (int)deltaTS);
            }

            // We're receiving the first packet for a new frame
            if (frame == null)
            {
                frame          = new RtpFrame(128, packetTS, returnBufferHandler);
                currentFrameTS = packetTS;
            }

            try
            {
                // Store the packet
                // payload type is jpeg
                frame_Index = packet.JpgOffset / packet.MaxPayloadSize;
                frame.ApproximatePacketsInFrame((uint)frame_Index + 1);
                frame[frame_Index] = packet;
            }
            catch (DuplicatePacketException)
            {
                // Note: We have already updated the performance counters for these bytes / this packet
                // and we are rejecting it now.  So pcs could be higher than expected.
                eventLog.WriteEntry("Duplicate packet received in RtpStream - " + packet.ToString(),
                                    EventLogEntryType.Error, (int)RtpEL.ID.DuplicatePacketReceived);

                return;
            }

            // We've received the correct number of data packets, so we can now re-create the frame
            //if (frame.Complete)
            if (packet.Marker)
            {
                packets_Size         = frame_Index + 1;
                frame.PacketsInFrame = (uint)packets_Size;
            }

            if (frame.Complete)
            {
                // Raise the event
                OnFrameReceivedEvent(frame.Data);

                // Clean up frame - like returning packets to RtpListener
                frame.Dispose();
                frame = null;

                // CXP RtpSenders increment by 1, to do otherwise is a signal from the Sender
                // which means the stream needs to know what the signal means
                currentFrameTS++;
            }
        }