WebRTC 中的带宽侦测
WebRTC的带宽利用率相当高, 在测试中, 绝大多数时间都可以在可用带宽的95%以上, 而且在高利用率的同时, 还能保持音视频的高质量, 其带宽侦测机制在其中扮演了关键的角色. 有几个关键点:
Pacing Bitrate
Pacing Bitrate 为allocated_bitrate_bps/1000 * kDefaultPaceMultiplier, 这里的kDefaultPaceMultiplier = 2.5
- void PacedSender::SetAllocatedSendBitrate(int allocated_bitrate,
- int padding_bitrate) {
- CriticalSectionScoped cs(critsect_.get());
- min_send_bitrate_kbps_ = allocated_bitrate / 1000;
- pacing_bitrate_kbps_ =
- std::max(min_send_bitrate_kbps_, estimated_bitrate_bps_ / 1000) *
- kDefaultPaceMultiplier;
- padding_budget_->set_target_rate_kbps(padding_bitrate / 1000);
- }
发起Probing 的时机
- void PacedSender::InsertPacket(RtpPacketSender::Priority priority,
- uint32_t ssrc,
- uint16_t sequence_number,
- int64_t capture_time_ms,
- size_t bytes,
- bool retransmission) {
- CriticalSectionScoped cs(critsect_.get());
- RTC_DCHECK(estimated_bitrate_bps_ > 0)
- << "SetEstimatedBitrate must be called before InsertPacket.";
-
- if (probing_enabled_ && !prober_->IsProbing())
- prober_->SetEnabled(true);
- int64_t now_ms = clock_->TimeInMilliseconds();
- prober_->OnIncomingPacket(estimated_bitrate_bps_, bytes, now_ms);
-
- if (capture_time_ms < 0)
- capture_time_ms = now_ms;
-
- packets_->Push(paced_sender::Packet(priority, ssrc, sequence_number,
- capture_time_ms, now_ms, bytes,
- retransmission, packet_counter_++));
- }
创建 Probing Cluster, 设置状态为Probing
Cluster 被清空后Probing结束.
- void BitrateProber::OnIncomingPacket(uint32_t bitrate_bps,
- size_t packet_size,
- int64_t now_ms) {
- // Don't initialize probing unless we have something large enough to start
- // probing.
- if (packet_size < PacedSender::kMinProbePacketSize)
- return;
- if (probing_state_ != kAllowedToProbe)
- return;
- // Max number of packets used for probing.
- const int kMaxNumProbes = 2;
- const int kPacketsPerProbe = 5;
- const float kProbeBitrateMultipliers[kMaxNumProbes] = {3, 6};
- std::stringstream bitrate_log;
- bitrate_log << "Start probing for bandwidth, (bitrate:packets): ";
- for (int i = 0; i < kMaxNumProbes; ++i) {
- ProbeCluster cluster;
- // We need one extra to get 5 deltas for the first probe, therefore (i == 0)
- cluster.max_probe_packets = kPacketsPerProbe + (i == 0 ? 1 : 0);
- cluster.probe_bitrate_bps = kProbeBitrateMultipliers[i] * bitrate_bps;
- cluster.id = next_cluster_id_++;
-
- bitrate_log << "(" << cluster.probe_bitrate_bps << ":"<<
- cluster.max_probe_packets << ") ";
-
- clusters_.push(cluster);
- }
- LOG(LS_INFO) << bitrate_log.str().c_str();
- // Set last send time to current time so TimeUntilNextProbe doesn't short
- // circuit due to inactivity.
- time_last_send_ms_ = now_ms;
- probing_state_ = kProbing;
- }
数据发送和Probing 是在PacedSender::Process函数中处理的
- void PacedSender::Process() {
- int64_t now_us = clock_->TimeInMicroseconds();
- CriticalSectionScoped cs(critsect_.get());
- int64_t elapsed_time_ms = (now_us - time_last_update_us_ + 500) / 1000;
- time_last_update_us_ = now_us;
- int target_bitrate_kbps = pacing_bitrate_kbps_;
-
- if (!paused_ && elapsed_time_ms > 0) {
- size_t queue_size_bytes = packets_->SizeInBytes();
- if (queue_size_bytes > 0) {
-
-
-
- packets_->UpdateQueueTime(clock_->TimeInMilliseconds());
- int64_t avg_time_left_ms = std::max(
- 1, kMaxQueueLengthMs - packets_->AverageQueueTimeMs());
- int min_bitrate_needed_kbps =
- static_cast(queue_size_bytes * 8 / avg_time_left_ms);
- if (min_bitrate_needed_kbps > target_bitrate_kbps)
- target_bitrate_kbps = min_bitrate_needed_kbps;
- }
-
- media_budget_->set_target_rate_kbps(target_bitrate_kbps);
-
- int64_t delta_time_ms = std::min(kMaxIntervalTimeMs, elapsed_time_ms);
- UpdateBytesPerInterval(delta_time_ms);
- }
- while (!packets_->Empty()) {
- if (media_budget_->bytes_remaining() == 0 && !prober_->IsProbing())
- return;
-
-
-
-
- const paced_sender::Packet& packet = packets_->BeginPop();
- int probe_cluster_id =
- prober_->IsProbing() ? prober_->CurrentClusterId() : -1;
-
- if (SendPacket(packet, probe_cluster_id)) {
-
- packets_->FinalizePop(packet);
- if (prober_->IsProbing())
- return;
- } else {
-
- packets_->CancelPop(packet);
- return;
- }
- }
-
-
- if (paused_ || !packets_->Empty())
- return;
-
- size_t padding_needed;
- if (prober_->IsProbing()) {
- padding_needed = prober_->RecommendedPacketSize();
- } else {
- padding_needed = padding_budget_->bytes_remaining();
- }
-
- if (padding_needed > 0)
- SendPadding(static_cast(padding_needed));
- }
Create Probing Packet
尝试使用之前发送过的数据包作为Probing Packet以RTX格式发送, 如果没有,则创建Padding Packet, 发送之.
Feedback
使用REMB 返回接收端的评估带宽.
(volvet) |