diff --git a/webrtc/video/video_send_stream.cc b/webrtc/video/video_send_stream.cc index 3b4238c47d..aa67532046 100644 --- a/webrtc/video/video_send_stream.cc +++ b/webrtc/video/video_send_stream.cc @@ -289,6 +289,24 @@ int CalculateMaxPadBitrateBps(std::vector streams, return pad_up_to_bitrate_bps; } +uint32_t CalculateOverheadRateBps(int packets_per_second, + size_t overhead_bytes_per_packet, + uint32_t max_overhead_bps) { + if (webrtc::field_trial::FindFullName("WebRTC-SendSideBwe-WithOverhead") != + "Enabled") + return 0; + uint32_t overhead_bps = + static_cast(8 * overhead_bytes_per_packet * packets_per_second); + return std::min(overhead_bps, max_overhead_bps); +} + +int CalculatePacketRate(uint32_t bitrate_bps, size_t packet_size_bytes) { + size_t packet_size_bits = 8 * packet_size_bytes; + // Ceil for int value of bitrate_bps / packet_size_bits. + return static_cast((bitrate_bps + packet_size_bits - 1) / + packet_size_bits); +} + } // namespace namespace internal { @@ -1203,36 +1221,35 @@ uint32_t VideoSendStreamImpl::OnBitrateUpdated(uint32_t bitrate_bps, RTC_DCHECK(payload_router_.IsActive()) << "VideoSendStream::Start has not been called."; - if (webrtc::field_trial::FindFullName("WebRTC-SendSideBwe-WithOverhead") == - "Enabled") { - // Subtract total overhead (transport + rtp) from bitrate. - size_t rtp_overhead; - { - rtc::CritScope lock(&overhead_bytes_per_packet_crit_); - rtp_overhead = overhead_bytes_per_packet_; - } - RTC_CHECK_GE(rtp_overhead, 0); - RTC_DCHECK_LT(rtp_overhead, config_->rtp.max_packet_size); - if (rtp_overhead >= config_->rtp.max_packet_size) { - LOG(LS_WARNING) << "RTP overhead (" << rtp_overhead << " bytes)" - << "exceeds maximum packet size (" - << config_->rtp.max_packet_size << " bytes)"; - - bitrate_bps = 0; - } else { - bitrate_bps = - static_cast(static_cast(bitrate_bps) * - (config_->rtp.max_packet_size - rtp_overhead) / - (config_->rtp.max_packet_size + - transport_overhead_bytes_per_packet_)); - } - } + // Substract overhead from bitrate. + rtc::CritScope lock(&overhead_bytes_per_packet_crit_); + uint32_t payload_bitrate_bps = + bitrate_bps - + CalculateOverheadRateBps( + CalculatePacketRate(bitrate_bps, + config_->rtp.max_packet_size + + transport_overhead_bytes_per_packet_), + overhead_bytes_per_packet_ + transport_overhead_bytes_per_packet_, + bitrate_bps); // Get the encoder target rate. It is the estimated network rate - // protection overhead. encoder_target_rate_bps_ = protection_bitrate_calculator_.SetTargetRates( - bitrate_bps, stats_proxy_->GetSendFrameRate(), fraction_loss, rtt); - uint32_t protection_bitrate = bitrate_bps - encoder_target_rate_bps_; + payload_bitrate_bps, stats_proxy_->GetSendFrameRate(), fraction_loss, + rtt); + + uint32_t encoder_overhead_rate_bps = CalculateOverheadRateBps( + CalculatePacketRate(encoder_target_rate_bps_, + config_->rtp.max_packet_size + + transport_overhead_bytes_per_packet_ - + overhead_bytes_per_packet_), + overhead_bytes_per_packet_ + transport_overhead_bytes_per_packet_, + bitrate_bps - encoder_target_rate_bps_); + + // When the field trial "WebRTC-SendSideBwe-WithOverhead" is enabled + // protection_bitrate includes overhead. + uint32_t protection_bitrate = + bitrate_bps - (encoder_target_rate_bps_ + encoder_overhead_rate_bps); encoder_target_rate_bps_ = std::min(encoder_max_bitrate_bps_, encoder_target_rate_bps_); diff --git a/webrtc/video/video_send_stream_tests.cc b/webrtc/video/video_send_stream_tests.cc index f6b7450473..9ce2bce27e 100644 --- a/webrtc/video/video_send_stream_tests.cc +++ b/webrtc/video/video_send_stream_tests.cc @@ -3169,16 +3169,10 @@ TEST_F(VideoSendStreamTest, TestRequestSourceRotateVideo(true); } -// Flaky on Win32 Release: http://crbug.com/webrtc/6886 -#if defined(WEBRTC_WIN) -#define MAYBE_RemoveOverheadFromBandwidth DISABLED_RemoveOverheadFromBandwidth -#else -#define MAYBE_RemoveOverheadFromBandwidth RemoveOverheadFromBandwidth -#endif // This test verifies that overhead is removed from the bandwidth estimate by // testing that the maximum possible target payload rate is smaller than the // maximum bandwidth estimate by the overhead rate. -TEST_F(VideoSendStreamTest, MAYBE_RemoveOverheadFromBandwidth) { +TEST_F(VideoSendStreamTest, RemoveOverheadFromBandwidth) { test::ScopedFieldTrials override_field_trials( "WebRTC-SendSideBwe-WithOverhead/Enabled/"); class RemoveOverheadFromBandwidthTest : public test::EndToEndTest, @@ -3188,13 +3182,19 @@ TEST_F(VideoSendStreamTest, MAYBE_RemoveOverheadFromBandwidth) { : EndToEndTest(test::CallTest::kDefaultTimeoutMs), FakeEncoder(Clock::GetRealTimeClock()), call_(nullptr), - max_bitrate_kbps_(0) {} + max_bitrate_bps_(0), + first_packet_sent_(false), + bitrate_changed_event_(false, false) {} int32_t SetRateAllocation(const BitrateAllocation& bitrate, uint32_t frameRate) override { rtc::CritScope lock(&crit_); - if (max_bitrate_kbps_ < bitrate.get_sum_kbps()) - max_bitrate_kbps_ = bitrate.get_sum_kbps(); + // Wait for the first sent packet so that videosendstream knows + // rtp_overhead. + if (first_packet_sent_) { + max_bitrate_bps_ = bitrate.get_sum_bps(); + bitrate_changed_event_.Set(); + } return FakeEncoder::SetRateAllocation(bitrate, frameRate); } @@ -3211,29 +3211,39 @@ TEST_F(VideoSendStreamTest, MAYBE_RemoveOverheadFromBandwidth) { EXPECT_FALSE(send_config->rtp.extensions.empty()); } + Action OnSendRtp(const uint8_t* packet, size_t length) override { + rtc::CritScope lock(&crit_); + first_packet_sent_ = true; + return SEND_PACKET; + } + void PerformTest() override { - call_->OnTransportOverheadChanged(webrtc::MediaType::VIDEO, 20); Call::Config::BitrateConfig bitrate_config; - constexpr int kStartBitrateBps = 50000; + constexpr int kStartBitrateBps = 60000; constexpr int kMaxBitrateBps = 60000; + constexpr int kMinBitrateBps = 10000; bitrate_config.start_bitrate_bps = kStartBitrateBps; bitrate_config.max_bitrate_bps = kMaxBitrateBps; + bitrate_config.min_bitrate_bps = kMinBitrateBps; call_->SetBitrateConfig(bitrate_config); + call_->OnTransportOverheadChanged(webrtc::MediaType::VIDEO, 20); // At a bitrate of 60kbps with a packet size of 1200B video and an - // overhead of 40B per packet video produces 2kbps overhead. - // So with a BWE should reach 58kbps but not 60kbps. - Wait(); + // overhead of 40B per packet video produces 2240bps overhead. + // So the encoder BW should be set to 57760bps. + bitrate_changed_event_.Wait(VideoSendStreamTest::kDefaultTimeoutMs); { rtc::CritScope lock(&crit_); - EXPECT_EQ(58u, max_bitrate_kbps_); + EXPECT_LE(57760u, max_bitrate_bps_); } } private: Call* call_; rtc::CriticalSection crit_; - uint32_t max_bitrate_kbps_ GUARDED_BY(&crit_); + uint32_t max_bitrate_bps_ GUARDED_BY(&crit_); + bool first_packet_sent_ GUARDED_BY(&crit_); + rtc::Event bitrate_changed_event_; } test; RunBaseTest(&test);