Revert "Reland "Refactor NetEq delay manager logic.""

This reverts commit 2a7c57c34f323ee1977f6e7809ee23bfcf9a7459.

Reason for revert: unexpected big changes in behavior.

Original change's description:
> Reland "Refactor NetEq delay manager logic."
>
> This is a reland of f8e62fcb14e37a5be4f1e4f599d34c8483fea8e9
>
> Original change's description:
> > Refactor NetEq delay manager logic.
> >
> > - Removes dependence on sequence number for calculating target delay.
> > - Changes target delay unit to milliseconds instead of number of
> >   packets.
> > - Moves acceleration/preemptive expand thresholds to decision logic.
> >   Tests for this will be added in a follow up cl.
> >
> > Bug: webrtc:10333
> > Change-Id: If690aae4abf41ef1d9353f0ff01fb7d121cf8a26
> > Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/186265
> > Commit-Queue: Jakob Ivarsson <jakobi@webrtc.org>
> > Reviewed-by: Ivo Creusen <ivoc@webrtc.org>
> > Cr-Commit-Position: refs/heads/master@{#32326}
>
> Bug: webrtc:10333
> Change-Id: Iad5e7063f63b84762959ee5b412f5f14a7b2cd06
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/186943
> Commit-Queue: Jakob Ivarsson <jakobi@webrtc.org>
> Reviewed-by: Ivo Creusen <ivoc@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#32332}

TBR=ivoc@webrtc.org,jakobi@webrtc.org

Change-Id: Iffda0e8a7b647392d8dfc6724d49439fa13d71b2
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: webrtc:10333
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/187100
Reviewed-by: Jakob Ivarsson <jakobi@webrtc.org>
Commit-Queue: Jakob Ivarsson <jakobi@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#32341}
This commit is contained in:
Jakob Ivarsson
2020-10-07 12:46:42 +00:00
committed by Commit Bot
parent d0a8f51ef7
commit ff9f6461b6
12 changed files with 640 additions and 266 deletions

View File

@ -939,58 +939,58 @@ class AcmReceiverBitExactnessOldApi : public ::testing::Test {
defined(WEBRTC_CODEC_ILBC)
TEST_F(AcmReceiverBitExactnessOldApi, 8kHzOutput) {
std::string others_checksum_reference =
GetCPUInfo(kAVX2) != 0 ? "1d7b784031599e2c01a3f575f8439f2f"
: "c119fda4ea2c119ff2a720fd0c289071";
GetCPUInfo(kAVX2) != 0 ? "6edbfe69b965a8687b8744ed1b8eb5a7"
: "6c204b289486b0695b08a9e94fab1948";
std::string win64_checksum_reference =
GetCPUInfo(kAVX2) != 0 ? "405a50f0bcb8827e20aa944299fc59f6"
: "38e70d4e186f8e1a56b929fafcb7c379";
: "ff5ffee2ee92f8fe61d9f2010b8a68a3";
Run(8000,
PlatformChecksum(others_checksum_reference, win64_checksum_reference,
"3b03e41731e1cef5ae2b9f9618660b42",
"53494a96f3db4a5b07d723e0cbac0ad7",
"4598140b5e4f7ee66c5adad609e65a3e",
"da7e76687c8c0a9509cd1d57ee1aba3b"));
"516c2859126ea4913f30d51af4a4f3dc"));
}
TEST_F(AcmReceiverBitExactnessOldApi, 16kHzOutput) {
std::string others_checksum_reference =
GetCPUInfo(kAVX2) != 0 ? "8884d910e443c244d8593c2e3cef5e63"
: "36dc8c0532ba0efa099e2b6a689cde40";
GetCPUInfo(kAVX2) != 0 ? "295f031e051f1770b4ab4107dba768b5"
: "226dbdbce2354399c6df05371042cda3";
std::string win64_checksum_reference =
GetCPUInfo(kAVX2) != 0 ? "58fd62a5c49ee513f9fa6fe7dbf62c97"
: "07e4b388168e273fa19da0a167aff782";
: "9c80bf5ec496c41ce8112e1523bf8c83";
Run(16000,
PlatformChecksum(others_checksum_reference, win64_checksum_reference,
"06b08d14a72f6e7c72840b1cc9ad204d",
"11a6f170fdaffa81a2948af121f370af",
"f2aad418af974a3b1694d5ae5cc2c3c7",
"1d5f9a93f3975e7e491373b81eb5fd14"));
"6133301a18be95c416984182816d859f"));
}
TEST_F(AcmReceiverBitExactnessOldApi, 32kHzOutput) {
std::string others_checksum_reference =
GetCPUInfo(kAVX2) != 0 ? "73f4fe21996c0af495e2c47e3708e519"
: "c848ce9002d3825056a1eac2a067c0d3";
GetCPUInfo(kAVX2) != 0 ? "2895e5ab3146eaa78fa6843ed60e7e37"
: "f94665cc0e904d5d5cf0394e30ee4edd";
std::string win64_checksum_reference =
GetCPUInfo(kAVX2) != 0 ? "04ce6a1dac5ffdd8438d804623d0132f"
: "0e705f6844c75fd57a84734f7c30af87";
: "697934bcf0849f80d76ce20854161220";
Run(32000,
PlatformChecksum(others_checksum_reference, win64_checksum_reference,
"c18e98e5701ec91bba5c026b720d1790",
"3609aa5288c1d512e8e652ceabecb495",
"100869c8dcde51346c2073e52a272d98",
"e35df943bfa3ca32e86b26bf1e37ed8f"));
"55363bc9cdda6464a58044919157827b"));
}
TEST_F(AcmReceiverBitExactnessOldApi, 48kHzOutput) {
std::string others_checksum_reference =
GetCPUInfo(kAVX2) != 0 ? "884243f7e1476931e93eda5de88d1326"
: "ba0f66d538487bba377e721cfac62d1e";
GetCPUInfo(kAVX2) != 0 ? "640bca210e1b8dd229224d2a0c79ff1f"
: "2955d0b83602541fd92d9b820ebce68d";
std::string win64_checksum_reference =
GetCPUInfo(kAVX2) != 0 ? "f59833d9b0924f4b0704707dd3589f80"
: "6a480541fb86faa95c7563b9de08104d";
: "f4a8386a6a49439ced60ed9a7c7f75fd";
Run(48000,
PlatformChecksum(others_checksum_reference, win64_checksum_reference,
"30e617e4b3c9ba1979d1b2e8eba3519b",
"d8169dfeba708b5212bdc365e08aee9d",
"bd44bf97e7899186532f91235cef444d",
"90158462a1853b1de50873eebd68dba7"));
"47594deaab5d9166cfbf577203b2563e"));
}
TEST_F(AcmReceiverBitExactnessOldApi, 48kHzOutputExternalDecoder) {
@ -1069,16 +1069,16 @@ TEST_F(AcmReceiverBitExactnessOldApi, 48kHzOutputExternalDecoder) {
rtc::scoped_refptr<rtc::RefCountedObject<ADFactory>> factory(
new rtc::RefCountedObject<ADFactory>);
std::string others_checksum_reference =
GetCPUInfo(kAVX2) != 0 ? "884243f7e1476931e93eda5de88d1326"
: "ba0f66d538487bba377e721cfac62d1e";
GetCPUInfo(kAVX2) != 0 ? "640bca210e1b8dd229224d2a0c79ff1f"
: "2955d0b83602541fd92d9b820ebce68d";
std::string win64_checksum_reference =
GetCPUInfo(kAVX2) != 0 ? "f59833d9b0924f4b0704707dd3589f80"
: "6a480541fb86faa95c7563b9de08104d";
: "f4a8386a6a49439ced60ed9a7c7f75fd";
Run(48000,
PlatformChecksum(others_checksum_reference, win64_checksum_reference,
"30e617e4b3c9ba1979d1b2e8eba3519b",
"d8169dfeba708b5212bdc365e08aee9d",
"bd44bf97e7899186532f91235cef444d",
"90158462a1853b1de50873eebd68dba7"),
"47594deaab5d9166cfbf577203b2563e"),
factory, [](AudioCodingModule* acm) {
acm->SetReceiveCodecs({{0, {"MockPCMu", 8000, 1}},
{103, {"ISAC", 16000, 1}},
@ -1312,11 +1312,11 @@ TEST_F(AcmSenderBitExactnessOldApi, IsacWb30ms) {
TEST_F(AcmSenderBitExactnessOldApi, IsacWb60ms) {
ASSERT_NO_FATAL_FAILURE(SetUpTest("ISAC", 16000, 1, 103, 960, 960));
Run(AcmReceiverBitExactnessOldApi::PlatformChecksum(
"1ad29139a04782a33daad8c2b9b35875",
"14d63c5f08127d280e722e3191b73bdd",
"f59760fa000991ee5fa81f2e607db254",
"986aa16d7097a26e32e212e39ec58517",
"9a81e467eb1485f84aca796f8ea65011",
"ef75e900e6f375e3061163c53fd09a63",
"1ad29139a04782a33daad8c2b9b35875"),
"f59760fa000991ee5fa81f2e607db254"),
AcmReceiverBitExactnessOldApi::PlatformChecksum(
"9e0a0ab743ad987b55b8e14802769c56",
"ebe04a819d3a9d83a83a17f271e1139a",
@ -1349,37 +1349,37 @@ TEST_F(AcmSenderBitExactnessOldApi, MAYBE_IsacSwb30ms) {
TEST_F(AcmSenderBitExactnessOldApi, Pcm16_8000khz_10ms) {
ASSERT_NO_FATAL_FAILURE(SetUpTest("L16", 8000, 1, 107, 80, 80));
Run("15396f66b5b0ab6842e151c807395e4c", "c1edd36339ce0326cc4550041ad719a0",
Run("de4a98e1406f8b798d99cd0704e862e2", "c1edd36339ce0326cc4550041ad719a0",
100, test::AcmReceiveTestOldApi::kMonoOutput);
}
TEST_F(AcmSenderBitExactnessOldApi, Pcm16_16000khz_10ms) {
ASSERT_NO_FATAL_FAILURE(SetUpTest("L16", 16000, 1, 108, 160, 160));
Run("54ae004529874c2b362c7f0ccd19cb99", "ad786526383178b08d80d6eee06e9bad",
Run("ae646d7b68384a1269cc080dd4501916", "ad786526383178b08d80d6eee06e9bad",
100, test::AcmReceiveTestOldApi::kMonoOutput);
}
TEST_F(AcmSenderBitExactnessOldApi, Pcm16_32000khz_10ms) {
ASSERT_NO_FATAL_FAILURE(SetUpTest("L16", 32000, 1, 109, 320, 320));
Run("d6a4a68b8c838dcc1e7ae7136467cdf0", "5ef82ea885e922263606c6fdbc49f651",
Run("7fe325e8fbaf755e3c5df0b11a4774fb", "5ef82ea885e922263606c6fdbc49f651",
100, test::AcmReceiveTestOldApi::kMonoOutput);
}
TEST_F(AcmSenderBitExactnessOldApi, Pcm16_stereo_8000khz_10ms) {
ASSERT_NO_FATAL_FAILURE(SetUpTest("L16", 8000, 2, 111, 80, 80));
Run("6b011dab43e3a8a46ccff7e4412ed8a2", "62ce5adb0d4965d0a52ec98ae7f98974",
Run("fb263b74e7ac3de915474d77e4744ceb", "62ce5adb0d4965d0a52ec98ae7f98974",
100, test::AcmReceiveTestOldApi::kStereoOutput);
}
TEST_F(AcmSenderBitExactnessOldApi, Pcm16_stereo_16000khz_10ms) {
ASSERT_NO_FATAL_FAILURE(SetUpTest("L16", 16000, 2, 112, 160, 160));
Run("17fc9854358bfe0419408290664bd78e", "41ca8edac4b8c71cd54fd9f25ec14870",
Run("d09e9239553649d7ac93e19d304281fd", "41ca8edac4b8c71cd54fd9f25ec14870",
100, test::AcmReceiveTestOldApi::kStereoOutput);
}
TEST_F(AcmSenderBitExactnessOldApi, Pcm16_stereo_32000khz_10ms) {
ASSERT_NO_FATAL_FAILURE(SetUpTest("L16", 32000, 2, 113, 320, 320));
Run("9ac9a1f64d55da2fc9f3167181cc511d", "50e58502fb04421bf5b857dda4c96879",
Run("5f025d4f390982cc26b3d92fe02e3044", "50e58502fb04421bf5b857dda4c96879",
100, test::AcmReceiveTestOldApi::kStereoOutput);
}

View File

@ -45,12 +45,12 @@ void BufferLevelFilter::Update(size_t buffer_size_samples,
filtered_current_level - (int64_t{time_stretched_samples} * (1 << 8))));
}
void BufferLevelFilter::SetTargetBufferLevel(int target_buffer_level_ms) {
if (target_buffer_level_ms <= 20) {
void BufferLevelFilter::SetTargetBufferLevel(int target_buffer_level) {
if (target_buffer_level <= 1) {
level_factor_ = 251;
} else if (target_buffer_level_ms <= 60) {
} else if (target_buffer_level <= 3) {
level_factor_ = 252;
} else if (target_buffer_level_ms <= 140) {
} else if (target_buffer_level <= 7) {
level_factor_ = 253;
} else {
level_factor_ = 254;

View File

@ -23,13 +23,15 @@ class BufferLevelFilter {
virtual ~BufferLevelFilter() {}
virtual void Reset();
// Updates the filter. Current buffer size is |buffer_size_samples|.
// Updates the filter. Current buffer size is |buffer_size_packets| (Q0).
// |time_stretched_samples| is subtracted from the filtered value (thus
// bypassing the filter operation).
virtual void Update(size_t buffer_size_samples, int time_stretched_samples);
// The target level is used to select the appropriate filter coefficient.
virtual void SetTargetBufferLevel(int target_buffer_level_ms);
// Set the current target buffer level in number of packets (obtained from
// DelayManager::base_target_level()). Used to select the appropriate
// filter coefficient.
virtual void SetTargetBufferLevel(int target_buffer_level_packets);
// Returns filtered current level in number of samples.
virtual int filtered_current_level() const {

View File

@ -30,7 +30,7 @@ TEST(BufferLevelFilter, ConvergenceTest) {
for (int times = 10; times <= 50; times += 10) {
for (int value = 100; value <= 200; value += 10) {
filter.Reset();
filter.SetTargetBufferLevel(20); // Makes filter coefficient 251/256.
filter.SetTargetBufferLevel(1); // Makes filter coefficient 251/256.
rtc::StringBuilder ss;
ss << "times = " << times << ", value = " << value;
SCOPED_TRACE(ss.str()); // Print out the parameter values on failure.
@ -57,7 +57,7 @@ TEST(BufferLevelFilter, FilterFactor) {
const int kTimes = 10;
const int kValue = 100;
filter.SetTargetBufferLevel(60); // Makes filter coefficient 252/256.
filter.SetTargetBufferLevel(3); // Makes filter coefficient 252/256.
for (int i = 0; i < kTimes; ++i) {
filter.Update(kValue, 0 /* time_stretched_samples */);
}
@ -67,7 +67,7 @@ TEST(BufferLevelFilter, FilterFactor) {
EXPECT_EQ(expected_value, filter.filtered_current_level());
filter.Reset();
filter.SetTargetBufferLevel(140); // Makes filter coefficient 253/256.
filter.SetTargetBufferLevel(7); // Makes filter coefficient 253/256.
for (int i = 0; i < kTimes; ++i) {
filter.Update(kValue, 0 /* time_stretched_samples */);
}
@ -77,7 +77,7 @@ TEST(BufferLevelFilter, FilterFactor) {
EXPECT_EQ(expected_value, filter.filtered_current_level());
filter.Reset();
filter.SetTargetBufferLevel(160); // Makes filter coefficient 254/256.
filter.SetTargetBufferLevel(8); // Makes filter coefficient 254/256.
for (int i = 0; i < kTimes; ++i) {
filter.Update(kValue, 0 /* time_stretched_samples */);
}
@ -89,7 +89,7 @@ TEST(BufferLevelFilter, FilterFactor) {
TEST(BufferLevelFilter, TimeStretchedSamples) {
BufferLevelFilter filter;
filter.SetTargetBufferLevel(20); // Makes filter coefficient 251/256.
filter.SetTargetBufferLevel(1); // Makes filter coefficient 251/256.
// Update 10 times with value 100.
const int kTimes = 10;
const int kValue = 100;

View File

@ -27,7 +27,6 @@ namespace {
constexpr int kPostponeDecodingLevel = 50;
constexpr int kDefaultTargetLevelWindowMs = 100;
constexpr int kDecelerationTargetLevelOffsetMs = 85;
} // namespace
@ -36,6 +35,7 @@ namespace webrtc {
DecisionLogic::DecisionLogic(NetEqController::Config config)
: delay_manager_(DelayManager::Create(config.max_packets_in_buffer,
config.base_min_delay_ms,
config.enable_rtx_handling,
config.tick_timer)),
tick_timer_(config.tick_timer),
disallow_time_stretching_(!config.allow_time_stretching),
@ -67,7 +67,6 @@ void DecisionLogic::Reset() {
packet_length_samples_ = 0;
sample_memory_ = 0;
prev_time_scale_ = false;
last_pack_cng_or_dtmf_ = true;
timescale_countdown_.reset();
num_consecutive_expands_ = 0;
time_stretched_cn_samples_ = 0;
@ -77,7 +76,6 @@ void DecisionLogic::SoftReset() {
packet_length_samples_ = 0;
sample_memory_ = 0;
prev_time_scale_ = false;
last_pack_cng_or_dtmf_ = true;
timescale_countdown_ =
tick_timer_->GetNewCountdown(kMinTimescaleInterval + 1);
time_stretched_cn_samples_ = 0;
@ -160,13 +158,12 @@ NetEq::Operation DecisionLogic::GetDecision(const NetEqStatus& status,
const size_t current_span =
estimate_dtx_delay_ ? status.packet_buffer_info.span_samples
: status.packet_buffer_info.span_samples_no_dtx;
const int target_level_samples =
delay_manager_->TargetDelayMs() * sample_rate_ / 1000;
if ((status.last_mode == NetEq::Mode::kExpand ||
status.last_mode == NetEq::Mode::kCodecPlc) &&
status.expand_mutefactor < 16384 / 2 &&
current_span < static_cast<size_t>(target_level_samples *
kPostponeDecodingLevel / 100) &&
current_span<static_cast<size_t>(delay_manager_->TargetLevel() *
packet_length_samples_ *
kPostponeDecodingLevel / 100)>> 8 &&
!status.packet_buffer_info.dtx_or_cng) {
return NetEq::Operation::kExpand;
}
@ -198,32 +195,41 @@ void DecisionLogic::ExpandDecision(NetEq::Operation operation) {
}
}
absl::optional<int> DecisionLogic::PacketArrived(bool is_cng_or_dtmf,
absl::optional<int> DecisionLogic::PacketArrived(bool last_cng_or_dtmf,
size_t packet_length_samples,
bool should_update_stats,
uint16_t main_sequence_number,
uint32_t main_timestamp,
int fs_hz) {
if (is_cng_or_dtmf) {
last_pack_cng_or_dtmf_ = true;
return absl::nullopt;
delay_manager_->LastDecodedWasCngOrDtmf(last_cng_or_dtmf);
absl::optional<int> relative_delay;
if (delay_manager_->last_pack_cng_or_dtmf() == 0) {
// Calculate the total speech length carried in each packet.
if (packet_length_samples > 0 &&
packet_length_samples != packet_length_samples_) {
packet_length_samples_ = packet_length_samples;
delay_manager_->SetPacketAudioLength(
rtc::dchecked_cast<int>((1000 * packet_length_samples) / fs_hz));
}
// Update statistics.
if (should_update_stats) {
relative_delay =
delay_manager_->Update(main_sequence_number, main_timestamp, fs_hz);
}
} else if (delay_manager_->last_pack_cng_or_dtmf() == -1) {
// This is first "normal" packet after CNG or DTMF.
// Reset packet time counter and measure time until next packet,
// but don't update statistics.
delay_manager_->set_last_pack_cng_or_dtmf(0);
delay_manager_->ResetPacketIatCount();
}
if (!should_update_stats) {
return absl::nullopt;
}
if (packet_length_samples > 0 && fs_hz > 0 &&
packet_length_samples != packet_length_samples_) {
packet_length_samples_ = packet_length_samples;
delay_manager_->SetPacketAudioLength(packet_length_samples_ * 1000 / fs_hz);
}
auto relative_delay = delay_manager_->Update(
main_timestamp, fs_hz, /*reset=*/last_pack_cng_or_dtmf_);
last_pack_cng_or_dtmf_ = false;
return relative_delay;
}
void DecisionLogic::FilterBufferLevel(size_t buffer_size_samples) {
buffer_level_filter_.SetTargetBufferLevel(delay_manager_->TargetDelayMs());
buffer_level_filter_.SetTargetBufferLevel(
delay_manager_->base_target_level());
int time_stretched_samples = time_stretched_cn_samples_;
if (prev_time_scale_) {
@ -244,8 +250,8 @@ NetEq::Operation DecisionLogic::CngOperation(NetEq::Mode prev_mode,
int32_t timestamp_diff = static_cast<int32_t>(
static_cast<uint32_t>(generated_noise_samples + target_timestamp) -
available_timestamp);
int optimal_level_samp =
delay_manager_->TargetDelayMs() * sample_rate_ / 1000;
int32_t optimal_level_samp = static_cast<int32_t>(
(delay_manager_->TargetLevel() * packet_length_samples_) >> 8);
const int64_t excess_waiting_time_samp =
-static_cast<int64_t>(timestamp_diff) - optimal_level_samp;
@ -289,26 +295,22 @@ NetEq::Operation DecisionLogic::ExpectedPacketAvailable(NetEq::Mode prev_mode,
bool play_dtmf) {
if (!disallow_time_stretching_ && prev_mode != NetEq::Mode::kExpand &&
!play_dtmf) {
const int samples_per_ms = sample_rate_ / 1000;
const int target_level_samples =
delay_manager_->TargetDelayMs() * samples_per_ms;
const int low_limit =
std::max(target_level_samples * 3 / 4,
target_level_samples -
kDecelerationTargetLevelOffsetMs * samples_per_ms);
// |higher_limit| is equal to |target_level|, but should at
// least be 20 ms higher than |lower_limit|.
const int high_limit =
std::max(target_level_samples, low_limit + 20 * samples_per_ms);
const int buffer_level_samples =
buffer_level_filter_.filtered_current_level();
if (buffer_level_samples >= high_limit << 2)
// Check criterion for time-stretching. The values are in number of packets
// in Q8.
int low_limit, high_limit;
delay_manager_->BufferLimits(&low_limit, &high_limit);
int buffer_level_packets = 0;
if (packet_length_samples_ > 0) {
buffer_level_packets =
((1 << 8) * buffer_level_filter_.filtered_current_level()) /
packet_length_samples_;
}
if (buffer_level_packets >= high_limit << 2)
return NetEq::Operation::kFastAccelerate;
if (TimescaleAllowed()) {
if (buffer_level_samples >= high_limit)
if (buffer_level_packets >= high_limit)
return NetEq::Operation::kAccelerate;
if (buffer_level_samples < low_limit)
if (buffer_level_packets < low_limit)
return NetEq::Operation::kPreemptiveExpand;
}
}
@ -350,11 +352,11 @@ NetEq::Operation DecisionLogic::FuturePacketAvailable(
prev_mode == NetEq::Mode::kCodecInternalCng) {
size_t cur_size_samples =
estimate_dtx_delay_
? span_samples_in_packet_buffer
? cur_size_samples = span_samples_in_packet_buffer
: num_packets_in_packet_buffer * decoder_frame_length;
// Target level is in number of packets in Q8.
const size_t target_level_samples =
delay_manager_->TargetDelayMs() * sample_rate_ / 1000;
(delay_manager_->TargetLevel() * packet_length_samples_) >> 8;
const bool generated_enough_noise =
static_cast<uint32_t>(generated_noise_samples + target_timestamp) >=
available_timestamp;
@ -404,8 +406,13 @@ NetEq::Operation DecisionLogic::FuturePacketAvailable(
}
bool DecisionLogic::UnderTargetLevel() const {
return buffer_level_filter_.filtered_current_level() <
delay_manager_->TargetDelayMs() * sample_rate_ / 1000;
int buffer_level_packets = 0;
if (packet_length_samples_ > 0) {
buffer_level_packets =
((1 << 8) * buffer_level_filter_.filtered_current_level()) /
packet_length_samples_;
}
return buffer_level_packets <= delay_manager_->TargetLevel();
}
bool DecisionLogic::ReinitAfterExpands(uint32_t timestamp_leap) const {

View File

@ -70,16 +70,19 @@ class DecisionLogic : public NetEqController {
// Adds |value| to |sample_memory_|.
void AddSampleMemory(int32_t value) override { sample_memory_ += value; }
int TargetLevelMs() const override { return delay_manager_->TargetDelayMs(); }
int TargetLevelMs() const override {
return ((delay_manager_->TargetLevel() * packet_length_samples_) >> 8) /
rtc::CheckedDivExact(sample_rate_, 1000);
}
absl::optional<int> PacketArrived(bool is_cng_or_dtmf,
absl::optional<int> PacketArrived(bool last_cng_or_dtmf,
size_t packet_length_samples,
bool should_update_stats,
uint16_t main_sequence_number,
uint32_t main_timestamp,
int fs_hz) override;
void RegisterEmptyPacket() override {}
void RegisterEmptyPacket() override { delay_manager_->RegisterEmptyPacket(); }
void NotifyMutedState() override {}
@ -119,8 +122,8 @@ class DecisionLogic : public NetEqController {
enum CngState { kCngOff, kCngRfc3389On, kCngInternalOn };
// Updates the |buffer_level_filter_| with the current buffer level
// |buffer_size_samples|.
void FilterBufferLevel(size_t buffer_size_samples);
// |buffer_size_packets|.
void FilterBufferLevel(size_t buffer_size_packets);
// Returns the operation given that the next available packet is a comfort
// noise payload (RFC 3389 only, not codec-internal).
@ -185,7 +188,6 @@ class DecisionLogic : public NetEqController {
std::unique_ptr<TickTimer::Countdown> timescale_countdown_;
int num_consecutive_expands_ = 0;
int time_stretched_cn_samples_ = 0;
bool last_pack_cng_or_dtmf_ = true;
FieldTrialParameter<bool> estimate_dtx_delay_;
FieldTrialParameter<bool> time_stretch_cn_;
FieldTrialConstrained<int> target_level_window_ms_;

View File

@ -43,6 +43,6 @@ TEST(DecisionLogic, CreateAndDestroy) {
logic->SetSampleRate(fs_hz, output_size_samples);
}
// TODO(jakobi): Write more tests.
// TODO(hlundin): Write more tests.
} // namespace webrtc

View File

@ -27,16 +27,17 @@
#include "rtc_base/numerics/safe_minmax.h"
#include "system_wrappers/include/field_trial.h"
namespace webrtc {
namespace {
constexpr int kMinBaseMinimumDelayMs = 0;
constexpr int kMaxBaseMinimumDelayMs = 10000;
constexpr int kMaxReorderedPackets =
10; // Max number of consecutive reordered packets.
constexpr int kMaxHistoryMs = 2000; // Oldest packet to include in history to
// calculate relative packet arrival delay.
constexpr int kDelayBuckets = 100;
constexpr int kBucketSizeMs = 20;
constexpr int kStartDelayMs = 80;
constexpr int kDecelerationTargetLevelOffsetMs = 85 << 8; // In Q8.
int PercentileToQuantile(double percentile) {
return static_cast<int>((1 << 30) * percentile / 100.0 + 0.5);
@ -48,7 +49,6 @@ struct DelayHistogramConfig {
absl::optional<double> start_forget_weight = 2;
};
// TODO(jakobi): Remove legacy field trial.
DelayHistogramConfig GetDelayHistogramConfig() {
constexpr char kDelayHistogramFieldTrial[] =
"WebRTC-Audio-NetEqDelayHistogram";
@ -81,9 +81,12 @@ DelayHistogramConfig GetDelayHistogramConfig() {
} // namespace
DelayManager::DelayManager(int max_packets_in_buffer,
namespace webrtc {
DelayManager::DelayManager(size_t max_packets_in_buffer,
int base_minimum_delay_ms,
int histogram_quantile,
bool enable_rtx_handling,
const TickTimer* tick_timer,
std::unique_ptr<Histogram> histogram)
: first_packet_received_(false),
@ -93,10 +96,15 @@ DelayManager::DelayManager(int max_packets_in_buffer,
tick_timer_(tick_timer),
base_minimum_delay_ms_(base_minimum_delay_ms),
effective_minimum_delay_ms_(base_minimum_delay_ms),
base_target_level_(4), // In Q0 domain.
target_level_(base_target_level_ << 8), // In Q8 domain.
packet_len_ms_(0),
last_seq_no_(0),
last_timestamp_(0),
minimum_delay_ms_(0),
maximum_delay_ms_(0),
target_level_ms_(kStartDelayMs),
last_timestamp_(0) {
last_pack_cng_or_dtmf_(1),
enable_rtx_handling_(enable_rtx_handling) {
RTC_CHECK(histogram_);
RTC_DCHECK_GE(base_minimum_delay_ms_, 0);
@ -104,70 +112,102 @@ DelayManager::DelayManager(int max_packets_in_buffer,
}
std::unique_ptr<DelayManager> DelayManager::Create(
int max_packets_in_buffer,
size_t max_packets_in_buffer,
int base_minimum_delay_ms,
bool enable_rtx_handling,
const TickTimer* tick_timer) {
auto config = GetDelayHistogramConfig();
DelayHistogramConfig config = GetDelayHistogramConfig();
const int quantile = config.quantile;
std::unique_ptr<Histogram> histogram = std::make_unique<Histogram>(
kDelayBuckets, config.forget_factor, config.start_forget_weight);
return std::make_unique<DelayManager>(max_packets_in_buffer,
base_minimum_delay_ms, config.quantile,
tick_timer, std::move(histogram));
return std::make_unique<DelayManager>(
max_packets_in_buffer, base_minimum_delay_ms, quantile,
enable_rtx_handling, tick_timer, std::move(histogram));
}
DelayManager::~DelayManager() {}
absl::optional<int> DelayManager::Update(uint32_t timestamp,
int sample_rate_hz,
bool reset) {
absl::optional<int> DelayManager::Update(uint16_t sequence_number,
uint32_t timestamp,
int sample_rate_hz) {
if (sample_rate_hz <= 0) {
return absl::nullopt;
}
if (!first_packet_received_ || reset) {
// Restart relative delay esimation from this packet.
delay_history_.clear();
if (!first_packet_received_) {
// Prepare for next packet arrival.
packet_iat_stopwatch_ = tick_timer_->GetNewStopwatch();
last_seq_no_ = sequence_number;
last_timestamp_ = timestamp;
first_packet_received_ = true;
return absl::nullopt;
}
const int expected_iat_ms =
1000 * static_cast<int32_t>(timestamp - last_timestamp_) / sample_rate_hz;
const int iat_ms = packet_iat_stopwatch_->ElapsedMs();
const int iat_delay_ms = iat_ms - expected_iat_ms;
absl::optional<int> relative_delay;
if (!IsNewerTimestamp(timestamp, last_timestamp_)) {
relative_delay = std::max(iat_delay_ms, 0);
// Reset the history and restart delay estimation from this packet.
delay_history_.clear();
// Try calculating packet length from current and previous timestamps.
int packet_len_ms;
if (!IsNewerTimestamp(timestamp, last_timestamp_) ||
!IsNewerSequenceNumber(sequence_number, last_seq_no_)) {
// Wrong timestamp or sequence order; use stored value.
packet_len_ms = packet_len_ms_;
} else {
UpdateDelayHistory(iat_delay_ms, timestamp, sample_rate_hz);
relative_delay = CalculateRelativePacketArrivalDelay();
}
const int index = relative_delay.value() / kBucketSizeMs;
if (index < histogram_->NumBuckets()) {
// Maximum delay to register is 2000 ms.
histogram_->Add(index);
}
// Calculate new |target_level_ms_| based on updated statistics.
int bucket_index = histogram_->Quantile(histogram_quantile_);
target_level_ms_ = (1 + bucket_index) * kBucketSizeMs;
target_level_ms_ = std::max(target_level_ms_, effective_minimum_delay_ms_);
if (maximum_delay_ms_ > 0) {
target_level_ms_ = std::min(target_level_ms_, maximum_delay_ms_);
}
if (packet_len_ms_ > 0) {
// Target level should be at least one packet.
target_level_ms_ = std::max(target_level_ms_, packet_len_ms_);
// Limit to 75% of maximum buffer size.
target_level_ms_ = std::min(
target_level_ms_, 3 * max_packets_in_buffer_ * packet_len_ms_ / 4);
// Calculate timestamps per packet and derive packet length in ms.
int64_t packet_len_samp =
static_cast<uint32_t>(timestamp - last_timestamp_) /
static_cast<uint16_t>(sequence_number - last_seq_no_);
packet_len_ms =
rtc::saturated_cast<int>(1000 * packet_len_samp / sample_rate_hz);
}
bool reordered = false;
absl::optional<int> relative_delay;
if (packet_len_ms > 0) {
// Cannot update statistics unless |packet_len_ms| is valid.
// Inter-arrival time (IAT) in integer "packet times" (rounding down). This
// is the value added to the inter-arrival time histogram.
int iat_ms = packet_iat_stopwatch_->ElapsedMs();
// Check for discontinuous packet sequence and re-ordering.
if (IsNewerSequenceNumber(sequence_number, last_seq_no_ + 1)) {
// Compensate for gap in the sequence numbers. Reduce IAT with the
// expected extra time due to lost packets.
int packet_offset =
static_cast<uint16_t>(sequence_number - last_seq_no_ - 1);
iat_ms -= packet_offset * packet_len_ms;
} else if (!IsNewerSequenceNumber(sequence_number, last_seq_no_)) {
int packet_offset =
static_cast<uint16_t>(last_seq_no_ + 1 - sequence_number);
iat_ms += packet_offset * packet_len_ms;
reordered = true;
}
int iat_delay = iat_ms - packet_len_ms;
if (reordered) {
relative_delay = std::max(iat_delay, 0);
} else {
UpdateDelayHistory(iat_delay, timestamp, sample_rate_hz);
relative_delay = CalculateRelativePacketArrivalDelay();
}
const int index = relative_delay.value() / kBucketSizeMs;
if (index < histogram_->NumBuckets()) {
// Maximum delay to register is 2000 ms.
histogram_->Add(index);
}
// Calculate new |target_level_| based on updated statistics.
target_level_ = CalculateTargetLevel();
LimitTargetLevel();
} // End if (packet_len_ms > 0).
if (enable_rtx_handling_ && reordered &&
num_reordered_packets_ < kMaxReorderedPackets) {
++num_reordered_packets_;
return relative_delay;
}
num_reordered_packets_ = 0;
// Prepare for next packet arrival.
packet_iat_stopwatch_ = tick_timer_->GetNewStopwatch();
last_seq_no_ = sequence_number;
last_timestamp_ = timestamp;
return relative_delay;
}
@ -198,26 +238,128 @@ int DelayManager::CalculateRelativePacketArrivalDelay() const {
return relative_delay;
}
// Enforces upper and lower limits for |target_level_|. The upper limit is
// chosen to be minimum of i) 75% of |max_packets_in_buffer_|, to leave some
// headroom for natural fluctuations around the target, and ii) equivalent of
// |maximum_delay_ms_| in packets. Note that in practice, if no
// |maximum_delay_ms_| is specified, this does not have any impact, since the
// target level is far below the buffer capacity in all reasonable cases.
// The lower limit is equivalent of |effective_minimum_delay_ms_| in packets.
// We update |least_required_level_| while the above limits are applied.
// TODO(hlundin): Move this check to the buffer logistics class.
void DelayManager::LimitTargetLevel() {
if (packet_len_ms_ > 0 && effective_minimum_delay_ms_ > 0) {
int minimum_delay_packet_q8 =
(effective_minimum_delay_ms_ << 8) / packet_len_ms_;
target_level_ = std::max(target_level_, minimum_delay_packet_q8);
}
if (maximum_delay_ms_ > 0 && packet_len_ms_ > 0) {
int maximum_delay_packet_q8 = (maximum_delay_ms_ << 8) / packet_len_ms_;
target_level_ = std::min(target_level_, maximum_delay_packet_q8);
}
// Shift to Q8, then 75%.;
int max_buffer_packets_q8 =
static_cast<int>((3 * (max_packets_in_buffer_ << 8)) / 4);
target_level_ = std::min(target_level_, max_buffer_packets_q8);
// Sanity check, at least 1 packet (in Q8).
target_level_ = std::max(target_level_, 1 << 8);
}
int DelayManager::CalculateTargetLevel() {
int limit_probability = histogram_quantile_;
int bucket_index = histogram_->Quantile(limit_probability);
int target_level = 1;
if (packet_len_ms_ > 0) {
target_level += bucket_index * kBucketSizeMs / packet_len_ms_;
}
base_target_level_ = target_level;
// Sanity check. |target_level| must be strictly positive.
target_level = std::max(target_level, 1);
// Scale to Q8 and assign to member variable.
target_level_ = target_level << 8;
return target_level_;
}
int DelayManager::SetPacketAudioLength(int length_ms) {
if (length_ms <= 0) {
RTC_LOG_F(LS_ERROR) << "length_ms = " << length_ms;
return -1;
}
packet_len_ms_ = length_ms;
packet_iat_stopwatch_ = tick_timer_->GetNewStopwatch();
last_pack_cng_or_dtmf_ = 1; // TODO(hlundin): Legacy. Remove?
return 0;
}
void DelayManager::Reset() {
packet_len_ms_ = 0;
packet_len_ms_ = 0; // Packet size unknown.
histogram_->Reset();
delay_history_.clear();
target_level_ms_ = kStartDelayMs;
base_target_level_ = 4;
target_level_ = base_target_level_ << 8;
packet_iat_stopwatch_ = tick_timer_->GetNewStopwatch();
first_packet_received_ = false;
last_pack_cng_or_dtmf_ = 1;
}
int DelayManager::TargetDelayMs() const {
return target_level_ms_;
void DelayManager::ResetPacketIatCount() {
packet_iat_stopwatch_ = tick_timer_->GetNewStopwatch();
}
void DelayManager::BufferLimits(int* lower_limit, int* higher_limit) const {
BufferLimits(target_level_, lower_limit, higher_limit);
}
// Note that |low_limit| and |higher_limit| are not assigned to
// |minimum_delay_ms_| and |maximum_delay_ms_| defined by the client of this
// class. They are computed from |target_level| in Q8 and used for decision
// making.
void DelayManager::BufferLimits(int target_level,
int* lower_limit,
int* higher_limit) const {
if (!lower_limit || !higher_limit) {
RTC_LOG_F(LS_ERROR) << "NULL pointers supplied as input";
assert(false);
return;
}
// |target_level| is in Q8 already.
*lower_limit = (target_level * 3) / 4;
if (packet_len_ms_ > 0) {
*lower_limit =
std::max(*lower_limit, target_level - kDecelerationTargetLevelOffsetMs /
packet_len_ms_);
}
int window_20ms = 0x7FFF; // Default large value for legacy bit-exactness.
if (packet_len_ms_ > 0) {
window_20ms = (20 << 8) / packet_len_ms_;
}
// |higher_limit| is equal to |target_level|, but should at
// least be 20 ms higher than |lower_limit|.
*higher_limit = std::max(target_level, *lower_limit + window_20ms);
}
int DelayManager::TargetLevel() const {
return target_level_;
}
void DelayManager::LastDecodedWasCngOrDtmf(bool it_was) {
if (it_was) {
last_pack_cng_or_dtmf_ = 1;
} else if (last_pack_cng_or_dtmf_ != 0) {
last_pack_cng_or_dtmf_ = -1;
}
}
void DelayManager::RegisterEmptyPacket() {
++last_seq_no_;
}
bool DelayManager::IsValidMinimumDelay(int delay_ms) const {
@ -267,6 +409,17 @@ int DelayManager::GetBaseMinimumDelay() const {
return base_minimum_delay_ms_;
}
int DelayManager::base_target_level() const {
return base_target_level_;
}
int DelayManager::last_pack_cng_or_dtmf() const {
return last_pack_cng_or_dtmf_;
}
void DelayManager::set_last_pack_cng_or_dtmf(int value) {
last_pack_cng_or_dtmf_ = value;
}
void DelayManager::UpdateEffectiveMinimumDelay() {
// Clamp |base_minimum_delay_ms_| into the range which can be effectively
// used.
@ -279,11 +432,16 @@ void DelayManager::UpdateEffectiveMinimumDelay() {
int DelayManager::MinimumDelayUpperBound() const {
// Choose the lowest possible bound discarding 0 cases which mean the value
// is not set and unconstrained.
int q75 = max_packets_in_buffer_ * packet_len_ms_ * 3 / 4;
int q75 = MaxBufferTimeQ75();
q75 = q75 > 0 ? q75 : kMaxBaseMinimumDelayMs;
const int maximum_delay_ms =
maximum_delay_ms_ > 0 ? maximum_delay_ms_ : kMaxBaseMinimumDelayMs;
return std::min(maximum_delay_ms, q75);
}
int DelayManager::MaxBufferTimeQ75() const {
const int max_buffer_time = max_packets_in_buffer_ * packet_len_ms_;
return rtc::dchecked_cast<int>(3 * max_buffer_time / 4);
}
} // namespace webrtc

View File

@ -25,9 +25,10 @@ namespace webrtc {
class DelayManager {
public:
DelayManager(int max_packets_in_buffer,
DelayManager(size_t max_packets_in_buffer,
int base_minimum_delay_ms,
int histogram_quantile,
bool enable_rtx_handling,
const TickTimer* tick_timer,
std::unique_ptr<Histogram> histogram);
@ -36,41 +37,75 @@ class DelayManager {
// is the number of packet slots in the buffer) and that the target delay
// should be greater than or equal to |base_minimum_delay_ms|. Supply a
// PeakDetector object to the DelayManager.
static std::unique_ptr<DelayManager> Create(int max_packets_in_buffer,
static std::unique_ptr<DelayManager> Create(size_t max_packets_in_buffer,
int base_minimum_delay_ms,
bool enable_rtx_handling,
const TickTimer* tick_timer);
virtual ~DelayManager();
// Updates the delay manager with a new incoming packet, with |timestamp| from
// the RTP header. This updates the statistics and a new target buffer level
// is calculated. Returns the relative delay if it can be calculated. If
// |reset| is true, restarts the relative arrival delay calculation from this
// packet.
virtual absl::optional<int> Update(uint32_t timestamp,
int sample_rate_hz,
bool reset = false);
// Updates the delay manager with a new incoming packet, with
// |sequence_number| and |timestamp| from the RTP header. This updates the
// inter-arrival time histogram and other statistics, as well as the
// associated DelayPeakDetector. A new target buffer level is calculated.
// Returns the relative delay if it can be calculated.
virtual absl::optional<int> Update(uint16_t sequence_number,
uint32_t timestamp,
int sample_rate_hz);
// Resets all state.
virtual void Reset();
// Gets the target buffer level in milliseconds.
virtual int TargetDelayMs() const;
// Calculates a new target buffer level. Called from the Update() method.
// Sets target_level_ (in Q8) and returns the same value. Also calculates
// and updates base_target_level_, which is the target buffer level before
// taking delay peaks into account.
virtual int CalculateTargetLevel();
// Notifies the DelayManager of how much audio data is carried in each packet.
// The method updates the DelayPeakDetector too, and resets the inter-arrival
// time counter. Returns 0 on success, -1 on failure.
virtual int SetPacketAudioLength(int length_ms);
// Resets the DelayManager and the associated DelayPeakDetector.
virtual void Reset();
// Reset the inter-arrival time counter to 0.
virtual void ResetPacketIatCount();
// Writes the lower and higher limits which the buffer level should stay
// within to the corresponding pointers. The values are in (fractions of)
// packets in Q8.
virtual void BufferLimits(int* lower_limit, int* higher_limit) const;
virtual void BufferLimits(int target_level,
int* lower_limit,
int* higher_limit) const;
// Gets the target buffer level, in (fractions of) packets in Q8.
virtual int TargetLevel() const;
// Informs the delay manager whether or not the last decoded packet contained
// speech.
virtual void LastDecodedWasCngOrDtmf(bool it_was);
// Notify the delay manager that empty packets have been received. These are
// packets that are part of the sequence number series, so that an empty
// packet will shift the sequence numbers for the following packets.
virtual void RegisterEmptyPacket();
// Accessors and mutators.
// Assuming |delay| is in valid range.
virtual bool SetMinimumDelay(int delay_ms);
virtual bool SetMaximumDelay(int delay_ms);
virtual bool SetBaseMinimumDelay(int delay_ms);
virtual int GetBaseMinimumDelay() const;
virtual int base_target_level() const;
virtual int last_pack_cng_or_dtmf() const;
virtual void set_last_pack_cng_or_dtmf(int value);
// These accessors are only intended for testing purposes.
// This accessor is only intended for testing purposes.
int effective_minimum_delay_ms_for_test() const {
return effective_minimum_delay_ms_;
}
// These accessors are only intended for testing purposes.
int histogram_quantile() const { return histogram_quantile_; }
Histogram* histogram() const { return histogram_.get(); }
@ -79,6 +114,9 @@ class DelayManager {
// size and given |maximum_delay_ms_|. Lower bound is a constant 0.
int MinimumDelayUpperBound() const;
// Provides 75% of currently possible maximum buffer size in milliseconds.
int MaxBufferTimeQ75() const;
// Updates |delay_history_|.
void UpdateDelayHistory(int iat_delay_ms,
uint32_t timestamp,
@ -92,6 +130,10 @@ class DelayManager {
// and buffer size.
void UpdateEffectiveMinimumDelay();
// Makes sure that |target_level_| is not too large, taking
// |max_packets_in_buffer_| into account. This method is called by Update().
void LimitTargetLevel();
// Makes sure that |delay_ms| is less than maximum delay, if any maximum
// is set. Also, if possible check |delay_ms| to be less than 75% of
// |max_packets_in_buffer_|.
@ -100,21 +142,31 @@ class DelayManager {
bool IsValidBaseMinimumDelay(int delay_ms) const;
bool first_packet_received_;
// TODO(jakobi): set maximum buffer delay instead of number of packets.
const int max_packets_in_buffer_;
const size_t max_packets_in_buffer_; // Capacity of the packet buffer.
std::unique_ptr<Histogram> histogram_;
const int histogram_quantile_;
const TickTimer* tick_timer_;
int base_minimum_delay_ms_;
int effective_minimum_delay_ms_; // Used as lower bound for target delay.
int minimum_delay_ms_; // Externally set minimum delay.
int maximum_delay_ms_; // Externally set maximum allowed delay.
// Provides delay which is used by LimitTargetLevel as lower bound on target
// delay.
int effective_minimum_delay_ms_;
int packet_len_ms_ = 0;
std::unique_ptr<TickTimer::Stopwatch>
packet_iat_stopwatch_; // Time elapsed since last packet.
int target_level_ms_; // Currently preferred buffer level.
uint32_t last_timestamp_; // Timestamp for the last received packet.
// Time elapsed since last packet.
std::unique_ptr<TickTimer::Stopwatch> packet_iat_stopwatch_;
int base_target_level_; // Currently preferred buffer level before peak
// detection and streaming mode (Q0).
// TODO(turajs) change the comment according to the implementation of
// minimum-delay.
int target_level_; // Currently preferred buffer level in (fractions)
// of packets (Q8), before adding any extra delay.
int packet_len_ms_; // Length of audio in each incoming packet [ms].
uint16_t last_seq_no_; // Sequence number for last received packet.
uint32_t last_timestamp_; // Timestamp for the last received packet.
int minimum_delay_ms_; // Externally set minimum delay.
int maximum_delay_ms_; // Externally set maximum allowed delay.
int last_pack_cng_or_dtmf_;
const bool enable_rtx_handling_;
int num_reordered_packets_ = 0; // Number of consecutive reordered packets.
struct PacketDelay {
int iat_delay_ms;

View File

@ -35,15 +35,19 @@ constexpr int kFrameSizeMs = 20;
constexpr int kTsIncrement = kFrameSizeMs * kFs / 1000;
constexpr int kMaxBufferSizeMs = kMaxNumberOfPackets * kFrameSizeMs;
constexpr int kDefaultHistogramQuantile = 1020054733;
constexpr int kNumBuckets = 100;
constexpr int kMaxIat = 64;
constexpr int kForgetFactor = 32745;
} // namespace
using ::testing::_;
using ::testing::Return;
class DelayManagerTest : public ::testing::Test {
protected:
DelayManagerTest();
virtual void SetUp();
void RecreateDelayManager();
void SetPacketAudioLength(int lengt_ms);
absl::optional<int> InsertNextPacket();
void IncreaseTime(int inc_ms);
@ -51,12 +55,15 @@ class DelayManagerTest : public ::testing::Test {
TickTimer tick_timer_;
MockStatisticsCalculator stats_;
MockHistogram* mock_histogram_;
uint16_t seq_no_;
uint32_t ts_;
bool enable_rtx_handling_ = false;
bool use_mock_histogram_ = false;
};
DelayManagerTest::DelayManagerTest()
: dm_(nullptr),
seq_no_(0x1234),
ts_(0x12345678) {}
void DelayManagerTest::SetUp() {
@ -65,19 +72,24 @@ void DelayManagerTest::SetUp() {
void DelayManagerTest::RecreateDelayManager() {
if (use_mock_histogram_) {
mock_histogram_ = new MockHistogram(kNumBuckets, kForgetFactor);
mock_histogram_ = new MockHistogram(kMaxIat, kForgetFactor);
std::unique_ptr<Histogram> histogram(mock_histogram_);
dm_ = std::make_unique<DelayManager>(kMaxNumberOfPackets, kMinDelayMs,
kDefaultHistogramQuantile,
&tick_timer_, std::move(histogram));
dm_ = std::make_unique<DelayManager>(
kMaxNumberOfPackets, kMinDelayMs, kDefaultHistogramQuantile,
enable_rtx_handling_, &tick_timer_, std::move(histogram));
} else {
dm_ = DelayManager::Create(kMaxNumberOfPackets, kMinDelayMs, &tick_timer_);
dm_ = DelayManager::Create(kMaxNumberOfPackets, kMinDelayMs,
enable_rtx_handling_, &tick_timer_);
}
dm_->SetPacketAudioLength(kFrameSizeMs);
}
void DelayManagerTest::SetPacketAudioLength(int lengt_ms) {
dm_->SetPacketAudioLength(lengt_ms);
}
absl::optional<int> DelayManagerTest::InsertNextPacket() {
auto relative_delay = dm_->Update(ts_, kFs);
auto relative_delay = dm_->Update(seq_no_, ts_, kFs);
seq_no_ += 1;
ts_ += kTsIncrement;
return relative_delay;
}
@ -93,66 +105,98 @@ TEST_F(DelayManagerTest, CreateAndDestroy) {
// object.
}
TEST_F(DelayManagerTest, SetPacketAudioLength) {
const int kLengthMs = 30;
EXPECT_EQ(0, dm_->SetPacketAudioLength(kLengthMs));
EXPECT_EQ(-1, dm_->SetPacketAudioLength(-1)); // Illegal parameter value.
}
TEST_F(DelayManagerTest, UpdateNormal) {
SetPacketAudioLength(kFrameSizeMs);
// First packet arrival.
InsertNextPacket();
// Advance time by one frame size.
IncreaseTime(kFrameSizeMs);
// Second packet arrival.
InsertNextPacket();
EXPECT_EQ(20, dm_->TargetDelayMs());
EXPECT_EQ(1 << 8, dm_->TargetLevel()); // In Q8.
EXPECT_EQ(1, dm_->base_target_level());
int lower, higher;
dm_->BufferLimits(&lower, &higher);
// Expect |lower| to be 75% of target level, and |higher| to be target level,
// but also at least 20 ms higher than |lower|, which is the limiting case
// here.
EXPECT_EQ((1 << 8) * 3 / 4, lower);
EXPECT_EQ(lower + (20 << 8) / kFrameSizeMs, higher);
}
TEST_F(DelayManagerTest, UpdateLongInterArrivalTime) {
SetPacketAudioLength(kFrameSizeMs);
// First packet arrival.
InsertNextPacket();
// Advance time by two frame size.
IncreaseTime(2 * kFrameSizeMs);
// Second packet arrival.
InsertNextPacket();
EXPECT_EQ(40, dm_->TargetDelayMs());
EXPECT_EQ(2 << 8, dm_->TargetLevel()); // In Q8.
EXPECT_EQ(2, dm_->base_target_level());
int lower, higher;
dm_->BufferLimits(&lower, &higher);
// Expect |lower| to be 75% of target level, and |higher| to be target level,
// but also at least 20 ms higher than |lower|, which is the limiting case
// here.
EXPECT_EQ((2 << 8) * 3 / 4, lower);
EXPECT_EQ(lower + (20 << 8) / kFrameSizeMs, higher);
}
TEST_F(DelayManagerTest, MaxDelay) {
const int kExpectedTarget = 5 * kFrameSizeMs;
const int kExpectedTarget = 5;
const int kTimeIncrement = kExpectedTarget * kFrameSizeMs;
SetPacketAudioLength(kFrameSizeMs);
// First packet arrival.
InsertNextPacket();
// Second packet arrival.
IncreaseTime(kExpectedTarget);
IncreaseTime(kTimeIncrement);
InsertNextPacket();
// No limit is set.
EXPECT_EQ(kExpectedTarget, dm_->TargetDelayMs());
EXPECT_EQ(kExpectedTarget << 8, dm_->TargetLevel());
const int kMaxDelayMs = 3 * kFrameSizeMs;
int kMaxDelayPackets = kExpectedTarget - 2;
int kMaxDelayMs = kMaxDelayPackets * kFrameSizeMs;
EXPECT_TRUE(dm_->SetMaximumDelay(kMaxDelayMs));
IncreaseTime(kFrameSizeMs);
IncreaseTime(kTimeIncrement);
InsertNextPacket();
EXPECT_EQ(kMaxDelayMs, dm_->TargetDelayMs());
EXPECT_EQ(kMaxDelayPackets << 8, dm_->TargetLevel());
// Target level at least should be one packet.
EXPECT_FALSE(dm_->SetMaximumDelay(kFrameSizeMs - 1));
}
TEST_F(DelayManagerTest, MinDelay) {
const int kExpectedTarget = 5 * kFrameSizeMs;
const int kExpectedTarget = 5;
const int kTimeIncrement = kExpectedTarget * kFrameSizeMs;
SetPacketAudioLength(kFrameSizeMs);
// First packet arrival.
InsertNextPacket();
// Second packet arrival.
IncreaseTime(kExpectedTarget);
IncreaseTime(kTimeIncrement);
InsertNextPacket();
// No limit is applied.
EXPECT_EQ(kExpectedTarget, dm_->TargetDelayMs());
EXPECT_EQ(kExpectedTarget << 8, dm_->TargetLevel());
int kMinDelayMs = 7 * kFrameSizeMs;
int kMinDelayPackets = kExpectedTarget + 2;
int kMinDelayMs = kMinDelayPackets * kFrameSizeMs;
dm_->SetMinimumDelay(kMinDelayMs);
IncreaseTime(kFrameSizeMs);
InsertNextPacket();
EXPECT_EQ(kMinDelayMs, dm_->TargetDelayMs());
EXPECT_EQ(kMinDelayPackets << 8, dm_->TargetLevel());
}
TEST_F(DelayManagerTest, BaseMinimumDelayCheckValidRange) {
SetPacketAudioLength(kFrameSizeMs);
// Base minimum delay should be between [0, 10000] milliseconds.
EXPECT_FALSE(dm_->SetBaseMinimumDelay(-1));
EXPECT_FALSE(dm_->SetBaseMinimumDelay(10001));
@ -163,6 +207,7 @@ TEST_F(DelayManagerTest, BaseMinimumDelayCheckValidRange) {
}
TEST_F(DelayManagerTest, BaseMinimumDelayLowerThanMinimumDelay) {
SetPacketAudioLength(kFrameSizeMs);
constexpr int kBaseMinimumDelayMs = 100;
constexpr int kMinimumDelayMs = 200;
@ -176,6 +221,7 @@ TEST_F(DelayManagerTest, BaseMinimumDelayLowerThanMinimumDelay) {
}
TEST_F(DelayManagerTest, BaseMinimumDelayGreaterThanMinimumDelay) {
SetPacketAudioLength(kFrameSizeMs);
constexpr int kBaseMinimumDelayMs = 70;
constexpr int kMinimumDelayMs = 30;
@ -189,6 +235,7 @@ TEST_F(DelayManagerTest, BaseMinimumDelayGreaterThanMinimumDelay) {
}
TEST_F(DelayManagerTest, BaseMinimumDelayGreaterThanBufferSize) {
SetPacketAudioLength(kFrameSizeMs);
constexpr int kBaseMinimumDelayMs = kMaxBufferSizeMs + 1;
constexpr int kMinimumDelayMs = 12;
constexpr int kMaximumDelayMs = 20;
@ -215,6 +262,7 @@ TEST_F(DelayManagerTest, BaseMinimumDelayGreaterThanBufferSize) {
}
TEST_F(DelayManagerTest, BaseMinimumDelayGreaterThanMaximumDelay) {
SetPacketAudioLength(kFrameSizeMs);
constexpr int kMaximumDelayMs = 400;
constexpr int kBaseMinimumDelayMs = kMaximumDelayMs + 1;
constexpr int kMinimumDelayMs = 20;
@ -232,6 +280,7 @@ TEST_F(DelayManagerTest, BaseMinimumDelayGreaterThanMaximumDelay) {
}
TEST_F(DelayManagerTest, BaseMinimumDelayLowerThanMaxSize) {
SetPacketAudioLength(kFrameSizeMs);
constexpr int kMaximumDelayMs = 400;
constexpr int kBaseMinimumDelayMs = kMaximumDelayMs - 1;
constexpr int kMinimumDelayMs = 20;
@ -252,6 +301,8 @@ TEST_F(DelayManagerTest, MinimumDelayMemorization) {
// minimum delay then minimum delay is still memorized. This allows to
// restore effective minimum delay to memorized minimum delay value when we
// decrease base minimum delay.
SetPacketAudioLength(kFrameSizeMs);
constexpr int kBaseMinimumDelayMsLow = 10;
constexpr int kMinimumDelayMs = 20;
constexpr int kBaseMinimumDelayMsHigh = 30;
@ -272,29 +323,9 @@ TEST_F(DelayManagerTest, MinimumDelayMemorization) {
}
TEST_F(DelayManagerTest, BaseMinimumDelay) {
const int kExpectedTarget = 5 * kFrameSizeMs;
// First packet arrival.
InsertNextPacket();
// Second packet arrival.
IncreaseTime(kExpectedTarget);
InsertNextPacket();
// No limit is applied.
EXPECT_EQ(kExpectedTarget, dm_->TargetDelayMs());
constexpr int kBaseMinimumDelayMs = 7 * kFrameSizeMs;
EXPECT_TRUE(dm_->SetBaseMinimumDelay(kBaseMinimumDelayMs));
EXPECT_EQ(dm_->GetBaseMinimumDelay(), kBaseMinimumDelayMs);
IncreaseTime(kFrameSizeMs);
InsertNextPacket();
EXPECT_EQ(dm_->GetBaseMinimumDelay(), kBaseMinimumDelayMs);
EXPECT_EQ(kBaseMinimumDelayMs, dm_->TargetDelayMs());
}
TEST_F(DelayManagerTest, BaseMinimumDelayAffectsTargetDelay) {
const int kExpectedTarget = 5;
const int kTimeIncrement = kExpectedTarget * kFrameSizeMs;
SetPacketAudioLength(kFrameSizeMs);
// First packet arrival.
InsertNextPacket();
// Second packet arrival.
@ -302,7 +333,31 @@ TEST_F(DelayManagerTest, BaseMinimumDelayAffectsTargetDelay) {
InsertNextPacket();
// No limit is applied.
EXPECT_EQ(kTimeIncrement, dm_->TargetDelayMs());
EXPECT_EQ(kExpectedTarget << 8, dm_->TargetLevel());
constexpr int kBaseMinimumDelayPackets = kExpectedTarget + 2;
constexpr int kBaseMinimumDelayMs = kBaseMinimumDelayPackets * kFrameSizeMs;
EXPECT_TRUE(dm_->SetBaseMinimumDelay(kBaseMinimumDelayMs));
EXPECT_EQ(dm_->GetBaseMinimumDelay(), kBaseMinimumDelayMs);
IncreaseTime(kFrameSizeMs);
InsertNextPacket();
EXPECT_EQ(dm_->GetBaseMinimumDelay(), kBaseMinimumDelayMs);
EXPECT_EQ(kBaseMinimumDelayPackets << 8, dm_->TargetLevel());
}
TEST_F(DelayManagerTest, BaseMinimumDealyAffectTargetLevel) {
const int kExpectedTarget = 5;
const int kTimeIncrement = kExpectedTarget * kFrameSizeMs;
SetPacketAudioLength(kFrameSizeMs);
// First packet arrival.
InsertNextPacket();
// Second packet arrival.
IncreaseTime(kTimeIncrement);
InsertNextPacket();
// No limit is applied.
EXPECT_EQ(kExpectedTarget << 8, dm_->TargetLevel());
// Minimum delay is lower than base minimum delay, that is why base minimum
// delay is used to calculate target level.
@ -320,19 +375,88 @@ TEST_F(DelayManagerTest, BaseMinimumDelayAffectsTargetDelay) {
IncreaseTime(kFrameSizeMs);
InsertNextPacket();
EXPECT_EQ(dm_->GetBaseMinimumDelay(), kBaseMinimumDelayMs);
EXPECT_EQ(kBaseMinimumDelayMs, dm_->TargetDelayMs());
EXPECT_EQ(kBaseMinimumDelayPackets << 8, dm_->TargetLevel());
}
TEST_F(DelayManagerTest, EnableRtxHandling) {
enable_rtx_handling_ = true;
use_mock_histogram_ = true;
RecreateDelayManager();
EXPECT_TRUE(mock_histogram_);
// Insert first packet.
SetPacketAudioLength(kFrameSizeMs);
InsertNextPacket();
// Insert reordered packet.
EXPECT_CALL(*mock_histogram_, Add(2));
dm_->Update(seq_no_ - 3, ts_ - 3 * kFrameSizeMs, kFs);
// Insert another reordered packet.
EXPECT_CALL(*mock_histogram_, Add(1));
dm_->Update(seq_no_ - 2, ts_ - 2 * kFrameSizeMs, kFs);
// Insert the next packet in order and verify that the inter-arrival time is
// estimated correctly.
IncreaseTime(kFrameSizeMs);
EXPECT_CALL(*mock_histogram_, Add(0));
InsertNextPacket();
}
// Tests that skipped sequence numbers (simulating empty packets) are handled
// correctly.
// TODO(jakobi): Make delay manager independent of sequence numbers.
TEST_F(DelayManagerTest, EmptyPacketsReported) {
SetPacketAudioLength(kFrameSizeMs);
// First packet arrival.
InsertNextPacket();
// Advance time by one frame size.
IncreaseTime(kFrameSizeMs);
// Advance the sequence number by 5, simulating that 5 empty packets were
// received, but never inserted.
seq_no_ += 10;
for (int j = 0; j < 10; ++j) {
dm_->RegisterEmptyPacket();
}
// Second packet arrival.
InsertNextPacket();
EXPECT_EQ(1 << 8, dm_->TargetLevel()); // In Q8.
}
// Same as above, but do not call RegisterEmptyPacket. Target level stays the
// same.
TEST_F(DelayManagerTest, EmptyPacketsNotReported) {
SetPacketAudioLength(kFrameSizeMs);
// First packet arrival.
InsertNextPacket();
// Advance time by one frame size.
IncreaseTime(kFrameSizeMs);
// Advance the sequence number by 10, simulating that 10 empty packets were
// received, but never inserted.
seq_no_ += 10;
// Second packet arrival.
InsertNextPacket();
EXPECT_EQ(1 << 8, dm_->TargetLevel()); // In Q8.
}
TEST_F(DelayManagerTest, Failures) {
// Wrong sample rate.
EXPECT_EQ(absl::nullopt, dm_->Update(0, -1));
EXPECT_EQ(absl::nullopt, dm_->Update(0, 0, -1));
// Wrong packet size.
EXPECT_EQ(-1, dm_->SetPacketAudioLength(0));
EXPECT_EQ(-1, dm_->SetPacketAudioLength(-1));
// Minimum delay higher than a maximum delay is not accepted.
EXPECT_TRUE(dm_->SetMaximumDelay(20));
EXPECT_FALSE(dm_->SetMinimumDelay(40));
EXPECT_TRUE(dm_->SetMaximumDelay(10));
EXPECT_FALSE(dm_->SetMinimumDelay(20));
// Maximum delay less than minimum delay is not accepted.
EXPECT_TRUE(dm_->SetMaximumDelay(100));
@ -386,6 +510,7 @@ TEST_F(DelayManagerTest, RelativeArrivalDelay) {
use_mock_histogram_ = true;
RecreateDelayManager();
SetPacketAudioLength(kFrameSizeMs);
InsertNextPacket();
IncreaseTime(kFrameSizeMs);
@ -394,20 +519,21 @@ TEST_F(DelayManagerTest, RelativeArrivalDelay) {
IncreaseTime(2 * kFrameSizeMs);
EXPECT_CALL(*mock_histogram_, Add(1)); // 20ms delayed.
dm_->Update(ts_, kFs);
dm_->Update(seq_no_, ts_, kFs);
IncreaseTime(2 * kFrameSizeMs);
EXPECT_CALL(*mock_histogram_, Add(2)); // 40ms delayed.
dm_->Update(ts_ + kTsIncrement, kFs);
dm_->Update(seq_no_ + 1, ts_ + kTsIncrement, kFs);
EXPECT_CALL(*mock_histogram_, Add(1)); // Reordered, 20ms delayed.
dm_->Update(ts_, kFs);
dm_->Update(seq_no_, ts_, kFs);
}
TEST_F(DelayManagerTest, MaxDelayHistory) {
use_mock_histogram_ = true;
RecreateDelayManager();
SetPacketAudioLength(kFrameSizeMs);
InsertNextPacket();
// Insert 20 ms iat delay in the delay history.
@ -421,10 +547,11 @@ TEST_F(DelayManagerTest, MaxDelayHistory) {
IncreaseTime(kMaxHistoryMs + kFrameSizeMs);
ts_ += kFs * kMaxHistoryMs / 1000;
EXPECT_CALL(*mock_histogram_, Add(0)); // Not delayed.
dm_->Update(ts_, kFs);
dm_->Update(seq_no_, ts_, kFs);
}
TEST_F(DelayManagerTest, RelativeArrivalDelayStatistic) {
SetPacketAudioLength(kFrameSizeMs);
EXPECT_EQ(absl::nullopt, InsertNextPacket());
IncreaseTime(kFrameSizeMs);
EXPECT_EQ(0, InsertNextPacket());
@ -433,4 +560,38 @@ TEST_F(DelayManagerTest, RelativeArrivalDelayStatistic) {
EXPECT_EQ(20, InsertNextPacket());
}
TEST_F(DelayManagerTest, DecelerationTargetLevelOffset) {
SetPacketAudioLength(kFrameSizeMs);
// Deceleration target level offset follows the value hardcoded in
// delay_manager.cc.
constexpr int kDecelerationTargetLevelOffsetMs = 85 << 8; // In Q8.
// Border value where |x * 3/4 = target_level - x|.
constexpr int kBoarderTargetLevel = kDecelerationTargetLevelOffsetMs * 4;
{
// Test that for a low target level, default behaviour is intact.
const int target_level_ms = kBoarderTargetLevel / kFrameSizeMs - 1;
int lower, higher; // In Q8.
dm_->BufferLimits(target_level_ms, &lower, &higher);
// Default behaviour of taking 75% of target level.
EXPECT_EQ(target_level_ms * 3 / 4, lower);
EXPECT_EQ(target_level_ms, higher);
}
{
// Test that for the high target level, |lower| is below target level by
// fixed |kOffset|.
const int target_level_ms = kBoarderTargetLevel / kFrameSizeMs + 1;
int lower, higher; // In Q8.
dm_->BufferLimits(target_level_ms, &lower, &higher);
EXPECT_EQ(target_level_ms - kDecelerationTargetLevelOffsetMs / kFrameSizeMs,
lower);
EXPECT_EQ(target_level_ms, higher);
}
}
} // namespace webrtc

View File

@ -804,10 +804,8 @@ TEST_P(NetEqImplTestSampleRateParameter,
EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output, &muted));
}
// Insert a few packets to avoid postpone decoding after expand.
for (size_t i = 0; i < 5; ++i) {
insert_packet();
}
// Insert one more packet.
insert_packet();
// Pull audio until the newly inserted packet is decoded and the PLC ends.
while (output.speech_type_ != AudioFrame::kNormalSpeech) {
@ -883,10 +881,8 @@ TEST_P(NetEqImplTestSampleRateParameter, AudioInterruptionLogged) {
EXPECT_NE(AudioFrame::kNormalSpeech, output.speech_type_);
}
// Insert a few packets to avoid postpone decoding after expand.
for (size_t i = 0; i < 5; ++i) {
insert_packet();
}
// Insert one more packet.
insert_packet();
// Pull audio until the newly inserted packet is decoded and the PLC ends.
while (output.speech_type_ != AudioFrame::kNormalSpeech) {
@ -1303,7 +1299,7 @@ TEST_F(NetEqImplTest, DecodingError) {
SdpAudioFormat("L16", 8000, 1)));
// Insert packets.
for (int i = 0; i < 20; ++i) {
for (int i = 0; i < 6; ++i) {
rtp_header.sequenceNumber += 1;
rtp_header.timestamp += kFrameLengthSamples;
EXPECT_EQ(NetEq::kOK, neteq_->InsertPacket(rtp_header, payload));

View File

@ -84,16 +84,16 @@ TEST_F(NetEqDecodingTest, MAYBE_TestBitExactness) {
webrtc::test::ResourcePath("audio_coding/neteq_universal_new", "rtp");
const std::string output_checksum =
PlatformChecksum("68ec266d2d152dfc0d938484e7936f6af4f803e3",
"1c243feb35e3e9ab37039eddf5b3c3ecfca3c60c", "not used",
"68ec266d2d152dfc0d938484e7936f6af4f803e3",
"f68c546a43bb25743297c9c0c9027e8424b8e10b");
PlatformChecksum("6ae9f643dc3e5f3452d28a772eef7e00e74158bc",
"f4374430e870d66268c1b8e22fb700eb072d567e", "not used",
"6ae9f643dc3e5f3452d28a772eef7e00e74158bc",
"8d73c98645917cdeaaa01c20cf095ccc5a10b2b5");
const std::string network_stats_checksum =
PlatformChecksum("2a5516cdc1c6af9f1d9d3c2f95ed292f509311c7",
"e96a7f081ebc111f49c7373d3728274057012ae9", "not used",
"2a5516cdc1c6af9f1d9d3c2f95ed292f509311c7",
"2a5516cdc1c6af9f1d9d3c2f95ed292f509311c7");
PlatformChecksum("8e50f528f245b7957db20ab406a72d81be60f5f4",
"4260b22ea6d2723b2d573e50d2c1476680c7fa4c", "not used",
"8e50f528f245b7957db20ab406a72d81be60f5f4",
"8e50f528f245b7957db20ab406a72d81be60f5f4");
DecodeAndCompare(input_rtp_file, output_checksum, network_stats_checksum,
absl::GetFlag(FLAGS_gen_ref));
@ -113,13 +113,13 @@ TEST_F(NetEqDecodingTest, MAYBE_TestOpusBitExactness) {
"554ad4133934e3920f97575579a46f674683d77c"
"|de316e2bfb15192edb820fe5fb579d11ff5a524b";
const std::string output_checksum = PlatformChecksum(
maybe_sse, "b3fac4ad4f6ea384aff676ee1ea816bd70415490",
"373ccd99c147cd3fcef0e7dcad6f87d0f8e5a1c0", maybe_sse, maybe_sse);
maybe_sse, "459c356a0ef245ddff381f7d82d205d426ef2002",
"625055e5eb0e6de2c9d170b4494eadc5afab08c8", maybe_sse, maybe_sse);
const std::string network_stats_checksum =
PlatformChecksum("ec29e047b019a86ec06e2c40643143dc1975c69f",
"ce6f519bc1220b003944ac5d9db077665a06834e",
"abb686d3ac6fac0001ca8d45a6ca6f5aefb2f9d6",
"0c24649824eb7147d4891b0767e86e732dd6ecc8",
"10f3e0b66c6947f78d60301454f2841033a6fcc0",
"ec29e047b019a86ec06e2c40643143dc1975c69f",
"ec29e047b019a86ec06e2c40643143dc1975c69f");
@ -138,14 +138,14 @@ TEST_F(NetEqDecodingTest, MAYBE_TestOpusDtxBitExactness) {
webrtc::test::ResourcePath("audio_coding/neteq_opus_dtx", "rtp");
const std::string maybe_sse =
"0fb0a3d6b3758ca6e108368bb777cd38d0a865af"
"|79cfb99a21338ba977eb0e15eb8464e2db9436f8";
"df5d1d3019bf3764829b84f4fb315721f4adde29"
"|5935d2fad14a69a8b61dbc8e6f2d37c8c0814925";
const std::string output_checksum = PlatformChecksum(
maybe_sse, "b6632690f8d7c2340c838df2821fc014f1cc8360",
"f890b9eb9bc5ab8313489230726b297f6a0825af", maybe_sse, maybe_sse);
maybe_sse, "551df04e8f45cd99eff28503edf0cf92974898ac",
"709a3f0f380393d3a67bace10e2265b90a6ebbeb", maybe_sse, maybe_sse);
const std::string network_stats_checksum =
"18983bb67a57628c604dbdefa99574c6e0c5bb48";
"80f5283ac71b27596204210152927666c1732de4";
DecodeAndCompare(input_rtp_file, output_checksum, network_stats_checksum,
absl::GetFlag(FLAGS_gen_ref));
@ -737,10 +737,8 @@ TEST_F(NetEqDecodingTestWithMutedState, MutedStateOldPacket) {
GetAudioUntilMuted();
EXPECT_NE(AudioFrame::kNormalSpeech, out_frame_.speech_type_);
// Insert a few packets which are older than the first packet.
for (int i = 0; i < 5; ++i) {
InsertPacket(kSamples * (i - 1000));
}
// Insert packet which is older than the first packet.
InsertPacket(kSamples * (counter_ - 1000));
EXPECT_FALSE(GetAudioReturnMuted());
EXPECT_EQ(AudioFrame::kNormalSpeech, out_frame_.speech_type_);
}
@ -855,11 +853,9 @@ TEST_F(NetEqDecodingTestTwoInstances, CompareMutedStateOnOff) {
// Insert new data. Timestamp is corrected for the time elapsed since the last
// packet.
for (int i = 0; i < 5; ++i) {
PopulateRtpInfo(0, kSamples * 1000 + kSamples * i, &rtp_info);
EXPECT_EQ(0, neteq_->InsertPacket(rtp_info, payload));
EXPECT_EQ(0, neteq2_->InsertPacket(rtp_info, payload));
}
PopulateRtpInfo(0, kSamples * 1000, &rtp_info);
EXPECT_EQ(0, neteq_->InsertPacket(rtp_info, payload));
EXPECT_EQ(0, neteq2_->InsertPacket(rtp_info, payload));
int counter = 0;
while (out_frame1.speech_type_ != AudioFrame::kNormalSpeech) {
@ -1268,7 +1264,7 @@ TEST(NetEqOutputDelayTest, RunTestWithFieldTrial) {
// The base delay values are taken from the resuts of the non-delayed case in
// NetEqOutputDelayTest.RunTest above.
EXPECT_EQ(20 + kExpectedDelayMs, result.target_delay_ms);
EXPECT_EQ(10 + kExpectedDelayMs, result.target_delay_ms);
EXPECT_EQ(24 + kExpectedDelayMs, result.filtered_current_delay_ms);
}
@ -1283,7 +1279,7 @@ TEST(NetEqOutputDelayTest, RunTestWithFieldTrialOddValue) {
// The base delay values are taken from the resuts of the non-delayed case in
// NetEqOutputDelayTest.RunTest above.
EXPECT_EQ(20 + kRoundedDelayMs, result.target_delay_ms);
EXPECT_EQ(10 + kRoundedDelayMs, result.target_delay_ms);
EXPECT_EQ(24 + kRoundedDelayMs, result.filtered_current_delay_ms);
}