美文网首页
iOS WebRTC 杂谈之 带宽预测及REMB码率实时调整

iOS WebRTC 杂谈之 带宽预测及REMB码率实时调整

作者: 王沐凡 | 来源:发表于2020-04-13 15:42 被阅读0次

本文关键词:WebRTC拥塞控制,goog-remb,带宽预测。

一、概念

RTP和RTCP。

实时传输协议RTP标准定义了两个子协议,数据传输协议RTP和控制协议RTCP。RTP协议定义了传输音频和视频的标准数据包格式,其报文中包含同步信源SSRC;RTCP通常和RTP一起使用,用于反馈和同步媒体流,其所占带宽非常小,只有RTP包的5%左右。根据所携带的控制信息的不同,RTCP信息包可分为RR(接收者报告包)、SR(源报告包)、SDES(源描述包)、BYE(离开申明)和APP(特殊应用包)五类。今天要说的码率实时控制就用到了RR。

RTCP中的 RR SR

RR(Receiver Reports)接受者报告
SR(Sender Reports)发送者报告
RTCP RR包的格式及字段说明在这里传送门
RTCP SR包的格式及字段说明在这里传送门

SR指的是包含了发送端信息的packets,由接收端接收后调用process()处理,RR指的是接收端向发送端发送的反馈包,包含丢包、延时等信息,发送端接收后调用process()方法,调整自己的发送码率。

goog-remb

二、函数调用逻辑

RTCP控制码率函数调用关系.png

当发送端接收到RR包时,经过解析后,bitrate_controller_impl的BitrateControllerImpl::OnReceivedRtcpReceiverReport方法会被触发,然后会调用SendSideBandwidthEstimation的UpdateReceiverBlock方法,将RR包的丢包率fraction_loss,rtt,number_of_packets,当前时间now_ms传过去,UpdateReceiverBlock会根据这些参数预测实际带宽。

void BitrateControllerImpl::OnReceivedRtcpReceiverReport(
    uint8_t fraction_loss,
    int64_t rtt,
    int number_of_packets,
    int64_t now_ms) {
  {
    rtc::CritScope cs(&critsect_);
    bandwidth_estimation_.UpdateReceiverBlock(fraction_loss, rtt,
                                              number_of_packets, now_ms);
  }
  MaybeTriggerOnNetworkChanged();
}


void SendSideBandwidthEstimation::UpdateReceiverBlock(uint8_t fraction_loss,
                                                      int64_t rtt,
                                                      int number_of_packets,
                                                      int64_t now_ms) {
  ............
  ............

  // Update RTT.
  last_round_trip_time_ms_ = rtt;
  ............
  ............
    UpdateEstimate(now_ms);
}

void SendSideBandwidthEstimation::UpdateEstimate(int64_t now_ms) {
......
......
bitrate_ = capped_bitrate;
}

在worker_thread中运行着一个ProcessThreadImpl::Process() ,由Clock进行计时,操作CongestionController::Process(),会一直轮询bitrate_是否发生变化;同时CongestionController::Process()里面又会调用bitrate_controller_impl里的Process(),它会一直轮询SendSideBandwidthEstimation::UpdateEstimate()方法。如果bitrate_发生了变化,CongestionController::Process()会调用PacedSender:: SetEstimatedBitrate(),pace节拍器会按照预测码率进行分片发送;同时bitrate_controller_impl::Process()会触发BitrateAllocator::OnNetworkChanged(),进而修改编码码率。

void CongestionController::MaybeTriggerOnNetworkChanged() {
  // TODO(perkj): |observer_| can be nullptr if the ctor that accepts a
  // BitrateObserver is used. Remove this check once the ctor is removed.
  if (!observer_)
    return;

  uint32_t bitrate_bps;
  uint8_t fraction_loss;
  int64_t rtt;
  bool estimate_changed = bitrate_controller_->GetNetworkParameters(
      &bitrate_bps, &fraction_loss, &rtt);
  if (estimate_changed) {
    pacer_->SetEstimatedBitrate(bitrate_bps);
    probe_controller_->SetEstimatedBitrate(bitrate_bps);
    retransmission_rate_limiter_->SetMaxRate(bitrate_bps);
  }
  ......
  ......
}

BitrateAllocator这个类在每个RTCP模块上注册了多个RtcpBirateObserver,将得到的bitrate进行计算,然后将结果推送到编码器。

goog-remb

bitrate_controller_impl类提供bitrate_controller模块的所有接口,用来操作带宽估计。当发送端收到REMB的带宽调整时,bitrate_controller_impl的OnReceivedEstimatedBitrate(uint32_t bitrate)方法会被调用,然后会调用BitrateControllerImpl::OnReceiverEstimatedBitrate(uint32_t bitrate),BitrateControllerImpl里有个SendSideBandwidthEstimation bandwidth_estimation_,然后会调用SendSideBandwidthEstimation的UpdateReceiverEstimate方法更新本地记录的接收端带宽预测bitrate_。这个bitrate_是通过bitrate_ = CapBitrateToThresholds(now_ms, bitrate_);计算得来的。

// Received RTCP REMB or TMMBR.
  void OnReceivedEstimatedBitrate(uint32_t bitrate) override {
      printf("OnReceivedEstimatedBitrate:%d",bitrate);
    owner_->OnReceiverEstimatedBitrate(bitrate);
  }

// This is called upon reception of REMB or TMMBR.
void BitrateControllerImpl::OnReceiverEstimatedBitrate(uint32_t bitrate) {
  {
    rtc::CritScope cs(&critsect_);
    bandwidth_estimation_.UpdateReceiverEstimate(clock_->TimeInMilliseconds(),
                                                 bitrate);
    BWE_TEST_LOGGING_PLOT(1, "REMB[kbps]", clock_->TimeInMilliseconds(),
                          bitrate / 1000);
  }
  MaybeTriggerOnNetworkChanged();
}

// Call when we receive a RTCP message with TMMBR or REMB.
void SendSideBandwidthEstimation::UpdateReceiverEstimate(
    int64_t now_ms, uint32_t bandwidth) {
  bwe_incoming_ = bandwidth;
  bitrate_ = CapBitrateToThresholds(now_ms, bitrate_);
    printf("接收端估计最大带宽:%d  计算后的码率:%d",bandwidth,bitrate_);
}

最终发送端的码率的确定,还要依赖RR包反馈的RTT和fraction_loss参数,
目标码率和编码码率确定后,会根据实际码率进行丢帧处理,关于丢帧算法没有具体的研究便直接略过了。

相关文章

网友评论

      本文标题:iOS WebRTC 杂谈之 带宽预测及REMB码率实时调整

      本文链接:https://www.haomeiwen.com/subject/xhbfictx.html