⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rtp.cxx

📁 sloedgy open sip stack source code
💻 CXX
📖 第 1 页 / 共 5 页
字号:


RTP_Session::~RTP_Session()
{
  PTRACE_IF(2, packetsSent != 0 || packetsReceived != 0,
	    "RTP\tFinal statistics:\n"
	    "    packetsSent       = " << packetsSent << "\n"
	    "    octetsSent        = " << octetsSent << "\n"
	    "    averageSendTime   = " << averageSendTime << "\n"
	    "    maximumSendTime   = " << maximumSendTime << "\n"
	    "    minimumSendTime   = " << minimumSendTime << "\n"
	    "    packetsReceived   = " << packetsReceived << "\n"
	    "    octetsReceived    = " << octetsReceived << "\n"
	    "    packetsLost       = " << packetsLost << "\n"
	    "    packetsTooLate    = " << GetPacketsTooLate() << "\n"
	    "    packetsOutOfOrder = " << packetsOutOfOrder << "\n"
	    "    averageReceiveTime= " << averageReceiveTime << "\n"
	    "    maximumReceiveTime= " << maximumReceiveTime << "\n"
	    "    minimumReceiveTime= " << minimumReceiveTime << "\n"
	    "    averageJitter     = " << (jitterLevel >> 7) << "\n"
	    "    maximumJitter     = " << (maximumJitterLevel >> 7)
	   );
  if (autoDeleteUserData)
    delete userData;
  delete jitter;
  
  ResourceCounter::DecrementRTPSession();
}


PString RTP_Session::GetCanonicalName() const
{
  PWaitAndSignal mutex(reportMutex);
  PString s = canonicalName;
  s.MakeUnique();
  return s;
}


void RTP_Session::SetCanonicalName(const PString & name)
{
  PWaitAndSignal mutex(reportMutex);
  canonicalName = name;
}


PString RTP_Session::GetToolName() const
{
  PWaitAndSignal mutex(reportMutex);
  PString s = toolName;
  s.MakeUnique();
  return s;
}


void RTP_Session::SetToolName(const PString & name)
{
  PWaitAndSignal mutex(reportMutex);
  toolName = name;
}


void RTP_Session::SetUserData(RTP_UserData * data, BOOL autoDelete)
{
  if (autoDeleteUserData)
    delete userData;
  userData = data;
  autoDeleteUserData = autoDelete;
}


void RTP_Session::SetJitterBufferSize(unsigned minJitterDelay,
				      unsigned maxJitterDelay,
				      unsigned timeUnits,
				      PINDEX stackSize)
{
  if (minJitterDelay == 0 && maxJitterDelay == 0) {
    delete jitter;
    jitter = NULL;
  }
  else if (jitter != NULL)
    jitter->SetDelay(minJitterDelay, maxJitterDelay);
  else {
    SetIgnoreOutOfOrderPackets(FALSE);
    jitter = new RTP_JitterBuffer(*this, minJitterDelay, maxJitterDelay, timeUnits, stackSize);
  }
}


unsigned RTP_Session::GetJitterBufferSize() const
{
  return jitter != NULL ? jitter->GetJitterTime() : 0;
}

unsigned RTP_Session::GetJitterTimeUnits() const
{
  return jitter != NULL ? jitter->GetTimeUnits() : 0;
}


BOOL RTP_Session::ReadBufferedData(DWORD timestamp, RTP_DataFrame & frame)
{
  if (jitter != NULL)
    return jitter->ReadData(timestamp, frame);
  else
    return ReadData(frame);
}


void RTP_Session::SetTxStatisticsInterval(unsigned packets)
{
  txStatisticsInterval = PMAX(packets, 2);
  txStatisticsCount = 0;
  averageSendTimeAccum = 0;
  maximumSendTimeAccum = 0;
  minimumSendTimeAccum = 0xffffffff;
}


void RTP_Session::SetRxStatisticsInterval(unsigned packets)
{
  rxStatisticsInterval = PMAX(packets, 2);
  rxStatisticsCount = 0;
  averageReceiveTimeAccum = 0;
  maximumReceiveTimeAccum = 0;
  minimumReceiveTimeAccum = 0xffffffff;
}


