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; } } }
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; } }
// 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; }
/// <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); } } } }