webrtc 发送带宽估计

来源:互联网 发布:js文件中引入js文件 编辑:程序博客网 时间:2024/06/05 06:54

几个问题
1、webrtc的发送带宽估计是针对每一路流还是总的带宽
2、webrtc的remb是统计的整体带宽吗?
3、如果webrtc同时观看了多路流,如何针对每一路流反馈带宽,丢包等信息
5、如果webrtc同时发送了多路流,如何估计每一路的带宽情况

跟踪代码 目的是 当有多个观看 和 发送 的时候, 发送端如何调整带宽

void  ProcessThreadImpl::Process(){        ...        m.module->Process();        ...}

这段代码没有什么信息,只是线程运行

void CongestionController::Process() {  bitrate_controller_->Process();  remote_bitrate_estimator_->Process();  MaybeTriggerOnNetworkChanged();}

带宽检测开始
先看看这个MaybeTriggerOnNetworkChanged();

void CongestionController::MaybeTriggerOnNetworkChanged() { ...  bool estimate_changed = bitrate_controller_->GetNetworkParameters(      &bitrate_bps, &fraction_loss, &rtt); ...  if (HasNetworkParametersToReportChanged(bitrate_bps, fraction_loss, rtt)) {    observer_->OnNetworkChanged(bitrate_bps, fraction_loss, rtt);    remote_estimator_proxy_.OnBitrateChanged(bitrate_bps);  }}

bitrate_controller_ 从这里获取发送的带宽 丢包率 rtt,并回调通知

void Call::OnNetworkChanged(uint32_t target_bitrate_bps, uint8_t fraction_loss,                            int64_t rtt_ms) {   ...  bitrate_allocator_->OnNetworkChanged(target_bitrate_bps, fraction_loss,                                       rtt_ms);  ...}

回调到call 进入bitrate_allocator_

void BitrateAllocator::OnNetworkChanged(uint32_t target_bitrate_bps,                                        uint8_t fraction_loss,                                        int64_t rtt) {  RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);  last_bitrate_bps_ = target_bitrate_bps;  last_non_zero_bitrate_bps_ =      target_bitrate_bps > 0 ? target_bitrate_bps : last_non_zero_bitrate_bps_;  last_fraction_loss_ = fraction_loss;  last_rtt_ = rtt;  // Periodically log the incoming BWE.  int64_t now = clock_->TimeInMilliseconds();  if (now > last_bwe_log_time_ + kBweLogIntervalMs) {    last_bwe_log_time_ = now;  }    printf("%s %d %s bitrate_bps:%d fraction_loss:%d rtt:%d\n",__FILE__, __LINE__, __FUNCTION__,           target_bitrate_bps, fraction_loss, rtt);  ObserverAllocation allocation = AllocateBitrates(target_bitrate_bps);  for (auto& config : bitrate_observer_configs_)  {    uint32_t allocated_bitrate = allocation[config.observer];    uint32_t protection_bitrate = config.observer->OnBitrateUpdated(        allocated_bitrate, last_fraction_loss_, last_rtt_);    printf("%s %d %s allocated_bitrate:%d fraction_loss:%d rtt:%d\n",__FILE__, __LINE__, __FUNCTION__,           allocated_bitrate, fraction_loss, rtt);    if (allocated_bitrate == 0 && config.allocated_bitrate_bps > 0) {      if (target_bitrate_bps > 0)        ++num_pause_events_;      // The protection bitrate is an estimate based on the ratio between media      // and protection used before this observer was muted.      uint32_t predicted_protection_bps =          (1.0 - config.media_ratio) * config.min_bitrate_bps;    } else if (allocated_bitrate > 0 && config.allocated_bitrate_bps == 0) {      if (target_bitrate_bps > 0)        ++num_pause_events_;    }    // Only update the media ratio if the observer got an allocation.    if (allocated_bitrate > 0)      config.media_ratio = MediaRatio(allocated_bitrate, protection_bitrate);    config.allocated_bitrate_bps = allocated_bitrate;  }}

大角色来了

... ObserverAllocation allocation = AllocateBitrates(target_bitrate_bps);  for (auto& config : bitrate_observer_configs_)  {    uint32_t allocated_bitrate = allocation[config.observer];    uint32_t protection_bitrate = config.observer->OnBitrateUpdated(        allocated_bitrate, last_fraction_loss_, last_rtt_);...

这段代码没有看懂
从打印的日志来看统计的是target_bitrate_bps 应该是全部的带宽,allocated_bitrate 好像是单路流的,这段代码到底做了什么?

BitrateAllocator::ObserverAllocation BitrateAllocator::AllocateBitrates(    uint32_t bitrate) {  RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);  if (bitrate_observer_configs_.empty())    return ObserverAllocation();  if (bitrate == 0)    return ZeroRateAllocation();  uint32_t sum_min_bitrates = 0;  uint32_t sum_max_bitrates = 0;  for (const auto& observer_config : bitrate_observer_configs_) {    sum_min_bitrates += observer_config.min_bitrate_bps;    sum_max_bitrates += observer_config.max_bitrate_bps;  }  // Not enough for all observers to get an allocation, allocate according to:  // enforced min bitrate -> allocated bitrate previous round -> restart paused  // streams.  if (!EnoughBitrateForAllObservers(bitrate, sum_min_bitrates))    return LowRateAllocation(bitrate);  // All observers will get their min bitrate plus an even share of the rest.  if (bitrate <= sum_max_bitrates)    return NormalRateAllocation(bitrate, sum_min_bitrates);  // All observers will get up to kTransmissionMaxBitrateMultiplier x max.  return MaxRateAllocation(bitrate, sum_max_bitrates);}

看着三个return,注释明确,但也太粗暴了吧,进去看看

BitrateAllocator::ObserverAllocation BitrateAllocator::NormalRateAllocation(    uint32_t bitrate,    uint32_t sum_min_bitrates) {  RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);  ObserverAllocation allocation;  for (const auto& observer_config : bitrate_observer_configs_)    allocation[observer_config.observer] = observer_config.min_bitrate_bps;  bitrate -= sum_min_bitrates;  if (bitrate > 0)    DistributeBitrateEvenly(bitrate, true, 1, &allocation);  return allocation;}

