diff --git a/webrtc/call/bitrate_allocator.cc b/webrtc/call/bitrate_allocator.cc index e82123a8b0..7e6242210c 100644 --- a/webrtc/call/bitrate_allocator.cc +++ b/webrtc/call/bitrate_allocator.cc @@ -15,7 +15,10 @@ #include #include "webrtc/base/checks.h" +#include "webrtc/base/logging.h" #include "webrtc/modules/bitrate_controller/include/bitrate_controller.h" +#include "webrtc/system_wrappers/include/clock.h" +#include "webrtc/system_wrappers/include/metrics.h" namespace webrtc { @@ -28,13 +31,35 @@ const int kDefaultBitrateBps = 300000; const double kToggleFactor = 0.1; const uint32_t kMinToggleBitrateBps = 20000; +const int64_t kBweLogIntervalMs = 5000; + +namespace { + +double MediaRatio(uint32_t allocated_bitrate, uint32_t protection_bitrate) { + RTC_DCHECK_GT(allocated_bitrate, 0u); + if (protection_bitrate == 0) + return 1.0; + + uint32_t media_bitrate = allocated_bitrate - protection_bitrate; + return media_bitrate / static_cast(allocated_bitrate); +} +} // namespace + BitrateAllocator::BitrateAllocator(LimitObserver* limit_observer) : limit_observer_(limit_observer), bitrate_observer_configs_(), last_bitrate_bps_(kDefaultBitrateBps), last_non_zero_bitrate_bps_(kDefaultBitrateBps), last_fraction_loss_(0), - last_rtt_(0) {} + last_rtt_(0), + num_pause_events_(0), + clock_(Clock::GetRealTimeClock()), + last_bwe_log_time_(0) {} + +BitrateAllocator::~BitrateAllocator() { + RTC_LOGGED_HISTOGRAM_COUNTS_100("WebRTC.Call.NumberOfPauseEvents", + num_pause_events_); +} void BitrateAllocator::OnNetworkChanged(uint32_t target_bitrate_bps, uint8_t fraction_loss, @@ -46,11 +71,45 @@ void BitrateAllocator::OnNetworkChanged(uint32_t target_bitrate_bps, last_fraction_loss_ = fraction_loss; last_rtt_ = rtt; - ObserverAllocation allocation = AllocateBitrates(target_bitrate_bps); - for (const auto& kv : allocation) { - kv.first->OnBitrateUpdated(kv.second, last_fraction_loss_, last_rtt_); + // Periodically log the incoming BWE. + int64_t now = clock_->TimeInMilliseconds(); + if (now > last_bwe_log_time_ + kBweLogIntervalMs) { + LOG(LS_INFO) << "Current BWE " << target_bitrate_bps; + last_bwe_log_time_ = now; + } + + ObserverAllocation allocation = AllocateBitrates(target_bitrate_bps); + + for (auto& config : bitrate_observer_configs_) { + uint32_t allocated_bitrate = allocation[config.observer]; + uint32_t protection_bitrate = config.observer->OnBitrateUpdated( + allocated_bitrate, last_fraction_loss_, last_rtt_); + + if (allocated_bitrate == 0 && config.allocated_bitrate_bps > 0) { + if (target_bitrate_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.min_bitrate_bps; + LOG(LS_INFO) << "Pausing observer " << config.observer + << " with configured min bitrate " << config.min_bitrate_bps + << " and current estimate of " << target_bitrate_bps + << " and protection bitrate " << predicted_protection_bps; + } else if (allocated_bitrate > 0 && config.allocated_bitrate_bps == 0) { + if (target_bitrate_bps > 0) + ++num_pause_events_; + LOG(LS_INFO) << "Resuming observer " << config.observer + << ", configured min bitrate " << 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; } - last_allocation_ = allocation; } void BitrateAllocator::AddObserver(BitrateAllocatorObserver* observer, @@ -77,8 +136,14 @@ void BitrateAllocator::AddObserver(BitrateAllocatorObserver* observer, if (last_bitrate_bps_ > 0) { // Calculate a new allocation and update all observers. allocation = AllocateBitrates(last_bitrate_bps_); - for (const auto& kv : allocation) - kv.first->OnBitrateUpdated(kv.second, last_fraction_loss_, last_rtt_); + for (auto& config : bitrate_observer_configs_) { + uint32_t allocated_bitrate = allocation[config.observer]; + uint32_t protection_bitrate = config.observer->OnBitrateUpdated( + allocated_bitrate, last_fraction_loss_, last_rtt_); + config.allocated_bitrate_bps = allocated_bitrate; + if (allocated_bitrate > 0) + config.media_ratio = MediaRatio(allocated_bitrate, protection_bitrate); + } } else { // Currently, an encoder is not allowed to produce frames. // But we still have to return the initial config bitrate + let the @@ -87,8 +152,6 @@ void BitrateAllocator::AddObserver(BitrateAllocatorObserver* observer, observer->OnBitrateUpdated(0, last_fraction_loss_, last_rtt_); } UpdateAllocationLimits(); - - last_allocation_ = allocation; } void BitrateAllocator::UpdateAllocationLimits() { @@ -122,17 +185,22 @@ void BitrateAllocator::RemoveObserver(BitrateAllocatorObserver* observer) { int BitrateAllocator::GetStartBitrate(BitrateAllocatorObserver* observer) { rtc::CritScope lock(&crit_sect_); - const auto& it = last_allocation_.find(observer); - if (it != last_allocation_.end()) - return it->second; - - // This is a new observer that has not yet been started. Assume that if it is - // added, all observers would split the available bitrate evenly. - return last_non_zero_bitrate_bps_ / - static_cast((bitrate_observer_configs_.size() + 1)); + const auto& it = FindObserverConfig(observer); + if (it == bitrate_observer_configs_.end()) { + // This observer hasn't been added yet, just give it its fair share. + return last_non_zero_bitrate_bps_ / + static_cast((bitrate_observer_configs_.size() + 1)); + } else if (it->allocated_bitrate_bps == -1) { + // This observer hasn't received an allocation yet, so do the same. + return last_non_zero_bitrate_bps_ / + static_cast(bitrate_observer_configs_.size()); + } else { + // This observer already has an allocation. + return it->allocated_bitrate_bps; + } } -BitrateAllocator::ObserverConfigList::iterator +BitrateAllocator::ObserverConfigs::iterator BitrateAllocator::FindObserverConfig( const BitrateAllocatorObserver* observer) { for (auto it = bitrate_observer_configs_.begin(); @@ -202,9 +270,10 @@ BitrateAllocator::ObserverAllocation BitrateAllocator::LowRateAllocation( LastAllocatedBitrate(observer_config) == 0) continue; - if (remaining_bitrate >= observer_config.min_bitrate_bps) { - allocation[observer_config.observer] = observer_config.min_bitrate_bps; - remaining_bitrate -= observer_config.min_bitrate_bps; + uint32_t required_bitrate = MinBitrateWithHysteresis(observer_config); + if (remaining_bitrate >= required_bitrate) { + allocation[observer_config.observer] = required_bitrate; + remaining_bitrate -= required_bitrate; } } } @@ -263,14 +332,11 @@ BitrateAllocator::ObserverAllocation BitrateAllocator::MaxRateAllocation( uint32_t BitrateAllocator::LastAllocatedBitrate( const ObserverConfig& observer_config) { - const auto& it = last_allocation_.find(observer_config.observer); - if (it != last_allocation_.end()) - return it->second; - // Return the configured minimum bitrate for newly added observers, to avoid // requiring an extra high bitrate for the observer to get an allocated // bitrate. - return observer_config.min_bitrate_bps; + return observer_config.allocated_bitrate_bps == -1 ? + observer_config.min_bitrate_bps : observer_config.allocated_bitrate_bps; } uint32_t BitrateAllocator::MinBitrateWithHysteresis( @@ -280,6 +346,15 @@ uint32_t BitrateAllocator::MinBitrateWithHysteresis( min_bitrate += std::max(static_cast(kToggleFactor * min_bitrate), kMinToggleBitrateBps); } + // Account for protection bitrate used by this observer in the previous + // allocation. + // Note: the ratio will only be updated when the stream is active, meaning a + // paused stream won't get any ratio updates. This might lead to waiting a bit + // longer than necessary if the network condition improves, but this is to + // avoid too much toggling. + if (observer_config.media_ratio > 0.0 && observer_config.media_ratio < 1.0) + min_bitrate += min_bitrate * (1.0 - observer_config.media_ratio); + return min_bitrate; } diff --git a/webrtc/call/bitrate_allocator.h b/webrtc/call/bitrate_allocator.h index 58d1c72fb9..37e15b4f7b 100644 --- a/webrtc/call/bitrate_allocator.h +++ b/webrtc/call/bitrate_allocator.h @@ -13,25 +13,28 @@ #include -#include #include #include +#include #include "webrtc/base/criticalsection.h" #include "webrtc/base/thread_annotations.h" namespace webrtc { +class Clock; + // Used by all send streams with adaptive bitrate, to get the currently // allocated bitrate for the send stream. The current network properties are // given at the same time, to let the send stream decide about possible loss // protection. class BitrateAllocatorObserver { public: - virtual void OnBitrateUpdated(uint32_t bitrate_bps, - uint8_t fraction_loss, - int64_t rtt) = 0; - + // Returns the amount of protection used by the BitrateAllocatorObserver + // implementation, as bitrate in bps. + virtual uint32_t OnBitrateUpdated(uint32_t bitrate_bps, + uint8_t fraction_loss, + int64_t rtt) = 0; protected: virtual ~BitrateAllocatorObserver() {} }; @@ -54,6 +57,7 @@ class BitrateAllocator { }; explicit BitrateAllocator(LimitObserver* limit_observer); + ~BitrateAllocator(); // Allocate target_bitrate across the registered BitrateAllocatorObservers. void OnNetworkChanged(uint32_t target_bitrate_bps, @@ -98,20 +102,25 @@ class BitrateAllocator { min_bitrate_bps(min_bitrate_bps), max_bitrate_bps(max_bitrate_bps), pad_up_bitrate_bps(pad_up_bitrate_bps), - enforce_min_bitrate(enforce_min_bitrate) {} - BitrateAllocatorObserver* const observer; + enforce_min_bitrate(enforce_min_bitrate), + allocated_bitrate_bps(-1), + media_ratio(1.0) {} + + BitrateAllocatorObserver* observer; uint32_t min_bitrate_bps; uint32_t max_bitrate_bps; uint32_t pad_up_bitrate_bps; bool enforce_min_bitrate; + int64_t allocated_bitrate_bps; + double media_ratio; // Part of the total bitrate used for media [0.0, 1.0]. }; // Calculates the minimum requested send bitrate and max padding bitrate and // calls LimitObserver::OnAllocationLimitsChanged. void UpdateAllocationLimits(); - typedef std::list ObserverConfigList; - ObserverConfigList::iterator FindObserverConfig( + typedef std::vector ObserverConfigs; + ObserverConfigs::iterator FindObserverConfig( const BitrateAllocatorObserver* observer) EXCLUSIVE_LOCKS_REQUIRED(crit_sect_); @@ -153,12 +162,15 @@ class BitrateAllocator { rtc::CriticalSection crit_sect_; // Stored in a list to keep track of the insertion order. - ObserverConfigList bitrate_observer_configs_ GUARDED_BY(crit_sect_); + ObserverConfigs bitrate_observer_configs_ GUARDED_BY(crit_sect_); uint32_t last_bitrate_bps_ GUARDED_BY(crit_sect_); uint32_t last_non_zero_bitrate_bps_ GUARDED_BY(crit_sect_); uint8_t last_fraction_loss_ GUARDED_BY(crit_sect_); int64_t last_rtt_ GUARDED_BY(crit_sect_); - ObserverAllocation last_allocation_ GUARDED_BY(crit_sect_); + // Number of mute events based on too low BWE, not network up/down. + int num_pause_events_ GUARDED_BY(crit_sect_); + Clock* const clock_; + int64_t last_bwe_log_time_; }; } // namespace webrtc #endif // WEBRTC_CALL_BITRATE_ALLOCATOR_H_ diff --git a/webrtc/call/bitrate_allocator_unittest.cc b/webrtc/call/bitrate_allocator_unittest.cc index 5b1410f61d..7473ed457c 100644 --- a/webrtc/call/bitrate_allocator_unittest.cc +++ b/webrtc/call/bitrate_allocator_unittest.cc @@ -31,18 +31,27 @@ class MockLimitObserver : public BitrateAllocator::LimitObserver { class TestBitrateObserver : public BitrateAllocatorObserver { public: TestBitrateObserver() - : last_bitrate_bps_(0), last_fraction_loss_(0), last_rtt_ms_(0) {} + : last_bitrate_bps_(0), + last_fraction_loss_(0), + last_rtt_ms_(0), + protection_ratio_(0.0) {} - void OnBitrateUpdated(uint32_t bitrate_bps, - uint8_t fraction_loss, - int64_t rtt) override { + void SetBitrateProtectionRatio(double protection_ratio) { + protection_ratio_ = protection_ratio; + } + + uint32_t OnBitrateUpdated(uint32_t bitrate_bps, + uint8_t fraction_loss, + int64_t rtt) override { last_bitrate_bps_ = bitrate_bps; last_fraction_loss_ = fraction_loss; last_rtt_ms_ = rtt; + return bitrate_bps * protection_ratio_; } uint32_t last_bitrate_bps_; uint8_t last_fraction_loss_; int64_t last_rtt_ms_; + double protection_ratio_; }; class BitrateAllocatorTest : public ::testing::Test { @@ -95,44 +104,44 @@ TEST_F(BitrateAllocatorTest, TwoBitrateObserversOneRtcpObserver) { TestBitrateObserver bitrate_observer_1; TestBitrateObserver bitrate_observer_2; EXPECT_CALL(limit_observer_, OnAllocationLimitsChanged(100000, 0)); - allocator_->AddObserver(&bitrate_observer_1, 100000, 300000, 0, true); - EXPECT_EQ(300000, allocator_->GetStartBitrate(&bitrate_observer_1)); - EXPECT_CALL(limit_observer_, - OnAllocationLimitsChanged(100000 + 200000, 0)); - allocator_->AddObserver(&bitrate_observer_2, 200000, 300000, 0, true); - EXPECT_EQ(200000, allocator_->GetStartBitrate(&bitrate_observer_2)); + allocator_->AddObserver(&bitrate_observer_1, 100000, 300000, 0, true); + EXPECT_EQ(300000, allocator_->GetStartBitrate(&bitrate_observer_1)); + EXPECT_CALL(limit_observer_, + OnAllocationLimitsChanged(100000 + 200000, 0)); + allocator_->AddObserver(&bitrate_observer_2, 200000, 300000, 0, true); + EXPECT_EQ(200000, allocator_->GetStartBitrate(&bitrate_observer_2)); - // Test too low start bitrate, hence lower than sum of min. Min bitrates - // will - // be allocated to all observers. - allocator_->OnNetworkChanged(200000, 0, 50); - EXPECT_EQ(100000u, bitrate_observer_1.last_bitrate_bps_); - EXPECT_EQ(0, bitrate_observer_1.last_fraction_loss_); - EXPECT_EQ(50, bitrate_observer_1.last_rtt_ms_); - EXPECT_EQ(200000u, bitrate_observer_2.last_bitrate_bps_); - EXPECT_EQ(0, bitrate_observer_2.last_fraction_loss_); - EXPECT_EQ(50, bitrate_observer_2.last_rtt_ms_); + // Test too low start bitrate, hence lower than sum of min. Min bitrates + // will + // be allocated to all observers. + allocator_->OnNetworkChanged(200000, 0, 50); + EXPECT_EQ(100000u, bitrate_observer_1.last_bitrate_bps_); + EXPECT_EQ(0, bitrate_observer_1.last_fraction_loss_); + EXPECT_EQ(50, bitrate_observer_1.last_rtt_ms_); + EXPECT_EQ(200000u, bitrate_observer_2.last_bitrate_bps_); + EXPECT_EQ(0, bitrate_observer_2.last_fraction_loss_); + EXPECT_EQ(50, bitrate_observer_2.last_rtt_ms_); - // Test a bitrate which should be distributed equally. - allocator_->OnNetworkChanged(500000, 0, 50); - const uint32_t kBitrateToShare = 500000 - 200000 - 100000; - EXPECT_EQ(100000u + kBitrateToShare / 2, - bitrate_observer_1.last_bitrate_bps_); - EXPECT_EQ(200000u + kBitrateToShare / 2, - bitrate_observer_2.last_bitrate_bps_); + // Test a bitrate which should be distributed equally. + allocator_->OnNetworkChanged(500000, 0, 50); + const uint32_t kBitrateToShare = 500000 - 200000 - 100000; + EXPECT_EQ(100000u + kBitrateToShare / 2, + bitrate_observer_1.last_bitrate_bps_); + EXPECT_EQ(200000u + kBitrateToShare / 2, + bitrate_observer_2.last_bitrate_bps_); - // Limited by 2x max bitrates since we leave room for FEC and - // retransmissions. - allocator_->OnNetworkChanged(1500000, 0, 50); - EXPECT_EQ(600000u, bitrate_observer_1.last_bitrate_bps_); - EXPECT_EQ(600000u, bitrate_observer_2.last_bitrate_bps_); + // Limited by 2x max bitrates since we leave room for FEC and + // retransmissions. + allocator_->OnNetworkChanged(1500000, 0, 50); + EXPECT_EQ(600000u, bitrate_observer_1.last_bitrate_bps_); + EXPECT_EQ(600000u, bitrate_observer_2.last_bitrate_bps_); - // Verify that if the bandwidth estimate is set to zero, the allocated - // rate is - // zero. - allocator_->OnNetworkChanged(0, 0, 50); - EXPECT_EQ(0u, bitrate_observer_1.last_bitrate_bps_); - EXPECT_EQ(0u, bitrate_observer_2.last_bitrate_bps_); + // Verify that if the bandwidth estimate is set to zero, the allocated + // rate is + // zero. + allocator_->OnNetworkChanged(0, 0, 50); + EXPECT_EQ(0u, bitrate_observer_1.last_bitrate_bps_); + EXPECT_EQ(0u, bitrate_observer_2.last_bitrate_bps_); } TEST_F(BitrateAllocatorTest, RemoveObserverTriggersLimitObserver) { @@ -167,19 +176,19 @@ TEST_F(BitrateAllocatorTestNoEnforceMin, OneBitrateObserver) { // Expect OnAllocationLimitsChanged with |min_send_bitrate_bps| = 0 since // AddObserver is called with |enforce_min_bitrate| = false. EXPECT_CALL(limit_observer_, OnAllocationLimitsChanged(0, 0)); - allocator_->AddObserver(&bitrate_observer_1, 100000, 400000, 0, false); - EXPECT_EQ(300000, allocator_->GetStartBitrate(&bitrate_observer_1)); + allocator_->AddObserver(&bitrate_observer_1, 100000, 400000, 0, false); + EXPECT_EQ(300000, allocator_->GetStartBitrate(&bitrate_observer_1)); - // High BWE. - allocator_->OnNetworkChanged(150000, 0, 0); - EXPECT_EQ(150000u, bitrate_observer_1.last_bitrate_bps_); + // High BWE. + allocator_->OnNetworkChanged(150000, 0, 0); + EXPECT_EQ(150000u, bitrate_observer_1.last_bitrate_bps_); - // Low BWE. - allocator_->OnNetworkChanged(10000, 0, 0); - EXPECT_EQ(0u, bitrate_observer_1.last_bitrate_bps_); + // Low BWE. + allocator_->OnNetworkChanged(10000, 0, 0); + EXPECT_EQ(0u, bitrate_observer_1.last_bitrate_bps_); - EXPECT_CALL(limit_observer_, OnAllocationLimitsChanged(0, 0)); - allocator_->RemoveObserver(&bitrate_observer_1); + EXPECT_CALL(limit_observer_, OnAllocationLimitsChanged(0, 0)); + allocator_->RemoveObserver(&bitrate_observer_1); } TEST_F(BitrateAllocatorTestNoEnforceMin, ThreeBitrateObservers) { @@ -243,6 +252,100 @@ TEST_F(BitrateAllocatorTestNoEnforceMin, ThreeBitrateObservers) { allocator_->RemoveObserver(&bitrate_observer_3); } +TEST_F(BitrateAllocatorTestNoEnforceMin, OneBitrateObserverWithPacketLoss) { + TestBitrateObserver bitrate_observer; + // Expect OnAllocationLimitsChanged with |min_send_bitrate_bps| = 0 since + // AddObserver is called with |enforce_min_bitrate| = false. + EXPECT_CALL(limit_observer_, OnAllocationLimitsChanged(0, 0)); + allocator_->AddObserver( + &bitrate_observer, 100000, 400000, 0, false); + EXPECT_EQ(300000, allocator_->GetStartBitrate(&bitrate_observer)); + + // High BWE. + allocator_->OnNetworkChanged(150000, 0, 0); + EXPECT_EQ(150000u, bitrate_observer.last_bitrate_bps_); + + // Add loss and use a part of the bitrate for protection. + double protection_ratio = 0.4; + uint8_t fraction_loss = protection_ratio * 256; + bitrate_observer.SetBitrateProtectionRatio(protection_ratio); + allocator_->OnNetworkChanged(200000, 0, fraction_loss); + EXPECT_EQ(200000u, bitrate_observer.last_bitrate_bps_); + + // Above the min threshold, but not enough given the protection used. + allocator_->OnNetworkChanged(139000, 0, fraction_loss); + EXPECT_EQ(0u, bitrate_observer.last_bitrate_bps_); + + // Verify the hysteresis is added for the protection. + allocator_->OnNetworkChanged(150000, 0, fraction_loss); + EXPECT_EQ(0u, bitrate_observer.last_bitrate_bps_); + + // Just enough to enable video again. + allocator_->OnNetworkChanged(168000, 0, fraction_loss); + EXPECT_EQ(168000u, bitrate_observer.last_bitrate_bps_); + + // Remove all protection and make sure video is not paused as earlier. + bitrate_observer.SetBitrateProtectionRatio(0.0); + allocator_->OnNetworkChanged(140000, 0, 0); + EXPECT_EQ(140000u, bitrate_observer.last_bitrate_bps_); + + allocator_->OnNetworkChanged(139000, 0, 0); + EXPECT_EQ(139000u, bitrate_observer.last_bitrate_bps_); + + EXPECT_CALL(limit_observer_, OnAllocationLimitsChanged(0, 0)); + allocator_->RemoveObserver(&bitrate_observer); +} + +TEST_F(BitrateAllocatorTestNoEnforceMin, TwoBitrateObserverWithPacketLoss) { + TestBitrateObserver bitrate_observer_1; + TestBitrateObserver bitrate_observer_2; + + allocator_->AddObserver(&bitrate_observer_1, 100000, 400000, 0, false); + EXPECT_EQ(300000, allocator_->GetStartBitrate(&bitrate_observer_1)); + allocator_->AddObserver(&bitrate_observer_2, 200000, 400000, 0, false); + EXPECT_EQ(200000, allocator_->GetStartBitrate(&bitrate_observer_2)); + EXPECT_EQ(100000u, bitrate_observer_1.last_bitrate_bps_); + + // Enough bitrate for both. + bitrate_observer_2.SetBitrateProtectionRatio(0.5); + allocator_->OnNetworkChanged(300000, 0, 0); + EXPECT_EQ(100000u, bitrate_observer_1.last_bitrate_bps_); + EXPECT_EQ(200000u, bitrate_observer_2.last_bitrate_bps_); + + // Above min for observer 2, but too little given the protection used. + allocator_->OnNetworkChanged(330000, 0, 0); + EXPECT_EQ(330000u, bitrate_observer_1.last_bitrate_bps_); + EXPECT_EQ(0u, bitrate_observer_2.last_bitrate_bps_); + + allocator_->OnNetworkChanged(100000, 0, 0); + EXPECT_EQ(100000u, bitrate_observer_1.last_bitrate_bps_); + EXPECT_EQ(0u, bitrate_observer_2.last_bitrate_bps_); + + allocator_->OnNetworkChanged(99999, 0, 0); + EXPECT_EQ(0u, bitrate_observer_1.last_bitrate_bps_); + EXPECT_EQ(0u, bitrate_observer_2.last_bitrate_bps_); + + allocator_->OnNetworkChanged(119000, 0, 0); + EXPECT_EQ(0u, bitrate_observer_1.last_bitrate_bps_); + EXPECT_EQ(0u, bitrate_observer_2.last_bitrate_bps_); + + allocator_->OnNetworkChanged(120000, 0, 0); + EXPECT_EQ(120000u, bitrate_observer_1.last_bitrate_bps_); + EXPECT_EQ(0u, bitrate_observer_2.last_bitrate_bps_); + + // Verify the protection is accounted for before resuming observer 2. + allocator_->OnNetworkChanged(429000, 0, 0); + EXPECT_EQ(400000u, bitrate_observer_1.last_bitrate_bps_); + EXPECT_EQ(0u, bitrate_observer_2.last_bitrate_bps_); + + allocator_->OnNetworkChanged(430000, 0, 0); + EXPECT_EQ(100000u, bitrate_observer_1.last_bitrate_bps_); + EXPECT_EQ(330000u, bitrate_observer_2.last_bitrate_bps_); + + allocator_->RemoveObserver(&bitrate_observer_1); + allocator_->RemoveObserver(&bitrate_observer_2); +} + TEST_F(BitrateAllocatorTest, ThreeBitrateObserversLowBweEnforceMin) { TestBitrateObserver bitrate_observer_1; TestBitrateObserver bitrate_observer_2; @@ -255,21 +358,21 @@ TEST_F(BitrateAllocatorTest, ThreeBitrateObserversLowBweEnforceMin) { EXPECT_EQ(200000, allocator_->GetStartBitrate(&bitrate_observer_2)); EXPECT_EQ(100000u, bitrate_observer_1.last_bitrate_bps_); - allocator_->AddObserver(&bitrate_observer_3, 300000, 400000, 0, true); - EXPECT_EQ(300000, allocator_->GetStartBitrate(&bitrate_observer_3)); - EXPECT_EQ(100000, static_cast(bitrate_observer_1.last_bitrate_bps_)); - EXPECT_EQ(200000, static_cast(bitrate_observer_2.last_bitrate_bps_)); + allocator_->AddObserver(&bitrate_observer_3, 300000, 400000, 0, true); + EXPECT_EQ(300000, allocator_->GetStartBitrate(&bitrate_observer_3)); + EXPECT_EQ(100000, static_cast(bitrate_observer_1.last_bitrate_bps_)); + EXPECT_EQ(200000, static_cast(bitrate_observer_2.last_bitrate_bps_)); - // Low BWE. Verify that all observers still get their respective min - // bitrate. - allocator_->OnNetworkChanged(1000, 0, 0); - EXPECT_EQ(100000u, bitrate_observer_1.last_bitrate_bps_); // Min cap. - EXPECT_EQ(200000u, bitrate_observer_2.last_bitrate_bps_); // Min cap. - EXPECT_EQ(300000u, bitrate_observer_3.last_bitrate_bps_); // Min cap. + // Low BWE. Verify that all observers still get their respective min + // bitrate. + allocator_->OnNetworkChanged(1000, 0, 0); + EXPECT_EQ(100000u, bitrate_observer_1.last_bitrate_bps_); // Min cap. + EXPECT_EQ(200000u, bitrate_observer_2.last_bitrate_bps_); // Min cap. + EXPECT_EQ(300000u, bitrate_observer_3.last_bitrate_bps_); // Min cap. - allocator_->RemoveObserver(&bitrate_observer_1); - allocator_->RemoveObserver(&bitrate_observer_2); - allocator_->RemoveObserver(&bitrate_observer_3); + allocator_->RemoveObserver(&bitrate_observer_1); + allocator_->RemoveObserver(&bitrate_observer_2); + allocator_->RemoveObserver(&bitrate_observer_3); } TEST_F(BitrateAllocatorTest, AddObserverWhileNetworkDown) { @@ -303,96 +406,96 @@ TEST_F(BitrateAllocatorTest, AddObserverWhileNetworkDown) { TEST_F(BitrateAllocatorTest, MixedEnforecedConfigs) { TestBitrateObserver enforced_observer; - allocator_->AddObserver(&enforced_observer, 6000, 30000, 0, true); - EXPECT_EQ(60000, allocator_->GetStartBitrate(&enforced_observer)); + allocator_->AddObserver(&enforced_observer, 6000, 30000, 0, true); + EXPECT_EQ(60000, allocator_->GetStartBitrate(&enforced_observer)); - TestBitrateObserver not_enforced_observer; - allocator_->AddObserver(¬_enforced_observer, 30000, 2500000, 0, false); - EXPECT_EQ(270000, allocator_->GetStartBitrate(¬_enforced_observer)); - EXPECT_EQ(30000u, enforced_observer.last_bitrate_bps_); + TestBitrateObserver not_enforced_observer; + allocator_->AddObserver(¬_enforced_observer, 30000, 2500000, 0, false); + EXPECT_EQ(270000, allocator_->GetStartBitrate(¬_enforced_observer)); + EXPECT_EQ(30000u, enforced_observer.last_bitrate_bps_); - allocator_->OnNetworkChanged(36000, 0, 50); - EXPECT_EQ(6000u, enforced_observer.last_bitrate_bps_); - EXPECT_EQ(30000u, not_enforced_observer.last_bitrate_bps_); + allocator_->OnNetworkChanged(36000, 0, 50); + EXPECT_EQ(6000u, enforced_observer.last_bitrate_bps_); + EXPECT_EQ(30000u, not_enforced_observer.last_bitrate_bps_); - allocator_->OnNetworkChanged(35000, 0, 50); - EXPECT_EQ(30000u, enforced_observer.last_bitrate_bps_); - EXPECT_EQ(0u, not_enforced_observer.last_bitrate_bps_); + allocator_->OnNetworkChanged(35000, 0, 50); + EXPECT_EQ(30000u, enforced_observer.last_bitrate_bps_); + EXPECT_EQ(0u, not_enforced_observer.last_bitrate_bps_); - allocator_->OnNetworkChanged(5000, 0, 50); - EXPECT_EQ(6000u, enforced_observer.last_bitrate_bps_); - EXPECT_EQ(0u, not_enforced_observer.last_bitrate_bps_); + allocator_->OnNetworkChanged(5000, 0, 50); + EXPECT_EQ(6000u, enforced_observer.last_bitrate_bps_); + EXPECT_EQ(0u, not_enforced_observer.last_bitrate_bps_); - allocator_->OnNetworkChanged(36000, 0, 50); - EXPECT_EQ(30000u, enforced_observer.last_bitrate_bps_); - EXPECT_EQ(0u, not_enforced_observer.last_bitrate_bps_); + allocator_->OnNetworkChanged(36000, 0, 50); + EXPECT_EQ(30000u, enforced_observer.last_bitrate_bps_); + EXPECT_EQ(0u, not_enforced_observer.last_bitrate_bps_); - allocator_->OnNetworkChanged(55000, 0, 50); - EXPECT_EQ(30000u, enforced_observer.last_bitrate_bps_); - EXPECT_EQ(0u, not_enforced_observer.last_bitrate_bps_); + allocator_->OnNetworkChanged(55000, 0, 50); + EXPECT_EQ(30000u, enforced_observer.last_bitrate_bps_); + EXPECT_EQ(0u, not_enforced_observer.last_bitrate_bps_); - allocator_->OnNetworkChanged(56000, 0, 50); - EXPECT_EQ(6000u, enforced_observer.last_bitrate_bps_); - EXPECT_EQ(50000u, not_enforced_observer.last_bitrate_bps_); + allocator_->OnNetworkChanged(56000, 0, 50); + EXPECT_EQ(6000u, enforced_observer.last_bitrate_bps_); + EXPECT_EQ(50000u, not_enforced_observer.last_bitrate_bps_); - allocator_->OnNetworkChanged(56000, 0, 50); - EXPECT_EQ(16000u, enforced_observer.last_bitrate_bps_); - EXPECT_EQ(40000u, not_enforced_observer.last_bitrate_bps_); + allocator_->OnNetworkChanged(56000, 0, 50); + EXPECT_EQ(16000u, enforced_observer.last_bitrate_bps_); + EXPECT_EQ(40000u, not_enforced_observer.last_bitrate_bps_); - allocator_->RemoveObserver(&enforced_observer); - allocator_->RemoveObserver(¬_enforced_observer); + allocator_->RemoveObserver(&enforced_observer); + allocator_->RemoveObserver(¬_enforced_observer); } TEST_F(BitrateAllocatorTest, AvoidToggleAbsolute) { TestBitrateObserver observer; - allocator_->AddObserver(&observer, 30000, 300000, 0, false); - EXPECT_EQ(300000, allocator_->GetStartBitrate(&observer)); + allocator_->AddObserver(&observer, 30000, 300000, 0, false); + EXPECT_EQ(300000, allocator_->GetStartBitrate(&observer)); - allocator_->OnNetworkChanged(30000, 0, 50); - EXPECT_EQ(30000u, observer.last_bitrate_bps_); + allocator_->OnNetworkChanged(30000, 0, 50); + EXPECT_EQ(30000u, observer.last_bitrate_bps_); - allocator_->OnNetworkChanged(20000, 0, 50); - EXPECT_EQ(0u, observer.last_bitrate_bps_); + allocator_->OnNetworkChanged(20000, 0, 50); + EXPECT_EQ(0u, observer.last_bitrate_bps_); - allocator_->OnNetworkChanged(30000, 0, 50); - EXPECT_EQ(0u, observer.last_bitrate_bps_); + allocator_->OnNetworkChanged(30000, 0, 50); + EXPECT_EQ(0u, observer.last_bitrate_bps_); - allocator_->OnNetworkChanged(49000, 0, 50); - EXPECT_EQ(0u, observer.last_bitrate_bps_); + allocator_->OnNetworkChanged(49000, 0, 50); + EXPECT_EQ(0u, observer.last_bitrate_bps_); - allocator_->OnNetworkChanged(50000, 0, 50); - EXPECT_EQ(50000u, observer.last_bitrate_bps_); + allocator_->OnNetworkChanged(50000, 0, 50); + EXPECT_EQ(50000u, observer.last_bitrate_bps_); - allocator_->OnNetworkChanged(30000, 0, 50); - EXPECT_EQ(30000u, observer.last_bitrate_bps_); + allocator_->OnNetworkChanged(30000, 0, 50); + EXPECT_EQ(30000u, observer.last_bitrate_bps_); - allocator_->RemoveObserver(&observer); + allocator_->RemoveObserver(&observer); } TEST_F(BitrateAllocatorTest, AvoidTogglePercent) { TestBitrateObserver observer; - allocator_->AddObserver(&observer, 300000, 600000, 0, false); - EXPECT_EQ(300000, allocator_->GetStartBitrate(&observer)); + allocator_->AddObserver(&observer, 300000, 600000, 0, false); + EXPECT_EQ(300000, allocator_->GetStartBitrate(&observer)); - allocator_->OnNetworkChanged(300000, 0, 50); - EXPECT_EQ(300000u, observer.last_bitrate_bps_); + allocator_->OnNetworkChanged(300000, 0, 50); + EXPECT_EQ(300000u, observer.last_bitrate_bps_); - allocator_->OnNetworkChanged(200000, 0, 50); - EXPECT_EQ(0u, observer.last_bitrate_bps_); + allocator_->OnNetworkChanged(200000, 0, 50); + EXPECT_EQ(0u, observer.last_bitrate_bps_); - allocator_->OnNetworkChanged(300000, 0, 50); - EXPECT_EQ(0u, observer.last_bitrate_bps_); + allocator_->OnNetworkChanged(300000, 0, 50); + EXPECT_EQ(0u, observer.last_bitrate_bps_); - allocator_->OnNetworkChanged(329000, 0, 50); - EXPECT_EQ(0u, observer.last_bitrate_bps_); + allocator_->OnNetworkChanged(329000, 0, 50); + EXPECT_EQ(0u, observer.last_bitrate_bps_); - allocator_->OnNetworkChanged(330000, 0, 50); - EXPECT_EQ(330000u, observer.last_bitrate_bps_); + allocator_->OnNetworkChanged(330000, 0, 50); + EXPECT_EQ(330000u, observer.last_bitrate_bps_); - allocator_->OnNetworkChanged(300000, 0, 50); - EXPECT_EQ(300000u, observer.last_bitrate_bps_); + allocator_->OnNetworkChanged(300000, 0, 50); + EXPECT_EQ(300000u, observer.last_bitrate_bps_); - allocator_->RemoveObserver(&observer); + allocator_->RemoveObserver(&observer); } } // namespace webrtc diff --git a/webrtc/video/full_stack.cc b/webrtc/video/full_stack.cc index 0399ed2ed7..368341370a 100644 --- a/webrtc/video/full_stack.cc +++ b/webrtc/video/full_stack.cc @@ -25,7 +25,7 @@ class FullStackTest : public VideoQualityTest { void ForemanCifWithoutPacketLoss(const std::string& video_codec) { // TODO(pbos): Decide on psnr/ssim thresholds for foreman_cif. VideoQualityTest::Params foreman_cif = { - {352, 288, 30, 700000, 700000, 700000, video_codec, 1}, + {352, 288, 30, 700000, 700000, 700000, false, video_codec, 1}, {"foreman_cif"}, {}, {"foreman_cif_net_delay_0_0_plr_0_" + video_codec, 0.0, 0.0, @@ -35,7 +35,7 @@ class FullStackTest : public VideoQualityTest { void ForemanCifPlr5(const std::string& video_codec) { VideoQualityTest::Params foreman_cif = { - {352, 288, 30, 30000, 500000, 2000000, video_codec, 1}, + {352, 288, 30, 30000, 500000, 2000000, false, video_codec, 1}, {"foreman_cif"}, {}, {"foreman_cif_delay_50_0_plr_5_" + video_codec, 0.0, 0.0, @@ -68,7 +68,7 @@ TEST_F(FullStackTest, ForemanCifPlr5Vp9) { TEST_F(FullStackTest, ParisQcifWithoutPacketLoss) { VideoQualityTest::Params paris_qcif = { - {176, 144, 30, 300000, 300000, 300000, "VP8", 1}, + {176, 144, 30, 300000, 300000, 300000, false, "VP8", 1}, {"paris_qcif"}, {}, {"net_delay_0_0_plr_0", 36.0, 0.96, kFullStackTestDurationSecs}}; @@ -78,7 +78,7 @@ TEST_F(FullStackTest, ParisQcifWithoutPacketLoss) { TEST_F(FullStackTest, ForemanCifWithoutPacketLoss) { // TODO(pbos): Decide on psnr/ssim thresholds for foreman_cif. VideoQualityTest::Params foreman_cif = { - {352, 288, 30, 700000, 700000, 700000, "VP8", 1}, + {352, 288, 30, 700000, 700000, 700000, false, "VP8", 1}, {"foreman_cif"}, {}, {"foreman_cif_net_delay_0_0_plr_0", 0.0, 0.0, kFullStackTestDurationSecs} @@ -88,7 +88,7 @@ TEST_F(FullStackTest, ForemanCifWithoutPacketLoss) { TEST_F(FullStackTest, ForemanCifPlr5) { VideoQualityTest::Params foreman_cif = { - {352, 288, 30, 30000, 500000, 2000000, "VP8", 1}, + {352, 288, 30, 30000, 500000, 2000000, false, "VP8", 1}, {"foreman_cif"}, {}, {"foreman_cif_delay_50_0_plr_5", 0.0, 0.0, kFullStackTestDurationSecs}}; @@ -99,7 +99,7 @@ TEST_F(FullStackTest, ForemanCifPlr5) { TEST_F(FullStackTest, ForemanCif500kbps) { VideoQualityTest::Params foreman_cif = { - {352, 288, 30, 30000, 500000, 2000000, "VP8", 1}, + {352, 288, 30, 30000, 500000, 2000000, false, "VP8", 1}, {"foreman_cif"}, {}, {"foreman_cif_500kbps", 0.0, 0.0, kFullStackTestDurationSecs}}; @@ -111,7 +111,7 @@ TEST_F(FullStackTest, ForemanCif500kbps) { TEST_F(FullStackTest, ForemanCif500kbpsLimitedQueue) { VideoQualityTest::Params foreman_cif = { - {352, 288, 30, 30000, 500000, 2000000, "VP8", 1}, + {352, 288, 30, 30000, 500000, 2000000, false, "VP8", 1}, {"foreman_cif"}, {}, {"foreman_cif_500kbps_32pkts_queue", 0.0, 0.0, kFullStackTestDurationSecs} @@ -124,7 +124,7 @@ TEST_F(FullStackTest, ForemanCif500kbpsLimitedQueue) { TEST_F(FullStackTest, ForemanCif500kbps100ms) { VideoQualityTest::Params foreman_cif = { - {352, 288, 30, 30000, 500000, 2000000, "VP8", 1}, + {352, 288, 30, 30000, 500000, 2000000, false, "VP8", 1}, {"foreman_cif"}, {}, {"foreman_cif_500kbps_100ms", 0.0, 0.0, kFullStackTestDurationSecs}}; @@ -136,7 +136,7 @@ TEST_F(FullStackTest, ForemanCif500kbps100ms) { TEST_F(FullStackTest, ForemanCif500kbps100msLimitedQueue) { VideoQualityTest::Params foreman_cif = { - {352, 288, 30, 30000, 500000, 2000000, "VP8", 1}, + {352, 288, 30, 30000, 500000, 2000000, false, "VP8", 1}, {"foreman_cif"}, {}, {"foreman_cif_500kbps_100ms_32pkts_queue", 0.0, 0.0, @@ -149,7 +149,7 @@ TEST_F(FullStackTest, ForemanCif500kbps100msLimitedQueue) { TEST_F(FullStackTest, ForemanCif1000kbps100msLimitedQueue) { VideoQualityTest::Params foreman_cif = { - {352, 288, 30, 30000, 2000000, 2000000, "VP8", 1}, + {352, 288, 30, 30000, 2000000, 2000000, false, "VP8", 1}, {"foreman_cif"}, {}, {"foreman_cif_1000kbps_100ms_32pkts_queue", 0.0, 0.0, @@ -162,7 +162,7 @@ TEST_F(FullStackTest, ForemanCif1000kbps100msLimitedQueue) { TEST_F(FullStackTest, ScreenshareSlidesVP8_2TL) { VideoQualityTest::Params screenshare = { - {1850, 1110, 5, 50000, 200000, 2000000, "VP8", 2, 1, 400000}, + {1850, 1110, 5, 50000, 200000, 2000000, false, "VP8", 2, 1, 400000}, {}, {true, 10}, {"screenshare_slides", 0.0, 0.0, kFullStackTestDurationSecs}}; @@ -171,7 +171,7 @@ TEST_F(FullStackTest, ScreenshareSlidesVP8_2TL) { TEST_F(FullStackTest, ScreenshareSlidesVP8_2TL_Scroll) { VideoQualityTest::Params config = { - {1850, 1110 / 2, 5, 50000, 200000, 2000000, "VP8", 2, 1, 400000}, + {1850, 1110 / 2, 5, 50000, 200000, 2000000, false, "VP8", 2, 1, 400000}, {}, {true, 10, 2}, {"screenshare_slides_scrolling", 0.0, 0.0, kFullStackTestDurationSecs}}; @@ -180,7 +180,7 @@ TEST_F(FullStackTest, ScreenshareSlidesVP8_2TL_Scroll) { TEST_F(FullStackTest, ScreenshareSlidesVP8_2TL_LossyNet) { VideoQualityTest::Params screenshare = { - {1850, 1110, 5, 50000, 200000, 2000000, "VP8", 2, 1, 400000}, + {1850, 1110, 5, 50000, 200000, 2000000, false, "VP8", 2, 1, 400000}, {}, // Video-specific. {true, 10}, // Screenshare-specific. {"screenshare_slides_lossy_net", 0.0, 0.0, kFullStackTestDurationSecs}}; @@ -192,7 +192,7 @@ TEST_F(FullStackTest, ScreenshareSlidesVP8_2TL_LossyNet) { TEST_F(FullStackTest, ScreenshareSlidesVP8_2TL_VeryLossyNet) { VideoQualityTest::Params screenshare = { - {1850, 1110, 5, 50000, 200000, 2000000, "VP8", 2, 1, 400000}, + {1850, 1110, 5, 50000, 200000, 2000000, false, "VP8", 2, 1, 400000}, {}, // Video-specific. {true, 10}, // Screenshare-specific. {"screenshare_slides_very_lossy", 0.0, 0.0, kFullStackTestDurationSecs}}; @@ -205,7 +205,7 @@ TEST_F(FullStackTest, ScreenshareSlidesVP8_2TL_VeryLossyNet) { #if !defined(RTC_DISABLE_VP9) TEST_F(FullStackTest, ScreenshareSlidesVP9_2SL) { VideoQualityTest::Params screenshare = { - {1850, 1110, 5, 50000, 200000, 2000000, "VP9", 1, 0, 400000}, + {1850, 1110, 5, 50000, 200000, 2000000, false, "VP9", 1, 0, 400000}, {}, {true, 10}, {"screenshare_slides_vp9_2sl", 0.0, 0.0, kFullStackTestDurationSecs}, diff --git a/webrtc/video/screenshare_loopback.cc b/webrtc/video/screenshare_loopback.cc index 912aaaddc4..8508cd3a1f 100644 --- a/webrtc/video/screenshare_loopback.cc +++ b/webrtc/video/screenshare_loopback.cc @@ -226,7 +226,7 @@ void Loopback() { VideoQualityTest::Params params{ {flags::Width(), flags::Height(), flags::Fps(), flags::MinBitrateKbps() * 1000, flags::TargetBitrateKbps() * 1000, - flags::MaxBitrateKbps() * 1000, flags::Codec(), + flags::MaxBitrateKbps() * 1000, false, flags::Codec(), flags::NumTemporalLayers(), flags::SelectedTL(), flags::MinTransmitBitrateKbps() * 1000, call_bitrate_config, flags::FLAGS_send_side_bwe}, diff --git a/webrtc/video/video_loopback.cc b/webrtc/video/video_loopback.cc index 1622e6ad86..f3e13de346 100644 --- a/webrtc/video/video_loopback.cc +++ b/webrtc/video/video_loopback.cc @@ -56,6 +56,10 @@ int MaxBitrateKbps() { return static_cast(FLAGS_max_bitrate); } +DEFINE_bool(suspend_below_min_bitrate, + false, + "Suspends video below the configured min bitrate."); + DEFINE_int32(num_temporal_layers, 1, "Number of temporal layers. Set to 1-4 to override."); @@ -223,7 +227,9 @@ void Loopback() { VideoQualityTest::Params params{ {flags::Width(), flags::Height(), flags::Fps(), flags::MinBitrateKbps() * 1000, flags::TargetBitrateKbps() * 1000, - flags::MaxBitrateKbps() * 1000, flags::Codec(), + flags::MaxBitrateKbps() * 1000, + flags::FLAGS_suspend_below_min_bitrate, + flags::Codec(), flags::NumTemporalLayers(), flags::SelectedTL(), 0, // No min transmit bitrate. call_bitrate_config, diff --git a/webrtc/video/video_quality_test.cc b/webrtc/video/video_quality_test.cc index 5e509cbc6e..66210d0864 100644 --- a/webrtc/video/video_quality_test.cc +++ b/webrtc/video/video_quality_test.cc @@ -1125,6 +1125,9 @@ void VideoQualityTest::RunWithVideoRenderer(const Params& params) { video_send_config_.local_renderer = local_preview.get(); video_receive_configs_[stream_id].renderer = loopback_video.get(); + video_send_config_.suspend_below_min_bitrate = + params_.common.suspend_below_min_bitrate; + if (params.common.fec) { video_send_config_.rtp.fec.red_payload_type = kRedPayloadType; video_send_config_.rtp.fec.ulpfec_payload_type = kUlpfecPayloadType; diff --git a/webrtc/video/video_quality_test.h b/webrtc/video/video_quality_test.h index e138a89a8c..b1f59e540d 100644 --- a/webrtc/video/video_quality_test.h +++ b/webrtc/video/video_quality_test.h @@ -34,6 +34,7 @@ class VideoQualityTest : public test::CallTest { int min_bitrate_bps; int target_bitrate_bps; int max_bitrate_bps; + bool suspend_below_min_bitrate; std::string codec; int num_temporal_layers; int selected_tl; diff --git a/webrtc/video/video_send_stream.cc b/webrtc/video/video_send_stream.cc index 01c2fc836c..eeb9580b6b 100644 --- a/webrtc/video/video_send_stream.cc +++ b/webrtc/video/video_send_stream.cc @@ -866,15 +866,18 @@ void VideoSendStream::SignalNetworkState(NetworkState state) { } } -void VideoSendStream::OnBitrateUpdated(uint32_t bitrate_bps, - uint8_t fraction_loss, - int64_t rtt) { +uint32_t VideoSendStream::OnBitrateUpdated(uint32_t bitrate_bps, + uint8_t fraction_loss, + int64_t rtt) { payload_router_.SetTargetSendBitrate(bitrate_bps); // Get the encoder target rate. It is the estimated network rate - // protection overhead. - uint32_t encoder_target_rate = protection_bitrate_calculator_.SetTargetRates( - bitrate_bps, stats_proxy_.GetSendFrameRate(), fraction_loss, rtt); - vie_encoder_.OnBitrateUpdated(encoder_target_rate, fraction_loss, rtt); + uint32_t encoder_target_rate_bps = + protection_bitrate_calculator_.SetTargetRates( + bitrate_bps, stats_proxy_.GetSendFrameRate(), fraction_loss, rtt); + vie_encoder_.OnBitrateUpdated(encoder_target_rate_bps, fraction_loss, rtt); + + return bitrate_bps - encoder_target_rate_bps; } int VideoSendStream::ProtectionRequest(const FecProtectionParams* delta_params, diff --git a/webrtc/video/video_send_stream.h b/webrtc/video/video_send_stream.h index 1c66c1fe33..f9c6cdc0d6 100644 --- a/webrtc/video/video_send_stream.h +++ b/webrtc/video/video_send_stream.h @@ -87,9 +87,9 @@ class VideoSendStream : public webrtc::VideoSendStream, int GetPaddingNeededBps() const; // Implements BitrateAllocatorObserver. - void OnBitrateUpdated(uint32_t bitrate_bps, - uint8_t fraction_loss, - int64_t rtt) override; + uint32_t OnBitrateUpdated(uint32_t bitrate_bps, + uint8_t fraction_loss, + int64_t rtt) override; protected: // Implements webrtc::VCMProtectionCallback.