blob: a4de9b8bb42242fc1ff3d9f5fe067b5818736ef5 [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;
Jakob Ivarsson80fb9782020-10-09 13:41:06 +020030constexpr int kDecelerationTargetLevelOffsetMs = 85;
Minyue Li7f6417f2018-10-03 21:19:08 +020031
32} // namespace
33
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000034namespace webrtc {
35
Ivo Creusen53a31f72019-10-24 15:20:39 +020036DecisionLogic::DecisionLogic(NetEqController::Config config)
Jakob Ivarssonbd5874a2020-01-07 17:07:40 +010037 : delay_manager_(DelayManager::Create(config.max_packets_in_buffer,
Ivo Creusen53a31f72019-10-24 15:20:39 +020038 config.base_min_delay_ms,
Ivo Creusen53a31f72019-10-24 15:20:39 +020039 config.tick_timer)),
40 tick_timer_(config.tick_timer),
41 disallow_time_stretching_(!config.allow_time_stretching),
Henrik Lundin47b17dc2016-05-10 10:20:59 +020042 timescale_countdown_(
43 tick_timer_->GetNewCountdown(kMinTimescaleInterval + 1)),
Jakob Ivarsson46dda832019-07-03 16:00:30 +020044 estimate_dtx_delay_("estimate_dtx_delay", false),
45 time_stretch_cn_("time_stretch_cn", false),
46 target_level_window_ms_("target_level_window",
47 kDefaultTargetLevelWindowMs,
48 0,
49 absl::nullopt) {
Jakob Ivarsson46dda832019-07-03 16:00:30 +020050 const std::string field_trial_name =
51 field_trial::FindFullName("WebRTC-Audio-NetEqDecisionLogicSettings");
52 ParseFieldTrial(
53 {&estimate_dtx_delay_, &time_stretch_cn_, &target_level_window_ms_},
54 field_trial_name);
55 RTC_LOG(LS_INFO) << "NetEq decision logic settings:"
Jonas Olssonb2b20312020-01-14 12:11:31 +010056 " estimate_dtx_delay="
57 << estimate_dtx_delay_
Jakob Ivarsson46dda832019-07-03 16:00:30 +020058 << " time_stretch_cn=" << time_stretch_cn_
59 << " target_level_window_ms=" << target_level_window_ms_;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000060}
61
Henrik Lundin47b17dc2016-05-10 10:20:59 +020062DecisionLogic::~DecisionLogic() = default;
63
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000064void DecisionLogic::Reset() {
65 cng_state_ = kCngOff;
henrik.lundinb1fb72b2016-05-03 08:18:47 -070066 noise_fast_forward_ = 0;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000067 packet_length_samples_ = 0;
68 sample_memory_ = 0;
69 prev_time_scale_ = false;
Jakob Ivarsson80fb9782020-10-09 13:41:06 +020070 last_pack_cng_or_dtmf_ = true;
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;
Jakob Ivarsson80fb9782020-10-09 13:41:06 +020080 last_pack_cng_or_dtmf_ = true;
Henrik Lundin47b17dc2016-05-10 10:20:59 +020081 timescale_countdown_ =
82 tick_timer_->GetNewCountdown(kMinTimescaleInterval + 1);
Jakob Ivarsson46dda832019-07-03 16:00:30 +020083 time_stretched_cn_samples_ = 0;
Ivo Creusen53a31f72019-10-24 15:20:39 +020084 delay_manager_->Reset();
85 buffer_level_filter_.Reset();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000086}
87
Peter Kastingdce40cf2015-08-24 14:52:23 -070088void DecisionLogic::SetSampleRate(int fs_hz, size_t output_size_samples) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000089 // TODO(hlundin): Change to an enumerator and skip assert.
Yves Gerey665174f2018-06-19 15:03:05 +020090 assert(fs_hz == 8000 || fs_hz == 16000 || fs_hz == 32000 || fs_hz == 48000);
Jakob Ivarsson46dda832019-07-03 16:00:30 +020091 sample_rate_ = fs_hz;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000092 output_size_samples_ = output_size_samples;
93}
94
Ivo Creusen3ce44a32019-10-31 14:38:11 +010095NetEq::Operation DecisionLogic::GetDecision(const NetEqStatus& status,
96 bool* reset_decoder) {
ossu61a208b2016-09-20 01:38:00 -070097 // If last mode was CNG (or Expand, since this could be covering up for
98 // a lost CNG packet), remember that CNG is on. This is needed if comfort
99 // noise is interrupted by DTMF.
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100100 if (status.last_mode == NetEq::Mode::kRfc3389Cng) {
ossu61a208b2016-09-20 01:38:00 -0700101 cng_state_ = kCngRfc3389On;
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100102 } else if (status.last_mode == NetEq::Mode::kCodecInternalCng) {
ossu61a208b2016-09-20 01:38:00 -0700103 cng_state_ = kCngInternalOn;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000104 }
105
Ivo Creusen53a31f72019-10-24 15:20:39 +0200106 size_t cur_size_samples = estimate_dtx_delay_
107 ? status.packet_buffer_info.span_samples
108 : status.packet_buffer_info.num_samples;
Yves Gerey665174f2018-06-19 15:03:05 +0200109 prev_time_scale_ =
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100110 prev_time_scale_ &&
111 (status.last_mode == NetEq::Mode::kAccelerateSuccess ||
112 status.last_mode == NetEq::Mode::kAccelerateLowEnergy ||
113 status.last_mode == NetEq::Mode::kPreemptiveExpandSuccess ||
114 status.last_mode == NetEq::Mode::kPreemptiveExpandLowEnergy);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000115
Minyue Li7d204d52019-04-16 11:44:49 +0200116 // Do not update buffer history if currently playing CNG since it will bias
117 // the filtered buffer level.
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100118 if (status.last_mode != NetEq::Mode::kRfc3389Cng &&
119 status.last_mode != NetEq::Mode::kCodecInternalCng &&
Ivo Creusen53a31f72019-10-24 15:20:39 +0200120 !(status.next_packet && status.next_packet->is_dtx &&
121 !estimate_dtx_delay_)) {
Minyue Li7d204d52019-04-16 11:44:49 +0200122 FilterBufferLevel(cur_size_samples);
123 }
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000124
Henrik Lundin7687ad52018-07-02 10:14:46 +0200125 // Guard for errors, to avoid getting stuck in error mode.
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100126 if (status.last_mode == NetEq::Mode::kError) {
Ivo Creusen53a31f72019-10-24 15:20:39 +0200127 if (!status.next_packet) {
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100128 return NetEq::Operation::kExpand;
Henrik Lundin7687ad52018-07-02 10:14:46 +0200129 } else {
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100130 // Use kUndefined to flag for a reset.
131 return NetEq::Operation::kUndefined;
Henrik Lundin7687ad52018-07-02 10:14:46 +0200132 }
133 }
134
Ivo Creusen53a31f72019-10-24 15:20:39 +0200135 if (status.next_packet && status.next_packet->is_cng) {
136 return CngOperation(status.last_mode, status.target_timestamp,
137 status.next_packet->timestamp,
138 status.generated_noise_samples);
Henrik Lundin7687ad52018-07-02 10:14:46 +0200139 }
140
141 // Handle the case with no packet at all available (except maybe DTMF).
Ivo Creusen53a31f72019-10-24 15:20:39 +0200142 if (!status.next_packet) {
143 return NoPacket(status.play_dtmf);
Henrik Lundin7687ad52018-07-02 10:14:46 +0200144 }
145
146 // If the expand period was very long, reset NetEQ since it is likely that the
147 // sender was restarted.
148 if (num_consecutive_expands_ > kReinitAfterExpands) {
149 *reset_decoder = true;
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100150 return NetEq::Operation::kNormal;
Henrik Lundin7687ad52018-07-02 10:14:46 +0200151 }
152
153 // Make sure we don't restart audio too soon after an expansion to avoid
154 // running out of data right away again. We should only wait if there are no
155 // DTX or CNG packets in the buffer (otherwise we should just play out what we
156 // have, since we cannot know the exact duration of DTX or CNG packets), and
157 // if the mute factor is low enough (otherwise the expansion was short enough
158 // to not be noticable).
159 // Note that the MuteFactor is in Q14, so a value of 16384 corresponds to 1.
Ivo Creusen53a31f72019-10-24 15:20:39 +0200160 const size_t current_span =
161 estimate_dtx_delay_ ? status.packet_buffer_info.span_samples
162 : status.packet_buffer_info.span_samples_no_dtx;
Jakob Ivarsson80fb9782020-10-09 13:41:06 +0200163 const int target_level_samples =
164 delay_manager_->TargetDelayMs() * sample_rate_ / 1000;
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100165 if ((status.last_mode == NetEq::Mode::kExpand ||
166 status.last_mode == NetEq::Mode::kCodecPlc) &&
Ivo Creusen53a31f72019-10-24 15:20:39 +0200167 status.expand_mutefactor < 16384 / 2 &&
Jakob Ivarsson80fb9782020-10-09 13:41:06 +0200168 current_span < static_cast<size_t>(target_level_samples *
169 kPostponeDecodingLevel / 100) &&
Ivo Creusen53a31f72019-10-24 15:20:39 +0200170 !status.packet_buffer_info.dtx_or_cng) {
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100171 return NetEq::Operation::kExpand;
Henrik Lundin7687ad52018-07-02 10:14:46 +0200172 }
173
Jakob Ivarsson46dda832019-07-03 16:00:30 +0200174 const uint32_t five_seconds_samples = static_cast<uint32_t>(5 * sample_rate_);
Henrik Lundin7687ad52018-07-02 10:14:46 +0200175 // Check if the required packet is available.
Ivo Creusen53a31f72019-10-24 15:20:39 +0200176 if (status.target_timestamp == status.next_packet->timestamp) {
177 return ExpectedPacketAvailable(status.last_mode, status.play_dtmf);
178 } else if (!PacketBuffer::IsObsoleteTimestamp(status.next_packet->timestamp,
179 status.target_timestamp,
180 five_seconds_samples)) {
181 return FuturePacketAvailable(
182 status.last_packet_samples, status.last_mode, status.target_timestamp,
183 status.next_packet->timestamp, status.play_dtmf,
184 status.generated_noise_samples, status.packet_buffer_info.span_samples,
185 status.packet_buffer_info.num_packets);
Henrik Lundin7687ad52018-07-02 10:14:46 +0200186 } else {
187 // This implies that available_timestamp < target_timestamp, which can
188 // happen when a new stream or codec is received. Signal for a reset.
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100189 return NetEq::Operation::kUndefined;
Henrik Lundin7687ad52018-07-02 10:14:46 +0200190 }
191}
192
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100193void DecisionLogic::ExpandDecision(NetEq::Operation operation) {
194 if (operation == NetEq::Operation::kExpand) {
Henrik Lundin5afa61c2018-07-02 14:53:24 +0200195 num_consecutive_expands_++;
196 } else {
197 num_consecutive_expands_ = 0;
198 }
199}
200
Jakob Ivarsson80fb9782020-10-09 13:41:06 +0200201absl::optional<int> DecisionLogic::PacketArrived(bool is_cng_or_dtmf,
Ivo Creusen53a31f72019-10-24 15:20:39 +0200202 size_t packet_length_samples,
203 bool should_update_stats,
204 uint16_t main_sequence_number,
205 uint32_t main_timestamp,
206 int fs_hz) {
Jakob Ivarsson80fb9782020-10-09 13:41:06 +0200207 if (is_cng_or_dtmf) {
208 last_pack_cng_or_dtmf_ = true;
209 return absl::nullopt;
Ivo Creusen53a31f72019-10-24 15:20:39 +0200210 }
Jakob Ivarsson80fb9782020-10-09 13:41:06 +0200211 if (!should_update_stats) {
212 return absl::nullopt;
213 }
214 if (packet_length_samples > 0 && fs_hz > 0 &&
215 packet_length_samples != packet_length_samples_) {
216 packet_length_samples_ = packet_length_samples;
217 delay_manager_->SetPacketAudioLength(packet_length_samples_ * 1000 / fs_hz);
218 }
219 auto relative_delay = delay_manager_->Update(
220 main_timestamp, fs_hz, /*reset=*/last_pack_cng_or_dtmf_);
221 last_pack_cng_or_dtmf_ = false;
Ivo Creusen53a31f72019-10-24 15:20:39 +0200222 return relative_delay;
223}
224
Minyue Li7d204d52019-04-16 11:44:49 +0200225void DecisionLogic::FilterBufferLevel(size_t buffer_size_samples) {
Jakob Ivarsson80fb9782020-10-09 13:41:06 +0200226 buffer_level_filter_.SetTargetBufferLevel(delay_manager_->TargetDelayMs());
Henrik Lundin5afa61c2018-07-02 14:53:24 +0200227
Jakob Ivarsson46dda832019-07-03 16:00:30 +0200228 int time_stretched_samples = time_stretched_cn_samples_;
Minyue Li7d204d52019-04-16 11:44:49 +0200229 if (prev_time_scale_) {
Jakob Ivarsson46dda832019-07-03 16:00:30 +0200230 time_stretched_samples += sample_memory_;
Minyue Li7d204d52019-04-16 11:44:49 +0200231 timescale_countdown_ = tick_timer_->GetNewCountdown(kMinTimescaleInterval);
232 }
233
Ivo Creusen53a31f72019-10-24 15:20:39 +0200234 buffer_level_filter_.Update(buffer_size_samples, time_stretched_samples);
Minyue Li7d204d52019-04-16 11:44:49 +0200235 prev_time_scale_ = false;
Jakob Ivarsson46dda832019-07-03 16:00:30 +0200236 time_stretched_cn_samples_ = 0;
Henrik Lundin5afa61c2018-07-02 14:53:24 +0200237}
238
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100239NetEq::Operation DecisionLogic::CngOperation(NetEq::Mode prev_mode,
240 uint32_t target_timestamp,
241 uint32_t available_timestamp,
242 size_t generated_noise_samples) {
Henrik Lundin7687ad52018-07-02 10:14:46 +0200243 // Signed difference between target and available timestamp.
244 int32_t timestamp_diff = static_cast<int32_t>(
245 static_cast<uint32_t>(generated_noise_samples + target_timestamp) -
246 available_timestamp);
Jakob Ivarsson80fb9782020-10-09 13:41:06 +0200247 int optimal_level_samp =
248 delay_manager_->TargetDelayMs() * sample_rate_ / 1000;
Henrik Lundin7687ad52018-07-02 10:14:46 +0200249 const int64_t excess_waiting_time_samp =
250 -static_cast<int64_t>(timestamp_diff) - optimal_level_samp;
251
252 if (excess_waiting_time_samp > optimal_level_samp / 2) {
253 // The waiting time for this packet will be longer than 1.5
254 // times the wanted buffer delay. Apply fast-forward to cut the
255 // waiting time down to the optimal.
Jakob Ivarsson42b6e2d2019-10-21 11:51:05 +0200256 noise_fast_forward_ = rtc::saturated_cast<size_t>(noise_fast_forward_ +
257 excess_waiting_time_samp);
Henrik Lundin7687ad52018-07-02 10:14:46 +0200258 timestamp_diff =
259 rtc::saturated_cast<int32_t>(timestamp_diff + excess_waiting_time_samp);
260 }
261
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100262 if (timestamp_diff < 0 && prev_mode == NetEq::Mode::kRfc3389Cng) {
Henrik Lundin7687ad52018-07-02 10:14:46 +0200263 // Not time to play this packet yet. Wait another round before using this
264 // packet. Keep on playing CNG from previous CNG parameters.
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100265 return NetEq::Operation::kRfc3389CngNoPacket;
Henrik Lundin7687ad52018-07-02 10:14:46 +0200266 } else {
267 // Otherwise, go for the CNG packet now.
268 noise_fast_forward_ = 0;
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100269 return NetEq::Operation::kRfc3389Cng;
Henrik Lundin7687ad52018-07-02 10:14:46 +0200270 }
271}
272
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100273NetEq::Operation DecisionLogic::NoPacket(bool play_dtmf) {
Henrik Lundin7687ad52018-07-02 10:14:46 +0200274 if (cng_state_ == kCngRfc3389On) {
275 // Keep on playing comfort noise.
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100276 return NetEq::Operation::kRfc3389CngNoPacket;
Henrik Lundin7687ad52018-07-02 10:14:46 +0200277 } else if (cng_state_ == kCngInternalOn) {
278 // Keep on playing codec internal comfort noise.
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100279 return NetEq::Operation::kCodecInternalCng;
Henrik Lundin7687ad52018-07-02 10:14:46 +0200280 } else if (play_dtmf) {
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100281 return NetEq::Operation::kDtmf;
Henrik Lundin7687ad52018-07-02 10:14:46 +0200282 } else {
283 // Nothing to play, do expand.
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100284 return NetEq::Operation::kExpand;
Henrik Lundin7687ad52018-07-02 10:14:46 +0200285 }
286}
287
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100288NetEq::Operation DecisionLogic::ExpectedPacketAvailable(NetEq::Mode prev_mode,
289 bool play_dtmf) {
290 if (!disallow_time_stretching_ && prev_mode != NetEq::Mode::kExpand &&
291 !play_dtmf) {
Jakob Ivarsson80fb9782020-10-09 13:41:06 +0200292 const int samples_per_ms = sample_rate_ / 1000;
293 const int target_level_samples =
294 delay_manager_->TargetDelayMs() * samples_per_ms;
295 const int low_limit =
296 std::max(target_level_samples * 3 / 4,
297 target_level_samples -
298 kDecelerationTargetLevelOffsetMs * samples_per_ms);
299 // |higher_limit| is equal to |target_level|, but should at
300 // least be 20 ms higher than |lower_limit|.
301 const int high_limit =
302 std::max(target_level_samples, low_limit + 20 * samples_per_ms);
303
304 const int buffer_level_samples =
305 buffer_level_filter_.filtered_current_level();
306 if (buffer_level_samples >= high_limit << 2)
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100307 return NetEq::Operation::kFastAccelerate;
Henrik Lundin7687ad52018-07-02 10:14:46 +0200308 if (TimescaleAllowed()) {
Jakob Ivarsson80fb9782020-10-09 13:41:06 +0200309 if (buffer_level_samples >= high_limit)
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100310 return NetEq::Operation::kAccelerate;
Jakob Ivarsson80fb9782020-10-09 13:41:06 +0200311 if (buffer_level_samples < low_limit)
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100312 return NetEq::Operation::kPreemptiveExpand;
Henrik Lundin7687ad52018-07-02 10:14:46 +0200313 }
314 }
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100315 return NetEq::Operation::kNormal;
Henrik Lundin7687ad52018-07-02 10:14:46 +0200316}
317
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100318NetEq::Operation DecisionLogic::FuturePacketAvailable(
Henrik Lundin7687ad52018-07-02 10:14:46 +0200319 size_t decoder_frame_length,
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100320 NetEq::Mode prev_mode,
Henrik Lundin7687ad52018-07-02 10:14:46 +0200321 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;
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100331 if ((prev_mode == NetEq::Mode::kExpand ||
332 prev_mode == NetEq::Mode::kCodecPlc) &&
Henrik Lundin00eb12a2018-09-05 18:14:52 +0200333 !ReinitAfterExpands(timestamp_leap) && !MaxWaitForPacket() &&
334 PacketTooEarly(timestamp_leap) && UnderTargetLevel()) {
Henrik Lundin7687ad52018-07-02 10:14:46 +0200335 if (play_dtmf) {
336 // Still have DTMF to play, so do not do expand.
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100337 return NetEq::Operation::kDtmf;
Henrik Lundin7687ad52018-07-02 10:14:46 +0200338 } else {
339 // Nothing to play.
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100340 return NetEq::Operation::kExpand;
Henrik Lundin7687ad52018-07-02 10:14:46 +0200341 }
342 }
343
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100344 if (prev_mode == NetEq::Mode::kCodecPlc) {
345 return NetEq::Operation::kNormal;
Henrik Lundin00eb12a2018-09-05 18:14:52 +0200346 }
347
Henrik Lundin7687ad52018-07-02 10:14:46 +0200348 // If previous was comfort noise, then no merge is needed.
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100349 if (prev_mode == NetEq::Mode::kRfc3389Cng ||
350 prev_mode == NetEq::Mode::kCodecInternalCng) {
Jakob Ivarsson46dda832019-07-03 16:00:30 +0200351 size_t cur_size_samples =
352 estimate_dtx_delay_
Jakob Ivarsson80fb9782020-10-09 13:41:06 +0200353 ? span_samples_in_packet_buffer
Ivo Creusen53a31f72019-10-24 15:20:39 +0200354 : num_packets_in_packet_buffer * decoder_frame_length;
Jakob Ivarsson46dda832019-07-03 16:00:30 +0200355 // Target level is in number of packets in Q8.
356 const size_t target_level_samples =
Jakob Ivarsson80fb9782020-10-09 13:41:06 +0200357 delay_manager_->TargetDelayMs() * sample_rate_ / 1000;
Jakob Ivarsson46dda832019-07-03 16:00:30 +0200358 const bool generated_enough_noise =
359 static_cast<uint32_t>(generated_noise_samples + target_timestamp) >=
360 available_timestamp;
361
362 if (time_stretch_cn_) {
363 const size_t target_threshold_samples =
364 target_level_window_ms_ / 2 * (sample_rate_ / 1000);
365 const bool above_target_window =
366 cur_size_samples > target_level_samples + target_threshold_samples;
367 const bool below_target_window =
368 target_level_samples > target_threshold_samples &&
369 cur_size_samples < target_level_samples - target_threshold_samples;
370 // Keep the delay same as before CNG, but make sure that it is within the
371 // target window.
372 if ((generated_enough_noise && !below_target_window) ||
373 above_target_window) {
374 time_stretched_cn_samples_ = timestamp_leap - generated_noise_samples;
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100375 return NetEq::Operation::kNormal;
Jakob Ivarsson46dda832019-07-03 16:00:30 +0200376 }
Henrik Lundin7687ad52018-07-02 10:14:46 +0200377 } else {
Jakob Ivarsson46dda832019-07-03 16:00:30 +0200378 // Keep the same delay as before the CNG, but make sure that the number of
379 // samples in buffer is no higher than 4 times the optimal level.
380 if (generated_enough_noise ||
381 cur_size_samples > target_level_samples * 4) {
382 // Time to play this new packet.
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100383 return NetEq::Operation::kNormal;
Henrik Lundin7687ad52018-07-02 10:14:46 +0200384 }
385 }
Jakob Ivarsson46dda832019-07-03 16:00:30 +0200386
387 // Too early to play this new packet; keep on playing comfort noise.
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100388 if (prev_mode == NetEq::Mode::kRfc3389Cng) {
389 return NetEq::Operation::kRfc3389CngNoPacket;
Jakob Ivarsson46dda832019-07-03 16:00:30 +0200390 }
391 // prevPlayMode == kModeCodecInternalCng.
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100392 return NetEq::Operation::kCodecInternalCng;
Henrik Lundin7687ad52018-07-02 10:14:46 +0200393 }
Jakob Ivarsson46dda832019-07-03 16:00:30 +0200394
Henrik Lundin7687ad52018-07-02 10:14:46 +0200395 // Do not merge unless we have done an expand before.
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100396 if (prev_mode == NetEq::Mode::kExpand) {
397 return NetEq::Operation::kMerge;
Henrik Lundin7687ad52018-07-02 10:14:46 +0200398 } else if (play_dtmf) {
399 // Play DTMF instead of expand.
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100400 return NetEq::Operation::kDtmf;
Henrik Lundin7687ad52018-07-02 10:14:46 +0200401 } else {
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100402 return NetEq::Operation::kExpand;
Henrik Lundin7687ad52018-07-02 10:14:46 +0200403 }
404}
405
406bool DecisionLogic::UnderTargetLevel() const {
Jakob Ivarsson80fb9782020-10-09 13:41:06 +0200407 return buffer_level_filter_.filtered_current_level() <
408 delay_manager_->TargetDelayMs() * sample_rate_ / 1000;
Henrik Lundin7687ad52018-07-02 10:14:46 +0200409}
410
411bool DecisionLogic::ReinitAfterExpands(uint32_t timestamp_leap) const {
412 return timestamp_leap >=
413 static_cast<uint32_t>(output_size_samples_ * kReinitAfterExpands);
414}
415
416bool DecisionLogic::PacketTooEarly(uint32_t timestamp_leap) const {
417 return timestamp_leap >
418 static_cast<uint32_t>(output_size_samples_ * num_consecutive_expands_);
419}
420
421bool DecisionLogic::MaxWaitForPacket() const {
422 return num_consecutive_expands_ >= kMaxWaitForPacket;
423}
424
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000425} // namespace webrtc