blob: 6147cacb4a0301e63df27bcdb48226fbd8cb03c9 [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"
Yves Gerey988cc082018-10-23 12:03:01 +020022#include "modules/include/module_common_types_public.h"
23#include "rtc_base/checks.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020024#include "rtc_base/logging.h"
Karl Wiberge40468b2017-11-22 10:42:26 +010025#include "rtc_base/numerics/safe_conversions.h"
Ruslan Burakov4a68fb92019-02-13 14:25:39 +010026#include "rtc_base/numerics/safe_minmax.h"
Ivo Creusen385b10b2017-10-13 12:37:27 +020027#include "system_wrappers/include/field_trial.h"
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000028
Minyue Li002fbb82018-10-04 11:31:03 +020029namespace {
30
Jakob Ivarsson1eb3d7e2019-02-21 15:42:31 +010031constexpr int kLimitProbability = 1020054733; // 19/20 in Q30.
32constexpr int kLimitProbabilityStreaming = 1073204953; // 1999/2000 in Q30.
33constexpr int kMaxStreamingPeakPeriodMs = 600000; // 10 minutes in ms.
Minyue Li002fbb82018-10-04 11:31:03 +020034constexpr int kCumulativeSumDrift = 2; // Drift term for cumulative sum
35 // |iat_cumulative_sum_|.
Ruslan Burakov4a68fb92019-02-13 14:25:39 +010036constexpr int kMinBaseMinimumDelayMs = 0;
37constexpr int kMaxBaseMinimumDelayMs = 10000;
Jakob Ivarsson1eb3d7e2019-02-21 15:42:31 +010038constexpr int kIatFactor = 32745; // 0.9993 in Q15.
39constexpr int kMaxIat = 64; // Max inter-arrival time to register.
Jakob Ivarssone98954c2019-02-06 15:37:50 +010040constexpr int kMaxReorderedPackets =
41 10; // Max number of consecutive reordered packets.
Minyue Li002fbb82018-10-04 11:31:03 +020042
43absl::optional<int> GetForcedLimitProbability() {
44 constexpr char kForceTargetDelayPercentileFieldTrial[] =
45 "WebRTC-Audio-NetEqForceTargetDelayPercentile";
46 const bool use_forced_target_delay_percentile =
47 webrtc::field_trial::IsEnabled(kForceTargetDelayPercentileFieldTrial);
48 if (use_forced_target_delay_percentile) {
49 const std::string field_trial_string = webrtc::field_trial::FindFullName(
50 kForceTargetDelayPercentileFieldTrial);
51 double percentile = -1.0;
52 if (sscanf(field_trial_string.c_str(), "Enabled-%lf", &percentile) == 1 &&
53 percentile >= 0.0 && percentile <= 100.0) {
Jakob Ivarsson1eb3d7e2019-02-21 15:42:31 +010054 return absl::make_optional<int>(
55 static_cast<int>((1 << 30) * percentile / 100.0 + 0.5)); // in Q30.
Minyue Li002fbb82018-10-04 11:31:03 +020056 } else {
57 RTC_LOG(LS_WARNING) << "Invalid parameter for "
58 << kForceTargetDelayPercentileFieldTrial
59 << ", ignored.";
60 }
61 }
62 return absl::nullopt;
63}
64
65} // namespace
66
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000067namespace webrtc {
68
Peter Kastingdce40cf2015-08-24 14:52:23 -070069DelayManager::DelayManager(size_t max_packets_in_buffer,
Ruslan Burakov4a68fb92019-02-13 14:25:39 +010070 int base_minimum_delay_ms,
Jakob Ivarssone98954c2019-02-06 15:37:50 +010071 bool enable_rtx_handling,
henrik.lundin8f8c96d2016-04-28 23:19:20 -070072 DelayPeakDetector* peak_detector,
Jakob Ivarsson1eb3d7e2019-02-21 15:42:31 +010073 const TickTimer* tick_timer,
74 std::unique_ptr<Histogram> iat_histogram)
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000075 : first_packet_received_(false),
76 max_packets_in_buffer_(max_packets_in_buffer),
Jakob Ivarsson1eb3d7e2019-02-21 15:42:31 +010077 iat_histogram_(std::move(iat_histogram)),
henrik.lundin8f8c96d2016-04-28 23:19:20 -070078 tick_timer_(tick_timer),
Ruslan Burakov4a68fb92019-02-13 14:25:39 +010079 base_minimum_delay_ms_(base_minimum_delay_ms),
80 effective_minimum_delay_ms_(base_minimum_delay_ms),
Ivo Creusen385b10b2017-10-13 12:37:27 +020081 base_target_level_(4), // In Q0 domain.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000082 target_level_(base_target_level_ << 8), // In Q8 domain.
83 packet_len_ms_(0),
84 streaming_mode_(false),
85 last_seq_no_(0),
86 last_timestamp_(0),
Ruslan Burakov76a74e62019-02-22 19:28:02 +010087 minimum_delay_ms_(0),
Ruslan Burakovb35bacc2019-02-20 13:41:59 +010088 maximum_delay_ms_(0),
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000089 iat_cumulative_sum_(0),
90 max_iat_cumulative_sum_(0),
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000091 peak_detector_(*peak_detector),
Ivo Creusen385b10b2017-10-13 12:37:27 +020092 last_pack_cng_or_dtmf_(1),
93 frame_length_change_experiment_(
Minyue Li002fbb82018-10-04 11:31:03 +020094 field_trial::IsEnabled("WebRTC-Audio-NetEqFramelengthExperiment")),
Jakob Ivarssone98954c2019-02-06 15:37:50 +010095 forced_limit_probability_(GetForcedLimitProbability()),
96 enable_rtx_handling_(enable_rtx_handling) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000097 assert(peak_detector); // Should never be NULL.
Jakob Ivarsson1eb3d7e2019-02-21 15:42:31 +010098 RTC_CHECK(iat_histogram_);
Ruslan Burakov4a68fb92019-02-13 14:25:39 +010099 RTC_DCHECK_GE(base_minimum_delay_ms_, 0);
Minyue Li002fbb82018-10-04 11:31:03 +0200100
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000101 Reset();
102}
103
Jakob Ivarsson1eb3d7e2019-02-21 15:42:31 +0100104std::unique_ptr<DelayManager> DelayManager::Create(
105 size_t max_packets_in_buffer,
106 int base_minimum_delay_ms,
107 bool enable_rtx_handling,
108 DelayPeakDetector* peak_detector,
109 const TickTimer* tick_timer) {
110 return absl::make_unique<DelayManager>(
111 max_packets_in_buffer, base_minimum_delay_ms, enable_rtx_handling,
112 peak_detector, tick_timer,
113 absl::make_unique<Histogram>(kMaxIat + 1, kIatFactor));
114}
115
pbos@webrtc.org2d1a55c2013-07-31 15:54:00 +0000116DelayManager::~DelayManager() {}
117
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000118int DelayManager::Update(uint16_t sequence_number,
119 uint32_t timestamp,
120 int sample_rate_hz) {
121 if (sample_rate_hz <= 0) {
122 return -1;
123 }
124
125 if (!first_packet_received_) {
126 // Prepare for next packet arrival.
henrik.lundin8f8c96d2016-04-28 23:19:20 -0700127 packet_iat_stopwatch_ = tick_timer_->GetNewStopwatch();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000128 last_seq_no_ = sequence_number;
129 last_timestamp_ = timestamp;
130 first_packet_received_ = true;
131 return 0;
132 }
133
134 // Try calculating packet length from current and previous timestamps.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000135 int packet_len_ms;
turaj@webrtc.org78b41a02013-11-22 20:27:07 +0000136 if (!IsNewerTimestamp(timestamp, last_timestamp_) ||
137 !IsNewerSequenceNumber(sequence_number, last_seq_no_)) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000138 // Wrong timestamp or sequence order; use stored value.
139 packet_len_ms = packet_len_ms_;
140 } else {
141 // Calculate timestamps per packet and derive packet length in ms.
henrik.lundin07c51e32016-02-11 03:35:43 -0800142 int64_t packet_len_samp =
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000143 static_cast<uint32_t>(timestamp - last_timestamp_) /
144 static_cast<uint16_t>(sequence_number - last_seq_no_);
henrik.lundin07c51e32016-02-11 03:35:43 -0800145 packet_len_ms =
henrik.lundin38d840c2016-08-18 03:49:32 -0700146 rtc::saturated_cast<int>(1000 * packet_len_samp / sample_rate_hz);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000147 }
148
Jakob Ivarssone98954c2019-02-06 15:37:50 +0100149 bool reordered = false;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000150 if (packet_len_ms > 0) {
151 // Cannot update statistics unless |packet_len_ms| is valid.
152 // Calculate inter-arrival time (IAT) in integer "packet times"
Jakob Ivarsson1eb3d7e2019-02-21 15:42:31 +0100153 // (rounding down). This is the value added to the inter-arrival time
154 // histogram.
henrik.lundin8f8c96d2016-04-28 23:19:20 -0700155 int iat_packets = packet_iat_stopwatch_->ElapsedMs() / packet_len_ms;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000156
157 if (streaming_mode_) {
158 UpdateCumulativeSums(packet_len_ms, sequence_number);
159 }
160
161 // Check for discontinuous packet sequence and re-ordering.
turaj@webrtc.org78b41a02013-11-22 20:27:07 +0000162 if (IsNewerSequenceNumber(sequence_number, last_seq_no_ + 1)) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000163 // Compensate for gap in the sequence numbers. Reduce IAT with the
164 // expected extra time due to lost packets, but ensure that the IAT is
165 // not negative.
turaj@webrtc.org78b41a02013-11-22 20:27:07 +0000166 iat_packets -= static_cast<uint16_t>(sequence_number - last_seq_no_ - 1);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000167 iat_packets = std::max(iat_packets, 0);
turaj@webrtc.org78b41a02013-11-22 20:27:07 +0000168 } else if (!IsNewerSequenceNumber(sequence_number, last_seq_no_)) {
169 iat_packets += static_cast<uint16_t>(last_seq_no_ + 1 - sequence_number);
Jakob Ivarsson39b934b2019-01-10 10:28:23 +0100170 reordered = true;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000171 }
172
173 // Saturate IAT at maximum value.
Jakob Ivarsson1eb3d7e2019-02-21 15:42:31 +0100174 iat_packets = std::min(iat_packets, iat_histogram_->NumBuckets() - 1);
175 iat_histogram_->Add(iat_packets);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000176 // Calculate new |target_level_| based on updated statistics.
Jakob Ivarsson39b934b2019-01-10 10:28:23 +0100177 target_level_ = CalculateTargetLevel(iat_packets, reordered);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000178 if (streaming_mode_) {
179 target_level_ = std::max(target_level_, max_iat_cumulative_sum_);
180 }
181
182 LimitTargetLevel();
183 } // End if (packet_len_ms > 0).
184
Jakob Ivarssone98954c2019-02-06 15:37:50 +0100185 if (enable_rtx_handling_ && reordered &&
186 num_reordered_packets_ < kMaxReorderedPackets) {
187 ++num_reordered_packets_;
188 return 0;
189 }
190 num_reordered_packets_ = 0;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000191 // Prepare for next packet arrival.
henrik.lundin8f8c96d2016-04-28 23:19:20 -0700192 packet_iat_stopwatch_ = tick_timer_->GetNewStopwatch();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000193 last_seq_no_ = sequence_number;
194 last_timestamp_ = timestamp;
195 return 0;
196}
197
198void DelayManager::UpdateCumulativeSums(int packet_len_ms,
199 uint16_t sequence_number) {
200 // Calculate IAT in Q8, including fractions of a packet (i.e., more
201 // accurate than |iat_packets|.
henrik.lundin8f8c96d2016-04-28 23:19:20 -0700202 int iat_packets_q8 =
203 (packet_iat_stopwatch_->ElapsedMs() << 8) / packet_len_ms;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000204 // Calculate cumulative sum IAT with sequence number compensation. The sum
205 // is zero if there is no clock-drift.
Yves Gerey665174f2018-06-19 15:03:05 +0200206 iat_cumulative_sum_ +=
207 (iat_packets_q8 -
208 (static_cast<int>(sequence_number - last_seq_no_) << 8));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000209 // Subtract drift term.
210 iat_cumulative_sum_ -= kCumulativeSumDrift;
211 // Ensure not negative.
212 iat_cumulative_sum_ = std::max(iat_cumulative_sum_, 0);
213 if (iat_cumulative_sum_ > max_iat_cumulative_sum_) {
214 // Found a new maximum.
215 max_iat_cumulative_sum_ = iat_cumulative_sum_;
henrik.lundin8f8c96d2016-04-28 23:19:20 -0700216 max_iat_stopwatch_ = tick_timer_->GetNewStopwatch();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000217 }
henrik.lundin8f8c96d2016-04-28 23:19:20 -0700218 if (max_iat_stopwatch_->ElapsedMs() > kMaxStreamingPeakPeriodMs) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000219 // Too long since the last maximum was observed; decrease max value.
220 max_iat_cumulative_sum_ -= kCumulativeSumDrift;
221 }
222}
223
turaj@webrtc.orgf1efc572013-08-16 23:44:24 +0000224// Enforces upper and lower limits for |target_level_|. The upper limit is
225// chosen to be minimum of i) 75% of |max_packets_in_buffer_|, to leave some
226// headroom for natural fluctuations around the target, and ii) equivalent of
227// |maximum_delay_ms_| in packets. Note that in practice, if no
228// |maximum_delay_ms_| is specified, this does not have any impact, since the
229// target level is far below the buffer capacity in all reasonable cases.
Ruslan Burakov4a68fb92019-02-13 14:25:39 +0100230// The lower limit is equivalent of |effective_minimum_delay_ms_| in packets.
231// We update |least_required_level_| while the above limits are applied.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000232// TODO(hlundin): Move this check to the buffer logistics class.
233void DelayManager::LimitTargetLevel() {
Ruslan Burakov4a68fb92019-02-13 14:25:39 +0100234 if (packet_len_ms_ > 0 && effective_minimum_delay_ms_ > 0) {
235 int minimum_delay_packet_q8 =
236 (effective_minimum_delay_ms_ << 8) / packet_len_ms_;
turaj@webrtc.orgf1efc572013-08-16 23:44:24 +0000237 target_level_ = std::max(target_level_, minimum_delay_packet_q8);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000238 }
turaj@webrtc.orgf1efc572013-08-16 23:44:24 +0000239
240 if (maximum_delay_ms_ > 0 && packet_len_ms_ > 0) {
241 int maximum_delay_packet_q8 = (maximum_delay_ms_ << 8) / packet_len_ms_;
242 target_level_ = std::min(target_level_, maximum_delay_packet_q8);
243 }
244
245 // Shift to Q8, then 75%.;
Peter Kastingdce40cf2015-08-24 14:52:23 -0700246 int max_buffer_packets_q8 =
247 static_cast<int>((3 * (max_packets_in_buffer_ << 8)) / 4);
turaj@webrtc.orgf1efc572013-08-16 23:44:24 +0000248 target_level_ = std::min(target_level_, max_buffer_packets_q8);
249
250 // Sanity check, at least 1 packet (in Q8).
251 target_level_ = std::max(target_level_, 1 << 8);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000252}
253
Jakob Ivarsson39b934b2019-01-10 10:28:23 +0100254int DelayManager::CalculateTargetLevel(int iat_packets, bool reordered) {
Minyue Li002fbb82018-10-04 11:31:03 +0200255 int limit_probability = forced_limit_probability_.value_or(kLimitProbability);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000256 if (streaming_mode_) {
257 limit_probability = kLimitProbabilityStreaming;
258 }
259
260 // Calculate target buffer level from inter-arrival time histogram.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000261 // This is the base value for the target buffer level.
Jakob Ivarsson1eb3d7e2019-02-21 15:42:31 +0100262 int target_level = iat_histogram_->Quantile(limit_probability);
263 base_target_level_ = target_level;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000264
265 // Update detector for delay peaks.
Jakob Ivarsson39b934b2019-01-10 10:28:23 +0100266 bool delay_peak_found =
267 peak_detector_.Update(iat_packets, reordered, target_level);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000268 if (delay_peak_found) {
turaj@webrtc.org362a55e2013-09-20 16:25:28 +0000269 target_level = std::max(target_level, peak_detector_.MaxPeakHeight());
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000270 }
271
272 // Sanity check. |target_level| must be strictly positive.
273 target_level = std::max(target_level, 1);
274 // Scale to Q8 and assign to member variable.
275 target_level_ = target_level << 8;
276 return target_level_;
277}
278
279int DelayManager::SetPacketAudioLength(int length_ms) {
280 if (length_ms <= 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100281 RTC_LOG_F(LS_ERROR) << "length_ms = " << length_ms;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000282 return -1;
283 }
Jakob Ivarsson1eb3d7e2019-02-21 15:42:31 +0100284 if (frame_length_change_experiment_ && packet_len_ms_ != length_ms &&
285 packet_len_ms_ > 0) {
286 iat_histogram_->Scale(packet_len_ms_, length_ms);
Ivo Creusen385b10b2017-10-13 12:37:27 +0200287 }
288
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000289 packet_len_ms_ = length_ms;
290 peak_detector_.SetPacketAudioLength(packet_len_ms_);
henrik.lundin8f8c96d2016-04-28 23:19:20 -0700291 packet_iat_stopwatch_ = tick_timer_->GetNewStopwatch();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000292 last_pack_cng_or_dtmf_ = 1; // TODO(hlundin): Legacy. Remove?
293 return 0;
294}
295
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000296void DelayManager::Reset() {
297 packet_len_ms_ = 0; // Packet size unknown.
298 streaming_mode_ = false;
299 peak_detector_.Reset();
Jakob Ivarsson1eb3d7e2019-02-21 15:42:31 +0100300 iat_histogram_->Reset();
301 base_target_level_ = 4;
302 target_level_ = base_target_level_ << 8;
henrik.lundin8f8c96d2016-04-28 23:19:20 -0700303 packet_iat_stopwatch_ = tick_timer_->GetNewStopwatch();
304 max_iat_stopwatch_ = tick_timer_->GetNewStopwatch();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000305 iat_cumulative_sum_ = 0;
306 max_iat_cumulative_sum_ = 0;
307 last_pack_cng_or_dtmf_ = 1;
308}
309
henrik.lundin0d838572016-10-13 03:35:55 -0700310double DelayManager::EstimatedClockDriftPpm() const {
311 double sum = 0.0;
Jakob Ivarsson1eb3d7e2019-02-21 15:42:31 +0100312 // Calculate the expected value based on the probabilities in
313 // |iat_histogram_|.
314 auto buckets = iat_histogram_->buckets();
315 for (size_t i = 0; i < buckets.size(); ++i) {
316 sum += static_cast<double>(buckets[i]) * i;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000317 }
Jakob Ivarsson1eb3d7e2019-02-21 15:42:31 +0100318 // The probabilities in |iat_histogram_| are in Q30. Divide by 1 << 30 to
319 // convert to Q0; subtract the nominal inter-arrival time (1) to make a zero
henrik.lundin0d838572016-10-13 03:35:55 -0700320 // clockdrift represent as 0; mulitply by 1000000 to produce parts-per-million
321 // (ppm).
322 return (sum / (1 << 30) - 1) * 1e6;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000323}
324
325bool DelayManager::PeakFound() const {
326 return peak_detector_.peak_found();
327}
328
henrik.lundin8f8c96d2016-04-28 23:19:20 -0700329void DelayManager::ResetPacketIatCount() {
330 packet_iat_stopwatch_ = tick_timer_->GetNewStopwatch();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000331}
332
turaj@webrtc.orgf1efc572013-08-16 23:44:24 +0000333// Note that |low_limit| and |higher_limit| are not assigned to
334// |minimum_delay_ms_| and |maximum_delay_ms_| defined by the client of this
335// class. They are computed from |target_level_| and used for decision making.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000336void DelayManager::BufferLimits(int* lower_limit, int* higher_limit) const {
337 if (!lower_limit || !higher_limit) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100338 RTC_LOG_F(LS_ERROR) << "NULL pointers supplied as input";
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000339 assert(false);
340 return;
341 }
342
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000343 int window_20ms = 0x7FFF; // Default large value for legacy bit-exactness.
344 if (packet_len_ms_ > 0) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000345 window_20ms = (20 << 8) / packet_len_ms_;
346 }
turaj@webrtc.orgf1efc572013-08-16 23:44:24 +0000347
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000348 // |target_level_| is in Q8 already.
turaj@webrtc.orgf1efc572013-08-16 23:44:24 +0000349 *lower_limit = (target_level_ * 3) / 4;
350 // |higher_limit| is equal to |target_level_|, but should at
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000351 // least be 20 ms higher than |lower_limit_|.
turaj@webrtc.orgf1efc572013-08-16 23:44:24 +0000352 *higher_limit = std::max(target_level_, *lower_limit + window_20ms);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000353}
354
355int DelayManager::TargetLevel() const {
turaj@webrtc.orgf1efc572013-08-16 23:44:24 +0000356 return target_level_;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000357}
358
ossuf1b08da2016-09-23 02:19:43 -0700359void DelayManager::LastDecodedWasCngOrDtmf(bool it_was) {
360 if (it_was) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000361 last_pack_cng_or_dtmf_ = 1;
362 } else if (last_pack_cng_or_dtmf_ != 0) {
363 last_pack_cng_or_dtmf_ = -1;
364 }
365}
pbos@webrtc.org2d1a55c2013-07-31 15:54:00 +0000366
henrik.lundinb8c55b12017-05-10 07:38:01 -0700367void DelayManager::RegisterEmptyPacket() {
368 ++last_seq_no_;
369}
370
Ruslan Burakov4a68fb92019-02-13 14:25:39 +0100371bool DelayManager::IsValidMinimumDelay(int delay_ms) const {
372 return 0 <= delay_ms && delay_ms <= MinimumDelayUpperBound();
373}
374
375bool DelayManager::IsValidBaseMinimumDelay(int delay_ms) const {
376 return kMinBaseMinimumDelayMs <= delay_ms &&
377 delay_ms <= kMaxBaseMinimumDelayMs;
Ruslan Burakovedbea462019-02-04 16:17:31 +0100378}
379
turaj@webrtc.orgf1efc572013-08-16 23:44:24 +0000380bool DelayManager::SetMinimumDelay(int delay_ms) {
Ruslan Burakovedbea462019-02-04 16:17:31 +0100381 if (!IsValidMinimumDelay(delay_ms)) {
turaj@webrtc.orgf1efc572013-08-16 23:44:24 +0000382 return false;
383 }
Ruslan Burakov4a68fb92019-02-13 14:25:39 +0100384
385 minimum_delay_ms_ = delay_ms;
386 UpdateEffectiveMinimumDelay();
turaj@webrtc.orgf1efc572013-08-16 23:44:24 +0000387 return true;
388}
389
390bool DelayManager::SetMaximumDelay(int delay_ms) {
Ruslan Burakov4a68fb92019-02-13 14:25:39 +0100391 // If |delay_ms| is zero then it unsets the maximum delay and target level is
392 // unconstrained by maximum delay.
393 if (delay_ms != 0 &&
394 (delay_ms < minimum_delay_ms_ || delay_ms < packet_len_ms_)) {
turaj@webrtc.orgf1efc572013-08-16 23:44:24 +0000395 // Maximum delay shouldn't be less than minimum delay or less than a packet.
396 return false;
397 }
Ruslan Burakov4a68fb92019-02-13 14:25:39 +0100398
turaj@webrtc.orgf1efc572013-08-16 23:44:24 +0000399 maximum_delay_ms_ = delay_ms;
Ruslan Burakov4a68fb92019-02-13 14:25:39 +0100400 UpdateEffectiveMinimumDelay();
turaj@webrtc.orgf1efc572013-08-16 23:44:24 +0000401 return true;
402}
403
Ruslan Burakovedbea462019-02-04 16:17:31 +0100404bool DelayManager::SetBaseMinimumDelay(int delay_ms) {
Ruslan Burakov4a68fb92019-02-13 14:25:39 +0100405 if (!IsValidBaseMinimumDelay(delay_ms)) {
Ruslan Burakovedbea462019-02-04 16:17:31 +0100406 return false;
407 }
408
Ruslan Burakov4a68fb92019-02-13 14:25:39 +0100409 base_minimum_delay_ms_ = delay_ms;
410 UpdateEffectiveMinimumDelay();
Ruslan Burakovedbea462019-02-04 16:17:31 +0100411 return true;
412}
413
414int DelayManager::GetBaseMinimumDelay() const {
Ruslan Burakov4a68fb92019-02-13 14:25:39 +0100415 return base_minimum_delay_ms_;
Ruslan Burakovedbea462019-02-04 16:17:31 +0100416}
417
Yves Gerey665174f2018-06-19 15:03:05 +0200418int DelayManager::base_target_level() const {
419 return base_target_level_;
420}
421void DelayManager::set_streaming_mode(bool value) {
422 streaming_mode_ = value;
423}
pbos@webrtc.org2d1a55c2013-07-31 15:54:00 +0000424int DelayManager::last_pack_cng_or_dtmf() const {
425 return last_pack_cng_or_dtmf_;
426}
427
428void DelayManager::set_last_pack_cng_or_dtmf(int value) {
429 last_pack_cng_or_dtmf_ = value;
430}
Ruslan Burakov4a68fb92019-02-13 14:25:39 +0100431
432void DelayManager::UpdateEffectiveMinimumDelay() {
433 // Clamp |base_minimum_delay_ms_| into the range which can be effectively
434 // used.
435 const int base_minimum_delay_ms =
436 rtc::SafeClamp(base_minimum_delay_ms_, 0, MinimumDelayUpperBound());
437 effective_minimum_delay_ms_ =
438 std::max(minimum_delay_ms_, base_minimum_delay_ms);
439}
440
441int DelayManager::MinimumDelayUpperBound() const {
442 // Choose the lowest possible bound discarding 0 cases which mean the value
443 // is not set and unconstrained.
444 int q75 = MaxBufferTimeQ75();
445 q75 = q75 > 0 ? q75 : kMaxBaseMinimumDelayMs;
446 const int maximum_delay_ms =
447 maximum_delay_ms_ > 0 ? maximum_delay_ms_ : kMaxBaseMinimumDelayMs;
448 return std::min(maximum_delay_ms, q75);
449}
450
451int DelayManager::MaxBufferTimeQ75() const {
452 const int max_buffer_time = max_packets_in_buffer_ * packet_len_ms_;
453 return rtc::dchecked_cast<int>(3 * max_buffer_time / 4);
454}
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000455} // namespace webrtc