blob: fefad689ed256b8d5338f58397bd566a4e65c09b [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/buffer_level_filter.h"
Henrik Lundin7687ad52018-07-02 10:14:46 +020020#include "modules/audio_coding/neteq/decoder_database.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020021#include "modules/audio_coding/neteq/delay_manager.h"
22#include "modules/audio_coding/neteq/expand.h"
23#include "modules/audio_coding/neteq/packet_buffer.h"
24#include "modules/audio_coding/neteq/sync_buffer.h"
Yves Gerey988cc082018-10-23 12:03:01 +020025#include "rtc_base/checks.h"
Jakob Ivarsson46dda832019-07-03 16:00:30 +020026#include "rtc_base/experiments/field_trial_parser.h"
Minyue Li7f6417f2018-10-03 21:19:08 +020027#include "rtc_base/logging.h"
Yves Gerey988cc082018-10-23 12:03:01 +020028#include "rtc_base/numerics/safe_conversions.h"
Jakob Ivarsson46dda832019-07-03 16:00:30 +020029#include "system_wrappers/include/field_trial.h"
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000030
Minyue Li7f6417f2018-10-03 21:19:08 +020031namespace {
Minyue Li7f6417f2018-10-03 21:19:08 +020032
Jakob Ivarssond3a780b2019-02-28 14:30:21 +010033constexpr int kPostponeDecodingLevel = 50;
Jakob Ivarsson46dda832019-07-03 16:00:30 +020034constexpr int kDefaultTargetLevelWindowMs = 100;
Minyue Li7f6417f2018-10-03 21:19:08 +020035
36} // namespace
37
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000038namespace webrtc {
39
40DecisionLogic* DecisionLogic::Create(int fs_hz,
Peter Kastingdce40cf2015-08-24 14:52:23 -070041 size_t output_size_samples,
Henrik Lundin7687ad52018-07-02 10:14:46 +020042 bool disallow_time_stretching,
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000043 DecoderDatabase* decoder_database,
44 const PacketBuffer& packet_buffer,
45 DelayManager* delay_manager,
Henrik Lundin47b17dc2016-05-10 10:20:59 +020046 BufferLevelFilter* buffer_level_filter,
47 const TickTimer* tick_timer) {
Henrik Lundin7687ad52018-07-02 10:14:46 +020048 return new DecisionLogic(fs_hz, output_size_samples, disallow_time_stretching,
49 decoder_database, packet_buffer, delay_manager,
50 buffer_level_filter, tick_timer);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000051}
52
53DecisionLogic::DecisionLogic(int fs_hz,
Peter Kastingdce40cf2015-08-24 14:52:23 -070054 size_t output_size_samples,
Henrik Lundin7687ad52018-07-02 10:14:46 +020055 bool disallow_time_stretching,
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000056 DecoderDatabase* decoder_database,
57 const PacketBuffer& packet_buffer,
58 DelayManager* delay_manager,
Henrik Lundin47b17dc2016-05-10 10:20:59 +020059 BufferLevelFilter* buffer_level_filter,
60 const TickTimer* tick_timer)
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000061 : decoder_database_(decoder_database),
62 packet_buffer_(packet_buffer),
63 delay_manager_(delay_manager),
64 buffer_level_filter_(buffer_level_filter),
Henrik Lundin47b17dc2016-05-10 10:20:59 +020065 tick_timer_(tick_timer),
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000066 cng_state_(kCngOff),
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000067 packet_length_samples_(0),
68 sample_memory_(0),
69 prev_time_scale_(false),
Henrik Lundin7687ad52018-07-02 10:14:46 +020070 disallow_time_stretching_(disallow_time_stretching),
Henrik Lundin47b17dc2016-05-10 10:20:59 +020071 timescale_countdown_(
72 tick_timer_->GetNewCountdown(kMinTimescaleInterval + 1)),
Jakob Ivarsson46dda832019-07-03 16:00:30 +020073 num_consecutive_expands_(0),
74 time_stretched_cn_samples_(0),
75 estimate_dtx_delay_("estimate_dtx_delay", false),
76 time_stretch_cn_("time_stretch_cn", false),
77 target_level_window_ms_("target_level_window",
78 kDefaultTargetLevelWindowMs,
79 0,
80 absl::nullopt) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000081 SetSampleRate(fs_hz, output_size_samples);
Jakob Ivarsson46dda832019-07-03 16:00:30 +020082 const std::string field_trial_name =
83 field_trial::FindFullName("WebRTC-Audio-NetEqDecisionLogicSettings");
84 ParseFieldTrial(
85 {&estimate_dtx_delay_, &time_stretch_cn_, &target_level_window_ms_},
86 field_trial_name);
87 RTC_LOG(LS_INFO) << "NetEq decision logic settings:"
88 << " estimate_dtx_delay=" << estimate_dtx_delay_
89 << " time_stretch_cn=" << time_stretch_cn_
90 << " target_level_window_ms=" << target_level_window_ms_;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000091}
92
Henrik Lundin47b17dc2016-05-10 10:20:59 +020093DecisionLogic::~DecisionLogic() = default;
94
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000095void DecisionLogic::Reset() {
96 cng_state_ = kCngOff;
henrik.lundinb1fb72b2016-05-03 08:18:47 -070097 noise_fast_forward_ = 0;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000098 packet_length_samples_ = 0;
99 sample_memory_ = 0;
100 prev_time_scale_ = false;
Henrik Lundin47b17dc2016-05-10 10:20:59 +0200101 timescale_countdown_.reset();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000102 num_consecutive_expands_ = 0;
Jakob Ivarsson46dda832019-07-03 16:00:30 +0200103 time_stretched_cn_samples_ = 0;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000104}
105
106void DecisionLogic::SoftReset() {
107 packet_length_samples_ = 0;
108 sample_memory_ = 0;
109 prev_time_scale_ = false;
Henrik Lundin47b17dc2016-05-10 10:20:59 +0200110 timescale_countdown_ =
111 tick_timer_->GetNewCountdown(kMinTimescaleInterval + 1);
Jakob Ivarsson46dda832019-07-03 16:00:30 +0200112 time_stretched_cn_samples_ = 0;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000113}
114
Peter Kastingdce40cf2015-08-24 14:52:23 -0700115void DecisionLogic::SetSampleRate(int fs_hz, size_t output_size_samples) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000116 // TODO(hlundin): Change to an enumerator and skip assert.
Yves Gerey665174f2018-06-19 15:03:05 +0200117 assert(fs_hz == 8000 || fs_hz == 16000 || fs_hz == 32000 || fs_hz == 48000);
Jakob Ivarsson46dda832019-07-03 16:00:30 +0200118 sample_rate_ = fs_hz;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000119 output_size_samples_ = output_size_samples;
120}
121
122Operations DecisionLogic::GetDecision(const SyncBuffer& sync_buffer,
123 const Expand& expand,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700124 size_t decoder_frame_length,
ossu7a377612016-10-18 04:06:13 -0700125 const Packet* next_packet,
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000126 Modes prev_mode,
henrik.lundinb1fb72b2016-05-03 08:18:47 -0700127 bool play_dtmf,
128 size_t generated_noise_samples,
129 bool* reset_decoder) {
ossu61a208b2016-09-20 01:38:00 -0700130 // If last mode was CNG (or Expand, since this could be covering up for
131 // a lost CNG packet), remember that CNG is on. This is needed if comfort
132 // noise is interrupted by DTMF.
133 if (prev_mode == kModeRfc3389Cng) {
134 cng_state_ = kCngRfc3389On;
135 } else if (prev_mode == kModeCodecInternalCng) {
136 cng_state_ = kCngInternalOn;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000137 }
138
Jakob Ivarsson46dda832019-07-03 16:00:30 +0200139 size_t cur_size_samples =
140 estimate_dtx_delay_
141 ? packet_buffer_.GetSpanSamples(decoder_frame_length, sample_rate_,
142 true)
143 : packet_buffer_.NumSamplesInBuffer(decoder_frame_length);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000144
Yves Gerey665174f2018-06-19 15:03:05 +0200145 prev_time_scale_ =
146 prev_time_scale_ && (prev_mode == kModeAccelerateSuccess ||
147 prev_mode == kModeAccelerateLowEnergy ||
148 prev_mode == kModePreemptiveExpandSuccess ||
149 prev_mode == kModePreemptiveExpandLowEnergy);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000150
Minyue Li7d204d52019-04-16 11:44:49 +0200151 // Do not update buffer history if currently playing CNG since it will bias
152 // the filtered buffer level.
Jakob Ivarsson46dda832019-07-03 16:00:30 +0200153 if (prev_mode != kModeRfc3389Cng && prev_mode != kModeCodecInternalCng &&
Minyue Li7d204d52019-04-16 11:44:49 +0200154 !(next_packet && next_packet->frame &&
Jakob Ivarsson46dda832019-07-03 16:00:30 +0200155 next_packet->frame->IsDtxPacket() && !estimate_dtx_delay_)) {
Minyue Li7d204d52019-04-16 11:44:49 +0200156 FilterBufferLevel(cur_size_samples);
157 }
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000158
Henrik Lundin7687ad52018-07-02 10:14:46 +0200159 // Guard for errors, to avoid getting stuck in error mode.
160 if (prev_mode == kModeError) {
161 if (!next_packet) {
162 return kExpand;
163 } else {
164 return kUndefined; // Use kUndefined to flag for a reset.
165 }
166 }
167
168 uint32_t target_timestamp = sync_buffer.end_timestamp();
169 uint32_t available_timestamp = 0;
170 bool is_cng_packet = false;
171 if (next_packet) {
172 available_timestamp = next_packet->timestamp;
173 is_cng_packet =
174 decoder_database_->IsComfortNoise(next_packet->payload_type);
175 }
176
177 if (is_cng_packet) {
178 return CngOperation(prev_mode, target_timestamp, available_timestamp,
179 generated_noise_samples);
180 }
181
182 // Handle the case with no packet at all available (except maybe DTMF).
183 if (!next_packet) {
184 return NoPacket(play_dtmf);
185 }
186
187 // If the expand period was very long, reset NetEQ since it is likely that the
188 // sender was restarted.
189 if (num_consecutive_expands_ > kReinitAfterExpands) {
190 *reset_decoder = true;
191 return kNormal;
192 }
193
194 // Make sure we don't restart audio too soon after an expansion to avoid
195 // running out of data right away again. We should only wait if there are no
196 // DTX or CNG packets in the buffer (otherwise we should just play out what we
197 // have, since we cannot know the exact duration of DTX or CNG packets), and
198 // if the mute factor is low enough (otherwise the expansion was short enough
199 // to not be noticable).
200 // Note that the MuteFactor is in Q14, so a value of 16384 corresponds to 1.
Jakob Ivarsson46dda832019-07-03 16:00:30 +0200201 size_t current_span = packet_buffer_.GetSpanSamples(
202 decoder_frame_length, sample_rate_, estimate_dtx_delay_);
Minyue Li7f6417f2018-10-03 21:19:08 +0200203 if ((prev_mode == kModeExpand || prev_mode == kModeCodecPlc) &&
204 expand.MuteFactor(0) < 16384 / 2 &&
Jonas Olssona4d87372019-07-05 19:08:33 +0200205 current_span<static_cast<size_t>(delay_manager_->TargetLevel() *
206 packet_length_samples_ *
207 kPostponeDecodingLevel / 100)>> 8 &&
Minyue Li7f6417f2018-10-03 21:19:08 +0200208 !packet_buffer_.ContainsDtxOrCngPacket(decoder_database_)) {
Henrik Lundin7687ad52018-07-02 10:14:46 +0200209 return kExpand;
210 }
211
Jakob Ivarsson46dda832019-07-03 16:00:30 +0200212 const uint32_t five_seconds_samples = static_cast<uint32_t>(5 * sample_rate_);
Henrik Lundin7687ad52018-07-02 10:14:46 +0200213 // Check if the required packet is available.
214 if (target_timestamp == available_timestamp) {
215 return ExpectedPacketAvailable(prev_mode, play_dtmf);
216 } else if (!PacketBuffer::IsObsoleteTimestamp(
217 available_timestamp, target_timestamp, five_seconds_samples)) {
Jakob Ivarssona36c5912019-06-27 10:12:02 +0200218 return FuturePacketAvailable(decoder_frame_length, prev_mode,
219 target_timestamp, available_timestamp,
220 play_dtmf, generated_noise_samples);
Henrik Lundin7687ad52018-07-02 10:14:46 +0200221 } else {
222 // This implies that available_timestamp < target_timestamp, which can
223 // happen when a new stream or codec is received. Signal for a reset.
224 return kUndefined;
225 }
226}
227
Henrik Lundin5afa61c2018-07-02 14:53:24 +0200228void DecisionLogic::ExpandDecision(Operations operation) {
229 if (operation == kExpand) {
230 num_consecutive_expands_++;
231 } else {
232 num_consecutive_expands_ = 0;
233 }
234}
235
Minyue Li7d204d52019-04-16 11:44:49 +0200236void DecisionLogic::FilterBufferLevel(size_t buffer_size_samples) {
237 buffer_level_filter_->SetTargetBufferLevel(
238 delay_manager_->base_target_level());
Henrik Lundin5afa61c2018-07-02 14:53:24 +0200239
Jakob Ivarsson46dda832019-07-03 16:00:30 +0200240 int time_stretched_samples = time_stretched_cn_samples_;
Minyue Li7d204d52019-04-16 11:44:49 +0200241 if (prev_time_scale_) {
Jakob Ivarsson46dda832019-07-03 16:00:30 +0200242 time_stretched_samples += sample_memory_;
Minyue Li7d204d52019-04-16 11:44:49 +0200243 timescale_countdown_ = tick_timer_->GetNewCountdown(kMinTimescaleInterval);
244 }
245
Jakob Ivarsson46dda832019-07-03 16:00:30 +0200246 buffer_level_filter_->Update(buffer_size_samples, time_stretched_samples);
Minyue Li7d204d52019-04-16 11:44:49 +0200247 prev_time_scale_ = false;
Jakob Ivarsson46dda832019-07-03 16:00:30 +0200248 time_stretched_cn_samples_ = 0;
Henrik Lundin5afa61c2018-07-02 14:53:24 +0200249}
250
Henrik Lundin7687ad52018-07-02 10:14:46 +0200251Operations DecisionLogic::CngOperation(Modes prev_mode,
252 uint32_t target_timestamp,
253 uint32_t available_timestamp,
254 size_t generated_noise_samples) {
255 // Signed difference between target and available timestamp.
256 int32_t timestamp_diff = static_cast<int32_t>(
257 static_cast<uint32_t>(generated_noise_samples + target_timestamp) -
258 available_timestamp);
259 int32_t optimal_level_samp = static_cast<int32_t>(
260 (delay_manager_->TargetLevel() * packet_length_samples_) >> 8);
261 const int64_t excess_waiting_time_samp =
262 -static_cast<int64_t>(timestamp_diff) - optimal_level_samp;
263
264 if (excess_waiting_time_samp > optimal_level_samp / 2) {
265 // The waiting time for this packet will be longer than 1.5
266 // times the wanted buffer delay. Apply fast-forward to cut the
267 // waiting time down to the optimal.
Jakob Ivarsson42b6e2d2019-10-21 11:51:05 +0200268 noise_fast_forward_ = rtc::saturated_cast<size_t>(noise_fast_forward_ +
269 excess_waiting_time_samp);
Henrik Lundin7687ad52018-07-02 10:14:46 +0200270 timestamp_diff =
271 rtc::saturated_cast<int32_t>(timestamp_diff + excess_waiting_time_samp);
272 }
273
274 if (timestamp_diff < 0 && prev_mode == kModeRfc3389Cng) {
275 // Not time to play this packet yet. Wait another round before using this
276 // packet. Keep on playing CNG from previous CNG parameters.
277 return kRfc3389CngNoPacket;
278 } else {
279 // Otherwise, go for the CNG packet now.
280 noise_fast_forward_ = 0;
281 return kRfc3389Cng;
282 }
283}
284
285Operations DecisionLogic::NoPacket(bool play_dtmf) {
286 if (cng_state_ == kCngRfc3389On) {
287 // Keep on playing comfort noise.
288 return kRfc3389CngNoPacket;
289 } else if (cng_state_ == kCngInternalOn) {
290 // Keep on playing codec internal comfort noise.
291 return kCodecInternalCng;
292 } else if (play_dtmf) {
293 return kDtmf;
294 } else {
295 // Nothing to play, do expand.
296 return kExpand;
297 }
298}
299
300Operations DecisionLogic::ExpectedPacketAvailable(Modes prev_mode,
301 bool play_dtmf) {
302 if (!disallow_time_stretching_ && prev_mode != kModeExpand && !play_dtmf) {
Jakob Ivarssona36c5912019-06-27 10:12:02 +0200303 // Check criterion for time-stretching. The values are in number of packets
304 // in Q8.
Henrik Lundin7687ad52018-07-02 10:14:46 +0200305 int low_limit, high_limit;
306 delay_manager_->BufferLimits(&low_limit, &high_limit);
Jakob Ivarssona36c5912019-06-27 10:12:02 +0200307 int buffer_level_packets = 0;
308 if (packet_length_samples_ > 0) {
309 buffer_level_packets =
310 ((1 << 8) * buffer_level_filter_->filtered_current_level()) /
311 packet_length_samples_;
312 }
313 if (buffer_level_packets >= high_limit << 2)
Henrik Lundin7687ad52018-07-02 10:14:46 +0200314 return kFastAccelerate;
315 if (TimescaleAllowed()) {
Jakob Ivarssona36c5912019-06-27 10:12:02 +0200316 if (buffer_level_packets >= high_limit)
Henrik Lundin7687ad52018-07-02 10:14:46 +0200317 return kAccelerate;
Jakob Ivarssona36c5912019-06-27 10:12:02 +0200318 if (buffer_level_packets < low_limit)
Henrik Lundin7687ad52018-07-02 10:14:46 +0200319 return kPreemptiveExpand;
320 }
321 }
322 return kNormal;
323}
324
325Operations DecisionLogic::FuturePacketAvailable(
Henrik Lundin7687ad52018-07-02 10:14:46 +0200326 size_t decoder_frame_length,
327 Modes prev_mode,
328 uint32_t target_timestamp,
329 uint32_t available_timestamp,
330 bool play_dtmf,
331 size_t generated_noise_samples) {
332 // Required packet is not available, but a future packet is.
333 // Check if we should continue with an ongoing expand because the new packet
334 // is too far into the future.
335 uint32_t timestamp_leap = available_timestamp - target_timestamp;
Henrik Lundin00eb12a2018-09-05 18:14:52 +0200336 if ((prev_mode == kModeExpand || prev_mode == kModeCodecPlc) &&
337 !ReinitAfterExpands(timestamp_leap) && !MaxWaitForPacket() &&
338 PacketTooEarly(timestamp_leap) && UnderTargetLevel()) {
Henrik Lundin7687ad52018-07-02 10:14:46 +0200339 if (play_dtmf) {
340 // Still have DTMF to play, so do not do expand.
341 return kDtmf;
342 } else {
343 // Nothing to play.
344 return kExpand;
345 }
346 }
347
Henrik Lundin00eb12a2018-09-05 18:14:52 +0200348 if (prev_mode == kModeCodecPlc) {
349 return kNormal;
350 }
351
Henrik Lundin7687ad52018-07-02 10:14:46 +0200352 // If previous was comfort noise, then no merge is needed.
353 if (prev_mode == kModeRfc3389Cng || prev_mode == kModeCodecInternalCng) {
Jakob Ivarsson46dda832019-07-03 16:00:30 +0200354 size_t cur_size_samples =
355 estimate_dtx_delay_
356 ? cur_size_samples = packet_buffer_.GetSpanSamples(
357 decoder_frame_length, sample_rate_, true)
358 : packet_buffer_.NumPacketsInBuffer() * decoder_frame_length;
359 // Target level is in number of packets in Q8.
360 const size_t target_level_samples =
361 (delay_manager_->TargetLevel() * packet_length_samples_) >> 8;
362 const bool generated_enough_noise =
363 static_cast<uint32_t>(generated_noise_samples + target_timestamp) >=
364 available_timestamp;
365
366 if (time_stretch_cn_) {
367 const size_t target_threshold_samples =
368 target_level_window_ms_ / 2 * (sample_rate_ / 1000);
369 const bool above_target_window =
370 cur_size_samples > target_level_samples + target_threshold_samples;
371 const bool below_target_window =
372 target_level_samples > target_threshold_samples &&
373 cur_size_samples < target_level_samples - target_threshold_samples;
374 // Keep the delay same as before CNG, but make sure that it is within the
375 // target window.
376 if ((generated_enough_noise && !below_target_window) ||
377 above_target_window) {
378 time_stretched_cn_samples_ = timestamp_leap - generated_noise_samples;
379 return kNormal;
380 }
Henrik Lundin7687ad52018-07-02 10:14:46 +0200381 } else {
Jakob Ivarsson46dda832019-07-03 16:00:30 +0200382 // Keep the same delay as before the CNG, but make sure that the number of
383 // samples in buffer is no higher than 4 times the optimal level.
384 if (generated_enough_noise ||
385 cur_size_samples > target_level_samples * 4) {
386 // Time to play this new packet.
387 return kNormal;
Henrik Lundin7687ad52018-07-02 10:14:46 +0200388 }
389 }
Jakob Ivarsson46dda832019-07-03 16:00:30 +0200390
391 // Too early to play this new packet; keep on playing comfort noise.
392 if (prev_mode == kModeRfc3389Cng) {
393 return kRfc3389CngNoPacket;
394 }
395 // prevPlayMode == kModeCodecInternalCng.
396 return kCodecInternalCng;
Henrik Lundin7687ad52018-07-02 10:14:46 +0200397 }
Jakob Ivarsson46dda832019-07-03 16:00:30 +0200398
Henrik Lundin7687ad52018-07-02 10:14:46 +0200399 // Do not merge unless we have done an expand before.
400 if (prev_mode == kModeExpand) {
401 return kMerge;
402 } else if (play_dtmf) {
403 // Play DTMF instead of expand.
404 return kDtmf;
405 } else {
406 return kExpand;
407 }
408}
409
410bool DecisionLogic::UnderTargetLevel() const {
Jakob Ivarssona36c5912019-06-27 10:12:02 +0200411 int buffer_level_packets = 0;
412 if (packet_length_samples_ > 0) {
413 buffer_level_packets =
414 ((1 << 8) * buffer_level_filter_->filtered_current_level()) /
415 packet_length_samples_;
416 }
417 return buffer_level_packets <= delay_manager_->TargetLevel();
Henrik Lundin7687ad52018-07-02 10:14:46 +0200418}
419
420bool DecisionLogic::ReinitAfterExpands(uint32_t timestamp_leap) const {
421 return timestamp_leap >=
422 static_cast<uint32_t>(output_size_samples_ * kReinitAfterExpands);
423}
424
425bool DecisionLogic::PacketTooEarly(uint32_t timestamp_leap) const {
426 return timestamp_leap >
427 static_cast<uint32_t>(output_size_samples_ * num_consecutive_expands_);
428}
429
430bool DecisionLogic::MaxWaitForPacket() const {
431 return num_consecutive_expands_ >= kMaxWaitForPacket;
432}
433
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000434} // namespace webrtc