webrtc 发送带宽估计

几个问题
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带宽, 计算要调整的带宽

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

先到这

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值