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("Duplicate packet received!", EventLogEntryType.Warning, (int)RtpEL.ID.DuplicatePacketReceived); return; } fecPxAct++; dataPx[dataPxExp + checksumFecIndex] = packet; data[dataPxExp + checksumFecIndex] = packet.Payload; recovery[recoveryIndex++] = getBufferHandler(); } }
internal void ReturnFecPacket(RtpPacketFec packet) { Debug.Assert(packet != null); packet.Reset(); fecPool.Push(packet); }
internal void SendPacketFec(RtpPacketFec packet) { packet.Sequence = fecSeq++; packet.DataRangeMin = dataRangeMin; packet.PacketsInFrame = cDataPx; packet.SSRC = SSRC; packet.FecIndex = checksumFecIndex++; rtpNetworkSender.Send((BufferChunk)packet); fecPackets++; fecBytes += packet.PayloadSize; }
protected void SendPacketsFec() { checksumFecIndex = 0; for (int i = 0; i < cFecPx; i++) { RtpPacketFec packet = checksumPx[i]; packet.PayloadSize = checksum[i].Length; SendPacketFec(packet); checksum[i].Reset(checksum[i].Index, 0); } // Clear cache of data packets ClearData(); }
/// <summary> /// Initialize storage for Data and Checksum /// </summary> protected void InitializeDCStorage() { dataPx = new RtpPacket[cDataPx]; data = new BufferChunk[cDataPx]; ReturnFecPackets(); checksumPx = new RtpPacketFec[cFecPx]; checksum = new BufferChunk[cFecPx]; for (int i = 0; i < cFecPx; i++) { RtpPacketFec packet = GetPacketFec(); checksumPx[i] = packet; checksum[i] = packet.Payload; } }
// 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 (frame 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); }
/// <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); } } } }
// 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 (frame 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; }
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("Duplicate packet received!", EventLogEntryType.Warning, (int)RtpEL.ID.DuplicatePacketReceived); return; } fecPxAct++; dataPx[dataPxExp + checksumFecIndex] = packet; data[dataPxExp + checksumFecIndex] = packet.Payload; recovery[recoveryIndex++] = getBufferHandler(); } }
/// <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); } } } }