Remove inter-arrival delay mode from DelayManager.
Also remove the delay peak detector which is no longer used. This should be a no-op since relative arrival delay mode is used by default. Bug: webrtc:10333 Change-Id: Ifa326b762d52f16f9dc5f3da2874139faf1022da Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/164462 Reviewed-by: Ivo Creusen <ivoc@webrtc.org> Commit-Queue: Jakob Ivarsson <jakobi@webrtc.org> Cr-Commit-Position: refs/heads/master@{#30179}
This commit is contained in:
parent
57218b4e22
commit
bd5874accf
@ -951,8 +951,6 @@ rtc_library("neteq") {
|
||||
"neteq/decoder_database.h",
|
||||
"neteq/delay_manager.cc",
|
||||
"neteq/delay_manager.h",
|
||||
"neteq/delay_peak_detector.cc",
|
||||
"neteq/delay_peak_detector.h",
|
||||
"neteq/dsp_helper.cc",
|
||||
"neteq/dsp_helper.h",
|
||||
"neteq/dtmf_buffer.cc",
|
||||
@ -2027,7 +2025,6 @@ if (rtc_include_tests) {
|
||||
"neteq/decision_logic_unittest.cc",
|
||||
"neteq/decoder_database_unittest.cc",
|
||||
"neteq/delay_manager_unittest.cc",
|
||||
"neteq/delay_peak_detector_unittest.cc",
|
||||
"neteq/dsp_helper_unittest.cc",
|
||||
"neteq/dtmf_buffer_unittest.cc",
|
||||
"neteq/dtmf_tone_generator_unittest.cc",
|
||||
@ -2035,7 +2032,6 @@ if (rtc_include_tests) {
|
||||
"neteq/histogram_unittest.cc",
|
||||
"neteq/merge_unittest.cc",
|
||||
"neteq/mock/mock_decoder_database.h",
|
||||
"neteq/mock/mock_delay_peak_detector.h",
|
||||
"neteq/mock/mock_dtmf_buffer.h",
|
||||
"neteq/mock/mock_dtmf_tone_generator.h",
|
||||
"neteq/mock/mock_expand.h",
|
||||
|
||||
@ -33,11 +33,9 @@ constexpr int kDefaultTargetLevelWindowMs = 100;
|
||||
namespace webrtc {
|
||||
|
||||
DecisionLogic::DecisionLogic(NetEqController::Config config)
|
||||
: delay_peak_detector_(config.tick_timer, config.enable_rtx_handling),
|
||||
delay_manager_(DelayManager::Create(config.max_packets_in_buffer,
|
||||
: delay_manager_(DelayManager::Create(config.max_packets_in_buffer,
|
||||
config.base_min_delay_ms,
|
||||
config.enable_rtx_handling,
|
||||
&delay_peak_detector_,
|
||||
config.tick_timer)),
|
||||
tick_timer_(config.tick_timer),
|
||||
disallow_time_stretching_(!config.allow_time_stretching),
|
||||
|
||||
@ -16,7 +16,6 @@
|
||||
#include "api/neteq/tick_timer.h"
|
||||
#include "modules/audio_coding/neteq/buffer_level_filter.h"
|
||||
#include "modules/audio_coding/neteq/delay_manager.h"
|
||||
#include "modules/audio_coding/neteq/delay_peak_detector.h"
|
||||
#include "rtc_base/constructor_magic.h"
|
||||
#include "rtc_base/experiments/field_trial_parser.h"
|
||||
|
||||
@ -97,7 +96,7 @@ class DecisionLogic : public NetEqController {
|
||||
int GetBaseMinimumDelay() const override {
|
||||
return delay_manager_->GetBaseMinimumDelay();
|
||||
}
|
||||
bool PeakFound() const override { return delay_manager_->PeakFound(); }
|
||||
bool PeakFound() const override { return false; }
|
||||
|
||||
int GetFilteredBufferLevel() const override {
|
||||
return buffer_level_filter_.filtered_current_level();
|
||||
@ -172,7 +171,6 @@ class DecisionLogic : public NetEqController {
|
||||
// Checks if num_consecutive_expands_ >= kMaxWaitForPacket.
|
||||
bool MaxWaitForPacket() const;
|
||||
|
||||
DelayPeakDetector delay_peak_detector_;
|
||||
std::unique_ptr<DelayManager> delay_manager_;
|
||||
BufferLevelFilter buffer_level_filter_;
|
||||
const TickTimer* tick_timer_;
|
||||
|
||||
@ -17,7 +17,6 @@
|
||||
#include "modules/audio_coding/neteq/buffer_level_filter.h"
|
||||
#include "modules/audio_coding/neteq/decoder_database.h"
|
||||
#include "modules/audio_coding/neteq/delay_manager.h"
|
||||
#include "modules/audio_coding/neteq/delay_peak_detector.h"
|
||||
#include "modules/audio_coding/neteq/packet_buffer.h"
|
||||
#include "modules/audio_coding/neteq/statistics_calculator.h"
|
||||
#include "test/gtest.h"
|
||||
|
||||
@ -19,7 +19,6 @@
|
||||
#include <numeric>
|
||||
#include <string>
|
||||
|
||||
#include "modules/audio_coding/neteq/delay_peak_detector.h"
|
||||
#include "modules/audio_coding/neteq/histogram.h"
|
||||
#include "modules/include/module_common_types_public.h"
|
||||
#include "rtc_base/checks.h"
|
||||
@ -103,16 +102,13 @@ namespace webrtc {
|
||||
DelayManager::DelayManager(size_t max_packets_in_buffer,
|
||||
int base_minimum_delay_ms,
|
||||
int histogram_quantile,
|
||||
HistogramMode histogram_mode,
|
||||
bool enable_rtx_handling,
|
||||
DelayPeakDetector* peak_detector,
|
||||
const TickTimer* tick_timer,
|
||||
std::unique_ptr<Histogram> histogram)
|
||||
: first_packet_received_(false),
|
||||
max_packets_in_buffer_(max_packets_in_buffer),
|
||||
histogram_(std::move(histogram)),
|
||||
histogram_quantile_(histogram_quantile),
|
||||
histogram_mode_(histogram_mode),
|
||||
tick_timer_(tick_timer),
|
||||
base_minimum_delay_ms_(base_minimum_delay_ms),
|
||||
effective_minimum_delay_ms_(base_minimum_delay_ms),
|
||||
@ -123,13 +119,9 @@ DelayManager::DelayManager(size_t max_packets_in_buffer,
|
||||
last_timestamp_(0),
|
||||
minimum_delay_ms_(0),
|
||||
maximum_delay_ms_(0),
|
||||
peak_detector_(*peak_detector),
|
||||
last_pack_cng_or_dtmf_(1),
|
||||
frame_length_change_experiment_(
|
||||
field_trial::IsEnabled("WebRTC-Audio-NetEqFramelengthExperiment")),
|
||||
enable_rtx_handling_(enable_rtx_handling),
|
||||
extra_delay_ms_(GetExtraDelayMs()) {
|
||||
assert(peak_detector); // Should never be NULL.
|
||||
RTC_CHECK(histogram_);
|
||||
RTC_DCHECK_GE(base_minimum_delay_ms_, 0);
|
||||
|
||||
@ -140,16 +132,14 @@ std::unique_ptr<DelayManager> DelayManager::Create(
|
||||
size_t max_packets_in_buffer,
|
||||
int base_minimum_delay_ms,
|
||||
bool enable_rtx_handling,
|
||||
DelayPeakDetector* peak_detector,
|
||||
const TickTimer* tick_timer) {
|
||||
const HistogramMode mode = RELATIVE_ARRIVAL_DELAY;
|
||||
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, quantile, mode,
|
||||
enable_rtx_handling, peak_detector, tick_timer, std::move(histogram));
|
||||
max_packets_in_buffer, base_minimum_delay_ms, quantile,
|
||||
enable_rtx_handling, tick_timer, std::move(histogram));
|
||||
}
|
||||
|
||||
DelayManager::~DelayManager() {}
|
||||
@ -193,19 +183,16 @@ absl::optional<int> DelayManager::Update(uint16_t sequence_number,
|
||||
// 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();
|
||||
int iat_packets = iat_ms / packet_len_ms;
|
||||
// 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_packets -= packet_offset;
|
||||
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_packets += packet_offset;
|
||||
iat_ms += packet_offset * packet_len_ms;
|
||||
reordered = true;
|
||||
}
|
||||
@ -218,25 +205,13 @@ absl::optional<int> DelayManager::Update(uint16_t sequence_number,
|
||||
relative_delay = CalculateRelativePacketArrivalDelay();
|
||||
}
|
||||
|
||||
switch (histogram_mode_) {
|
||||
case RELATIVE_ARRIVAL_DELAY: {
|
||||
const int index = relative_delay.value() / kBucketSizeMs;
|
||||
if (index < histogram_->NumBuckets()) {
|
||||
// Maximum delay to register is 2000 ms.
|
||||
histogram_->Add(index);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case INTER_ARRIVAL_TIME: {
|
||||
// Saturate IAT between 0 and maximum value.
|
||||
iat_packets =
|
||||
std::max(std::min(iat_packets, histogram_->NumBuckets() - 1), 0);
|
||||
histogram_->Add(iat_packets);
|
||||
break;
|
||||
}
|
||||
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(iat_packets, reordered);
|
||||
target_level_ = CalculateTargetLevel();
|
||||
|
||||
LimitTargetLevel();
|
||||
} // End if (packet_len_ms > 0).
|
||||
@ -310,32 +285,15 @@ void DelayManager::LimitTargetLevel() {
|
||||
target_level_ = std::max(target_level_, 1 << 8);
|
||||
}
|
||||
|
||||
int DelayManager::CalculateTargetLevel(int iat_packets, bool reordered) {
|
||||
int DelayManager::CalculateTargetLevel() {
|
||||
int limit_probability = histogram_quantile_;
|
||||
|
||||
int bucket_index = histogram_->Quantile(limit_probability);
|
||||
int target_level;
|
||||
switch (histogram_mode_) {
|
||||
case RELATIVE_ARRIVAL_DELAY: {
|
||||
target_level = 1;
|
||||
if (packet_len_ms_ > 0) {
|
||||
target_level += bucket_index * kBucketSizeMs / packet_len_ms_;
|
||||
}
|
||||
base_target_level_ = target_level;
|
||||
break;
|
||||
}
|
||||
case INTER_ARRIVAL_TIME: {
|
||||
target_level = std::max(bucket_index, 1);
|
||||
base_target_level_ = target_level;
|
||||
// Update detector for delay peaks.
|
||||
bool delay_peak_found =
|
||||
peak_detector_.Update(iat_packets, reordered, target_level);
|
||||
if (delay_peak_found) {
|
||||
target_level = std::max(target_level, peak_detector_.MaxPeakHeight());
|
||||
}
|
||||
break;
|
||||
}
|
||||
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);
|
||||
@ -353,14 +311,8 @@ int DelayManager::SetPacketAudioLength(int length_ms) {
|
||||
RTC_LOG_F(LS_ERROR) << "length_ms = " << length_ms;
|
||||
return -1;
|
||||
}
|
||||
if (histogram_mode_ == INTER_ARRIVAL_TIME &&
|
||||
frame_length_change_experiment_ && packet_len_ms_ != length_ms &&
|
||||
packet_len_ms_ > 0) {
|
||||
histogram_->Scale(packet_len_ms_, length_ms);
|
||||
}
|
||||
|
||||
packet_len_ms_ = length_ms;
|
||||
peak_detector_.SetPacketAudioLength(packet_len_ms_);
|
||||
packet_iat_stopwatch_ = tick_timer_->GetNewStopwatch();
|
||||
last_pack_cng_or_dtmf_ = 1; // TODO(hlundin): Legacy. Remove?
|
||||
return 0;
|
||||
@ -368,7 +320,6 @@ int DelayManager::SetPacketAudioLength(int length_ms) {
|
||||
|
||||
void DelayManager::Reset() {
|
||||
packet_len_ms_ = 0; // Packet size unknown.
|
||||
peak_detector_.Reset();
|
||||
histogram_->Reset();
|
||||
delay_history_.clear();
|
||||
base_target_level_ = 4;
|
||||
@ -377,10 +328,6 @@ void DelayManager::Reset() {
|
||||
last_pack_cng_or_dtmf_ = 1;
|
||||
}
|
||||
|
||||
bool DelayManager::PeakFound() const {
|
||||
return peak_detector_.peak_found();
|
||||
}
|
||||
|
||||
void DelayManager::ResetPacketIatCount() {
|
||||
packet_iat_stopwatch_ = tick_timer_->GetNewStopwatch();
|
||||
}
|
||||
|
||||
@ -23,22 +23,12 @@
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// Forward declaration.
|
||||
class DelayPeakDetector;
|
||||
|
||||
class DelayManager {
|
||||
public:
|
||||
enum HistogramMode {
|
||||
INTER_ARRIVAL_TIME,
|
||||
RELATIVE_ARRIVAL_DELAY,
|
||||
};
|
||||
|
||||
DelayManager(size_t max_packets_in_buffer,
|
||||
int base_minimum_delay_ms,
|
||||
int histogram_quantile,
|
||||
HistogramMode histogram_mode,
|
||||
bool enable_rtx_handling,
|
||||
DelayPeakDetector* peak_detector,
|
||||
const TickTimer* tick_timer,
|
||||
std::unique_ptr<Histogram> histogram);
|
||||
|
||||
@ -50,7 +40,6 @@ class DelayManager {
|
||||
static std::unique_ptr<DelayManager> Create(size_t max_packets_in_buffer,
|
||||
int base_minimum_delay_ms,
|
||||
bool enable_rtx_handling,
|
||||
DelayPeakDetector* peak_detector,
|
||||
const TickTimer* tick_timer);
|
||||
|
||||
virtual ~DelayManager();
|
||||
@ -68,7 +57,7 @@ class DelayManager {
|
||||
// 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(int iat_packets, bool reordered);
|
||||
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
|
||||
@ -78,11 +67,6 @@ class DelayManager {
|
||||
// Resets the DelayManager and the associated DelayPeakDetector.
|
||||
virtual void Reset();
|
||||
|
||||
// Returns true if peak-mode is active. That is, delay peaks were observed
|
||||
// recently. This method simply asks for the same information from the
|
||||
// DelayPeakDetector object.
|
||||
virtual bool PeakFound() const;
|
||||
|
||||
// Reset the inter-arrival time counter to 0.
|
||||
virtual void ResetPacketIatCount();
|
||||
|
||||
@ -122,7 +106,6 @@ class DelayManager {
|
||||
}
|
||||
|
||||
// These accessors are only intended for testing purposes.
|
||||
HistogramMode histogram_mode() const { return histogram_mode_; }
|
||||
int histogram_quantile() const { return histogram_quantile_; }
|
||||
Histogram* histogram() const { return histogram_.get(); }
|
||||
|
||||
@ -163,7 +146,6 @@ class DelayManager {
|
||||
const size_t max_packets_in_buffer_; // Capacity of the packet buffer.
|
||||
std::unique_ptr<Histogram> histogram_;
|
||||
const int histogram_quantile_;
|
||||
const HistogramMode histogram_mode_;
|
||||
const TickTimer* tick_timer_;
|
||||
int base_minimum_delay_ms_;
|
||||
// Provides delay which is used by LimitTargetLevel as lower bound on target
|
||||
@ -183,9 +165,7 @@ class DelayManager {
|
||||
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.
|
||||
DelayPeakDetector& peak_detector_;
|
||||
int last_pack_cng_or_dtmf_;
|
||||
const bool frame_length_change_experiment_;
|
||||
const bool enable_rtx_handling_;
|
||||
int num_reordered_packets_ = 0; // Number of consecutive reordered packets.
|
||||
|
||||
|
||||
@ -17,7 +17,6 @@
|
||||
#include <memory>
|
||||
|
||||
#include "modules/audio_coding/neteq/histogram.h"
|
||||
#include "modules/audio_coding/neteq/mock/mock_delay_peak_detector.h"
|
||||
#include "modules/audio_coding/neteq/mock/mock_histogram.h"
|
||||
#include "modules/audio_coding/neteq/mock/mock_statistics_calculator.h"
|
||||
#include "rtc_base/checks.h"
|
||||
@ -47,7 +46,6 @@ class DelayManagerTest : public ::testing::Test {
|
||||
protected:
|
||||
DelayManagerTest();
|
||||
virtual void SetUp();
|
||||
virtual void TearDown();
|
||||
void RecreateDelayManager();
|
||||
void SetPacketAudioLength(int lengt_ms);
|
||||
absl::optional<int> InsertNextPacket();
|
||||
@ -56,19 +54,15 @@ class DelayManagerTest : public ::testing::Test {
|
||||
std::unique_ptr<DelayManager> dm_;
|
||||
TickTimer tick_timer_;
|
||||
MockStatisticsCalculator stats_;
|
||||
MockDelayPeakDetector detector_;
|
||||
MockHistogram* mock_histogram_;
|
||||
uint16_t seq_no_;
|
||||
uint32_t ts_;
|
||||
bool enable_rtx_handling_ = false;
|
||||
bool use_mock_histogram_ = false;
|
||||
DelayManager::HistogramMode histogram_mode_ =
|
||||
DelayManager::HistogramMode::RELATIVE_ARRIVAL_DELAY;
|
||||
};
|
||||
|
||||
DelayManagerTest::DelayManagerTest()
|
||||
: dm_(nullptr),
|
||||
detector_(&tick_timer_, false),
|
||||
seq_no_(0x1234),
|
||||
ts_(0x12345678) {}
|
||||
|
||||
@ -77,22 +71,19 @@ void DelayManagerTest::SetUp() {
|
||||
}
|
||||
|
||||
void DelayManagerTest::RecreateDelayManager() {
|
||||
EXPECT_CALL(detector_, Reset()).Times(1);
|
||||
if (use_mock_histogram_) {
|
||||
mock_histogram_ = new MockHistogram(kMaxIat, kForgetFactor);
|
||||
std::unique_ptr<Histogram> histogram(mock_histogram_);
|
||||
dm_ = std::make_unique<DelayManager>(
|
||||
kMaxNumberOfPackets, kMinDelayMs, kDefaultHistogramQuantile,
|
||||
histogram_mode_, enable_rtx_handling_, &detector_, &tick_timer_,
|
||||
std::move(histogram));
|
||||
enable_rtx_handling_, &tick_timer_, std::move(histogram));
|
||||
} else {
|
||||
dm_ = DelayManager::Create(kMaxNumberOfPackets, kMinDelayMs,
|
||||
enable_rtx_handling_, &detector_, &tick_timer_);
|
||||
enable_rtx_handling_, &tick_timer_);
|
||||
}
|
||||
}
|
||||
|
||||
void DelayManagerTest::SetPacketAudioLength(int lengt_ms) {
|
||||
EXPECT_CALL(detector_, SetPacketAudioLength(lengt_ms));
|
||||
dm_->SetPacketAudioLength(lengt_ms);
|
||||
}
|
||||
|
||||
@ -109,10 +100,6 @@ void DelayManagerTest::IncreaseTime(int inc_ms) {
|
||||
}
|
||||
}
|
||||
|
||||
void DelayManagerTest::TearDown() {
|
||||
EXPECT_CALL(detector_, Die());
|
||||
}
|
||||
|
||||
TEST_F(DelayManagerTest, CreateAndDestroy) {
|
||||
// Nothing to do here. The test fixture creates and destroys the DelayManager
|
||||
// object.
|
||||
@ -120,23 +107,10 @@ TEST_F(DelayManagerTest, CreateAndDestroy) {
|
||||
|
||||
TEST_F(DelayManagerTest, SetPacketAudioLength) {
|
||||
const int kLengthMs = 30;
|
||||
// Expect DelayManager to pass on the new length to the detector object.
|
||||
EXPECT_CALL(detector_, SetPacketAudioLength(kLengthMs)).Times(1);
|
||||
EXPECT_EQ(0, dm_->SetPacketAudioLength(kLengthMs));
|
||||
EXPECT_EQ(-1, dm_->SetPacketAudioLength(-1)); // Illegal parameter value.
|
||||
}
|
||||
|
||||
TEST_F(DelayManagerTest, PeakFound) {
|
||||
// Expect DelayManager to pass on the question to the detector.
|
||||
// Call twice, and let the detector return true the first time and false the
|
||||
// second time.
|
||||
EXPECT_CALL(detector_, peak_found())
|
||||
.WillOnce(Return(true))
|
||||
.WillOnce(Return(false));
|
||||
EXPECT_TRUE(dm_->PeakFound());
|
||||
EXPECT_FALSE(dm_->PeakFound());
|
||||
}
|
||||
|
||||
TEST_F(DelayManagerTest, UpdateNormal) {
|
||||
SetPacketAudioLength(kFrameSizeMs);
|
||||
// First packet arrival.
|
||||
@ -495,8 +469,6 @@ TEST_F(DelayManagerTest, DelayHistogramFieldTrial) {
|
||||
test::ScopedFieldTrials field_trial(
|
||||
"WebRTC-Audio-NetEqDelayHistogram/Enabled-96-0.998/");
|
||||
RecreateDelayManager();
|
||||
EXPECT_EQ(DelayManager::HistogramMode::RELATIVE_ARRIVAL_DELAY,
|
||||
dm_->histogram_mode());
|
||||
EXPECT_EQ(1030792151, dm_->histogram_quantile()); // 0.96 in Q30.
|
||||
EXPECT_EQ(
|
||||
32702,
|
||||
@ -507,8 +479,6 @@ TEST_F(DelayManagerTest, DelayHistogramFieldTrial) {
|
||||
test::ScopedFieldTrials field_trial(
|
||||
"WebRTC-Audio-NetEqDelayHistogram/Enabled-97.5-0.998/");
|
||||
RecreateDelayManager();
|
||||
EXPECT_EQ(DelayManager::HistogramMode::RELATIVE_ARRIVAL_DELAY,
|
||||
dm_->histogram_mode());
|
||||
EXPECT_EQ(1046898278, dm_->histogram_quantile()); // 0.975 in Q30.
|
||||
EXPECT_EQ(
|
||||
32702,
|
||||
@ -536,8 +506,7 @@ TEST_F(DelayManagerTest, DelayHistogramFieldTrial) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(DelayManagerTest, RelativeArrivalDelayMode) {
|
||||
histogram_mode_ = DelayManager::HistogramMode::RELATIVE_ARRIVAL_DELAY;
|
||||
TEST_F(DelayManagerTest, RelativeArrivalDelay) {
|
||||
use_mock_histogram_ = true;
|
||||
RecreateDelayManager();
|
||||
|
||||
@ -561,7 +530,6 @@ TEST_F(DelayManagerTest, RelativeArrivalDelayMode) {
|
||||
}
|
||||
|
||||
TEST_F(DelayManagerTest, MaxDelayHistory) {
|
||||
histogram_mode_ = DelayManager::HistogramMode::RELATIVE_ARRIVAL_DELAY;
|
||||
use_mock_histogram_ = true;
|
||||
RecreateDelayManager();
|
||||
|
||||
|
||||
@ -1,134 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012 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/audio_coding/neteq/delay_peak_detector.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "rtc_base/checks.h"
|
||||
#include "system_wrappers/include/field_trial.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// The DelayPeakDetector keeps track of severe inter-arrival times, called
|
||||
// delay peaks. When a peak is observed, the "height" (the time elapsed since
|
||||
// the previous packet arrival) and the peak "period" (the time since the last
|
||||
// observed peak) is recorded in a vector. When enough peaks have been observed,
|
||||
// peak-mode is engaged and the DelayManager asks the DelayPeakDetector for
|
||||
// the worst peak height.
|
||||
|
||||
DelayPeakDetector::~DelayPeakDetector() = default;
|
||||
|
||||
DelayPeakDetector::DelayPeakDetector(const TickTimer* tick_timer,
|
||||
bool ignore_reordered_packets)
|
||||
: peak_found_(false),
|
||||
peak_detection_threshold_(0),
|
||||
tick_timer_(tick_timer),
|
||||
ignore_reordered_packets_(ignore_reordered_packets),
|
||||
frame_length_change_experiment_(
|
||||
field_trial::IsEnabled("WebRTC-Audio-NetEqFramelengthExperiment")) {
|
||||
RTC_DCHECK(!peak_period_stopwatch_);
|
||||
}
|
||||
|
||||
void DelayPeakDetector::Reset() {
|
||||
peak_period_stopwatch_.reset();
|
||||
peak_found_ = false;
|
||||
peak_history_.clear();
|
||||
}
|
||||
|
||||
// Calculates the threshold in number of packets.
|
||||
void DelayPeakDetector::SetPacketAudioLength(int length_ms) {
|
||||
if (length_ms > 0) {
|
||||
if (frame_length_change_experiment_) {
|
||||
peak_detection_threshold_ = std::max(2, kPeakHeightMs / length_ms);
|
||||
} else {
|
||||
peak_detection_threshold_ = kPeakHeightMs / length_ms;
|
||||
}
|
||||
}
|
||||
if (frame_length_change_experiment_) {
|
||||
peak_history_.clear();
|
||||
}
|
||||
}
|
||||
|
||||
bool DelayPeakDetector::peak_found() {
|
||||
return peak_found_;
|
||||
}
|
||||
|
||||
int DelayPeakDetector::MaxPeakHeight() const {
|
||||
int max_height = -1; // Returns -1 for an empty history.
|
||||
std::list<Peak>::const_iterator it;
|
||||
for (it = peak_history_.begin(); it != peak_history_.end(); ++it) {
|
||||
max_height = std::max(max_height, it->peak_height_packets);
|
||||
}
|
||||
return max_height;
|
||||
}
|
||||
|
||||
uint64_t DelayPeakDetector::MaxPeakPeriod() const {
|
||||
auto max_period_element = std::max_element(
|
||||
peak_history_.begin(), peak_history_.end(),
|
||||
[](Peak a, Peak b) { return a.period_ms < b.period_ms; });
|
||||
if (max_period_element == peak_history_.end()) {
|
||||
return 0; // |peak_history_| is empty.
|
||||
}
|
||||
RTC_DCHECK_GT(max_period_element->period_ms, 0);
|
||||
return max_period_element->period_ms;
|
||||
}
|
||||
|
||||
bool DelayPeakDetector::Update(int inter_arrival_time,
|
||||
bool reordered,
|
||||
int target_level) {
|
||||
if (ignore_reordered_packets_ && reordered) {
|
||||
return CheckPeakConditions();
|
||||
}
|
||||
if (inter_arrival_time > target_level + peak_detection_threshold_ ||
|
||||
inter_arrival_time > 2 * target_level) {
|
||||
// A delay peak is observed.
|
||||
if (!peak_period_stopwatch_) {
|
||||
// This is the first peak. Reset the period counter.
|
||||
peak_period_stopwatch_ = tick_timer_->GetNewStopwatch();
|
||||
} else if (peak_period_stopwatch_->ElapsedMs() > 0) {
|
||||
if (peak_period_stopwatch_->ElapsedMs() <= kMaxPeakPeriodMs) {
|
||||
// This is not the first peak, and the period is valid.
|
||||
// Store peak data in the vector.
|
||||
Peak peak_data;
|
||||
peak_data.period_ms = peak_period_stopwatch_->ElapsedMs();
|
||||
peak_data.peak_height_packets = inter_arrival_time;
|
||||
peak_history_.push_back(peak_data);
|
||||
while (peak_history_.size() > kMaxNumPeaks) {
|
||||
// Delete the oldest data point.
|
||||
peak_history_.pop_front();
|
||||
}
|
||||
peak_period_stopwatch_ = tick_timer_->GetNewStopwatch();
|
||||
} else if (peak_period_stopwatch_->ElapsedMs() <= 2 * kMaxPeakPeriodMs) {
|
||||
// Invalid peak due to too long period. Reset period counter and start
|
||||
// looking for next peak.
|
||||
peak_period_stopwatch_ = tick_timer_->GetNewStopwatch();
|
||||
} else {
|
||||
// More than 2 times the maximum period has elapsed since the last peak
|
||||
// was registered. It seams that the network conditions have changed.
|
||||
// Reset the peak statistics.
|
||||
Reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
return CheckPeakConditions();
|
||||
}
|
||||
|
||||
bool DelayPeakDetector::CheckPeakConditions() {
|
||||
size_t s = peak_history_.size();
|
||||
if (s >= kMinPeaksToTrigger &&
|
||||
peak_period_stopwatch_->ElapsedMs() <= 2 * MaxPeakPeriod()) {
|
||||
peak_found_ = true;
|
||||
} else {
|
||||
peak_found_ = false;
|
||||
}
|
||||
return peak_found_;
|
||||
}
|
||||
} // namespace webrtc
|
||||
@ -1,78 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012 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_AUDIO_CODING_NETEQ_DELAY_PEAK_DETECTOR_H_
|
||||
#define MODULES_AUDIO_CODING_NETEQ_DELAY_PEAK_DETECTOR_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <list>
|
||||
#include <memory>
|
||||
|
||||
#include "api/neteq/tick_timer.h"
|
||||
#include "rtc_base/constructor_magic.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class DelayPeakDetector {
|
||||
public:
|
||||
DelayPeakDetector(const TickTimer* tick_timer, bool ignore_reordered_packets);
|
||||
virtual ~DelayPeakDetector();
|
||||
virtual void Reset();
|
||||
|
||||
// Notifies the DelayPeakDetector of how much audio data is carried in each
|
||||
// packet.
|
||||
virtual void SetPacketAudioLength(int length_ms);
|
||||
|
||||
// Returns true if peak-mode is active. That is, delay peaks were observed
|
||||
// recently.
|
||||
virtual bool peak_found();
|
||||
|
||||
// Calculates and returns the maximum delay peak height. Returns -1 if no
|
||||
// delay peaks have been observed recently. The unit is number of packets.
|
||||
virtual int MaxPeakHeight() const;
|
||||
|
||||
// Calculates and returns the maximum delay peak distance in ms (strictly
|
||||
// larger than 0), or 0 if no delay peaks have been observed recently.
|
||||
virtual uint64_t MaxPeakPeriod() const;
|
||||
|
||||
// Updates the DelayPeakDetector with a new inter-arrival time (in packets),
|
||||
// the current target buffer level (needed to decide if a peak is observed or
|
||||
// not) and if the new inter-arrival time includes a compensation for
|
||||
// reordering. Returns true if peak-mode is active, false if not.
|
||||
virtual bool Update(int inter_arrival_time, bool reordered, int target_level);
|
||||
|
||||
private:
|
||||
static const size_t kMaxNumPeaks = 8;
|
||||
static const size_t kMinPeaksToTrigger = 2;
|
||||
static const int kPeakHeightMs = 78;
|
||||
static const int kMaxPeakPeriodMs = 10000;
|
||||
|
||||
typedef struct {
|
||||
uint64_t period_ms;
|
||||
int peak_height_packets;
|
||||
} Peak;
|
||||
|
||||
bool CheckPeakConditions();
|
||||
|
||||
std::list<Peak> peak_history_;
|
||||
bool peak_found_;
|
||||
int peak_detection_threshold_;
|
||||
const TickTimer* tick_timer_;
|
||||
std::unique_ptr<TickTimer::Stopwatch> peak_period_stopwatch_;
|
||||
const bool ignore_reordered_packets_;
|
||||
const bool frame_length_change_experiment_;
|
||||
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(DelayPeakDetector);
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
#endif // MODULES_AUDIO_CODING_NETEQ_DELAY_PEAK_DETECTOR_H_
|
||||
@ -1,161 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012 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.
|
||||
*/
|
||||
|
||||
// Unit tests for DelayPeakDetector class.
|
||||
|
||||
#include "modules/audio_coding/neteq/delay_peak_detector.h"
|
||||
|
||||
#include "test/gtest.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
TEST(DelayPeakDetector, CreateAndDestroy) {
|
||||
TickTimer tick_timer;
|
||||
DelayPeakDetector* detector = new DelayPeakDetector(&tick_timer, false);
|
||||
EXPECT_FALSE(detector->peak_found());
|
||||
delete detector;
|
||||
}
|
||||
|
||||
TEST(DelayPeakDetector, EmptyHistory) {
|
||||
TickTimer tick_timer;
|
||||
DelayPeakDetector detector(&tick_timer, false);
|
||||
EXPECT_EQ(-1, detector.MaxPeakHeight());
|
||||
EXPECT_EQ(0u, detector.MaxPeakPeriod());
|
||||
}
|
||||
|
||||
// Inject a series of packet arrivals into the detector. Three of the packets
|
||||
// have suffered delays. After the third delay peak, peak-mode is expected to
|
||||
// start. This should then continue until it is disengaged due to lack of peaks.
|
||||
TEST(DelayPeakDetector, TriggerPeakMode) {
|
||||
TickTimer tick_timer;
|
||||
DelayPeakDetector detector(&tick_timer, false);
|
||||
const int kPacketSizeMs = 30;
|
||||
detector.SetPacketAudioLength(kPacketSizeMs);
|
||||
|
||||
// Load up normal arrival times; 0 ms, 30 ms, 60 ms, 90 ms, ...
|
||||
const int kNumPackets = 1000;
|
||||
int arrival_times_ms[kNumPackets];
|
||||
for (int i = 0; i < kNumPackets; ++i) {
|
||||
arrival_times_ms[i] = i * kPacketSizeMs;
|
||||
}
|
||||
|
||||
// Delay three packets.
|
||||
const int kPeakDelayMs = 100;
|
||||
// First delay peak.
|
||||
arrival_times_ms[100] += kPeakDelayMs;
|
||||
// Second delay peak.
|
||||
arrival_times_ms[200] += kPeakDelayMs;
|
||||
// Third delay peak. Trigger peak-mode after this packet.
|
||||
arrival_times_ms[400] += kPeakDelayMs;
|
||||
// The second peak period is the longest, 200 packets.
|
||||
const uint64_t kWorstPeakPeriod = 200 * kPacketSizeMs;
|
||||
int peak_mode_start_ms = arrival_times_ms[400];
|
||||
// Expect to disengage after no peaks are observed for two period times.
|
||||
int peak_mode_end_ms = peak_mode_start_ms + 2 * kWorstPeakPeriod;
|
||||
|
||||
// Load into detector.
|
||||
int time = 0;
|
||||
int next = 1; // Start with the second packet to get a proper IAT.
|
||||
while (next < kNumPackets) {
|
||||
while (next < kNumPackets && arrival_times_ms[next] <= time) {
|
||||
int iat_packets =
|
||||
(arrival_times_ms[next] - arrival_times_ms[next - 1]) / kPacketSizeMs;
|
||||
const int kTargetBufferLevel = 1; // Define peaks to be iat > 2.
|
||||
if (time < peak_mode_start_ms || time > peak_mode_end_ms) {
|
||||
EXPECT_FALSE(detector.Update(iat_packets, false, kTargetBufferLevel));
|
||||
} else {
|
||||
EXPECT_TRUE(detector.Update(iat_packets, false, kTargetBufferLevel));
|
||||
EXPECT_EQ(kWorstPeakPeriod, detector.MaxPeakPeriod());
|
||||
EXPECT_EQ(kPeakDelayMs / kPacketSizeMs + 1, detector.MaxPeakHeight());
|
||||
}
|
||||
++next;
|
||||
}
|
||||
tick_timer.Increment();
|
||||
time += 10; // Increase time 10 ms.
|
||||
}
|
||||
}
|
||||
|
||||
// Same test as TriggerPeakMode, but with base target buffer level increased to
|
||||
// 2, in order to raise the bar for delay peaks to inter-arrival times > 4.
|
||||
// The delay pattern has peaks with delay = 3, thus should not trigger.
|
||||
TEST(DelayPeakDetector, DoNotTriggerPeakMode) {
|
||||
TickTimer tick_timer;
|
||||
DelayPeakDetector detector(&tick_timer, false);
|
||||
const int kPacketSizeMs = 30;
|
||||
detector.SetPacketAudioLength(kPacketSizeMs);
|
||||
|
||||
// Load up normal arrival times; 0 ms, 30 ms, 60 ms, 90 ms, ...
|
||||
const int kNumPackets = 1000;
|
||||
int arrival_times_ms[kNumPackets];
|
||||
for (int i = 0; i < kNumPackets; ++i) {
|
||||
arrival_times_ms[i] = i * kPacketSizeMs;
|
||||
}
|
||||
|
||||
// Delay three packets.
|
||||
const int kPeakDelayMs = 100;
|
||||
// First delay peak.
|
||||
arrival_times_ms[100] += kPeakDelayMs;
|
||||
// Second delay peak.
|
||||
arrival_times_ms[200] += kPeakDelayMs;
|
||||
// Third delay peak.
|
||||
arrival_times_ms[400] += kPeakDelayMs;
|
||||
|
||||
// Load into detector.
|
||||
int time = 0;
|
||||
int next = 1; // Start with the second packet to get a proper IAT.
|
||||
while (next < kNumPackets) {
|
||||
while (next < kNumPackets && arrival_times_ms[next] <= time) {
|
||||
int iat_packets =
|
||||
(arrival_times_ms[next] - arrival_times_ms[next - 1]) / kPacketSizeMs;
|
||||
const int kTargetBufferLevel = 2; // Define peaks to be iat > 4.
|
||||
EXPECT_FALSE(detector.Update(iat_packets, false, kTargetBufferLevel));
|
||||
++next;
|
||||
}
|
||||
tick_timer.Increment();
|
||||
time += 10; // Increase time 10 ms.
|
||||
}
|
||||
}
|
||||
|
||||
// In situations with reordered packets, the DelayPeakDetector may be updated
|
||||
// back-to-back (i.e., without the tick_timer moving) but still with non-zero
|
||||
// inter-arrival time. This test is to make sure that this does not cause
|
||||
// problems.
|
||||
TEST(DelayPeakDetector, ZeroDistancePeaks) {
|
||||
TickTimer tick_timer;
|
||||
DelayPeakDetector detector(&tick_timer, false);
|
||||
const int kPacketSizeMs = 30;
|
||||
detector.SetPacketAudioLength(kPacketSizeMs);
|
||||
|
||||
const int kTargetBufferLevel = 2; // Define peaks to be iat > 4.
|
||||
const int kInterArrivalTime =
|
||||
3 * kTargetBufferLevel; // Above peak threshold.
|
||||
EXPECT_FALSE(detector.Update(kInterArrivalTime, false, kTargetBufferLevel));
|
||||
tick_timer.Increment();
|
||||
EXPECT_FALSE(detector.Update(kInterArrivalTime, false, kTargetBufferLevel));
|
||||
// The following would fail if there were non-zero time between the updates.
|
||||
EXPECT_FALSE(detector.Update(kInterArrivalTime, false, kTargetBufferLevel));
|
||||
}
|
||||
|
||||
TEST(DelayPeakDetector, IgnoreReorderedPacket) {
|
||||
TickTimer tick_timer;
|
||||
DelayPeakDetector detector(&tick_timer, true);
|
||||
|
||||
const int kTargetBufferLevel = 2; // Define peaks to be iat > 4.
|
||||
const int kInterArrivalTime =
|
||||
3 * kTargetBufferLevel; // Above peak threshold.
|
||||
EXPECT_FALSE(detector.Update(kInterArrivalTime, false, kTargetBufferLevel));
|
||||
tick_timer.Increment();
|
||||
EXPECT_FALSE(detector.Update(kInterArrivalTime, false, kTargetBufferLevel));
|
||||
tick_timer.Increment();
|
||||
// The following would fail if the packet was not reordered.
|
||||
EXPECT_FALSE(detector.Update(kInterArrivalTime, true, kTargetBufferLevel));
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
@ -146,58 +146,4 @@ int Histogram::NumBuckets() const {
|
||||
return buckets_.size();
|
||||
}
|
||||
|
||||
void Histogram::Scale(int old_bucket_width, int new_bucket_width) {
|
||||
buckets_ = ScaleBuckets(buckets_, old_bucket_width, new_bucket_width);
|
||||
}
|
||||
|
||||
std::vector<int> Histogram::ScaleBuckets(const std::vector<int>& buckets,
|
||||
int old_bucket_width,
|
||||
int new_bucket_width) {
|
||||
RTC_DCHECK_GT(old_bucket_width, 0);
|
||||
RTC_DCHECK_GT(new_bucket_width, 0);
|
||||
RTC_DCHECK_EQ(old_bucket_width % 10, 0);
|
||||
RTC_DCHECK_EQ(new_bucket_width % 10, 0);
|
||||
std::vector<int> new_histogram(buckets.size(), 0);
|
||||
int64_t acc = 0;
|
||||
int time_counter = 0;
|
||||
size_t new_histogram_idx = 0;
|
||||
for (size_t i = 0; i < buckets.size(); i++) {
|
||||
acc += buckets[i];
|
||||
time_counter += old_bucket_width;
|
||||
// The bins should be scaled, to ensure the histogram still sums to one.
|
||||
const int64_t scaled_acc = acc * new_bucket_width / time_counter;
|
||||
int64_t actually_used_acc = 0;
|
||||
while (time_counter >= new_bucket_width) {
|
||||
const int64_t old_histogram_val = new_histogram[new_histogram_idx];
|
||||
new_histogram[new_histogram_idx] =
|
||||
rtc::saturated_cast<int>(old_histogram_val + scaled_acc);
|
||||
actually_used_acc += new_histogram[new_histogram_idx] - old_histogram_val;
|
||||
new_histogram_idx =
|
||||
std::min(new_histogram_idx + 1, new_histogram.size() - 1);
|
||||
time_counter -= new_bucket_width;
|
||||
}
|
||||
// Only subtract the part that was succesfully written to the new histogram.
|
||||
acc -= actually_used_acc;
|
||||
}
|
||||
// If there is anything left in acc (due to rounding errors), add it to the
|
||||
// last bin. If we cannot add everything to the last bin we need to add as
|
||||
// much as possible to the bins after the last bin (this is only possible
|
||||
// when compressing a histogram).
|
||||
while (acc > 0 && new_histogram_idx < new_histogram.size()) {
|
||||
const int64_t old_histogram_val = new_histogram[new_histogram_idx];
|
||||
new_histogram[new_histogram_idx] =
|
||||
rtc::saturated_cast<int>(old_histogram_val + acc);
|
||||
acc -= new_histogram[new_histogram_idx] - old_histogram_val;
|
||||
new_histogram_idx++;
|
||||
}
|
||||
RTC_DCHECK_EQ(buckets.size(), new_histogram.size());
|
||||
if (acc == 0) {
|
||||
// If acc is non-zero, we were not able to add everything to the new
|
||||
// histogram, so this check will not hold.
|
||||
RTC_DCHECK_EQ(accumulate(buckets.begin(), buckets.end(), 0ll),
|
||||
accumulate(new_histogram.begin(), new_histogram.end(), 0ll));
|
||||
}
|
||||
return new_histogram;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
@ -38,20 +38,12 @@ class Histogram {
|
||||
// distribution.
|
||||
virtual int Quantile(int probability);
|
||||
|
||||
// Apply compression or stretching to the histogram.
|
||||
virtual void Scale(int old_bucket_width, int new_bucket_width);
|
||||
|
||||
// Returns the number of buckets in the histogram.
|
||||
virtual int NumBuckets() const;
|
||||
|
||||
// Returns the probability for each bucket in Q30.
|
||||
std::vector<int> buckets() const { return buckets_; }
|
||||
|
||||
// Made public for testing.
|
||||
static std::vector<int> ScaleBuckets(const std::vector<int>& buckets,
|
||||
int old_bucket_width,
|
||||
int new_bucket_width);
|
||||
|
||||
// Accessors only intended for testing purposes.
|
||||
int base_forget_factor_for_testing() const { return base_forget_factor_; }
|
||||
int forget_factor_for_testing() const { return forget_factor_; }
|
||||
|
||||
@ -59,116 +59,6 @@ TEST(HistogramTest, ForgetFactor) {
|
||||
}
|
||||
}
|
||||
|
||||
// Test if the histogram is scaled correctly if the bucket width is decreased.
|
||||
TEST(HistogramTest, DownScale) {
|
||||
// Test a straightforward 60 to 20 change.
|
||||
std::vector<int> buckets = {12, 0, 0, 0, 0, 0};
|
||||
std::vector<int> expected_result = {4, 4, 4, 0, 0, 0};
|
||||
std::vector<int> stretched_buckets = Histogram::ScaleBuckets(buckets, 60, 20);
|
||||
EXPECT_EQ(stretched_buckets, expected_result);
|
||||
|
||||
// Test an example where the last bin in the stretched histogram should
|
||||
// contain the sum of the elements that don't fit into the new histogram.
|
||||
buckets = {18, 15, 12, 9, 6, 3, 0};
|
||||
expected_result = {6, 6, 6, 5, 5, 5, 30};
|
||||
stretched_buckets = Histogram::ScaleBuckets(buckets, 60, 20);
|
||||
EXPECT_EQ(stretched_buckets, expected_result);
|
||||
|
||||
// Test a 120 to 60 change.
|
||||
buckets = {18, 16, 14, 4, 0};
|
||||
expected_result = {9, 9, 8, 8, 18};
|
||||
stretched_buckets = Histogram::ScaleBuckets(buckets, 120, 60);
|
||||
EXPECT_EQ(stretched_buckets, expected_result);
|
||||
|
||||
// Test a 120 to 20 change.
|
||||
buckets = {19, 12, 0, 0, 0, 0, 0, 0};
|
||||
expected_result = {3, 3, 3, 3, 3, 3, 2, 11};
|
||||
stretched_buckets = Histogram::ScaleBuckets(buckets, 120, 20);
|
||||
EXPECT_EQ(stretched_buckets, expected_result);
|
||||
|
||||
// Test a 70 to 40 change.
|
||||
buckets = {13, 7, 5, 3, 1, 5, 12, 11, 3, 0, 0, 0};
|
||||
expected_result = {7, 5, 5, 3, 3, 2, 2, 1, 2, 2, 6, 22};
|
||||
stretched_buckets = Histogram::ScaleBuckets(buckets, 70, 40);
|
||||
EXPECT_EQ(stretched_buckets, expected_result);
|
||||
|
||||
// Test a 30 to 20 change.
|
||||
buckets = {13, 7, 5, 3, 1, 5, 12, 11, 3, 0, 0, 0};
|
||||
expected_result = {8, 6, 6, 3, 2, 2, 1, 3, 3, 8, 7, 11};
|
||||
stretched_buckets = Histogram::ScaleBuckets(buckets, 30, 20);
|
||||
EXPECT_EQ(stretched_buckets, expected_result);
|
||||
}
|
||||
|
||||
// Test if the histogram is scaled correctly if the bucket width is increased.
|
||||
TEST(HistogramTest, UpScale) {
|
||||
// Test a 20 to 60 change.
|
||||
std::vector<int> buckets = {12, 11, 10, 3, 2, 1};
|
||||
std::vector<int> expected_result = {33, 6, 0, 0, 0, 0};
|
||||
std::vector<int> compressed_buckets =
|
||||
Histogram::ScaleBuckets(buckets, 20, 60);
|
||||
EXPECT_EQ(compressed_buckets, expected_result);
|
||||
|
||||
// Test a 60 to 120 change.
|
||||
buckets = {18, 16, 14, 4, 1};
|
||||
expected_result = {34, 18, 1, 0, 0};
|
||||
compressed_buckets = Histogram::ScaleBuckets(buckets, 60, 120);
|
||||
EXPECT_EQ(compressed_buckets, expected_result);
|
||||
|
||||
// Test a 20 to 120 change.
|
||||
buckets = {18, 12, 5, 4, 4, 3, 5, 1};
|
||||
expected_result = {46, 6, 0, 0, 0, 0, 0, 0};
|
||||
compressed_buckets = Histogram::ScaleBuckets(buckets, 20, 120);
|
||||
EXPECT_EQ(compressed_buckets, expected_result);
|
||||
|
||||
// Test a 70 to 80 change.
|
||||
buckets = {13, 7, 5, 3, 1, 5, 12, 11, 3};
|
||||
expected_result = {11, 8, 6, 2, 5, 12, 13, 3, 0};
|
||||
compressed_buckets = Histogram::ScaleBuckets(buckets, 70, 80);
|
||||
EXPECT_EQ(compressed_buckets, expected_result);
|
||||
|
||||
// Test a 50 to 110 change.
|
||||
buckets = {13, 7, 5, 3, 1, 5, 12, 11, 3};
|
||||
expected_result = {18, 8, 16, 16, 2, 0, 0, 0, 0};
|
||||
compressed_buckets = Histogram::ScaleBuckets(buckets, 50, 110);
|
||||
EXPECT_EQ(compressed_buckets, expected_result);
|
||||
}
|
||||
|
||||
// Test if the histogram scaling function handles overflows correctly.
|
||||
TEST(HistogramTest, OverflowTest) {
|
||||
// Test a upscale operation that can cause overflow.
|
||||
std::vector<int> buckets = {733544448, 0, 0, 0, 0, 0, 0,
|
||||
340197376, 0, 0, 0, 0, 0, 0};
|
||||
std::vector<int> expected_result = {733544448, 340197376, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0};
|
||||
std::vector<int> scaled_buckets = Histogram::ScaleBuckets(buckets, 10, 60);
|
||||
EXPECT_EQ(scaled_buckets, expected_result);
|
||||
|
||||
buckets = {655591163, 39962288, 360736736, 1930514, 4003853, 1782764,
|
||||
114119, 2072996, 0, 2149354, 0};
|
||||
expected_result = {1056290187, 7717131, 2187115, 2149354, 0, 0,
|
||||
0, 0, 0, 0, 0};
|
||||
scaled_buckets = Histogram::ScaleBuckets(buckets, 20, 60);
|
||||
EXPECT_EQ(scaled_buckets, expected_result);
|
||||
|
||||
// In this test case we will not be able to add everything to the final bin in
|
||||
// the scaled histogram. Check that the last bin doesn't overflow.
|
||||
buckets = {2000000000, 2000000000, 2000000000,
|
||||
2000000000, 2000000000, 2000000000};
|
||||
expected_result = {666666666, 666666666, 666666666,
|
||||
666666667, 666666667, 2147483647};
|
||||
scaled_buckets = Histogram::ScaleBuckets(buckets, 60, 20);
|
||||
EXPECT_EQ(scaled_buckets, expected_result);
|
||||
|
||||
// In this test case we will not be able to add enough to each of the bins,
|
||||
// so the values should be smeared out past the end of the normal range.
|
||||
buckets = {2000000000, 2000000000, 2000000000,
|
||||
2000000000, 2000000000, 2000000000};
|
||||
expected_result = {2147483647, 2147483647, 2147483647,
|
||||
2147483647, 2147483647, 1262581765};
|
||||
scaled_buckets = Histogram::ScaleBuckets(buckets, 20, 60);
|
||||
EXPECT_EQ(scaled_buckets, expected_result);
|
||||
}
|
||||
|
||||
TEST(HistogramTest, ReachSteadyStateForgetFactor) {
|
||||
static constexpr int kSteadyStateForgetFactor = (1 << 15) * 0.9993;
|
||||
Histogram histogram(100, kSteadyStateForgetFactor, 1.0);
|
||||
|
||||
@ -1,37 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012 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_AUDIO_CODING_NETEQ_MOCK_MOCK_DELAY_PEAK_DETECTOR_H_
|
||||
#define MODULES_AUDIO_CODING_NETEQ_MOCK_MOCK_DELAY_PEAK_DETECTOR_H_
|
||||
|
||||
#include "modules/audio_coding/neteq/delay_peak_detector.h"
|
||||
#include "test/gmock.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class MockDelayPeakDetector : public DelayPeakDetector {
|
||||
public:
|
||||
MockDelayPeakDetector(const TickTimer* tick_timer,
|
||||
bool ignore_reordered_packets)
|
||||
: DelayPeakDetector(tick_timer, ignore_reordered_packets) {}
|
||||
virtual ~MockDelayPeakDetector() { Die(); }
|
||||
MOCK_METHOD0(Die, void());
|
||||
MOCK_METHOD0(Reset, void());
|
||||
MOCK_METHOD1(SetPacketAudioLength, void(int length_ms));
|
||||
MOCK_METHOD0(peak_found, bool());
|
||||
MOCK_CONST_METHOD0(MaxPeakHeight, int());
|
||||
MOCK_CONST_METHOD0(MaxPeakPeriod, uint64_t());
|
||||
MOCK_METHOD3(Update,
|
||||
bool(int inter_arrival_time, bool reordered, int target_level));
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // MODULES_AUDIO_CODING_NETEQ_MOCK_MOCK_DELAY_PEAK_DETECTOR_H_
|
||||
Loading…
x
Reference in New Issue
Block a user