- 带宽分配回调接收上行带宽评估值
void BitrateAllocator::OnNetworkEstimateChanged(TargetTransferRate msg) {
RTC_DCHECK_RUN_ON(&sequenced_checker_);
last_target_bps_ = msg.target_rate.bps();
last_stable_target_bps_ = msg.stable_target_rate.bps();
last_non_zero_bitrate_bps_ =
last_target_bps_ > 0 ? last_target_bps_ : last_non_zero_bitrate_bps_;
int loss_ratio_255 = msg.network_estimate.loss_rate_ratio * 255;
last_fraction_loss_ =
rtc::dchecked_cast<uint8_t>(rtc::SafeClamp(loss_ratio_255, 0, 255));
last_rtt_ = msg.network_estimate.round_trip_time.ms();
last_bwe_period_ms_ = msg.network_estimate.bwe_period.ms();
// Periodically log the incoming BWE.
int64_t now = msg.at_time.ms();
if (now > last_bwe_log_time_ + kBweLogIntervalMs) {
// 上行带宽评估结果
RTC_LOG(LS_INFO) << "Current BWE " << last_target_bps_;
last_bwe_log_time_ = now;
}
// 带宽结果转换
auto allocation = AllocateBitrates(allocatable_tracks_, last_target_bps_);
auto stable_bitrate_allocation =
AllocateBitrates(allocatable_tracks_, last_stable_target_bps_);
// 遍历track 往每一条媒体流分配带宽
for (auto& config : allocatable_tracks_) {
uint32_t allocated_bitrate = allocation[config.observer];
uint32_t allocated_stable_target_rate =
stable_bitrate_allocation[config.observer];
BitrateAllocationUpdate update;
update.target_bitrate = DataRate::BitsPerSec(allocated_bitrate);
update.stable_target_bitrate =
DataRate::BitsPerSec(allocated_stable_target_rate);
update.packet_loss_ratio = last_fraction_loss_ / 256.0;
update.round_trip_time = TimeDelta::Millis(last_rtt_);
update.bwe_period = TimeDelta::Millis(last_bwe_period_ms_);
update.cwnd_reduce_ratio = msg.cwnd_reduce_ratio;
// 回调带宽评估结果 AudioSendStream / VideoSendStream
uint32_t protection_bitrate = config.observer->OnBitrateUpdated(update);
if (allocated_bitrate == 0 && config.allocated_bitrate_bps > 0) {
if (last_target_bps_ > 0)
++num_pause_events_;
// The protection bitrate is an estimate based on the ratio between media
// and protection used before this observer was muted.
uint32_t predicted_protection_bps =
(1.0 - config.media_ratio) * config.config.min_bitrate_bps;
RTC_LOG(LS_INFO) << "Pausing observer " << config.observer
<< " with configured min bitrate "
<< config.config.min_bitrate_bps
<< " and current estimate of " << last_target_bps_
<< " and protection bitrate "
<< predicted_protection_bps;
} else if (allocated_bitrate > 0 && config.allocated_bitrate_bps == 0) {
if (last_target_bps_ > 0)
++num_pause_events_;
RTC_LOG(LS_INFO) << "Resuming observer " << config.observer
<< ", configured min bitrate "
<< config.config.min_bitrate_bps
<< ", current allocation " << allocated_bitrate
<< " and protection bitrate " << protection_bitrate;
}
// Only update the media ratio if the observer got an allocation.
if (allocated_bitrate > 0)
config.media_ratio = MediaRatio(allocated_bitrate, protection_bitrate);
config.allocated_bitrate_bps = allocated_bitrate;
}
UpdateAllocationLimits();
}
- 视频分配
uint32_t VideoSendStreamImpl::OnBitrateUpdated(BitrateAllocationUpdate update) {
RTC_DCHECK_RUN_ON(rtp_transport_queue_);
RTC_DCHECK(rtp_video_sender_->IsActive())
<< "VideoSendStream::Start has not been called.";
// When the BWE algorithm doesn't pass a stable estimate, we'll use the
// unstable one instead.
if (update.stable_target_bitrate.IsZero()) {
update.stable_target_bitrate = update.target_bitrate;
}
rtp_video_sender_->OnBitrateUpdated(update, stats_proxy_->GetSendFrameRate());
encoder_target_rate_bps_ = rtp_video_sender_->GetPayloadBitrateBps();
const uint32_t protection_bitrate_bps =
rtp_video_sender_->GetProtectionBitrateBps();
DataRate link_allocation = DataRate::Zero();
if (encoder_target_rate_bps_ > protection_bitrate_bps) {
link_allocation =
DataRate::BitsPerSec(encoder_target_rate_bps_ - protection_bitrate_bps);
}
DataRate overhead =
update.target_bitrate - DataRate::BitsPerSec(encoder_target_rate_bps_);
DataRate encoder_stable_target_rate = update.stable_target_bitrate;
if (encoder_stable_target_rate > overhead) {
encoder_stable_target_rate = encoder_stable_target_rate - overhead;
} else {
encoder_stable_target_rate = DataRate::BitsPerSec(encoder_target_rate_bps_);
}
encoder_target_rate_bps_ =
std::min(encoder_max_bitrate_bps_, encoder_target_rate_bps_);
encoder_stable_target_rate =
std::min(DataRate::BitsPerSec(encoder_max_bitrate_bps_),
encoder_stable_target_rate);
DataRate encoder_target_rate = DataRate::BitsPerSec(encoder_target_rate_bps_);
link_allocation = std::max(encoder_target_rate, link_allocation);
video_stream_encoder_->OnBitrateUpdated(
encoder_target_rate, encoder_stable_target_rate, link_allocation,
rtc::dchecked_cast<uint8_t>(update.packet_loss_ratio * 256),
update.round_trip_time.ms(), update.cwnd_reduce_ratio);
stats_proxy_->OnSetEncoderTargetRate(encoder_target_rate_bps_);
return protection_bitrate_bps;
}
- 回调到VideoStreamEncoder
void VideoStreamEncoder::OnBitrateUpdated(DataRate target_bitrate,
DataRate stable_target_bitrate,
DataRate link_allocation,
uint8_t fraction_lost,
int64_t round_trip_time_ms,
double cwnd_reduce_ratio) {
RTC_DCHECK_GE(link_allocation, target_bitrate);
if (!encoder_queue_.IsCurrent()) {
encoder_queue_.PostTask([this, target_bitrate, stable_target_bitrate,
link_allocation, fraction_lost, round_trip_time_ms,
cwnd_reduce_ratio] {
DataRate updated_target_bitrate =
UpdateTargetBitrate(target_bitrate, cwnd_reduce_ratio);
OnBitrateUpdated(updated_target_bitrate, stable_target_bitrate,
link_allocation, fraction_lost, round_trip_time_ms,
cwnd_reduce_ratio);
});
return;
}
RTC_DCHECK_RUN_ON(&encoder_queue_);
const bool video_is_suspended = target_bitrate == DataRate::Zero();
const bool video_suspension_changed = video_is_suspended != EncoderPaused();
if (!video_is_suspended && settings_.encoder_switch_request_callback &&
encoder_selector_) {
if (auto encoder = encoder_selector_->OnAvailableBitrate(link_allocation)) {
settings_.encoder_switch_request_callback->RequestEncoderSwitch(
*encoder, /*allow_default_fallback=*/false);
}
}
RTC_DCHECK(sink_) << "sink_ must be set before the encoder is active.";
RTC_LOG(LS_VERBOSE) << "OnBitrateUpdated, bitrate " << target_bitrate.bps()
<< " stable bitrate = " << stable_target_bitrate.bps()
<< " link allocation bitrate = " << link_allocation.bps()
<< " packet loss " << static_cast<int>(fraction_lost)
<< " rtt " << round_trip_time_ms;
if (encoder_) {
encoder_->OnPacketLossRateUpdate(static_cast<float>(fraction_lost) / 256.f);
encoder_->OnRttUpdate(round_trip_time_ms);
}
uint32_t framerate_fps = GetInputFramerateFps();
frame_dropper_.SetRates((target_bitrate.bps() + 500) / 1000, framerate_fps);
EncoderRateSettings new_rate_settings{
VideoBitrateAllocation(), static_cast<double>(framerate_fps),
link_allocation, target_bitrate, stable_target_bitrate};
SetEncoderRates(UpdateBitrateAllocation(new_rate_settings));
if (target_bitrate.bps() != 0)
encoder_target_bitrate_bps_ = target_bitrate.bps();
stream_resource_manager_.SetTargetBitrate(target_bitrate);
if (video_suspension_changed) {
RTC_LOG(LS_INFO) << "Video suspend state changed to: "
<< (video_is_suspended ? "suspended" : "not suspended");
encoder_stats_observer_->OnSuspendChange(video_is_suspended);
if (!video_is_suspended && pending_frame_ &&
!DropDueToSize(pending_frame_->size())) {
// A pending stored frame can be processed.
int64_t pending_time_us =
clock_->CurrentTime().us() - pending_frame_post_time_us_;
if (pending_time_us < kPendingFrameTimeoutMs * 1000)
EncodeVideoFrame(*pending_frame_, pending_frame_post_time_us_);
pending_frame_.reset();
} else if (!video_is_suspended && !pending_frame_ &&
encoder_paused_and_dropped_frame_) {
// A frame was enqueued during pause-state, but since it was a native
// frame we could not store it in `pending_frame_` so request a
// refresh-frame instead.
RequestRefreshFrame();
}
}
}
-
VideoStreamEncoder::EncoderRateSettings
VideoStreamEncoder::UpdateBitrateAllocation(
const EncoderRateSettings& rate_settings) {
VideoBitrateAllocation new_allocation;
// Only call allocators if bitrate > 0 (ie, not suspended), otherwise they
// might cap the bitrate to the min bitrate configured.
if (rate_allocator_ && rate_settings.encoder_target > DataRate::Zero()) {
new_allocation = rate_allocator_->Allocate(VideoBitrateAllocationParameters(
rate_settings.encoder_target, rate_settings.stable_encoder_target,
rate_settings.rate_control.framerate_fps));
}
EncoderRateSettings new_rate_settings = rate_settings;
new_rate_settings.rate_control.target_bitrate = new_allocation;
new_rate_settings.rate_control.bitrate = new_allocation;
// VideoBitrateAllocator subclasses may allocate a bitrate higher than the
// target in order to sustain the min bitrate of the video codec. In this
// case, make sure the bandwidth allocation is at least equal the allocation
// as that is part of the document contract for that field.
new_rate_settings.rate_control.bandwidth_allocation =
std::max(new_rate_settings.rate_control.bandwidth_allocation,
DataRate::BitsPerSec(
new_rate_settings.rate_control.bitrate.get_sum_bps()));
if (bitrate_adjuster_) {
VideoBitrateAllocation adjusted_allocation =
bitrate_adjuster_->AdjustRateAllocation(new_rate_settings.rate_control);
RTC_LOG(LS_VERBOSE) << "Adjusting allocation, fps = "
<< rate_settings.rate_control.framerate_fps << ", from "
<< new_allocation.ToString() << ", to "
<< adjusted_allocation.ToString();
new_rate_settings.rate_control.bitrate = adjusted_allocation;
}
return new_rate_settings;
}
- 回调到了SimulcastRateAllocator
VideoBitrateAllocation SimulcastRateAllocator::Allocate(
VideoBitrateAllocationParameters parameters) {
VideoBitrateAllocation allocated_bitrates;
DataRate stable_rate = parameters.total_bitrate;
if (stable_rate_settings_.IsEnabled() &&
parameters.stable_bitrate > DataRate::Zero()) {
stable_rate = std::min(parameters.stable_bitrate, parameters.total_bitrate);
}
// 空间层分配带宽
DistributeAllocationToSimulcastLayers(parameters.total_bitrate, stable_rate,
&allocated_bitrates);
// 时间层分配带宽
DistributeAllocationToTemporalLayers(&allocated_bitrates);
return allocated_bitrates;
}
网友评论