void RTP_Session::AddReceiverReport(RTP_ControlFrame::ReceiverReport & receiver)
{
  receiver.ssrc = syncSourceIn;
  receiver.SetLostPackets(packetsLost);

  if (expectedSequenceNumber > lastRRSequenceNumber)
    receiver.fraction = (BYTE)((packetsLostSinceLastRR<<8)/(expectedSequenceNumber - lastRRSequenceNumber));
  else
    receiver.fraction = 0;
  packetsLostSinceLastRR = 0;

  receiver.last_seq = lastRRSequenceNumber;
  lastRRSequenceNumber = expectedSequenceNumber;

  receiver.jitter = jitterLevel >> 4; // Allow for rounding protection bits

  // The following have not been calculated yet.
  receiver.lsr = 0;
  receiver.dlsr = 0;

  PTRACE(3, "RTP\tSentReceiverReport:"
	 " ssrc=" << receiver.ssrc
	 << " fraction=" << (unsigned)receiver.fraction
	 << " lost=" << receiver.GetLostPackets()
	 << " last_seq=" << receiver.last_seq
	 << " jitter=" << receiver.jitter
	 << " lsr=" << receiver.lsr
	 << " dlsr=" << receiver.dlsr);
}


RTP_Session::SendReceiveStatus RTP_Session::OnSendData(RTP_DataFrame & frame)
{
  PTimeInterval tick = PTimer::Tick();  // Timestamp set now

  frame.SetSequenceNumber(++lastSentSequenceNumber);
  frame.SetSyncSource(syncSourceOut);

  PTRACE_IF(2, packetsSent == 0, "RTP\tFirst sent data:"
	   " ver=" << frame.GetVersion()
	   << " pt=" << frame.GetPayloadType()
	   << " psz=" << frame.GetPayloadSize()
	   << " m=" << frame.GetMarker()
	   << " x=" << frame.GetExtension()
	   << " seq=" << frame.GetSequenceNumber()
	   << " ts=" << frame.GetTimestamp()
	   << " src=" << frame.GetSyncSource()
	   << " ccnt=" << frame.GetContribSrcCount());

  if (packetsSent != 0 && !frame.GetMarker()) {
    // Only do statistics on subsequent packets
    DWORD diff = (tick - lastSentPacketTime).GetInterval();

    averageSendTimeAccum += diff;
    if (diff > maximumSendTimeAccum)
      maximumSendTimeAccum = diff;
    if (diff < minimumSendTimeAccum)
      minimumSendTimeAccum = diff;
    txStatisticsCount++;
  }

  lastSentTimestamp = frame.GetTimestamp();
  lastSentPacketTime = tick;

  octetsSent += frame.GetPayloadSize();
  packetsSent++;

  // Call the statistics call-back on the first PDU with total count == 1
  if (packetsSent == 1 && userData != NULL)
    userData->OnTxStatistics(*this);

  if (!SendReport())
    return e_AbortTransport;

  if (txStatisticsCount < txStatisticsInterval)
    return e_ProcessPacket;

  txStatisticsCount = 0;

  averageSendTime = averageSendTimeAccum/txStatisticsInterval;
  maximumSendTime = maximumSendTimeAccum;
  minimumSendTime = minimumSendTimeAccum;

  averageSendTimeAccum = 0;
  maximumSendTimeAccum = 0;
  minimumSendTimeAccum = 0xffffffff;

  PTRACE(2, "RTP\tTransmit statistics: "
	 " packets=" << packetsSent <<
	 " octets=" << octetsSent <<
	 " avgTime=" << averageSendTime <<
	 " maxTime=" << maximumSendTime <<
	 " minTime=" << minimumSendTime
	);

  if (userData != NULL)
    userData->OnTxStatistics(*this);

  return e_ProcessPacket;
}


