webrtc弱网-PacingController 源码分析与算法原理

在webrtc弱网整个链路中,存在这么一个模块,发送数据时采取有节奏的平滑发送,这个模块就是PacingController类。

一、核心功能
  1. 流量整形:基于漏桶算法控制数据包发送速率

  2. 优先级调度:音频 > 重传 > 视频 > 填充的优先级处理

  3. 带宽探测:通过 BitrateProber 实现主动带宽探测

  4. 拥塞响应:根据网络状态动态调整发送行为

  5. 队列管理:监控队列长度,动态提速防止积压

  6. 统计监控:实时统计各类数据包发送速率

二、核心算法原理

漏桶算法实现

// 媒体负债更新逻辑
void UpdateBudgetWithElapsedTime(TimeDelta delta) {
  // 随时间减少负债(漏水过程)
  media_debt_ -= min(media_debt_, adjusted_media_rate_ * delta);
  padding_debt_ -= min(padding_debt_, padding_rate_ * delta);
}

三、关键数据结构

// 发送统计结构
struct PacerPacketStat {
  size_t rtx_bytes_sent = 0;        // 重传包字节数
  size_t fec_bytes_sent = 0;        // FEC包字节数
  size_t media_bytes_sent = 0;      // 媒体包总字节数
  size_t media_bytes_sent_only_video = 0; // 视频媒体包字节数
};

// 优先级队列(核心排序逻辑)
class PrioritizedPacketQueue {
  // 优先级顺序:音频 > 重传 > 视频 > 填充
  std::priority_queue<...> queue_;
};

四、核心方法详解

1.入队控制 (EnqueuePacket)

void EnqueuePacket(std::unique_ptr<RtpPacketToSend> packet) {
  // 关键帧刷新:清空队列保证关键帧优先
  if (keyframe_flushing_ && packet->is_key_frame()) {
    packet_queue_.RemovePacketsForSsrc(packet->Ssrc());
  }
  
  // 通知探测器新包到达
  prober_.OnIncomingPacket(DataSize::Bytes(packet->payload_size()));
  
  // 入队并更新状态
  packet_queue_.Push(CurrentTime(), std::move(packet));
}

2.发送引擎 (ProcessPackets)

void ProcessPackets() {
  // 1. 保活包发送(防止连接冻结)
  if (ShouldSendKeepalive(now)) {
    SendPadding(DataSize::Bytes(1));
  }
  
  // 2. 带宽探测处理
  if (prober_.is_probing()) {
    DataSize probe_size = prober_.RecommendedMinProbeSize();
    SendProbePackets(probe_size);
  }
  
  // 3. 主发送循环(带熔断保护)
  while (!circuit_breaker_triggered) {
    // 4. 获取待发送包(优先级顺序)
    auto packet = GetPendingPacket();
    
    if (packet) {
      // 5. 发送并更新负债
      SendMediaPacket(std::move(packet));
    } else if (CanSendPadding()) {
      // 6. 发送填充包
      SendGeneratedPadding();
    }
  }
  
  // 7. 状态更新
  UpdateBitrateStat();
  MaybeUpdateMediaRateDueToLongQueue();
}

3.动态速率调整

void MaybeUpdateMediaRateDueToLongQueue() {
  // 计算队列预计消耗时间
  TimeDelta avg_time_left = queue_time_limit_ - packet_queue_.AverageQueueTime();
  
  // 动态提速逻辑
  if (avg_time_left < kMinQueueThreshold) {
    // 需要的最小速率 = 队列大小 / 剩余时间
    DataRate min_rate_needed = queue_size_data / avg_time_left;
    adjusted_media_rate_ = min_rate_needed;
  }
}
五、设计亮点
  1. 多级优先级系统:确保音频和重传包绝对优先

  2. 动态速率调整:基于队列长度自动提速防止积压

  3. 关键帧刷新:清空队列保证关键帧低延迟

  4. 熔断机制circuit_breaker_threshold_防止死循环

  5. 精确时间控制kMaxEarlyProbeProcessing控制探测包发送时机

  6. 保活机制:网络空闲时定期发送1字节填充包维持连接

六、典型工作流程

七、核心负债机制详解
// 媒体负债(media_debt_):
// - 发送媒体包时增加:media_debt_ += sent_bytes
// - 随时间减少:media_debt_ -= min(media_debt_, rate * elapsed_time)
// - 上限控制:不超过adjusted_media_rate_ * kMaxDebtInTime

// 填充负债(padding_debt_):
// - 发送填充包时增加
// - 随时间减少(类似媒体负债)
// - 用于控制填充包发送频率

// 负债更新示例:
void OnPacketSent(RtpPacketMediaType type, DataSize size) {
  if (type != RtpPacketMediaType::kPadding) {
    media_debt_ += size;  // 发送媒体包增加负债
  }
  padding_debt_ += size;  // 所有发送都增加填充负债
}

总结

PacingController 作为 WebRTC 的流量整形引擎,通过负债机制实现:

  1. 平滑发送:漏桶算法控制发送速率

  2. 智能调度:四级优先级保障关键数据

  3. 动态适应:队列监控自动提速

  4. 网络探测:主动带宽测量

  5. 拥塞响应:实时调整发送策略

其精妙的负债管理和时间控制机制(关键变量 media_debt_/padding_debt_)使其能在复杂网络环境中平衡传输效率与网络友好性,是 WebRTC 传输系统的核心组件。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值