WebRTC研究:rrt 时间 之 再次处理以供重传等功能使用

在之前的文章:WebRTC研究:rrt 时间计算 之 接收 SR / RR 包 中讲到,sender 在接收到 RR 包后,会根据包体所携带的 DelayLastSR / LastSR 计算出 RRT 时间,但这个 RRT 时间并不能直接应用到重传等功能中,必须经过二次处理。

二次处理在 ModuleRtpRtcpImpl::Process() 中完成,这个函数在之前的文章:WebRTC研究:rrt 时间计算 之 发送 SR / RR 包 中提到过,它的执行间隔为 5 ms。

具体逻辑:

  • 若本端是发送端:sending_ = true:

    • 判断上一次处理完 RRT 时间之后,本端是否又收到了新的 SR/RR 包,并且距离上一次处理 RRT 时间 已经超过了 1000ms,是的话继续;

    • 遍历所有 remoteReceiveBlock,取出 RTCPReceiver 在收到 RR 包时所记录的最新 RRT 时间,即文章:WebRTC研究:rrt 时间计算 之 接收 SR / RR 包 中第四章节所记录的 reportBlock->RTT,并记录所有 remoteReceiveBlock 中最新 RRT 时间的最大值:max_rtt;

    • 将 max_rtt 与当前时间存入 CallStats 对象的 reports_ 集合中,后续CallStats.Process() 会每隔 1000ms 对 reports_ 进行统计分析,计算出最新的 avg_rtt_ms_ 与 max_rtt_ms_(计算逻辑请参考文章:WebRTC研究:rrt 时间 之 CallStats);

  • 若本端不是发送端:sending_ = false:
    XR 协议相关,与 SR 协议实现类似。若 receiver 也是发送端,那么按照上一步,receiver 同样可计算出 RRT 时间,但若 receiver 仅仅是接收端,则需开启 XR 协议,然后按照此部分计算出 RRT 时间。

    • 判断距离上一次处理 RRT 时间 已经超过了 1000ms,是的话继续;
    • 从 RTCPReceiver 中取出 xr_rr_rtt_ms_(与报文类型 kXrDlrrReportBlock 有关),并与当前时间一起存入 CallStats 对象的 reports_ 集合,交由 CallStats.Process() 后续处理。
  • 若距离上一次处理 RRT 时间已经超过了 1000ms,则取出 CallStats.Process() 处理后的 avg_rtt_ms_,这个 RRT 时间就是最终重传等功能所用到的 RRT 时间。

void ModuleRtpRtcpImpl::Process() 
{
  const int64_t now = clock_->TimeInMilliseconds();

  /* 记录本次处理时间 */
  last_process_time_ = now;

  /* 处理 bitrate */
  const int64_t kRtpRtcpBitrateProcessTimeMs = 10;
  if (now >= last_bitrate_process_time_ + kRtpRtcpBitrateProcessTimeMs) 
  {
    rtp_sender_.ProcessBitrate();
    last_bitrate_process_time_ = now;
  }

  /* rrt 处理时间间隔为 1000ms */
  const int64_t kRtpRtcpRttProcessTimeMs = 1000;
  /* 判断处理 rrt 时间是否到了 */
  bool process_rtt = now >= last_rtt_process_time_ + kRtpRtcpRttProcessTimeMs;

  if (rtcp_sender_.Sending()) 
  {
	/*
	上一次处理完 RRT 时间之后,本端又收到了新的 SR/RR 包,
	并且距离上一次处理 RRT 时间 已经超过了 1000ms
	*/
    if (rtcp_receiver_.LastReceivedReceiverReport() > last_rtt_process_time_ && process_rtt) 
	{
	  /*
	  遍历 std::map<uint32_t, std::map<uint32_t, RTCPHelp::RTCPReportBlockInformation*> > _receivedReportBlockMap,
	  收集内层 value:RTCPReportBlockInformation 中的 remoteReceiveBlock 值
	  */
      std::vector<RTCPReportBlock> receive_blocks;
      rtcp_receiver_.StatisticsReceived(&receive_blocks);
      
      /* 遍历 remoteReceiveBlock,获取最大 RRT */
      int64_t max_rtt = 0;
      for (std::vector<RTCPReportBlock>::iterator it = receive_blocks.begin(); it != receive_blocks.end(); ++it) 
	  {
		/*
		取出 RTCPReceiver 在收到 RR 包时所记录的 最新/平均/最小/最大 RRT 时间,
		本别对应函数的第2~第5个参数,参数为NULL,表示不需要获取对应的值
		*/
        int64_t rtt = 0;
        rtcp_receiver_.RTT(it->remoteSSRC, &rtt, NULL, NULL, NULL);
        max_rtt = (rtt > max_rtt) ? rtt : max_rtt;
      }

      /*
	  将 max_rtt 与 当前时间 存入 list:reports_,
	  后续 CallStats.Process() 会每隔 1000ms 对 reports_ 进行统计分析,计算出最新的 avg_rtt_ms_ 与 max_rtt_ms_
	  */
      if (rtt_stats_ && max_rtt != 0)
        rtt_stats_->OnRttUpdate(max_rtt);
    }

    // Verify receiver reports are delivered and the reported sequence number
    // is increasing.

	/* 时间间隔,audio:5000ms */
    int64_t rtcp_interval = RtcpReportInterval();

	/*
	判断接收 RR包 是否超时,
	超时时间:距离上一次接收到 RR包 超过 3*5000 ms
	*/
    if (rtcp_receiver_.RtcpRrTimeout(rtcp_interval)) 
	{
      LOG_F(LS_WARNING) << "Timeout: No RTCP RR received.";
    }
	else if (rtcp_receiver_.RtcpRrSequenceNumberTimeout(rtcp_interval)) 
	{
      LOG_F(LS_WARNING) <<
          "Timeout: No increase in RTCP RR extended highest sequence number.";
    }

    if (remote_bitrate_ && rtcp_sender_.TMMBR()) 
	{
      unsigned int target_bitrate = 0;
      std::vector<unsigned int> ssrcs;
      if (remote_bitrate_->LatestEstimate(&ssrcs, &target_bitrate)) 
	  {
        if (!ssrcs.empty()) 
		{
          target_bitrate = target_bitrate / ssrcs.size();
        }
        rtcp_sender_.SetTargetBitrate(target_bitrate);
      }
    }
  } 
  else 
  {
    // Report rtt from receiver.
    if (process_rtt) 
	{
	   /* 取出 xr_rr_rtt_ms_ 并将其重置为0,同时更新 list:reports_ */
       int64_t rtt_ms;
       if (rtt_stats_ && rtcp_receiver_.GetAndResetXrRrRtt(&rtt_ms)) 
	   {
		 /* 将 rrt时间 与 当前时间 存入 list:reports_ */
         rtt_stats_->OnRttUpdate(rtt_ms);
       }
    }
  }

  // Get processed rtt.
  if (process_rtt) 
  {
	/* 基本本次处理 rrt 时间 */
    last_rtt_process_time_ = now;
    if (rtt_stats_) 
	{
	  // 从 CallStats 对象中取出 avg_rtt_ms_
      int64_t last_rtt = rtt_stats_->LastProcessedRtt();

	  /* 保存 avg_rtt_ms_,后续重传 RTP 包等都需要用到 */
      if (last_rtt >= 0)
        set_rtt_ms(last_rtt);
    }
  }

  /*
  判断发送 RTP 包的时间是否到达
  对于 audio,RTP 包的发送间隔是 5000ms
  */
  if (rtcp_sender_.TimeToSendRTCPReport()) 
  {
	/*
	获取 上一次收到的 SR 包中所携带的 NTP 时间戳、收到 SR 包时本地时间戳等信息
	*/
    RTCPSender::FeedbackState state = GetFeedbackState();
    // Prevent sending streams to send SR before any media has been sent.
    if (!rtcp_sender_.Sending() || state.packets_sent > 0)
      rtcp_sender_.SendRTCP(state, kRtcpReport); /* 发送RTP包 并计算下一次发送 RTP包的时间 */
  }

  if (UpdateRTCPReceiveInformationTimers()) 
  {
    // A receiver has timed out
    rtcp_receiver_.UpdateTMMBR();
  }
}

