blob: 1c7ad1902556385ceaa35decc07200354a8448cd [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>
16#include <algorithm>
Ivo Creusen385b10b2017-10-13 12:37:27 +020017#include <numeric>
Yves Gerey988cc082018-10-23 12:03:01 +020018#include <string>
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000019
Jakob Ivarsson1eb3d7e2019-02-21 15:42:31 +010020#include "absl/memory/memory.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020021#include "modules/audio_coding/neteq/delay_peak_detector.h"
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
Jakob Ivarsson1eb3d7e2019-02-21 15:42:31 +010032constexpr int kLimitProbability = 1020054733; // 19/20 in Q30.
33constexpr int kLimitProbabilityStreaming = 1073204953; // 1999/2000 in Q30.
34constexpr int kMaxStreamingPeakPeriodMs = 600000; // 10 minutes in ms.
Minyue Li002fbb82018-10-04 11:31:03 +020035constexpr int kCumulativeSumDrift = 2; // Drift term for cumulative sum
36 // |iat_cumulative_sum_|.
Ruslan Burakov4a68fb92019-02-13 14:25:39 +010037constexpr int kMinBaseMinimumDelayMs = 0;
38constexpr int kMaxBaseMinimumDelayMs = 10000;
Jakob Ivarsson1eb3d7e2019-02-21 15:42:31 +010039constexpr int kIatFactor = 32745; // 0.9993 in Q15.
40constexpr int kMaxIat = 64; // Max inter-arrival time to register.
Jakob Ivarssone98954c2019-02-06 15:37:50 +010041constexpr int kMaxReorderedPackets =
42 10; // Max number of consecutive reordered packets.
Jakob Ivarssondb42ed22019-02-27 10:08:09 +010043constexpr int kMaxHistoryPackets =
44 100; // Max number of packets used to calculate relative packet arrival
45 // delay.
46constexpr int kDelayBuckets = 100;
47constexpr int kBucketSizeMs = 20;
48
49int PercentileToQuantile(double percentile) {
50 return static_cast<int>((1 << 30) * percentile / 100.0 + 0.5);
51}
Minyue Li002fbb82018-10-04 11:31:03 +020052
53absl::optional<int> GetForcedLimitProbability() {
54 constexpr char kForceTargetDelayPercentileFieldTrial[] =
55 "WebRTC-Audio-NetEqForceTargetDelayPercentile";
56 const bool use_forced_target_delay_percentile =
57 webrtc::field_trial::IsEnabled(kForceTargetDelayPercentileFieldTrial);
58 if (use_forced_target_delay_percentile) {
59 const std::string field_trial_string = webrtc::field_trial::FindFullName(
60 kForceTargetDelayPercentileFieldTrial);
61 double percentile = -1.0;
62 if (sscanf(field_trial_string.c_str(), "Enabled-%lf", &percentile) == 1 &&
63 percentile >= 0.0 && percentile <= 100.0) {
Jakob Ivarsson1eb3d7e2019-02-21 15:42:31 +010064 return absl::make_optional<int>(
Jakob Ivarssondb42ed22019-02-27 10:08:09 +010065 PercentileToQuantile(percentile)); // in Q30.
Minyue Li002fbb82018-10-04 11:31:03 +020066 } else {
67 RTC_LOG(LS_WARNING) << "Invalid parameter for "
68 << kForceTargetDelayPercentileFieldTrial
69 << ", ignored.";
70 }
71 }
72 return absl::nullopt;
73}
74
Jakob Ivarssondb42ed22019-02-27 10:08:09 +010075struct DelayHistogramConfig {
76 int quantile = 1020054733; // 0.95 in Q30.
77 int forget_factor = 32745; // 0.9993 in Q15.
78};
79
80absl::optional<DelayHistogramConfig> GetDelayHistogramConfig() {
81 constexpr char kDelayHistogramFieldTrial[] =
82 "WebRTC-Audio-NetEqDelayHistogram";
83 const bool use_new_delay_manager =
84 webrtc::field_trial::IsEnabled(kDelayHistogramFieldTrial);
85 if (use_new_delay_manager) {
86 const auto field_trial_string =
87 webrtc::field_trial::FindFullName(kDelayHistogramFieldTrial);
88 DelayHistogramConfig config;
89 double percentile = -1.0;
90 double forget_factor = -1.0;
91 if (sscanf(field_trial_string.c_str(), "Enabled-%lf-%lf", &percentile,
92 &forget_factor) == 2 &&
93 percentile >= 0.0 && percentile <= 100.0 && forget_factor >= 0.0 &&
94 forget_factor <= 1.0) {
95 config.quantile = PercentileToQuantile(percentile);
96 config.forget_factor = (1 << 15) * forget_factor;
97 }
98 RTC_LOG(LS_INFO) << "Delay histogram config:"
99 << " quantile=" << config.quantile
100 << " forget_factor=" << config.forget_factor;
101 return absl::make_optional(config);
102 }
103 return absl::nullopt;
104}
105
Minyue Li002fbb82018-10-04 11:31:03 +0200106} // namespace
107
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000108namespace webrtc {
109
Peter Kastingdce40cf2015-08-24 14:52:23 -0700110DelayManager::DelayManager(size_t max_packets_in_buffer,
Ruslan Burakov4a68fb92019-02-13 14:25:39 +0100111 int base_minimum_delay_ms,
Jakob Ivarssondb42ed22019-02-27 10:08:09 +0100112 int histogram_quantile,
113 HistogramMode histogram_mode,
Jakob Ivarssone98954c2019-02-06 15:37:50 +0100114 bool enable_rtx_handling,
henrik.lundin8f8c96d2016-04-28 23:19:20 -0700115 DelayPeakDetector* peak_detector,
Jakob Ivarsson1eb3d7e2019-02-21 15:42:31 +0100116 const TickTimer* tick_timer,
Jakob Ivarssondb42ed22019-02-27 10:08:09 +0100117 std::unique_ptr<Histogram> histogram)
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000118 : first_packet_received_(false),
119 max_packets_in_buffer_(max_packets_in_buffer),
Jakob Ivarssondb42ed22019-02-27 10:08:09 +0100120 histogram_(std::move(histogram)),
121 histogram_quantile_(histogram_quantile),
122 histogram_mode_(histogram_mode),
henrik.lundin8f8c96d2016-04-28 23:19:20 -0700123 tick_timer_(tick_timer),
Ruslan Burakov4a68fb92019-02-13 14:25:39 +0100124 base_minimum_delay_ms_(base_minimum_delay_ms),
125 effective_minimum_delay_ms_(base_minimum_delay_ms),
Ivo Creusen385b10b2017-10-13 12:37:27 +0200126 base_target_level_(4), // In Q0 domain.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000127 target_level_(base_target_level_ << 8), // In Q8 domain.
128 packet_len_ms_(0),
129 streaming_mode_(false),
130 last_seq_no_(0),
131 last_timestamp_(0),
Ruslan Burakov76a74e62019-02-22 19:28:02 +0100132 minimum_delay_ms_(0),
Ruslan Burakovb35bacc2019-02-20 13:41:59 +0100133 maximum_delay_ms_(0),
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000134 iat_cumulative_sum_(0),
135 max_iat_cumulative_sum_(0),
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000136 peak_detector_(*peak_detector),
Ivo Creusen385b10b2017-10-13 12:37:27 +0200137 last_pack_cng_or_dtmf_(1),
138 frame_length_change_experiment_(
Minyue Li002fbb82018-10-04 11:31:03 +0200139 field_trial::IsEnabled("WebRTC-Audio-NetEqFramelengthExperiment")),
Jakob Ivarssone98954c2019-02-06 15:37:50 +0100140 enable_rtx_handling_(enable_rtx_handling) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000141 assert(peak_detector); // Should never be NULL.
Jakob Ivarssondb42ed22019-02-27 10:08:09 +0100142 RTC_CHECK(histogram_);
Ruslan Burakov4a68fb92019-02-13 14:25:39 +0100143 RTC_DCHECK_GE(base_minimum_delay_ms_, 0);
Minyue Li002fbb82018-10-04 11:31:03 +0200144
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000145 Reset();
146}
147
Jakob Ivarsson1eb3d7e2019-02-21 15:42:31 +0100148std::unique_ptr<DelayManager> DelayManager::Create(
149 size_t max_packets_in_buffer,
150 int base_minimum_delay_ms,
151 bool enable_rtx_handling,
152 DelayPeakDetector* peak_detector,
153 const TickTimer* tick_timer) {
Jakob Ivarssondb42ed22019-02-27 10:08:09 +0100154 int quantile;
155 std::unique_ptr<Histogram> histogram;
156 HistogramMode mode;
157 auto delay_histogram_config = GetDelayHistogramConfig();
158 if (delay_histogram_config) {
159 DelayHistogramConfig config = delay_histogram_config.value();
160 quantile = config.quantile;
161 histogram =
162 absl::make_unique<Histogram>(kDelayBuckets, config.forget_factor);
163 mode = RELATIVE_ARRIVAL_DELAY;
164 } else {
165 quantile = GetForcedLimitProbability().value_or(kLimitProbability);
166 histogram = absl::make_unique<Histogram>(kMaxIat + 1, kIatFactor);
167 mode = INTER_ARRIVAL_TIME;
168 }
Jakob Ivarsson1eb3d7e2019-02-21 15:42:31 +0100169 return absl::make_unique<DelayManager>(
Jakob Ivarssondb42ed22019-02-27 10:08:09 +0100170 max_packets_in_buffer, base_minimum_delay_ms, quantile, mode,
171 enable_rtx_handling, peak_detector, tick_timer, std::move(histogram));
Jakob Ivarsson1eb3d7e2019-02-21 15:42:31 +0100172}
173
pbos@webrtc.org2d1a55c2013-07-31 15:54:00 +0000174DelayManager::~DelayManager() {}
175
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000176int DelayManager::Update(uint16_t sequence_number,
177 uint32_t timestamp,
178 int sample_rate_hz) {
179 if (sample_rate_hz <= 0) {
180 return -1;
181 }
182
183 if (!first_packet_received_) {
184 // Prepare for next packet arrival.
henrik.lundin8f8c96d2016-04-28 23:19:20 -0700185 packet_iat_stopwatch_ = tick_timer_->GetNewStopwatch();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000186 last_seq_no_ = sequence_number;
187 last_timestamp_ = timestamp;
188 first_packet_received_ = true;
189 return 0;
190 }
191
192 // Try calculating packet length from current and previous timestamps.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000193 int packet_len_ms;
turaj@webrtc.org78b41a02013-11-22 20:27:07 +0000194 if (!IsNewerTimestamp(timestamp, last_timestamp_) ||
195 !IsNewerSequenceNumber(sequence_number, last_seq_no_)) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000196 // Wrong timestamp or sequence order; use stored value.
197 packet_len_ms = packet_len_ms_;
198 } else {
199 // Calculate timestamps per packet and derive packet length in ms.
henrik.lundin07c51e32016-02-11 03:35:43 -0800200 int64_t packet_len_samp =
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000201 static_cast<uint32_t>(timestamp - last_timestamp_) /
202 static_cast<uint16_t>(sequence_number - last_seq_no_);
henrik.lundin07c51e32016-02-11 03:35:43 -0800203 packet_len_ms =
henrik.lundin38d840c2016-08-18 03:49:32 -0700204 rtc::saturated_cast<int>(1000 * packet_len_samp / sample_rate_hz);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000205 }
206
Jakob Ivarssone98954c2019-02-06 15:37:50 +0100207 bool reordered = false;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000208 if (packet_len_ms > 0) {
209 // Cannot update statistics unless |packet_len_ms| is valid.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000210 if (streaming_mode_) {
211 UpdateCumulativeSums(packet_len_ms, sequence_number);
212 }
213
Jakob Ivarssondb42ed22019-02-27 10:08:09 +0100214 // Inter-arrival time (IAT) in integer "packet times" (rounding down). This
215 // is the value added to the inter-arrival time histogram.
216 int iat_ms = packet_iat_stopwatch_->ElapsedMs();
217 int iat_packets = iat_ms / packet_len_ms;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000218 // Check for discontinuous packet sequence and re-ordering.
turaj@webrtc.org78b41a02013-11-22 20:27:07 +0000219 if (IsNewerSequenceNumber(sequence_number, last_seq_no_ + 1)) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000220 // Compensate for gap in the sequence numbers. Reduce IAT with the
221 // expected extra time due to lost packets, but ensure that the IAT is
222 // not negative.
Jakob Ivarssondb42ed22019-02-27 10:08:09 +0100223 int packet_offset =
224 static_cast<uint16_t>(sequence_number - last_seq_no_ - 1);
225 iat_packets -= packet_offset;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000226 iat_packets = std::max(iat_packets, 0);
Jakob Ivarssondb42ed22019-02-27 10:08:09 +0100227 iat_ms -= packet_offset * packet_len_ms;
228 iat_ms = std::max(iat_ms, 0);
turaj@webrtc.org78b41a02013-11-22 20:27:07 +0000229 } else if (!IsNewerSequenceNumber(sequence_number, last_seq_no_)) {
Jakob Ivarssondb42ed22019-02-27 10:08:09 +0100230 int packet_offset =
231 static_cast<uint16_t>(last_seq_no_ + 1 - sequence_number);
232 iat_packets += packet_offset;
233 iat_ms += packet_offset * packet_len_ms;
Jakob Ivarsson39b934b2019-01-10 10:28:23 +0100234 reordered = true;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000235 }
236
Jakob Ivarssondb42ed22019-02-27 10:08:09 +0100237 switch (histogram_mode_) {
238 case RELATIVE_ARRIVAL_DELAY: {
239 int iat_delay = iat_ms - packet_len_ms;
240 int relative_delay;
241 if (reordered) {
242 relative_delay = std::max(iat_delay, 0);
243 } else {
244 UpdateDelayHistory(iat_delay);
245 relative_delay = CalculateRelativePacketArrivalDelay();
246 }
247 const int index = relative_delay / kBucketSizeMs;
248 if (index < histogram_->NumBuckets()) {
249 // Maximum delay to register is 2000 ms.
250 histogram_->Add(index);
251 }
252 break;
253 }
254 case INTER_ARRIVAL_TIME: {
255 // Saturate IAT at maximum value.
256 iat_packets = std::min(iat_packets, histogram_->NumBuckets() - 1);
257 histogram_->Add(iat_packets);
258 break;
259 }
260 }
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000261 // Calculate new |target_level_| based on updated statistics.
Jakob Ivarsson39b934b2019-01-10 10:28:23 +0100262 target_level_ = CalculateTargetLevel(iat_packets, reordered);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000263 if (streaming_mode_) {
264 target_level_ = std::max(target_level_, max_iat_cumulative_sum_);
265 }
266
267 LimitTargetLevel();
268 } // End if (packet_len_ms > 0).
269
Jakob Ivarssone98954c2019-02-06 15:37:50 +0100270 if (enable_rtx_handling_ && reordered &&
271 num_reordered_packets_ < kMaxReorderedPackets) {
272 ++num_reordered_packets_;
273 return 0;
274 }
275 num_reordered_packets_ = 0;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000276 // Prepare for next packet arrival.
henrik.lundin8f8c96d2016-04-28 23:19:20 -0700277 packet_iat_stopwatch_ = tick_timer_->GetNewStopwatch();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000278 last_seq_no_ = sequence_number;
279 last_timestamp_ = timestamp;
280 return 0;
281}
282
Jakob Ivarssondb42ed22019-02-27 10:08:09 +0100283void DelayManager::UpdateDelayHistory(int iat_delay) {
284 delay_history_.push_back(iat_delay);
285 if (delay_history_.size() > kMaxHistoryPackets) {
286 delay_history_.pop_front();
287 }
288}
289
290int DelayManager::CalculateRelativePacketArrivalDelay() const {
291 // This effectively calculates arrival delay of a packet relative to the
292 // packet preceding the history window. If the arrival delay ever becomes
293 // smaller than zero, it means the reference packet is invalid, and we
294 // move the reference.
295 int relative_delay = 0;
296 for (int delay : delay_history_) {
297 relative_delay += delay;
298 relative_delay = std::max(relative_delay, 0);
299 }
300 return relative_delay;
301}
302
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000303void DelayManager::UpdateCumulativeSums(int packet_len_ms,
304 uint16_t sequence_number) {
305 // Calculate IAT in Q8, including fractions of a packet (i.e., more
306 // accurate than |iat_packets|.
henrik.lundin8f8c96d2016-04-28 23:19:20 -0700307 int iat_packets_q8 =
308 (packet_iat_stopwatch_->ElapsedMs() << 8) / packet_len_ms;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000309 // Calculate cumulative sum IAT with sequence number compensation. The sum
310 // is zero if there is no clock-drift.
Yves Gerey665174f2018-06-19 15:03:05 +0200311 iat_cumulative_sum_ +=
312 (iat_packets_q8 -
313 (static_cast<int>(sequence_number - last_seq_no_) << 8));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000314 // Subtract drift term.
315 iat_cumulative_sum_ -= kCumulativeSumDrift;
316 // Ensure not negative.
317 iat_cumulative_sum_ = std::max(iat_cumulative_sum_, 0);
318 if (iat_cumulative_sum_ > max_iat_cumulative_sum_) {
319 // Found a new maximum.
320 max_iat_cumulative_sum_ = iat_cumulative_sum_;
henrik.lundin8f8c96d2016-04-28 23:19:20 -0700321 max_iat_stopwatch_ = tick_timer_->GetNewStopwatch();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000322 }
henrik.lundin8f8c96d2016-04-28 23:19:20 -0700323 if (max_iat_stopwatch_->ElapsedMs() > kMaxStreamingPeakPeriodMs) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000324 // Too long since the last maximum was observed; decrease max value.
325 max_iat_cumulative_sum_ -= kCumulativeSumDrift;
326 }
327}
328
turaj@webrtc.orgf1efc572013-08-16 23:44:24 +0000329// Enforces upper and lower limits for |target_level_|. The upper limit is
330// chosen to be minimum of i) 75% of |max_packets_in_buffer_|, to leave some
331// headroom for natural fluctuations around the target, and ii) equivalent of
332// |maximum_delay_ms_| in packets. Note that in practice, if no
333// |maximum_delay_ms_| is specified, this does not have any impact, since the
334// target level is far below the buffer capacity in all reasonable cases.
Ruslan Burakov4a68fb92019-02-13 14:25:39 +0100335// The lower limit is equivalent of |effective_minimum_delay_ms_| in packets.
336// We update |least_required_level_| while the above limits are applied.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000337// TODO(hlundin): Move this check to the buffer logistics class.
338void DelayManager::LimitTargetLevel() {
Ruslan Burakov4a68fb92019-02-13 14:25:39 +0100339 if (packet_len_ms_ > 0 && effective_minimum_delay_ms_ > 0) {
340 int minimum_delay_packet_q8 =
341 (effective_minimum_delay_ms_ << 8) / packet_len_ms_;
turaj@webrtc.orgf1efc572013-08-16 23:44:24 +0000342 target_level_ = std::max(target_level_, minimum_delay_packet_q8);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000343 }
turaj@webrtc.orgf1efc572013-08-16 23:44:24 +0000344
345 if (maximum_delay_ms_ > 0 && packet_len_ms_ > 0) {
346 int maximum_delay_packet_q8 = (maximum_delay_ms_ << 8) / packet_len_ms_;
347 target_level_ = std::min(target_level_, maximum_delay_packet_q8);
348 }
349
350 // Shift to Q8, then 75%.;
Peter Kastingdce40cf2015-08-24 14:52:23 -0700351 int max_buffer_packets_q8 =
352 static_cast<int>((3 * (max_packets_in_buffer_ << 8)) / 4);
turaj@webrtc.orgf1efc572013-08-16 23:44:24 +0000353 target_level_ = std::min(target_level_, max_buffer_packets_q8);
354
355 // Sanity check, at least 1 packet (in Q8).
356 target_level_ = std::max(target_level_, 1 << 8);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000357}
358
Jakob Ivarsson39b934b2019-01-10 10:28:23 +0100359int DelayManager::CalculateTargetLevel(int iat_packets, bool reordered) {
Jakob Ivarssondb42ed22019-02-27 10:08:09 +0100360 int limit_probability = histogram_quantile_;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000361 if (streaming_mode_) {
362 limit_probability = kLimitProbabilityStreaming;
363 }
364
Jakob Ivarssondb42ed22019-02-27 10:08:09 +0100365 int bucket_index = histogram_->Quantile(limit_probability);
366 int target_level;
367 switch (histogram_mode_) {
368 case RELATIVE_ARRIVAL_DELAY: {
369 target_level = 1 + bucket_index * kBucketSizeMs / packet_len_ms_;
370 base_target_level_ = target_level;
371 break;
372 }
373 case INTER_ARRIVAL_TIME: {
374 target_level = bucket_index;
375 base_target_level_ = target_level;
376 // Update detector for delay peaks.
377 bool delay_peak_found =
378 peak_detector_.Update(iat_packets, reordered, target_level);
379 if (delay_peak_found) {
380 target_level = std::max(target_level, peak_detector_.MaxPeakHeight());
381 }
382 break;
383 }
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000384 }
385
386 // Sanity check. |target_level| must be strictly positive.
387 target_level = std::max(target_level, 1);
388 // Scale to Q8 and assign to member variable.
389 target_level_ = target_level << 8;
390 return target_level_;
391}
392
393int DelayManager::SetPacketAudioLength(int length_ms) {
394 if (length_ms <= 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100395 RTC_LOG_F(LS_ERROR) << "length_ms = " << length_ms;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000396 return -1;
397 }
Jakob Ivarssondb42ed22019-02-27 10:08:09 +0100398 if (histogram_mode_ == INTER_ARRIVAL_TIME &&
399 frame_length_change_experiment_ && packet_len_ms_ != length_ms &&
Jakob Ivarsson1eb3d7e2019-02-21 15:42:31 +0100400 packet_len_ms_ > 0) {
Jakob Ivarssondb42ed22019-02-27 10:08:09 +0100401 histogram_->Scale(packet_len_ms_, length_ms);
Ivo Creusen385b10b2017-10-13 12:37:27 +0200402 }
403
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000404 packet_len_ms_ = length_ms;
405 peak_detector_.SetPacketAudioLength(packet_len_ms_);
henrik.lundin8f8c96d2016-04-28 23:19:20 -0700406 packet_iat_stopwatch_ = tick_timer_->GetNewStopwatch();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000407 last_pack_cng_or_dtmf_ = 1; // TODO(hlundin): Legacy. Remove?
408 return 0;
409}
410
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000411void DelayManager::Reset() {
412 packet_len_ms_ = 0; // Packet size unknown.
413 streaming_mode_ = false;
414 peak_detector_.Reset();
Jakob Ivarssondb42ed22019-02-27 10:08:09 +0100415 histogram_->Reset();
Jakob Ivarsson1eb3d7e2019-02-21 15:42:31 +0100416 base_target_level_ = 4;
417 target_level_ = base_target_level_ << 8;
henrik.lundin8f8c96d2016-04-28 23:19:20 -0700418 packet_iat_stopwatch_ = tick_timer_->GetNewStopwatch();
419 max_iat_stopwatch_ = tick_timer_->GetNewStopwatch();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000420 iat_cumulative_sum_ = 0;
421 max_iat_cumulative_sum_ = 0;
422 last_pack_cng_or_dtmf_ = 1;
423}
424
henrik.lundin0d838572016-10-13 03:35:55 -0700425double DelayManager::EstimatedClockDriftPpm() const {
426 double sum = 0.0;
Jakob Ivarsson1eb3d7e2019-02-21 15:42:31 +0100427 // Calculate the expected value based on the probabilities in
Jakob Ivarssondb42ed22019-02-27 10:08:09 +0100428 // |histogram_|.
429 auto buckets = histogram_->buckets();
Jakob Ivarsson1eb3d7e2019-02-21 15:42:31 +0100430 for (size_t i = 0; i < buckets.size(); ++i) {
431 sum += static_cast<double>(buckets[i]) * i;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000432 }
Jakob Ivarssondb42ed22019-02-27 10:08:09 +0100433 // The probabilities in |histogram_| are in Q30. Divide by 1 << 30 to
Jakob Ivarsson1eb3d7e2019-02-21 15:42:31 +0100434 // convert to Q0; subtract the nominal inter-arrival time (1) to make a zero
henrik.lundin0d838572016-10-13 03:35:55 -0700435 // clockdrift represent as 0; mulitply by 1000000 to produce parts-per-million
436 // (ppm).
437 return (sum / (1 << 30) - 1) * 1e6;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000438}
439
440bool DelayManager::PeakFound() const {
441 return peak_detector_.peak_found();
442}
443
henrik.lundin8f8c96d2016-04-28 23:19:20 -0700444void DelayManager::ResetPacketIatCount() {
445 packet_iat_stopwatch_ = tick_timer_->GetNewStopwatch();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000446}
447
turaj@webrtc.orgf1efc572013-08-16 23:44:24 +0000448// Note that |low_limit| and |higher_limit| are not assigned to
449// |minimum_delay_ms_| and |maximum_delay_ms_| defined by the client of this
450// class. They are computed from |target_level_| and used for decision making.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000451void DelayManager::BufferLimits(int* lower_limit, int* higher_limit) const {
452 if (!lower_limit || !higher_limit) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100453 RTC_LOG_F(LS_ERROR) << "NULL pointers supplied as input";
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000454 assert(false);
455 return;
456 }
457
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000458 int window_20ms = 0x7FFF; // Default large value for legacy bit-exactness.
459 if (packet_len_ms_ > 0) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000460 window_20ms = (20 << 8) / packet_len_ms_;
461 }
turaj@webrtc.orgf1efc572013-08-16 23:44:24 +0000462
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000463 // |target_level_| is in Q8 already.
turaj@webrtc.orgf1efc572013-08-16 23:44:24 +0000464 *lower_limit = (target_level_ * 3) / 4;
465 // |higher_limit| is equal to |target_level_|, but should at
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000466 // least be 20 ms higher than |lower_limit_|.
turaj@webrtc.orgf1efc572013-08-16 23:44:24 +0000467 *higher_limit = std::max(target_level_, *lower_limit + window_20ms);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000468}
469
470int DelayManager::TargetLevel() const {
turaj@webrtc.orgf1efc572013-08-16 23:44:24 +0000471 return target_level_;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000472}
473
ossuf1b08da2016-09-23 02:19:43 -0700474void DelayManager::LastDecodedWasCngOrDtmf(bool it_was) {
475 if (it_was) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000476 last_pack_cng_or_dtmf_ = 1;
477 } else if (last_pack_cng_or_dtmf_ != 0) {
478 last_pack_cng_or_dtmf_ = -1;
479 }
480}
pbos@webrtc.org2d1a55c2013-07-31 15:54:00 +0000481
henrik.lundinb8c55b12017-05-10 07:38:01 -0700482void DelayManager::RegisterEmptyPacket() {
483 ++last_seq_no_;
484}
485
Ruslan Burakov4a68fb92019-02-13 14:25:39 +0100486bool DelayManager::IsValidMinimumDelay(int delay_ms) const {
487 return 0 <= delay_ms && delay_ms <= MinimumDelayUpperBound();
488}
489
490bool DelayManager::IsValidBaseMinimumDelay(int delay_ms) const {
491 return kMinBaseMinimumDelayMs <= delay_ms &&
492 delay_ms <= kMaxBaseMinimumDelayMs;
Ruslan Burakovedbea462019-02-04 16:17:31 +0100493}
494
turaj@webrtc.orgf1efc572013-08-16 23:44:24 +0000495bool DelayManager::SetMinimumDelay(int delay_ms) {
Ruslan Burakovedbea462019-02-04 16:17:31 +0100496 if (!IsValidMinimumDelay(delay_ms)) {
turaj@webrtc.orgf1efc572013-08-16 23:44:24 +0000497 return false;
498 }
Ruslan Burakov4a68fb92019-02-13 14:25:39 +0100499
500 minimum_delay_ms_ = delay_ms;
501 UpdateEffectiveMinimumDelay();
turaj@webrtc.orgf1efc572013-08-16 23:44:24 +0000502 return true;
503}
504
505bool DelayManager::SetMaximumDelay(int delay_ms) {
Ruslan Burakov4a68fb92019-02-13 14:25:39 +0100506 // If |delay_ms| is zero then it unsets the maximum delay and target level is
507 // unconstrained by maximum delay.
508 if (delay_ms != 0 &&
509 (delay_ms < minimum_delay_ms_ || delay_ms < packet_len_ms_)) {
turaj@webrtc.orgf1efc572013-08-16 23:44:24 +0000510 // Maximum delay shouldn't be less than minimum delay or less than a packet.
511 return false;
512 }
Ruslan Burakov4a68fb92019-02-13 14:25:39 +0100513
turaj@webrtc.orgf1efc572013-08-16 23:44:24 +0000514 maximum_delay_ms_ = delay_ms;
Ruslan Burakov4a68fb92019-02-13 14:25:39 +0100515 UpdateEffectiveMinimumDelay();
turaj@webrtc.orgf1efc572013-08-16 23:44:24 +0000516 return true;
517}
518
Ruslan Burakovedbea462019-02-04 16:17:31 +0100519bool DelayManager::SetBaseMinimumDelay(int delay_ms) {
Ruslan Burakov4a68fb92019-02-13 14:25:39 +0100520 if (!IsValidBaseMinimumDelay(delay_ms)) {
Ruslan Burakovedbea462019-02-04 16:17:31 +0100521 return false;
522 }
523
Ruslan Burakov4a68fb92019-02-13 14:25:39 +0100524 base_minimum_delay_ms_ = delay_ms;
525 UpdateEffectiveMinimumDelay();
Ruslan Burakovedbea462019-02-04 16:17:31 +0100526 return true;
527}
528
529int DelayManager::GetBaseMinimumDelay() const {
Ruslan Burakov4a68fb92019-02-13 14:25:39 +0100530 return base_minimum_delay_ms_;
Ruslan Burakovedbea462019-02-04 16:17:31 +0100531}
532
Yves Gerey665174f2018-06-19 15:03:05 +0200533int DelayManager::base_target_level() const {
534 return base_target_level_;
535}
536void DelayManager::set_streaming_mode(bool value) {
537 streaming_mode_ = value;
538}
pbos@webrtc.org2d1a55c2013-07-31 15:54:00 +0000539int DelayManager::last_pack_cng_or_dtmf() const {
540 return last_pack_cng_or_dtmf_;
541}
542
543void DelayManager::set_last_pack_cng_or_dtmf(int value) {
544 last_pack_cng_or_dtmf_ = value;
545}
Ruslan Burakov4a68fb92019-02-13 14:25:39 +0100546
547void DelayManager::UpdateEffectiveMinimumDelay() {
548 // Clamp |base_minimum_delay_ms_| into the range which can be effectively
549 // used.
550 const int base_minimum_delay_ms =
551 rtc::SafeClamp(base_minimum_delay_ms_, 0, MinimumDelayUpperBound());
552 effective_minimum_delay_ms_ =
553 std::max(minimum_delay_ms_, base_minimum_delay_ms);
554}
555
556int DelayManager::MinimumDelayUpperBound() const {
557 // Choose the lowest possible bound discarding 0 cases which mean the value
558 // is not set and unconstrained.
559 int q75 = MaxBufferTimeQ75();
560 q75 = q75 > 0 ? q75 : kMaxBaseMinimumDelayMs;
561 const int maximum_delay_ms =
562 maximum_delay_ms_ > 0 ? maximum_delay_ms_ : kMaxBaseMinimumDelayMs;
563 return std::min(maximum_delay_ms, q75);
564}
565
566int DelayManager::MaxBufferTimeQ75() const {
567 const int max_buffer_time = max_packets_in_buffer_ * packet_len_ms_;
568 return rtc::dchecked_cast<int>(3 * max_buffer_time / 4);
569}
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000570} // namespace webrtc