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带宽, 计算要调整的带宽
结束:
总感觉怪怪的,所有流的丢包率统计都用的整体的?要是有一个人看着卡,会影响整体吗?
先到这
- webrtc 发送带宽估计
- WebRTC带宽估计
- WebRTC带宽估计
- WebRTC带宽估计
- webrtc发送端带宽预测
- webrtc音频限制带宽
- webrtc 研究-带宽控制
- WebRTC 中的带宽侦测
- webrtc 编码器带宽调整
- webrtc中的带宽自适应算法
- webrtc中的带宽自适应算法
- webrtc中的带宽自适应算法
- webrtc中的带宽自适应算法
- 端到端可用带宽变化范围估计
- 核密度估计与自适应带宽的核密度估计
- WebRTC的带宽评估的新变化
- Pathchirp—有效的带宽估计方法(二)
- 【WebRTC】视频采集 / 编码 / 发送
- 覆盖 (重写)
- 使用git上传代码到码云
- springboot之mybaits(非注解方式)
- 智能交通课堂记录
- loadrunner之Windows系统资源性能常用计数器
- webrtc 发送带宽估计
- java I/O库中设计模式的应用
- Androidstudio编译c/c++jni方法
- 求一颗不含指向父节点指针的普通树中任意两个结点的最近公共祖先(O(N*N) 和 O(N) 算法)
- 子父类中成员的特点
- Spring Security(17)——基于方法的权限控制
- 13.3. Swap
- 常量与变量
- Centos下替换yum源为阿里云源