RTP_Session::SendReceiveStatus RTP_Session::OnReceiveData(const RTP_DataFrame & frame)
{
  // Check that the PDU is the right version
  if (frame.GetVersion() != RTP_DataFrame::ProtocolVersion)
    return e_IgnorePacket; // Non fatal error, just ignore

  // Check for if a control packet rather than data packet.
  if (frame.GetPayloadType() > RTP_DataFrame::MaxPayloadType)
    return e_IgnorePacket; // Non fatal error, just ignore

  PTimeInterval tick = PTimer::Tick();  // Get timestamp now

  // Have not got SSRC yet, so grab it now
  if (syncSourceIn == 0)
    syncSourceIn = frame.GetSyncSource();

  // Check packet sequence numbers
  if (packetsReceived == 0) {
    expectedSequenceNumber = (WORD)(frame.GetSequenceNumber() + 1);
    PTRACE(2, "RTP\tFirst receive data:"
	   " ver=" << frame.GetVersion()
	   << " pt=" << frame.GetPayloadType()
	   << " psz=" << frame.GetPayloadSize()
	   << " m=" << frame.GetMarker()
	   << " x=" << frame.GetExtension()
	   << " seq=" << frame.GetSequenceNumber()
	   << " ts=" << frame.GetTimestamp()
	   << " src=" << frame.GetSyncSource()
	   << " ccnt=" << frame.GetContribSrcCount());
  }
  else {
    if (!ignoreOtherSources && frame.GetSyncSource() != syncSourceIn) {
      if (allowSyncSourceInChange) {
	      syncSourceIn = frame.GetSyncSource();
	      allowSyncSourceInChange = FALSE;
      }
      else {
      	PTRACE(2, "RTP\tPacket from SSRC=" << frame.GetSyncSource() << " ignored, expecting SSRC=" << syncSourceIn);
	      return e_IgnorePacket; // Non fatal error, just ignore
      }
    }

    WORD sequenceNumber = frame.GetSequenceNumber();
    if (sequenceNumber == expectedSequenceNumber) {
      expectedSequenceNumber++;
      consecutiveOutOfOrderPackets = 0;
      // Only do statistics on packets after first received in talk burst
      if (!frame.GetMarker()) {
	      DWORD diff = (tick - lastReceivedPacketTime).GetInterval();

	      averageReceiveTimeAccum += diff;
	      if (diff > maximumReceiveTimeAccum)
	        maximumReceiveTimeAccum = diff;
	      if (diff < minimumReceiveTimeAccum)
	        minimumReceiveTimeAccum = diff;
	      rxStatisticsCount++;

	      // The following has the implicit assumption that something that has jitter
	      // is an audio codec and thus is in 8kHz timestamp units.
	      diff *= 8;
	      long variance = diff - lastTransitTime;
	      lastTransitTime = diff;
	      if (variance < 0)
	        variance = -variance;
	      jitterLevel += variance - ((jitterLevel+8) >> 4);
	      if (jitterLevel > maximumJitterLevel)
	        maximumJitterLevel = jitterLevel;
      }
    }
    else if (allowSequenceChange) {
      expectedSequenceNumber = (WORD) (sequenceNumber + 1);
      allowSequenceChange = FALSE;
    }
    else if (sequenceNumber < expectedSequenceNumber) {
      PTRACE(3, "RTP\tOut of order packet, received "
	     << sequenceNumber << " expected " << expectedSequenceNumber
	     << " ssrc=" << syncSourceIn);
      packetsOutOfOrder++;

      // Check for Cisco bug where sequence numbers suddenly start incrementing
      // from a different base.
      if (++consecutiveOutOfOrderPackets > 10) {
        expectedSequenceNumber = (WORD)(sequenceNumber + 1);
	      PTRACE(1, "RTP\tAbnormal change of sequence numbers, adjusting to expect " << expectedSequenceNumber << " ssrc=" << syncSourceIn);
      }

      if (ignoreOutOfOrderPackets)
	      return e_IgnorePacket; // Non fatal error, just ignore
    }
    else {
      unsigned dropped = sequenceNumber - expectedSequenceNumber;
      packetsLost += dropped;
      packetsLostSinceLastRR += dropped;
      PTRACE(3, "RTP\tDropped " << dropped << " packet(s) at " << sequenceNumber
	     << ", ssrc=" << syncSourceIn);
      expectedSequenceNumber = (WORD)(sequenceNumber + 1);
      consecutiveOutOfOrderPackets = 0;
    }
  }

  lastReceivedPacketTime = tick;

  octetsReceived += frame.GetPayloadSize();
  packetsReceived++;

  // Call the statistics call-back on the first PDU with total count == 1
  if (packetsReceived == 1 && userData != NULL)
    userData->OnRxStatistics(*this);

  if (!SendReport())
    return e_AbortTransport;

  if (rxStatisticsCount < rxStatisticsInterval)
    return e_ProcessPacket;

  rxStatisticsCount = 0;

  averageReceiveTime = averageReceiveTimeAccum/rxStatisticsInterval;
  maximumReceiveTime = maximumReceiveTimeAccum;
  minimumReceiveTime = minimumReceiveTimeAccum;

  averageReceiveTimeAccum = 0;
  maximumReceiveTimeAccum = 0;
  minimumReceiveTimeAccum = 0xffffffff;

  PTRACE(2, "RTP\tReceive statistics: "
	 " packets=" << packetsReceived <<
	 " octets=" << octetsReceived <<
	 " lost=" << packetsLost <<
	 " tooLate=" << GetPacketsTooLate() <<
	 " order=" << packetsOutOfOrder <<
	 " avgTime=" << averageReceiveTime <<
	 " maxTime=" << maximumReceiveTime <<
	 " minTime=" << minimumReceiveTime <<
	 " jitter=" << (jitterLevel >> 7) <<
	 " maxJitter=" << (maximumJitterLevel >> 7)
	);

  if (userData != NULL)
    userData->OnRxStatistics(*this);

  return e_ProcessPacket;
}


