blob: 1c887b11b5947df8f73cf51ef351da3be2504645 [file] [log] [blame]
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +00001/*
2 * Copyright (c) 2013 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/decision_logic.h"
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000012
Henrik Lundin7687ad52018-07-02 10:14:46 +020013#include <assert.h>
Yves Gerey988cc082018-10-23 12:03:01 +020014#include <stdio.h>
Jonas Olssona4d87372019-07-05 19:08:33 +020015
Yves Gerey988cc082018-10-23 12:03:01 +020016#include <string>
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000017
Jakob Ivarsson46dda832019-07-03 16:00:30 +020018#include "absl/types/optional.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020019#include "modules/audio_coding/neteq/packet_buffer.h"
Yves Gerey988cc082018-10-23 12:03:01 +020020#include "rtc_base/checks.h"
Jakob Ivarsson46dda832019-07-03 16:00:30 +020021#include "rtc_base/experiments/field_trial_parser.h"
Minyue Li7f6417f2018-10-03 21:19:08 +020022#include "rtc_base/logging.h"
Yves Gerey988cc082018-10-23 12:03:01 +020023#include "rtc_base/numerics/safe_conversions.h"
Jakob Ivarsson46dda832019-07-03 16:00:30 +020024#include "system_wrappers/include/field_trial.h"
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000025
Minyue Li7f6417f2018-10-03 21:19:08 +020026namespace {
Minyue Li7f6417f2018-10-03 21:19:08 +020027
Jakob Ivarssond3a780b2019-02-28 14:30:21 +010028constexpr int kPostponeDecodingLevel = 50;
Jakob Ivarsson46dda832019-07-03 16:00:30 +020029constexpr int kDefaultTargetLevelWindowMs = 100;
Minyue Li7f6417f2018-10-03 21:19:08 +020030
31} // namespace
32
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000033namespace webrtc {
34
Ivo Creusen53a31f72019-10-24 15:20:39 +020035DecisionLogic::DecisionLogic(NetEqController::Config config)
36 : delay_peak_detector_(config.tick_timer, config.enable_rtx_handling),
37 delay_manager_(DelayManager::Create(config.max_packets_in_buffer,
38 config.base_min_delay_ms,
39 config.enable_rtx_handling,
40 &delay_peak_detector_,
41 config.tick_timer)),
42 tick_timer_(config.tick_timer),
43 disallow_time_stretching_(!config.allow_time_stretching),
Henrik Lundin47b17dc2016-05-10 10:20:59 +020044 timescale_countdown_(
45 tick_timer_->GetNewCountdown(kMinTimescaleInterval + 1)),
Jakob Ivarsson46dda832019-07-03 16:00:30 +020046 estimate_dtx_delay_("estimate_dtx_delay", false),
47 time_stretch_cn_("time_stretch_cn", false),
48 target_level_window_ms_("target_level_window",
49 kDefaultTargetLevelWindowMs,
50 0,
51 absl::nullopt) {
Jakob Ivarsson46dda832019-07-03 16:00:30 +020052 const std::string field_trial_name =
53 field_trial::FindFullName("WebRTC-Audio-NetEqDecisionLogicSettings");
54 ParseFieldTrial(
55 {&estimate_dtx_delay_, &time_stretch_cn_, &target_level_window_ms_},
56 field_trial_name);
57 RTC_LOG(LS_INFO) << "NetEq decision logic settings:"
58 << " estimate_dtx_delay=" << estimate_dtx_delay_
59 << " time_stretch_cn=" << time_stretch_cn_
60 << " target_level_window_ms=" << target_level_window_ms_;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000061}
62
Henrik Lundin47b17dc2016-05-10 10:20:59 +020063DecisionLogic::~DecisionLogic() = default;
64
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000065void DecisionLogic::Reset() {
66 cng_state_ = kCngOff;
henrik.lundinb1fb72b2016-05-03 08:18:47 -070067 noise_fast_forward_ = 0;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000068 packet_length_samples_ = 0;
69 sample_memory_ = 0;
70 prev_time_scale_ = false;
Henrik Lundin47b17dc2016-05-10 10:20:59 +020071 timescale_countdown_.reset();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000072 num_consecutive_expands_ = 0;
Jakob Ivarsson46dda832019-07-03 16:00:30 +020073 time_stretched_cn_samples_ = 0;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000074}
75
76void DecisionLogic::SoftReset() {
77 packet_length_samples_ = 0;
78 sample_memory_ = 0;
79 prev_time_scale_ = false;
Henrik Lundin47b17dc2016-05-10 10:20:59 +020080 timescale_countdown_ =
81 tick_timer_->GetNewCountdown(kMinTimescaleInterval + 1);
Jakob Ivarsson46dda832019-07-03 16:00:30 +020082 time_stretched_cn_samples_ = 0;
Ivo Creusen53a31f72019-10-24 15:20:39 +020083 delay_manager_->Reset();
84 buffer_level_filter_.Reset();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000085}
86
Peter Kastingdce40cf2015-08-24 14:52:23 -070087void DecisionLogic::SetSampleRate(int fs_hz, size_t output_size_samples) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000088 // TODO(hlundin): Change to an enumerator and skip assert.
Yves Gerey665174f2018-06-19 15:03:05 +020089 assert(fs_hz == 8000 || fs_hz == 16000 || fs_hz == 32000 || fs_hz == 48000);
Jakob Ivarsson46dda832019-07-03 16:00:30 +020090 sample_rate_ = fs_hz;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000091 output_size_samples_ = output_size_samples;
92}
93
Ivo Creusen53a31f72019-10-24 15:20:39 +020094Operations DecisionLogic::GetDecision(const NetEqStatus& status,
henrik.lundinb1fb72b2016-05-03 08:18:47 -070095 bool* reset_decoder) {
ossu61a208b2016-09-20 01:38:00 -070096 // If last mode was CNG (or Expand, since this could be covering up for
97 // a lost CNG packet), remember that CNG is on. This is needed if comfort
98 // noise is interrupted by DTMF.
Ivo Creusen53a31f72019-10-24 15:20:39 +020099 if (status.last_mode == kModeRfc3389Cng) {
ossu61a208b2016-09-20 01:38:00 -0700100 cng_state_ = kCngRfc3389On;
Ivo Creusen53a31f72019-10-24 15:20:39 +0200101 } else if (status.last_mode == kModeCodecInternalCng) {
ossu61a208b2016-09-20 01:38:00 -0700102 cng_state_ = kCngInternalOn;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000103 }
104
Ivo Creusen53a31f72019-10-24 15:20:39 +0200105 size_t cur_size_samples = estimate_dtx_delay_
106 ? status.packet_buffer_info.span_samples
107 : status.packet_buffer_info.num_samples;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000108
Yves Gerey665174f2018-06-19 15:03:05 +0200109 prev_time_scale_ =
Ivo Creusen53a31f72019-10-24 15:20:39 +0200110 prev_time_scale_ && (status.last_mode == kModeAccelerateSuccess ||
111 status.last_mode == kModeAccelerateLowEnergy ||
112 status.last_mode == kModePreemptiveExpandSuccess ||
113 status.last_mode == kModePreemptiveExpandLowEnergy);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000114
Minyue Li7d204d52019-04-16 11:44:49 +0200115 // Do not update buffer history if currently playing CNG since it will bias
116 // the filtered buffer level.
Ivo Creusen53a31f72019-10-24 15:20:39 +0200117 if (status.last_mode != kModeRfc3389Cng &&
118 status.last_mode != kModeCodecInternalCng &&
119 !(status.next_packet && status.next_packet->is_dtx &&
120 !estimate_dtx_delay_)) {
Minyue Li7d204d52019-04-16 11:44:49 +0200121 FilterBufferLevel(cur_size_samples);
122 }
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000123
Henrik Lundin7687ad52018-07-02 10:14:46 +0200124 // Guard for errors, to avoid getting stuck in error mode.
Ivo Creusen53a31f72019-10-24 15:20:39 +0200125 if (status.last_mode == kModeError) {
126 if (!status.next_packet) {
Henrik Lundin7687ad52018-07-02 10:14:46 +0200127 return kExpand;
128 } else {
129 return kUndefined; // Use kUndefined to flag for a reset.
130 }
131 }
132
Ivo Creusen53a31f72019-10-24 15:20:39 +0200133 if (status.next_packet && status.next_packet->is_cng) {
134 return CngOperation(status.last_mode, status.target_timestamp,
135 status.next_packet->timestamp,
136 status.generated_noise_samples);
Henrik Lundin7687ad52018-07-02 10:14:46 +0200137 }
138
139 // Handle the case with no packet at all available (except maybe DTMF).
Ivo Creusen53a31f72019-10-24 15:20:39 +0200140 if (!status.next_packet) {
141 return NoPacket(status.play_dtmf);
Henrik Lundin7687ad52018-07-02 10:14:46 +0200142 }
143
144 // If the expand period was very long, reset NetEQ since it is likely that the
145 // sender was restarted.
146 if (num_consecutive_expands_ > kReinitAfterExpands) {
147 *reset_decoder = true;
148 return kNormal;
149 }
150
151 // Make sure we don't restart audio too soon after an expansion to avoid
152 // running out of data right away again. We should only wait if there are no
153 // DTX or CNG packets in the buffer (otherwise we should just play out what we
154 // have, since we cannot know the exact duration of DTX or CNG packets), and
155 // if the mute factor is low enough (otherwise the expansion was short enough
156 // to not be noticable).
157 // Note that the MuteFactor is in Q14, so a value of 16384 corresponds to 1.
Ivo Creusen53a31f72019-10-24 15:20:39 +0200158 const size_t current_span =
159 estimate_dtx_delay_ ? status.packet_buffer_info.span_samples
160 : status.packet_buffer_info.span_samples_no_dtx;
161 if ((status.last_mode == kModeExpand || status.last_mode == kModeCodecPlc) &&
162 status.expand_mutefactor < 16384 / 2 &&
Jonas Olssona4d87372019-07-05 19:08:33 +0200163 current_span<static_cast<size_t>(delay_manager_->TargetLevel() *
164 packet_length_samples_ *
165 kPostponeDecodingLevel / 100)>> 8 &&
Ivo Creusen53a31f72019-10-24 15:20:39 +0200166 !status.packet_buffer_info.dtx_or_cng) {
Henrik Lundin7687ad52018-07-02 10:14:46 +0200167 return kExpand;
168 }
169
Jakob Ivarsson46dda832019-07-03 16:00:30 +0200170 const uint32_t five_seconds_samples = static_cast<uint32_t>(5 * sample_rate_);
Henrik Lundin7687ad52018-07-02 10:14:46 +0200171 // Check if the required packet is available.
Ivo Creusen53a31f72019-10-24 15:20:39 +0200172 if (status.target_timestamp == status.next_packet->timestamp) {
173 return ExpectedPacketAvailable(status.last_mode, status.play_dtmf);
174 } else if (!PacketBuffer::IsObsoleteTimestamp(status.next_packet->timestamp,
175 status.target_timestamp,
176 five_seconds_samples)) {
177 return FuturePacketAvailable(
178 status.last_packet_samples, status.last_mode, status.target_timestamp,
179 status.next_packet->timestamp, status.play_dtmf,
180 status.generated_noise_samples, status.packet_buffer_info.span_samples,
181 status.packet_buffer_info.num_packets);
Henrik Lundin7687ad52018-07-02 10:14:46 +0200182 } else {
183 // This implies that available_timestamp < target_timestamp, which can
184 // happen when a new stream or codec is received. Signal for a reset.
185 return kUndefined;
186 }
187}
188
Henrik Lundin5afa61c2018-07-02 14:53:24 +0200189void DecisionLogic::ExpandDecision(Operations operation) {
190 if (operation == kExpand) {
191 num_consecutive_expands_++;
192 } else {
193 num_consecutive_expands_ = 0;
194 }
195}
196
Ivo Creusen53a31f72019-10-24 15:20:39 +0200197absl::optional<int> DecisionLogic::PacketArrived(bool last_cng_or_dtmf,
198 size_t packet_length_samples,
199 bool should_update_stats,
200 uint16_t main_sequence_number,
201 uint32_t main_timestamp,
202 int fs_hz) {
203 delay_manager_->LastDecodedWasCngOrDtmf(last_cng_or_dtmf);
204 absl::optional<int> relative_delay;
205 if (delay_manager_->last_pack_cng_or_dtmf() == 0) {
206 // Calculate the total speech length carried in each packet.
207 if (packet_length_samples > 0 &&
208 packet_length_samples != packet_length_samples_) {
209 packet_length_samples_ = packet_length_samples;
210 delay_manager_->SetPacketAudioLength(
211 rtc::dchecked_cast<int>((1000 * packet_length_samples) / fs_hz));
212 }
213
214 // Update statistics.
215 if (should_update_stats) {
216 relative_delay =
217 delay_manager_->Update(main_sequence_number, main_timestamp, fs_hz);
218 }
219 } else if (delay_manager_->last_pack_cng_or_dtmf() == -1) {
220 // This is first "normal" packet after CNG or DTMF.
221 // Reset packet time counter and measure time until next packet,
222 // but don't update statistics.
223 delay_manager_->set_last_pack_cng_or_dtmf(0);
224 delay_manager_->ResetPacketIatCount();
225 }
226 return relative_delay;
227}
228
Minyue Li7d204d52019-04-16 11:44:49 +0200229void DecisionLogic::FilterBufferLevel(size_t buffer_size_samples) {
Ivo Creusen53a31f72019-10-24 15:20:39 +0200230 buffer_level_filter_.SetTargetBufferLevel(
Minyue Li7d204d52019-04-16 11:44:49 +0200231 delay_manager_->base_target_level());
Henrik Lundin5afa61c2018-07-02 14:53:24 +0200232
Jakob Ivarsson46dda832019-07-03 16:00:30 +0200233 int time_stretched_samples = time_stretched_cn_samples_;
Minyue Li7d204d52019-04-16 11:44:49 +0200234 if (prev_time_scale_) {
Jakob Ivarsson46dda832019-07-03 16:00:30 +0200235 time_stretched_samples += sample_memory_;
Minyue Li7d204d52019-04-16 11:44:49 +0200236 timescale_countdown_ = tick_timer_->GetNewCountdown(kMinTimescaleInterval);
237 }
238
Ivo Creusen53a31f72019-10-24 15:20:39 +0200239 buffer_level_filter_.Update(buffer_size_samples, time_stretched_samples);
Minyue Li7d204d52019-04-16 11:44:49 +0200240 prev_time_scale_ = false;
Jakob Ivarsson46dda832019-07-03 16:00:30 +0200241 time_stretched_cn_samples_ = 0;
Henrik Lundin5afa61c2018-07-02 14:53:24 +0200242}
243
Henrik Lundin7687ad52018-07-02 10:14:46 +0200244Operations DecisionLogic::CngOperation(Modes prev_mode,
245 uint32_t target_timestamp,
246 uint32_t available_timestamp,
247 size_t generated_noise_samples) {
248 // Signed difference between target and available timestamp.
249 int32_t timestamp_diff = static_cast<int32_t>(
250 static_cast<uint32_t>(generated_noise_samples + target_timestamp) -
251 available_timestamp);
252 int32_t optimal_level_samp = static_cast<int32_t>(
253 (delay_manager_->TargetLevel() * packet_length_samples_) >> 8);
254 const int64_t excess_waiting_time_samp =
255 -static_cast<int64_t>(timestamp_diff) - optimal_level_samp;
256
257 if (excess_waiting_time_samp > optimal_level_samp / 2) {
258 // The waiting time for this packet will be longer than 1.5
259 // times the wanted buffer delay. Apply fast-forward to cut the
260 // waiting time down to the optimal.
Jakob Ivarsson42b6e2d2019-10-21 11:51:05 +0200261 noise_fast_forward_ = rtc::saturated_cast<size_t>(noise_fast_forward_ +
262 excess_waiting_time_samp);
Henrik Lundin7687ad52018-07-02 10:14:46 +0200263 timestamp_diff =
264 rtc::saturated_cast<int32_t>(timestamp_diff + excess_waiting_time_samp);
265 }
266
267 if (timestamp_diff < 0 && prev_mode == kModeRfc3389Cng) {
268 // Not time to play this packet yet. Wait another round before using this
269 // packet. Keep on playing CNG from previous CNG parameters.
270 return kRfc3389CngNoPacket;
271 } else {
272 // Otherwise, go for the CNG packet now.
273 noise_fast_forward_ = 0;
274 return kRfc3389Cng;
275 }
276}
277
278Operations DecisionLogic::NoPacket(bool play_dtmf) {
279 if (cng_state_ == kCngRfc3389On) {
280 // Keep on playing comfort noise.
281 return kRfc3389CngNoPacket;
282 } else if (cng_state_ == kCngInternalOn) {
283 // Keep on playing codec internal comfort noise.
284 return kCodecInternalCng;
285 } else if (play_dtmf) {
286 return kDtmf;
287 } else {
288 // Nothing to play, do expand.
289 return kExpand;
290 }
291}
292
293Operations DecisionLogic::ExpectedPacketAvailable(Modes prev_mode,
294 bool play_dtmf) {
295 if (!disallow_time_stretching_ && prev_mode != kModeExpand && !play_dtmf) {
Jakob Ivarssona36c5912019-06-27 10:12:02 +0200296 // Check criterion for time-stretching. The values are in number of packets
297 // in Q8.
Henrik Lundin7687ad52018-07-02 10:14:46 +0200298 int low_limit, high_limit;
299 delay_manager_->BufferLimits(&low_limit, &high_limit);
Jakob Ivarssona36c5912019-06-27 10:12:02 +0200300 int buffer_level_packets = 0;
301 if (packet_length_samples_ > 0) {
302 buffer_level_packets =
Ivo Creusen53a31f72019-10-24 15:20:39 +0200303 ((1 << 8) * buffer_level_filter_.filtered_current_level()) /
Jakob Ivarssona36c5912019-06-27 10:12:02 +0200304 packet_length_samples_;
305 }
306 if (buffer_level_packets >= high_limit << 2)
Henrik Lundin7687ad52018-07-02 10:14:46 +0200307 return kFastAccelerate;
308 if (TimescaleAllowed()) {
Jakob Ivarssona36c5912019-06-27 10:12:02 +0200309 if (buffer_level_packets >= high_limit)
Henrik Lundin7687ad52018-07-02 10:14:46 +0200310 return kAccelerate;
Jakob Ivarssona36c5912019-06-27 10:12:02 +0200311 if (buffer_level_packets < low_limit)
Henrik Lundin7687ad52018-07-02 10:14:46 +0200312 return kPreemptiveExpand;
313 }
314 }
315 return kNormal;
316}
317
318Operations DecisionLogic::FuturePacketAvailable(
Henrik Lundin7687ad52018-07-02 10:14:46 +0200319 size_t decoder_frame_length,
320 Modes prev_mode,
321 uint32_t target_timestamp,
322 uint32_t available_timestamp,
323 bool play_dtmf,
Ivo Creusen53a31f72019-10-24 15:20:39 +0200324 size_t generated_noise_samples,
325 size_t span_samples_in_packet_buffer,
326 size_t num_packets_in_packet_buffer) {
Henrik Lundin7687ad52018-07-02 10:14:46 +0200327 // Required packet is not available, but a future packet is.
328 // Check if we should continue with an ongoing expand because the new packet
329 // is too far into the future.
330 uint32_t timestamp_leap = available_timestamp - target_timestamp;
Henrik Lundin00eb12a2018-09-05 18:14:52 +0200331 if ((prev_mode == kModeExpand || prev_mode == kModeCodecPlc) &&
332 !ReinitAfterExpands(timestamp_leap) && !MaxWaitForPacket() &&
333 PacketTooEarly(timestamp_leap) && UnderTargetLevel()) {
Henrik Lundin7687ad52018-07-02 10:14:46 +0200334 if (play_dtmf) {
335 // Still have DTMF to play, so do not do expand.
336 return kDtmf;
337 } else {
338 // Nothing to play.
339 return kExpand;
340 }
341 }
342
Henrik Lundin00eb12a2018-09-05 18:14:52 +0200343 if (prev_mode == kModeCodecPlc) {
344 return kNormal;
345 }
346
Henrik Lundin7687ad52018-07-02 10:14:46 +0200347 // If previous was comfort noise, then no merge is needed.
348 if (prev_mode == kModeRfc3389Cng || prev_mode == kModeCodecInternalCng) {
Jakob Ivarsson46dda832019-07-03 16:00:30 +0200349 size_t cur_size_samples =
350 estimate_dtx_delay_
Ivo Creusen53a31f72019-10-24 15:20:39 +0200351 ? cur_size_samples = span_samples_in_packet_buffer
352 : num_packets_in_packet_buffer * decoder_frame_length;
Jakob Ivarsson46dda832019-07-03 16:00:30 +0200353 // Target level is in number of packets in Q8.
354 const size_t target_level_samples =
355 (delay_manager_->TargetLevel() * packet_length_samples_) >> 8;
356 const bool generated_enough_noise =
357 static_cast<uint32_t>(generated_noise_samples + target_timestamp) >=
358 available_timestamp;
359
360 if (time_stretch_cn_) {
361 const size_t target_threshold_samples =
362 target_level_window_ms_ / 2 * (sample_rate_ / 1000);
363 const bool above_target_window =
364 cur_size_samples > target_level_samples + target_threshold_samples;
365 const bool below_target_window =
366 target_level_samples > target_threshold_samples &&
367 cur_size_samples < target_level_samples - target_threshold_samples;
368 // Keep the delay same as before CNG, but make sure that it is within the
369 // target window.
370 if ((generated_enough_noise && !below_target_window) ||
371 above_target_window) {
372 time_stretched_cn_samples_ = timestamp_leap - generated_noise_samples;
373 return kNormal;
374 }
Henrik Lundin7687ad52018-07-02 10:14:46 +0200375 } else {
Jakob Ivarsson46dda832019-07-03 16:00:30 +0200376 // Keep the same delay as before the CNG, but make sure that the number of
377 // samples in buffer is no higher than 4 times the optimal level.
378 if (generated_enough_noise ||
379 cur_size_samples > target_level_samples * 4) {
380 // Time to play this new packet.
381 return kNormal;
Henrik Lundin7687ad52018-07-02 10:14:46 +0200382 }
383 }
Jakob Ivarsson46dda832019-07-03 16:00:30 +0200384
385 // Too early to play this new packet; keep on playing comfort noise.
386 if (prev_mode == kModeRfc3389Cng) {
387 return kRfc3389CngNoPacket;
388 }
389 // prevPlayMode == kModeCodecInternalCng.
390 return kCodecInternalCng;
Henrik Lundin7687ad52018-07-02 10:14:46 +0200391 }
Jakob Ivarsson46dda832019-07-03 16:00:30 +0200392
Henrik Lundin7687ad52018-07-02 10:14:46 +0200393 // Do not merge unless we have done an expand before.
394 if (prev_mode == kModeExpand) {
395 return kMerge;
396 } else if (play_dtmf) {
397 // Play DTMF instead of expand.
398 return kDtmf;
399 } else {
400 return kExpand;
401 }
402}
403
404bool DecisionLogic::UnderTargetLevel() const {
Jakob Ivarssona36c5912019-06-27 10:12:02 +0200405 int buffer_level_packets = 0;
406 if (packet_length_samples_ > 0) {
407 buffer_level_packets =
Ivo Creusen53a31f72019-10-24 15:20:39 +0200408 ((1 << 8) * buffer_level_filter_.filtered_current_level()) /
Jakob Ivarssona36c5912019-06-27 10:12:02 +0200409 packet_length_samples_;
410 }
411 return buffer_level_packets <= delay_manager_->TargetLevel();
Henrik Lundin7687ad52018-07-02 10:14:46 +0200412}
413
414bool DecisionLogic::ReinitAfterExpands(uint32_t timestamp_leap) const {
415 return timestamp_leap >=
416 static_cast<uint32_t>(output_size_samples_ * kReinitAfterExpands);
417}
418
419bool DecisionLogic::PacketTooEarly(uint32_t timestamp_leap) const {
420 return timestamp_leap >
421 static_cast<uint32_t>(output_size_samples_ * num_consecutive_expands_);
422}
423
424bool DecisionLogic::MaxWaitForPacket() const {
425 return num_consecutive_expands_ >= kMaxWaitForPacket;
426}
427
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000428} // namespace webrtc