Reland of Fixes a bug where a video stream can get stuck in the suspended state. (patchset #1 id:1 of https://codereview.chromium.org/2703393002/ )

Reason for revert:
Downstream fixed

Original issue's description:
> Revert of Fixes a bug where a video stream can get stuck in the suspended state. (patchset #8 id:120001 of https://codereview.webrtc.org/2705603002/ )
>
> Reason for revert:
> Breaks downstream
>
> Original issue's description:
> > Fixes a bug where a video stream can get stuck in the suspended state.
> >
> > This happens if a lot of FEC is allocated when the stream becomes suspended. The required bitrate to unsuspend can then be too high so that the padding bitrate we are allowed to generate is not enough.
> >
> > This CL also switches the tests from using ISAC to OPUS as RampUpTest.UpDownUpAudioVideoTransportSequenceNumberRtx relies on audio BWE to work (which is only compatible with OPUS). I don't know why it didn't fail before.
> >
> > BUG=webrtc:7178
> >
> > Review-Url: https://codereview.webrtc.org/2705603002
> > Cr-Commit-Position: refs/heads/master@{#16739}
> > Committed: a518a39963
>
> TBR=mflodman@webrtc.org,terelius@webrtc.org,stefan@webrtc.org
> # Skipping CQ checks because original CL landed less than 1 days ago.
> NOPRESUBMIT=true
> NOTREECHECKS=true
> NOTRY=true
> BUG=webrtc:7178
>
> Review-Url: https://codereview.webrtc.org/2703393002
> Cr-Commit-Position: refs/heads/master@{#16751}
> Committed: b80bdcafed

TBR=mflodman@webrtc.org,terelius@webrtc.org,stefan@webrtc.org
# Skipping CQ checks because original CL landed less than 1 days ago.
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=webrtc:7178

Review-Url: https://codereview.webrtc.org/2704323003
Cr-Commit-Position: refs/heads/master@{#16753}
This commit is contained in:
philipel
2017-02-21 07:28:31 -08:00
committed by Commit bot
parent e326cd8342
commit 5ef2bc1914
8 changed files with 191 additions and 78 deletions

View File

@ -54,7 +54,9 @@ BitrateAllocator::BitrateAllocator(LimitObserver* limit_observer)
last_rtt_(0), last_rtt_(0),
num_pause_events_(0), num_pause_events_(0),
clock_(Clock::GetRealTimeClock()), clock_(Clock::GetRealTimeClock()),
last_bwe_log_time_(0) { last_bwe_log_time_(0),
total_requested_padding_bitrate_(0),
total_requested_min_bitrate_(0) {
sequenced_checker_.Detach(); sequenced_checker_.Detach();
} }
@ -115,6 +117,7 @@ void BitrateAllocator::OnNetworkChanged(uint32_t target_bitrate_bps,
config.media_ratio = MediaRatio(allocated_bitrate, protection_bitrate); config.media_ratio = MediaRatio(allocated_bitrate, protection_bitrate);
config.allocated_bitrate_bps = allocated_bitrate; config.allocated_bitrate_bps = allocated_bitrate;
} }
UpdateAllocationLimits();
} }
void BitrateAllocator::AddObserver(BitrateAllocatorObserver* observer, void BitrateAllocator::AddObserver(BitrateAllocatorObserver* observer,
@ -167,12 +170,24 @@ void BitrateAllocator::UpdateAllocationLimits() {
uint32_t total_requested_min_bitrate = 0; uint32_t total_requested_min_bitrate = 0;
for (const auto& config : bitrate_observer_configs_) { for (const auto& config : bitrate_observer_configs_) {
uint32_t stream_padding = config.pad_up_bitrate_bps;
if (config.enforce_min_bitrate) { if (config.enforce_min_bitrate) {
total_requested_min_bitrate += config.min_bitrate_bps; total_requested_min_bitrate += config.min_bitrate_bps;
} else if (config.allocated_bitrate_bps == 0) {
stream_padding =
std::max(MinBitrateWithHysteresis(config), stream_padding);
} }
total_requested_padding_bitrate += config.pad_up_bitrate_bps; total_requested_padding_bitrate += stream_padding;
} }
if (total_requested_padding_bitrate == total_requested_padding_bitrate_ &&
total_requested_min_bitrate == total_requested_min_bitrate_) {
return;
}
total_requested_min_bitrate_ = total_requested_min_bitrate;
total_requested_padding_bitrate_ = total_requested_padding_bitrate;
LOG(LS_INFO) << "UpdateAllocationLimits : total_requested_min_bitrate: " LOG(LS_INFO) << "UpdateAllocationLimits : total_requested_min_bitrate: "
<< total_requested_min_bitrate << total_requested_min_bitrate
<< "bps, total_requested_padding_bitrate: " << "bps, total_requested_padding_bitrate: "
@ -416,8 +431,9 @@ bool BitrateAllocator::EnoughBitrateForAllObservers(uint32_t bitrate,
static_cast<uint32_t>(bitrate_observer_configs_.size()); static_cast<uint32_t>(bitrate_observer_configs_.size());
for (const auto& observer_config : bitrate_observer_configs_) { for (const auto& observer_config : bitrate_observer_configs_) {
if (observer_config.min_bitrate_bps + extra_bitrate_per_observer < if (observer_config.min_bitrate_bps + extra_bitrate_per_observer <
MinBitrateWithHysteresis(observer_config)) MinBitrateWithHysteresis(observer_config)) {
return false; return false;
}
} }
return true; return true;
} }

View File

@ -165,6 +165,8 @@ class BitrateAllocator {
int num_pause_events_ GUARDED_BY(&sequenced_checker_); int num_pause_events_ GUARDED_BY(&sequenced_checker_);
Clock* const clock_ GUARDED_BY(&sequenced_checker_); Clock* const clock_ GUARDED_BY(&sequenced_checker_);
int64_t last_bwe_log_time_ GUARDED_BY(&sequenced_checker_); int64_t last_bwe_log_time_ GUARDED_BY(&sequenced_checker_);
uint32_t total_requested_padding_bitrate_ GUARDED_BY(&sequenced_checker_);
uint32_t total_requested_min_bitrate_ GUARDED_BY(&sequenced_checker_);
}; };
} // namespace webrtc } // namespace webrtc
#endif // WEBRTC_CALL_BITRATE_ALLOCATOR_H_ #endif // WEBRTC_CALL_BITRATE_ALLOCATOR_H_

View File

@ -98,8 +98,6 @@ TEST_F(BitrateAllocatorTest, UpdatingBitrateObserver) {
true); true);
EXPECT_EQ(4000000, allocator_->GetStartBitrate(&bitrate_observer)); EXPECT_EQ(4000000, allocator_->GetStartBitrate(&bitrate_observer));
EXPECT_CALL(limit_observer_,
OnAllocationLimitsChanged(kMinSendBitrateBps, 0));
allocator_->AddObserver(&bitrate_observer, kMinSendBitrateBps, 1500000, 0, allocator_->AddObserver(&bitrate_observer, kMinSendBitrateBps, 1500000, 0,
true); true);
EXPECT_EQ(3000000, allocator_->GetStartBitrate(&bitrate_observer)); EXPECT_EQ(3000000, allocator_->GetStartBitrate(&bitrate_observer));
@ -183,7 +181,7 @@ TEST_F(BitrateAllocatorTestNoEnforceMin, OneBitrateObserver) {
TestBitrateObserver bitrate_observer_1; TestBitrateObserver bitrate_observer_1;
// Expect OnAllocationLimitsChanged with |min_send_bitrate_bps| = 0 since // Expect OnAllocationLimitsChanged with |min_send_bitrate_bps| = 0 since
// AddObserver is called with |enforce_min_bitrate| = false. // AddObserver is called with |enforce_min_bitrate| = false.
EXPECT_CALL(limit_observer_, OnAllocationLimitsChanged(0, 0)); EXPECT_CALL(limit_observer_, OnAllocationLimitsChanged(0, 120000));
allocator_->AddObserver(&bitrate_observer_1, 100000, 400000, 0, false); allocator_->AddObserver(&bitrate_observer_1, 100000, 400000, 0, false);
EXPECT_EQ(300000, allocator_->GetStartBitrate(&bitrate_observer_1)); EXPECT_EQ(300000, allocator_->GetStartBitrate(&bitrate_observer_1));
@ -264,7 +262,7 @@ TEST_F(BitrateAllocatorTestNoEnforceMin, OneBitrateObserverWithPacketLoss) {
TestBitrateObserver bitrate_observer; TestBitrateObserver bitrate_observer;
// Expect OnAllocationLimitsChanged with |min_send_bitrate_bps| = 0 since // Expect OnAllocationLimitsChanged with |min_send_bitrate_bps| = 0 since
// AddObserver is called with |enforce_min_bitrate| = false. // AddObserver is called with |enforce_min_bitrate| = false.
EXPECT_CALL(limit_observer_, OnAllocationLimitsChanged(0, 0)); EXPECT_CALL(limit_observer_, OnAllocationLimitsChanged(0, 168000));
allocator_->AddObserver( allocator_->AddObserver(
&bitrate_observer, 100000, 400000, 0, false); &bitrate_observer, 100000, 400000, 0, false);
EXPECT_EQ(300000, allocator_->GetStartBitrate(&bitrate_observer)); EXPECT_EQ(300000, allocator_->GetStartBitrate(&bitrate_observer));
@ -292,6 +290,7 @@ TEST_F(BitrateAllocatorTestNoEnforceMin, OneBitrateObserverWithPacketLoss) {
EXPECT_EQ(0u, bitrate_observer.last_bitrate_bps_); EXPECT_EQ(0u, bitrate_observer.last_bitrate_bps_);
// Just enough to enable video again. // Just enough to enable video again.
EXPECT_CALL(limit_observer_, OnAllocationLimitsChanged(0, 0));
allocator_->OnNetworkChanged(168000, 0, fraction_loss, allocator_->OnNetworkChanged(168000, 0, fraction_loss,
kDefaultProbingIntervalMs); kDefaultProbingIntervalMs);
EXPECT_EQ(168000u, bitrate_observer.last_bitrate_bps_); EXPECT_EQ(168000u, bitrate_observer.last_bitrate_bps_);
@ -304,7 +303,6 @@ TEST_F(BitrateAllocatorTestNoEnforceMin, OneBitrateObserverWithPacketLoss) {
allocator_->OnNetworkChanged(139000, 0, 0, kDefaultProbingIntervalMs); allocator_->OnNetworkChanged(139000, 0, 0, kDefaultProbingIntervalMs);
EXPECT_EQ(139000u, bitrate_observer.last_bitrate_bps_); EXPECT_EQ(139000u, bitrate_observer.last_bitrate_bps_);
EXPECT_CALL(limit_observer_, OnAllocationLimitsChanged(0, 0));
allocator_->RemoveObserver(&bitrate_observer); allocator_->RemoveObserver(&bitrate_observer);
} }

View File

@ -11,6 +11,7 @@
#include "webrtc/call/rampup_tests.h" #include "webrtc/call/rampup_tests.h"
#include "webrtc/base/checks.h" #include "webrtc/base/checks.h"
#include "webrtc/base/logging.h"
#include "webrtc/base/platform_thread.h" #include "webrtc/base/platform_thread.h"
#include "webrtc/test/encoder_settings.h" #include "webrtc/test/encoder_settings.h"
#include "webrtc/test/gtest.h" #include "webrtc/test/gtest.h"
@ -20,7 +21,7 @@ namespace webrtc {
namespace { namespace {
static const int64_t kPollIntervalMs = 20; static const int64_t kPollIntervalMs = 20;
static const int kExpectedHighVideoBitrateBps = 60000; static const int kExpectedHighVideoBitrateBps = 80000;
static const int kExpectedHighAudioBitrateBps = 30000; static const int kExpectedHighAudioBitrateBps = 30000;
static const int kLowBandwidthLimitBps = 20000; static const int kLowBandwidthLimitBps = 20000;
static const int kExpectedLowBitrateBps = 20000; static const int kExpectedLowBitrateBps = 20000;
@ -35,6 +36,7 @@ std::vector<uint32_t> GenerateSsrcs(size_t num_streams, uint32_t ssrc_offset) {
RampUpTester::RampUpTester(size_t num_video_streams, RampUpTester::RampUpTester(size_t num_video_streams,
size_t num_audio_streams, size_t num_audio_streams,
size_t num_flexfec_streams,
unsigned int start_bitrate_bps, unsigned int start_bitrate_bps,
int64_t min_run_time_ms, int64_t min_run_time_ms,
const std::string& extension_type, const std::string& extension_type,
@ -46,6 +48,7 @@ RampUpTester::RampUpTester(size_t num_video_streams,
clock_(Clock::GetRealTimeClock()), clock_(Clock::GetRealTimeClock()),
num_video_streams_(num_video_streams), num_video_streams_(num_video_streams),
num_audio_streams_(num_audio_streams), num_audio_streams_(num_audio_streams),
num_flexfec_streams_(num_flexfec_streams),
rtx_(rtx), rtx_(rtx),
red_(red), red_(red),
sender_call_(nullptr), sender_call_(nullptr),
@ -63,6 +66,8 @@ RampUpTester::RampUpTester(size_t num_video_streams,
poller_thread_(&BitrateStatsPollingThread, poller_thread_(&BitrateStatsPollingThread,
this, this,
"BitrateStatsPollingThread") { "BitrateStatsPollingThread") {
if (red_)
EXPECT_EQ(0u, num_flexfec_streams_);
EXPECT_LE(num_audio_streams_, 1u); EXPECT_LE(num_audio_streams_, 1u);
} }
@ -100,6 +105,10 @@ size_t RampUpTester::GetNumAudioStreams() const {
return num_audio_streams_; return num_audio_streams_;
} }
size_t RampUpTester::GetNumFlexfecStreams() const {
return num_flexfec_streams_;
}
class RampUpTester::VideoStreamFactory class RampUpTester::VideoStreamFactory
: public VideoEncoderConfig::VideoStreamFactoryInterface { : public VideoEncoderConfig::VideoStreamFactoryInterface {
public: public:
@ -209,6 +218,13 @@ void RampUpTester::ModifyVideoConfigs(
} }
++i; ++i;
} }
RTC_DCHECK_LE(num_flexfec_streams_, 1);
if (num_flexfec_streams_ == 1) {
send_config->rtp.flexfec.payload_type = test::CallTest::kFlexfecPayloadType;
send_config->rtp.flexfec.ssrc = test::CallTest::kFlexfecSendSsrc;
send_config->rtp.flexfec.protected_media_ssrcs = {video_ssrcs_[0]};
}
} }
void RampUpTester::ModifyAudioConfigs( void RampUpTester::ModifyAudioConfigs(
@ -219,6 +235,8 @@ void RampUpTester::ModifyAudioConfigs(
EXPECT_NE(RtpExtension::kTimestampOffsetUri, extension_type_) EXPECT_NE(RtpExtension::kTimestampOffsetUri, extension_type_)
<< "Audio BWE not supported with toffset."; << "Audio BWE not supported with toffset.";
EXPECT_NE(RtpExtension::kAbsSendTimeUri, extension_type_)
<< "Audio BWE not supported with abs-send-time.";
send_config->rtp.ssrc = audio_ssrcs_[0]; send_config->rtp.ssrc = audio_ssrcs_[0];
send_config->rtp.extensions.clear(); send_config->rtp.extensions.clear();
@ -227,11 +245,7 @@ void RampUpTester::ModifyAudioConfigs(
send_config->max_bitrate_bps = 60000; send_config->max_bitrate_bps = 60000;
bool transport_cc = false; bool transport_cc = false;
if (extension_type_ == RtpExtension::kAbsSendTimeUri) { if (extension_type_ == RtpExtension::kTransportSequenceNumberUri) {
transport_cc = false;
send_config->rtp.extensions.push_back(
RtpExtension(extension_type_.c_str(), kAbsSendTimeExtensionId));
} else if (extension_type_ == RtpExtension::kTransportSequenceNumberUri) {
transport_cc = true; transport_cc = true;
send_config->rtp.extensions.push_back(RtpExtension( send_config->rtp.extensions.push_back(RtpExtension(
extension_type_.c_str(), kTransportSequenceNumberExtensionId)); extension_type_.c_str(), kTransportSequenceNumberExtensionId));
@ -244,6 +258,26 @@ void RampUpTester::ModifyAudioConfigs(
} }
} }
void RampUpTester::ModifyFlexfecConfigs(
std::vector<FlexfecReceiveStream::Config>* receive_configs) {
if (num_flexfec_streams_ == 0)
return;
RTC_DCHECK_EQ(1, num_flexfec_streams_);
(*receive_configs)[0].payload_type = test::CallTest::kFlexfecPayloadType;
(*receive_configs)[0].remote_ssrc = test::CallTest::kFlexfecSendSsrc;
(*receive_configs)[0].protected_media_ssrcs = {video_ssrcs_[0]};
(*receive_configs)[0].local_ssrc = video_ssrcs_[0];
if (extension_type_ == RtpExtension::kAbsSendTimeUri) {
(*receive_configs)[0].transport_cc = false;
(*receive_configs)[0].rtp_header_extensions.push_back(
RtpExtension(extension_type_.c_str(), kAbsSendTimeExtensionId));
} else if (extension_type_ == RtpExtension::kTransportSequenceNumberUri) {
(*receive_configs)[0].transport_cc = true;
(*receive_configs)[0].rtp_header_extensions.push_back(RtpExtension(
extension_type_.c_str(), kTransportSequenceNumberExtensionId));
}
}
void RampUpTester::OnCallsCreated(Call* sender_call, Call* receiver_call) { void RampUpTester::OnCallsCreated(Call* sender_call, Call* receiver_call) {
sender_call_ = sender_call; sender_call_ = sender_call;
} }
@ -351,23 +385,32 @@ void RampUpTester::PerformTest() {
RampUpDownUpTester::RampUpDownUpTester(size_t num_video_streams, RampUpDownUpTester::RampUpDownUpTester(size_t num_video_streams,
size_t num_audio_streams, size_t num_audio_streams,
size_t num_flexfec_streams,
unsigned int start_bitrate_bps, unsigned int start_bitrate_bps,
const std::string& extension_type, const std::string& extension_type,
bool rtx, bool rtx,
bool red) bool red,
const std::vector<int>& loss_rates)
: RampUpTester(num_video_streams, : RampUpTester(num_video_streams,
num_audio_streams, num_audio_streams,
num_flexfec_streams,
start_bitrate_bps, start_bitrate_bps,
0, 0,
extension_type, extension_type,
rtx, rtx,
red, red,
true), true),
link_rates_({GetHighLinkCapacity(), kLowBandwidthLimitBps / 1000,
GetHighLinkCapacity(), 0}),
test_state_(kFirstRampup), test_state_(kFirstRampup),
next_state_(kTransitionToNextState),
state_start_ms_(clock_->TimeInMilliseconds()), state_start_ms_(clock_->TimeInMilliseconds()),
interval_start_ms_(clock_->TimeInMilliseconds()), interval_start_ms_(clock_->TimeInMilliseconds()),
sent_bytes_(0) { sent_bytes_(0),
forward_transport_config_.link_capacity_kbps = GetHighLinkCapacity(); loss_rates_(loss_rates) {
forward_transport_config_.link_capacity_kbps = link_rates_[test_state_];
forward_transport_config_.queue_delay_ms = 100;
forward_transport_config_.loss_percent = loss_rates_[test_state_];
} }
RampUpDownUpTester::~RampUpDownUpTester() {} RampUpDownUpTester::~RampUpDownUpTester() {}
@ -432,57 +475,79 @@ int RampUpDownUpTester::GetHighLinkCapacity() const {
return 4 * GetExpectedHighBitrate() / (3 * 1000); return 4 * GetExpectedHighBitrate() / (3 * 1000);
} }
size_t RampUpDownUpTester::GetFecBytes() const {
size_t flex_fec_bytes = 0;
if (num_flexfec_streams_ > 0) {
webrtc::VideoSendStream::Stats stats = send_stream_->GetStats();
for (const auto& kv : stats.substreams)
flex_fec_bytes += kv.second.rtp_stats.fec.TotalBytes();
}
return flex_fec_bytes;
}
bool RampUpDownUpTester::ExpectingFec() const {
return num_flexfec_streams_ > 0 && forward_transport_config_.loss_percent > 0;
}
void RampUpDownUpTester::EvolveTestState(int bitrate_bps, bool suspended) { void RampUpDownUpTester::EvolveTestState(int bitrate_bps, bool suspended) {
int64_t now = clock_->TimeInMilliseconds(); int64_t now = clock_->TimeInMilliseconds();
switch (test_state_) { switch (test_state_) {
case kFirstRampup: { case kFirstRampup:
EXPECT_FALSE(suspended); EXPECT_FALSE(suspended);
if (bitrate_bps >= GetExpectedHighBitrate()) { if (bitrate_bps >= GetExpectedHighBitrate()) {
// The first ramp-up has reached the target bitrate. Change the
// channel limit, and move to the next test state.
forward_transport_config_.link_capacity_kbps =
kLowBandwidthLimitBps / 1000;
send_transport_->SetConfig(forward_transport_config_);
test_state_ = kLowRate;
webrtc::test::PrintResult("ramp_up_down_up", GetModifierString(), webrtc::test::PrintResult("ramp_up_down_up", GetModifierString(),
"first_rampup", now - state_start_ms_, "ms", "first_rampup", now - state_start_ms_, "ms",
false); false);
state_start_ms_ = now; // Apply loss during the transition between states if FEC is enabled.
interval_start_ms_ = now; forward_transport_config_.loss_percent = loss_rates_[test_state_];
sent_bytes_ = 0; test_state_ = kTransitionToNextState;
next_state_ = kLowRate;
} }
break; break;
}
case kLowRate: { case kLowRate: {
// Audio streams are never suspended. // Audio streams are never suspended.
bool check_suspend_state = num_video_streams_ > 0; bool check_suspend_state = num_video_streams_ > 0;
if (bitrate_bps < kExpectedLowBitrateBps && if (bitrate_bps < kExpectedLowBitrateBps &&
suspended == check_suspend_state) { suspended == check_suspend_state) {
// The ramp-down was successful. Change the channel limit back to a
// high value, and move to the next test state.
forward_transport_config_.link_capacity_kbps = GetHighLinkCapacity();
send_transport_->SetConfig(forward_transport_config_);
test_state_ = kSecondRampup;
webrtc::test::PrintResult("ramp_up_down_up", GetModifierString(), webrtc::test::PrintResult("ramp_up_down_up", GetModifierString(),
"rampdown", now - state_start_ms_, "ms", "rampdown", now - state_start_ms_, "ms",
false); false);
state_start_ms_ = now; // Apply loss during the transition between states if FEC is enabled.
interval_start_ms_ = now; forward_transport_config_.loss_percent = loss_rates_[test_state_];
sent_bytes_ = 0; test_state_ = kTransitionToNextState;
next_state_ = kSecondRampup;
} }
break; break;
} }
case kSecondRampup: { case kSecondRampup:
if (bitrate_bps >= GetExpectedHighBitrate() && !suspended) { if (bitrate_bps >= GetExpectedHighBitrate() && !suspended) {
webrtc::test::PrintResult("ramp_up_down_up", GetModifierString(), webrtc::test::PrintResult("ramp_up_down_up", GetModifierString(),
"second_rampup", now - state_start_ms_, "ms", "second_rampup", now - state_start_ms_, "ms",
false); false);
ReportResult("ramp-up-down-up-average-network-latency", ReportResult("ramp-up-down-up-average-network-latency",
send_transport_->GetAverageDelayMs(), "milliseconds"); send_transport_->GetAverageDelayMs(), "milliseconds");
observation_complete_.Set(); // Apply loss during the transition between states if FEC is enabled.
forward_transport_config_.loss_percent = loss_rates_[test_state_];
test_state_ = kTransitionToNextState;
next_state_ = kTestEnd;
}
break;
case kTestEnd:
observation_complete_.Set();
break;
case kTransitionToNextState:
if (!ExpectingFec() || GetFecBytes() > 0) {
test_state_ = next_state_;
forward_transport_config_.link_capacity_kbps = link_rates_[test_state_];
// No loss while ramping up and down as it may affect the BWE
// negatively, making the test flaky.
forward_transport_config_.loss_percent = 0;
state_start_ms_ = now;
interval_start_ms_ = now;
sent_bytes_ = 0;
send_transport_->SetConfig(forward_transport_config_);
} }
break; break;
}
} }
} }
@ -499,70 +564,83 @@ class RampUpTest : public test::CallTest {
static const uint32_t kStartBitrateBps = 60000; static const uint32_t kStartBitrateBps = 60000;
TEST_F(RampUpTest, UpDownUpAbsSendTimeSimulcastRedRtx) { TEST_F(RampUpTest, UpDownUpAbsSendTimeSimulcastRedRtx) {
RampUpDownUpTester test(3, 0, kStartBitrateBps, RtpExtension::kAbsSendTimeUri, std::vector<int> loss_rates = {0, 0, 0, 0};
true, true); RampUpDownUpTester test(3, 0, 0, kStartBitrateBps,
RtpExtension::kAbsSendTimeUri, true, true,
loss_rates);
RunBaseTest(&test); RunBaseTest(&test);
} }
TEST_F(RampUpTest, UpDownUpTransportSequenceNumberRtx) { TEST_F(RampUpTest, UpDownUpTransportSequenceNumberRtx) {
RampUpDownUpTester test(3, 0, kStartBitrateBps, std::vector<int> loss_rates = {0, 0, 0, 0};
RampUpDownUpTester test(3, 0, 0, kStartBitrateBps,
RtpExtension::kTransportSequenceNumberUri, true, RtpExtension::kTransportSequenceNumberUri, true,
false); false, loss_rates);
RunBaseTest(&test);
}
TEST_F(RampUpTest, UpDownUpTransportSequenceNumberPacketLoss) {
std::vector<int> loss_rates = {20, 0, 0, 0};
RampUpDownUpTester test(1, 0, 1, kStartBitrateBps,
RtpExtension::kTransportSequenceNumberUri, true,
false, loss_rates);
RunBaseTest(&test); RunBaseTest(&test);
} }
TEST_F(RampUpTest, UpDownUpAudioVideoTransportSequenceNumberRtx) { TEST_F(RampUpTest, UpDownUpAudioVideoTransportSequenceNumberRtx) {
RampUpDownUpTester test(3, 1, kStartBitrateBps, std::vector<int> loss_rates = {0, 0, 0, 0};
RampUpDownUpTester test(3, 1, 0, kStartBitrateBps,
RtpExtension::kTransportSequenceNumberUri, true, RtpExtension::kTransportSequenceNumberUri, true,
false); false, loss_rates);
RunBaseTest(&test); RunBaseTest(&test);
} }
TEST_F(RampUpTest, UpDownUpAudioTransportSequenceNumberRtx) { TEST_F(RampUpTest, UpDownUpAudioTransportSequenceNumberRtx) {
RampUpDownUpTester test(0, 1, kStartBitrateBps, std::vector<int> loss_rates = {0, 0, 0, 0};
RampUpDownUpTester test(0, 1, 0, kStartBitrateBps,
RtpExtension::kTransportSequenceNumberUri, true, RtpExtension::kTransportSequenceNumberUri, true,
false); false, loss_rates);
RunBaseTest(&test); RunBaseTest(&test);
} }
TEST_F(RampUpTest, TOffsetSimulcastRedRtx) { TEST_F(RampUpTest, TOffsetSimulcastRedRtx) {
RampUpTester test(3, 0, 0, 0, RtpExtension::kTimestampOffsetUri, true, true, RampUpTester test(3, 0, 0, 0, 0, RtpExtension::kTimestampOffsetUri, true,
true); true, true);
RunBaseTest(&test); RunBaseTest(&test);
} }
TEST_F(RampUpTest, AbsSendTime) { TEST_F(RampUpTest, AbsSendTime) {
RampUpTester test(1, 0, 0, 0, RtpExtension::kAbsSendTimeUri, false, false, RampUpTester test(1, 0, 0, 0, 0, RtpExtension::kAbsSendTimeUri, false, false,
true); true);
RunBaseTest(&test); RunBaseTest(&test);
} }
TEST_F(RampUpTest, AbsSendTimeSimulcastRedRtx) { TEST_F(RampUpTest, AbsSendTimeSimulcastRedRtx) {
RampUpTester test(3, 0, 0, 0, RtpExtension::kAbsSendTimeUri, true, true, RampUpTester test(3, 0, 0, 0, 0, RtpExtension::kAbsSendTimeUri, true, true,
true); true);
RunBaseTest(&test); RunBaseTest(&test);
} }
TEST_F(RampUpTest, TransportSequenceNumber) { TEST_F(RampUpTest, TransportSequenceNumber) {
RampUpTester test(1, 0, 0, 0, RtpExtension::kTransportSequenceNumberUri, RampUpTester test(1, 0, 0, 0, 0, RtpExtension::kTransportSequenceNumberUri,
false, false, true); false, false, true);
RunBaseTest(&test); RunBaseTest(&test);
} }
TEST_F(RampUpTest, TransportSequenceNumberSimulcast) { TEST_F(RampUpTest, TransportSequenceNumberSimulcast) {
RampUpTester test(3, 0, 0, 0, RtpExtension::kTransportSequenceNumberUri, RampUpTester test(3, 0, 0, 0, 0, RtpExtension::kTransportSequenceNumberUri,
false, false, true); false, false, true);
RunBaseTest(&test); RunBaseTest(&test);
} }
TEST_F(RampUpTest, TransportSequenceNumberSimulcastRedRtx) { TEST_F(RampUpTest, TransportSequenceNumberSimulcastRedRtx) {
RampUpTester test(3, 0, 0, 0, RtpExtension::kTransportSequenceNumberUri, RampUpTester test(3, 0, 0, 0, 0, RtpExtension::kTransportSequenceNumberUri,
true, true, true); true, true, true);
RunBaseTest(&test); RunBaseTest(&test);
} }
TEST_F(RampUpTest, AudioTransportSequenceNumber) { TEST_F(RampUpTest, AudioTransportSequenceNumber) {
RampUpTester test(0, 1, 300000, 10000, RampUpTester test(0, 1, 0, 300000, 10000,
RtpExtension::kTransportSequenceNumberUri, false, false, RtpExtension::kTransportSequenceNumberUri, false, false,
false); false);
RunBaseTest(&test); RunBaseTest(&test);

View File

@ -33,6 +33,7 @@ class RampUpTester : public test::EndToEndTest {
public: public:
RampUpTester(size_t num_video_streams, RampUpTester(size_t num_video_streams,
size_t num_audio_streams, size_t num_audio_streams,
size_t num_flexfec_streams,
unsigned int start_bitrate_bps, unsigned int start_bitrate_bps,
int64_t min_run_time_ms, int64_t min_run_time_ms,
const std::string& extension_type, const std::string& extension_type,
@ -43,6 +44,7 @@ class RampUpTester : public test::EndToEndTest {
size_t GetNumVideoStreams() const override; size_t GetNumVideoStreams() const override;
size_t GetNumAudioStreams() const override; size_t GetNumAudioStreams() const override;
size_t GetNumFlexfecStreams() const override;
void PerformTest() override; void PerformTest() override;
@ -66,6 +68,7 @@ class RampUpTester : public test::EndToEndTest {
FakeNetworkPipe::Config forward_transport_config_; FakeNetworkPipe::Config forward_transport_config_;
const size_t num_video_streams_; const size_t num_video_streams_;
const size_t num_audio_streams_; const size_t num_audio_streams_;
const size_t num_flexfec_streams_;
const bool rtx_; const bool rtx_;
const bool red_; const bool red_;
Call* sender_call_; Call* sender_call_;
@ -88,6 +91,8 @@ class RampUpTester : public test::EndToEndTest {
void ModifyAudioConfigs( void ModifyAudioConfigs(
AudioSendStream::Config* send_config, AudioSendStream::Config* send_config,
std::vector<AudioReceiveStream::Config>* receive_configs) override; std::vector<AudioReceiveStream::Config>* receive_configs) override;
void ModifyFlexfecConfigs(
std::vector<FlexfecReceiveStream::Config>* receive_configs) override;
void OnCallsCreated(Call* sender_call, Call* receiver_call) override; void OnCallsCreated(Call* sender_call, Call* receiver_call) override;
static bool BitrateStatsPollingThread(void* obj); static bool BitrateStatsPollingThread(void* obj);
@ -111,29 +116,42 @@ class RampUpDownUpTester : public RampUpTester {
public: public:
RampUpDownUpTester(size_t num_video_streams, RampUpDownUpTester(size_t num_video_streams,
size_t num_audio_streams, size_t num_audio_streams,
size_t num_flexfec_streams,
unsigned int start_bitrate_bps, unsigned int start_bitrate_bps,
const std::string& extension_type, const std::string& extension_type,
bool rtx, bool rtx,
bool red); bool red,
const std::vector<int>& loss_rates);
~RampUpDownUpTester() override; ~RampUpDownUpTester() override;
protected: protected:
bool PollStats() override; bool PollStats() override;
private: private:
enum TestStates { kFirstRampup, kLowRate, kSecondRampup }; enum TestStates {
kFirstRampup = 0,
kLowRate,
kSecondRampup,
kTestEnd,
kTransitionToNextState,
};
Call::Config GetReceiverCallConfig() override; Call::Config GetReceiverCallConfig() override;
std::string GetModifierString() const; std::string GetModifierString() const;
int GetExpectedHighBitrate() const; int GetExpectedHighBitrate() const;
int GetHighLinkCapacity() const; int GetHighLinkCapacity() const;
size_t GetFecBytes() const;
bool ExpectingFec() const;
void EvolveTestState(int bitrate_bps, bool suspended); void EvolveTestState(int bitrate_bps, bool suspended);
const std::vector<int> link_rates_;
TestStates test_state_; TestStates test_state_;
TestStates next_state_;
int64_t state_start_ms_; int64_t state_start_ms_;
int64_t interval_start_ms_; int64_t interval_start_ms_;
int sent_bytes_; int sent_bytes_;
std::vector<int> loss_rates_;
}; };
} // namespace webrtc } // namespace webrtc
#endif // WEBRTC_CALL_RAMPUP_TESTS_H_ #endif // WEBRTC_CALL_RAMPUP_TESTS_H_

View File

@ -215,7 +215,7 @@ void CallTest::CreateSendConfig(size_t num_video_streams,
audio_send_config_.voe_channel_id = voe_send_.channel_id; audio_send_config_.voe_channel_id = voe_send_.channel_id;
audio_send_config_.rtp.ssrc = kAudioSendSsrc; audio_send_config_.rtp.ssrc = kAudioSendSsrc;
audio_send_config_.send_codec_spec.codec_inst = audio_send_config_.send_codec_spec.codec_inst =
CodecInst{kAudioSendPayloadType, "ISAC", 16000, 480, 1, 32000}; CodecInst{kAudioSendPayloadType, "OPUS", 48000, 960, 2, 64000};
} }
// TODO(brandtr): Update this when we support multistream protection. // TODO(brandtr): Update this when we support multistream protection.

View File

@ -24,7 +24,7 @@ const size_t DefaultVideoStreamFactory::kMaxNumberOfStreams;
const int DefaultVideoStreamFactory::kMaxBitratePerStream[] = {150000, 450000, const int DefaultVideoStreamFactory::kMaxBitratePerStream[] = {150000, 450000,
1500000}; 1500000};
const int DefaultVideoStreamFactory::kDefaultMinBitratePerStream[] = { const int DefaultVideoStreamFactory::kDefaultMinBitratePerStream[] = {
50000, 200000, 700000}; 30000, 200000, 700000};
// static // static
std::vector<VideoStream> CreateVideoStreams( std::vector<VideoStream> CreateVideoStreams(

View File

@ -33,31 +33,14 @@ FakeNetworkPipe::FakeNetworkPipe(Clock* clock,
: clock_(clock), : clock_(clock),
packet_receiver_(NULL), packet_receiver_(NULL),
random_(seed), random_(seed),
config_(config), config_(),
dropped_packets_(0), dropped_packets_(0),
sent_packets_(0), sent_packets_(0),
total_packet_delay_(0), total_packet_delay_(0),
bursting_(false), bursting_(false),
next_process_time_(clock_->TimeInMilliseconds()), next_process_time_(clock_->TimeInMilliseconds()),
last_log_time_(clock_->TimeInMilliseconds()) { last_log_time_(clock_->TimeInMilliseconds()) {
double prob_loss = config.loss_percent / 100.0; SetConfig(config);
if (config_.avg_burst_loss_length == -1) {
// Uniform loss
prob_loss_bursting_ = prob_loss;
prob_start_bursting_ = prob_loss;
} else {
// Lose packets according to a gilbert-elliot model.
int avg_burst_loss_length = config.avg_burst_loss_length;
int min_avg_burst_loss_length = std::ceil(prob_loss / (1 - prob_loss));
RTC_CHECK_GT(avg_burst_loss_length, min_avg_burst_loss_length)
<< "For a total packet loss of " << config.loss_percent << "%% then"
<< " avg_burst_loss_length must be " << min_avg_burst_loss_length + 1
<< " or higher.";
prob_loss_bursting_ = (1.0 - 1.0 / avg_burst_loss_length);
prob_start_bursting_ = prob_loss / (1 - prob_loss) / avg_burst_loss_length;
}
} }
FakeNetworkPipe::~FakeNetworkPipe() { FakeNetworkPipe::~FakeNetworkPipe() {
@ -78,6 +61,24 @@ void FakeNetworkPipe::SetReceiver(PacketReceiver* receiver) {
void FakeNetworkPipe::SetConfig(const FakeNetworkPipe::Config& config) { void FakeNetworkPipe::SetConfig(const FakeNetworkPipe::Config& config) {
rtc::CritScope crit(&lock_); rtc::CritScope crit(&lock_);
config_ = config; // Shallow copy of the struct. config_ = config; // Shallow copy of the struct.
double prob_loss = config.loss_percent / 100.0;
if (config_.avg_burst_loss_length == -1) {
// Uniform loss
prob_loss_bursting_ = prob_loss;
prob_start_bursting_ = prob_loss;
} else {
// Lose packets according to a gilbert-elliot model.
int avg_burst_loss_length = config.avg_burst_loss_length;
int min_avg_burst_loss_length = std::ceil(prob_loss / (1 - prob_loss));
RTC_CHECK_GT(avg_burst_loss_length, min_avg_burst_loss_length)
<< "For a total packet loss of " << config.loss_percent << "%% then"
<< " avg_burst_loss_length must be " << min_avg_burst_loss_length + 1
<< " or higher.";
prob_loss_bursting_ = (1.0 - 1.0 / avg_burst_loss_length);
prob_start_bursting_ = prob_loss / (1 - prob_loss) / avg_burst_loss_length;
}
} }
void FakeNetworkPipe::SendPacket(const uint8_t* data, size_t data_length) { void FakeNetworkPipe::SendPacket(const uint8_t* data, size_t data_length) {