BOOL RTP_Session::SendReport()
{
  PWaitAndSignal mutex(reportMutex);

  if (reportTimer.IsRunning())
    return TRUE;

  // Have not got anything yet, do nothing
  if (packetsSent == 0 && packetsReceived == 0) {
    reportTimer = reportTimeInterval;
    return TRUE;
  }

  RTP_ControlFrame report;

  // No packets sent yet, so only send RR
  if (packetsSent == 0) {
    // Send RR as we are not transmitting
    report.SetPayloadType(RTP_ControlFrame::e_ReceiverReport);
    report.SetPayloadSize(4+sizeof(RTP_ControlFrame::ReceiverReport));
    report.SetCount(1);

    PUInt32b * payload = (PUInt32b *)report.GetPayloadPtr();
    *payload = syncSourceOut;
    AddReceiverReport(*(RTP_ControlFrame::ReceiverReport *)&payload[1]);
  }
  else {
    report.SetPayloadType(RTP_ControlFrame::e_SenderReport);
    report.SetPayloadSize(sizeof(RTP_ControlFrame::SenderReport));

    RTP_ControlFrame::SenderReport * sender =
      (RTP_ControlFrame::SenderReport *)report.GetPayloadPtr();
    sender->ssrc = syncSourceOut;
    PTime now;
    sender->ntp_sec = now.GetTimeInSeconds()+SecondsFrom1900to1970; // Convert from 1970 to 1900
    sender->ntp_frac = now.GetMicrosecond()*4294; // Scale microseconds to "fraction" from 0 to 2^32
    sender->rtp_ts = lastSentTimestamp;
    sender->psent = packetsSent;
    sender->osent = octetsSent;

    PTRACE(3, "RTP\tSentSenderReport: "
	   " ssrc=" << sender->ssrc
	   << " ntp=" << sender->ntp_sec << '.' << sender->ntp_frac
	   << " rtp=" << sender->rtp_ts
	   << " psent=" << sender->psent
	   << " osent=" << sender->osent);

    if (syncSourceIn != 0) {
      report.SetPayloadSize(sizeof(RTP_ControlFrame::SenderReport) +
			    sizeof(RTP_ControlFrame::ReceiverReport));
      report.SetCount(1);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -