织梦CMS - 轻松建站从此开始!

罗索

WebRTC 中的带宽侦测

jackyhwei 发布于 2021-01-13 18:10 点击:次 
WebRTC的带宽利用率相当高, 在测试中, 绝大多数时间都可以在可用带宽的95%以上, 而且在高利用率的同时, 还能保持音视频的高质量, 其带宽侦测机制在其中扮演了关键的角色.
TAG: WebRTC  gcc  带宽控制  BWE  带宽检测  

WebRTC 中的带宽侦测

WebRTC的带宽利用率相当高, 在测试中, 绝大多数时间都可以在可用带宽的95%以上, 而且在高利用率的同时, 还能保持音视频的高质量, 其带宽侦测机制在其中扮演了关键的角色. 有几个关键点:

Pacing Bitrate

Pacing Bitrate 为allocated_bitrate_bps/1000 * kDefaultPaceMultiplier, 这里的kDefaultPaceMultiplier = 2.5

  1. void PacedSender::SetAllocatedSendBitrate(int allocated_bitrate, 
  2.                                           int padding_bitrate) { 
  3.   CriticalSectionScoped cs(critsect_.get()); 
  4.   min_send_bitrate_kbps_ = allocated_bitrate / 1000; 
  5.   pacing_bitrate_kbps_ = 
  6.       std::max(min_send_bitrate_kbps_, estimated_bitrate_bps_ / 1000) * 
  7.       kDefaultPaceMultiplier; 
  8.   padding_budget_->set_target_rate_kbps(padding_bitrate / 1000); 

发起Probing 的时机

  1. void PacedSender::InsertPacket(RtpPacketSender::Priority priority, 
  2.                                uint32_t ssrc, 
  3.                                uint16_t sequence_number, 
  4.                                int64_t capture_time_ms, 
  5.                                size_t bytes, 
  6.                                bool retransmission) { 
  7.   CriticalSectionScoped cs(critsect_.get()); 
  8.   RTC_DCHECK(estimated_bitrate_bps_ > 0) 
  9.         << "SetEstimatedBitrate must be called before InsertPacket."
  10.  
  11.   if (probing_enabled_ && !prober_->IsProbing()) 
  12.     prober_->SetEnabled(true); 
  13.   int64_t now_ms = clock_->TimeInMilliseconds(); 
  14.   prober_->OnIncomingPacket(estimated_bitrate_bps_, bytes, now_ms); 
  15.  
  16.   if (capture_time_ms < 0) 
  17.     capture_time_ms = now_ms; 
  18.  
  19.   packets_->Push(paced_sender::Packet(priority, ssrc, sequence_number, 
  20.                                       capture_time_ms, now_ms, bytes, 
  21.                                       retransmission, packet_counter_++)); 

创建 Probing Cluster, 设置状态为Probing

Cluster 被清空后Probing结束.

  1. void BitrateProber::OnIncomingPacket(uint32_t bitrate_bps, 
  2.                                      size_t packet_size, 
  3.                                      int64_t now_ms) { 
  4.   // Don't initialize probing unless we have something large enough to start 
  5.   // probing. 
  6.   if (packet_size < PacedSender::kMinProbePacketSize
  7.     return; 
  8.   if (probing_state_ != kAllowedToProbe) 
  9.     return; 
  10.   // Max number of packets used for probing. 
  11.   const int kMaxNumProbes = 2
  12.   const int kPacketsPerProbe = 5
  13.   const float kProbeBitrateMultipliers[kMaxNumProbes] = {3, 6}; 
  14.   std::stringstream bitrate_log; 
  15.   bitrate_log << "Start probing for bandwidth, (bitrate:packets): "; 
  16.   for (int i = 0; i < kMaxNumProbes; ++i) { 
  17.     ProbeCluster cluster; 
  18.     // We need one extra to get 5 deltas for the first probe, therefore (i == 0) 
  19.     cluster.max_probe_packets = kPacketsPerProbe + (i == 0 ? 1 : 0); 
  20.     cluster.probe_bitrate_bps = kProbeBitrateMultipliers[i] * bitrate_bps; 
  21.     cluster.id = next_cluster_id_++; 
  22.  
  23.     bitrate_log << "(" << cluster.probe_bitrate_bps << ":"<<
  24.  cluster.max_probe_packets << ") "; 
  25.  
  26.     clusters_.push(cluster); 
  27.   } 
  28.   LOG(LS_INFO) << bitrate_log.str().c_str(); 
  29.   // Set last send time to current time so TimeUntilNextProbe doesn't short 
  30.   // circuit due to inactivity. 
  31.   time_last_send_ms_ = now_ms
  32.   probing_state_ = kProbing

数据发送和Probing 是在PacedSender::Process函数中处理的

  1. void PacedSender::Process() { 
  2.   int64_t now_us = clock_->TimeInMicroseconds(); 
  3.   CriticalSectionScoped cs(critsect_.get()); 
  4.   int64_t elapsed_time_ms = (now_us - time_last_update_us_ + 500) / 1000; 
  5.   time_last_update_us_ = now_us; 
  6.   int target_bitrate_kbps = pacing_bitrate_kbps_; 
  7.   // TODO(holmer): Remove the !paused_ check when issue 5307 has been fixed. 
  8.   if (!paused_ && elapsed_time_ms > 0) { 
  9.     size_t queue_size_bytes = packets_->SizeInBytes(); 
  10.     if (queue_size_bytes > 0) { 
  11.       // Assuming equal size packets and input/output rate, the average packet 
  12.       // has avg_time_left_ms left to get queue_size_bytes out of the queue, if 
  13.       // time constraint shall be met. Determine bitrate needed for that. 
  14.       packets_->UpdateQueueTime(clock_->TimeInMilliseconds()); 
  15.       int64_t avg_time_left_ms = std::max( 
  16.           1, kMaxQueueLengthMs - packets_->AverageQueueTimeMs()); 
  17.       int min_bitrate_needed_kbps = 
  18.           static_cast(queue_size_bytes * 8 / avg_time_left_ms); 
  19.       if (min_bitrate_needed_kbps > target_bitrate_kbps) 
  20.         target_bitrate_kbps = min_bitrate_needed_kbps; 
  21.     } 
  22.  
  23.     media_budget_->set_target_rate_kbps(target_bitrate_kbps); 
  24.  
  25.     int64_t delta_time_ms = std::min(kMaxIntervalTimeMs, elapsed_time_ms); 
  26.     UpdateBytesPerInterval(delta_time_ms); 
  27.   } 
  28.   while (!packets_->Empty()) { 
  29.     if (media_budget_->bytes_remaining() == 0 && !prober_->IsProbing()) 
  30.       return
  31.  
  32.     // Since we need to release the lock in order to send, we first pop the 
  33.     // element from the priority queue but keep it in storage, so that we can 
  34.     // reinsert it if send fails. 
  35.     const paced_sender::Packet& packet = packets_->BeginPop(); 
  36.     int probe_cluster_id = 
  37.         prober_->IsProbing() ? prober_->CurrentClusterId() : -1; 
  38.  
  39.     if (SendPacket(packet, probe_cluster_id)) { 
  40.       // Send succeeded, remove it from the queue. 
  41.       packets_->FinalizePop(packet); 
  42.       if (prober_->IsProbing()) 
  43.         return
  44.     } else { 
  45.       // Send failed, put it back into the queue. 
  46.       packets_->CancelPop(packet); 
  47.       return
  48.     } 
  49.   } 
  50.  
  51.   // TODO(holmer): Remove the paused_ check when issue 5307 has been fixed. 
  52.   if (paused_ || !packets_->Empty()) 
  53.     return
  54.  
  55.   size_t padding_needed; 
  56.   if (prober_->IsProbing()) { 
  57.     padding_needed = prober_->RecommendedPacketSize(); 
  58.   } else { 
  59.     padding_needed = padding_budget_->bytes_remaining(); 
  60.   } 
  61.  
  62.   if (padding_needed > 0) 
  63.     SendPadding(static_cast(padding_needed)); 

Create Probing Packet

尝试使用之前发送过的数据包作为Probing Packet以RTX格式发送, 如果没有,则创建Padding Packet, 发送之. 

Feedback

使用REMB 返回接收端的评估带宽.

(volvet)
本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。转载请注明:文章转载自:罗索实验室 [http://www.rosoo.net/a/202101/17793.html]
本文出处:CSDN博客 作者:volvet 原文
顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
将本文分享到微信
织梦二维码生成器
推荐内容