一、获取最近接收到 SR/RR 包时间:

int64_t RTCPReceiver::LastReceivedReceiverReport() const 
{
  rtc::CritScope lock(&_criticalSectionRTCPReceiver);
  int64_t last_received_rr = -1;

  for (ReceivedInfoMap::const_iterator it = _receivedInfoMap.begin(); it != _receivedInfoMap.end(); ++it) 
  {
    if (it->second->lastTimeReceived > last_received_rr) 
	{
      last_received_rr = it->second->lastTimeReceived;
    }
  }
  return last_received_rr;
}

二、取出 RTCPReceiver 在收到 RR 包时所记录的 最新/平均/最小/最大 RRT 时间:

int32_t RTCPReceiver::RTT(uint32_t remoteSSRC,
                          int64_t* RTT,
                          int64_t* avgRTT,
                          int64_t* minRTT,
                          int64_t* maxRTT) const 
{
  rtc::CritScope lock(&_criticalSectionRTCPReceiver);

  RTCPReportBlockInformation* reportBlock = GetReportBlockInformation(remoteSSRC, main_ssrc_);

  if (reportBlock == NULL) 
  {
    return -1;
  }

  if (RTT) 
  {
    *RTT = reportBlock->RTT;
  }

  if (avgRTT) 
  {
    *avgRTT = reportBlock->avgRTT;
  }

  if (minRTT) 
  {
    *minRTT = reportBlock->minRTT;
  }

  if (maxRTT) 
  {
    *maxRTT = reportBlock->maxRTT;
  }

  return 0;
}

三、更新 CallStats 对象的 reports_ 集合:

virtual void OnRttUpdate(int64_t rtt) 
{
  owner_->OnRttUpdate(rtt);
}
void CallStats::OnRttUpdate(int64_t rtt) 
{
  rtc::CritScope cs(&crit_);
  int64_t now_ms = clock_->TimeInMilliseconds();

  /* 将 rrt时间 与 当前时间 存入 list:reports_ */
  reports_.push_back(RttTime(rtt, now_ms));

  if (time_of_first_rtt_ms_ == -1)
    time_of_first_rtt_ms_ = now_ms;
}

四、取出 CallStats 对象中的 avg_rtt_ms_:

virtual int64_t LastProcessedRtt() const 
{
  return owner_->avg_rtt_ms();
}

五、保存 avg_rtt_ms_,后续重传 RTP 包等都需要用到:

void ModuleRtpRtcpImpl::set_rtt_ms(int64_t rtt_ms) 
{
  rtc::CritScope cs(&critical_section_rtt_);
  rtt_ms_ = rtt_ms;
}
发布了112 篇原创文章 · 获赞 22 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/u010601662/article/details/105266530
今日推荐