blob: f81535c84d284ac0442d3a652f4414be69a7a8b0 [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
Yves Gerey988cc082018-10-23 12:03:01 +020013#include <stdio.h>
Jonas Olssona4d87372019-07-05 19:08:33 +020014
Yves Gerey988cc082018-10-23 12:03:01 +020015#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/packet_buffer.h"
Yves Gerey988cc082018-10-23 12:03:01 +020019#include "rtc_base/checks.h"
Jakob Ivarsson46dda832019-07-03 16:00:30 +020020#include "rtc_base/experiments/field_trial_parser.h"
Minyue Li7f6417f2018-10-03 21:19:08 +020021#include "rtc_base/logging.h"
Yves Gerey988cc082018-10-23 12:03:01 +020022#include "rtc_base/numerics/safe_conversions.h"
Jakob Ivarsson46dda832019-07-03 16:00:30 +020023#include "system_wrappers/include/field_trial.h"
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000024
Jakob Ivarsson74158ff2021-09-07 14:24:56 +020025namespace webrtc {
26
Minyue Li7f6417f2018-10-03 21:19:08 +020027namespace {
Minyue Li7f6417f2018-10-03 21:19:08 +020028
Jakob Ivarssond3a780b2019-02-28 14:30:21 +010029constexpr int kPostponeDecodingLevel = 50;
Jakob Ivarsson46dda832019-07-03 16:00:30 +020030constexpr int kDefaultTargetLevelWindowMs = 100;
Jakob Ivarsson80fb9782020-10-09 13:41:06 +020031constexpr int kDecelerationTargetLevelOffsetMs = 85;
Minyue Li7f6417f2018-10-03 21:19:08 +020032
Jakob Ivarsson74158ff2021-09-07 14:24:56 +020033std::unique_ptr<DelayManager> CreateDelayManager(
34 const NetEqController::Config& neteq_config) {
35 DelayManager::Config config;
36 config.max_packets_in_buffer = neteq_config.max_packets_in_buffer;
37 config.base_minimum_delay_ms = neteq_config.base_min_delay_ms;
38 config.Log();
39 return std::make_unique<DelayManager>(config, neteq_config.tick_timer);
40}
Minyue Li7f6417f2018-10-03 21:19:08 +020041
Jakob Ivarssonca101e62022-04-04 21:42:55 +020042bool IsExpand(NetEq::Mode mode) {
43 return mode == NetEq::Mode::kExpand || mode == NetEq::Mode::kCodecPlc;
44}
45
Jakob Ivarsson74158ff2021-09-07 14:24:56 +020046} // namespace
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000047
Ivo Creusen53a31f72019-10-24 15:20:39 +020048DecisionLogic::DecisionLogic(NetEqController::Config config)
Jakob Ivarsson609b0472020-10-19 09:19:34 +020049 : DecisionLogic(config,
Jakob Ivarsson74158ff2021-09-07 14:24:56 +020050 CreateDelayManager(config),
Jakob Ivarsson609b0472020-10-19 09:19:34 +020051 std::make_unique<BufferLevelFilter>()) {}
52
53DecisionLogic::DecisionLogic(
54 NetEqController::Config config,
55 std::unique_ptr<DelayManager> delay_manager,
56 std::unique_ptr<BufferLevelFilter> buffer_level_filter)
57 : delay_manager_(std::move(delay_manager)),
58 buffer_level_filter_(std::move(buffer_level_filter)),
Ivo Creusen53a31f72019-10-24 15:20:39 +020059 tick_timer_(config.tick_timer),
60 disallow_time_stretching_(!config.allow_time_stretching),
Henrik Lundin47b17dc2016-05-10 10:20:59 +020061 timescale_countdown_(
62 tick_timer_->GetNewCountdown(kMinTimescaleInterval + 1)),
Jakob Ivarsson46dda832019-07-03 16:00:30 +020063 target_level_window_ms_("target_level_window",
64 kDefaultTargetLevelWindowMs,
65 0,
66 absl::nullopt) {
Jakob Ivarsson46dda832019-07-03 16:00:30 +020067 const std::string field_trial_name =
68 field_trial::FindFullName("WebRTC-Audio-NetEqDecisionLogicSettings");
Jakob Ivarssone6aabd02022-03-28 16:06:37 +020069 ParseFieldTrial({&target_level_window_ms_}, field_trial_name);
Jakob Ivarsson46dda832019-07-03 16:00:30 +020070 RTC_LOG(LS_INFO) << "NetEq decision logic settings:"
Jakob Ivarsson46dda832019-07-03 16:00:30 +020071 << " target_level_window_ms=" << target_level_window_ms_;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000072}
73
Henrik Lundin47b17dc2016-05-10 10:20:59 +020074DecisionLogic::~DecisionLogic() = default;
75
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000076void DecisionLogic::Reset() {
77 cng_state_ = kCngOff;
henrik.lundinb1fb72b2016-05-03 08:18:47 -070078 noise_fast_forward_ = 0;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000079 packet_length_samples_ = 0;
80 sample_memory_ = 0;
81 prev_time_scale_ = false;
Jakob Ivarsson80fb9782020-10-09 13:41:06 +020082 last_pack_cng_or_dtmf_ = true;
Henrik Lundin47b17dc2016-05-10 10:20:59 +020083 timescale_countdown_.reset();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000084 num_consecutive_expands_ = 0;
Jakob Ivarsson46dda832019-07-03 16:00:30 +020085 time_stretched_cn_samples_ = 0;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000086}
87
88void DecisionLogic::SoftReset() {
89 packet_length_samples_ = 0;
90 sample_memory_ = 0;
91 prev_time_scale_ = false;
Jakob Ivarsson80fb9782020-10-09 13:41:06 +020092 last_pack_cng_or_dtmf_ = true;
Henrik Lundin47b17dc2016-05-10 10:20:59 +020093 timescale_countdown_ =
94 tick_timer_->GetNewCountdown(kMinTimescaleInterval + 1);
Jakob Ivarsson46dda832019-07-03 16:00:30 +020095 time_stretched_cn_samples_ = 0;
Ivo Creusen53a31f72019-10-24 15:20:39 +020096 delay_manager_->Reset();
Jakob Ivarsson609b0472020-10-19 09:19:34 +020097 buffer_level_filter_->Reset();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000098}
99
Peter Kastingdce40cf2015-08-24 14:52:23 -0700100void DecisionLogic::SetSampleRate(int fs_hz, size_t output_size_samples) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000101 // TODO(hlundin): Change to an enumerator and skip assert.
Mirko Bonadei25ab3222021-07-08 20:08:20 +0200102 RTC_DCHECK(fs_hz == 8000 || fs_hz == 16000 || fs_hz == 32000 ||
103 fs_hz == 48000);
Jakob Ivarsson46dda832019-07-03 16:00:30 +0200104 sample_rate_ = fs_hz;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000105 output_size_samples_ = output_size_samples;
106}
107
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100108NetEq::Operation DecisionLogic::GetDecision(const NetEqStatus& status,
109 bool* reset_decoder) {
ossu61a208b2016-09-20 01:38:00 -0700110 // If last mode was CNG (or Expand, since this could be covering up for
111 // a lost CNG packet), remember that CNG is on. This is needed if comfort
112 // noise is interrupted by DTMF.
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100113 if (status.last_mode == NetEq::Mode::kRfc3389Cng) {
ossu61a208b2016-09-20 01:38:00 -0700114 cng_state_ = kCngRfc3389On;
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100115 } else if (status.last_mode == NetEq::Mode::kCodecInternalCng) {
ossu61a208b2016-09-20 01:38:00 -0700116 cng_state_ = kCngInternalOn;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000117 }
118
Jakob Ivarssonca101e62022-04-04 21:42:55 +0200119 if (IsExpand(status.last_mode)) {
120 ++num_consecutive_expands_;
121 } else {
122 num_consecutive_expands_ = 0;
123 }
124
Yves Gerey665174f2018-06-19 15:03:05 +0200125 prev_time_scale_ =
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100126 prev_time_scale_ &&
127 (status.last_mode == NetEq::Mode::kAccelerateSuccess ||
128 status.last_mode == NetEq::Mode::kAccelerateLowEnergy ||
129 status.last_mode == NetEq::Mode::kPreemptiveExpandSuccess ||
130 status.last_mode == NetEq::Mode::kPreemptiveExpandLowEnergy);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000131
Minyue Li7d204d52019-04-16 11:44:49 +0200132 // Do not update buffer history if currently playing CNG since it will bias
133 // the filtered buffer level.
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100134 if (status.last_mode != NetEq::Mode::kRfc3389Cng &&
Jakob Ivarssone6aabd02022-03-28 16:06:37 +0200135 status.last_mode != NetEq::Mode::kCodecInternalCng) {
136 FilterBufferLevel(status.packet_buffer_info.span_samples);
Minyue Li7d204d52019-04-16 11:44:49 +0200137 }
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000138
Henrik Lundin7687ad52018-07-02 10:14:46 +0200139 // Guard for errors, to avoid getting stuck in error mode.
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100140 if (status.last_mode == NetEq::Mode::kError) {
Ivo Creusen53a31f72019-10-24 15:20:39 +0200141 if (!status.next_packet) {
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100142 return NetEq::Operation::kExpand;
Henrik Lundin7687ad52018-07-02 10:14:46 +0200143 } else {
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100144 // Use kUndefined to flag for a reset.
145 return NetEq::Operation::kUndefined;
Henrik Lundin7687ad52018-07-02 10:14:46 +0200146 }
147 }
148
Ivo Creusen53a31f72019-10-24 15:20:39 +0200149 if (status.next_packet && status.next_packet->is_cng) {
150 return CngOperation(status.last_mode, status.target_timestamp,
151 status.next_packet->timestamp,
152 status.generated_noise_samples);
Henrik Lundin7687ad52018-07-02 10:14:46 +0200153 }
154
155 // Handle the case with no packet at all available (except maybe DTMF).
Ivo Creusen53a31f72019-10-24 15:20:39 +0200156 if (!status.next_packet) {
157 return NoPacket(status.play_dtmf);
Henrik Lundin7687ad52018-07-02 10:14:46 +0200158 }
159
160 // If the expand period was very long, reset NetEQ since it is likely that the
161 // sender was restarted.
162 if (num_consecutive_expands_ > kReinitAfterExpands) {
163 *reset_decoder = true;
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100164 return NetEq::Operation::kNormal;
Henrik Lundin7687ad52018-07-02 10:14:46 +0200165 }
166
167 // Make sure we don't restart audio too soon after an expansion to avoid
168 // running out of data right away again. We should only wait if there are no
169 // DTX or CNG packets in the buffer (otherwise we should just play out what we
170 // have, since we cannot know the exact duration of DTX or CNG packets), and
171 // if the mute factor is low enough (otherwise the expansion was short enough
172 // to not be noticable).
173 // Note that the MuteFactor is in Q14, so a value of 16384 corresponds to 1.
Jakob Ivarsson80fb9782020-10-09 13:41:06 +0200174 const int target_level_samples =
175 delay_manager_->TargetDelayMs() * sample_rate_ / 1000;
Jakob Ivarssonca101e62022-04-04 21:42:55 +0200176 if (IsExpand(status.last_mode) && status.expand_mutefactor < 16384 / 2 &&
Jakob Ivarssone6aabd02022-03-28 16:06:37 +0200177 status.packet_buffer_info.span_samples <
178 static_cast<size_t>(target_level_samples * kPostponeDecodingLevel /
179 100) &&
Ivo Creusen53a31f72019-10-24 15:20:39 +0200180 !status.packet_buffer_info.dtx_or_cng) {
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100181 return NetEq::Operation::kExpand;
Henrik Lundin7687ad52018-07-02 10:14:46 +0200182 }
183
Jakob Ivarsson46dda832019-07-03 16:00:30 +0200184 const uint32_t five_seconds_samples = static_cast<uint32_t>(5 * sample_rate_);
Henrik Lundin7687ad52018-07-02 10:14:46 +0200185 // Check if the required packet is available.
Ivo Creusen53a31f72019-10-24 15:20:39 +0200186 if (status.target_timestamp == status.next_packet->timestamp) {
187 return ExpectedPacketAvailable(status.last_mode, status.play_dtmf);
188 } else if (!PacketBuffer::IsObsoleteTimestamp(status.next_packet->timestamp,
189 status.target_timestamp,
190 five_seconds_samples)) {
191 return FuturePacketAvailable(
192 status.last_packet_samples, status.last_mode, status.target_timestamp,
193 status.next_packet->timestamp, status.play_dtmf,
194 status.generated_noise_samples, status.packet_buffer_info.span_samples,
195 status.packet_buffer_info.num_packets);
Henrik Lundin7687ad52018-07-02 10:14:46 +0200196 } else {
197 // This implies that available_timestamp < target_timestamp, which can
198 // happen when a new stream or codec is received. Signal for a reset.
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100199 return NetEq::Operation::kUndefined;
Henrik Lundin7687ad52018-07-02 10:14:46 +0200200 }
201}
202
Jakob Ivarssonca101e62022-04-04 21:42:55 +0200203void DecisionLogic::NotifyMutedState() {
204 ++num_consecutive_expands_;
Henrik Lundin5afa61c2018-07-02 14:53:24 +0200205}
206
Ivo Creusena2b31c32020-10-14 17:54:22 +0200207absl::optional<int> DecisionLogic::PacketArrived(
208 int fs_hz,
209 bool should_update_stats,
210 const PacketArrivedInfo& info) {
Ivo Creusen7b463c52020-11-25 11:32:40 +0100211 buffer_flush_ = buffer_flush_ || info.buffer_flush;
Ivo Creusena2b31c32020-10-14 17:54:22 +0200212 if (info.is_cng_or_dtmf) {
Jakob Ivarsson80fb9782020-10-09 13:41:06 +0200213 last_pack_cng_or_dtmf_ = true;
214 return absl::nullopt;
Ivo Creusen53a31f72019-10-24 15:20:39 +0200215 }
Jakob Ivarsson80fb9782020-10-09 13:41:06 +0200216 if (!should_update_stats) {
217 return absl::nullopt;
218 }
Ivo Creusena2b31c32020-10-14 17:54:22 +0200219 if (info.packet_length_samples > 0 && fs_hz > 0 &&
220 info.packet_length_samples != packet_length_samples_) {
221 packet_length_samples_ = info.packet_length_samples;
Jakob Ivarsson80fb9782020-10-09 13:41:06 +0200222 delay_manager_->SetPacketAudioLength(packet_length_samples_ * 1000 / fs_hz);
223 }
224 auto relative_delay = delay_manager_->Update(
Ivo Creusena2b31c32020-10-14 17:54:22 +0200225 info.main_timestamp, fs_hz, /*reset=*/last_pack_cng_or_dtmf_);
Jakob Ivarsson80fb9782020-10-09 13:41:06 +0200226 last_pack_cng_or_dtmf_ = false;
Ivo Creusen53a31f72019-10-24 15:20:39 +0200227 return relative_delay;
228}
229
Minyue Li7d204d52019-04-16 11:44:49 +0200230void DecisionLogic::FilterBufferLevel(size_t buffer_size_samples) {
Jakob Ivarsson609b0472020-10-19 09:19:34 +0200231 buffer_level_filter_->SetTargetBufferLevel(delay_manager_->TargetDelayMs());
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 Creusen7b463c52020-11-25 11:32:40 +0100239 if (buffer_flush_) {
240 buffer_level_filter_->SetFilteredBufferLevel(buffer_size_samples);
241 buffer_flush_ = false;
242 } else {
243 buffer_level_filter_->Update(buffer_size_samples, time_stretched_samples);
244 }
Minyue Li7d204d52019-04-16 11:44:49 +0200245 prev_time_scale_ = false;
Jakob Ivarsson46dda832019-07-03 16:00:30 +0200246 time_stretched_cn_samples_ = 0;
Henrik Lundin5afa61c2018-07-02 14:53:24 +0200247}
248
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100249NetEq::Operation DecisionLogic::CngOperation(NetEq::Mode prev_mode,
250 uint32_t target_timestamp,
251 uint32_t available_timestamp,
252 size_t generated_noise_samples) {
Henrik Lundin7687ad52018-07-02 10:14:46 +0200253 // Signed difference between target and available timestamp.
254 int32_t timestamp_diff = static_cast<int32_t>(
255 static_cast<uint32_t>(generated_noise_samples + target_timestamp) -
256 available_timestamp);
Jakob Ivarsson80fb9782020-10-09 13:41:06 +0200257 int optimal_level_samp =
258 delay_manager_->TargetDelayMs() * sample_rate_ / 1000;
Henrik Lundin7687ad52018-07-02 10:14:46 +0200259 const int64_t excess_waiting_time_samp =
260 -static_cast<int64_t>(timestamp_diff) - optimal_level_samp;
261
262 if (excess_waiting_time_samp > optimal_level_samp / 2) {
263 // The waiting time for this packet will be longer than 1.5
264 // times the wanted buffer delay. Apply fast-forward to cut the
265 // waiting time down to the optimal.
Jakob Ivarsson42b6e2d2019-10-21 11:51:05 +0200266 noise_fast_forward_ = rtc::saturated_cast<size_t>(noise_fast_forward_ +
267 excess_waiting_time_samp);
Henrik Lundin7687ad52018-07-02 10:14:46 +0200268 timestamp_diff =
269 rtc::saturated_cast<int32_t>(timestamp_diff + excess_waiting_time_samp);
270 }
271
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100272 if (timestamp_diff < 0 && prev_mode == NetEq::Mode::kRfc3389Cng) {
Henrik Lundin7687ad52018-07-02 10:14:46 +0200273 // Not time to play this packet yet. Wait another round before using this
274 // packet. Keep on playing CNG from previous CNG parameters.
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100275 return NetEq::Operation::kRfc3389CngNoPacket;
Henrik Lundin7687ad52018-07-02 10:14:46 +0200276 } else {
277 // Otherwise, go for the CNG packet now.
278 noise_fast_forward_ = 0;
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100279 return NetEq::Operation::kRfc3389Cng;
Henrik Lundin7687ad52018-07-02 10:14:46 +0200280 }
281}
282
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100283NetEq::Operation DecisionLogic::NoPacket(bool play_dtmf) {
Henrik Lundin7687ad52018-07-02 10:14:46 +0200284 if (cng_state_ == kCngRfc3389On) {
285 // Keep on playing comfort noise.
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100286 return NetEq::Operation::kRfc3389CngNoPacket;
Henrik Lundin7687ad52018-07-02 10:14:46 +0200287 } else if (cng_state_ == kCngInternalOn) {
288 // Keep on playing codec internal comfort noise.
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100289 return NetEq::Operation::kCodecInternalCng;
Henrik Lundin7687ad52018-07-02 10:14:46 +0200290 } else if (play_dtmf) {
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100291 return NetEq::Operation::kDtmf;
Henrik Lundin7687ad52018-07-02 10:14:46 +0200292 } else {
293 // Nothing to play, do expand.
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100294 return NetEq::Operation::kExpand;
Henrik Lundin7687ad52018-07-02 10:14:46 +0200295 }
296}
297
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100298NetEq::Operation DecisionLogic::ExpectedPacketAvailable(NetEq::Mode prev_mode,
299 bool play_dtmf) {
300 if (!disallow_time_stretching_ && prev_mode != NetEq::Mode::kExpand &&
301 !play_dtmf) {
Jakob Ivarsson80fb9782020-10-09 13:41:06 +0200302 const int samples_per_ms = sample_rate_ / 1000;
303 const int target_level_samples =
304 delay_manager_->TargetDelayMs() * samples_per_ms;
305 const int low_limit =
306 std::max(target_level_samples * 3 / 4,
307 target_level_samples -
308 kDecelerationTargetLevelOffsetMs * samples_per_ms);
Artem Titovd00ce742021-07-28 20:00:17 +0200309 // `higher_limit` is equal to `target_level`, but should at
310 // least be 20 ms higher than `lower_limit`.
Jakob Ivarsson80fb9782020-10-09 13:41:06 +0200311 const int high_limit =
312 std::max(target_level_samples, low_limit + 20 * samples_per_ms);
313
314 const int buffer_level_samples =
Jakob Ivarsson609b0472020-10-19 09:19:34 +0200315 buffer_level_filter_->filtered_current_level();
Jakob Ivarsson80fb9782020-10-09 13:41:06 +0200316 if (buffer_level_samples >= high_limit << 2)
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100317 return NetEq::Operation::kFastAccelerate;
Henrik Lundin7687ad52018-07-02 10:14:46 +0200318 if (TimescaleAllowed()) {
Jakob Ivarsson80fb9782020-10-09 13:41:06 +0200319 if (buffer_level_samples >= high_limit)
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100320 return NetEq::Operation::kAccelerate;
Jakob Ivarsson80fb9782020-10-09 13:41:06 +0200321 if (buffer_level_samples < low_limit)
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100322 return NetEq::Operation::kPreemptiveExpand;
Henrik Lundin7687ad52018-07-02 10:14:46 +0200323 }
324 }
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100325 return NetEq::Operation::kNormal;
Henrik Lundin7687ad52018-07-02 10:14:46 +0200326}
327
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100328NetEq::Operation DecisionLogic::FuturePacketAvailable(
Henrik Lundin7687ad52018-07-02 10:14:46 +0200329 size_t decoder_frame_length,
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100330 NetEq::Mode prev_mode,
Henrik Lundin7687ad52018-07-02 10:14:46 +0200331 uint32_t target_timestamp,
332 uint32_t available_timestamp,
333 bool play_dtmf,
Ivo Creusen53a31f72019-10-24 15:20:39 +0200334 size_t generated_noise_samples,
335 size_t span_samples_in_packet_buffer,
336 size_t num_packets_in_packet_buffer) {
Henrik Lundin7687ad52018-07-02 10:14:46 +0200337 // Required packet is not available, but a future packet is.
338 // Check if we should continue with an ongoing expand because the new packet
339 // is too far into the future.
340 uint32_t timestamp_leap = available_timestamp - target_timestamp;
Jakob Ivarssonca101e62022-04-04 21:42:55 +0200341 if (IsExpand(prev_mode) && !ReinitAfterExpands(timestamp_leap) &&
342 !MaxWaitForPacket() && PacketTooEarly(timestamp_leap) &&
343 UnderTargetLevel()) {
Henrik Lundin7687ad52018-07-02 10:14:46 +0200344 if (play_dtmf) {
345 // Still have DTMF to play, so do not do expand.
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100346 return NetEq::Operation::kDtmf;
Henrik Lundin7687ad52018-07-02 10:14:46 +0200347 } else {
348 // Nothing to play.
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100349 return NetEq::Operation::kExpand;
Henrik Lundin7687ad52018-07-02 10:14:46 +0200350 }
351 }
352
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100353 if (prev_mode == NetEq::Mode::kCodecPlc) {
354 return NetEq::Operation::kNormal;
Henrik Lundin00eb12a2018-09-05 18:14:52 +0200355 }
356
Henrik Lundin7687ad52018-07-02 10:14:46 +0200357 // If previous was comfort noise, then no merge is needed.
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100358 if (prev_mode == NetEq::Mode::kRfc3389Cng ||
359 prev_mode == NetEq::Mode::kCodecInternalCng) {
Jakob Ivarsson46dda832019-07-03 16:00:30 +0200360 const size_t target_level_samples =
Jakob Ivarsson80fb9782020-10-09 13:41:06 +0200361 delay_manager_->TargetDelayMs() * sample_rate_ / 1000;
Jakob Ivarsson46dda832019-07-03 16:00:30 +0200362 const bool generated_enough_noise =
363 static_cast<uint32_t>(generated_noise_samples + target_timestamp) >=
364 available_timestamp;
Jakob Ivarssone6aabd02022-03-28 16:06:37 +0200365 const size_t target_threshold_samples =
366 target_level_window_ms_ / 2 * (sample_rate_ / 1000);
367 const bool above_target_window =
368 span_samples_in_packet_buffer >
369 target_level_samples + target_threshold_samples;
370 const bool below_target_window =
371 target_level_samples > target_threshold_samples &&
372 span_samples_in_packet_buffer <
373 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 NetEq::Operation::kNormal;
Henrik Lundin7687ad52018-07-02 10:14:46 +0200380 }
Jakob Ivarsson46dda832019-07-03 16:00:30 +0200381
382 // Too early to play this new packet; keep on playing comfort noise.
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100383 if (prev_mode == NetEq::Mode::kRfc3389Cng) {
384 return NetEq::Operation::kRfc3389CngNoPacket;
Jakob Ivarsson46dda832019-07-03 16:00:30 +0200385 }
386 // prevPlayMode == kModeCodecInternalCng.
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100387 return NetEq::Operation::kCodecInternalCng;
Henrik Lundin7687ad52018-07-02 10:14:46 +0200388 }
Jakob Ivarsson46dda832019-07-03 16:00:30 +0200389
Henrik Lundin7687ad52018-07-02 10:14:46 +0200390 // Do not merge unless we have done an expand before.
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100391 if (prev_mode == NetEq::Mode::kExpand) {
392 return NetEq::Operation::kMerge;
Henrik Lundin7687ad52018-07-02 10:14:46 +0200393 } else if (play_dtmf) {
394 // Play DTMF instead of expand.
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100395 return NetEq::Operation::kDtmf;
Henrik Lundin7687ad52018-07-02 10:14:46 +0200396 } else {
Ivo Creusen3ce44a32019-10-31 14:38:11 +0100397 return NetEq::Operation::kExpand;
Henrik Lundin7687ad52018-07-02 10:14:46 +0200398 }
399}
400
401bool DecisionLogic::UnderTargetLevel() const {
Jakob Ivarsson609b0472020-10-19 09:19:34 +0200402 return buffer_level_filter_->filtered_current_level() <
Jakob Ivarsson80fb9782020-10-09 13:41:06 +0200403 delay_manager_->TargetDelayMs() * sample_rate_ / 1000;
Henrik Lundin7687ad52018-07-02 10:14:46 +0200404}
405
406bool DecisionLogic::ReinitAfterExpands(uint32_t timestamp_leap) const {
407 return timestamp_leap >=
408 static_cast<uint32_t>(output_size_samples_ * kReinitAfterExpands);
409}
410
411bool DecisionLogic::PacketTooEarly(uint32_t timestamp_leap) const {
412 return timestamp_leap >
413 static_cast<uint32_t>(output_size_samples_ * num_consecutive_expands_);
414}
415
416bool DecisionLogic::MaxWaitForPacket() const {
417 return num_consecutive_expands_ >= kMaxWaitForPacket;
418}
419
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000420} // namespace webrtc