diff --git a/webrtc/modules/bitrate_controller/bitrate_controller_impl.cc b/webrtc/modules/bitrate_controller/bitrate_controller_impl.cc index d777536b9..212ac194f 100644 --- a/webrtc/modules/bitrate_controller/bitrate_controller_impl.cc +++ b/webrtc/modules/bitrate_controller/bitrate_controller_impl.cc @@ -84,11 +84,19 @@ BitrateController* BitrateController::CreateBitrateController( BitrateControllerImpl::BitrateControllerImpl(bool enforce_min_bitrate) : critsect_(CriticalSectionWrapper::CreateCriticalSection()), - enforce_min_bitrate_(enforce_min_bitrate) {} + bandwidth_estimation_(), + bitrate_observers_(), + enforce_min_bitrate_(enforce_min_bitrate), + last_bitrate_(0), + last_fraction_loss_(0), + last_rtt_(0), + last_enforce_min_bitrate_(!enforce_min_bitrate_), + bitrate_observers_modified_(false), + last_reserved_bitrate_bps_(0), + reserved_bitrate_bps_(0) {} BitrateControllerImpl::~BitrateControllerImpl() { - BitrateObserverConfList::iterator it = - bitrate_observers_.begin(); + BitrateObserverConfList::iterator it = bitrate_observers_.begin(); while (it != bitrate_observers_.end()) { delete it->second; bitrate_observers_.erase(it); @@ -187,6 +195,12 @@ void BitrateControllerImpl::EnforceMinBitrate(bool enforce_min_bitrate) { UpdateMinMaxBitrate(); } +void BitrateControllerImpl::SetReservedBitrate(uint32_t reserved_bitrate_bps) { + CriticalSectionScoped cs(critsect_); + reserved_bitrate_bps_ = reserved_bitrate_bps; + MaybeTriggerOnNetworkChanged(); +} + void BitrateControllerImpl::OnReceivedEstimatedBitrate(const uint32_t bitrate) { CriticalSectionScoped cs(critsect_); bandwidth_estimation_.UpdateReceiverEstimate(bitrate); @@ -209,10 +223,12 @@ void BitrateControllerImpl::MaybeTriggerOnNetworkChanged() { uint8_t fraction_loss; uint32_t rtt; bandwidth_estimation_.CurrentEstimate(&bitrate, &fraction_loss, &rtt); + bitrate -= std::min(bitrate, reserved_bitrate_bps_); if (bitrate_observers_modified_ || bitrate != last_bitrate_ || fraction_loss != last_fraction_loss_ || rtt != last_rtt_ || - last_enforce_min_bitrate_ != enforce_min_bitrate_) { + last_enforce_min_bitrate_ != enforce_min_bitrate_ || + last_reserved_bitrate_bps_ != reserved_bitrate_bps_) { last_bitrate_ = bitrate; last_fraction_loss_ = fraction_loss; last_rtt_ = rtt; @@ -316,7 +332,7 @@ bool BitrateControllerImpl::AvailableBandwidth(uint32_t* bandwidth) const { uint32_t rtt; bandwidth_estimation_.CurrentEstimate(&bitrate, &fraction_loss, &rtt); if (bitrate) { - *bandwidth = bitrate; + *bandwidth = bitrate - std::min(bitrate, reserved_bitrate_bps_); return true; } return false; diff --git a/webrtc/modules/bitrate_controller/bitrate_controller_impl.h b/webrtc/modules/bitrate_controller/bitrate_controller_impl.h index f9d2354ca..02b41f2c9 100644 --- a/webrtc/modules/bitrate_controller/bitrate_controller_impl.h +++ b/webrtc/modules/bitrate_controller/bitrate_controller_impl.h @@ -44,6 +44,7 @@ class BitrateControllerImpl : public BitrateController { virtual void RemoveBitrateObserver(BitrateObserver* observer) OVERRIDE; virtual void EnforceMinBitrate(bool enforce_min_bitrate) OVERRIDE; + virtual void SetReservedBitrate(uint32_t reserved_bitrate_bps) OVERRIDE; private: class RtcpBandwidthObserverImpl; @@ -116,6 +117,10 @@ class BitrateControllerImpl : public BitrateController { uint32_t last_rtt_ GUARDED_BY(*critsect_); bool last_enforce_min_bitrate_ GUARDED_BY(*critsect_); bool bitrate_observers_modified_ GUARDED_BY(*critsect_); + uint32_t last_reserved_bitrate_bps_ GUARDED_BY(*critsect_); + uint32_t reserved_bitrate_bps_ GUARDED_BY(*critsect_); + + DISALLOW_IMPLICIT_CONSTRUCTORS(BitrateControllerImpl); }; } // namespace webrtc #endif // WEBRTC_MODULES_BITRATE_CONTROLLER_BITRATE_CONTROLLER_IMPL_H_ diff --git a/webrtc/modules/bitrate_controller/bitrate_controller_unittest.cc b/webrtc/modules/bitrate_controller/bitrate_controller_unittest.cc index c53928b23..2bc1dacbd 100644 --- a/webrtc/modules/bitrate_controller/bitrate_controller_unittest.cc +++ b/webrtc/modules/bitrate_controller/bitrate_controller_unittest.cc @@ -412,6 +412,61 @@ TEST_F(BitrateControllerTest, TwoBitrateObserversOneRtcpObserver) { controller_->RemoveBitrateObserver(&bitrate_observer_2); } +TEST_F(BitrateControllerTest, SetReservedBitrate) { + TestBitrateObserver bitrate_observer; + controller_->SetBitrateObserver(&bitrate_observer, 200000, 100000, 300000); + + // Receive successively lower REMBs, verify the reserved bitrate is deducted. + + controller_->SetReservedBitrate(0); + bandwidth_observer_->OnReceivedEstimatedBitrate(400000); + EXPECT_EQ(200000u, bitrate_observer.last_bitrate_); + controller_->SetReservedBitrate(50000); + bandwidth_observer_->OnReceivedEstimatedBitrate(400000); + EXPECT_EQ(150000u, bitrate_observer.last_bitrate_); + + controller_->SetReservedBitrate(0); + bandwidth_observer_->OnReceivedEstimatedBitrate(250000); + EXPECT_EQ(200000u, bitrate_observer.last_bitrate_); + controller_->SetReservedBitrate(50000); + bandwidth_observer_->OnReceivedEstimatedBitrate(250000); + EXPECT_EQ(150000u, bitrate_observer.last_bitrate_); + + controller_->SetReservedBitrate(0); + bandwidth_observer_->OnReceivedEstimatedBitrate(200000); + EXPECT_EQ(200000u, bitrate_observer.last_bitrate_); + controller_->SetReservedBitrate(30000); + bandwidth_observer_->OnReceivedEstimatedBitrate(200000); + EXPECT_EQ(170000u, bitrate_observer.last_bitrate_); + + controller_->SetReservedBitrate(0); + bandwidth_observer_->OnReceivedEstimatedBitrate(160000); + EXPECT_EQ(160000u, bitrate_observer.last_bitrate_); + controller_->SetReservedBitrate(30000); + bandwidth_observer_->OnReceivedEstimatedBitrate(160000); + EXPECT_EQ(130000u, bitrate_observer.last_bitrate_); + + controller_->SetReservedBitrate(0); + bandwidth_observer_->OnReceivedEstimatedBitrate(120000); + EXPECT_EQ(120000u, bitrate_observer.last_bitrate_); + controller_->SetReservedBitrate(10000); + bandwidth_observer_->OnReceivedEstimatedBitrate(120000); + EXPECT_EQ(110000u, bitrate_observer.last_bitrate_); + + controller_->SetReservedBitrate(0); + bandwidth_observer_->OnReceivedEstimatedBitrate(120000); + EXPECT_EQ(120000u, bitrate_observer.last_bitrate_); + controller_->SetReservedBitrate(50000); + bandwidth_observer_->OnReceivedEstimatedBitrate(120000); + EXPECT_EQ(100000u, bitrate_observer.last_bitrate_); + + controller_->SetReservedBitrate(10000); + bandwidth_observer_->OnReceivedEstimatedBitrate(0); + EXPECT_EQ(100000u, bitrate_observer.last_bitrate_); + + controller_->RemoveBitrateObserver(&bitrate_observer); +} + class BitrateControllerTestNoEnforceMin : public BitrateControllerTest { protected: BitrateControllerTestNoEnforceMin() : BitrateControllerTest() { @@ -440,6 +495,26 @@ TEST_F(BitrateControllerTestNoEnforceMin, OneBitrateObserver) { controller_->RemoveBitrateObserver(&bitrate_observer_1); } +TEST_F(BitrateControllerTestNoEnforceMin, SetReservedBitrate) { + TestBitrateObserver bitrate_observer_1; + controller_->SetBitrateObserver(&bitrate_observer_1, 200000, 100000, 400000); + controller_->SetReservedBitrate(10000); + + // High REMB. + bandwidth_observer_->OnReceivedEstimatedBitrate(150000); + EXPECT_EQ(140000u, bitrate_observer_1.last_bitrate_); + + // Low REMB. + bandwidth_observer_->OnReceivedEstimatedBitrate(15000); + EXPECT_EQ(5000u, bitrate_observer_1.last_bitrate_); + + // Keeps at least 10 kbps. + bandwidth_observer_->OnReceivedEstimatedBitrate(9000); + EXPECT_EQ(0u, bitrate_observer_1.last_bitrate_); + + controller_->RemoveBitrateObserver(&bitrate_observer_1); +} + TEST_F(BitrateControllerTestNoEnforceMin, ThreeBitrateObservers) { TestBitrateObserver bitrate_observer_1; TestBitrateObserver bitrate_observer_2; diff --git a/webrtc/modules/bitrate_controller/include/bitrate_controller.h b/webrtc/modules/bitrate_controller/include/bitrate_controller.h index 0f7436765..b25852dfd 100644 --- a/webrtc/modules/bitrate_controller/include/bitrate_controller.h +++ b/webrtc/modules/bitrate_controller/include/bitrate_controller.h @@ -73,6 +73,8 @@ class BitrateController { // Changes the mode that was set in the constructor. virtual void EnforceMinBitrate(bool enforce_min_bitrate) = 0; + + virtual void SetReservedBitrate(uint32_t reserved_bitrate_bps) = 0; }; } // namespace webrtc #endif // WEBRTC_MODULES_BITRATE_CONTROLLER_INCLUDE_BITRATE_CONTROLLER_H_ diff --git a/webrtc/video_engine/include/vie_rtp_rtcp.h b/webrtc/video_engine/include/vie_rtp_rtcp.h index b7db7ec0e..46d80989c 100644 --- a/webrtc/video_engine/include/vie_rtp_rtcp.h +++ b/webrtc/video_engine/include/vie_rtp_rtcp.h @@ -270,6 +270,13 @@ class WEBRTC_DLLEXPORT ViERTP_RTCP { return -1; }; + // Set a constant amount to deduct from received bitrate estimates before + // using it to allocate capacity among outgoing video streams. + virtual int SetReservedTransmitBitrate( + int video_channel, unsigned int reserved_transmit_bitrate_bps) { + return 0; + } + // This function returns our locally created statistics of the received RTP // stream. virtual int GetReceiveChannelRtcpStatistics(const int video_channel, diff --git a/webrtc/video_engine/test/auto_test/automated/vie_network_test.cc b/webrtc/video_engine/test/auto_test/automated/vie_network_test.cc index 3a595084c..efb9013d7 100644 --- a/webrtc/video_engine/test/auto_test/automated/vie_network_test.cc +++ b/webrtc/video_engine/test/auto_test/automated/vie_network_test.cc @@ -56,7 +56,7 @@ class RtcpCollectorTransport : public webrtc::Transport { it != packets_.end(); ++it) { if (it->remb_bitrate >= min_rate && it->remb_ssrc.end() != std::find(it->remb_ssrc.begin(), it->remb_ssrc.end(), ssrc)) { - return true; + return true; } } return false; @@ -210,5 +210,4 @@ TEST_F(ViENetworkTest, ReceiveBWEPacket_AST_DisabledReceive) { ReceiveASTPacketsForBWE(); EXPECT_FALSE(transport.FindREMBFor(kSsrc1, 0.0)); } - } // namespace diff --git a/webrtc/video_engine/test/auto_test/source/vie_autotest_rtp_rtcp.cc b/webrtc/video_engine/test/auto_test/source/vie_autotest_rtp_rtcp.cc index a635dfc3a..05540bc67 100644 --- a/webrtc/video_engine/test/auto_test/source/vie_autotest_rtp_rtcp.cc +++ b/webrtc/video_engine/test/auto_test/source/vie_autotest_rtp_rtcp.cc @@ -364,6 +364,33 @@ void ViEAutoTest::ViERtpRtcpStandardTest() EXPECT_GE(received.extended_max_sequence_number, sent.extended_max_sequence_number); EXPECT_EQ(0, ViE.base->StopSend(tbChannel.videoChannel)); + EXPECT_EQ(0, ViE.base->StopReceive(tbChannel.videoChannel)); + + // + // Test bandwidth statistics with reserved bitrate + // + + myTransport.ClearStats(); + network.packet_loss_rate = 0; + network.loss_model = kUniformLoss; + myTransport.SetNetworkParameters(network); + + ViE.rtp_rtcp->SetReservedTransmitBitrate(tbChannel.videoChannel, 2000000); + + EXPECT_EQ(0, ViE.base->StartReceive(tbChannel.videoChannel)); + EXPECT_EQ(0, ViE.base->StartSend(tbChannel.videoChannel)); + + AutoTestSleep(kAutoTestSleepTimeMs); + + estimated_bandwidth = 0; + EXPECT_EQ(0, ViE.rtp_rtcp->GetEstimatedSendBandwidth(tbChannel.videoChannel, + &estimated_bandwidth)); + if (FLAGS_include_timing_dependent_tests) { + EXPECT_EQ(0u, estimated_bandwidth); + } + + EXPECT_EQ(0, ViE.base->StopReceive(tbChannel.videoChannel)); + EXPECT_EQ(0, ViE.base->StopSend(tbChannel.videoChannel)); // // Test bandwidth statistics with NACK and FEC separately @@ -492,6 +519,7 @@ void ViEAutoTest::ViERtpRtcpStandardTest() EXPECT_EQ(0, ViE.base->StopReceive(tbChannel.videoChannel)); + ViETest::Log("Testing Network Down...\n"); EXPECT_EQ(0, ViE.rtp_rtcp->SetNACKStatus(tbChannel.videoChannel, true)); diff --git a/webrtc/video_engine/vie_channel_manager.cc b/webrtc/video_engine/vie_channel_manager.cc index 746cb2582..2e8387244 100644 --- a/webrtc/video_engine/vie_channel_manager.cc +++ b/webrtc/video_engine/vie_channel_manager.cc @@ -368,6 +368,19 @@ bool ViEChannelManager::SetRembStatus(int channel_id, bool sender, return group->SetChannelRembStatus(channel_id, sender, receiver, channel); } +bool ViEChannelManager::SetReservedTransmitBitrate( + int channel_id, uint32_t reserved_transmit_bitrate_bps) { + CriticalSectionScoped cs(channel_id_critsect_); + ChannelGroup* group = FindGroup(channel_id); + if (!group) { + return false; + } + + BitrateController* bitrate_controller = group->GetBitrateController(); + bitrate_controller->SetReservedBitrate(reserved_transmit_bitrate_bps); + return true; +} + void ViEChannelManager::UpdateSsrcs(int channel_id, const std::list& ssrcs) { CriticalSectionScoped cs(channel_id_critsect_); diff --git a/webrtc/video_engine/vie_channel_manager.h b/webrtc/video_engine/vie_channel_manager.h index a979ab60c..240f1b197 100644 --- a/webrtc/video_engine/vie_channel_manager.h +++ b/webrtc/video_engine/vie_channel_manager.h @@ -75,6 +75,9 @@ class ViEChannelManager: private ViEManagerBase { // Adds a channel to include when sending REMB. bool SetRembStatus(int channel_id, bool sender, bool receiver); + bool SetReservedTransmitBitrate(int channel_id, + uint32_t reserved_transmit_bitrate_bps); + // Updates the SSRCs for a channel. If one of the SSRCs already is registered, // it will simply be ignored and no error is returned. void UpdateSsrcs(int channel_id, const std::list& ssrcs); diff --git a/webrtc/video_engine/vie_rtp_rtcp_impl.cc b/webrtc/video_engine/vie_rtp_rtcp_impl.cc index cd8a46a6b..be7cc65e2 100644 --- a/webrtc/video_engine/vie_rtp_rtcp_impl.cc +++ b/webrtc/video_engine/vie_rtp_rtcp_impl.cc @@ -860,6 +860,19 @@ int ViERTP_RTCPImpl::SetMinTransmitBitrate(int video_channel, return 0; } +int ViERTP_RTCPImpl::SetReservedTransmitBitrate( + int video_channel, unsigned int reserved_transmit_bitrate_bps) { + WEBRTC_TRACE(kTraceApiCall, kTraceVideo, + ViEId(shared_data_->instance_id(), video_channel), + "ViERTP_RTCPImpl::SetReservedTransmitBitrate(%d, %d)", + video_channel, reserved_transmit_bitrate_bps); + if (!shared_data_->channel_manager()->SetReservedTransmitBitrate( + video_channel, reserved_transmit_bitrate_bps)) { + return -1; + } + return 0; +} + int ViERTP_RTCPImpl::GetReceiveChannelRtcpStatistics( const int video_channel, RtcpStatistics& basic_stats, diff --git a/webrtc/video_engine/vie_rtp_rtcp_impl.h b/webrtc/video_engine/vie_rtp_rtcp_impl.h index 3120beed0..1702d63e2 100644 --- a/webrtc/video_engine/vie_rtp_rtcp_impl.h +++ b/webrtc/video_engine/vie_rtp_rtcp_impl.h @@ -92,6 +92,8 @@ class ViERTP_RTCPImpl virtual int SetTransmissionSmoothingStatus(int video_channel, bool enable); virtual int SetMinTransmitBitrate(int video_channel, int min_transmit_bitrate_kbps); + virtual int SetReservedTransmitBitrate( + int video_channel, unsigned int reserved_transmit_bitrate_bps); virtual int GetReceiveChannelRtcpStatistics(const int video_channel, RtcpStatistics& basic_stats, int& rtt_ms) const;