blob: fc255e54a90687659ee963eeeb4de31c4e9e83e2 [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>
15#include <string>
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000016
Jakob Ivarsson46dda832019-07-03 16:00:30 +020017#include "absl/types/optional.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020018#include "modules/audio_coding/neteq/buffer_level_filter.h"
Henrik Lundin7687ad52018-07-02 10:14:46 +020019#include "modules/audio_coding/neteq/decoder_database.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020020#include "modules/audio_coding/neteq/delay_manager.h"
21#include "modules/audio_coding/neteq/expand.h"
22#include "modules/audio_coding/neteq/packet_buffer.h"
23#include "modules/audio_coding/neteq/sync_buffer.h"
Yves Gerey988cc082018-10-23 12:03:01 +020024#include "rtc_base/checks.h"
Jakob Ivarsson46dda832019-07-03 16:00:30 +020025#include "rtc_base/experiments/field_trial_parser.h"
Minyue Li7f6417f2018-10-03 21:19:08 +020026#include "rtc_base/logging.h"
Yves Gerey988cc082018-10-23 12:03:01 +020027#include "rtc_base/numerics/safe_conversions.h"
Jakob Ivarsson46dda832019-07-03 16:00:30 +020028#include "system_wrappers/include/field_trial.h"
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000029
Minyue Li7f6417f2018-10-03 21:19:08 +020030namespace {
Minyue Li7f6417f2018-10-03 21:19:08 +020031
Jakob Ivarssond3a780b2019-02-28 14:30:21 +010032constexpr int kPostponeDecodingLevel = 50;
Jakob Ivarsson46dda832019-07-03 16:00:30 +020033constexpr int kDefaultTargetLevelWindowMs = 100;
Minyue Li7f6417f2018-10-03 21:19:08 +020034
35} // namespace
36
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000037namespace webrtc {
38
39DecisionLogic* DecisionLogic::Create(int fs_hz,
Peter Kastingdce40cf2015-08-24 14:52:23 -070040 size_t output_size_samples,
Henrik Lundin7687ad52018-07-02 10:14:46 +020041 bool disallow_time_stretching,
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000042 DecoderDatabase* decoder_database,
43 const PacketBuffer& packet_buffer,
44 DelayManager* delay_manager,
Henrik Lundin47b17dc2016-05-10 10:20:59 +020045 BufferLevelFilter* buffer_level_filter,
46 const TickTimer* tick_timer) {
Henrik Lundin7687ad52018-07-02 10:14:46 +020047 return new DecisionLogic(fs_hz, output_size_samples, disallow_time_stretching,
48 decoder_database, packet_buffer, delay_manager,
49 buffer_level_filter, tick_timer);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000050}
51
52DecisionLogic::DecisionLogic(int fs_hz,
Peter Kastingdce40cf2015-08-24 14:52:23 -070053 size_t output_size_samples,
Henrik Lundin7687ad52018-07-02 10:14:46 +020054 bool disallow_time_stretching,
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000055 DecoderDatabase* decoder_database,
56 const PacketBuffer& packet_buffer,
57 DelayManager* delay_manager,
Henrik Lundin47b17dc2016-05-10 10:20:59 +020058 BufferLevelFilter* buffer_level_filter,
59 const TickTimer* tick_timer)
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000060 : decoder_database_(decoder_database),
61 packet_buffer_(packet_buffer),
62 delay_manager_(delay_manager),
63 buffer_level_filter_(buffer_level_filter),
Henrik Lundin47b17dc2016-05-10 10:20:59 +020064 tick_timer_(tick_timer),
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000065 cng_state_(kCngOff),
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000066 packet_length_samples_(0),
67 sample_memory_(0),
68 prev_time_scale_(false),
Henrik Lundin7687ad52018-07-02 10:14:46 +020069 disallow_time_stretching_(disallow_time_stretching),
Henrik Lundin47b17dc2016-05-10 10:20:59 +020070 timescale_countdown_(
71 tick_timer_->GetNewCountdown(kMinTimescaleInterval + 1)),
Jakob Ivarsson46dda832019-07-03 16:00:30 +020072 num_consecutive_expands_(0),
73 time_stretched_cn_samples_(0),
74 estimate_dtx_delay_("estimate_dtx_delay", false),
75 time_stretch_cn_("time_stretch_cn", false),
76 target_level_window_ms_("target_level_window",
77 kDefaultTargetLevelWindowMs,
78 0,
79 absl::nullopt) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000080 SetSampleRate(fs_hz, output_size_samples);
Jakob Ivarsson46dda832019-07-03 16:00:30 +020081 const std::string field_trial_name =
82 field_trial::FindFullName("WebRTC-Audio-NetEqDecisionLogicSettings");
83 ParseFieldTrial(
84 {&estimate_dtx_delay_, &time_stretch_cn_, &target_level_window_ms_},
85 field_trial_name);
86 RTC_LOG(LS_INFO) << "NetEq decision logic settings:"
87 << " estimate_dtx_delay=" << estimate_dtx_delay_
88 << " time_stretch_cn=" << time_stretch_cn_
89 << " target_level_window_ms=" << target_level_window_ms_;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000090}
91
Henrik Lundin47b17dc2016-05-10 10:20:59 +020092DecisionLogic::~DecisionLogic() = default;
93
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000094void DecisionLogic::Reset() {
95 cng_state_ = kCngOff;
henrik.lundinb1fb72b2016-05-03 08:18:47 -070096 noise_fast_forward_ = 0;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000097 packet_length_samples_ = 0;
98 sample_memory_ = 0;
99 prev_time_scale_ = false;
Henrik Lundin47b17dc2016-05-10 10:20:59 +0200100 timescale_countdown_.reset();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000101 num_consecutive_expands_ = 0;
Jakob Ivarsson46dda832019-07-03 16:00:30 +0200102 time_stretched_cn_samples_ = 0;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000103}
104
105void DecisionLogic::SoftReset() {
106 packet_length_samples_ = 0;
107 sample_memory_ = 0;
108 prev_time_scale_ = false;
Henrik Lundin47b17dc2016-05-10 10:20:59 +0200109 timescale_countdown_ =
110 tick_timer_->GetNewCountdown(kMinTimescaleInterval + 1);
Jakob Ivarsson46dda832019-07-03 16:00:30 +0200111 time_stretched_cn_samples_ = 0;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000112}
113
Peter Kastingdce40cf2015-08-24 14:52:23 -0700114void DecisionLogic::SetSampleRate(int fs_hz, size_t output_size_samples) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000115 // TODO(hlundin): Change to an enumerator and skip assert.
Yves Gerey665174f2018-06-19 15:03:05 +0200116 assert(fs_hz == 8000 || fs_hz == 16000 || fs_hz == 32000 || fs_hz == 48000);
Jakob Ivarsson46dda832019-07-03 16:00:30 +0200117 sample_rate_ = fs_hz;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000118 output_size_samples_ = output_size_samples;
119}
120
121Operations DecisionLogic::GetDecision(const SyncBuffer& sync_buffer,
122 const Expand& expand,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700123 size_t decoder_frame_length,
ossu7a377612016-10-18 04:06:13 -0700124 const Packet* next_packet,
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000125 Modes prev_mode,
henrik.lundinb1fb72b2016-05-03 08:18:47 -0700126 bool play_dtmf,
127 size_t generated_noise_samples,
128 bool* reset_decoder) {
ossu61a208b2016-09-20 01:38:00 -0700129 // If last mode was CNG (or Expand, since this could be covering up for
130 // a lost CNG packet), remember that CNG is on. This is needed if comfort
131 // noise is interrupted by DTMF.
132 if (prev_mode == kModeRfc3389Cng) {
133 cng_state_ = kCngRfc3389On;
134 } else if (prev_mode == kModeCodecInternalCng) {
135 cng_state_ = kCngInternalOn;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000136 }
137
Jakob Ivarsson46dda832019-07-03 16:00:30 +0200138 size_t cur_size_samples =
139 estimate_dtx_delay_
140 ? packet_buffer_.GetSpanSamples(decoder_frame_length, sample_rate_,
141 true)
142 : packet_buffer_.NumSamplesInBuffer(decoder_frame_length);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000143
Yves Gerey665174f2018-06-19 15:03:05 +0200144 prev_time_scale_ =
145 prev_time_scale_ && (prev_mode == kModeAccelerateSuccess ||
146 prev_mode == kModeAccelerateLowEnergy ||
147 prev_mode == kModePreemptiveExpandSuccess ||
148 prev_mode == kModePreemptiveExpandLowEnergy);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000149
Minyue Li7d204d52019-04-16 11:44:49 +0200150 // Do not update buffer history if currently playing CNG since it will bias
151 // the filtered buffer level.
Jakob Ivarsson46dda832019-07-03 16:00:30 +0200152 if (prev_mode != kModeRfc3389Cng && prev_mode != kModeCodecInternalCng &&
Minyue Li7d204d52019-04-16 11:44:49 +0200153 !(next_packet && next_packet->frame &&
Jakob Ivarsson46dda832019-07-03 16:00:30 +0200154 next_packet->frame->IsDtxPacket() && !estimate_dtx_delay_)) {
Minyue Li7d204d52019-04-16 11:44:49 +0200155 FilterBufferLevel(cur_size_samples);
156 }
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000157
Henrik Lundin7687ad52018-07-02 10:14:46 +0200158 // Guard for errors, to avoid getting stuck in error mode.
159 if (prev_mode == kModeError) {
160 if (!next_packet) {
161 return kExpand;
162 } else {
163 return kUndefined; // Use kUndefined to flag for a reset.
164 }
165 }
166
167 uint32_t target_timestamp = sync_buffer.end_timestamp();
168 uint32_t available_timestamp = 0;
169 bool is_cng_packet = false;
170 if (next_packet) {
171 available_timestamp = next_packet->timestamp;
172 is_cng_packet =
173 decoder_database_->IsComfortNoise(next_packet->payload_type);
174 }
175
176 if (is_cng_packet) {
177 return CngOperation(prev_mode, target_timestamp, available_timestamp,
178 generated_noise_samples);
179 }
180
181 // Handle the case with no packet at all available (except maybe DTMF).
182 if (!next_packet) {
183 return NoPacket(play_dtmf);
184 }
185
186 // If the expand period was very long, reset NetEQ since it is likely that the
187 // sender was restarted.
188 if (num_consecutive_expands_ > kReinitAfterExpands) {
189 *reset_decoder = true;
190 return kNormal;
191 }
192
193 // Make sure we don't restart audio too soon after an expansion to avoid
194 // running out of data right away again. We should only wait if there are no
195 // DTX or CNG packets in the buffer (otherwise we should just play out what we
196 // have, since we cannot know the exact duration of DTX or CNG packets), and
197 // if the mute factor is low enough (otherwise the expansion was short enough
198 // to not be noticable).
199 // Note that the MuteFactor is in Q14, so a value of 16384 corresponds to 1.
Jakob Ivarsson46dda832019-07-03 16:00:30 +0200200 size_t current_span = packet_buffer_.GetSpanSamples(
201 decoder_frame_length, sample_rate_, estimate_dtx_delay_);
Minyue Li7f6417f2018-10-03 21:19:08 +0200202 if ((prev_mode == kModeExpand || prev_mode == kModeCodecPlc) &&
203 expand.MuteFactor(0) < 16384 / 2 &&
Jakob Ivarsson1b4254a2019-03-12 15:12:08 +0100204 current_span < static_cast<size_t>(delay_manager_->TargetLevel() *
205 packet_length_samples_ *
206 kPostponeDecodingLevel / 100)>> 8 &&
Minyue Li7f6417f2018-10-03 21:19:08 +0200207 !packet_buffer_.ContainsDtxOrCngPacket(decoder_database_)) {
Henrik Lundin7687ad52018-07-02 10:14:46 +0200208 return kExpand;
209 }
210
Jakob Ivarsson46dda832019-07-03 16:00:30 +0200211 const uint32_t five_seconds_samples = static_cast<uint32_t>(5 * sample_rate_);
Henrik Lundin7687ad52018-07-02 10:14:46 +0200212 // Check if the required packet is available.
213 if (target_timestamp == available_timestamp) {
214 return ExpectedPacketAvailable(prev_mode, play_dtmf);
215 } else if (!PacketBuffer::IsObsoleteTimestamp(
216 available_timestamp, target_timestamp, five_seconds_samples)) {
Jakob Ivarssona36c5912019-06-27 10:12:02 +0200217 return FuturePacketAvailable(decoder_frame_length, prev_mode,
218 target_timestamp, available_timestamp,
219 play_dtmf, generated_noise_samples);
Henrik Lundin7687ad52018-07-02 10:14:46 +0200220 } else {
221 // This implies that available_timestamp < target_timestamp, which can
222 // happen when a new stream or codec is received. Signal for a reset.
223 return kUndefined;
224 }
225}
226
Henrik Lundin5afa61c2018-07-02 14:53:24 +0200227void DecisionLogic::ExpandDecision(Operations operation) {
228 if (operation == kExpand) {
229 num_consecutive_expands_++;
230 } else {
231 num_consecutive_expands_ = 0;
232 }
233}
234
Minyue Li7d204d52019-04-16 11:44:49 +0200235void DecisionLogic::FilterBufferLevel(size_t buffer_size_samples) {
236 buffer_level_filter_->SetTargetBufferLevel(
237 delay_manager_->base_target_level());
Henrik Lundin5afa61c2018-07-02 14:53:24 +0200238
Jakob Ivarsson46dda832019-07-03 16:00:30 +0200239 int time_stretched_samples = time_stretched_cn_samples_;
Minyue Li7d204d52019-04-16 11:44:49 +0200240 if (prev_time_scale_) {
Jakob Ivarsson46dda832019-07-03 16:00:30 +0200241 time_stretched_samples += sample_memory_;
Minyue Li7d204d52019-04-16 11:44:49 +0200242 timescale_countdown_ = tick_timer_->GetNewCountdown(kMinTimescaleInterval);
243 }
244
Jakob Ivarsson46dda832019-07-03 16:00:30 +0200245 buffer_level_filter_->Update(buffer_size_samples, time_stretched_samples);
Minyue Li7d204d52019-04-16 11:44:49 +0200246 prev_time_scale_ = false;
Jakob Ivarsson46dda832019-07-03 16:00:30 +0200247 time_stretched_cn_samples_ = 0;
Henrik Lundin5afa61c2018-07-02 14:53:24 +0200248}
249
Henrik Lundin7687ad52018-07-02 10:14:46 +0200250Operations DecisionLogic::CngOperation(Modes prev_mode,
251 uint32_t target_timestamp,
252 uint32_t available_timestamp,
253 size_t generated_noise_samples) {
254 // Signed difference between target and available timestamp.
255 int32_t timestamp_diff = static_cast<int32_t>(
256 static_cast<uint32_t>(generated_noise_samples + target_timestamp) -
257 available_timestamp);
258 int32_t optimal_level_samp = static_cast<int32_t>(
259 (delay_manager_->TargetLevel() * packet_length_samples_) >> 8);
260 const int64_t excess_waiting_time_samp =
261 -static_cast<int64_t>(timestamp_diff) - optimal_level_samp;
262
263 if (excess_waiting_time_samp > optimal_level_samp / 2) {
264 // The waiting time for this packet will be longer than 1.5
265 // times the wanted buffer delay. Apply fast-forward to cut the
266 // waiting time down to the optimal.
267 noise_fast_forward_ = rtc::dchecked_cast<size_t>(noise_fast_forward_ +
268 excess_waiting_time_samp);
269 timestamp_diff =
270 rtc::saturated_cast<int32_t>(timestamp_diff + excess_waiting_time_samp);
271 }
272
273 if (timestamp_diff < 0 && prev_mode == kModeRfc3389Cng) {
274 // Not time to play this packet yet. Wait another round before using this
275 // packet. Keep on playing CNG from previous CNG parameters.
276 return kRfc3389CngNoPacket;
277 } else {
278 // Otherwise, go for the CNG packet now.
279 noise_fast_forward_ = 0;
280 return kRfc3389Cng;
281 }
282}
283
284Operations DecisionLogic::NoPacket(bool play_dtmf) {
285 if (cng_state_ == kCngRfc3389On) {
286 // Keep on playing comfort noise.
287 return kRfc3389CngNoPacket;
288 } else if (cng_state_ == kCngInternalOn) {
289 // Keep on playing codec internal comfort noise.
290 return kCodecInternalCng;
291 } else if (play_dtmf) {
292 return kDtmf;
293 } else {
294 // Nothing to play, do expand.
295 return kExpand;
296 }
297}
298
299Operations DecisionLogic::ExpectedPacketAvailable(Modes prev_mode,
300 bool play_dtmf) {
301 if (!disallow_time_stretching_ && prev_mode != kModeExpand && !play_dtmf) {
Jakob Ivarssona36c5912019-06-27 10:12:02 +0200302 // Check criterion for time-stretching. The values are in number of packets
303 // in Q8.
Henrik Lundin7687ad52018-07-02 10:14:46 +0200304 int low_limit, high_limit;
305 delay_manager_->BufferLimits(&low_limit, &high_limit);
Jakob Ivarssona36c5912019-06-27 10:12:02 +0200306 int buffer_level_packets = 0;
307 if (packet_length_samples_ > 0) {
308 buffer_level_packets =
309 ((1 << 8) * buffer_level_filter_->filtered_current_level()) /
310 packet_length_samples_;
311 }
312 if (buffer_level_packets >= high_limit << 2)
Henrik Lundin7687ad52018-07-02 10:14:46 +0200313 return kFastAccelerate;
314 if (TimescaleAllowed()) {
Jakob Ivarssona36c5912019-06-27 10:12:02 +0200315 if (buffer_level_packets >= high_limit)
Henrik Lundin7687ad52018-07-02 10:14:46 +0200316 return kAccelerate;
Jakob Ivarssona36c5912019-06-27 10:12:02 +0200317 if (buffer_level_packets < low_limit)
Henrik Lundin7687ad52018-07-02 10:14:46 +0200318 return kPreemptiveExpand;
319 }
320 }
321 return kNormal;
322}
323
324Operations DecisionLogic::FuturePacketAvailable(
Henrik Lundin7687ad52018-07-02 10:14:46 +0200325 size_t decoder_frame_length,
326 Modes prev_mode,
327 uint32_t target_timestamp,
328 uint32_t available_timestamp,
329 bool play_dtmf,
330 size_t generated_noise_samples) {
331 // Required packet is not available, but a future packet is.
332 // Check if we should continue with an ongoing expand because the new packet
333 // is too far into the future.
334 uint32_t timestamp_leap = available_timestamp - target_timestamp;
Henrik Lundin00eb12a2018-09-05 18:14:52 +0200335 if ((prev_mode == kModeExpand || prev_mode == kModeCodecPlc) &&
336 !ReinitAfterExpands(timestamp_leap) && !MaxWaitForPacket() &&
337 PacketTooEarly(timestamp_leap) && UnderTargetLevel()) {
Henrik Lundin7687ad52018-07-02 10:14:46 +0200338 if (play_dtmf) {
339 // Still have DTMF to play, so do not do expand.
340 return kDtmf;
341 } else {
342 // Nothing to play.
343 return kExpand;
344 }
345 }
346
Henrik Lundin00eb12a2018-09-05 18:14:52 +0200347 if (prev_mode == kModeCodecPlc) {
348 return kNormal;
349 }
350
Henrik Lundin7687ad52018-07-02 10:14:46 +0200351 // If previous was comfort noise, then no merge is needed.
352 if (prev_mode == kModeRfc3389Cng || prev_mode == kModeCodecInternalCng) {
Jakob Ivarsson46dda832019-07-03 16:00:30 +0200353 size_t cur_size_samples =
354 estimate_dtx_delay_
355 ? cur_size_samples = packet_buffer_.GetSpanSamples(
356 decoder_frame_length, sample_rate_, true)
357 : packet_buffer_.NumPacketsInBuffer() * decoder_frame_length;
358 // Target level is in number of packets in Q8.
359 const size_t target_level_samples =
360 (delay_manager_->TargetLevel() * packet_length_samples_) >> 8;
361 const bool generated_enough_noise =
362 static_cast<uint32_t>(generated_noise_samples + target_timestamp) >=
363 available_timestamp;
364
365 if (time_stretch_cn_) {
366 const size_t target_threshold_samples =
367 target_level_window_ms_ / 2 * (sample_rate_ / 1000);
368 const bool above_target_window =
369 cur_size_samples > target_level_samples + target_threshold_samples;
370 const bool below_target_window =
371 target_level_samples > target_threshold_samples &&
372 cur_size_samples < target_level_samples - target_threshold_samples;
373 // Keep the delay same as before CNG, but make sure that it is within the
374 // target window.
375 if ((generated_enough_noise && !below_target_window) ||
376 above_target_window) {
377 time_stretched_cn_samples_ = timestamp_leap - generated_noise_samples;
378 return kNormal;
379 }
Henrik Lundin7687ad52018-07-02 10:14:46 +0200380 } else {
Jakob Ivarsson46dda832019-07-03 16:00:30 +0200381 // Keep the same delay as before the CNG, but make sure that the number of
382 // samples in buffer is no higher than 4 times the optimal level.
383 if (generated_enough_noise ||
384 cur_size_samples > target_level_samples * 4) {
385 // Time to play this new packet.
386 return kNormal;
Henrik Lundin7687ad52018-07-02 10:14:46 +0200387 }
388 }
Jakob Ivarsson46dda832019-07-03 16:00:30 +0200389
390 // Too early to play this new packet; keep on playing comfort noise.
391 if (prev_mode == kModeRfc3389Cng) {
392 return kRfc3389CngNoPacket;
393 }
394 // prevPlayMode == kModeCodecInternalCng.
395 return kCodecInternalCng;
Henrik Lundin7687ad52018-07-02 10:14:46 +0200396 }
Jakob Ivarsson46dda832019-07-03 16:00:30 +0200397
Henrik Lundin7687ad52018-07-02 10:14:46 +0200398 // Do not merge unless we have done an expand before.
399 if (prev_mode == kModeExpand) {
400 return kMerge;
401 } else if (play_dtmf) {
402 // Play DTMF instead of expand.
403 return kDtmf;
404 } else {
405 return kExpand;
406 }
407}
408
409bool DecisionLogic::UnderTargetLevel() const {
Jakob Ivarssona36c5912019-06-27 10:12:02 +0200410 int buffer_level_packets = 0;
411 if (packet_length_samples_ > 0) {
412 buffer_level_packets =
413 ((1 << 8) * buffer_level_filter_->filtered_current_level()) /
414 packet_length_samples_;
415 }
416 return buffer_level_packets <= delay_manager_->TargetLevel();
Henrik Lundin7687ad52018-07-02 10:14:46 +0200417}
418
419bool DecisionLogic::ReinitAfterExpands(uint32_t timestamp_leap) const {
420 return timestamp_leap >=
421 static_cast<uint32_t>(output_size_samples_ * kReinitAfterExpands);
422}
423
424bool DecisionLogic::PacketTooEarly(uint32_t timestamp_leap) const {
425 return timestamp_leap >
426 static_cast<uint32_t>(output_size_samples_ * num_consecutive_expands_);
427}
428
429bool DecisionLogic::MaxWaitForPacket() const {
430 return num_consecutive_expands_ >= kMaxWaitForPacket;
431}
432
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000433} // namespace webrtc