webrtc可以对网络带宽进行主动探测。视频流的码率相对稳定,因此在带宽探测的时候,因为要向网络中发送多余的数据包,可能会面临着没有新的数据包向外发送的情况。对于这个问题,webrtc采取冗余发送数据包的方式,对带宽进行探测。数据包在发送到网络中,webrtc/modules/rtp_rtcp/source/rtp_sender.cc会将数据包缓存到 packet_history_。在带宽探测是的时候,可以拿出一个与探测包最合适的历史包,冗余发送到网络中。
size_t PacedSender::SendPadding(size_t padding_needed,
const PacedPacketInfo& pacing_info) {
RTC_DCHECK_GT(packet_counter_, 0);
critsect_.Leave();
size_t bytes_sent =
packet_sender_->TimeToSendPadding(padding_needed, pacing_info);//PacketRouter
critsect_.Enter();
if (bytes_sent > 0) {
UpdateBudgetWithBytesSent(bytes_sent);
}
return bytes_sent;
}
PacketRouter
size_t PacketRouter::TimeToSendPadding(size_t bytes_to_send,
const PacedPacketInfo& pacing_info) {
size_t total_bytes_sent = 0;
rtc::CritScope cs(&modules_crit_);
// First try on the last rtp module to have sent media. This increases the
// the chance that any payload based padding will be useful as it will be
// somewhat distributed over modules according the packet rate, even if it
// will be more skewed towards the highest bitrate stream. At the very least
// this prevents sending payload padding on a disabled stream where it's
// guaranteed not to be useful.
if (last_send_module_ != nullptr) {
RTC_DCHECK(std::find(rtp_send_modules_.begin(), rtp_send_modules_.end(),
last_send_module_) != rtp_send_modules_.end());
RTC_DCHECK(last_send_module_->HasBweExtensions());
total_bytes_sent += last_send_module_->TimeToSendPadding(
bytes_to_send - total_bytes_sent, pacing_info);
if (total_bytes_sent >= bytes_to_send) {
return total_bytes_sent;
}
}
// Rtp modules are ordered by which stream can most benefit from padding.
for (RtpRtcp* module : rtp_send_modules_) {
if (module->SendingMedia() && module->HasBweExtensions()) {
size_t bytes_sent = module->TimeToSendPadding(
bytes_to_send - total_bytes_sent, pacing_info);//ModuleRtpRtcpImpl
total_bytes_sent += bytes_sent;
if (total_bytes_sent >= bytes_to_send)
break;
}
}
return total_bytes_sent;
}
ModuleRtpRtcpImpl
size_t ModuleRtpRtcpImpl::TimeToSendPadding(
size_t bytes,
const PacedPacketInfo& pacing_info) {
return rtp_sender_->TimeToSendPadding(bytes, pacing_info);//RTPSender
}
RTPSender
size_t RTPSender::TimeToSendPadding(size_t bytes,
const PacedPacketInfo& pacing_info) {
if (bytes == 0)
return 0;
size_t bytes_sent = TrySendRedundantPayloads(bytes, pacing_info);
if (bytes_sent < bytes)
bytes_sent += SendPadData(bytes - bytes_sent, pacing_info);
return bytes_sent;
}
size_t RTPSender::TrySendRedundantPayloads(size_t bytes_to_send,
const PacedPacketInfo& pacing_info) {
{
rtc::CritScope lock(&send_critsect_);
if (!sending_media_)
return 0;
if ((rtx_ & kRtxRedundantPayloads) == 0)
return 0;
}
int bytes_left = static_cast<int>(bytes_to_send);
while (bytes_left > 0) {
std::unique_ptr<RtpPacketToSend> packet =
packet_history_.GetBestFittingPacket(bytes_left);/**if any optimization?**/
if (!packet)
break;
size_t payload_size = packet->payload_size();
if (!PrepareAndSendPacket(std::move(packet), true, false, pacing_info))
break;
bytes_left -= payload_size;
}
return bytes_to_send - bytes_left;
}
最终,拿出一个已经发过的历史数据,再次发送出去,packet_history_.GetBestFittingPacket(bytes_left)。
[1]WebRTC 中的带宽侦测