Support REMB in combination with send-side BWE.

BUG=webrtc:4173

Review URL: https://codereview.webrtc.org/1581113006

Cr-Commit-Position: refs/heads/master@{#11322}
This commit is contained in:
stefan
2016-01-20 07:13:58 -08:00
committed by Commit bot
parent a5dec16b42
commit 32f81542c2
12 changed files with 206 additions and 24 deletions

View File

@ -237,8 +237,7 @@ TransportFeedbackObserver*
CongestionController::GetTransportFeedbackObserver() {
if (transport_feedback_adapter_.get() == nullptr) {
transport_feedback_adapter_.reset(new TransportFeedbackAdapter(
bitrate_controller_->CreateRtcpBandwidthObserver(),
Clock::GetRealTimeClock(), process_thread_));
bitrate_controller_.get(), Clock::GetRealTimeClock(), process_thread_));
transport_feedback_adapter_->SetBitrateEstimator(
new RemoteBitrateEstimatorAbsSendTime(
transport_feedback_adapter_.get(), Clock::GetRealTimeClock()));

View File

@ -143,6 +143,15 @@ void BitrateControllerImpl::OnReceivedEstimatedBitrate(uint32_t bitrate) {
MaybeTriggerOnNetworkChanged();
}
void BitrateControllerImpl::UpdateDelayBasedEstimate(uint32_t bitrate_bps) {
{
rtc::CritScope cs(&critsect_);
bandwidth_estimation_.UpdateDelayBasedEstimate(clock_->TimeInMilliseconds(),
bitrate_bps);
}
MaybeTriggerOnNetworkChanged();
}
int64_t BitrateControllerImpl::TimeUntilNextProcess() {
const int64_t kBitrateControllerUpdateIntervalMs = 25;
rtc::CritScope cs(&critsect_);

View File

@ -36,8 +36,9 @@ class BitrateControllerImpl : public BitrateController {
RtcpBandwidthObserver* CreateRtcpBandwidthObserver() override;
void SetStartBitrate(int start_bitrate_bps) override;
void SetMinMaxBitrate(int min_bitrate_bps,
int max_bitrate_bps) override;
void SetMinMaxBitrate(int min_bitrate_bps, int max_bitrate_bps) override;
void UpdateDelayBasedEstimate(uint32_t bitrate_bps) override;
void SetReservedBitrate(uint32_t reserved_bitrate_bps) override;

View File

@ -162,14 +162,18 @@ TEST_F(BitrateControllerTest, OneBitrateObserverOneRtcpObserver) {
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
EXPECT_EQ(300000, bitrate_observer_.last_bitrate_);
// Test that a low REMB trigger immediately.
// Test that a low delay-based estimate limits the combined estimate.
controller_->UpdateDelayBasedEstimate(280000);
EXPECT_EQ(280000, bitrate_observer_.last_bitrate_);
// Test that a low REMB limits the combined estimate.
bandwidth_observer_->OnReceivedEstimatedBitrate(250000);
EXPECT_EQ(250000, bitrate_observer_.last_bitrate_);
EXPECT_EQ(0, bitrate_observer_.last_fraction_loss_);
EXPECT_EQ(50, bitrate_observer_.last_rtt_);
bandwidth_observer_->OnReceivedEstimatedBitrate(1000);
EXPECT_EQ(100000, bitrate_observer_.last_bitrate_); // Min cap.
EXPECT_EQ(100000, bitrate_observer_.last_bitrate_);
}
TEST_F(BitrateControllerTest, OneBitrateObserverTwoRtcpObservers) {

View File

@ -57,6 +57,8 @@ class BitrateController : public Module {
virtual void SetStartBitrate(int start_bitrate_bps) = 0;
virtual void SetMinMaxBitrate(int min_bitrate_bps, int max_bitrate_bps) = 0;
virtual void UpdateDelayBasedEstimate(uint32_t bitrate_bps) = 0;
virtual void SetEventLog(RtcEventLog* event_log) = 0;
// Gets the available payload bandwidth in bits per second. Note that

View File

@ -24,6 +24,21 @@ class MockBitrateObserver : public BitrateObserver {
uint8_t fraction_loss,
int64_t rtt_ms));
};
class MockBitrateController : public BitrateController {
public:
MOCK_METHOD0(CreateRtcpBandwidthObserver, RtcpBandwidthObserver*());
MOCK_METHOD1(SetStartBitrate, void(int start_bitrate_bps));
MOCK_METHOD2(SetMinMaxBitrate,
void(int min_bitrate_bps, int max_bitrate_bps));
MOCK_METHOD1(UpdateDelayBasedEstimate, void(uint32_t bitrate_bps));
MOCK_METHOD1(SetEventLog, void(RtcEventLog* event_log));
MOCK_CONST_METHOD1(AvailableBandwidth, bool(uint32_t* bandwidth));
MOCK_METHOD1(SetReservedBitrate, void(uint32_t reserved_bitrate_bps));
MOCK_METHOD0(Process, int());
MOCK_METHOD0(TimeUntilNextProcess, int64_t());
};
} // namespace test
} // namespace webrtc

View File

@ -55,6 +55,7 @@ SendSideBandwidthEstimation::SendSideBandwidthEstimation()
last_fraction_loss_(0),
last_round_trip_time_ms_(0),
bwe_incoming_(0),
delay_based_bitrate_bps_(0),
time_last_decrease_ms_(0),
first_report_time_ms_(-1),
initially_lost_packets_(0),
@ -104,6 +105,13 @@ void SendSideBandwidthEstimation::UpdateReceiverEstimate(
bitrate_ = CapBitrateToThresholds(now_ms, bitrate_);
}
void SendSideBandwidthEstimation::UpdateDelayBasedEstimate(
int64_t now_ms,
uint32_t bitrate_bps) {
delay_based_bitrate_bps_ = bitrate_bps;
bitrate_ = CapBitrateToThresholds(now_ms, bitrate_);
}
void SendSideBandwidthEstimation::UpdateReceiverBlock(uint8_t fraction_loss,
int64_t rtt,
int number_of_packets,
@ -268,6 +276,9 @@ uint32_t SendSideBandwidthEstimation::CapBitrateToThresholds(
if (bwe_incoming_ > 0 && bitrate > bwe_incoming_) {
bitrate = bwe_incoming_;
}
if (delay_based_bitrate_bps_ > 0 && bitrate > delay_based_bitrate_bps_) {
bitrate = delay_based_bitrate_bps_;
}
if (bitrate > max_bitrate_configured_) {
bitrate = max_bitrate_configured_;
}

View File

@ -35,6 +35,9 @@ class SendSideBandwidthEstimation {
// Call when we receive a RTCP message with TMMBR or REMB.
void UpdateReceiverEstimate(int64_t now_ms, uint32_t bandwidth);
// Call when a new delay-based estimate is available.
void UpdateDelayBasedEstimate(int64_t now_ms, uint32_t bitrate_bps);
// Call when we receive a RTCP message with a ReceiveBlock.
void UpdateReceiverBlock(uint8_t fraction_loss,
int64_t rtt,
@ -80,6 +83,7 @@ class SendSideBandwidthEstimation {
int64_t last_round_trip_time_ms_;
uint32_t bwe_incoming_;
uint32_t delay_based_bitrate_bps_;
int64_t time_last_decrease_ms_;
int64_t first_report_time_ms_;
int initially_lost_packets_;

View File

@ -27,11 +27,11 @@ const int64_t kBaseTimestampScaleFactor =
const int64_t kBaseTimestampRangeSizeUs = kBaseTimestampScaleFactor * (1 << 24);
TransportFeedbackAdapter::TransportFeedbackAdapter(
RtcpBandwidthObserver* bandwidth_observer,
BitrateController* bitrate_controller,
Clock* clock,
ProcessThread* process_thread)
: send_time_history_(clock, kSendTimeHistoryWindowMs),
rtcp_bandwidth_observer_(bandwidth_observer),
bitrate_controller_(bitrate_controller),
process_thread_(process_thread),
clock_(clock),
current_offset_ms_(kNoTimestamp),
@ -124,7 +124,7 @@ void TransportFeedbackAdapter::OnTransportFeedback(
void TransportFeedbackAdapter::OnReceiveBitrateChanged(
const std::vector<unsigned int>& ssrcs,
unsigned int bitrate) {
rtcp_bandwidth_observer_->OnReceivedEstimatedBitrate(bitrate);
bitrate_controller_->UpdateDelayBasedEstimate(bitrate);
}
void TransportFeedbackAdapter::OnRttUpdate(int64_t avg_rtt_ms,

View File

@ -15,7 +15,7 @@
#include "webrtc/base/criticalsection.h"
#include "webrtc/base/thread_annotations.h"
#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h"
#include "webrtc/modules/bitrate_controller/include/bitrate_controller.h"
#include "webrtc/modules/include/module_common_types.h"
#include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
#include "webrtc/modules/remote_bitrate_estimator/include/send_time_history.h"
@ -28,7 +28,7 @@ class TransportFeedbackAdapter : public TransportFeedbackObserver,
public CallStatsObserver,
public RemoteBitrateObserver {
public:
TransportFeedbackAdapter(RtcpBandwidthObserver* bandwidth_observer,
TransportFeedbackAdapter(BitrateController* bitrate_controller,
Clock* clock,
ProcessThread* process_thread);
virtual ~TransportFeedbackAdapter();
@ -54,7 +54,7 @@ class TransportFeedbackAdapter : public TransportFeedbackObserver,
rtc::CriticalSection lock_;
SendTimeHistory send_time_history_ GUARDED_BY(&lock_);
rtc::scoped_ptr<RtcpBandwidthObserver> rtcp_bandwidth_observer_;
BitrateController* bitrate_controller_;
rtc::scoped_ptr<RemoteBitrateEstimator> bitrate_estimator_;
ProcessThread* const process_thread_;
Clock* const clock_;

View File

@ -16,6 +16,7 @@
#include "webrtc/base/checks.h"
#include "webrtc/base/scoped_ptr.h"
#include "webrtc/modules/bitrate_controller/include/mock/mock_bitrate_controller.h"
#include "webrtc/modules/remote_bitrate_estimator/include/mock/mock_remote_bitrate_estimator.h"
#include "webrtc/modules/remote_bitrate_estimator/transport_feedback_adapter.h"
#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h"
@ -34,13 +35,14 @@ class TransportFeedbackAdapterTest : public ::testing::Test {
TransportFeedbackAdapterTest()
: clock_(0),
bitrate_estimator_(nullptr),
bitrate_controller_(this),
receiver_estimated_bitrate_(0) {}
virtual ~TransportFeedbackAdapterTest() {}
virtual void SetUp() {
adapter_.reset(new TransportFeedbackAdapter(
new RtcpBandwidthObserverAdapter(this), &clock_, &process_thread_));
adapter_.reset(new TransportFeedbackAdapter(&bitrate_controller_, &clock_,
&process_thread_));
bitrate_estimator_ = new MockRemoteBitrateEstimator();
EXPECT_CALL(process_thread_, RegisterModule(bitrate_estimator_)).Times(1);
@ -55,19 +57,15 @@ class TransportFeedbackAdapterTest : public ::testing::Test {
protected:
// Proxy class used since TransportFeedbackAdapter will own the instance
// passed at construction.
class RtcpBandwidthObserverAdapter : public RtcpBandwidthObserver {
class MockBitrateControllerAdapter : public MockBitrateController {
public:
explicit RtcpBandwidthObserverAdapter(TransportFeedbackAdapterTest* owner)
: owner_(owner) {}
explicit MockBitrateControllerAdapter(TransportFeedbackAdapterTest* owner)
: MockBitrateController(), owner_(owner) {}
void OnReceivedEstimatedBitrate(uint32_t bitrate) override {
owner_->receiver_estimated_bitrate_ = bitrate;
}
~MockBitrateControllerAdapter() override {}
void OnReceivedRtcpReceiverReport(const ReportBlockList& report_blocks,
int64_t rtt,
int64_t now_ms) override {
RTC_NOTREACHED();
void UpdateDelayBasedEstimate(uint32_t bitrate_bps) override {
owner_->receiver_estimated_bitrate_ = bitrate_bps;
}
TransportFeedbackAdapterTest* const owner_;
@ -113,6 +111,7 @@ class TransportFeedbackAdapterTest : public ::testing::Test {
SimulatedClock clock_;
MockProcessThread process_thread_;
MockRemoteBitrateEstimator* bitrate_estimator_;
MockBitrateControllerAdapter bitrate_controller_;
rtc::scoped_ptr<TransportFeedbackAdapter> adapter_;
uint32_t receiver_estimated_bitrate_;

View File

@ -20,6 +20,7 @@
#include "webrtc/call.h"
#include "webrtc/call/transport_adapter.h"
#include "webrtc/frame_callback.h"
#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h"
#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
#include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h"
@ -1807,6 +1808,143 @@ TEST_F(EndToEndTest, VerifyBandwidthStats) {
RunBaseTest(&test);
}
// Verifies that it's possible to limit the send BWE by sending a REMB.
// This is verified by allowing the send BWE to ramp-up to >1000 kbps,
// then have the test generate a REMB of 500 kbps and verify that the send BWE
// is reduced to exactly 500 kbps. Then a REMB of 1000 kbps is generated and the
// test verifies that the send BWE ramps back up to exactly 1000 kbps.
TEST_F(EndToEndTest, RembWithSendSideBwe) {
class BweObserver : public test::EndToEndTest {
public:
BweObserver()
: EndToEndTest(kDefaultTimeoutMs),
sender_call_(nullptr),
clock_(Clock::GetRealTimeClock()),
sender_ssrc_(0),
remb_bitrate_bps_(1000000),
receive_transport_(nullptr),
event_(false, false),
poller_thread_(&BitrateStatsPollingThread,
this,
"BitrateStatsPollingThread"),
state_(kWaitForFirstRampUp) {}
~BweObserver() {}
test::PacketTransport* CreateReceiveTransport() {
receive_transport_ = new test::PacketTransport(
nullptr, this, test::PacketTransport::kReceiver,
FakeNetworkPipe::Config());
return receive_transport_;
}
Call::Config GetSenderCallConfig() override {
Call::Config config;
// Set a high start bitrate to reduce the test completion time.
config.bitrate_config.start_bitrate_bps = remb_bitrate_bps_;
return config;
}
void ModifyVideoConfigs(
VideoSendStream::Config* send_config,
std::vector<VideoReceiveStream::Config>* receive_configs,
VideoEncoderConfig* encoder_config) override {
ASSERT_EQ(1u, send_config->rtp.ssrcs.size());
send_config->rtp.extensions.clear();
send_config->rtp.extensions.push_back(
RtpExtension(RtpExtension::kTransportSequenceNumber,
test::kTransportSequenceNumberExtensionId));
sender_ssrc_ = send_config->rtp.ssrcs[0];
encoder_config->streams[0].max_bitrate_bps =
encoder_config->streams[0].target_bitrate_bps = 2000000;
ASSERT_EQ(1u, receive_configs->size());
(*receive_configs)[0].rtp.remb = false;
(*receive_configs)[0].rtp.transport_cc = true;
(*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
RtpRtcp::Configuration config;
config.receiver_only = true;
config.clock = clock_;
config.outgoing_transport = receive_transport_;
rtp_rtcp_.reset(RtpRtcp::CreateRtpRtcp(config));
rtp_rtcp_->SetRemoteSSRC((*receive_configs)[0].rtp.remote_ssrc);
rtp_rtcp_->SetSSRC((*receive_configs)[0].rtp.local_ssrc);
rtp_rtcp_->SetREMBStatus(true);
rtp_rtcp_->SetSendingStatus(true);
rtp_rtcp_->SetRTCPStatus(RtcpMode::kReducedSize);
}
void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
sender_call_ = sender_call;
}
static bool BitrateStatsPollingThread(void* obj) {
return static_cast<BweObserver*>(obj)->PollStats();
}
bool PollStats() {
if (sender_call_) {
Call::Stats stats = sender_call_->GetStats();
switch (state_) {
case kWaitForFirstRampUp:
if (stats.send_bandwidth_bps >= remb_bitrate_bps_) {
state_ = kWaitForRemb;
remb_bitrate_bps_ /= 2;
rtp_rtcp_->SetREMBData(
remb_bitrate_bps_,
std::vector<uint32_t>(&sender_ssrc_, &sender_ssrc_ + 1));
rtp_rtcp_->SendRTCP(kRtcpRr);
}
break;
case kWaitForRemb:
if (stats.send_bandwidth_bps == remb_bitrate_bps_) {
state_ = kWaitForSecondRampUp;
remb_bitrate_bps_ *= 2;
rtp_rtcp_->SetREMBData(
remb_bitrate_bps_,
std::vector<uint32_t>(&sender_ssrc_, &sender_ssrc_ + 1));
rtp_rtcp_->SendRTCP(kRtcpRr);
}
break;
case kWaitForSecondRampUp:
if (stats.send_bandwidth_bps == remb_bitrate_bps_) {
observation_complete_.Set();
}
break;
}
}
return !event_.Wait(1000);
}
void PerformTest() override {
poller_thread_.Start();
EXPECT_TRUE(Wait())
<< "Timed out while waiting for bitrate to change according to REMB.";
poller_thread_.Stop();
}
private:
enum TestState { kWaitForFirstRampUp, kWaitForRemb, kWaitForSecondRampUp };
Call* sender_call_;
Clock* const clock_;
uint32_t sender_ssrc_;
int remb_bitrate_bps_;
rtc::scoped_ptr<RtpRtcp> rtp_rtcp_;
test::PacketTransport* receive_transport_;
rtc::Event event_;
rtc::PlatformThread poller_thread_;
TestState state_;
} test;
RunBaseTest(&test);
}
TEST_F(EndToEndTest, VerifyNackStats) {
static const int kPacketNumberToDrop = 200;
class NackObserver : public test::EndToEndTest {