PacedSender
发送节拍器,控制发送的节奏,大概5ms一次,发送比较均匀
使用的内部类
-
PacedSender::IntervalBudget
根据设置的码率,计算这个时间间隔(IncreaseBudget(delta_time_ms) 最大kWindowMs = 500)可以发送的字节数,
随着时间流逝剩余可以发送的字节数也会变得越来越小(1.)设置码率 void set_target_rate_kbps(int target_rate_kbps) { target_rate_kbps_ = target_rate_kbps; //根据码率设置kWindowMs间隔内可以发送的字节数 bytes_remaining_ = std::max(-kWindowMs * target_rate_kbps_ / 8, bytes_remaining_); } (2.)增加delta_time_ms长时间数据量 void IncreaseBudget(int64_t delta_time_ms) { int64_t bytes = target_rate_kbps_ * delta_time_ms / 8; if (bytes_remaining_ < 0) { //上一次使用过度了,上一个间隔发送的数据量有点大,平均到这一次上 bytes_remaining_ = bytes_remaining_ + bytes; } else { // 未充分使用上一个间隔,剩下的时间还可以发送这么多字节 bytes_remaining_ = bytes; } } (3.) 已经发送了这么多数据了 void UseBudget(size_t bytes) { bytes_remaining_ = std::max(bytes_remaining_ - static_cast<int>(bytes), -kWindowMs * target_rate_kbps_ / 8); // 负值表示多发送了字节数,就是这个间隔发送过多 } (4.) 获取还可以发送多少数据 size_t bytes_remaining() const { return static_cast<size_t>(std::max(0, bytes_remaining_)); }
-
PacedSender::PacketQueue 保存待发送包信息队列
插入支持优先级,基本上队列的基本操作// 计算一个包在队列中待的平均时长 int64_t AverageQueueTimeMs() const { if (prio_queue_.empty()) return 0; return queue_time_sum_ / packet_list_.size(); }
节拍发送器
-
主要成员
PacedSender{ //节拍内发送数据的上限控制 paced_sender::IntervalBudget media_budget_; //节拍内发送数据的下限控制,不够就发送rtp填充数据 paced_sender::IntervalBudget padding_budget_ //队列 paced_sender::PacketQueue> packets_; }
-
插入数据,这个简单就是队列中插数据
void InsertPacket(RtpPacketSender::Priority priority, uint32_t ssrc, uint16_t sequence_number, int64_t capture_time_ms, size_t bytes, bool retransmission)
-
节拍驱动循环
如果码率探测过程中,则会限制发送的最大大小,限制一次不能发送太多字节
void Process(){
{ **//1. 根据一包在队列中的平均时长计算出清空对象需要的码率,更新码率限制的上限** size_t queue_size_bytes = packets_->SizeInBytes(); if (queue_size_bytes > 0) { packets_->UpdateQueueTime(clock_->TimeInMilliseconds()); // kMaxQueueLengthMs 一个包在队列中的最大时长 int64_t avg_time_left_ms = std::max<int64_t>( 1, kMaxQueueLengthMs - packets_->AverageQueueTimeMs()); // 根据历史一个包在队列中的平均时长,计算发送队列中的所有的这些数据需要的最小码率 int min_bitrate_needed_kbps = static_cast<int>(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); elapsed_time_ms = std::min(kMaxIntervalTimeMs, elapsed_time_ms); UpdateBudgetWithElapsedTime(elapsed_time_ms); } //**2. 控制rtp有效数据的发送** while (!packets_->Empty()) { const paced_sender::Packet& packet = packets_->BeginPop(); // SendPacket内部会根据最大码率限制进行发送,如果达到了最大码率则不发送了 if (SendPacket(packet, pacing_info)) { bytes_sent += packet.bytes; packets_->FinalizePop(packet); if (is_probing && bytes_sent > recommended_probe_size) // 码率探测过程中,控制码率不要大于这个 recommended_probe_size break; } else { // Send failed, put it back into the queue. packets_->CancelPop(packet); break; } } //**3. 看一下限制的最小发送码率是否达到了如果没达到则发送pad包** if (packets_->Empty() && !paused_) { if (packet_counter_ > 0) { int padding_needed = static_cast<int>(is_probing ? (recommended_probe_size - bytes_sent) : padding_budget_->bytes_remaining()); // 这为了保证一个最小码率 if (padding_needed > 0) bytes_sent += SendPadding(padding_needed, pacing_info); } } }