学习2:使用cc-feedback包进行WebRTC的预估码率

79 篇文章 ¥59.90 ¥99.00
本文介绍了如何使用cc-feedback包进行WebRTC的预估码率计算。该包通过监测网络传输,帮助确定带宽并调整音视频质量。示例代码展示了如何集成cc-feedback,通过监听数据流和计算预估码率来优化实时通信应用的性能。

WebRTC是一种用于实时通信的开放式标准,它提供了浏览器之间进行音频、视频和数据传输的能力。在WebRTC中,预估码率是一个重要的概念,它用于确定网络的可用带宽,并帮助调整音视频传输的质量。在本文中,我们将介绍如何使用cc-feedback包进行WebRTC的预估码率。

预估码率的实现通常涉及到对网络传输的监测和测量。cc-feedback包是一个用于测量WebRTC传输性能的开源工具包,它提供了一种简单而有效的方式来计算预估码率。下面是一个使用cc-feedback包进行预估码率的示例代码:

// 引入cc-feedback包
const {
   
    CCFeedback } = require('cc-feedback');

// 创建CCFeed
NetworkControlUpdate GoogCcNetworkController::OnTransportPacketsFeedback( TransportPacketsFeedback report) { if (report.packet_feedbacks.empty()) { // TODO(bugs.webrtc.org/10125): Design a better mechanism to safe-guard // against building very large network queues. return NetworkControlUpdate(); } if (congestion_window_pushback_controller_) { // congestion_windows_pushback_controller 根据feedback更新 // 发送的数据 congestion_window_pushback_controller_->UpdateOutstandingData( report.data_in_flight.bytes()); } TimeDelta max_feedback_rtt = TimeDelta::MinusInfinity(); TimeDelta min_propagation_rtt = TimeDelta::PlusInfinity(); Timestamp max_recv_time = Timestamp::MinusInfinity(); // 遍历获取最大的到达时间(feedback.receive_time) std::vector<packetresult> feedbacks = report.ReceivedWithSendInfo(); for (const auto& feedback : feedbacks) max_recv_time = std::max(max_recv_time, feedback.receive_time); // 从feedback中统计rtt,更新到各个组件 // 遍历获取最大的feedback_rtt(发出去到收到feed)和propagation_rtt(在网络中传输的rtt,不含在服务端pending的时间) for (const auto& feedback : feedbacks) { TimeDelta feedback_rtt = report.feedback_time - feedback.sent_packet.send_time; TimeDelta min_pending_time = feedback.receive_time - max_recv_time; // ?? TimeDelta propagation_rtt = feedback_rtt - min_pending_time; max_feedback_rtt = std::max(max_feedback_rtt, feedback_rtt); min_propagation_rtt = std::min(min_propagation_rtt, propagation_rtt); } // 更新PropagationRtt if (max_feedback_rtt.IsFinite()) { feedback_max_rtts_.push_back(max_feedback_rtt.ms()); const size_t kMaxFeedbackRttWindow = 32; // 滑动窗口feedback_max_rtts,长度为32 if (feedback_max_rtts_.size() > kMaxFeedbackRttWindow) feedback_max_rtts_.pop_front(); // TODO(srte): Use time since last unacknowledged packet. bandwidth_estimation_->UpdatePropagationRtt(report.feedback_time, min_propagation_rtt); } // 更新loss和delay estimation的rtt,注意 // loss使用的是feedback_min_rtt // delay使用的是feedback_max_rtt if (packet_feedback_only_) { // 计算平均feed_back_max_rtt if (!feedback_max_rtts_.empty()) { // 计算平均feedback_rtt int64_t sum_rtt_ms = std::accumulate(feedback_max_rtts_.begin(), feedback_max_rtts_.end(), 0); int64_t mean_rtt_ms = sum_rtt_ms / feedback_max_rtts_.size(); // 更新bwe的rtt if (delay_based_bwe_) delay_based_bwe_->OnRttUpdate(TimeDelta::Millis(mean_rtt_ms)); } // 计算feedback_min_rtt,更新bandwidth_estimation_ rtt TimeDelta feedback_min_rtt = TimeDelta::PlusInfinity(); // 这块逻辑和上面计算feedback_max_rtt一样,写了重复代码 for (const auto& packet_feedback : feedbacks) { TimeDelta pending_time = packet_feedback.receive_time - max_recv_time; TimeDelta rtt = report.feedback_time - packet_feedback.sent_packet.send_time - pending_time; // Value used for predicting NACK round trip time in FEC controller. feedback_min_rtt = std::min(rtt, feedback_min_rtt); } if (feedback_min_rtt.IsFinite()) { bandwidth_estimation_->UpdateRtt(feedback_min_rtt, report.feedback_time); } // 更新丢率 // 上次更新丢后到现在应该收到的的总数 expected_packets_since_last_loss_update_ += report.PacketsWithFeedback().size(); for (const auto& packet_feedback : report.PacketsWithFeedback()) { if (packet_feedback.receive_time.IsInfinite()) lost_packets_since_last_loss_update_ += 1; } // feedback_time大于丢更新时间了,更新丢率 if (report.feedback_time > next_loss_update_) { next_loss_update_ = report.feedback_time + kLossUpdateInterval; bandwidth_estimation_->UpdatePacketsLost( lost_packets_since_last_loss_update_, expected_packets_since_last_loss_update_, report.feedback_time); expected_packets_since_last_loss_update_ = 0; lost_packets_since_last_loss_update_ = 0; } } // 获取当前是否处于alr absl::optional<int64_t> alr_start_time = alr_detector_->GetApplicationLimitedRegionStartTime(); // 告知acknowledge和probe_controller,当前不再处于alr if (previously_in_alr_ && !alr_start_time.has_value()) { int64_t now_ms = report.feedback_time.ms(); acknowledged_bitrate_estimator_->SetAlrEndedTime(report.feedback_time); probe_controller_->SetAlrEndedTimeMs(now_ms); } previously_in_alr_ = alr_start_time.has_value(); // 预估接收端吞吐量 acknowledged_bitrate_estimator_->IncomingPacketFeedbackVector( report.SortedByReceiveTime()); auto acknowledged_bitrate = acknowledged_bitrate_estimator_->bitrate(); // 将其设置到bandwidth_estimation_中去更新链路容量(link_capacity) bandwidth_estimation_->SetAcknowledgedRate(acknowledged_bitrate, report.feedback_time); bandwidth_estimation_->IncomingPacketFeedbackVector(report); for (const auto& feedback : report.SortedByReceiveTime()) { if (feedback.sent_packet.pacing_info.probe_cluster_id != PacedPacketInfo::kNotAProbe) { // probe_estimator 根据返回的feedback更新带宽探测的计算 probe_bitrate_estimator_->HandleProbeAndEstimateBitrate(feedback); } } if (network_estimator_) { // 这一块暂时还在开发中,目前还未使用,不太清楚干什么 network_estimator_->OnTransportPacketsFeedback(report); auto prev_estimate = estimate_; estimate_ = network_estimator_->GetCurrentEstimate(); // TODO(srte): Make OnTransportPacketsFeedback signal whether the state // changed to avoid the need for this check. if (estimate_ && (!prev_estimate || estimate_->last_feed_time != prev_estimate->last_feed_time)) { event_log_->Log(std::make_unique<rtceventremoteestimate>( estimate_->link_capacity_lower, estimate_->link_capacity_upper)); } } // 获取上面循环更新probe_estimator的最终的结果 absl::optional<datarate> probe_bitrate = probe_bitrate_estimator_->FetchAndResetLastEstimatedBitrate(); // 如果enable probe < network_estimate时 忽略probe的特性,则忽略probe_bitrate if (ignore_probes_lower_than_network_estimate_ && probe_bitrate && estimate_ && *probe_bitrate < delay_based_bwe_->last_estimate() && *probe_bitrate < estimate_->link_capacity_lower) { probe_bitrate.reset(); } // 如果enable // 将probe略小于throughput_estimate_(预估吞吐量)的特性 // 对probe现在acknowledged_bitrate(链路吞吐量)下 if (limit_probes_lower_than_throughput_estimate_ && probe_bitrate && acknowledged_bitrate) { // Limit the backoff to something slightly below the acknowledged // bitrate. ("Slightly below" because we want to drain the queues // if we are actually overusing.) // The acknowledged bitrate shouldn't normally be higher than the delay // based estimate, but it could happen e.g. due to packet bursts or // encoder overshoot. We use std::min to ensure that a probe result // below the current BWE never causes an increase. DataRate limit = std::min(delay_based_bwe_->last_estimate(), *acknowledged_bitrate * kProbeDropThroughputFraction); probe_bitrate = std::max(*probe_bitrate, limit); } NetworkControlUpdate update; bool recovered_from_overuse = false; bool backoff_in_alr = false; // 使用feedback进行bwe预测,获得基于延迟的码率估计 DelayBasedBwe::Result result; result = delay_based_bwe_->IncomingPacketFeedbackVector( report, acknowledged_bitrate, probe_bitrate, estimate_, alr_start_time.has_value()); if (result.updated) { // 预估码率更新了 if (result.probe) { // bwe使用了探测码率进行重设 // bandwidth_estimation_也进行重设sendbitrate bandwidth_estimation_->SetSendBitrate(result.target_bitrate, report.feedback_time); } // Since SetSendBitrate now resets the delay-based estimate, we have to // call UpdateDelayBasedEstimate after SetSendBitrate. // 更新bandwidth_estimation_中基于延迟的估计码率 bandwidth_estimation_->UpdateDelayBasedEstimate(report.feedback_time, result.target_bitrate); // Update the estimate in the ProbeController, in case we want to probe. // 将变化的码率通知到probe_controller, alr_detector, congestion_window等 MaybeTriggerOnNetworkChanged(&update, report.feedback_time); } recovered_from_overuse = result.recovered_from_overuse; backoff_in_alr = result.backoff_in_alr; if (recovered_from_overuse) { // 从overuse中恢复了,重设alr start 时间 probe_controller_->SetAlrStartTimeMs(alr_start_time); // 获取接下来要做带宽探测的参数,放到update中 auto probes = probe_controller_->RequestProbe(report.feedback_time.ms()); update.probe_cluster_configs.insert(update.probe_cluster_configs.end(), probes.begin(), probes.end()); } else if (backoff_in_alr) { // 如果在alr中做了码率回退,进行新一轮的探测? // If we just backed off during ALR, request a new probe. auto probes = probe_controller_->RequestProbe(report.feedback_time.ms()); update.probe_cluster_configs.insert(update.probe_cluster_configs.end(), probes.begin(), probes.end()); } // No valid RTT could be because send-side BWE isn't used, in which case // we don't try to limit the outstanding packets. if (rate_control_settings_.UseCongestionWindow() && max_feedback_rtt.IsFinite()) { // TODO 这个window需要花时间看一看,直接一直没有看这个东西 UpdateCongestionWindowSize(); } if (congestion_window_pushback_controller_ && current_data_window_) { // 如果有congestion_window_pushback_controller_,将当前的窗口放在通知器下回推给编码器 congestion_window_pushback_controller_->SetDataWindow( *current_data_window_); } else { // 否则,直接放在结果中 update.congestion_window = current_data_window_; } // 返回结果 return update; } 详细分析并解释上述代码,绘制调用流程图
最新发布
09-10
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值