2013-01-29 12:09:21 +00:00
|
|
|
/*
|
|
|
|
|
* 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.
|
|
|
|
|
*/
|
|
|
|
|
|
2017-09-15 06:47:31 +02:00
|
|
|
#include "modules/audio_coding/neteq/delay_manager.h"
|
2013-01-29 12:09:21 +00:00
|
|
|
|
2018-10-23 12:03:01 +02:00
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
2019-07-05 19:08:33 +02:00
|
|
|
|
2018-10-23 12:03:01 +02:00
|
|
|
#include <algorithm>
|
2019-09-17 17:06:18 +02:00
|
|
|
#include <memory>
|
2017-10-13 12:37:27 +02:00
|
|
|
#include <numeric>
|
2018-10-23 12:03:01 +02:00
|
|
|
#include <string>
|
2013-01-29 12:09:21 +00:00
|
|
|
|
2019-02-27 10:08:09 +01:00
|
|
|
#include "modules/audio_coding/neteq/histogram.h"
|
2018-10-23 12:03:01 +02:00
|
|
|
#include "modules/include/module_common_types_public.h"
|
|
|
|
|
#include "rtc_base/checks.h"
|
2020-11-11 15:26:10 +01:00
|
|
|
#include "rtc_base/experiments/struct_parameters_parser.h"
|
2017-09-15 06:47:31 +02:00
|
|
|
#include "rtc_base/logging.h"
|
2017-11-22 10:42:26 +01:00
|
|
|
#include "rtc_base/numerics/safe_conversions.h"
|
2019-02-13 14:25:39 +01:00
|
|
|
#include "rtc_base/numerics/safe_minmax.h"
|
2017-10-13 12:37:27 +02:00
|
|
|
#include "system_wrappers/include/field_trial.h"
|
2013-01-29 12:09:21 +00:00
|
|
|
|
2020-10-09 13:41:06 +02:00
|
|
|
namespace webrtc {
|
2018-10-04 11:31:03 +02:00
|
|
|
namespace {
|
|
|
|
|
|
2019-02-13 14:25:39 +01:00
|
|
|
constexpr int kMinBaseMinimumDelayMs = 0;
|
|
|
|
|
constexpr int kMaxBaseMinimumDelayMs = 10000;
|
2019-02-27 10:08:09 +01:00
|
|
|
constexpr int kDelayBuckets = 100;
|
|
|
|
|
constexpr int kBucketSizeMs = 20;
|
2020-10-09 13:41:06 +02:00
|
|
|
constexpr int kStartDelayMs = 80;
|
|
|
|
|
constexpr int kMaxNumReorderedPackets = 5;
|
2019-02-27 10:08:09 +01:00
|
|
|
|
2020-11-11 15:26:10 +01:00
|
|
|
struct DelayManagerConfig {
|
|
|
|
|
double quantile = 0.97;
|
|
|
|
|
double forget_factor = 0.9993;
|
2019-09-03 13:04:41 +02:00
|
|
|
absl::optional<double> start_forget_weight = 2;
|
2020-11-11 15:26:10 +01:00
|
|
|
absl::optional<int> resample_interval_ms;
|
|
|
|
|
int max_history_ms = 2000;
|
|
|
|
|
|
|
|
|
|
std::unique_ptr<webrtc::StructParametersParser> Parser() {
|
|
|
|
|
return webrtc::StructParametersParser::Create( //
|
|
|
|
|
"quantile", &quantile, //
|
|
|
|
|
"forget_factor", &forget_factor, //
|
|
|
|
|
"start_forget_weight", &start_forget_weight, //
|
|
|
|
|
"resample_interval_ms", &resample_interval_ms, //
|
|
|
|
|
"max_history_ms", &max_history_ms);
|
|
|
|
|
}
|
2019-02-27 10:08:09 +01:00
|
|
|
|
2020-11-11 15:26:10 +01:00
|
|
|
// TODO(jakobi): remove legacy field trial.
|
|
|
|
|
void MaybeUpdateFromLegacyFieldTrial() {
|
|
|
|
|
constexpr char kDelayHistogramFieldTrial[] =
|
|
|
|
|
"WebRTC-Audio-NetEqDelayHistogram";
|
|
|
|
|
if (!webrtc::field_trial::IsEnabled(kDelayHistogramFieldTrial)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2019-02-27 10:08:09 +01:00
|
|
|
const auto field_trial_string =
|
|
|
|
|
webrtc::field_trial::FindFullName(kDelayHistogramFieldTrial);
|
|
|
|
|
double percentile = -1.0;
|
|
|
|
|
double forget_factor = -1.0;
|
2019-05-22 16:54:09 +02:00
|
|
|
double start_forget_weight = -1.0;
|
|
|
|
|
if (sscanf(field_trial_string.c_str(), "Enabled-%lf-%lf-%lf", &percentile,
|
|
|
|
|
&forget_factor, &start_forget_weight) >= 2 &&
|
2019-02-27 10:08:09 +01:00
|
|
|
percentile >= 0.0 && percentile <= 100.0 && forget_factor >= 0.0 &&
|
|
|
|
|
forget_factor <= 1.0) {
|
2020-11-11 15:26:10 +01:00
|
|
|
this->quantile = percentile / 100;
|
|
|
|
|
this->forget_factor = forget_factor;
|
|
|
|
|
this->start_forget_weight = start_forget_weight >= 1
|
|
|
|
|
? absl::make_optional(start_forget_weight)
|
|
|
|
|
: absl::nullopt;
|
2019-02-27 10:08:09 +01:00
|
|
|
}
|
|
|
|
|
}
|
2020-11-11 15:26:10 +01:00
|
|
|
|
|
|
|
|
explicit DelayManagerConfig() {
|
|
|
|
|
Parser()->Parse(webrtc::field_trial::FindFullName(
|
|
|
|
|
"WebRTC-Audio-NetEqDelayManagerConfig"));
|
|
|
|
|
MaybeUpdateFromLegacyFieldTrial();
|
|
|
|
|
RTC_LOG(LS_INFO) << "Delay manager config:"
|
|
|
|
|
" quantile="
|
|
|
|
|
<< quantile << " forget_factor=" << forget_factor
|
|
|
|
|
<< " start_forget_weight="
|
|
|
|
|
<< start_forget_weight.value_or(0)
|
|
|
|
|
<< " resample_interval_ms="
|
|
|
|
|
<< resample_interval_ms.value_or(0)
|
|
|
|
|
<< " max_history_ms=" << max_history_ms;
|
|
|
|
|
}
|
|
|
|
|
};
|
2019-02-27 10:08:09 +01:00
|
|
|
|
2018-10-04 11:31:03 +02:00
|
|
|
} // namespace
|
|
|
|
|
|
2020-10-09 13:41:06 +02:00
|
|
|
DelayManager::DelayManager(int max_packets_in_buffer,
|
2019-02-13 14:25:39 +01:00
|
|
|
int base_minimum_delay_ms,
|
2019-02-27 10:08:09 +01:00
|
|
|
int histogram_quantile,
|
2020-11-11 15:26:10 +01:00
|
|
|
absl::optional<int> resample_interval_ms,
|
|
|
|
|
int max_history_ms,
|
2019-02-21 15:42:31 +01:00
|
|
|
const TickTimer* tick_timer,
|
2019-02-27 10:08:09 +01:00
|
|
|
std::unique_ptr<Histogram> histogram)
|
2013-01-29 12:09:21 +00:00
|
|
|
: first_packet_received_(false),
|
|
|
|
|
max_packets_in_buffer_(max_packets_in_buffer),
|
2019-02-27 10:08:09 +01:00
|
|
|
histogram_(std::move(histogram)),
|
|
|
|
|
histogram_quantile_(histogram_quantile),
|
2016-04-28 23:19:20 -07:00
|
|
|
tick_timer_(tick_timer),
|
2020-11-11 15:26:10 +01:00
|
|
|
resample_interval_ms_(resample_interval_ms),
|
|
|
|
|
max_history_ms_(max_history_ms),
|
2019-02-13 14:25:39 +01:00
|
|
|
base_minimum_delay_ms_(base_minimum_delay_ms),
|
|
|
|
|
effective_minimum_delay_ms_(base_minimum_delay_ms),
|
2019-02-22 19:28:02 +01:00
|
|
|
minimum_delay_ms_(0),
|
2019-02-20 13:41:59 +01:00
|
|
|
maximum_delay_ms_(0),
|
2020-10-09 13:41:06 +02:00
|
|
|
target_level_ms_(kStartDelayMs),
|
|
|
|
|
last_timestamp_(0) {
|
2019-02-27 10:08:09 +01:00
|
|
|
RTC_CHECK(histogram_);
|
2019-02-13 14:25:39 +01:00
|
|
|
RTC_DCHECK_GE(base_minimum_delay_ms_, 0);
|
2018-10-04 11:31:03 +02:00
|
|
|
|
2013-01-29 12:09:21 +00:00
|
|
|
Reset();
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-21 15:42:31 +01:00
|
|
|
std::unique_ptr<DelayManager> DelayManager::Create(
|
2020-10-09 13:41:06 +02:00
|
|
|
int max_packets_in_buffer,
|
2019-02-21 15:42:31 +01:00
|
|
|
int base_minimum_delay_ms,
|
2019-10-24 15:20:39 +02:00
|
|
|
const TickTimer* tick_timer) {
|
2020-11-11 15:26:10 +01:00
|
|
|
DelayManagerConfig config;
|
|
|
|
|
int forget_factor_q15 = (1 << 15) * config.forget_factor;
|
|
|
|
|
int quantile_q30 = (1 << 30) * config.quantile;
|
2019-09-17 17:06:18 +02:00
|
|
|
std::unique_ptr<Histogram> histogram = std::make_unique<Histogram>(
|
2020-11-11 15:26:10 +01:00
|
|
|
kDelayBuckets, forget_factor_q15, config.start_forget_weight);
|
|
|
|
|
return std::make_unique<DelayManager>(
|
|
|
|
|
max_packets_in_buffer, base_minimum_delay_ms, quantile_q30,
|
|
|
|
|
config.resample_interval_ms, config.max_history_ms, tick_timer,
|
|
|
|
|
std::move(histogram));
|
2013-07-31 15:54:00 +00:00
|
|
|
}
|
|
|
|
|
|
2019-02-21 15:42:31 +01:00
|
|
|
DelayManager::~DelayManager() {}
|
2013-01-29 12:09:21 +00:00
|
|
|
|
2020-10-09 13:41:06 +02:00
|
|
|
absl::optional<int> DelayManager::Update(uint32_t timestamp,
|
|
|
|
|
int sample_rate_hz,
|
|
|
|
|
bool reset) {
|
2013-01-29 12:09:21 +00:00
|
|
|
if (sample_rate_hz <= 0) {
|
2019-10-24 15:20:39 +02:00
|
|
|
return absl::nullopt;
|
2013-01-29 12:09:21 +00:00
|
|
|
}
|
|
|
|
|
|
2020-10-09 13:41:06 +02:00
|
|
|
if (!first_packet_received_ || reset) {
|
|
|
|
|
// Restart relative delay esimation from this packet.
|
|
|
|
|
delay_history_.clear();
|
2016-04-28 23:19:20 -07:00
|
|
|
packet_iat_stopwatch_ = tick_timer_->GetNewStopwatch();
|
2013-01-29 12:09:21 +00:00
|
|
|
last_timestamp_ = timestamp;
|
|
|
|
|
first_packet_received_ = true;
|
2020-10-09 13:41:06 +02:00
|
|
|
num_reordered_packets_ = 0;
|
2020-11-11 15:26:10 +01:00
|
|
|
resample_stopwatch_ = tick_timer_->GetNewStopwatch();
|
|
|
|
|
max_delay_in_interval_ms_ = 0;
|
2019-10-24 15:20:39 +02:00
|
|
|
return absl::nullopt;
|
2013-01-29 12:09:21 +00:00
|
|
|
}
|
|
|
|
|
|
2020-10-09 13:41:06 +02:00
|
|
|
const int expected_iat_ms =
|
2020-12-03 10:06:25 +01:00
|
|
|
1000ll * static_cast<int32_t>(timestamp - last_timestamp_) /
|
|
|
|
|
sample_rate_hz;
|
2020-10-09 13:41:06 +02:00
|
|
|
const int iat_ms = packet_iat_stopwatch_->ElapsedMs();
|
|
|
|
|
const int iat_delay_ms = iat_ms - expected_iat_ms;
|
2020-11-11 15:26:10 +01:00
|
|
|
int relative_delay;
|
2020-10-09 13:41:06 +02:00
|
|
|
bool reordered = !IsNewerTimestamp(timestamp, last_timestamp_);
|
|
|
|
|
if (reordered) {
|
|
|
|
|
relative_delay = std::max(iat_delay_ms, 0);
|
2013-01-29 12:09:21 +00:00
|
|
|
} else {
|
2020-10-09 13:41:06 +02:00
|
|
|
UpdateDelayHistory(iat_delay_ms, timestamp, sample_rate_hz);
|
|
|
|
|
relative_delay = CalculateRelativePacketArrivalDelay();
|
|
|
|
|
}
|
2020-11-11 15:26:10 +01:00
|
|
|
|
|
|
|
|
absl::optional<int> histogram_update;
|
|
|
|
|
if (resample_interval_ms_) {
|
|
|
|
|
if (static_cast<int>(resample_stopwatch_->ElapsedMs()) >
|
|
|
|
|
*resample_interval_ms_) {
|
|
|
|
|
histogram_update = max_delay_in_interval_ms_;
|
|
|
|
|
resample_stopwatch_ = tick_timer_->GetNewStopwatch();
|
|
|
|
|
max_delay_in_interval_ms_ = 0;
|
|
|
|
|
}
|
|
|
|
|
max_delay_in_interval_ms_ =
|
|
|
|
|
std::max(max_delay_in_interval_ms_, relative_delay);
|
|
|
|
|
} else {
|
|
|
|
|
histogram_update = relative_delay;
|
|
|
|
|
}
|
|
|
|
|
if (histogram_update) {
|
|
|
|
|
const int index = *histogram_update / kBucketSizeMs;
|
|
|
|
|
if (index < histogram_->NumBuckets()) {
|
|
|
|
|
// Maximum delay to register is 2000 ms.
|
|
|
|
|
histogram_->Add(index);
|
|
|
|
|
}
|
2020-10-09 13:41:06 +02:00
|
|
|
}
|
2020-11-11 15:26:10 +01:00
|
|
|
|
2021-07-28 20:00:17 +02:00
|
|
|
// Calculate new `target_level_ms_` based on updated statistics.
|
2020-10-09 13:41:06 +02:00
|
|
|
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);
|
2020-10-06 15:37:28 +00:00
|
|
|
}
|
2020-10-06 18:12:07 +02:00
|
|
|
|
2020-10-09 13:41:06 +02:00
|
|
|
// Prepare for next packet arrival.
|
|
|
|
|
if (reordered) {
|
|
|
|
|
// Allow a small number of reordered packets before resetting the delay
|
|
|
|
|
// estimation.
|
|
|
|
|
if (num_reordered_packets_ < kMaxNumReorderedPackets) {
|
|
|
|
|
++num_reordered_packets_;
|
|
|
|
|
return relative_delay;
|
2020-10-07 12:46:42 +00:00
|
|
|
}
|
2020-10-09 13:41:06 +02:00
|
|
|
delay_history_.clear();
|
2020-10-07 12:46:42 +00:00
|
|
|
}
|
|
|
|
|
num_reordered_packets_ = 0;
|
2016-04-28 23:19:20 -07:00
|
|
|
packet_iat_stopwatch_ = tick_timer_->GetNewStopwatch();
|
2013-01-29 12:09:21 +00:00
|
|
|
last_timestamp_ = timestamp;
|
2019-10-24 15:20:39 +02:00
|
|
|
return relative_delay;
|
2013-01-29 12:09:21 +00:00
|
|
|
}
|
|
|
|
|
|
2019-08-22 15:00:16 +02:00
|
|
|
void DelayManager::UpdateDelayHistory(int iat_delay_ms,
|
|
|
|
|
uint32_t timestamp,
|
|
|
|
|
int sample_rate_hz) {
|
|
|
|
|
PacketDelay delay;
|
|
|
|
|
delay.iat_delay_ms = iat_delay_ms;
|
|
|
|
|
delay.timestamp = timestamp;
|
|
|
|
|
delay_history_.push_back(delay);
|
|
|
|
|
while (timestamp - delay_history_.front().timestamp >
|
2020-11-11 15:26:10 +01:00
|
|
|
static_cast<uint32_t>(max_history_ms_ * sample_rate_hz / 1000)) {
|
2019-02-27 10:08:09 +01:00
|
|
|
delay_history_.pop_front();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int DelayManager::CalculateRelativePacketArrivalDelay() const {
|
|
|
|
|
// This effectively calculates arrival delay of a packet relative to the
|
|
|
|
|
// packet preceding the history window. If the arrival delay ever becomes
|
|
|
|
|
// smaller than zero, it means the reference packet is invalid, and we
|
|
|
|
|
// move the reference.
|
|
|
|
|
int relative_delay = 0;
|
2019-08-22 15:00:16 +02:00
|
|
|
for (const PacketDelay& delay : delay_history_) {
|
|
|
|
|
relative_delay += delay.iat_delay_ms;
|
2019-02-27 10:08:09 +01:00
|
|
|
relative_delay = std::max(relative_delay, 0);
|
|
|
|
|
}
|
|
|
|
|
return relative_delay;
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-29 12:09:21 +00:00
|
|
|
int DelayManager::SetPacketAudioLength(int length_ms) {
|
|
|
|
|
if (length_ms <= 0) {
|
2017-11-09 11:09:25 +01:00
|
|
|
RTC_LOG_F(LS_ERROR) << "length_ms = " << length_ms;
|
2013-01-29 12:09:21 +00:00
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
packet_len_ms_ = length_ms;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void DelayManager::Reset() {
|
2020-10-09 13:41:06 +02:00
|
|
|
packet_len_ms_ = 0;
|
2019-02-27 10:08:09 +01:00
|
|
|
histogram_->Reset();
|
2019-08-22 15:00:16 +02:00
|
|
|
delay_history_.clear();
|
2020-10-09 13:41:06 +02:00
|
|
|
target_level_ms_ = kStartDelayMs;
|
2016-04-28 23:19:20 -07:00
|
|
|
packet_iat_stopwatch_ = tick_timer_->GetNewStopwatch();
|
2020-10-09 13:41:06 +02:00
|
|
|
first_packet_received_ = false;
|
|
|
|
|
num_reordered_packets_ = 0;
|
2020-11-11 15:26:10 +01:00
|
|
|
resample_stopwatch_ = tick_timer_->GetNewStopwatch();
|
|
|
|
|
max_delay_in_interval_ms_ = 0;
|
2013-01-29 12:09:21 +00:00
|
|
|
}
|
|
|
|
|
|
2020-10-09 13:41:06 +02:00
|
|
|
int DelayManager::TargetDelayMs() const {
|
|
|
|
|
return target_level_ms_;
|
Handle padded audio packets correctly
RTP packets can be padded with extra data at the end of the payload. The usable
payload length of the packet should then be reduced with the padding length,
since the padding must be discarded. This was not the case; instead, the entire
payload, including padding data, was forwarded to the audio channel and in the
end to the decoder.
A special case of padding is packets which are empty except for the padding.
That is, they carry no usable payload. These packets are sometimes used for
probing the network and were discarded in
RTPReceiverAudio::ParseAudioCodecSpecific. The result is that NetEq never sees
those empty packets, just the holes in the sequence number series; this can
throw off the target buffer calculations.
With this change, the empty (after removing the padding) packets are let through,
all the way down to NetEq, to a new method called NetEq::InsertEmptyPacket. This
method notifies the DelayManager that an empty packet was received.
BUG=webrtc:7610, webrtc:7625
Review-Url: https://codereview.webrtc.org/2870043003
Cr-Commit-Position: refs/heads/master@{#18083}
2017-05-10 07:38:01 -07:00
|
|
|
}
|
|
|
|
|
|
2019-02-13 14:25:39 +01:00
|
|
|
bool DelayManager::IsValidMinimumDelay(int delay_ms) const {
|
|
|
|
|
return 0 <= delay_ms && delay_ms <= MinimumDelayUpperBound();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool DelayManager::IsValidBaseMinimumDelay(int delay_ms) const {
|
|
|
|
|
return kMinBaseMinimumDelayMs <= delay_ms &&
|
|
|
|
|
delay_ms <= kMaxBaseMinimumDelayMs;
|
2019-02-04 16:17:31 +01:00
|
|
|
}
|
|
|
|
|
|
2013-08-16 23:44:24 +00:00
|
|
|
bool DelayManager::SetMinimumDelay(int delay_ms) {
|
2019-02-04 16:17:31 +01:00
|
|
|
if (!IsValidMinimumDelay(delay_ms)) {
|
2013-08-16 23:44:24 +00:00
|
|
|
return false;
|
|
|
|
|
}
|
2019-02-13 14:25:39 +01:00
|
|
|
|
|
|
|
|
minimum_delay_ms_ = delay_ms;
|
|
|
|
|
UpdateEffectiveMinimumDelay();
|
2013-08-16 23:44:24 +00:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool DelayManager::SetMaximumDelay(int delay_ms) {
|
2021-07-28 20:00:17 +02:00
|
|
|
// If `delay_ms` is zero then it unsets the maximum delay and target level is
|
2019-02-13 14:25:39 +01:00
|
|
|
// unconstrained by maximum delay.
|
|
|
|
|
if (delay_ms != 0 &&
|
|
|
|
|
(delay_ms < minimum_delay_ms_ || delay_ms < packet_len_ms_)) {
|
2013-08-16 23:44:24 +00:00
|
|
|
// Maximum delay shouldn't be less than minimum delay or less than a packet.
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2019-02-13 14:25:39 +01:00
|
|
|
|
2013-08-16 23:44:24 +00:00
|
|
|
maximum_delay_ms_ = delay_ms;
|
2019-02-13 14:25:39 +01:00
|
|
|
UpdateEffectiveMinimumDelay();
|
2013-08-16 23:44:24 +00:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-04 16:17:31 +01:00
|
|
|
bool DelayManager::SetBaseMinimumDelay(int delay_ms) {
|
2019-02-13 14:25:39 +01:00
|
|
|
if (!IsValidBaseMinimumDelay(delay_ms)) {
|
2019-02-04 16:17:31 +01:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-13 14:25:39 +01:00
|
|
|
base_minimum_delay_ms_ = delay_ms;
|
|
|
|
|
UpdateEffectiveMinimumDelay();
|
2019-02-04 16:17:31 +01:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int DelayManager::GetBaseMinimumDelay() const {
|
2019-02-13 14:25:39 +01:00
|
|
|
return base_minimum_delay_ms_;
|
2019-02-04 16:17:31 +01:00
|
|
|
}
|
|
|
|
|
|
2019-02-13 14:25:39 +01:00
|
|
|
void DelayManager::UpdateEffectiveMinimumDelay() {
|
2021-07-28 20:00:17 +02:00
|
|
|
// Clamp `base_minimum_delay_ms_` into the range which can be effectively
|
2019-02-13 14:25:39 +01:00
|
|
|
// used.
|
|
|
|
|
const int base_minimum_delay_ms =
|
|
|
|
|
rtc::SafeClamp(base_minimum_delay_ms_, 0, MinimumDelayUpperBound());
|
|
|
|
|
effective_minimum_delay_ms_ =
|
|
|
|
|
std::max(minimum_delay_ms_, base_minimum_delay_ms);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int DelayManager::MinimumDelayUpperBound() const {
|
|
|
|
|
// Choose the lowest possible bound discarding 0 cases which mean the value
|
|
|
|
|
// is not set and unconstrained.
|
2020-10-09 13:41:06 +02:00
|
|
|
int q75 = max_packets_in_buffer_ * packet_len_ms_ * 3 / 4;
|
2019-02-13 14:25:39 +01:00
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-29 12:09:21 +00:00
|
|
|
} // namespace webrtc
|