先看这个,有点类似 保底(observer_config.min_bitrate_bps)+绩效 啊!
绩效咋算的?

void BitrateAllocator::DistributeBitrateEvenly(uint32_t bitrate,                                               bool include_zero_allocations,                                               int max_multiplier,                                               ObserverAllocation* allocation) {  RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);  RTC_DCHECK_EQ(allocation->size(), bitrate_observer_configs_.size());  ObserverSortingMap list_max_bitrates;  for (const auto& observer_config : bitrate_observer_configs_) {    if (include_zero_allocations ||        allocation->at(observer_config.observer) != 0) {      list_max_bitrates.insert(std::pair<uint32_t, const ObserverConfig*>(          observer_config.max_bitrate_bps, &observer_config));    }  }  auto it = list_max_bitrates.begin();  while (it != list_max_bitrates.end()) {    RTC_DCHECK_GT(bitrate, 0u);    uint32_t extra_allocation =        bitrate / static_cast<uint32_t>(list_max_bitrates.size());    uint32_t total_allocation =        extra_allocation + allocation->at(it->second->observer);    bitrate -= extra_allocation;    if (total_allocation > max_multiplier * it->first) {      // There is more than we can fit for this observer, carry over to the      // remaining observers.      bitrate += total_allocation - max_multiplier * it->first;      total_allocation = max_multiplier * it->first;    }    // Finally, update the allocation for this observer.    allocation->at(it->second->observer) = total_allocation;    it = list_max_bitrates.erase(it);  }}

果然有毒,ObserverSortingMap list_max_bitrates; 按照每一路最大码率排序
while里面就是分配了
从设置最大码率最小的开始,从码率池子里面取个平均数给加上,发现超出了设置的最大值,则把超出的部分在放给码率的池子里面,给后面的平均分配
这种是不是有点暴力?没有考虑哪一路的丢包?

uint32_t VideoSendStreamImpl::OnBitrateUpdated(uint32_t bitrate_bps,                                               uint8_t fraction_loss,                                               int64_t rtt) {  RTC_DCHECK(payload_router_.active())      << "VideoSendStream::Start has not been called.";  // Get the encoder target rate. It is the estimated network rate -  // protection overhead.  uint32_t target = encoder_target_rate_bps_;  encoder_target_rate_bps_ = protection_bitrate_calculator_.SetTargetRates(      bitrate_bps, stats_proxy_->GetSendFrameRate(), fraction_loss, rtt);  uint32_t protection_bitrate = bitrate_bps - encoder_target_rate_bps_;  encoder_target_rate_bps_ =      std::min(encoder_max_bitrate_bps_, encoder_target_rate_bps_);  //config_->band_width_callback_  printf("%s %d %s bitrate_bps:%d encoder_target_rate_bps:%d protection_bitrate:%d\n",         __FILE__, __LINE__, __FUNCTION__, bitrate_bps, encoder_target_rate_bps_, protection_bitrate); if(band_width_callback_ != NULL && encoder_target_rate_bps_ != target) {     band_width_callback_->OnReceivedEstimatedBitrate(local_ssrc_, 0, encoder_target_rate_bps_); } vie_encoder_->OnBitrateUpdated(encoder_target_rate_bps_, fraction_loss, rtt);  stats_proxy_->OnSetEncoderTargetRate(encoder_target_rate_bps_);  return protection_bitrate;}

码率算完了,就到了这里来,准备设置了
稍等 还有闹心的一幕

  encoder_target_rate_bps_ = protection_bitrate_calculator_.SetTargetRates(      bitrate_bps, stats_proxy_->GetSendFrameRate(), fraction_loss, rtt);

感觉事情没有这么简单结束
由拿好了底薪加提成,到了这里了还得算算,看看要不要交点税,encoder_target_rate_bps_码率的计算

uint32_t ProtectionBitrateCalculator::SetTargetRates(    uint32_t estimated_bitrate_bps,    int actual_framerate_fps,    uint8_t fraction_lost,    int64_t round_trip_time_ms) {    ...      // TODO(Marco): Pass FEC protection values per layer.  protection_callback_->ProtectionRequest(      &delta_fec_params, &key_fec_params, &sent_video_rate_bps,      &sent_nack_rate_bps, &sent_fec_rate_bps);  uint32_t sent_total_rate_bps =      sent_video_rate_bps + sent_nack_rate_bps + sent_fec_rate_bps;  // Estimate the overhead costs of the next second as staying the same  // wrt the source bitrate.  if (sent_total_rate_bps > 0) {    protection_overhead_rate =        static_cast<float>(sent_nack_rate_bps + sent_fec_rate_bps) /        sent_total_rate_bps;  }  // Cap the overhead estimate to 50%.  if (protection_overhead_rate > 0.5)    protection_overhead_rate = 0.5;  // Source coding rate: total rate - protection overhead.  return estimated_bitrate_bps * (1.0 - protection_overhead_rate);    ...}

获取单路流的 流带宽,nack带宽 fec带宽, 计算要调整的带宽

结束:
总感觉怪怪的,所有流的丢包率统计都用的整体的?要是有一个人看着卡,会影响整体吗?

先到这

原创粉丝点击