Reland Addd class InterArrivalDelta to goog_cc
This time the class is added but only used if the field trial "WebRTC-Bwe-NewInterArrivalDelta/Enabled/" is enabled. Original cl description: This cl copies modules/remote_bitrate_estimator/inter_arrival.x to inter_arrival.h and interrival_delta.cc in goog_cc but modified to use webrtc::Timestamp and webrtc::Timedelta in order to avoid having to use 24 bit time repressentation. patchset 1 is a pure revert of the revert https://webrtc-review.googlesource.com/c/src/+/196343 patchset 2 contains a modification to allow running it behind an experiment. Bug: webrtc:12269 Change-Id: Ide80e9f5243362799a2cc1f0fcf7e613e707d851 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/196502 Commit-Queue: Per Kjellander <perkj@webrtc.org> Reviewed-by: Christoffer Rodbro <crodbro@webrtc.org> Cr-Commit-Position: refs/heads/master@{#32784}
This commit is contained in:

committed by
Commit Bot

parent
c20baf6067
commit
ea969d287b
@ -180,6 +180,8 @@ rtc_library("delay_based_bwe") {
|
||||
sources = [
|
||||
"delay_based_bwe.cc",
|
||||
"delay_based_bwe.h",
|
||||
"inter_arrival_delta.cc",
|
||||
"inter_arrival_delta.h",
|
||||
]
|
||||
|
||||
deps = [
|
||||
@ -187,8 +189,9 @@ rtc_library("delay_based_bwe") {
|
||||
"../../../api:network_state_predictor_api",
|
||||
"../../../api/rtc_event_log",
|
||||
"../../../api/transport:network_control",
|
||||
"../../../api/transport:network_control",
|
||||
"../../../api/transport:webrtc_key_value_config",
|
||||
"../../../api/units:time_delta",
|
||||
"../../../api/units:timestamp",
|
||||
"../../../logging:rtc_event_bwe",
|
||||
"../../../rtc_base:checks",
|
||||
"../../../rtc_base:rtc_base_approved",
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "absl/strings/match.h"
|
||||
#include "api/rtc_event_log/rtc_event.h"
|
||||
#include "api/rtc_event_log/rtc_event_log.h"
|
||||
#include "api/units/time_delta.h"
|
||||
#include "logging/rtc_event_log/events/rtc_event_bwe_update_delay_based.h"
|
||||
#include "modules/congestion_controller/goog_cc/trendline_estimator.h"
|
||||
#include "modules/remote_bitrate_estimator/include/bwe_defines.h"
|
||||
@ -31,6 +32,11 @@
|
||||
namespace webrtc {
|
||||
namespace {
|
||||
constexpr TimeDelta kStreamTimeOut = TimeDelta::Seconds(2);
|
||||
|
||||
// Used with field trial "WebRTC-Bwe-NewInterArrivalDelta/Enabled/
|
||||
constexpr TimeDelta kSendTimeGroupLength = TimeDelta::Millis(5);
|
||||
|
||||
// Used unless field trial "WebRTC-Bwe-NewInterArrivalDelta/Enabled/"
|
||||
constexpr int kTimestampGroupLengthMs = 5;
|
||||
constexpr int kAbsSendTimeFraction = 18;
|
||||
constexpr int kAbsSendTimeInterArrivalUpshift = 8;
|
||||
@ -69,7 +75,6 @@ DelayBasedBwe::Result::Result()
|
||||
recovered_from_overuse(false),
|
||||
backoff_in_alr(false) {}
|
||||
|
||||
|
||||
DelayBasedBwe::DelayBasedBwe(const WebRtcKeyValueConfig* key_value_config,
|
||||
RtcEventLog* event_log,
|
||||
NetworkStatePredictor* network_state_predictor)
|
||||
@ -79,10 +84,8 @@ DelayBasedBwe::DelayBasedBwe(const WebRtcKeyValueConfig* key_value_config,
|
||||
audio_packets_since_last_video_(0),
|
||||
last_video_packet_recv_time_(Timestamp::MinusInfinity()),
|
||||
network_state_predictor_(network_state_predictor),
|
||||
video_inter_arrival_(),
|
||||
video_delay_detector_(
|
||||
new TrendlineEstimator(key_value_config_, network_state_predictor_)),
|
||||
audio_inter_arrival_(),
|
||||
audio_delay_detector_(
|
||||
new TrendlineEstimator(key_value_config_, network_state_predictor_)),
|
||||
active_delay_detector_(video_delay_detector_.get()),
|
||||
@ -92,6 +95,9 @@ DelayBasedBwe::DelayBasedBwe(const WebRtcKeyValueConfig* key_value_config,
|
||||
prev_bitrate_(DataRate::Zero()),
|
||||
has_once_detected_overuse_(false),
|
||||
prev_state_(BandwidthUsage::kBwNormal),
|
||||
use_new_inter_arrival_delta_(absl::StartsWith(
|
||||
key_value_config->Lookup("WebRTC-Bwe-NewInterArrivalDelta"),
|
||||
"Enabled")),
|
||||
alr_limited_backoff_enabled_(absl::StartsWith(
|
||||
key_value_config->Lookup("WebRTC-Bwe-AlrLimitedBackoff"),
|
||||
"Enabled")) {
|
||||
@ -156,12 +162,19 @@ void DelayBasedBwe::IncomingPacketFeedback(const PacketResult& packet_feedback,
|
||||
// Reset if the stream has timed out.
|
||||
if (last_seen_packet_.IsInfinite() ||
|
||||
at_time - last_seen_packet_ > kStreamTimeOut) {
|
||||
video_inter_arrival_.reset(
|
||||
new InterArrival(kTimestampGroupTicks, kTimestampToMs, true));
|
||||
if (use_new_inter_arrival_delta_) {
|
||||
video_inter_arrival_delta_ =
|
||||
std::make_unique<InterArrivalDelta>(kSendTimeGroupLength);
|
||||
audio_inter_arrival_delta_ =
|
||||
std::make_unique<InterArrivalDelta>(kSendTimeGroupLength);
|
||||
} else {
|
||||
video_inter_arrival_ = std::make_unique<InterArrival>(
|
||||
kTimestampGroupTicks, kTimestampToMs, true);
|
||||
audio_inter_arrival_ = std::make_unique<InterArrival>(
|
||||
kTimestampGroupTicks, kTimestampToMs, true);
|
||||
}
|
||||
video_delay_detector_.reset(
|
||||
new TrendlineEstimator(key_value_config_, network_state_predictor_));
|
||||
audio_inter_arrival_.reset(
|
||||
new InterArrival(kTimestampGroupTicks, kTimestampToMs, true));
|
||||
audio_delay_detector_.reset(
|
||||
new TrendlineEstimator(key_value_config_, network_state_predictor_));
|
||||
active_delay_detector_ = video_delay_detector_.get();
|
||||
@ -170,12 +183,10 @@ void DelayBasedBwe::IncomingPacketFeedback(const PacketResult& packet_feedback,
|
||||
|
||||
// As an alternative to ignoring small packets, we can separate audio and
|
||||
// video packets for overuse detection.
|
||||
InterArrival* inter_arrival_for_packet = video_inter_arrival_.get();
|
||||
DelayIncreaseDetectorInterface* delay_detector_for_packet =
|
||||
video_delay_detector_.get();
|
||||
if (separate_audio_.enabled) {
|
||||
if (packet_feedback.sent_packet.audio) {
|
||||
inter_arrival_for_packet = audio_inter_arrival_.get();
|
||||
delay_detector_for_packet = audio_delay_detector_.get();
|
||||
audio_packets_since_last_video_++;
|
||||
if (audio_packets_since_last_video_ > separate_audio_.packet_threshold &&
|
||||
@ -190,30 +201,59 @@ void DelayBasedBwe::IncomingPacketFeedback(const PacketResult& packet_feedback,
|
||||
active_delay_detector_ = video_delay_detector_.get();
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t send_time_24bits =
|
||||
static_cast<uint32_t>(
|
||||
((static_cast<uint64_t>(packet_feedback.sent_packet.send_time.ms())
|
||||
<< kAbsSendTimeFraction) +
|
||||
500) /
|
||||
1000) &
|
||||
0x00FFFFFF;
|
||||
// Shift up send time to use the full 32 bits that inter_arrival works with,
|
||||
// so wrapping works properly.
|
||||
uint32_t timestamp = send_time_24bits << kAbsSendTimeInterArrivalUpshift;
|
||||
|
||||
uint32_t timestamp_delta = 0;
|
||||
int64_t recv_delta_ms = 0;
|
||||
int size_delta = 0;
|
||||
DataSize packet_size = packet_feedback.sent_packet.size;
|
||||
bool calculated_deltas = inter_arrival_for_packet->ComputeDeltas(
|
||||
timestamp, packet_feedback.receive_time.ms(), at_time.ms(),
|
||||
packet_size.bytes(), ×tamp_delta, &recv_delta_ms, &size_delta);
|
||||
double send_delta_ms = (1000.0 * timestamp_delta) / (1 << kInterArrivalShift);
|
||||
delay_detector_for_packet->Update(recv_delta_ms, send_delta_ms,
|
||||
packet_feedback.sent_packet.send_time.ms(),
|
||||
packet_feedback.receive_time.ms(),
|
||||
packet_size.bytes(), calculated_deltas);
|
||||
|
||||
if (use_new_inter_arrival_delta_) {
|
||||
TimeDelta send_delta = TimeDelta::Zero();
|
||||
TimeDelta recv_delta = TimeDelta::Zero();
|
||||
int size_delta = 0;
|
||||
|
||||
InterArrivalDelta* inter_arrival_for_packet =
|
||||
(separate_audio_.enabled && packet_feedback.sent_packet.audio)
|
||||
? video_inter_arrival_delta_.get()
|
||||
: audio_inter_arrival_delta_.get();
|
||||
bool calculated_deltas = inter_arrival_for_packet->ComputeDeltas(
|
||||
packet_feedback.sent_packet.send_time, packet_feedback.receive_time,
|
||||
at_time, packet_size.bytes(), &send_delta, &recv_delta, &size_delta);
|
||||
|
||||
delay_detector_for_packet->Update(
|
||||
recv_delta.ms(), send_delta.ms(),
|
||||
packet_feedback.sent_packet.send_time.ms(),
|
||||
packet_feedback.receive_time.ms(), packet_size.bytes(),
|
||||
calculated_deltas);
|
||||
} else {
|
||||
InterArrival* inter_arrival_for_packet =
|
||||
(separate_audio_.enabled && packet_feedback.sent_packet.audio)
|
||||
? video_inter_arrival_.get()
|
||||
: audio_inter_arrival_.get();
|
||||
|
||||
uint32_t send_time_24bits =
|
||||
static_cast<uint32_t>(
|
||||
((static_cast<uint64_t>(packet_feedback.sent_packet.send_time.ms())
|
||||
<< kAbsSendTimeFraction) +
|
||||
500) /
|
||||
1000) &
|
||||
0x00FFFFFF;
|
||||
// Shift up send time to use the full 32 bits that inter_arrival works with,
|
||||
// so wrapping works properly.
|
||||
uint32_t timestamp = send_time_24bits << kAbsSendTimeInterArrivalUpshift;
|
||||
|
||||
uint32_t timestamp_delta = 0;
|
||||
int64_t recv_delta_ms = 0;
|
||||
int size_delta = 0;
|
||||
|
||||
bool calculated_deltas = inter_arrival_for_packet->ComputeDeltas(
|
||||
timestamp, packet_feedback.receive_time.ms(), at_time.ms(),
|
||||
packet_size.bytes(), ×tamp_delta, &recv_delta_ms, &size_delta);
|
||||
double send_delta_ms =
|
||||
(1000.0 * timestamp_delta) / (1 << kInterArrivalShift);
|
||||
|
||||
delay_detector_for_packet->Update(
|
||||
recv_delta_ms, send_delta_ms,
|
||||
packet_feedback.sent_packet.send_time.ms(),
|
||||
packet_feedback.receive_time.ms(), packet_size.bytes(),
|
||||
calculated_deltas);
|
||||
}
|
||||
}
|
||||
|
||||
DataRate DelayBasedBwe::TriggerOveruse(Timestamp at_time,
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "api/transport/network_types.h"
|
||||
#include "api/transport/webrtc_key_value_config.h"
|
||||
#include "modules/congestion_controller/goog_cc/delay_increase_detector_interface.h"
|
||||
#include "modules/congestion_controller/goog_cc/inter_arrival_delta.h"
|
||||
#include "modules/congestion_controller/goog_cc/probe_bitrate_estimator.h"
|
||||
#include "modules/remote_bitrate_estimator/aimd_rate_control.h"
|
||||
#include "modules/remote_bitrate_estimator/inter_arrival.h"
|
||||
@ -113,8 +114,10 @@ class DelayBasedBwe {
|
||||
|
||||
NetworkStatePredictor* network_state_predictor_;
|
||||
std::unique_ptr<InterArrival> video_inter_arrival_;
|
||||
std::unique_ptr<InterArrivalDelta> video_inter_arrival_delta_;
|
||||
std::unique_ptr<DelayIncreaseDetectorInterface> video_delay_detector_;
|
||||
std::unique_ptr<InterArrival> audio_inter_arrival_;
|
||||
std::unique_ptr<InterArrivalDelta> audio_inter_arrival_delta_;
|
||||
std::unique_ptr<DelayIncreaseDetectorInterface> audio_delay_detector_;
|
||||
DelayIncreaseDetectorInterface* active_delay_detector_;
|
||||
|
||||
@ -124,6 +127,7 @@ class DelayBasedBwe {
|
||||
DataRate prev_bitrate_;
|
||||
bool has_once_detected_overuse_;
|
||||
BandwidthUsage prev_state_;
|
||||
const bool use_new_inter_arrival_delta_;
|
||||
bool alr_limited_backoff_enabled_;
|
||||
};
|
||||
|
||||
|
@ -10,6 +10,8 @@
|
||||
|
||||
#include "modules/congestion_controller/goog_cc/delay_based_bwe.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "api/transport/network_types.h"
|
||||
#include "modules/congestion_controller/goog_cc/acknowledged_bitrate_estimator.h"
|
||||
#include "modules/congestion_controller/goog_cc/delay_based_bwe_unittest_helper.h"
|
||||
@ -26,7 +28,15 @@ const PacedPacketInfo kPacingInfo1(1, kNumProbesCluster1, 4000);
|
||||
constexpr float kTargetUtilizationFraction = 0.95f;
|
||||
} // namespace
|
||||
|
||||
TEST_F(DelayBasedBweTest, ProbeDetection) {
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
,
|
||||
DelayBasedBweTest,
|
||||
::testing::Values("", "WebRTC-Bwe-NewInterArrivalDelta/Enabled/"),
|
||||
[](::testing::TestParamInfo<std::string> info) {
|
||||
return info.param == "" ? "Default" : "NewInterArrival";
|
||||
});
|
||||
|
||||
TEST_P(DelayBasedBweTest, ProbeDetection) {
|
||||
int64_t now_ms = clock_.TimeInMilliseconds();
|
||||
|
||||
// First burst sent at 8 * 1000 / 10 = 800 kbps.
|
||||
@ -48,7 +58,7 @@ TEST_F(DelayBasedBweTest, ProbeDetection) {
|
||||
EXPECT_GT(bitrate_observer_.latest_bitrate(), 1500000u);
|
||||
}
|
||||
|
||||
TEST_F(DelayBasedBweTest, ProbeDetectionNonPacedPackets) {
|
||||
TEST_P(DelayBasedBweTest, ProbeDetectionNonPacedPackets) {
|
||||
int64_t now_ms = clock_.TimeInMilliseconds();
|
||||
// First burst sent at 8 * 1000 / 10 = 800 kbps, but with every other packet
|
||||
// not being paced which could mess things up.
|
||||
@ -65,7 +75,7 @@ TEST_F(DelayBasedBweTest, ProbeDetectionNonPacedPackets) {
|
||||
EXPECT_GT(bitrate_observer_.latest_bitrate(), 800000u);
|
||||
}
|
||||
|
||||
TEST_F(DelayBasedBweTest, ProbeDetectionFasterArrival) {
|
||||
TEST_P(DelayBasedBweTest, ProbeDetectionFasterArrival) {
|
||||
int64_t now_ms = clock_.TimeInMilliseconds();
|
||||
// First burst sent at 8 * 1000 / 10 = 800 kbps.
|
||||
// Arriving at 8 * 1000 / 5 = 1600 kbps.
|
||||
@ -80,7 +90,7 @@ TEST_F(DelayBasedBweTest, ProbeDetectionFasterArrival) {
|
||||
EXPECT_FALSE(bitrate_observer_.updated());
|
||||
}
|
||||
|
||||
TEST_F(DelayBasedBweTest, ProbeDetectionSlowerArrival) {
|
||||
TEST_P(DelayBasedBweTest, ProbeDetectionSlowerArrival) {
|
||||
int64_t now_ms = clock_.TimeInMilliseconds();
|
||||
// First burst sent at 8 * 1000 / 5 = 1600 kbps.
|
||||
// Arriving at 8 * 1000 / 7 = 1142 kbps.
|
||||
@ -99,7 +109,7 @@ TEST_F(DelayBasedBweTest, ProbeDetectionSlowerArrival) {
|
||||
kTargetUtilizationFraction * 1140000u, 10000u);
|
||||
}
|
||||
|
||||
TEST_F(DelayBasedBweTest, ProbeDetectionSlowerArrivalHighBitrate) {
|
||||
TEST_P(DelayBasedBweTest, ProbeDetectionSlowerArrivalHighBitrate) {
|
||||
int64_t now_ms = clock_.TimeInMilliseconds();
|
||||
// Burst sent at 8 * 1000 / 1 = 8000 kbps.
|
||||
// Arriving at 8 * 1000 / 2 = 4000 kbps.
|
||||
@ -118,7 +128,7 @@ TEST_F(DelayBasedBweTest, ProbeDetectionSlowerArrivalHighBitrate) {
|
||||
kTargetUtilizationFraction * 4000000u, 10000u);
|
||||
}
|
||||
|
||||
TEST_F(DelayBasedBweTest, GetExpectedBwePeriodMs) {
|
||||
TEST_P(DelayBasedBweTest, GetExpectedBwePeriodMs) {
|
||||
auto default_interval = bitrate_estimator_->GetExpectedBwePeriod();
|
||||
EXPECT_GT(default_interval.ms(), 0);
|
||||
CapacityDropTestHelper(1, true, 333, 0);
|
||||
@ -127,45 +137,45 @@ TEST_F(DelayBasedBweTest, GetExpectedBwePeriodMs) {
|
||||
EXPECT_NE(interval.ms(), default_interval.ms());
|
||||
}
|
||||
|
||||
TEST_F(DelayBasedBweTest, InitialBehavior) {
|
||||
TEST_P(DelayBasedBweTest, InitialBehavior) {
|
||||
InitialBehaviorTestHelper(730000);
|
||||
}
|
||||
|
||||
TEST_F(DelayBasedBweTest, RateIncreaseReordering) {
|
||||
TEST_P(DelayBasedBweTest, RateIncreaseReordering) {
|
||||
RateIncreaseReorderingTestHelper(730000);
|
||||
}
|
||||
TEST_F(DelayBasedBweTest, RateIncreaseRtpTimestamps) {
|
||||
TEST_P(DelayBasedBweTest, RateIncreaseRtpTimestamps) {
|
||||
RateIncreaseRtpTimestampsTestHelper(622);
|
||||
}
|
||||
|
||||
TEST_F(DelayBasedBweTest, CapacityDropOneStream) {
|
||||
TEST_P(DelayBasedBweTest, CapacityDropOneStream) {
|
||||
CapacityDropTestHelper(1, false, 300, 0);
|
||||
}
|
||||
|
||||
TEST_F(DelayBasedBweTest, CapacityDropPosOffsetChange) {
|
||||
TEST_P(DelayBasedBweTest, CapacityDropPosOffsetChange) {
|
||||
CapacityDropTestHelper(1, false, 867, 30000);
|
||||
}
|
||||
|
||||
TEST_F(DelayBasedBweTest, CapacityDropNegOffsetChange) {
|
||||
TEST_P(DelayBasedBweTest, CapacityDropNegOffsetChange) {
|
||||
CapacityDropTestHelper(1, false, 933, -30000);
|
||||
}
|
||||
|
||||
TEST_F(DelayBasedBweTest, CapacityDropOneStreamWrap) {
|
||||
TEST_P(DelayBasedBweTest, CapacityDropOneStreamWrap) {
|
||||
CapacityDropTestHelper(1, true, 333, 0);
|
||||
}
|
||||
|
||||
TEST_F(DelayBasedBweTest, TestTimestampGrouping) {
|
||||
TEST_P(DelayBasedBweTest, TestTimestampGrouping) {
|
||||
TestTimestampGroupingTestHelper();
|
||||
}
|
||||
|
||||
TEST_F(DelayBasedBweTest, TestShortTimeoutAndWrap) {
|
||||
TEST_P(DelayBasedBweTest, TestShortTimeoutAndWrap) {
|
||||
// Simulate a client leaving and rejoining the call after 35 seconds. This
|
||||
// will make abs send time wrap, so if streams aren't timed out properly
|
||||
// the next 30 seconds of packets will be out of order.
|
||||
TestWrappingHelper(35);
|
||||
}
|
||||
|
||||
TEST_F(DelayBasedBweTest, TestLongTimeoutAndWrap) {
|
||||
TEST_P(DelayBasedBweTest, TestLongTimeoutAndWrap) {
|
||||
// Simulate a client leaving and rejoining the call after some multiple of
|
||||
// 64 seconds later. This will cause a zero difference in abs send times due
|
||||
// to the wrap, but a big difference in arrival time, if streams aren't
|
||||
@ -173,7 +183,7 @@ TEST_F(DelayBasedBweTest, TestLongTimeoutAndWrap) {
|
||||
TestWrappingHelper(10 * 64);
|
||||
}
|
||||
|
||||
TEST_F(DelayBasedBweTest, TestInitialOveruse) {
|
||||
TEST_P(DelayBasedBweTest, TestInitialOveruse) {
|
||||
const DataRate kStartBitrate = DataRate::KilobitsPerSec(300);
|
||||
const DataRate kInitialCapacity = DataRate::KilobitsPerSec(200);
|
||||
const uint32_t kDummySsrc = 0;
|
||||
@ -213,15 +223,16 @@ TEST_F(DelayBasedBweTest, TestInitialOveruse) {
|
||||
}
|
||||
|
||||
class DelayBasedBweTestWithBackoffTimeoutExperiment : public DelayBasedBweTest {
|
||||
public:
|
||||
DelayBasedBweTestWithBackoffTimeoutExperiment()
|
||||
: DelayBasedBweTest(
|
||||
"WebRTC-BweAimdRateControlConfig/initial_backoff_interval:200ms/") {
|
||||
}
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
,
|
||||
DelayBasedBweTestWithBackoffTimeoutExperiment,
|
||||
::testing::Values(
|
||||
"WebRTC-BweAimdRateControlConfig/initial_backoff_interval:200ms/"));
|
||||
|
||||
// This test subsumes and improves DelayBasedBweTest.TestInitialOveruse above.
|
||||
TEST_F(DelayBasedBweTestWithBackoffTimeoutExperiment, TestInitialOveruse) {
|
||||
TEST_P(DelayBasedBweTestWithBackoffTimeoutExperiment, TestInitialOveruse) {
|
||||
const DataRate kStartBitrate = DataRate::KilobitsPerSec(300);
|
||||
const DataRate kInitialCapacity = DataRate::KilobitsPerSec(200);
|
||||
const uint32_t kDummySsrc = 0;
|
||||
|
@ -146,21 +146,7 @@ int64_t StreamGenerator::GenerateFrame(std::vector<PacketResult>* packets,
|
||||
} // namespace test
|
||||
|
||||
DelayBasedBweTest::DelayBasedBweTest()
|
||||
: field_trial(),
|
||||
clock_(100000000),
|
||||
acknowledged_bitrate_estimator_(
|
||||
AcknowledgedBitrateEstimatorInterface::Create(&field_trial_config_)),
|
||||
probe_bitrate_estimator_(new ProbeBitrateEstimator(nullptr)),
|
||||
bitrate_estimator_(
|
||||
new DelayBasedBwe(&field_trial_config_, nullptr, nullptr)),
|
||||
stream_generator_(new test::StreamGenerator(1e6, // Capacity.
|
||||
clock_.TimeInMicroseconds())),
|
||||
arrival_time_offset_ms_(0),
|
||||
first_update_(true) {}
|
||||
|
||||
DelayBasedBweTest::DelayBasedBweTest(const std::string& field_trial_string)
|
||||
: field_trial(
|
||||
std::make_unique<test::ScopedFieldTrials>(field_trial_string)),
|
||||
: field_trial(std::make_unique<test::ScopedFieldTrials>(GetParam())),
|
||||
clock_(100000000),
|
||||
acknowledged_bitrate_estimator_(
|
||||
AcknowledgedBitrateEstimatorInterface::Create(&field_trial_config_)),
|
||||
|
@ -113,10 +113,9 @@ class StreamGenerator {
|
||||
};
|
||||
} // namespace test
|
||||
|
||||
class DelayBasedBweTest : public ::testing::Test {
|
||||
class DelayBasedBweTest : public ::testing::TestWithParam<std::string> {
|
||||
public:
|
||||
DelayBasedBweTest();
|
||||
explicit DelayBasedBweTest(const std::string& field_trial_string);
|
||||
~DelayBasedBweTest() override;
|
||||
|
||||
protected:
|
||||
@ -176,9 +175,8 @@ class DelayBasedBweTest : public ::testing::Test {
|
||||
std::unique_ptr<test::StreamGenerator> stream_generator_;
|
||||
int64_t arrival_time_offset_ms_;
|
||||
bool first_update_;
|
||||
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(DelayBasedBweTest);
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // MODULES_CONGESTION_CONTROLLER_GOOG_CC_DELAY_BASED_BWE_UNITTEST_HELPER_H_
|
||||
|
140
modules/congestion_controller/goog_cc/inter_arrival_delta.cc
Normal file
140
modules/congestion_controller/goog_cc/inter_arrival_delta.cc
Normal file
@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "modules/congestion_controller/goog_cc/inter_arrival_delta.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "api/units/time_delta.h"
|
||||
#include "api/units/timestamp.h"
|
||||
#include "rtc_base/logging.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
static constexpr TimeDelta kBurstDeltaThreshold = TimeDelta::Millis(5);
|
||||
static constexpr TimeDelta kMaxBurstDuration = TimeDelta::Millis(100);
|
||||
constexpr TimeDelta InterArrivalDelta::kArrivalTimeOffsetThreshold;
|
||||
|
||||
InterArrivalDelta::InterArrivalDelta(TimeDelta send_time_group_length)
|
||||
: send_time_group_length_(send_time_group_length),
|
||||
current_timestamp_group_(),
|
||||
prev_timestamp_group_(),
|
||||
num_consecutive_reordered_packets_(0) {}
|
||||
|
||||
bool InterArrivalDelta::ComputeDeltas(Timestamp send_time,
|
||||
Timestamp arrival_time,
|
||||
Timestamp system_time,
|
||||
size_t packet_size,
|
||||
TimeDelta* send_time_delta,
|
||||
TimeDelta* arrival_time_delta,
|
||||
int* packet_size_delta) {
|
||||
bool calculated_deltas = false;
|
||||
if (current_timestamp_group_.IsFirstPacket()) {
|
||||
// We don't have enough data to update the filter, so we store it until we
|
||||
// have two frames of data to process.
|
||||
current_timestamp_group_.send_time = send_time;
|
||||
current_timestamp_group_.first_send_time = send_time;
|
||||
current_timestamp_group_.first_arrival = arrival_time;
|
||||
} else if (current_timestamp_group_.first_send_time > send_time) {
|
||||
// Reordered packet.
|
||||
return false;
|
||||
} else if (NewTimestampGroup(arrival_time, send_time)) {
|
||||
// First packet of a later send burst, the previous packets sample is ready.
|
||||
if (prev_timestamp_group_.complete_time.IsFinite()) {
|
||||
*send_time_delta =
|
||||
current_timestamp_group_.send_time - prev_timestamp_group_.send_time;
|
||||
*arrival_time_delta = current_timestamp_group_.complete_time -
|
||||
prev_timestamp_group_.complete_time;
|
||||
|
||||
TimeDelta system_time_delta = current_timestamp_group_.last_system_time -
|
||||
prev_timestamp_group_.last_system_time;
|
||||
|
||||
if (*arrival_time_delta - system_time_delta >=
|
||||
kArrivalTimeOffsetThreshold) {
|
||||
RTC_LOG(LS_WARNING)
|
||||
<< "The arrival time clock offset has changed (diff = "
|
||||
<< arrival_time_delta->ms() - system_time_delta.ms()
|
||||
<< " ms), resetting.";
|
||||
Reset();
|
||||
return false;
|
||||
}
|
||||
if (*arrival_time_delta < TimeDelta::Zero()) {
|
||||
// The group of packets has been reordered since receiving its local
|
||||
// arrival timestamp.
|
||||
++num_consecutive_reordered_packets_;
|
||||
if (num_consecutive_reordered_packets_ >= kReorderedResetThreshold) {
|
||||
RTC_LOG(LS_WARNING)
|
||||
<< "Packets between send burst arrived out of order, resetting."
|
||||
<< " arrival_time_delta" << arrival_time_delta->ms()
|
||||
<< " send time delta " << send_time_delta->ms();
|
||||
Reset();
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
num_consecutive_reordered_packets_ = 0;
|
||||
}
|
||||
*packet_size_delta = static_cast<int>(current_timestamp_group_.size) -
|
||||
static_cast<int>(prev_timestamp_group_.size);
|
||||
calculated_deltas = true;
|
||||
}
|
||||
prev_timestamp_group_ = current_timestamp_group_;
|
||||
// The new timestamp is now the current frame.
|
||||
current_timestamp_group_.first_send_time = send_time;
|
||||
current_timestamp_group_.send_time = send_time;
|
||||
current_timestamp_group_.first_arrival = arrival_time;
|
||||
current_timestamp_group_.size = 0;
|
||||
} else {
|
||||
current_timestamp_group_.send_time =
|
||||
std::max(current_timestamp_group_.send_time, send_time);
|
||||
}
|
||||
// Accumulate the frame size.
|
||||
current_timestamp_group_.size += packet_size;
|
||||
current_timestamp_group_.complete_time = arrival_time;
|
||||
current_timestamp_group_.last_system_time = system_time;
|
||||
|
||||
return calculated_deltas;
|
||||
}
|
||||
|
||||
// Assumes that |timestamp| is not reordered compared to
|
||||
// |current_timestamp_group_|.
|
||||
bool InterArrivalDelta::NewTimestampGroup(Timestamp arrival_time,
|
||||
Timestamp send_time) const {
|
||||
if (current_timestamp_group_.IsFirstPacket()) {
|
||||
return false;
|
||||
} else if (BelongsToBurst(arrival_time, send_time)) {
|
||||
return false;
|
||||
} else {
|
||||
return send_time - current_timestamp_group_.first_send_time >
|
||||
send_time_group_length_;
|
||||
}
|
||||
}
|
||||
|
||||
bool InterArrivalDelta::BelongsToBurst(Timestamp arrival_time,
|
||||
Timestamp send_time) const {
|
||||
RTC_DCHECK(current_timestamp_group_.complete_time.IsFinite());
|
||||
TimeDelta arrival_time_delta =
|
||||
arrival_time - current_timestamp_group_.complete_time;
|
||||
TimeDelta send_time_delta = send_time - current_timestamp_group_.send_time;
|
||||
if (send_time_delta.IsZero())
|
||||
return true;
|
||||
TimeDelta propagation_delta = arrival_time_delta - send_time_delta;
|
||||
if (propagation_delta < TimeDelta::Zero() &&
|
||||
arrival_time_delta <= kBurstDeltaThreshold &&
|
||||
arrival_time - current_timestamp_group_.first_arrival < kMaxBurstDuration)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void InterArrivalDelta::Reset() {
|
||||
num_consecutive_reordered_packets_ = 0;
|
||||
current_timestamp_group_ = SendTimeGroup();
|
||||
prev_timestamp_group_ = SendTimeGroup();
|
||||
}
|
||||
} // namespace webrtc
|
90
modules/congestion_controller/goog_cc/inter_arrival_delta.h
Normal file
90
modules/congestion_controller/goog_cc/inter_arrival_delta.h
Normal file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef MODULES_CONGESTION_CONTROLLER_GOOG_CC_INTER_ARRIVAL_DELTA_H_
|
||||
#define MODULES_CONGESTION_CONTROLLER_GOOG_CC_INTER_ARRIVAL_DELTA_H_
|
||||
|
||||
#include "api/units/time_delta.h"
|
||||
#include "api/units/timestamp.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// Helper class to compute the inter-arrival time delta and the size delta
|
||||
// between two send bursts. This code is branched from
|
||||
// modules/remote_bitrate_estimator/inter_arrival.
|
||||
class InterArrivalDelta {
|
||||
public:
|
||||
// After this many packet groups received out of order InterArrival will
|
||||
// reset, assuming that clocks have made a jump.
|
||||
static constexpr int kReorderedResetThreshold = 3;
|
||||
static constexpr TimeDelta kArrivalTimeOffsetThreshold =
|
||||
TimeDelta::Seconds(3);
|
||||
|
||||
// A send time group is defined as all packets with a send time which are at
|
||||
// most send_time_group_length older than the first timestamp in that
|
||||
// group.
|
||||
explicit InterArrivalDelta(TimeDelta send_time_group_length);
|
||||
|
||||
InterArrivalDelta() = delete;
|
||||
InterArrivalDelta(const InterArrivalDelta&) = delete;
|
||||
InterArrivalDelta& operator=(const InterArrivalDelta&) = delete;
|
||||
|
||||
// This function returns true if a delta was computed, or false if the current
|
||||
// group is still incomplete or if only one group has been completed.
|
||||
// |send_time| is the send time.
|
||||
// |arrival_time| is the time at which the packet arrived.
|
||||
// |packet_size| is the size of the packet.
|
||||
// |timestamp_delta| (output) is the computed send time delta.
|
||||
// |arrival_time_delta_ms| (output) is the computed arrival-time delta.
|
||||
// |packet_size_delta| (output) is the computed size delta.
|
||||
bool ComputeDeltas(Timestamp send_time,
|
||||
Timestamp arrival_time,
|
||||
Timestamp system_time,
|
||||
size_t packet_size,
|
||||
TimeDelta* send_time_delta,
|
||||
TimeDelta* arrival_time_delta,
|
||||
int* packet_size_delta);
|
||||
|
||||
private:
|
||||
struct SendTimeGroup {
|
||||
SendTimeGroup()
|
||||
: size(0),
|
||||
first_send_time(Timestamp::MinusInfinity()),
|
||||
send_time(Timestamp::MinusInfinity()),
|
||||
first_arrival(Timestamp::MinusInfinity()),
|
||||
complete_time(Timestamp::MinusInfinity()),
|
||||
last_system_time(Timestamp::MinusInfinity()) {}
|
||||
|
||||
bool IsFirstPacket() const { return complete_time.IsInfinite(); }
|
||||
|
||||
size_t size;
|
||||
Timestamp first_send_time;
|
||||
Timestamp send_time;
|
||||
Timestamp first_arrival;
|
||||
Timestamp complete_time;
|
||||
Timestamp last_system_time;
|
||||
};
|
||||
|
||||
// Returns true if the last packet was the end of the current batch and the
|
||||
// packet with |send_time| is the first of a new batch.
|
||||
bool NewTimestampGroup(Timestamp arrival_time, Timestamp send_time) const;
|
||||
|
||||
bool BelongsToBurst(Timestamp arrival_time, Timestamp send_time) const;
|
||||
|
||||
void Reset();
|
||||
|
||||
const TimeDelta send_time_group_length_;
|
||||
SendTimeGroup current_timestamp_group_;
|
||||
SendTimeGroup prev_timestamp_group_;
|
||||
int num_consecutive_reordered_packets_;
|
||||
};
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // MODULES_CONGESTION_CONTROLLER_GOOG_CC_INTER_ARRIVAL_DELTA_H_
|
Reference in New Issue
Block a user