几个问题
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::pairconst 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(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(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带宽, 计算要调整的带宽
结束:
总感觉怪怪的,所有流的丢包率统计都用的整体的?要是有一个人看着卡,会影响整体吗?
先到这