Add API to allow deducting bitrate from incoming estimates before the capacity is distributed among outgoing video streams. For example, this can be used to reserve space for audio streams.
BUG= R=stefan@webrtc.org Review URL: https://webrtc-codereview.appspot.com/10499004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@5791 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
@@ -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;
|
||||
|
@@ -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_
|
||||
|
@@ -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;
|
||||
|
@@ -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_
|
||||
|
@@ -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,
|
||||
|
@@ -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
|
||||
|
@@ -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));
|
||||
|
@@ -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<unsigned int>& ssrcs) {
|
||||
CriticalSectionScoped cs(channel_id_critsect_);
|
||||
|
@@ -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<unsigned int>& ssrcs);
|
||||
|
@@ -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,
|
||||
|
@@ -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;
|
||||
|
Reference in New Issue
Block a user