码迷,mamicode.com
首页 > 其他好文 > 详细

live555分析:RTPReceptionStats::noteIncomingPacket函数详解

时间:2015-11-02 19:11:24      阅读:1201      评论:0      收藏:0      [点我收藏+]

标签:

//奔函数用于计算抖动,每次接收到一个rtp包后,都会调用此函数计算抖动。
void RTPReceptionStats
::noteIncomingPacket(u_int16_t seqNum, u_int32_t rtpTimestamp,
             unsigned timestampFrequency,
             Boolean useForJitterCalculation,
             struct timeval& resultPresentationTime,
             Boolean& resultHasBeenSyncedUsingRTCP,
             unsigned packetSize) {
  if (!fHaveSeenInitialSequenceNumber) initSeqNum(seqNum);

  ++fNumPacketsReceivedSinceLastReset;  //上次重置后,接收到的rtp包个数。
  ++fTotNumPacketsReceived;                //一共接收到的rtp包个数。
  u_int32_t prevTotBytesReceived_lo = fTotBytesReceived_lo;   //fTotBytesReceived_lo,总共接收到的rtp字节数。
  fTotBytesReceived_lo += packetSize;
  if (fTotBytesReceived_lo < prevTotBytesReceived_lo) { // wrap-around   fTotBytesReceived_lo是一个无符号32位整数,当达到最大值后,会从新开始计算。
    ++fTotBytesReceived_hi;    //    归零次数。
  }

  // Check whether the new sequence number is the highest yet seen:
  unsigned oldSeqNum = (fHighestExtSeqNumReceived&0xFFFF);          //取低16位数据
  unsigned seqNumCycle = (fHighestExtSeqNumReceived&0xFFFF0000);      //取高16位数据
  unsigned seqNumDifference = (unsigned)((int)seqNum-(int)oldSeqNum);
  unsigned newSeqNum = 0;
  if (seqNumLT((u_int16_t)oldSeqNum, seqNum)) { //当前序列号大于前一次的序列号,看似是合法的rtp包。但还是要检测是否出现归零的情况。
    // This packet was not an old packet received out of order, so check it:
    
    if (seqNumDifference >= 0x8000) { //出现归零的情况,0x8000最高位(即16位)上为1,其余位为0,前后序列号差距如此到,假设出现归零的情况。
      // The sequence number wrapped around, so start a new cycle:
      seqNumCycle += 0x10000;
    }
    
    newSeqNum = seqNumCycle|seqNum; // 当前序列号和循坏次数做一个组合。
    if (newSeqNum > fHighestExtSeqNumReceived) { //当新的序号比前一次的序列号小时,if语句会有可能为true。
      fHighestExtSeqNumReceived = newSeqNum;  //新的组合保存到成员变量里面。
    }
  } else if (fTotNumPacketsReceived > 1) { //先前已经接收到了rtp包。有rtp包已经存在。
    // This packet was an old packet received out of order
    
    if ((int)seqNumDifference >= 0x8000) {//出现归零的情况,0x8000最高位(即16位)上为1,其余位为0,前后序列号差距如此到,假设出现归零的情况。
      // The sequence number wrapped around, so switch to an old cycle:
      seqNumCycle -= 0x10000;     //上次出现了一次归零的情况,所以这里要把循坏次数减一。
    }
    
    //这里的代码,上面出现过,见上面的解释。
    newSeqNum = seqNumCycle|seqNum;
    if (newSeqNum < fBaseExtSeqNumReceived) {
      fBaseExtSeqNumReceived = newSeqNum;
    }
  }

  // Record the inter-packet delay
  struct timeval timeNow;
  gettimeofday(&timeNow, NULL);
  if (fLastPacketReceptionTime.tv_sec != 0
      || fLastPacketReceptionTime.tv_usec != 0) {
    unsigned gap          //计算rtp包的时间间隔。单位:一百万分之一秒,微秒,1/1000000秒。
      = (timeNow.tv_sec - fLastPacketReceptionTime.tv_sec)*MILLION
      + timeNow.tv_usec - fLastPacketReceptionTime.tv_usec; 
    if (gap > fMaxInterPacketGapUS) {  //记录出现过的最大rtp包时间间隔。
      fMaxInterPacketGapUS = gap;
    }
    if (gap < fMinInterPacketGapUS) {  //记录出现过的最小rtp包时间间隔。
      fMinInterPacketGapUS = gap;
    }
    fTotalInterPacketGaps.tv_usec += gap; //fTotalInterPacketGaps,两个rtp包到达的时间间隔累计。
    if (fTotalInterPacketGaps.tv_usec >= MILLION) { //数学计算,进1。
      ++fTotalInterPacketGaps.tv_sec;
      fTotalInterPacketGaps.tv_usec -= MILLION;
    }
  }
  fLastPacketReceptionTime = timeNow;  //fLastPacketReceptionTime,记录rtp包抵达的时间。

  // Compute the current ‘jitter‘ using the received packet‘s RTP timestamp,
  // and the RTP timestamp that would correspond to the current time.
  // (Use the code from appendix A.8 in the RTP spec.)
  // Note, however, that we don‘t use this packet if its timestamp is
  // the same as that of the previous packet (this indicates a multi-packet
  // fragment), or if we‘ve been explicitly told not to use this packet.
  /*
   * 如果当前rtp包时间戳和上一个rtp包时间戳相同,不用此rtp包计算抖动。fPreviousPacketRTPTimestamp==rtpTimestamp。
  */

  if (useForJitterCalculation
      && rtpTimestamp != fPreviousPacketRTPTimestamp) {         //rtpTimestamp,rtp包头部记录的时间戳。
    unsigned arrival = (timestampFrequency*timeNow.tv_sec);
    arrival += (unsigned)  //计算rtp包的理论抵达时间。
      ((2.0*timestampFrequency*timeNow.tv_usec + 1000000.0)/2000000);
            // note: rounding
    int transit = arrival - rtpTimestamp;  //理论和实际的时间差值。
    if (fLastTransit == (~0)) fLastTransit = transit; // hack for first time  //如果是第一个rtp包。
    int d = transit - fLastTransit;        //求本次差值和上次差值的差异。
    fLastTransit = transit;        //把当前差值放到上次差值成员变量里面,下次使用。
    if (d < 0) d = -d;   //取正数。
    fJitter += (1.0/16.0) * ((double)d - fJitter);   //计算出抖动值。每次d的权重会越来越低,变体为:( (double)d )/16 + (15.0/16.0)*fJitter。
  }

  // Return the ‘presentation time‘ that corresponds to "rtpTimestamp": //根据rtp头部的时间戳,计算显现时间。
  if (fSyncTime.tv_sec == 0 && fSyncTime.tv_usec == 0) {
    // This is the first timestamp that we‘ve seen, so use the current
    // ‘wall clock‘ time as the synchronization time.  (This will be
    // corrected later when we receive RTCP SRs.)
    fSyncTimestamp = rtpTimestamp;     //fSyncTimestamp上次的rtp头部时间戳。
    fSyncTime = timeNow;            //fSyncTime上次计算出来的呈现时间,基于接收端的本地时间,gettimeofday(&timeNow, NULL);。
  }

  int timestampDiff = rtpTimestamp - fSyncTimestamp;  //rtp头部时间戳和上次的rtp头部时间戳的差值。
      // Note: This works even if the timestamp wraps around
      // (as long as "int" is 32 bits)

  //timestampFrequency,采样率,每秒钟采样的数量。
  //rtpTimestamp,设备每采样一次,时间戳递增1。
  // Divide this by the timestamp frequency to get real time:
  double timeDiff = timestampDiff/(double)timestampFrequency; //获取前后rtp包的时间差,单位为妙。

  // Add this to the ‘sync time‘ to get our result:
  unsigned const million = 1000000;
  unsigned seconds, uSeconds;
  if (timeDiff >= 0.0) {
    seconds = fSyncTime.tv_sec + (unsigned)(timeDiff);  //取秒数。
    uSeconds = fSyncTime.tv_usec
      + (unsigned)((timeDiff - (unsigned)timeDiff)*million); //取微妙数。
    if (uSeconds >= million) {
      uSeconds -= million;
      ++seconds;
    }
  } else {    //timeDiff的负数这种情况的处理。
                      //如果当前rtp包的序列号小于前一次rtp包的序列号,并且它们的时间戳不同,就会有这种负数的情况。
    timeDiff = -timeDiff;
    seconds = fSyncTime.tv_sec - (unsigned)(timeDiff);
    uSeconds = fSyncTime.tv_usec
      - (unsigned)((timeDiff - (unsigned)timeDiff)*million);
    if ((int)uSeconds < 0) {
      uSeconds += million;
      --seconds;
    }
  }
  //已经计算出要呈现的时间,通过resultPresentationTime返回时间数值。
  resultPresentationTime.tv_sec = seconds;
  resultPresentationTime.tv_usec = uSeconds;
  resultHasBeenSyncedUsingRTCP = fHasBeenSynchronized;  //估计用于rtcp使用,标示当前的统计数据有没有被rtcp使用。

  //记录这次同步的时间戳和时间。
  // Save these as the new synchronization timestamp & time:
  fSyncTimestamp = rtpTimestamp;
  fSyncTime = resultPresentationTime;

  fPreviousPacketRTPTimestamp = rtpTimestamp;
}

 

资料:

  rtp抖动--RFC3550,附录A.8 https://www.ietf.org/rfc/rfc3550.txt

  网络图书--《RTP: Audio and Video for the Internet By Colin Perkings》,见:百度网盘\共享\G:\workspace\download\RTP -- Audio and Video for the Internet By Colin Perkings.pdf

 

完。

 

live555分析:RTPReceptionStats::noteIncomingPacket函数详解

标签:

原文地址:http://www.cnblogs.com/liyou-blog/p/4930933.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!