blob: 0003d3243bc1cf69ca959467331deafe7a05d368 [file] [log] [blame]
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +00001/*
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "modules/audio_coding/neteq/delay_manager.h"
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000012
13#include <assert.h>
Yves Gerey988cc082018-10-23 12:03:01 +020014#include <stdio.h>
15#include <stdlib.h>
Jonas Olssona4d87372019-07-05 19:08:33 +020016
Yves Gerey988cc082018-10-23 12:03:01 +020017#include <algorithm>
Mirko Bonadei317a1f02019-09-17 17:06:18 +020018#include <memory>
Ivo Creusen385b10b2017-10-13 12:37:27 +020019#include <numeric>
Yves Gerey988cc082018-10-23 12:03:01 +020020#include <string>
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000021
Jakob Ivarssondb42ed22019-02-27 10:08:09 +010022#include "modules/audio_coding/neteq/histogram.h"
Yves Gerey988cc082018-10-23 12:03:01 +020023#include "modules/include/module_common_types_public.h"
24#include "rtc_base/checks.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020025#include "rtc_base/logging.h"
Karl Wiberge40468b2017-11-22 10:42:26 +010026#include "rtc_base/numerics/safe_conversions.h"
Ruslan Burakov4a68fb92019-02-13 14:25:39 +010027#include "rtc_base/numerics/safe_minmax.h"
Ivo Creusen385b10b2017-10-13 12:37:27 +020028#include "system_wrappers/include/field_trial.h"
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000029
Minyue Li002fbb82018-10-04 11:31:03 +020030namespace {
31
Ruslan Burakov4a68fb92019-02-13 14:25:39 +010032constexpr int kMinBaseMinimumDelayMs = 0;
33constexpr int kMaxBaseMinimumDelayMs = 10000;
Jakob Ivarssone98954c2019-02-06 15:37:50 +010034constexpr int kMaxReorderedPackets =
35 10; // Max number of consecutive reordered packets.
Jakob Ivarsson74154e62019-08-22 15:00:16 +020036constexpr int kMaxHistoryMs = 2000; // Oldest packet to include in history to
37 // calculate relative packet arrival delay.
Jakob Ivarssondb42ed22019-02-27 10:08:09 +010038constexpr int kDelayBuckets = 100;
39constexpr int kBucketSizeMs = 20;
Ruslan Burakovaa5a75d2019-09-12 15:44:18 +020040constexpr int kDecelerationTargetLevelOffsetMs = 85 << 8; // In Q8.
Jakob Ivarssondb42ed22019-02-27 10:08:09 +010041
42int PercentileToQuantile(double percentile) {
43 return static_cast<int>((1 << 30) * percentile / 100.0 + 0.5);
44}
Minyue Li002fbb82018-10-04 11:31:03 +020045
Jakob Ivarssondb42ed22019-02-27 10:08:09 +010046struct DelayHistogramConfig {
Jakob Ivarsson507f4342019-09-03 13:04:41 +020047 int quantile = 1041529569; // 0.97 in Q30.
Jakob Ivarssondb42ed22019-02-27 10:08:09 +010048 int forget_factor = 32745; // 0.9993 in Q15.
Jakob Ivarsson507f4342019-09-03 13:04:41 +020049 absl::optional<double> start_forget_weight = 2;
Jakob Ivarssondb42ed22019-02-27 10:08:09 +010050};
51
Jakob Ivarsson507f4342019-09-03 13:04:41 +020052DelayHistogramConfig GetDelayHistogramConfig() {
Jakob Ivarssondb42ed22019-02-27 10:08:09 +010053 constexpr char kDelayHistogramFieldTrial[] =
54 "WebRTC-Audio-NetEqDelayHistogram";
Jakob Ivarsson507f4342019-09-03 13:04:41 +020055 DelayHistogramConfig config;
56 if (webrtc::field_trial::IsEnabled(kDelayHistogramFieldTrial)) {
Jakob Ivarssondb42ed22019-02-27 10:08:09 +010057 const auto field_trial_string =
58 webrtc::field_trial::FindFullName(kDelayHistogramFieldTrial);
Jakob Ivarssondb42ed22019-02-27 10:08:09 +010059 double percentile = -1.0;
60 double forget_factor = -1.0;
Jakob Ivarssone9a2ee22019-05-22 16:54:09 +020061 double start_forget_weight = -1.0;
62 if (sscanf(field_trial_string.c_str(), "Enabled-%lf-%lf-%lf", &percentile,
63 &forget_factor, &start_forget_weight) >= 2 &&
Jakob Ivarssondb42ed22019-02-27 10:08:09 +010064 percentile >= 0.0 && percentile <= 100.0 && forget_factor >= 0.0 &&
65 forget_factor <= 1.0) {
66 config.quantile = PercentileToQuantile(percentile);
67 config.forget_factor = (1 << 15) * forget_factor;
Jakob Ivarsson507f4342019-09-03 13:04:41 +020068 config.start_forget_weight =
69 start_forget_weight >= 1 ? absl::make_optional(start_forget_weight)
70 : absl::nullopt;
Jakob Ivarssondb42ed22019-02-27 10:08:09 +010071 }
Jakob Ivarssondb42ed22019-02-27 10:08:09 +010072 }
Jakob Ivarsson507f4342019-09-03 13:04:41 +020073 RTC_LOG(LS_INFO) << "Delay histogram config:"
74 << " quantile=" << config.quantile
75 << " forget_factor=" << config.forget_factor
76 << " start_forget_weight="
77 << config.start_forget_weight.value_or(0);
78 return config;
Jakob Ivarssondb42ed22019-02-27 10:08:09 +010079}
80
Minyue Li002fbb82018-10-04 11:31:03 +020081} // namespace
82
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000083namespace webrtc {
84
Peter Kastingdce40cf2015-08-24 14:52:23 -070085DelayManager::DelayManager(size_t max_packets_in_buffer,
Ruslan Burakov4a68fb92019-02-13 14:25:39 +010086 int base_minimum_delay_ms,
Jakob Ivarssondb42ed22019-02-27 10:08:09 +010087 int histogram_quantile,
Jakob Ivarssone98954c2019-02-06 15:37:50 +010088 bool enable_rtx_handling,
Jakob Ivarsson1eb3d7e2019-02-21 15:42:31 +010089 const TickTimer* tick_timer,
Jakob Ivarssondb42ed22019-02-27 10:08:09 +010090 std::unique_ptr<Histogram> histogram)
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000091 : first_packet_received_(false),
92 max_packets_in_buffer_(max_packets_in_buffer),
Jakob Ivarssondb42ed22019-02-27 10:08:09 +010093 histogram_(std::move(histogram)),
94 histogram_quantile_(histogram_quantile),
henrik.lundin8f8c96d2016-04-28 23:19:20 -070095 tick_timer_(tick_timer),
Ruslan Burakov4a68fb92019-02-13 14:25:39 +010096 base_minimum_delay_ms_(base_minimum_delay_ms),
97 effective_minimum_delay_ms_(base_minimum_delay_ms),
Ivo Creusen385b10b2017-10-13 12:37:27 +020098 base_target_level_(4), // In Q0 domain.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000099 target_level_(base_target_level_ << 8), // In Q8 domain.
100 packet_len_ms_(0),
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000101 last_seq_no_(0),
102 last_timestamp_(0),
Ruslan Burakov76a74e62019-02-22 19:28:02 +0100103 minimum_delay_ms_(0),
Ruslan Burakovb35bacc2019-02-20 13:41:59 +0100104 maximum_delay_ms_(0),
Ivo Creusen385b10b2017-10-13 12:37:27 +0200105 last_pack_cng_or_dtmf_(1),
Jakob Ivarsson2ee15eb2020-01-08 14:29:04 +0100106 enable_rtx_handling_(enable_rtx_handling) {
Jakob Ivarssondb42ed22019-02-27 10:08:09 +0100107 RTC_CHECK(histogram_);
Ruslan Burakov4a68fb92019-02-13 14:25:39 +0100108 RTC_DCHECK_GE(base_minimum_delay_ms_, 0);
Minyue Li002fbb82018-10-04 11:31:03 +0200109
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000110 Reset();
111}
112
Jakob Ivarsson1eb3d7e2019-02-21 15:42:31 +0100113std::unique_ptr<DelayManager> DelayManager::Create(
114 size_t max_packets_in_buffer,
115 int base_minimum_delay_ms,
116 bool enable_rtx_handling,
Ivo Creusen53a31f72019-10-24 15:20:39 +0200117 const TickTimer* tick_timer) {
Jakob Ivarsson507f4342019-09-03 13:04:41 +0200118 DelayHistogramConfig config = GetDelayHistogramConfig();
119 const int quantile = config.quantile;
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200120 std::unique_ptr<Histogram> histogram = std::make_unique<Histogram>(
Jakob Ivarsson507f4342019-09-03 13:04:41 +0200121 kDelayBuckets, config.forget_factor, config.start_forget_weight);
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200122 return std::make_unique<DelayManager>(
Jakob Ivarssonbd5874a2020-01-07 17:07:40 +0100123 max_packets_in_buffer, base_minimum_delay_ms, quantile,
124 enable_rtx_handling, tick_timer, std::move(histogram));
Jakob Ivarsson1eb3d7e2019-02-21 15:42:31 +0100125}
126
pbos@webrtc.org2d1a55c2013-07-31 15:54:00 +0000127DelayManager::~DelayManager() {}
128
Ivo Creusen53a31f72019-10-24 15:20:39 +0200129absl::optional<int> DelayManager::Update(uint16_t sequence_number,
130 uint32_t timestamp,
131 int sample_rate_hz) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000132 if (sample_rate_hz <= 0) {
Ivo Creusen53a31f72019-10-24 15:20:39 +0200133 return absl::nullopt;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000134 }
135
136 if (!first_packet_received_) {
137 // Prepare for next packet arrival.
henrik.lundin8f8c96d2016-04-28 23:19:20 -0700138 packet_iat_stopwatch_ = tick_timer_->GetNewStopwatch();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000139 last_seq_no_ = sequence_number;
140 last_timestamp_ = timestamp;
141 first_packet_received_ = true;
Ivo Creusen53a31f72019-10-24 15:20:39 +0200142 return absl::nullopt;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000143 }
144
145 // Try calculating packet length from current and previous timestamps.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000146 int packet_len_ms;
turaj@webrtc.org78b41a02013-11-22 20:27:07 +0000147 if (!IsNewerTimestamp(timestamp, last_timestamp_) ||
148 !IsNewerSequenceNumber(sequence_number, last_seq_no_)) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000149 // Wrong timestamp or sequence order; use stored value.
150 packet_len_ms = packet_len_ms_;
151 } else {
152 // Calculate timestamps per packet and derive packet length in ms.
henrik.lundin07c51e32016-02-11 03:35:43 -0800153 int64_t packet_len_samp =
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000154 static_cast<uint32_t>(timestamp - last_timestamp_) /
155 static_cast<uint16_t>(sequence_number - last_seq_no_);
henrik.lundin07c51e32016-02-11 03:35:43 -0800156 packet_len_ms =
henrik.lundin38d840c2016-08-18 03:49:32 -0700157 rtc::saturated_cast<int>(1000 * packet_len_samp / sample_rate_hz);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000158 }
159
Jakob Ivarssone98954c2019-02-06 15:37:50 +0100160 bool reordered = false;
Ivo Creusen53a31f72019-10-24 15:20:39 +0200161 absl::optional<int> relative_delay;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000162 if (packet_len_ms > 0) {
163 // Cannot update statistics unless |packet_len_ms| is valid.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000164
Jakob Ivarssondb42ed22019-02-27 10:08:09 +0100165 // Inter-arrival time (IAT) in integer "packet times" (rounding down). This
166 // is the value added to the inter-arrival time histogram.
167 int iat_ms = packet_iat_stopwatch_->ElapsedMs();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000168 // Check for discontinuous packet sequence and re-ordering.
turaj@webrtc.org78b41a02013-11-22 20:27:07 +0000169 if (IsNewerSequenceNumber(sequence_number, last_seq_no_ + 1)) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000170 // Compensate for gap in the sequence numbers. Reduce IAT with the
Jakob Ivarsson37b56622019-03-18 16:48:15 +0100171 // expected extra time due to lost packets.
Jakob Ivarssondb42ed22019-02-27 10:08:09 +0100172 int packet_offset =
173 static_cast<uint16_t>(sequence_number - last_seq_no_ - 1);
Jakob Ivarssondb42ed22019-02-27 10:08:09 +0100174 iat_ms -= packet_offset * packet_len_ms;
turaj@webrtc.org78b41a02013-11-22 20:27:07 +0000175 } else if (!IsNewerSequenceNumber(sequence_number, last_seq_no_)) {
Jakob Ivarssondb42ed22019-02-27 10:08:09 +0100176 int packet_offset =
177 static_cast<uint16_t>(last_seq_no_ + 1 - sequence_number);
Jakob Ivarssondb42ed22019-02-27 10:08:09 +0100178 iat_ms += packet_offset * packet_len_ms;
Jakob Ivarsson39b934b2019-01-10 10:28:23 +0100179 reordered = true;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000180 }
181
Jakob Ivarsson44507082019-03-05 16:59:03 +0100182 int iat_delay = iat_ms - packet_len_ms;
Jakob Ivarsson44507082019-03-05 16:59:03 +0100183 if (reordered) {
184 relative_delay = std::max(iat_delay, 0);
185 } else {
Jakob Ivarsson74154e62019-08-22 15:00:16 +0200186 UpdateDelayHistory(iat_delay, timestamp, sample_rate_hz);
Jakob Ivarsson44507082019-03-05 16:59:03 +0100187 relative_delay = CalculateRelativePacketArrivalDelay();
188 }
Jakob Ivarsson44507082019-03-05 16:59:03 +0100189
Jakob Ivarssonbd5874a2020-01-07 17:07:40 +0100190 const int index = relative_delay.value() / kBucketSizeMs;
191 if (index < histogram_->NumBuckets()) {
192 // Maximum delay to register is 2000 ms.
193 histogram_->Add(index);
Jakob Ivarssondb42ed22019-02-27 10:08:09 +0100194 }
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000195 // Calculate new |target_level_| based on updated statistics.
Jakob Ivarssonbd5874a2020-01-07 17:07:40 +0100196 target_level_ = CalculateTargetLevel();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000197
198 LimitTargetLevel();
199 } // End if (packet_len_ms > 0).
200
Jakob Ivarssone98954c2019-02-06 15:37:50 +0100201 if (enable_rtx_handling_ && reordered &&
202 num_reordered_packets_ < kMaxReorderedPackets) {
203 ++num_reordered_packets_;
Ivo Creusen53a31f72019-10-24 15:20:39 +0200204 return relative_delay;
Jakob Ivarssone98954c2019-02-06 15:37:50 +0100205 }
206 num_reordered_packets_ = 0;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000207 // Prepare for next packet arrival.
henrik.lundin8f8c96d2016-04-28 23:19:20 -0700208 packet_iat_stopwatch_ = tick_timer_->GetNewStopwatch();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000209 last_seq_no_ = sequence_number;
210 last_timestamp_ = timestamp;
Ivo Creusen53a31f72019-10-24 15:20:39 +0200211 return relative_delay;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000212}
213
Jakob Ivarsson74154e62019-08-22 15:00:16 +0200214void DelayManager::UpdateDelayHistory(int iat_delay_ms,
215 uint32_t timestamp,
216 int sample_rate_hz) {
217 PacketDelay delay;
218 delay.iat_delay_ms = iat_delay_ms;
219 delay.timestamp = timestamp;
220 delay_history_.push_back(delay);
221 while (timestamp - delay_history_.front().timestamp >
222 static_cast<uint32_t>(kMaxHistoryMs * sample_rate_hz / 1000)) {
Jakob Ivarssondb42ed22019-02-27 10:08:09 +0100223 delay_history_.pop_front();
224 }
225}
226
227int DelayManager::CalculateRelativePacketArrivalDelay() const {
228 // This effectively calculates arrival delay of a packet relative to the
229 // packet preceding the history window. If the arrival delay ever becomes
230 // smaller than zero, it means the reference packet is invalid, and we
231 // move the reference.
232 int relative_delay = 0;
Jakob Ivarsson74154e62019-08-22 15:00:16 +0200233 for (const PacketDelay& delay : delay_history_) {
234 relative_delay += delay.iat_delay_ms;
Jakob Ivarssondb42ed22019-02-27 10:08:09 +0100235 relative_delay = std::max(relative_delay, 0);
236 }
237 return relative_delay;
238}
239
turaj@webrtc.orgf1efc572013-08-16 23:44:24 +0000240// Enforces upper and lower limits for |target_level_|. The upper limit is
241// chosen to be minimum of i) 75% of |max_packets_in_buffer_|, to leave some
242// headroom for natural fluctuations around the target, and ii) equivalent of
243// |maximum_delay_ms_| in packets. Note that in practice, if no
244// |maximum_delay_ms_| is specified, this does not have any impact, since the
245// target level is far below the buffer capacity in all reasonable cases.
Ruslan Burakov4a68fb92019-02-13 14:25:39 +0100246// The lower limit is equivalent of |effective_minimum_delay_ms_| in packets.
247// We update |least_required_level_| while the above limits are applied.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000248// TODO(hlundin): Move this check to the buffer logistics class.
249void DelayManager::LimitTargetLevel() {
Ruslan Burakov4a68fb92019-02-13 14:25:39 +0100250 if (packet_len_ms_ > 0 && effective_minimum_delay_ms_ > 0) {
251 int minimum_delay_packet_q8 =
252 (effective_minimum_delay_ms_ << 8) / packet_len_ms_;
turaj@webrtc.orgf1efc572013-08-16 23:44:24 +0000253 target_level_ = std::max(target_level_, minimum_delay_packet_q8);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000254 }
turaj@webrtc.orgf1efc572013-08-16 23:44:24 +0000255
256 if (maximum_delay_ms_ > 0 && packet_len_ms_ > 0) {
257 int maximum_delay_packet_q8 = (maximum_delay_ms_ << 8) / packet_len_ms_;
258 target_level_ = std::min(target_level_, maximum_delay_packet_q8);
259 }
260
261 // Shift to Q8, then 75%.;
Peter Kastingdce40cf2015-08-24 14:52:23 -0700262 int max_buffer_packets_q8 =
263 static_cast<int>((3 * (max_packets_in_buffer_ << 8)) / 4);
turaj@webrtc.orgf1efc572013-08-16 23:44:24 +0000264 target_level_ = std::min(target_level_, max_buffer_packets_q8);
265
266 // Sanity check, at least 1 packet (in Q8).
267 target_level_ = std::max(target_level_, 1 << 8);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000268}
269
Jakob Ivarssonbd5874a2020-01-07 17:07:40 +0100270int DelayManager::CalculateTargetLevel() {
Jakob Ivarssondb42ed22019-02-27 10:08:09 +0100271 int limit_probability = histogram_quantile_;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000272
Jakob Ivarssondb42ed22019-02-27 10:08:09 +0100273 int bucket_index = histogram_->Quantile(limit_probability);
Jakob Ivarssonbd5874a2020-01-07 17:07:40 +0100274 int target_level = 1;
275 if (packet_len_ms_ > 0) {
276 target_level += bucket_index * kBucketSizeMs / packet_len_ms_;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000277 }
Jakob Ivarssonbd5874a2020-01-07 17:07:40 +0100278 base_target_level_ = target_level;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000279
280 // Sanity check. |target_level| must be strictly positive.
281 target_level = std::max(target_level, 1);
282 // Scale to Q8 and assign to member variable.
283 target_level_ = target_level << 8;
284 return target_level_;
285}
286
287int DelayManager::SetPacketAudioLength(int length_ms) {
288 if (length_ms <= 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100289 RTC_LOG_F(LS_ERROR) << "length_ms = " << length_ms;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000290 return -1;
291 }
Ivo Creusen385b10b2017-10-13 12:37:27 +0200292
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000293 packet_len_ms_ = length_ms;
henrik.lundin8f8c96d2016-04-28 23:19:20 -0700294 packet_iat_stopwatch_ = tick_timer_->GetNewStopwatch();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000295 last_pack_cng_or_dtmf_ = 1; // TODO(hlundin): Legacy. Remove?
296 return 0;
297}
298
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000299void DelayManager::Reset() {
300 packet_len_ms_ = 0; // Packet size unknown.
Jakob Ivarssondb42ed22019-02-27 10:08:09 +0100301 histogram_->Reset();
Jakob Ivarsson74154e62019-08-22 15:00:16 +0200302 delay_history_.clear();
Jakob Ivarsson1eb3d7e2019-02-21 15:42:31 +0100303 base_target_level_ = 4;
304 target_level_ = base_target_level_ << 8;
henrik.lundin8f8c96d2016-04-28 23:19:20 -0700305 packet_iat_stopwatch_ = tick_timer_->GetNewStopwatch();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000306 last_pack_cng_or_dtmf_ = 1;
307}
308
henrik.lundin8f8c96d2016-04-28 23:19:20 -0700309void DelayManager::ResetPacketIatCount() {
310 packet_iat_stopwatch_ = tick_timer_->GetNewStopwatch();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000311}
312
Ruslan Burakov1e193fa2019-05-15 14:31:22 +0200313void DelayManager::BufferLimits(int* lower_limit, int* higher_limit) const {
314 BufferLimits(target_level_, lower_limit, higher_limit);
315}
316
turaj@webrtc.orgf1efc572013-08-16 23:44:24 +0000317// Note that |low_limit| and |higher_limit| are not assigned to
318// |minimum_delay_ms_| and |maximum_delay_ms_| defined by the client of this
Ruslan Burakov1e193fa2019-05-15 14:31:22 +0200319// class. They are computed from |target_level| in Q8 and used for decision
320// making.
321void DelayManager::BufferLimits(int target_level,
322 int* lower_limit,
323 int* higher_limit) const {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000324 if (!lower_limit || !higher_limit) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100325 RTC_LOG_F(LS_ERROR) << "NULL pointers supplied as input";
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000326 assert(false);
327 return;
328 }
329
Ruslan Burakov1e193fa2019-05-15 14:31:22 +0200330 // |target_level| is in Q8 already.
331 *lower_limit = (target_level * 3) / 4;
332
Ruslan Burakovaa5a75d2019-09-12 15:44:18 +0200333 if (packet_len_ms_ > 0) {
334 *lower_limit =
335 std::max(*lower_limit, target_level - kDecelerationTargetLevelOffsetMs /
336 packet_len_ms_);
Ruslan Burakov1e193fa2019-05-15 14:31:22 +0200337 }
338
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000339 int window_20ms = 0x7FFF; // Default large value for legacy bit-exactness.
340 if (packet_len_ms_ > 0) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000341 window_20ms = (20 << 8) / packet_len_ms_;
342 }
Ruslan Burakov1e193fa2019-05-15 14:31:22 +0200343 // |higher_limit| is equal to |target_level|, but should at
344 // least be 20 ms higher than |lower_limit|.
345 *higher_limit = std::max(target_level, *lower_limit + window_20ms);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000346}
347
348int DelayManager::TargetLevel() const {
turaj@webrtc.orgf1efc572013-08-16 23:44:24 +0000349 return target_level_;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000350}
351
ossuf1b08da2016-09-23 02:19:43 -0700352void DelayManager::LastDecodedWasCngOrDtmf(bool it_was) {
353 if (it_was) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000354 last_pack_cng_or_dtmf_ = 1;
355 } else if (last_pack_cng_or_dtmf_ != 0) {
356 last_pack_cng_or_dtmf_ = -1;
357 }
358}
pbos@webrtc.org2d1a55c2013-07-31 15:54:00 +0000359
henrik.lundinb8c55b12017-05-10 07:38:01 -0700360void DelayManager::RegisterEmptyPacket() {
361 ++last_seq_no_;
362}
363
Ruslan Burakov4a68fb92019-02-13 14:25:39 +0100364bool DelayManager::IsValidMinimumDelay(int delay_ms) const {
365 return 0 <= delay_ms && delay_ms <= MinimumDelayUpperBound();
366}
367
368bool DelayManager::IsValidBaseMinimumDelay(int delay_ms) const {
369 return kMinBaseMinimumDelayMs <= delay_ms &&
370 delay_ms <= kMaxBaseMinimumDelayMs;
Ruslan Burakovedbea462019-02-04 16:17:31 +0100371}
372
turaj@webrtc.orgf1efc572013-08-16 23:44:24 +0000373bool DelayManager::SetMinimumDelay(int delay_ms) {
Ruslan Burakovedbea462019-02-04 16:17:31 +0100374 if (!IsValidMinimumDelay(delay_ms)) {
turaj@webrtc.orgf1efc572013-08-16 23:44:24 +0000375 return false;
376 }
Ruslan Burakov4a68fb92019-02-13 14:25:39 +0100377
378 minimum_delay_ms_ = delay_ms;
379 UpdateEffectiveMinimumDelay();
turaj@webrtc.orgf1efc572013-08-16 23:44:24 +0000380 return true;
381}
382
383bool DelayManager::SetMaximumDelay(int delay_ms) {
Ruslan Burakov4a68fb92019-02-13 14:25:39 +0100384 // If |delay_ms| is zero then it unsets the maximum delay and target level is
385 // unconstrained by maximum delay.
386 if (delay_ms != 0 &&
387 (delay_ms < minimum_delay_ms_ || delay_ms < packet_len_ms_)) {
turaj@webrtc.orgf1efc572013-08-16 23:44:24 +0000388 // Maximum delay shouldn't be less than minimum delay or less than a packet.
389 return false;
390 }
Ruslan Burakov4a68fb92019-02-13 14:25:39 +0100391
turaj@webrtc.orgf1efc572013-08-16 23:44:24 +0000392 maximum_delay_ms_ = delay_ms;
Ruslan Burakov4a68fb92019-02-13 14:25:39 +0100393 UpdateEffectiveMinimumDelay();
turaj@webrtc.orgf1efc572013-08-16 23:44:24 +0000394 return true;
395}
396
Ruslan Burakovedbea462019-02-04 16:17:31 +0100397bool DelayManager::SetBaseMinimumDelay(int delay_ms) {
Ruslan Burakov4a68fb92019-02-13 14:25:39 +0100398 if (!IsValidBaseMinimumDelay(delay_ms)) {
Ruslan Burakovedbea462019-02-04 16:17:31 +0100399 return false;
400 }
401
Ruslan Burakov4a68fb92019-02-13 14:25:39 +0100402 base_minimum_delay_ms_ = delay_ms;
403 UpdateEffectiveMinimumDelay();
Ruslan Burakovedbea462019-02-04 16:17:31 +0100404 return true;
405}
406
407int DelayManager::GetBaseMinimumDelay() const {
Ruslan Burakov4a68fb92019-02-13 14:25:39 +0100408 return base_minimum_delay_ms_;
Ruslan Burakovedbea462019-02-04 16:17:31 +0100409}
410
Yves Gerey665174f2018-06-19 15:03:05 +0200411int DelayManager::base_target_level() const {
412 return base_target_level_;
413}
pbos@webrtc.org2d1a55c2013-07-31 15:54:00 +0000414int DelayManager::last_pack_cng_or_dtmf() const {
415 return last_pack_cng_or_dtmf_;
416}
417
418void DelayManager::set_last_pack_cng_or_dtmf(int value) {
419 last_pack_cng_or_dtmf_ = value;
420}
Ruslan Burakov4a68fb92019-02-13 14:25:39 +0100421
422void DelayManager::UpdateEffectiveMinimumDelay() {
423 // Clamp |base_minimum_delay_ms_| into the range which can be effectively
424 // used.
425 const int base_minimum_delay_ms =
426 rtc::SafeClamp(base_minimum_delay_ms_, 0, MinimumDelayUpperBound());
427 effective_minimum_delay_ms_ =
428 std::max(minimum_delay_ms_, base_minimum_delay_ms);
429}
430
431int DelayManager::MinimumDelayUpperBound() const {
432 // Choose the lowest possible bound discarding 0 cases which mean the value
433 // is not set and unconstrained.
434 int q75 = MaxBufferTimeQ75();
435 q75 = q75 > 0 ? q75 : kMaxBaseMinimumDelayMs;
436 const int maximum_delay_ms =
437 maximum_delay_ms_ > 0 ? maximum_delay_ms_ : kMaxBaseMinimumDelayMs;
438 return std::min(maximum_delay_ms, q75);
439}
440
441int DelayManager::MaxBufferTimeQ75() const {
442 const int max_buffer_time = max_packets_in_buffer_ * packet_len_ms_;
443 return rtc::dchecked_cast<int>(3 * max_buffer_time / 4);
444}
Ruslan Burakovaa5a75d2019-09-12 15:44:18 +0200445
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000446} // namespace webrtc