blob: 6b10d33a5b3c2896b04e984189103b5d9b9a96d1 [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
Jakob Ivarsson80fb9782020-10-09 13:41:06 +020030namespace webrtc {
Minyue Li002fbb82018-10-04 11:31:03 +020031namespace {
32
Ruslan Burakov4a68fb92019-02-13 14:25:39 +010033constexpr int kMinBaseMinimumDelayMs = 0;
34constexpr int kMaxBaseMinimumDelayMs = 10000;
Jakob Ivarsson74154e62019-08-22 15:00:16 +020035constexpr int kMaxHistoryMs = 2000; // Oldest packet to include in history to
36 // calculate relative packet arrival delay.
Jakob Ivarssondb42ed22019-02-27 10:08:09 +010037constexpr int kDelayBuckets = 100;
38constexpr int kBucketSizeMs = 20;
Jakob Ivarsson80fb9782020-10-09 13:41:06 +020039constexpr int kStartDelayMs = 80;
40constexpr int kMaxNumReorderedPackets = 5;
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 Ivarsson80fb9782020-10-09 13:41:06 +020052// TODO(jakobi): Remove legacy field trial.
Jakob Ivarsson507f4342019-09-03 13:04:41 +020053DelayHistogramConfig GetDelayHistogramConfig() {
Jakob Ivarssondb42ed22019-02-27 10:08:09 +010054 constexpr char kDelayHistogramFieldTrial[] =
55 "WebRTC-Audio-NetEqDelayHistogram";
Jakob Ivarsson507f4342019-09-03 13:04:41 +020056 DelayHistogramConfig config;
57 if (webrtc::field_trial::IsEnabled(kDelayHistogramFieldTrial)) {
Jakob Ivarssondb42ed22019-02-27 10:08:09 +010058 const auto field_trial_string =
59 webrtc::field_trial::FindFullName(kDelayHistogramFieldTrial);
Jakob Ivarssondb42ed22019-02-27 10:08:09 +010060 double percentile = -1.0;
61 double forget_factor = -1.0;
Jakob Ivarssone9a2ee22019-05-22 16:54:09 +020062 double start_forget_weight = -1.0;
63 if (sscanf(field_trial_string.c_str(), "Enabled-%lf-%lf-%lf", &percentile,
64 &forget_factor, &start_forget_weight) >= 2 &&
Jakob Ivarssondb42ed22019-02-27 10:08:09 +010065 percentile >= 0.0 && percentile <= 100.0 && forget_factor >= 0.0 &&
66 forget_factor <= 1.0) {
67 config.quantile = PercentileToQuantile(percentile);
68 config.forget_factor = (1 << 15) * forget_factor;
Jakob Ivarsson507f4342019-09-03 13:04:41 +020069 config.start_forget_weight =
70 start_forget_weight >= 1 ? absl::make_optional(start_forget_weight)
71 : absl::nullopt;
Jakob Ivarssondb42ed22019-02-27 10:08:09 +010072 }
Jakob Ivarssondb42ed22019-02-27 10:08:09 +010073 }
Jakob Ivarsson507f4342019-09-03 13:04:41 +020074 RTC_LOG(LS_INFO) << "Delay histogram config:"
Jonas Olssonb2b20312020-01-14 12:11:31 +010075 " quantile="
76 << config.quantile
Jakob Ivarsson507f4342019-09-03 13:04:41 +020077 << " forget_factor=" << config.forget_factor
78 << " start_forget_weight="
79 << config.start_forget_weight.value_or(0);
80 return config;
Jakob Ivarssondb42ed22019-02-27 10:08:09 +010081}
82
Minyue Li002fbb82018-10-04 11:31:03 +020083} // namespace
84
Jakob Ivarsson80fb9782020-10-09 13:41:06 +020085DelayManager::DelayManager(int 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 Ivarsson1eb3d7e2019-02-21 15:42:31 +010088 const TickTimer* tick_timer,
Jakob Ivarssondb42ed22019-02-27 10:08:09 +010089 std::unique_ptr<Histogram> histogram)
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000090 : first_packet_received_(false),
91 max_packets_in_buffer_(max_packets_in_buffer),
Jakob Ivarssondb42ed22019-02-27 10:08:09 +010092 histogram_(std::move(histogram)),
93 histogram_quantile_(histogram_quantile),
henrik.lundin8f8c96d2016-04-28 23:19:20 -070094 tick_timer_(tick_timer),
Ruslan Burakov4a68fb92019-02-13 14:25:39 +010095 base_minimum_delay_ms_(base_minimum_delay_ms),
96 effective_minimum_delay_ms_(base_minimum_delay_ms),
Ruslan Burakov76a74e62019-02-22 19:28:02 +010097 minimum_delay_ms_(0),
Ruslan Burakovb35bacc2019-02-20 13:41:59 +010098 maximum_delay_ms_(0),
Jakob Ivarsson80fb9782020-10-09 13:41:06 +020099 target_level_ms_(kStartDelayMs),
100 last_timestamp_(0) {
Jakob Ivarssondb42ed22019-02-27 10:08:09 +0100101 RTC_CHECK(histogram_);
Ruslan Burakov4a68fb92019-02-13 14:25:39 +0100102 RTC_DCHECK_GE(base_minimum_delay_ms_, 0);
Minyue Li002fbb82018-10-04 11:31:03 +0200103
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000104 Reset();
105}
106
Jakob Ivarsson1eb3d7e2019-02-21 15:42:31 +0100107std::unique_ptr<DelayManager> DelayManager::Create(
Jakob Ivarsson80fb9782020-10-09 13:41:06 +0200108 int max_packets_in_buffer,
Jakob Ivarsson1eb3d7e2019-02-21 15:42:31 +0100109 int base_minimum_delay_ms,
Ivo Creusen53a31f72019-10-24 15:20:39 +0200110 const TickTimer* tick_timer) {
Jakob Ivarsson80fb9782020-10-09 13:41:06 +0200111 auto config = GetDelayHistogramConfig();
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200112 std::unique_ptr<Histogram> histogram = std::make_unique<Histogram>(
Jakob Ivarsson507f4342019-09-03 13:04:41 +0200113 kDelayBuckets, config.forget_factor, config.start_forget_weight);
Jakob Ivarsson80fb9782020-10-09 13:41:06 +0200114 return std::make_unique<DelayManager>(max_packets_in_buffer,
115 base_minimum_delay_ms, config.quantile,
116 tick_timer, std::move(histogram));
Jakob Ivarsson1eb3d7e2019-02-21 15:42:31 +0100117}
118
pbos@webrtc.org2d1a55c2013-07-31 15:54:00 +0000119DelayManager::~DelayManager() {}
120
Jakob Ivarsson80fb9782020-10-09 13:41:06 +0200121absl::optional<int> DelayManager::Update(uint32_t timestamp,
122 int sample_rate_hz,
123 bool reset) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000124 if (sample_rate_hz <= 0) {
Ivo Creusen53a31f72019-10-24 15:20:39 +0200125 return absl::nullopt;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000126 }
127
Jakob Ivarsson80fb9782020-10-09 13:41:06 +0200128 if (!first_packet_received_ || reset) {
129 // Restart relative delay esimation from this packet.
130 delay_history_.clear();
henrik.lundin8f8c96d2016-04-28 23:19:20 -0700131 packet_iat_stopwatch_ = tick_timer_->GetNewStopwatch();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000132 last_timestamp_ = timestamp;
133 first_packet_received_ = true;
Jakob Ivarsson80fb9782020-10-09 13:41:06 +0200134 num_reordered_packets_ = 0;
Ivo Creusen53a31f72019-10-24 15:20:39 +0200135 return absl::nullopt;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000136 }
137
Jakob Ivarsson80fb9782020-10-09 13:41:06 +0200138 const int expected_iat_ms =
139 1000 * static_cast<int32_t>(timestamp - last_timestamp_) / sample_rate_hz;
140 const int iat_ms = packet_iat_stopwatch_->ElapsedMs();
141 const int iat_delay_ms = iat_ms - expected_iat_ms;
142 absl::optional<int> relative_delay;
143 bool reordered = !IsNewerTimestamp(timestamp, last_timestamp_);
144 if (reordered) {
145 relative_delay = std::max(iat_delay_ms, 0);
Jakob Ivarsson2a7c57c2020-10-06 18:12:07 +0200146 } else {
Jakob Ivarsson80fb9782020-10-09 13:41:06 +0200147 UpdateDelayHistory(iat_delay_ms, timestamp, sample_rate_hz);
148 relative_delay = CalculateRelativePacketArrivalDelay();
149 }
150 const int index = relative_delay.value() / kBucketSizeMs;
151 if (index < histogram_->NumBuckets()) {
152 // Maximum delay to register is 2000 ms.
153 histogram_->Add(index);
154 }
155 // Calculate new |target_level_ms_| based on updated statistics.
156 int bucket_index = histogram_->Quantile(histogram_quantile_);
157 target_level_ms_ = (1 + bucket_index) * kBucketSizeMs;
158 target_level_ms_ = std::max(target_level_ms_, effective_minimum_delay_ms_);
159 if (maximum_delay_ms_ > 0) {
160 target_level_ms_ = std::min(target_level_ms_, maximum_delay_ms_);
161 }
162 if (packet_len_ms_ > 0) {
163 // Target level should be at least one packet.
164 target_level_ms_ = std::max(target_level_ms_, packet_len_ms_);
165 // Limit to 75% of maximum buffer size.
166 target_level_ms_ = std::min(
167 target_level_ms_, 3 * max_packets_in_buffer_ * packet_len_ms_ / 4);
Jakob Ivarsson2a7c57c2020-10-06 18:12:07 +0200168 }
169
Jakob Ivarsson80fb9782020-10-09 13:41:06 +0200170 // Prepare for next packet arrival.
171 if (reordered) {
172 // Allow a small number of reordered packets before resetting the delay
173 // estimation.
174 if (num_reordered_packets_ < kMaxNumReorderedPackets) {
175 ++num_reordered_packets_;
176 return relative_delay;
Jakob Ivarssonff9f6462020-10-07 12:46:42 +0000177 }
Jakob Ivarsson80fb9782020-10-09 13:41:06 +0200178 delay_history_.clear();
Jakob Ivarssonff9f6462020-10-07 12:46:42 +0000179 }
180 num_reordered_packets_ = 0;
henrik.lundin8f8c96d2016-04-28 23:19:20 -0700181 packet_iat_stopwatch_ = tick_timer_->GetNewStopwatch();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000182 last_timestamp_ = timestamp;
Ivo Creusen53a31f72019-10-24 15:20:39 +0200183 return relative_delay;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000184}
185
Jakob Ivarsson74154e62019-08-22 15:00:16 +0200186void DelayManager::UpdateDelayHistory(int iat_delay_ms,
187 uint32_t timestamp,
188 int sample_rate_hz) {
189 PacketDelay delay;
190 delay.iat_delay_ms = iat_delay_ms;
191 delay.timestamp = timestamp;
192 delay_history_.push_back(delay);
193 while (timestamp - delay_history_.front().timestamp >
194 static_cast<uint32_t>(kMaxHistoryMs * sample_rate_hz / 1000)) {
Jakob Ivarssondb42ed22019-02-27 10:08:09 +0100195 delay_history_.pop_front();
196 }
197}
198
199int DelayManager::CalculateRelativePacketArrivalDelay() const {
200 // This effectively calculates arrival delay of a packet relative to the
201 // packet preceding the history window. If the arrival delay ever becomes
202 // smaller than zero, it means the reference packet is invalid, and we
203 // move the reference.
204 int relative_delay = 0;
Jakob Ivarsson74154e62019-08-22 15:00:16 +0200205 for (const PacketDelay& delay : delay_history_) {
206 relative_delay += delay.iat_delay_ms;
Jakob Ivarssondb42ed22019-02-27 10:08:09 +0100207 relative_delay = std::max(relative_delay, 0);
208 }
209 return relative_delay;
210}
211
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000212int DelayManager::SetPacketAudioLength(int length_ms) {
213 if (length_ms <= 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100214 RTC_LOG_F(LS_ERROR) << "length_ms = " << length_ms;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000215 return -1;
216 }
217 packet_len_ms_ = length_ms;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000218 return 0;
219}
220
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000221void DelayManager::Reset() {
Jakob Ivarsson80fb9782020-10-09 13:41:06 +0200222 packet_len_ms_ = 0;
Jakob Ivarssondb42ed22019-02-27 10:08:09 +0100223 histogram_->Reset();
Jakob Ivarsson74154e62019-08-22 15:00:16 +0200224 delay_history_.clear();
Jakob Ivarsson80fb9782020-10-09 13:41:06 +0200225 target_level_ms_ = kStartDelayMs;
henrik.lundin8f8c96d2016-04-28 23:19:20 -0700226 packet_iat_stopwatch_ = tick_timer_->GetNewStopwatch();
Jakob Ivarsson80fb9782020-10-09 13:41:06 +0200227 first_packet_received_ = false;
228 num_reordered_packets_ = 0;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000229}
230
Jakob Ivarsson80fb9782020-10-09 13:41:06 +0200231int DelayManager::TargetDelayMs() const {
232 return target_level_ms_;
henrik.lundinb8c55b12017-05-10 07:38:01 -0700233}
234
Ruslan Burakov4a68fb92019-02-13 14:25:39 +0100235bool DelayManager::IsValidMinimumDelay(int delay_ms) const {
236 return 0 <= delay_ms && delay_ms <= MinimumDelayUpperBound();
237}
238
239bool DelayManager::IsValidBaseMinimumDelay(int delay_ms) const {
240 return kMinBaseMinimumDelayMs <= delay_ms &&
241 delay_ms <= kMaxBaseMinimumDelayMs;
Ruslan Burakovedbea462019-02-04 16:17:31 +0100242}
243
turaj@webrtc.orgf1efc572013-08-16 23:44:24 +0000244bool DelayManager::SetMinimumDelay(int delay_ms) {
Ruslan Burakovedbea462019-02-04 16:17:31 +0100245 if (!IsValidMinimumDelay(delay_ms)) {
turaj@webrtc.orgf1efc572013-08-16 23:44:24 +0000246 return false;
247 }
Ruslan Burakov4a68fb92019-02-13 14:25:39 +0100248
249 minimum_delay_ms_ = delay_ms;
250 UpdateEffectiveMinimumDelay();
turaj@webrtc.orgf1efc572013-08-16 23:44:24 +0000251 return true;
252}
253
254bool DelayManager::SetMaximumDelay(int delay_ms) {
Ruslan Burakov4a68fb92019-02-13 14:25:39 +0100255 // If |delay_ms| is zero then it unsets the maximum delay and target level is
256 // unconstrained by maximum delay.
257 if (delay_ms != 0 &&
258 (delay_ms < minimum_delay_ms_ || delay_ms < packet_len_ms_)) {
turaj@webrtc.orgf1efc572013-08-16 23:44:24 +0000259 // Maximum delay shouldn't be less than minimum delay or less than a packet.
260 return false;
261 }
Ruslan Burakov4a68fb92019-02-13 14:25:39 +0100262
turaj@webrtc.orgf1efc572013-08-16 23:44:24 +0000263 maximum_delay_ms_ = delay_ms;
Ruslan Burakov4a68fb92019-02-13 14:25:39 +0100264 UpdateEffectiveMinimumDelay();
turaj@webrtc.orgf1efc572013-08-16 23:44:24 +0000265 return true;
266}
267
Ruslan Burakovedbea462019-02-04 16:17:31 +0100268bool DelayManager::SetBaseMinimumDelay(int delay_ms) {
Ruslan Burakov4a68fb92019-02-13 14:25:39 +0100269 if (!IsValidBaseMinimumDelay(delay_ms)) {
Ruslan Burakovedbea462019-02-04 16:17:31 +0100270 return false;
271 }
272
Ruslan Burakov4a68fb92019-02-13 14:25:39 +0100273 base_minimum_delay_ms_ = delay_ms;
274 UpdateEffectiveMinimumDelay();
Ruslan Burakovedbea462019-02-04 16:17:31 +0100275 return true;
276}
277
278int DelayManager::GetBaseMinimumDelay() const {
Ruslan Burakov4a68fb92019-02-13 14:25:39 +0100279 return base_minimum_delay_ms_;
Ruslan Burakovedbea462019-02-04 16:17:31 +0100280}
281
Ruslan Burakov4a68fb92019-02-13 14:25:39 +0100282void DelayManager::UpdateEffectiveMinimumDelay() {
283 // Clamp |base_minimum_delay_ms_| into the range which can be effectively
284 // used.
285 const int base_minimum_delay_ms =
286 rtc::SafeClamp(base_minimum_delay_ms_, 0, MinimumDelayUpperBound());
287 effective_minimum_delay_ms_ =
288 std::max(minimum_delay_ms_, base_minimum_delay_ms);
289}
290
291int DelayManager::MinimumDelayUpperBound() const {
292 // Choose the lowest possible bound discarding 0 cases which mean the value
293 // is not set and unconstrained.
Jakob Ivarsson80fb9782020-10-09 13:41:06 +0200294 int q75 = max_packets_in_buffer_ * packet_len_ms_ * 3 / 4;
Ruslan Burakov4a68fb92019-02-13 14:25:39 +0100295 q75 = q75 > 0 ? q75 : kMaxBaseMinimumDelayMs;
296 const int maximum_delay_ms =
297 maximum_delay_ms_ > 0 ? maximum_delay_ms_ : kMaxBaseMinimumDelayMs;
298 return std::min(maximum_delay_ms, q75);
299}
300
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000301} // namespace webrtc