Bug Summary

File:root/firefox-clang/obj-x86_64-pc-linux-gnu/third_party/libwebrtc/modules/audio_coding/neteq_gn/./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc
Warning:line 265, column 5
Value stored to 'main_timestamp' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -O2 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name Unified_cpp_neteq_gn1.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/third_party/libwebrtc/modules/audio_coding/neteq_gn -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/third_party/libwebrtc/modules/audio_coding/neteq_gn -resource-dir /usr/lib/llvm-23/lib/clang/23 -include /root/firefox-clang/config/gcc_hidden.h -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -D _GLIBCXX_ASSERTIONS=1 -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG=1 -D ABSL_ALLOCATOR_NOTHROW=1 -D PROTOBUF_ENABLE_DEBUG_LOGGING_MAY_LEAK_PII=0 -D RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY -D RTC_ENABLE_VP9 -D WEBRTC_DEPRECATE_PLAN_B -D WEBRTC_ENABLE_PROTOBUF=0 -D WEBRTC_ENCODER_PSNR_STATS -D WEBRTC_LIBRARY_IMPL -D WEBRTC_MOZILLA_BUILD -D WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS=0 -D WEBRTC_STRICT_FIELD_TRIALS=0 -D DYNAMIC_ANNOTATIONS_ENABLED=1 -D USE_AURA=1 -D USE_GLIB=1 -D USE_OZONE=1 -D USE_UDEV -D WEBRTC_LINUX -D WEBRTC_POSIX -D _FILE_OFFSET_BITS=64 -D _LARGEFILE64_SOURCE -D _LARGEFILE_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D WEBRTC_ENABLE_AVX2 -D _DEBUG -D _GNU_SOURCE -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D MOZ_SUPPORT_LEAKCHECKING -D STATIC_EXPORTABLE_JS_API -I /root/firefox-clang/third_party/libwebrtc/modules/audio_coding/neteq_gn -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/third_party/libwebrtc/modules/audio_coding/neteq_gn -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/libwebrtc_overrides -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/ipc/ipdl/_ipdlheaders -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/third_party/libwebrtc/gen -I /root/firefox-clang/ipc/chromium/src -I /root/firefox-clang/third_party/abseil-cpp -I /root/firefox-clang/third_party/libwebrtc -I /root/firefox-clang/tools/profiler/public -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -D MOZILLA_CLIENT -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/x86_64-linux-gnu/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16/backward -internal-isystem /usr/lib/llvm-23/lib/clang/23/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-error=pessimizing-move -Wno-error=large-by-value-copy=128 -Wno-error=implicit-int-float-conversion -Wno-error=thread-safety-analysis -Wno-error=tautological-type-limit-compare -Wno-invalid-offsetof -Wno-range-loop-analysis -Wno-deprecated-anon-enum-enum-conversion -Wno-deprecated-enum-enum-conversion -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-vla-cxx-extension -Wno-unknown-warning-option -Wno-character-conversion -std=gnu++20 -fdeprecated-macro -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fno-implicit-modules -fskip-odr-check-in-gmf -fno-sized-deallocation -fno-aligned-allocation -fdiagnostics-absolute-paths -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -mllvm -dwarf-linkage-names=Abstract -faddrsig -fdwarf2-cfi-asm -o /tmp/scan-build-2026-09-01-224014-2642839-1 -x c++ Unified_cpp_neteq_gn1.cpp
1/*
2 * Copyright (c) 2012 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
11#include "modules/audio_coding/neteq/neteq_impl.h"
12
13#include <algorithm>
14#include <cstdint>
15#include <cstring>
16#include <list>
17#include <map>
18#include <memory>
19#include <optional>
20#include <span>
21#include <utility>
22#include <vector>
23
24#include "absl/strings/str_cat.h"
25#include "api/audio/audio_frame.h"
26#include "api/audio/audio_view.h"
27#include "api/audio_codecs/audio_decoder.h"
28#include "api/audio_codecs/audio_decoder_factory.h"
29#include "api/audio_codecs/audio_format.h"
30#include "api/environment/environment.h"
31#include "api/neteq/neteq.h"
32#include "api/neteq/neteq_controller.h"
33#include "api/neteq/neteq_controller_factory.h"
34#include "api/neteq/tick_timer.h"
35#include "api/rtp_headers.h"
36#include "api/rtp_packet_info.h"
37#include "api/rtp_packet_infos.h"
38#include "api/scoped_refptr.h"
39#include "api/units/time_delta.h"
40#include "modules/audio_coding/codecs/cng/webrtc_cng.h"
41#include "modules/audio_coding/neteq/accelerate.h"
42#include "modules/audio_coding/neteq/background_noise.h"
43#include "modules/audio_coding/neteq/comfort_noise.h"
44#include "modules/audio_coding/neteq/decoder_database.h"
45#include "modules/audio_coding/neteq/dtmf_buffer.h"
46#include "modules/audio_coding/neteq/dtmf_tone_generator.h"
47#include "modules/audio_coding/neteq/expand.h"
48#include "modules/audio_coding/neteq/merge.h"
49#include "modules/audio_coding/neteq/normal.h"
50#include "modules/audio_coding/neteq/packet.h"
51#include "modules/audio_coding/neteq/packet_buffer.h"
52#include "modules/audio_coding/neteq/preemptive_expand.h"
53#include "modules/audio_coding/neteq/red_payload_splitter.h"
54#include "modules/audio_coding/neteq/statistics_calculator.h"
55#include "modules/audio_coding/neteq/sync_buffer.h"
56#include "modules/audio_coding/neteq/time_stretch.h"
57#include "modules/audio_coding/neteq/timestamp_scaler.h"
58#include "rtc_base/checks.h"
59#include "rtc_base/logging.h"
60#include "rtc_base/numerics/safe_conversions.h"
61#include "rtc_base/sanitizer.h"
62#include "rtc_base/trace_event.h"
63#include "system_wrappers/include/clock.h"
64
65namespace webrtc {
66namespace {
67
68AudioFrame::SpeechType ToSpeechType(NetEqImpl::OutputType type) {
69 switch (type) {
70 case NetEqImpl::OutputType::kNormalSpeech: {
71 return AudioFrame::kNormalSpeech;
72 }
73 case NetEqImpl::OutputType::kCNG: {
74 return AudioFrame::kCNG;
75 }
76 case NetEqImpl::OutputType::kPLC: {
77 return AudioFrame::kPLC;
78 }
79 case NetEqImpl::OutputType::kPLCCNG: {
80 return AudioFrame::kPLCCNG;
81 }
82 case NetEqImpl::OutputType::kCodecPLC: {
83 return AudioFrame::kCodecPLC;
84 }
85 default:
86 RTC_DCHECK_NOTREACHED()(false) ? static_cast<void>(0) : ::webrtc::webrtc_checks_impl
::FatalLogCall<false>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 86, "false") & ::webrtc::webrtc_checks_impl::LogStreamer
<>()
;
87 return AudioFrame::kUndefined;
88 }
89}
90
91// Returns true if both payload types are known to the decoder database, and
92// have the same sample rate.
93bool EqualSampleRates(uint8_t pt1,
94 uint8_t pt2,
95 const DecoderDatabase& decoder_database) {
96 auto* di1 = decoder_database.GetDecoderInfo(pt1);
97 auto* di2 = decoder_database.GetDecoderInfo(pt2);
98 return di1 && di2 && di1->SampleRateHz() == di2->SampleRateHz();
99}
100
101} // namespace
102
103NetEqImpl::Dependencies::Dependencies(
104 const Environment& env,
105 const NetEq::Config& config,
106 scoped_refptr<AudioDecoderFactory> decoder_factory,
107 const NetEqControllerFactory& controller_factory)
108 : env(env),
109 tick_timer(new TickTimer),
110 stats(std::make_unique<StatisticsCalculator>(tick_timer.get())),
111 decoder_database(
112 std::make_unique<DecoderDatabase>(env, std::move(decoder_factory))),
113 dtmf_buffer(new DtmfBuffer(config.sample_rate_hz)),
114 dtmf_tone_generator(new DtmfToneGenerator),
115 packet_buffer(new PacketBuffer(env.field_trials(),
116 config.max_packets_in_buffer,
117 tick_timer.get(),
118 stats.get())),
119 neteq_controller(controller_factory.Create(
120 env,
121 {.allow_time_stretching = !config.for_test_no_time_stretching,
122 .max_packets_in_buffer =
123 static_cast<int>(config.max_packets_in_buffer),
124 .base_min_delay_ms = config.min_delay_ms,
125 .tick_timer = tick_timer.get()})),
126 red_payload_splitter(new RedPayloadSplitter),
127 timestamp_scaler(new TimestampScaler(*decoder_database)),
128 accelerate_factory(new AccelerateFactory),
129 expand_factory(new ExpandFactory),
130 preemptive_expand_factory(new PreemptiveExpandFactory) {}
131
132NetEqImpl::Dependencies::~Dependencies() = default;
133
134NetEqImpl::NetEqImpl(const NetEq::Config& config,
135 Dependencies&& deps,
136 bool create_components)
137 : env_(deps.env),
138 tick_timer_(std::move(deps.tick_timer)),
139 decoder_database_(std::move(deps.decoder_database)),
140 dtmf_buffer_(std::move(deps.dtmf_buffer)),
141 dtmf_tone_generator_(std::move(deps.dtmf_tone_generator)),
142 packet_buffer_(std::move(deps.packet_buffer)),
143 red_payload_splitter_(std::move(deps.red_payload_splitter)),
144 timestamp_scaler_(std::move(deps.timestamp_scaler)),
145 expand_factory_(std::move(deps.expand_factory)),
146 accelerate_factory_(std::move(deps.accelerate_factory)),
147 preemptive_expand_factory_(std::move(deps.preemptive_expand_factory)),
148 stats_(std::move(deps.stats)),
149 controller_(std::move(deps.neteq_controller)),
150 last_mode_(Mode::kNormal),
151 decoded_buffer_length_(kMaxFrameSize),
152 decoded_buffer_(new int16_t[decoded_buffer_length_]),
153 playout_timestamp_(0),
154 new_codec_(false),
155 timestamp_(0),
156 reset_decoder_(false),
157 first_packet_(true),
158 enable_fast_accelerate_(config.enable_fast_accelerate),
159 enable_muted_state_(config.enable_muted_state),
160 no_time_stretching_(config.for_test_no_time_stretching) {
161 RTC_LOG(LS_INFO)!::webrtc::LogMessage::IsNoop<::webrtc::LS_INFO>() &&
::webrtc::webrtc_logging_impl::LogCall() & ::webrtc::webrtc_logging_impl
::LogStreamer<>() << ::webrtc::webrtc_logging_impl
::LogMetadata("./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 161, ::webrtc::LS_INFO)
<< "NetEq config: " << config.ToString();
162 int fs = config.sample_rate_hz;
163 if (fs != 8000 && fs != 16000 && fs != 32000 && fs != 48000) {
164 RTC_LOG(LS_ERROR)!::webrtc::LogMessage::IsNoop<::webrtc::LS_ERROR>() &&
::webrtc::webrtc_logging_impl::LogCall() & ::webrtc::webrtc_logging_impl
::LogStreamer<>() << ::webrtc::webrtc_logging_impl
::LogMetadata("./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 164, ::webrtc::LS_ERROR)
<< "Sample rate " << fs
165 << " Hz not supported. "
166 "Changing to 8000 Hz.";
167 fs = 8000;
168 }
169 controller_->SetMaximumDelay(config.max_delay_ms);
170 fs_hz_ = fs;
171 fs_mult_ = fs / 8000;
172 last_output_sample_rate_hz_ = fs;
173 output_size_samples_ = static_cast<size_t>(kOutputSizeMs * 8 * fs_mult_);
174 controller_->SetSampleRate(fs_hz_, output_size_samples_);
175 decoder_frame_length_ = 2 * output_size_samples_; // 20 ms.
176 if (create_components) {
177 SetSampleRateAndChannels(fs, 1); // Default is 1 channel.
178 }
179}
180
181NetEqImpl::~NetEqImpl() = default;
182
183int NetEqImpl::InsertPacket(const RTPHeader& rtp_header,
184 std::span<const uint8_t> payload,
185 const RtpPacketInfo& packet_info) {
186 MsanCheckInitialized(payload);
187 TRACE_EVENT0("webrtc", "NetEqImpl::InsertPacket")static const unsigned char* trace_event_unique_catstatic187 =
reinterpret_cast<const unsigned char*>("webrtc");; webrtc
::trace_event_internal::TraceEndOnScopeClose trace_event_unique_profileScope187
; if (*trace_event_unique_catstatic187) { webrtc::trace_event_internal
::AddTraceEvent( ('B'), trace_event_unique_catstatic187, "NetEqImpl::InsertPacket"
, webrtc::trace_event_internal::kNoEventId, (static_cast<unsigned
char>(0))); trace_event_unique_profileScope187 .Initialize
(trace_event_unique_catstatic187, "NetEqImpl::InsertPacket");
}
;
188 if (payload.empty()) {
189 RTC_LOG_F(LS_ERROR)!::webrtc::LogMessage::IsNoop<::webrtc::LS_ERROR>() &&
::webrtc::webrtc_logging_impl::LogCall() & ::webrtc::webrtc_logging_impl
::LogStreamer<>() << ::webrtc::webrtc_logging_impl
::LogMetadata("./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 189, ::webrtc::LS_ERROR) << __PRETTY_FUNCTION__ <<
": "
<< "payload is empty";
190 return kFail;
191 }
192 stats_->ReceivedPacket();
193
194 PacketList packet_list;
195 // Insert packet in a packet list.
196 packet_list.push_back([&rtp_header, &payload] {
197 // Convert to Packet.
198 Packet packet;
199 packet.payload_type = rtp_header.payloadType;
200 packet.sequence_number = rtp_header.sequenceNumber;
201 packet.timestamp = rtp_header.timestamp;
202 packet.payload.SetData(payload.data(), payload.size());
203 // Waiting time will be set upon inserting the packet in the buffer.
204 RTC_DCHECK(!packet.waiting_time)(!packet.waiting_time) ? static_cast<void>(0) : ::webrtc
::webrtc_checks_impl::FatalLogCall<false>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 204, "!packet.waiting_time") & ::webrtc::webrtc_checks_impl
::LogStreamer<>()
;
205 return packet;
206 }());
207
208 bool update_sample_rate_and_channels = first_packet_;
209
210 if (update_sample_rate_and_channels) {
211 // Reset timestamp scaling.
212 timestamp_scaler_->Reset();
213 }
214
215 if (!decoder_database_->IsRed(rtp_header.payloadType)) {
216 // Scale timestamp to internal domain (only for some codecs).
217 timestamp_scaler_->ToInternal(&packet_list);
218 }
219
220 // Store these for later use, since the first packet may very well disappear
221 // before we need these values.
222 uint32_t main_timestamp = packet_list.front().timestamp;
223
224 // Reinitialize NetEq if it's needed (changed SSRC or first call).
225 if (update_sample_rate_and_channels) {
226 // Note: `first_packet_` will be cleared further down in this method, once
227 // the packet has been successfully inserted into the packet buffer.
228
229 // Flush the packet buffer and DTMF buffer.
230 packet_buffer_->Flush();
231 dtmf_buffer_->Flush();
232
233 // Update audio buffer timestamp.
234 sync_buffer_->IncreaseEndTimestamp(main_timestamp - timestamp_);
235
236 // Update codecs.
237 timestamp_ = main_timestamp;
238 }
239
240 // Check for RED payload type, and separate payloads into several packets.
241 if (decoder_database_->IsRed(rtp_header.payloadType)) {
242 if (!red_payload_splitter_->SplitRed(&packet_list)) {
243 return kFail;
244 }
245 // Only accept a few RED payloads of the same type as the main data,
246 // DTMF events and CNG.
247 red_payload_splitter_->CheckRedPayloads(&packet_list, *decoder_database_);
248 if (packet_list.empty()) {
249 return kFail;
250 }
251 }
252
253 // Check payload types.
254 if (decoder_database_->CheckPayloadTypes(packet_list) ==
255 DecoderDatabase::kDecoderNotFound) {
256 return kFail;
257 }
258
259 RTC_DCHECK(!packet_list.empty())(!packet_list.empty()) ? static_cast<void>(0) : ::webrtc
::webrtc_checks_impl::FatalLogCall<false>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 259, "!packet_list.empty()") & ::webrtc::webrtc_checks_impl
::LogStreamer<>()
;
260
261 // Update main_timestamp, if new packets appear in the list
262 // after RED splitting.
263 if (decoder_database_->IsRed(rtp_header.payloadType)) {
264 timestamp_scaler_->ToInternal(&packet_list);
265 main_timestamp = packet_list.front().timestamp;
Value stored to 'main_timestamp' is never read
266 }
267
268 // Process DTMF payloads. Cycle through the list of packets, and pick out any
269 // DTMF payloads found.
270 PacketList::iterator it = packet_list.begin();
271 while (it != packet_list.end()) {
272 const Packet& current_packet = (*it);
273 RTC_DCHECK(!current_packet.payload.empty())(!current_packet.payload.empty()) ? static_cast<void>(0
) : ::webrtc::webrtc_checks_impl::FatalLogCall<false>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 273, "!current_packet.payload.empty()") & ::webrtc::webrtc_checks_impl
::LogStreamer<>()
;
274 if (decoder_database_->IsDtmf(current_packet.payload_type)) {
275 DtmfEvent event;
276 int ret = DtmfBuffer::ParseEvent(current_packet.timestamp,
277 current_packet.payload.data(),
278 current_packet.payload.size(), &event);
279 if (ret != DtmfBuffer::kOK) {
280 return kFail;
281 }
282 if (dtmf_buffer_->InsertEvent(event) != DtmfBuffer::kOK) {
283 return kFail;
284 }
285 it = packet_list.erase(it);
286 } else {
287 ++it;
288 }
289 }
290
291 PacketList parsed_packet_list;
292 while (!packet_list.empty()) {
293 Packet& packet = packet_list.front();
294 const DecoderDatabase::DecoderInfo* info =
295 decoder_database_->GetDecoderInfo(packet.payload_type);
296 if (!info) {
297 RTC_LOG(LS_WARNING)!::webrtc::LogMessage::IsNoop<::webrtc::LS_WARNING>() &&
::webrtc::webrtc_logging_impl::LogCall() & ::webrtc::webrtc_logging_impl
::LogStreamer<>() << ::webrtc::webrtc_logging_impl
::LogMetadata("./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 297, ::webrtc::LS_WARNING)
<< "SplitAudio unknown payload type";
298 return kFail;
299 }
300
301 if (info->IsComfortNoise()) {
302 // Carry comfort noise packets along.
303 parsed_packet_list.splice(parsed_packet_list.end(), packet_list,
304 packet_list.begin());
305 } else {
306 const uint16_t sequence_number = packet.sequence_number;
307 const uint8_t payload_type = packet.payload_type;
308 const Packet::Priority original_priority = packet.priority;
309 auto packet_from_result = [&](AudioDecoder::ParseResult& result) {
310 Packet new_packet;
311 new_packet.sequence_number = sequence_number;
312 new_packet.payload_type = payload_type;
313 new_packet.timestamp = result.timestamp;
314 new_packet.priority.codec_level = result.priority;
315 new_packet.priority.red_level = original_priority.red_level;
316 // Only associate the header information with the primary packet.
317 if (new_packet.timestamp == packet_info.rtp_timestamp()) {
318 new_packet.packet_info = packet_info;
319 }
320 new_packet.frame = std::move(result.frame);
321 return new_packet;
322 };
323
324 std::vector<AudioDecoder::ParseResult> results =
325 info->GetDecoder()->ParsePayload(std::move(packet.payload),
326 packet.timestamp);
327 if (results.empty()) {
328 packet_list.pop_front();
329 } else {
330 bool first = true;
331 for (auto& result : results) {
332 RTC_DCHECK(result.frame)(result.frame) ? static_cast<void>(0) : ::webrtc::webrtc_checks_impl
::FatalLogCall<false>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 332, "result.frame") & ::webrtc::webrtc_checks_impl::LogStreamer
<>()
;
333 RTC_DCHECK_GE(result.priority, 0)::webrtc::SafeGe((result.priority), (0)) ? static_cast<void
>(0) : ::webrtc::webrtc_checks_impl::FatalLogCall<true>
( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 333, "result.priority" " " ">=" " " "0") & ::webrtc::
webrtc_checks_impl::LogStreamer<>() << (result.priority
) << (0)
;
334 if (first) {
335 // Re-use the node and move it to parsed_packet_list.
336 packet_list.front() = packet_from_result(result);
337 parsed_packet_list.splice(parsed_packet_list.end(), packet_list,
338 packet_list.begin());
339 first = false;
340 } else {
341 parsed_packet_list.push_back(packet_from_result(result));
342 }
343 }
344 }
345 }
346 }
347
348 // Calculate the number of primary (non-FEC/RED) packets.
349 const size_t number_of_primary_packets = std::count_if(
350 parsed_packet_list.begin(), parsed_packet_list.end(),
351 [](const Packet& in) { return in.priority.codec_level == 0; });
352 if (number_of_primary_packets < parsed_packet_list.size()) {
353 stats_->SecondaryPacketsReceived(parsed_packet_list.size() -
354 number_of_primary_packets);
355 }
356
357 const int target_level_ms = controller_->TargetLevelMs();
358 for (Packet& packet : parsed_packet_list) {
359 NetEqController::PacketArrivedInfo info = ToPacketArrivedInfo(packet);
360 if (MaybeChangePayloadType(packet.payload_type)) {
361 packet_buffer_->Flush();
362 new_codec_ = true;
363 update_sample_rate_and_channels = true;
364 info.buffer_flush = true;
365 }
366 int return_val = packet_buffer_->InsertPacket(
367 std::move(packet), decoder_frame_length_, last_output_sample_rate_hz_,
368 target_level_ms);
369 if (return_val == PacketBuffer::kFlushed) {
370 new_codec_ = true;
371 update_sample_rate_and_channels = true;
372 info.buffer_flush = true;
373 } else if (return_val == PacketBuffer::kPartialFlush) {
374 // Forward sync buffer timestamp.
375 const Packet* next_packet = packet_buffer_->PeekNextPacket();
376 if (next_packet) {
377 timestamp_ = next_packet->timestamp;
378 sync_buffer_->IncreaseEndTimestamp(timestamp_ -
379 sync_buffer_->end_timestamp());
380 }
381 info.buffer_flush = true;
382 } else if (return_val != PacketBuffer::kOK) {
383 // An error occurred.
384 return kFail;
385 }
386
387 const bool should_update_stats = !new_codec_;
388 auto relative_delay =
389 controller_->PacketArrived(fs_hz_, should_update_stats, info);
390 if (relative_delay) {
391 stats_->RelativePacketArrivalDelay(relative_delay.value());
392 }
393 }
394
395 if (first_packet_) {
396 first_packet_ = false;
397 // Update the codec on the next GetAudio call.
398 new_codec_ = true;
399 }
400
401 if (current_rtp_payload_type_) {
402 RTC_DCHECK(decoder_database_->GetDecoderInfo(*current_rtp_payload_type_))(decoder_database_->GetDecoderInfo(*current_rtp_payload_type_
)) ? static_cast<void>(0) : ::webrtc::webrtc_checks_impl
::FatalLogCall<false>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 402, "decoder_database_->GetDecoderInfo(*current_rtp_payload_type_)"
) & ::webrtc::webrtc_checks_impl::LogStreamer<>()
403 << "Payload type " << static_cast<int>(*current_rtp_payload_type_)
404 << " is unknown where it shouldn't be";
405 }
406
407 if (update_sample_rate_and_channels && !packet_buffer_->Empty()) {
408 // We do not use `current_rtp_payload_type_` to |set payload_type|, but
409 // get the next RTP header from `packet_buffer_` to obtain the payload type.
410 // The reason for it is the following corner case. If NetEq receives a
411 // CNG packet with a sample rate different than the current CNG then it
412 // flushes its buffer, assuming send codec must have been changed. However,
413 // payload type of the hypothetically new send codec is not known.
414 const Packet* next_packet = packet_buffer_->PeekNextPacket();
415 RTC_DCHECK(next_packet)(next_packet) ? static_cast<void>(0) : ::webrtc::webrtc_checks_impl
::FatalLogCall<false>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 415, "next_packet") & ::webrtc::webrtc_checks_impl::LogStreamer
<>()
;
416 const int payload_type = next_packet->payload_type;
417 size_t channels = 1;
418 if (!decoder_database_->IsComfortNoise(payload_type)) {
419 AudioDecoder* decoder = decoder_database_->GetDecoder(payload_type);
420 RTC_DCHECK(decoder)(decoder) ? static_cast<void>(0) : ::webrtc::webrtc_checks_impl
::FatalLogCall<false>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 420, "decoder") & ::webrtc::webrtc_checks_impl::LogStreamer
<>()
; // Payloads are already checked to be valid.
421 channels = decoder->Channels();
422 RTC_DCHECK_LE(channels, kMaxNumberOfAudioChannels)::webrtc::SafeLe((channels), (kMaxNumberOfAudioChannels)) ? static_cast
<void>(0) : ::webrtc::webrtc_checks_impl::FatalLogCall<
true>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 422, "channels" " " "<=" " " "kMaxNumberOfAudioChannels"
) & ::webrtc::webrtc_checks_impl::LogStreamer<>() <<
(channels) << (kMaxNumberOfAudioChannels)
;
423 }
424 const DecoderDatabase::DecoderInfo* decoder_info =
425 decoder_database_->GetDecoderInfo(payload_type);
426 RTC_DCHECK(decoder_info)(decoder_info) ? static_cast<void>(0) : ::webrtc::webrtc_checks_impl
::FatalLogCall<false>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 426, "decoder_info") & ::webrtc::webrtc_checks_impl::LogStreamer
<>()
;
427 if (decoder_info->SampleRateHz() != fs_hz_ ||
428 channels != algorithm_buffer_->Channels()) {
429 RTC_DCHECK_LE(channels, kMaxNumberOfAudioChannels)::webrtc::SafeLe((channels), (kMaxNumberOfAudioChannels)) ? static_cast
<void>(0) : ::webrtc::webrtc_checks_impl::FatalLogCall<
true>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 429, "channels" " " "<=" " " "kMaxNumberOfAudioChannels"
) & ::webrtc::webrtc_checks_impl::LogStreamer<>() <<
(channels) << (kMaxNumberOfAudioChannels)
;
430 SetSampleRateAndChannels(decoder_info->SampleRateHz(), channels);
431 }
432 }
433
434 return kOK;
435}
436
437int NetEqImpl::GetAudio(AudioFrame* audio_frame,
438 bool* muted,
439 int* current_sample_rate_hz,
440 std::optional<Operation> action_override) {
441 TRACE_EVENT0("webrtc", "NetEqImpl::GetAudio")static const unsigned char* trace_event_unique_catstatic441 =
reinterpret_cast<const unsigned char*>("webrtc");; webrtc
::trace_event_internal::TraceEndOnScopeClose trace_event_unique_profileScope441
; if (*trace_event_unique_catstatic441) { webrtc::trace_event_internal
::AddTraceEvent( ('B'), trace_event_unique_catstatic441, "NetEqImpl::GetAudio"
, webrtc::trace_event_internal::kNoEventId, (static_cast<unsigned
char>(0))); trace_event_unique_profileScope441 .Initialize
(trace_event_unique_catstatic441, "NetEqImpl::GetAudio"); }
;
442 if (GetAudioInternal(audio_frame, action_override) != kNoError) {
443 return kFail;
444 }
445 stats_->IncreaseCounter(output_size_samples_, fs_hz_);
446 RTC_DCHECK_EQ(audio_frame->sample_rate_hz_,::webrtc::SafeEq((audio_frame->sample_rate_hz_), (dchecked_cast
<int>(audio_frame->samples_per_channel_ * 100))) ? static_cast
<void>(0) : ::webrtc::webrtc_checks_impl::FatalLogCall<
true>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 447, "audio_frame->sample_rate_hz_" " " "==" " " "dchecked_cast<int>(audio_frame->samples_per_channel_ * 100)"
) & ::webrtc::webrtc_checks_impl::LogStreamer<>() <<
(audio_frame->sample_rate_hz_) << (dchecked_cast<
int>(audio_frame->samples_per_channel_ * 100))
447 dchecked_cast<int>(audio_frame->samples_per_channel_ * 100))::webrtc::SafeEq((audio_frame->sample_rate_hz_), (dchecked_cast
<int>(audio_frame->samples_per_channel_ * 100))) ? static_cast
<void>(0) : ::webrtc::webrtc_checks_impl::FatalLogCall<
true>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 447, "audio_frame->sample_rate_hz_" " " "==" " " "dchecked_cast<int>(audio_frame->samples_per_channel_ * 100)"
) & ::webrtc::webrtc_checks_impl::LogStreamer<>() <<
(audio_frame->sample_rate_hz_) << (dchecked_cast<
int>(audio_frame->samples_per_channel_ * 100))
;
448 if (muted != nullptr) {
449 *muted = audio_frame->muted();
450 }
451 audio_frame->speech_type_ = ToSpeechType(LastOutputType());
452 last_output_sample_rate_hz_ = audio_frame->sample_rate_hz_;
453 RTC_DCHECK(last_output_sample_rate_hz_ == 8000 ||(last_output_sample_rate_hz_ == 8000 || last_output_sample_rate_hz_
== 16000 || last_output_sample_rate_hz_ == 32000 || last_output_sample_rate_hz_
== 48000) ? static_cast<void>(0) : ::webrtc::webrtc_checks_impl
::FatalLogCall<false>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 456, "last_output_sample_rate_hz_ == 8000 || last_output_sample_rate_hz_ == 16000 || last_output_sample_rate_hz_ == 32000 || last_output_sample_rate_hz_ == 48000"
) & ::webrtc::webrtc_checks_impl::LogStreamer<>()
454 last_output_sample_rate_hz_ == 16000 ||(last_output_sample_rate_hz_ == 8000 || last_output_sample_rate_hz_
== 16000 || last_output_sample_rate_hz_ == 32000 || last_output_sample_rate_hz_
== 48000) ? static_cast<void>(0) : ::webrtc::webrtc_checks_impl
::FatalLogCall<false>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 456, "last_output_sample_rate_hz_ == 8000 || last_output_sample_rate_hz_ == 16000 || last_output_sample_rate_hz_ == 32000 || last_output_sample_rate_hz_ == 48000"
) & ::webrtc::webrtc_checks_impl::LogStreamer<>()
455 last_output_sample_rate_hz_ == 32000 ||(last_output_sample_rate_hz_ == 8000 || last_output_sample_rate_hz_
== 16000 || last_output_sample_rate_hz_ == 32000 || last_output_sample_rate_hz_
== 48000) ? static_cast<void>(0) : ::webrtc::webrtc_checks_impl
::FatalLogCall<false>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 456, "last_output_sample_rate_hz_ == 8000 || last_output_sample_rate_hz_ == 16000 || last_output_sample_rate_hz_ == 32000 || last_output_sample_rate_hz_ == 48000"
) & ::webrtc::webrtc_checks_impl::LogStreamer<>()
456 last_output_sample_rate_hz_ == 48000)(last_output_sample_rate_hz_ == 8000 || last_output_sample_rate_hz_
== 16000 || last_output_sample_rate_hz_ == 32000 || last_output_sample_rate_hz_
== 48000) ? static_cast<void>(0) : ::webrtc::webrtc_checks_impl
::FatalLogCall<false>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 456, "last_output_sample_rate_hz_ == 8000 || last_output_sample_rate_hz_ == 16000 || last_output_sample_rate_hz_ == 32000 || last_output_sample_rate_hz_ == 48000"
) & ::webrtc::webrtc_checks_impl::LogStreamer<>()
457 << "Unexpected sample rate " << last_output_sample_rate_hz_;
458
459 if (current_sample_rate_hz) {
460 *current_sample_rate_hz = last_output_sample_rate_hz_;
461 }
462
463 return kOK;
464}
465
466void NetEqImpl::SetCodecs(const std::map<int, SdpAudioFormat>& codecs) {
467 const std::vector<int> changed_payload_types =
468 decoder_database_->SetCodecs(codecs);
469 for (const int pt : changed_payload_types) {
470 packet_buffer_->DiscardPacketsWithPayloadType(pt);
471 }
472}
473
474bool NetEqImpl::RegisterPayloadType(int rtp_payload_type,
475 const SdpAudioFormat& audio_format) {
476 RTC_LOG(LS_VERBOSE)!::webrtc::LogMessage::IsNoop<::webrtc::LS_VERBOSE>() &&
::webrtc::webrtc_logging_impl::LogCall() & ::webrtc::webrtc_logging_impl
::LogStreamer<>() << ::webrtc::webrtc_logging_impl
::LogMetadata("./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 476, ::webrtc::LS_VERBOSE)
<< "NetEqImpl::RegisterPayloadType: payload type "
477 << rtp_payload_type << ", codec "
478 << absl::StrCat(audio_format);
479 return decoder_database_->RegisterPayload(rtp_payload_type, audio_format) ==
480 DecoderDatabase::kOK;
481}
482
483bool NetEqImpl::CreateDecoder(int rtp_payload_type) {
484 return decoder_database_->GetDecoder(rtp_payload_type) != nullptr;
485}
486
487int NetEqImpl::RemovePayloadType(uint8_t rtp_payload_type) {
488 int ret = decoder_database_->Remove(rtp_payload_type);
489 if (ret == DecoderDatabase::kOK || ret == DecoderDatabase::kDecoderNotFound) {
490 packet_buffer_->DiscardPacketsWithPayloadType(rtp_payload_type);
491 return kOK;
492 }
493 return kFail;
494}
495
496void NetEqImpl::RemoveAllPayloadTypes() {
497 decoder_database_->RemoveAll();
498}
499
500bool NetEqImpl::SetMinimumDelay(int delay_ms) {
501 if (delay_ms >= 0 && delay_ms <= 10000) {
502 RTC_DCHECK(controller_.get())(controller_.get()) ? static_cast<void>(0) : ::webrtc::
webrtc_checks_impl::FatalLogCall<false>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 502, "controller_.get()") & ::webrtc::webrtc_checks_impl
::LogStreamer<>()
;
503 return controller_->SetMinimumDelay(delay_ms);
504 }
505 return false;
506}
507
508bool NetEqImpl::SetMaximumDelay(int delay_ms) {
509 if (delay_ms >= 0 && delay_ms <= 10000) {
510 RTC_DCHECK(controller_.get())(controller_.get()) ? static_cast<void>(0) : ::webrtc::
webrtc_checks_impl::FatalLogCall<false>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 510, "controller_.get()") & ::webrtc::webrtc_checks_impl
::LogStreamer<>()
;
511 return controller_->SetMaximumDelay(delay_ms);
512 }
513 return false;
514}
515
516bool NetEqImpl::SetBaseMinimumDelayMs(int delay_ms) {
517 if (delay_ms >= 0 && delay_ms <= 10000) {
518 return controller_->SetBaseMinimumDelay(delay_ms);
519 }
520 return false;
521}
522
523int NetEqImpl::GetBaseMinimumDelayMs() const {
524 return controller_->GetBaseMinimumDelay();
525}
526
527int NetEqImpl::TargetDelayMs() const {
528 RTC_DCHECK(controller_.get())(controller_.get()) ? static_cast<void>(0) : ::webrtc::
webrtc_checks_impl::FatalLogCall<false>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 528, "controller_.get()") & ::webrtc::webrtc_checks_impl
::LogStreamer<>()
;
529 return controller_->TargetLevelMs();
530}
531
532int NetEqImpl::FilteredCurrentDelayMs() const {
533 // Sum up the filtered packet buffer level with the future length of the sync
534 // buffer.
535 const int delay_samples =
536 controller_->GetFilteredBufferLevel() + sync_buffer_->FutureLength();
537 // The division below will truncate. The return value is in ms.
538 return delay_samples / CheckedDivExact(fs_hz_, 1000);
539}
540
541int NetEqImpl::NetworkStatistics(NetEqNetworkStatistics* stats) {
542 RTC_DCHECK(decoder_database_.get())(decoder_database_.get()) ? static_cast<void>(0) : ::webrtc
::webrtc_checks_impl::FatalLogCall<false>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 542, "decoder_database_.get()") & ::webrtc::webrtc_checks_impl
::LogStreamer<>()
;
543 *stats = CurrentNetworkStatisticsInternal();
544 stats_->GetNetworkStatistics(decoder_frame_length_, stats);
545 return 0;
546}
547
548NetEqNetworkStatistics NetEqImpl::CurrentNetworkStatistics() const {
549 return CurrentNetworkStatisticsInternal();
550}
551
552NetEqNetworkStatistics NetEqImpl::CurrentNetworkStatisticsInternal() const {
553 RTC_DCHECK(decoder_database_.get())(decoder_database_.get()) ? static_cast<void>(0) : ::webrtc
::webrtc_checks_impl::FatalLogCall<false>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 553, "decoder_database_.get()") & ::webrtc::webrtc_checks_impl
::LogStreamer<>()
;
554 NetEqNetworkStatistics stats;
555 const size_t total_samples_in_buffers =
556 packet_buffer_->NumSamplesInBuffer(decoder_frame_length_) +
557 sync_buffer_->FutureLength();
558
559 RTC_DCHECK(controller_.get())(controller_.get()) ? static_cast<void>(0) : ::webrtc::
webrtc_checks_impl::FatalLogCall<false>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 559, "controller_.get()") & ::webrtc::webrtc_checks_impl
::LogStreamer<>()
;
560 stats.preferred_buffer_size_ms = controller_->TargetLevelMs();
561 stats.jitter_peaks_found = controller_->PeakFound();
562 RTC_DCHECK_GT(fs_hz_, 0)::webrtc::SafeGt((fs_hz_), (0)) ? static_cast<void>(0) :
::webrtc::webrtc_checks_impl::FatalLogCall<true>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 562, "fs_hz_" " " ">" " " "0") & ::webrtc::webrtc_checks_impl
::LogStreamer<>() << (fs_hz_) << (0)
;
563 stats.current_buffer_size_ms =
564 static_cast<uint16_t>(total_samples_in_buffers * 1000 / fs_hz_);
565 return stats;
566}
567
568NetEqLifetimeStatistics NetEqImpl::GetLifetimeStatistics() const {
569 return stats_->GetLifetimeStatistics();
570}
571
572NetEqOperationsAndState NetEqImpl::GetOperationsAndState() const {
573 auto result = stats_->GetOperationsAndState();
574 result.current_buffer_size_ms =
575 (packet_buffer_->NumSamplesInBuffer(decoder_frame_length_) +
576 sync_buffer_->FutureLength()) *
577 1000 / fs_hz_;
578 result.current_frame_size_ms = decoder_frame_length_ * 1000 / fs_hz_;
579 result.next_packet_available = packet_buffer_->PeekNextPacket() &&
580 packet_buffer_->PeekNextPacket()->timestamp ==
581 sync_buffer_->end_timestamp();
582 return result;
583}
584
585std::optional<uint32_t> NetEqImpl::GetPlayoutTimestamp() const {
586 if (first_packet_ || last_mode_ == Mode::kRfc3389Cng ||
587 last_mode_ == Mode::kCodecInternalCng) {
588 // We don't have a valid RTP timestamp until we have decoded our first
589 // RTP packet. Also, the RTP timestamp is not accurate while playing CNG,
590 // which is indicated by returning an empty value.
591 return std::nullopt;
592 }
593 return timestamp_scaler_->ToExternal(playout_timestamp_);
594}
595
596int NetEqImpl::last_output_sample_rate_hz() const {
597 return last_output_sample_rate_hz_;
598}
599
600std::optional<NetEq::DecoderFormat> NetEqImpl::GetCurrentDecoderFormat() const {
601 if (!current_rtp_payload_type_.has_value()) {
602 return std::nullopt;
603 }
604 const DecoderDatabase::DecoderInfo* di =
605 decoder_database_->GetDecoderInfo(*current_rtp_payload_type_);
606 if (di == nullptr) {
607 return std::nullopt;
608 }
609 return DecoderFormat{
610 .payload_type = *current_rtp_payload_type_,
611 .sample_rate_hz = di->SampleRateHz(),
612 .num_channels = dchecked_cast<int>(di->GetDecoder()->Channels()),
613 .sdp_format = di->GetFormat()};
614}
615
616void NetEqImpl::FlushBuffers() {
617 RTC_LOG(LS_VERBOSE)!::webrtc::LogMessage::IsNoop<::webrtc::LS_VERBOSE>() &&
::webrtc::webrtc_logging_impl::LogCall() & ::webrtc::webrtc_logging_impl
::LogStreamer<>() << ::webrtc::webrtc_logging_impl
::LogMetadata("./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 617, ::webrtc::LS_VERBOSE)
<< "FlushBuffers";
618 packet_buffer_->Flush();
619 RTC_DCHECK(sync_buffer_.get())(sync_buffer_.get()) ? static_cast<void>(0) : ::webrtc::
webrtc_checks_impl::FatalLogCall<false>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 619, "sync_buffer_.get()") & ::webrtc::webrtc_checks_impl
::LogStreamer<>()
;
620 RTC_DCHECK(expand_.get())(expand_.get()) ? static_cast<void>(0) : ::webrtc::webrtc_checks_impl
::FatalLogCall<false>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 620, "expand_.get()") & ::webrtc::webrtc_checks_impl::LogStreamer
<>()
;
621 sync_buffer_->Flush();
622 sync_buffer_->set_next_index(sync_buffer_->next_index() -
623 expand_->overlap_length());
624 // Set to wait for new codec.
625 first_packet_ = true;
626}
627
628int NetEqImpl::SyncBufferSizeMs() const {
629 return dchecked_cast<int>(sync_buffer_->FutureLength() /
630 CheckedDivExact(fs_hz_, 1000));
631}
632
633const SyncBuffer* NetEqImpl::sync_buffer_for_test() const {
634 return sync_buffer_.get();
635}
636
637NetEq::Operation NetEqImpl::last_operation_for_test() const {
638 return last_operation_;
639}
640
641// Methods below this line are private.
642
643bool NetEqImpl::MaybeChangePayloadType(uint8_t payload_type) {
644 bool changed = false;
645 if (decoder_database_->IsComfortNoise(payload_type)) {
646 if (current_cng_rtp_payload_type_ &&
647 *current_cng_rtp_payload_type_ != payload_type) {
648 // New CNG payload type implies new codec type.
649 current_rtp_payload_type_ = std::nullopt;
650 changed = true;
651 }
652 current_cng_rtp_payload_type_ = payload_type;
653 } else if (!decoder_database_->IsDtmf(payload_type)) {
654 // This must be speech.
655 if ((current_rtp_payload_type_ &&
656 *current_rtp_payload_type_ != payload_type) ||
657 (current_cng_rtp_payload_type_ &&
658 !EqualSampleRates(payload_type, *current_cng_rtp_payload_type_,
659 *decoder_database_))) {
660 current_cng_rtp_payload_type_ = std::nullopt;
661 changed = true;
662 }
663 current_rtp_payload_type_ = payload_type;
664 }
665 return changed;
666}
667
668int NetEqImpl::GetAudioInternal(AudioFrame* audio_frame,
669 std::optional<Operation> action_override) {
670 PacketList packet_list;
671 DtmfEvent dtmf_event;
672 Operation operation;
673 bool play_dtmf;
674 last_decoded_packet_infos_.clear();
675 tick_timer_->Increment();
676
677 // Sanity check - should already be taken care of when setting
678 // output_size_samples_.
679 RTC_DCHECK_LE(output_size_samples_ * sync_buffer_->Channels(),::webrtc::SafeLe((output_size_samples_ * sync_buffer_->Channels
()), (AudioFrame::kMaxDataSizeSamples)) ? static_cast<void
>(0) : ::webrtc::webrtc_checks_impl::FatalLogCall<true>
( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 680, "output_size_samples_ * sync_buffer_->Channels()" " "
"<=" " " "AudioFrame::kMaxDataSizeSamples") & ::webrtc
::webrtc_checks_impl::LogStreamer<>() << (output_size_samples_
* sync_buffer_->Channels()) << (AudioFrame::kMaxDataSizeSamples
)
680 AudioFrame::kMaxDataSizeSamples)::webrtc::SafeLe((output_size_samples_ * sync_buffer_->Channels
()), (AudioFrame::kMaxDataSizeSamples)) ? static_cast<void
>(0) : ::webrtc::webrtc_checks_impl::FatalLogCall<true>
( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 680, "output_size_samples_ * sync_buffer_->Channels()" " "
"<=" " " "AudioFrame::kMaxDataSizeSamples") & ::webrtc
::webrtc_checks_impl::LogStreamer<>() << (output_size_samples_
* sync_buffer_->Channels()) << (AudioFrame::kMaxDataSizeSamples
)
;
681
682 // Check for muted state.
683 if (enable_muted_state_ && expand_->Muted() && packet_buffer_->Empty()) {
684 RTC_DCHECK_EQ(last_mode_, Mode::kExpand)::webrtc::SafeEq((last_mode_), (Mode::kExpand)) ? static_cast
<void>(0) : ::webrtc::webrtc_checks_impl::FatalLogCall<
true>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 684, "last_mode_" " " "==" " " "Mode::kExpand") & ::webrtc
::webrtc_checks_impl::LogStreamer<>() << (last_mode_
) << (Mode::kExpand)
;
685 audio_frame->Reset();
686 RTC_DCHECK(audio_frame->muted())(audio_frame->muted()) ? static_cast<void>(0) : ::webrtc
::webrtc_checks_impl::FatalLogCall<false>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 686, "audio_frame->muted()") & ::webrtc::webrtc_checks_impl
::LogStreamer<>()
; // Reset() should mute the frame.
687 playout_timestamp_ += static_cast<uint32_t>(output_size_samples_);
688 audio_frame->sample_rate_hz_ = fs_hz_;
689 audio_frame->samples_per_channel_ = output_size_samples_;
690 audio_frame->timestamp_ =
691 first_packet_
692 ? 0
693 : timestamp_scaler_->ToExternal(playout_timestamp_) -
694 static_cast<uint32_t>(audio_frame->samples_per_channel_);
695 audio_frame->num_channels_ = sync_buffer_->Channels();
696 stats_->ExpandedNoiseSamples(output_size_samples_, false);
697 controller_->NotifyMutedState();
698 return 0;
699 }
700 int return_value = GetDecision(&operation, &packet_list, &dtmf_event,
701 &play_dtmf, action_override);
702 if (return_value != 0) {
703 last_mode_ = Mode::kError;
704 return return_value;
705 }
706
707 AudioDecoder::SpeechType speech_type;
708 int length = 0;
709 const size_t start_num_packets = packet_list.size();
710 int decode_return_value =
711 Decode(&packet_list, &operation, &length, &speech_type);
712 if (length > 0) {
713 last_decoded_type_ = speech_type;
714 }
715
716 bool sid_frame_available =
717 (operation == Operation::kRfc3389Cng && !packet_list.empty());
718
719 // This is the criterion that we did decode some data through the speech
720 // decoder, and the operation resulted in comfort noise.
721 const bool codec_internal_sid_frame =
722 (speech_type == AudioDecoder::kComfortNoise &&
723 start_num_packets > packet_list.size());
724
725 if (sid_frame_available || codec_internal_sid_frame) {
726 // Start a new stopwatch since we are decoding a new CNG packet.
727 generated_noise_stopwatch_ = tick_timer_->GetNewStopwatch();
728 }
729
730 algorithm_buffer_->Clear();
731 switch (operation) {
732 case Operation::kNormal: {
733 DoNormal(decoded_buffer_.get(), length, speech_type, play_dtmf);
734 if (length > 0) {
735 stats_->DecodedOutputPlayed();
736 }
737 break;
738 }
739 case Operation::kMerge: {
740 DoMerge(decoded_buffer_.get(), length, speech_type, play_dtmf);
741 break;
742 }
743 case Operation::kExpand: {
744 RTC_DCHECK_EQ(return_value, 0)::webrtc::SafeEq((return_value), (0)) ? static_cast<void>
(0) : ::webrtc::webrtc_checks_impl::FatalLogCall<true>(
"./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 744, "return_value" " " "==" " " "0") & ::webrtc::webrtc_checks_impl
::LogStreamer<>() << (return_value) << (0)
;
745 if (!current_rtp_payload_type_ || !DoCodecPlc()) {
746 return_value = DoExpand(play_dtmf);
747 }
748 RTC_DCHECK_GE(sync_buffer_->FutureLength() - expand_->overlap_length(),::webrtc::SafeGe((sync_buffer_->FutureLength() - expand_->
overlap_length()), (output_size_samples_)) ? static_cast<void
>(0) : ::webrtc::webrtc_checks_impl::FatalLogCall<true>
( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 749, "sync_buffer_->FutureLength() - expand_->overlap_length()"
" " ">=" " " "output_size_samples_") & ::webrtc::webrtc_checks_impl
::LogStreamer<>() << (sync_buffer_->FutureLength
() - expand_->overlap_length()) << (output_size_samples_
)
749 output_size_samples_)::webrtc::SafeGe((sync_buffer_->FutureLength() - expand_->
overlap_length()), (output_size_samples_)) ? static_cast<void
>(0) : ::webrtc::webrtc_checks_impl::FatalLogCall<true>
( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 749, "sync_buffer_->FutureLength() - expand_->overlap_length()"
" " ">=" " " "output_size_samples_") & ::webrtc::webrtc_checks_impl
::LogStreamer<>() << (sync_buffer_->FutureLength
() - expand_->overlap_length()) << (output_size_samples_
)
;
750 break;
751 }
752 case Operation::kAccelerate:
753 case Operation::kFastAccelerate: {
754 const bool fast_accelerate =
755 enable_fast_accelerate_ && (operation == Operation::kFastAccelerate);
756 return_value = DoAccelerate(decoded_buffer_.get(), length, speech_type,
757 play_dtmf, fast_accelerate);
758 break;
759 }
760 case Operation::kPreemptiveExpand: {
761 return_value = DoPreemptiveExpand(decoded_buffer_.get(), length,
762 speech_type, play_dtmf);
763 break;
764 }
765 case Operation::kRfc3389Cng:
766 case Operation::kRfc3389CngNoPacket: {
767 return_value = DoRfc3389Cng(&packet_list, play_dtmf);
768 break;
769 }
770 case Operation::kCodecInternalCng: {
771 // This handles the case when there is no transmission and the decoder
772 // should produce internal comfort noise.
773 // TODO(hlundin): Write test for codec-internal CNG.
774 DoCodecInternalCng(decoded_buffer_.get(), length);
775 break;
776 }
777 case Operation::kDtmf: {
778 // TODO(hlundin): Write test for this.
779 return_value = DoDtmf(dtmf_event, &play_dtmf);
780 break;
781 }
782 case Operation::kUndefined: {
783 RTC_LOG(LS_ERROR)!::webrtc::LogMessage::IsNoop<::webrtc::LS_ERROR>() &&
::webrtc::webrtc_logging_impl::LogCall() & ::webrtc::webrtc_logging_impl
::LogStreamer<>() << ::webrtc::webrtc_logging_impl
::LogMetadata("./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 783, ::webrtc::LS_ERROR)
<< "Invalid operation kUndefined.";
784 RTC_DCHECK_NOTREACHED()(false) ? static_cast<void>(0) : ::webrtc::webrtc_checks_impl
::FatalLogCall<false>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 784, "false") & ::webrtc::webrtc_checks_impl::LogStreamer
<>()
; // This should not happen.
785 last_mode_ = Mode::kError;
786 return kInvalidOperation;
787 }
788 } // End of switch.
789 last_operation_ = operation;
790 if (return_value < 0) {
791 return return_value;
792 }
793
794 if (last_mode_ != Mode::kRfc3389Cng) {
795 comfort_noise_->Reset();
796 }
797
798 // We treat it as if all packets referenced to by `last_decoded_packet_infos_`
799 // were mashed together when creating the samples in `algorithm_buffer_`.
800 RtpPacketInfos packet_infos(last_decoded_packet_infos_);
801
802 // Copy samples from `algorithm_buffer_` to `sync_buffer_`.
803 //
804 // TODO(bugs.webrtc.org/10757):
805 // We would in the future also like to pass `packet_infos` so that we can do
806 // sample-perfect tracking of that information across `sync_buffer_`.
807 sync_buffer_->PushBack(*algorithm_buffer_);
808
809 // Extract data from `sync_buffer_` to `output`.
810 audio_frame->ResetWithoutMuting();
811 audio_frame->SetSampleRateAndChannelSize(fs_hz_);
812 InterleavedView<int16_t> view =
813 audio_frame->mutable_data(output_size_samples_, sync_buffer_->Channels());
814 bool got_audio = sync_buffer_->GetNextAudioInterleaved(view);
815
816 // TODO(bugs.webrtc.org/10757):
817 // We don't have the ability to properly track individual packets once their
818 // audio samples have entered `sync_buffer_`. So for now, treat it as if
819 // `packet_infos` from packets decoded by the current `GetAudioInternal()`
820 // call were all consumed assembling the current audio frame and the current
821 // audio frame only.
822 audio_frame->packet_infos_ = std::move(packet_infos);
823 if (sync_buffer_->FutureLength() < expand_->overlap_length()) {
824 // The sync buffer should always contain `overlap_length` samples, but now
825 // too many samples have been extracted. Reinstall the `overlap_length`
826 // lookahead by moving the index.
827 const size_t missing_lookahead_samples =
828 expand_->overlap_length() - sync_buffer_->FutureLength();
829 RTC_DCHECK_GE(sync_buffer_->next_index(), missing_lookahead_samples)::webrtc::SafeGe((sync_buffer_->next_index()), (missing_lookahead_samples
)) ? static_cast<void>(0) : ::webrtc::webrtc_checks_impl
::FatalLogCall<true>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 829, "sync_buffer_->next_index()" " " ">=" " " "missing_lookahead_samples"
) & ::webrtc::webrtc_checks_impl::LogStreamer<>() <<
(sync_buffer_->next_index()) << (missing_lookahead_samples
)
;
830 sync_buffer_->set_next_index(sync_buffer_->next_index() -
831 missing_lookahead_samples);
832 }
833
834 if (!got_audio) {
835 RTC_LOG(LS_ERROR)!::webrtc::LogMessage::IsNoop<::webrtc::LS_ERROR>() &&
::webrtc::webrtc_logging_impl::LogCall() & ::webrtc::webrtc_logging_impl
::LogStreamer<>() << ::webrtc::webrtc_logging_impl
::LogMetadata("./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 835, ::webrtc::LS_ERROR)
<< "audio_frame->samples_per_channel_ ("
836 << audio_frame->samples_per_channel_
837 << ") != output_size_samples_ (" << output_size_samples_
838 << ")";
839 // TODO(minyue): treatment of under-run, filling zeros
840 audio_frame->Mute();
841 return kSampleUnderrun;
842 }
843
844 // Should always have overlap samples left in the `sync_buffer_`.
845 RTC_DCHECK_GE(sync_buffer_->FutureLength(), expand_->overlap_length())::webrtc::SafeGe((sync_buffer_->FutureLength()), (expand_->
overlap_length())) ? static_cast<void>(0) : ::webrtc::webrtc_checks_impl
::FatalLogCall<true>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 845, "sync_buffer_->FutureLength()" " " ">=" " " "expand_->overlap_length()"
) & ::webrtc::webrtc_checks_impl::LogStreamer<>() <<
(sync_buffer_->FutureLength()) << (expand_->overlap_length
())
;
846
847 // TODO(yujo): For muted frames, this can be a copy rather than an addition.
848 if (play_dtmf) {
849 return_value = DtmfOverdub(dtmf_event, sync_buffer_->Channels(),
850 audio_frame->mutable_data());
851 }
852
853 // Update the background noise parameters if last operation wrote data
854 // straight from the decoder to the `sync_buffer_`. That is, none of the
855 // operations that modify the signal can be followed by a parameter update.
856 if ((last_mode_ == Mode::kNormal) || (last_mode_ == Mode::kAccelerateFail) ||
857 (last_mode_ == Mode::kPreemptiveExpandFail) ||
858 (last_mode_ == Mode::kRfc3389Cng) ||
859 (last_mode_ == Mode::kCodecInternalCng)) {
860 background_noise_->Update(*sync_buffer_);
861 }
862
863 if (operation == Operation::kDtmf) {
864 // DTMF data was written the end of `sync_buffer_`.
865 // Update index to end of DTMF data in `sync_buffer_`.
866 sync_buffer_->set_dtmf_index(sync_buffer_->Size());
867 }
868
869 if (last_mode_ != Mode::kExpand && last_mode_ != Mode::kCodecPlc) {
870 // If last operation was not expand, calculate the `playout_timestamp_` from
871 // the `sync_buffer_`. However, do not update the `playout_timestamp_` if it
872 // would be moved "backwards".
873 uint32_t temp_timestamp =
874 sync_buffer_->end_timestamp() -
875 static_cast<uint32_t>(sync_buffer_->FutureLength());
876 if (static_cast<int32_t>(temp_timestamp - playout_timestamp_) > 0) {
877 playout_timestamp_ = temp_timestamp;
878 }
879 } else {
880 // Use dead reckoning to estimate the `playout_timestamp_`.
881 playout_timestamp_ += static_cast<uint32_t>(output_size_samples_);
882 }
883 // Set the timestamp in the audio frame to zero before the first packet has
884 // been inserted. Otherwise, subtract the frame size in samples to get the
885 // timestamp of the first sample in the frame (playout_timestamp_ is the
886 // last + 1).
887 audio_frame->timestamp_ =
888 first_packet_
889 ? 0
890 : timestamp_scaler_->ToExternal(playout_timestamp_) -
891 static_cast<uint32_t>(audio_frame->samples_per_channel_);
892
893 if (!(last_mode_ == Mode::kRfc3389Cng ||
894 last_mode_ == Mode::kCodecInternalCng || last_mode_ == Mode::kExpand ||
895 last_mode_ == Mode::kCodecPlc)) {
896 generated_noise_stopwatch_.reset();
897 }
898
899 if (decode_return_value)
900 return decode_return_value;
901 return return_value;
902}
903
904int NetEqImpl::GetDecision(Operation* operation,
905 PacketList* packet_list,
906 DtmfEvent* dtmf_event,
907 bool* play_dtmf,
908 std::optional<Operation> action_override) {
909 // Initialize output variables.
910 *play_dtmf = false;
911 *operation = Operation::kUndefined;
912
913 RTC_DCHECK(sync_buffer_.get())(sync_buffer_.get()) ? static_cast<void>(0) : ::webrtc::
webrtc_checks_impl::FatalLogCall<false>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 913, "sync_buffer_.get()") & ::webrtc::webrtc_checks_impl
::LogStreamer<>()
;
914 uint32_t end_timestamp = sync_buffer_->end_timestamp();
915 if (!new_codec_) {
916 const uint32_t five_seconds_samples = 5 * fs_hz_;
917 packet_buffer_->DiscardOldPackets(end_timestamp, five_seconds_samples);
918 }
919 const Packet* packet = packet_buffer_->PeekNextPacket();
920
921 RTC_DCHECK(!generated_noise_stopwatch_ ||(!generated_noise_stopwatch_ || generated_noise_stopwatch_->
ElapsedTicks() >= 1) ? static_cast<void>(0) : ::webrtc
::webrtc_checks_impl::FatalLogCall<false>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 922, "!generated_noise_stopwatch_ || generated_noise_stopwatch_->ElapsedTicks() >= 1"
) & ::webrtc::webrtc_checks_impl::LogStreamer<>()
922 generated_noise_stopwatch_->ElapsedTicks() >= 1)(!generated_noise_stopwatch_ || generated_noise_stopwatch_->
ElapsedTicks() >= 1) ? static_cast<void>(0) : ::webrtc
::webrtc_checks_impl::FatalLogCall<false>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 922, "!generated_noise_stopwatch_ || generated_noise_stopwatch_->ElapsedTicks() >= 1"
) & ::webrtc::webrtc_checks_impl::LogStreamer<>()
;
923 uint64_t generated_noise_samples =
924 generated_noise_stopwatch_ ? (generated_noise_stopwatch_->ElapsedTicks() -
925 1) * output_size_samples_ +
926 controller_->noise_fast_forward()
927 : 0;
928
929 if (last_mode_ == Mode::kRfc3389Cng) {
930 // Because of timestamp peculiarities, we have to "manually" disallow using
931 // a CNG packet with the same timestamp as the one that was last played.
932 // This can happen when using redundancy and will cause the timing to shift.
933 while (packet && decoder_database_->IsComfortNoise(packet->payload_type) &&
934 (end_timestamp >= packet->timestamp ||
935 end_timestamp + generated_noise_samples > packet->timestamp)) {
936 // Don't use this packet, discard it.
937 if (packet_buffer_->DiscardNextPacket() != PacketBuffer::kOK) {
938 RTC_DCHECK_NOTREACHED()(false) ? static_cast<void>(0) : ::webrtc::webrtc_checks_impl
::FatalLogCall<false>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 938, "false") & ::webrtc::webrtc_checks_impl::LogStreamer
<>()
; // Must be ok by design.
939 }
940 // Check buffer again.
941 if (!new_codec_) {
942 packet_buffer_->DiscardOldPackets(end_timestamp, 5 * fs_hz_);
943 }
944 packet = packet_buffer_->PeekNextPacket();
945 }
946 }
947
948 RTC_DCHECK(expand_.get())(expand_.get()) ? static_cast<void>(0) : ::webrtc::webrtc_checks_impl
::FatalLogCall<false>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 948, "expand_.get()") & ::webrtc::webrtc_checks_impl::LogStreamer
<>()
;
949 const int samples_left = static_cast<int>(sync_buffer_->FutureLength() -
950 expand_->overlap_length());
951 if (last_mode_ == Mode::kAccelerateSuccess ||
952 last_mode_ == Mode::kAccelerateLowEnergy ||
953 last_mode_ == Mode::kPreemptiveExpandSuccess ||
954 last_mode_ == Mode::kPreemptiveExpandLowEnergy) {
955 // Subtract (samples_left + output_size_samples_) from sampleMemory.
956 controller_->AddSampleMemory(
957 -(samples_left + dchecked_cast<int>(output_size_samples_)));
958 }
959
960 // Check if it is time to play a DTMF event.
961 if (dtmf_buffer_->GetEvent(
962 static_cast<uint32_t>(end_timestamp + generated_noise_samples),
963 dtmf_event)) {
964 *play_dtmf = true;
965 }
966
967 // Get instruction.
968 RTC_DCHECK(sync_buffer_.get())(sync_buffer_.get()) ? static_cast<void>(0) : ::webrtc::
webrtc_checks_impl::FatalLogCall<false>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 968, "sync_buffer_.get()") & ::webrtc::webrtc_checks_impl
::LogStreamer<>()
;
969 RTC_DCHECK(expand_.get())(expand_.get()) ? static_cast<void>(0) : ::webrtc::webrtc_checks_impl
::FatalLogCall<false>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 969, "expand_.get()") & ::webrtc::webrtc_checks_impl::LogStreamer
<>()
;
970 generated_noise_samples =
971 generated_noise_stopwatch_
972 ? generated_noise_stopwatch_->ElapsedTicks() * output_size_samples_ +
973 controller_->noise_fast_forward()
974 : 0;
975 NetEqController::NetEqStatus status;
976 status.packet_buffer_info.dtx_or_cng =
977 packet_buffer_->ContainsDtxOrCngPacket(decoder_database_.get());
978 status.packet_buffer_info.num_samples =
979 packet_buffer_->NumSamplesInBuffer(decoder_frame_length_);
980 status.packet_buffer_info.span_samples = packet_buffer_->GetSpanSamples(
981 decoder_frame_length_, last_output_sample_rate_hz_, false);
982 status.packet_buffer_info.span_samples_wait_time =
983 packet_buffer_->GetSpanSamples(decoder_frame_length_,
984 last_output_sample_rate_hz_, true);
985 status.packet_buffer_info.num_packets = packet_buffer_->NumPacketsInBuffer();
986 status.target_timestamp = sync_buffer_->end_timestamp();
987 status.expand_mutefactor = expand_->MuteFactor(0);
988 status.last_packet_samples = decoder_frame_length_;
989 status.last_mode = last_mode_;
990 status.play_dtmf = *play_dtmf;
991 status.generated_noise_samples = generated_noise_samples;
992 status.sync_buffer_samples = sync_buffer_->FutureLength();
993 if (packet) {
994 status.next_packet = {
995 .timestamp = packet->timestamp,
996 .is_dtx = packet->frame && packet->frame->IsDtxPacket(),
997 .is_cng = decoder_database_->IsComfortNoise(packet->payload_type)};
998 }
999 *operation = controller_->GetDecision(status, &reset_decoder_);
1000
1001 // Disallow time stretching if this packet is DTX, because such a decision may
1002 // be based on earlier buffer level estimate, as we do not update buffer level
1003 // during DTX. When we have a better way to update buffer level during DTX,
1004 // this can be discarded.
1005 if (packet && packet->frame && packet->frame->IsDtxPacket() &&
1006 (*operation == Operation::kMerge ||
1007 *operation == Operation::kAccelerate ||
1008 *operation == Operation::kFastAccelerate ||
1009 *operation == Operation::kPreemptiveExpand)) {
1010 *operation = Operation::kNormal;
1011 }
1012
1013 if (action_override) {
1014 // Use the provided action instead of the decision NetEq decided on.
1015 *operation = *action_override;
1016 }
1017 // Check if we already have enough samples in the `sync_buffer_`. If so,
1018 // change decision to normal, unless the decision was merge, accelerate, or
1019 // preemptive expand.
1020 if (samples_left >= dchecked_cast<int>(output_size_samples_) &&
1021 *operation != Operation::kMerge && *operation != Operation::kAccelerate &&
1022 *operation != Operation::kFastAccelerate &&
1023 *operation != Operation::kPreemptiveExpand) {
1024 *operation = Operation::kNormal;
1025 return 0;
1026 }
1027
1028 controller_->ExpandDecision(*operation);
1029 if ((last_mode_ == Mode::kCodecPlc) && (*operation != Operation::kExpand)) {
1030 // Getting out of the PLC expand mode, reporting interruptions.
1031 // NetEq PLC reports this metrics in expand.cc
1032 stats_->EndExpandEvent(fs_hz_);
1033 }
1034
1035 // Check conditions for reset.
1036 if (new_codec_ || *operation == Operation::kUndefined) {
1037 // The only valid reason to get kUndefined is that new_codec_ is set.
1038 RTC_DCHECK(new_codec_)(new_codec_) ? static_cast<void>(0) : ::webrtc::webrtc_checks_impl
::FatalLogCall<false>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 1038, "new_codec_") & ::webrtc::webrtc_checks_impl::LogStreamer
<>()
;
1039 if (*play_dtmf && !packet) {
1040 timestamp_ = dtmf_event->timestamp;
1041 } else {
1042 if (!packet) {
1043 RTC_LOG(LS_ERROR)!::webrtc::LogMessage::IsNoop<::webrtc::LS_ERROR>() &&
::webrtc::webrtc_logging_impl::LogCall() & ::webrtc::webrtc_logging_impl
::LogStreamer<>() << ::webrtc::webrtc_logging_impl
::LogMetadata("./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 1043, ::webrtc::LS_ERROR)
<< "Packet missing where it shouldn't.";
1044 return -1;
1045 }
1046 timestamp_ = packet->timestamp;
1047 if (*operation == Operation::kRfc3389CngNoPacket &&
1048 decoder_database_->IsComfortNoise(packet->payload_type)) {
1049 // Change decision to CNG packet, since we do have a CNG packet, but it
1050 // was considered too early to use. Now, use it anyway.
1051 *operation = Operation::kRfc3389Cng;
1052 } else if (*operation != Operation::kRfc3389Cng) {
1053 *operation = Operation::kNormal;
1054 }
1055 }
1056 // Adjust `sync_buffer_` timestamp before setting `end_timestamp` to the
1057 // new value.
1058 sync_buffer_->IncreaseEndTimestamp(timestamp_ - end_timestamp);
1059 end_timestamp = timestamp_;
1060 new_codec_ = false;
1061 controller_->SoftReset();
1062 stats_->ResetMcu();
1063 }
1064
1065 size_t required_samples = output_size_samples_;
1066 const size_t samples_10_ms = static_cast<size_t>(80 * fs_mult_);
1067 const size_t samples_20_ms = 2 * samples_10_ms;
1068 const size_t samples_30_ms = 3 * samples_10_ms;
1069
1070 switch (*operation) {
1071 case Operation::kExpand: {
1072 timestamp_ = end_timestamp;
1073 return 0;
1074 }
1075 case Operation::kRfc3389CngNoPacket:
1076 case Operation::kCodecInternalCng: {
1077 return 0;
1078 }
1079 case Operation::kDtmf: {
1080 // TODO(hlundin): Write test for this.
1081 // Update timestamp.
1082 timestamp_ = end_timestamp;
1083 generated_noise_samples =
1084 generated_noise_stopwatch_
1085 ? generated_noise_stopwatch_->ElapsedTicks() *
1086 output_size_samples_ +
1087 controller_->noise_fast_forward()
1088 : 0;
1089 if (generated_noise_samples > 0 && last_mode_ != Mode::kDtmf) {
1090 // Make a jump in timestamp due to the recently played comfort noise.
1091 uint32_t timestamp_jump =
1092 static_cast<uint32_t>(generated_noise_samples);
1093 sync_buffer_->IncreaseEndTimestamp(timestamp_jump);
1094 timestamp_ += timestamp_jump;
1095 }
1096 return 0;
1097 }
1098 case Operation::kAccelerate:
1099 case Operation::kFastAccelerate: {
1100 // In order to do an accelerate we need at least 30 ms of audio data.
1101 if (samples_left >= static_cast<int>(samples_30_ms)) {
1102 // Already have enough data, so we do not need to extract any more.
1103 controller_->set_sample_memory(samples_left);
1104 controller_->set_prev_time_scale(true);
1105 return 0;
1106 } else if (samples_left >= static_cast<int>(samples_10_ms) &&
1107 decoder_frame_length_ >= samples_30_ms) {
1108 // Avoid decoding more data as it might overflow the playout buffer.
1109 *operation = Operation::kNormal;
1110 return 0;
1111 } else if (samples_left < static_cast<int>(samples_20_ms) &&
1112 decoder_frame_length_ < samples_30_ms) {
1113 // Build up decoded data by decoding at least 20 ms of audio data. Do
1114 // not perform accelerate yet, but wait until we only need to do one
1115 // decoding.
1116 required_samples = 2 * output_size_samples_;
1117 *operation = Operation::kNormal;
1118 }
1119 // If none of the above is true, we have one of two possible situations:
1120 // (1) 20 ms <= samples_left < 30 ms and decoder_frame_length_ < 30 ms; or
1121 // (2) samples_left < 10 ms and decoder_frame_length_ >= 30 ms.
1122 // In either case, we move on with the accelerate decision, and decode one
1123 // frame now.
1124 break;
1125 }
1126 case Operation::kPreemptiveExpand: {
1127 // In order to do a preemptive expand we need at least 30 ms of decoded
1128 // audio data.
1129 if ((samples_left >= static_cast<int>(samples_30_ms)) ||
1130 (samples_left >= static_cast<int>(samples_10_ms) &&
1131 decoder_frame_length_ >= samples_30_ms)) {
1132 // Already have enough data, so we do not need to extract any more.
1133 // Or, avoid decoding more data as it might overflow the playout buffer.
1134 // Still try preemptive expand, though.
1135 controller_->set_sample_memory(samples_left);
1136 controller_->set_prev_time_scale(true);
1137 return 0;
1138 }
1139 if (samples_left < static_cast<int>(samples_20_ms) &&
1140 decoder_frame_length_ < samples_30_ms) {
1141 // Build up decoded data by decoding at least 20 ms of audio data.
1142 // Still try to perform preemptive expand.
1143 required_samples = 2 * output_size_samples_;
1144 }
1145 // Move on with the preemptive expand decision.
1146 break;
1147 }
1148 case Operation::kMerge: {
1149 required_samples =
1150 std::max(merge_->RequiredFutureSamples(), required_samples);
1151 break;
1152 }
1153 default: {
1154 // Do nothing.
1155 }
1156 }
1157
1158 // Get packets from buffer.
1159 int extracted_samples = 0;
1160 if (packet) {
1161 sync_buffer_->IncreaseEndTimestamp(packet->timestamp - end_timestamp);
1162 extracted_samples = ExtractPackets(required_samples, packet_list);
1163 if (extracted_samples < 0) {
1164 return kPacketBufferCorruption;
1165 }
1166 }
1167
1168 if (*operation == Operation::kAccelerate ||
1169 *operation == Operation::kFastAccelerate ||
1170 *operation == Operation::kPreemptiveExpand) {
1171 controller_->set_sample_memory(samples_left + extracted_samples);
1172 controller_->set_prev_time_scale(true);
1173 }
1174
1175 if (*operation == Operation::kAccelerate ||
1176 *operation == Operation::kFastAccelerate) {
1177 // Check that we have enough data (30ms) to do accelerate.
1178 if (extracted_samples + samples_left < static_cast<int>(samples_30_ms)) {
1179 // TODO(hlundin): Write test for this.
1180 // Not enough, do normal operation instead.
1181 *operation = Operation::kNormal;
1182 }
1183 }
1184
1185 timestamp_ = sync_buffer_->end_timestamp();
1186 return 0;
1187}
1188
1189int NetEqImpl::Decode(PacketList* packet_list,
1190 Operation* operation,
1191 int* decoded_length,
1192 AudioDecoder::SpeechType* speech_type) {
1193 *speech_type = AudioDecoder::kSpeech;
1194
1195 // When packet_list is empty, we may be in kCodecInternalCng mode, and for
1196 // that we use current active decoder.
1197 AudioDecoder* decoder = decoder_database_->GetActiveDecoder();
1198
1199 if (!packet_list->empty()) {
1200 const Packet& packet = packet_list->front();
1201 uint8_t payload_type = packet.payload_type;
1202 if (!decoder_database_->IsComfortNoise(payload_type)) {
1203 decoder = decoder_database_->GetDecoder(payload_type);
1204 RTC_DCHECK(decoder)(decoder) ? static_cast<void>(0) : ::webrtc::webrtc_checks_impl
::FatalLogCall<false>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 1204, "decoder") & ::webrtc::webrtc_checks_impl::LogStreamer
<>()
;
1205 if (!decoder) {
1206 RTC_LOG(LS_WARNING)!::webrtc::LogMessage::IsNoop<::webrtc::LS_WARNING>() &&
::webrtc::webrtc_logging_impl::LogCall() & ::webrtc::webrtc_logging_impl
::LogStreamer<>() << ::webrtc::webrtc_logging_impl
::LogMetadata("./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 1206, ::webrtc::LS_WARNING)
1207 << "Unknown payload type " << static_cast<int>(payload_type);
1208 packet_list->clear();
1209 return kDecoderNotFound;
1210 }
1211 bool decoder_changed;
1212 decoder_database_->SetActiveDecoder(payload_type, &decoder_changed);
1213 if (decoder_changed) {
1214 // We have a new decoder. Re-init some values.
1215 const DecoderDatabase::DecoderInfo* decoder_info =
1216 decoder_database_->GetDecoderInfo(payload_type);
1217 RTC_DCHECK(decoder_info)(decoder_info) ? static_cast<void>(0) : ::webrtc::webrtc_checks_impl
::FatalLogCall<false>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 1217, "decoder_info") & ::webrtc::webrtc_checks_impl::LogStreamer
<>()
;
1218 if (!decoder_info) {
1219 RTC_LOG(LS_WARNING)!::webrtc::LogMessage::IsNoop<::webrtc::LS_WARNING>() &&
::webrtc::webrtc_logging_impl::LogCall() & ::webrtc::webrtc_logging_impl
::LogStreamer<>() << ::webrtc::webrtc_logging_impl
::LogMetadata("./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 1219, ::webrtc::LS_WARNING)
1220 << "Unknown payload type " << static_cast<int>(payload_type);
1221 packet_list->clear();
1222 return kDecoderNotFound;
1223 }
1224 // If sampling rate or number of channels has changed, we need to make
1225 // a reset.
1226 if (decoder_info->SampleRateHz() != fs_hz_ ||
1227 decoder->Channels() != algorithm_buffer_->Channels()) {
1228 SetSampleRateAndChannels(decoder_info->SampleRateHz(),
1229 decoder->Channels());
1230 }
1231 sync_buffer_->set_end_timestamp(timestamp_);
1232 playout_timestamp_ = timestamp_;
1233 }
1234 }
1235 }
1236
1237 if (reset_decoder_) {
1238 // TODO(hlundin): Write test for this.
1239 if (decoder)
1240 decoder->Reset();
1241
1242 // Reset comfort noise decoder.
1243 ComfortNoiseDecoder* cng_decoder = decoder_database_->GetActiveCngDecoder();
1244 if (cng_decoder)
1245 cng_decoder->Reset();
1246
1247 reset_decoder_ = false;
1248 }
1249
1250 *decoded_length = 0;
1251 // Update codec-internal PLC state.
1252 if ((*operation == Operation::kMerge) && decoder && decoder->HasDecodePlc()) {
1253 decoder->DecodePlc(1, &decoded_buffer_[*decoded_length]);
1254 }
1255
1256 int return_value;
1257 if (*operation == Operation::kCodecInternalCng) {
1258 RTC_DCHECK(packet_list->empty())(packet_list->empty()) ? static_cast<void>(0) : ::webrtc
::webrtc_checks_impl::FatalLogCall<false>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 1258, "packet_list->empty()") & ::webrtc::webrtc_checks_impl
::LogStreamer<>()
;
1259 return_value = DecodeCng(decoder, decoded_length, speech_type);
1260 } else {
1261 return_value = DecodeLoop(packet_list, *operation, decoder, decoded_length,
1262 speech_type);
1263 }
1264
1265 if (*decoded_length < 0) {
1266 // Error returned from the decoder.
1267 *decoded_length = 0;
1268 sync_buffer_->IncreaseEndTimestamp(
1269 static_cast<uint32_t>(decoder_frame_length_));
1270 int error_code = 0;
1271 if (decoder)
1272 error_code = decoder->ErrorCode();
1273 if (error_code != 0) {
1274 // Got some error code from the decoder.
1275 return_value = kDecoderErrorCode;
1276 RTC_LOG(LS_WARNING)!::webrtc::LogMessage::IsNoop<::webrtc::LS_WARNING>() &&
::webrtc::webrtc_logging_impl::LogCall() & ::webrtc::webrtc_logging_impl
::LogStreamer<>() << ::webrtc::webrtc_logging_impl
::LogMetadata("./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 1276, ::webrtc::LS_WARNING)
<< "Decoder returned error code: " << error_code;
1277 } else {
1278 // Decoder does not implement error codes. Return generic error.
1279 return_value = kOtherDecoderError;
1280 RTC_LOG(LS_WARNING)!::webrtc::LogMessage::IsNoop<::webrtc::LS_WARNING>() &&
::webrtc::webrtc_logging_impl::LogCall() & ::webrtc::webrtc_logging_impl
::LogStreamer<>() << ::webrtc::webrtc_logging_impl
::LogMetadata("./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 1280, ::webrtc::LS_WARNING)
<< "Decoder error (no error code)";
1281 }
1282 *operation = Operation::kExpand; // Do expansion to get data instead.
1283 }
1284 if (*speech_type != AudioDecoder::kComfortNoise) {
1285 // Don't increment timestamp if codec returned CNG speech type
1286 // since in this case, the we will increment the CNGplayedTS counter.
1287 // Increase with number of samples per channel.
1288 RTC_DCHECK(*decoded_length == 0 ||(*decoded_length == 0 || (decoder && decoder->Channels
() == sync_buffer_->Channels())) ? static_cast<void>
(0) : ::webrtc::webrtc_checks_impl::FatalLogCall<false>
( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 1289, "*decoded_length == 0 || (decoder && decoder->Channels() == sync_buffer_->Channels())"
) & ::webrtc::webrtc_checks_impl::LogStreamer<>()
1289 (decoder && decoder->Channels() == sync_buffer_->Channels()))(*decoded_length == 0 || (decoder && decoder->Channels
() == sync_buffer_->Channels())) ? static_cast<void>
(0) : ::webrtc::webrtc_checks_impl::FatalLogCall<false>
( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 1289, "*decoded_length == 0 || (decoder && decoder->Channels() == sync_buffer_->Channels())"
) & ::webrtc::webrtc_checks_impl::LogStreamer<>()
;
1290 sync_buffer_->IncreaseEndTimestamp(
1291 *decoded_length / static_cast<int>(sync_buffer_->Channels()));
1292 }
1293 return return_value;
1294}
1295
1296int NetEqImpl::DecodeCng(AudioDecoder* decoder,
1297 int* decoded_length,
1298 AudioDecoder::SpeechType* speech_type) {
1299 if (!decoder) {
1300 // This happens when active decoder is not defined.
1301 *decoded_length = -1;
1302 return 0;
1303 }
1304
1305 while (*decoded_length < dchecked_cast<int>(output_size_samples_)) {
1306 const int length = decoder->Decode(
1307 nullptr, 0, fs_hz_,
1308 (decoded_buffer_length_ - *decoded_length) * sizeof(int16_t),
1309 &decoded_buffer_[*decoded_length], speech_type);
1310 if (length > 0) {
1311 *decoded_length += length;
1312 } else {
1313 // Error.
1314 RTC_LOG(LS_WARNING)!::webrtc::LogMessage::IsNoop<::webrtc::LS_WARNING>() &&
::webrtc::webrtc_logging_impl::LogCall() & ::webrtc::webrtc_logging_impl
::LogStreamer<>() << ::webrtc::webrtc_logging_impl
::LogMetadata("./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 1314, ::webrtc::LS_WARNING)
<< "Failed to decode CNG";
1315 *decoded_length = -1;
1316 break;
1317 }
1318 if (*decoded_length > static_cast<int>(decoded_buffer_length_)) {
1319 // Guard against overflow.
1320 RTC_LOG(LS_WARNING)!::webrtc::LogMessage::IsNoop<::webrtc::LS_WARNING>() &&
::webrtc::webrtc_logging_impl::LogCall() & ::webrtc::webrtc_logging_impl
::LogStreamer<>() << ::webrtc::webrtc_logging_impl
::LogMetadata("./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 1320, ::webrtc::LS_WARNING)
<< "Decoded too much CNG.";
1321 return kDecodedTooMuch;
1322 }
1323 }
1324 stats_->GeneratedNoiseSamples(*decoded_length);
1325 return 0;
1326}
1327
1328int NetEqImpl::DecodeLoop(PacketList* packet_list,
1329 const Operation& operation,
1330 AudioDecoder* decoder,
1331 int* decoded_length,
1332 AudioDecoder::SpeechType* speech_type) {
1333 RTC_DCHECK(last_decoded_packet_infos_.empty())(last_decoded_packet_infos_.empty()) ? static_cast<void>
(0) : ::webrtc::webrtc_checks_impl::FatalLogCall<false>
( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 1333, "last_decoded_packet_infos_.empty()") & ::webrtc::
webrtc_checks_impl::LogStreamer<>()
;
1334
1335 // Do decoding.
1336 while (!packet_list->empty() && !decoder_database_->IsComfortNoise(
1337 packet_list->front().payload_type)) {
1338 RTC_DCHECK(decoder)(decoder) ? static_cast<void>(0) : ::webrtc::webrtc_checks_impl
::FatalLogCall<false>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 1338, "decoder") & ::webrtc::webrtc_checks_impl::LogStreamer
<>()
; // At this point, we must have a decoder object.
1339 // The number of channels in the `sync_buffer_` should be the same as the
1340 // number decoder channels.
1341 RTC_DCHECK_EQ(sync_buffer_->Channels(), decoder->Channels())::webrtc::SafeEq((sync_buffer_->Channels()), (decoder->
Channels())) ? static_cast<void>(0) : ::webrtc::webrtc_checks_impl
::FatalLogCall<true>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 1341, "sync_buffer_->Channels()" " " "==" " " "decoder->Channels()"
) & ::webrtc::webrtc_checks_impl::LogStreamer<>() <<
(sync_buffer_->Channels()) << (decoder->Channels
())
;
1342 RTC_DCHECK_GE(decoded_buffer_length_, kMaxFrameSize * decoder->Channels())::webrtc::SafeGe((decoded_buffer_length_), (kMaxFrameSize * decoder
->Channels())) ? static_cast<void>(0) : ::webrtc::webrtc_checks_impl
::FatalLogCall<true>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 1342, "decoded_buffer_length_" " " ">=" " " "kMaxFrameSize * decoder->Channels()"
) & ::webrtc::webrtc_checks_impl::LogStreamer<>() <<
(decoded_buffer_length_) << (kMaxFrameSize * decoder->
Channels())
;
1343 RTC_DCHECK(operation == Operation::kNormal ||(operation == Operation::kNormal || operation == Operation::kAccelerate
|| operation == Operation::kFastAccelerate || operation == Operation
::kMerge || operation == Operation::kPreemptiveExpand) ? static_cast
<void>(0) : ::webrtc::webrtc_checks_impl::FatalLogCall<
false>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 1347, "operation == Operation::kNormal || operation == Operation::kAccelerate || operation == Operation::kFastAccelerate || operation == Operation::kMerge || operation == Operation::kPreemptiveExpand"
) & ::webrtc::webrtc_checks_impl::LogStreamer<>()
1344 operation == Operation::kAccelerate ||(operation == Operation::kNormal || operation == Operation::kAccelerate
|| operation == Operation::kFastAccelerate || operation == Operation
::kMerge || operation == Operation::kPreemptiveExpand) ? static_cast
<void>(0) : ::webrtc::webrtc_checks_impl::FatalLogCall<
false>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 1347, "operation == Operation::kNormal || operation == Operation::kAccelerate || operation == Operation::kFastAccelerate || operation == Operation::kMerge || operation == Operation::kPreemptiveExpand"
) & ::webrtc::webrtc_checks_impl::LogStreamer<>()
1345 operation == Operation::kFastAccelerate ||(operation == Operation::kNormal || operation == Operation::kAccelerate
|| operation == Operation::kFastAccelerate || operation == Operation
::kMerge || operation == Operation::kPreemptiveExpand) ? static_cast
<void>(0) : ::webrtc::webrtc_checks_impl::FatalLogCall<
false>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 1347, "operation == Operation::kNormal || operation == Operation::kAccelerate || operation == Operation::kFastAccelerate || operation == Operation::kMerge || operation == Operation::kPreemptiveExpand"
) & ::webrtc::webrtc_checks_impl::LogStreamer<>()
1346 operation == Operation::kMerge ||(operation == Operation::kNormal || operation == Operation::kAccelerate
|| operation == Operation::kFastAccelerate || operation == Operation
::kMerge || operation == Operation::kPreemptiveExpand) ? static_cast
<void>(0) : ::webrtc::webrtc_checks_impl::FatalLogCall<
false>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 1347, "operation == Operation::kNormal || operation == Operation::kAccelerate || operation == Operation::kFastAccelerate || operation == Operation::kMerge || operation == Operation::kPreemptiveExpand"
) & ::webrtc::webrtc_checks_impl::LogStreamer<>()
1347 operation == Operation::kPreemptiveExpand)(operation == Operation::kNormal || operation == Operation::kAccelerate
|| operation == Operation::kFastAccelerate || operation == Operation
::kMerge || operation == Operation::kPreemptiveExpand) ? static_cast
<void>(0) : ::webrtc::webrtc_checks_impl::FatalLogCall<
false>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 1347, "operation == Operation::kNormal || operation == Operation::kAccelerate || operation == Operation::kFastAccelerate || operation == Operation::kMerge || operation == Operation::kPreemptiveExpand"
) & ::webrtc::webrtc_checks_impl::LogStreamer<>()
;
1348
1349 auto opt_result = packet_list->front().frame->Decode(
1350 std::span<int16_t>(&decoded_buffer_[*decoded_length],
1351 decoded_buffer_length_ - *decoded_length));
1352 if (packet_list->front().packet_info) {
1353 last_decoded_packet_infos_.push_back(*packet_list->front().packet_info);
1354 }
1355 packet_list->pop_front();
1356 if (opt_result) {
1357 const auto& result = *opt_result;
1358 *speech_type = result.speech_type;
1359 if (result.num_decoded_samples > 0) {
1360 *decoded_length += dchecked_cast<int>(result.num_decoded_samples);
1361 // Update `decoder_frame_length_` with number of samples per channel.
1362 decoder_frame_length_ =
1363 result.num_decoded_samples / decoder->Channels();
1364 }
1365 } else {
1366 // Error.
1367 // TODO(ossu): What to put here?
1368 RTC_LOG(LS_WARNING)!::webrtc::LogMessage::IsNoop<::webrtc::LS_WARNING>() &&
::webrtc::webrtc_logging_impl::LogCall() & ::webrtc::webrtc_logging_impl
::LogStreamer<>() << ::webrtc::webrtc_logging_impl
::LogMetadata("./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 1368, ::webrtc::LS_WARNING)
<< "Decode error";
1369 *decoded_length = -1;
1370 last_decoded_packet_infos_.clear();
1371 packet_list->clear();
1372 break;
1373 }
1374 if (*decoded_length > dchecked_cast<int>(decoded_buffer_length_)) {
1375 // Guard against overflow.
1376 RTC_LOG(LS_WARNING)!::webrtc::LogMessage::IsNoop<::webrtc::LS_WARNING>() &&
::webrtc::webrtc_logging_impl::LogCall() & ::webrtc::webrtc_logging_impl
::LogStreamer<>() << ::webrtc::webrtc_logging_impl
::LogMetadata("./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 1376, ::webrtc::LS_WARNING)
<< "Decoded too much.";
1377 packet_list->clear();
1378 return kDecodedTooMuch;
1379 }
1380 } // End of decode loop.
1381
1382 // If the list is not empty at this point, either a decoding error terminated
1383 // the while-loop, or list must hold exactly one CNG packet.
1384 RTC_DCHECK((packet_list->empty() || *decoded_length < 0 || (packet_list
->size() == 1 && decoder_database_->IsComfortNoise
(packet_list->front().payload_type))) ? static_cast<void
>(0) : ::webrtc::webrtc_checks_impl::FatalLogCall<false
>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 1387, "packet_list->empty() || *decoded_length < 0 || (packet_list->size() == 1 && decoder_database_->IsComfortNoise(packet_list->front().payload_type))"
) & ::webrtc::webrtc_checks_impl::LogStreamer<>()
1385 packet_list->empty() || *decoded_length < 0 ||(packet_list->empty() || *decoded_length < 0 || (packet_list
->size() == 1 && decoder_database_->IsComfortNoise
(packet_list->front().payload_type))) ? static_cast<void
>(0) : ::webrtc::webrtc_checks_impl::FatalLogCall<false
>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 1387, "packet_list->empty() || *decoded_length < 0 || (packet_list->size() == 1 && decoder_database_->IsComfortNoise(packet_list->front().payload_type))"
) & ::webrtc::webrtc_checks_impl::LogStreamer<>()
1386 (packet_list->size() == 1 &&(packet_list->empty() || *decoded_length < 0 || (packet_list
->size() == 1 && decoder_database_->IsComfortNoise
(packet_list->front().payload_type))) ? static_cast<void
>(0) : ::webrtc::webrtc_checks_impl::FatalLogCall<false
>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 1387, "packet_list->empty() || *decoded_length < 0 || (packet_list->size() == 1 && decoder_database_->IsComfortNoise(packet_list->front().payload_type))"
) & ::webrtc::webrtc_checks_impl::LogStreamer<>()
1387 decoder_database_->IsComfortNoise(packet_list->front().payload_type)))(packet_list->empty() || *decoded_length < 0 || (packet_list
->size() == 1 && decoder_database_->IsComfortNoise
(packet_list->front().payload_type))) ? static_cast<void
>(0) : ::webrtc::webrtc_checks_impl::FatalLogCall<false
>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 1387, "packet_list->empty() || *decoded_length < 0 || (packet_list->size() == 1 && decoder_database_->IsComfortNoise(packet_list->front().payload_type))"
) & ::webrtc::webrtc_checks_impl::LogStreamer<>()
;
1388 return 0;
1389}
1390
1391void NetEqImpl::DoNormal(const int16_t* decoded_buffer,
1392 size_t decoded_length,
1393 AudioDecoder::SpeechType speech_type,
1394 bool play_dtmf) {
1395 RTC_DCHECK(normal_.get())(normal_.get()) ? static_cast<void>(0) : ::webrtc::webrtc_checks_impl
::FatalLogCall<false>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 1395, "normal_.get()") & ::webrtc::webrtc_checks_impl::
LogStreamer<>()
;
1396 normal_->Process(decoded_buffer, decoded_length, last_mode_,
1397 algorithm_buffer_.get());
1398 if (decoded_length != 0) {
1399 last_mode_ = Mode::kNormal;
1400 }
1401
1402 // If last packet was decoded as an inband CNG, set mode to CNG instead.
1403 if ((speech_type == AudioDecoder::kComfortNoise) ||
1404 ((last_mode_ == Mode::kCodecInternalCng) && (decoded_length == 0))) {
1405 // TODO(hlundin): Remove second part of || statement above.
1406 last_mode_ = Mode::kCodecInternalCng;
1407 }
1408
1409 if (!play_dtmf) {
1410 dtmf_tone_generator_->Reset();
1411 }
1412}
1413
1414void NetEqImpl::DoMerge(int16_t* decoded_buffer,
1415 size_t decoded_length,
1416 AudioDecoder::SpeechType speech_type,
1417 bool play_dtmf) {
1418 RTC_DCHECK(merge_.get())(merge_.get()) ? static_cast<void>(0) : ::webrtc::webrtc_checks_impl
::FatalLogCall<false>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 1418, "merge_.get()") & ::webrtc::webrtc_checks_impl::LogStreamer
<>()
;
1419 size_t new_length =
1420 merge_->Process(decoded_buffer, decoded_length, algorithm_buffer_.get());
1421 // Correction can be negative.
1422 int expand_length_correction =
1423 dchecked_cast<int>(new_length) -
1424 dchecked_cast<int>(decoded_length / algorithm_buffer_->Channels());
1425
1426 // Update in-call and post-call statistics.
1427 if (expand_->Muted() || last_decoded_type_ == AudioDecoder::kComfortNoise) {
1428 // Expand generates only noise.
1429 stats_->ExpandedNoiseSamplesCorrection(expand_length_correction);
1430 } else {
1431 // Expansion generates more than only noise.
1432 stats_->ExpandedVoiceSamplesCorrection(expand_length_correction);
1433 }
1434
1435 last_mode_ = Mode::kMerge;
1436 // If last packet was decoded as an inband CNG, set mode to CNG instead.
1437 if (speech_type == AudioDecoder::kComfortNoise) {
1438 last_mode_ = Mode::kCodecInternalCng;
1439 }
1440 expand_->Reset();
1441 if (!play_dtmf) {
1442 dtmf_tone_generator_->Reset();
1443 }
1444}
1445
1446bool NetEqImpl::DoCodecPlc() {
1447 AudioDecoder* decoder = decoder_database_->GetActiveDecoder();
1448 if (!decoder) {
1449 return false;
1450 }
1451 const size_t channels = algorithm_buffer_->Channels();
1452 const size_t requested_samples_per_channel =
1453 output_size_samples_ -
1454 (sync_buffer_->FutureLength() - expand_->overlap_length());
1455 concealment_audio_.Clear();
1456 decoder->GeneratePlc(requested_samples_per_channel, &concealment_audio_);
1457 if (concealment_audio_.empty()) {
1458 // Nothing produced. Resort to regular expand.
1459 return false;
1460 }
1461 RTC_CHECK_GE(concealment_audio_.size(),::webrtc::SafeGe((concealment_audio_.size()), (requested_samples_per_channel
* channels)) ? static_cast<void>(0) : ::webrtc::webrtc_checks_impl
::FatalLogCall<true>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 1462, "concealment_audio_.size()" " " ">=" " " "requested_samples_per_channel * channels"
) & ::webrtc::webrtc_checks_impl::LogStreamer<>() <<
(concealment_audio_.size()) << (requested_samples_per_channel
* channels)
1462 requested_samples_per_channel * channels)::webrtc::SafeGe((concealment_audio_.size()), (requested_samples_per_channel
* channels)) ? static_cast<void>(0) : ::webrtc::webrtc_checks_impl
::FatalLogCall<true>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 1462, "concealment_audio_.size()" " " ">=" " " "requested_samples_per_channel * channels"
) & ::webrtc::webrtc_checks_impl::LogStreamer<>() <<
(concealment_audio_.size()) << (requested_samples_per_channel
* channels)
;
1463 sync_buffer_->PushBackInterleaved(concealment_audio_);
1464 RTC_DCHECK_NE(algorithm_buffer_->Channels(), 0)::webrtc::SafeNe((algorithm_buffer_->Channels()), (0)) ? static_cast
<void>(0) : ::webrtc::webrtc_checks_impl::FatalLogCall<
true>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 1464, "algorithm_buffer_->Channels()" " " "!=" " " "0") &
::webrtc::webrtc_checks_impl::LogStreamer<>() <<
(algorithm_buffer_->Channels()) << (0)
;
1465 const size_t concealed_samples_per_channel =
1466 concealment_audio_.size() / channels;
1467
1468 // Update in-call and post-call statistics.
1469 const bool is_new_concealment_event = (last_mode_ != Mode::kCodecPlc);
1470 if (std::all_of(concealment_audio_.cbegin(), concealment_audio_.cend(),
1471 [](int16_t i) { return i == 0; })) {
1472 // Expand operation generates only noise.
1473 stats_->ExpandedNoiseSamples(concealed_samples_per_channel,
1474 is_new_concealment_event);
1475 } else {
1476 // Expand operation generates more than only noise.
1477 stats_->ExpandedVoiceSamples(concealed_samples_per_channel,
1478 is_new_concealment_event);
1479 }
1480 last_mode_ = Mode::kCodecPlc;
1481 if (!generated_noise_stopwatch_) {
1482 // Start a new stopwatch since we may be covering for a lost CNG packet.
1483 generated_noise_stopwatch_ = tick_timer_->GetNewStopwatch();
1484 }
1485 return true;
1486}
1487
1488int NetEqImpl::DoExpand(bool play_dtmf) {
1489 while ((sync_buffer_->FutureLength() - expand_->overlap_length()) <
1490 output_size_samples_) {
1491 algorithm_buffer_->Clear();
1492 int return_value = expand_->Process(algorithm_buffer_.get());
1493 size_t length = algorithm_buffer_->Size();
1494 bool is_new_concealment_event = (last_mode_ != Mode::kExpand);
1495
1496 // Update in-call and post-call statistics.
1497 if (expand_->Muted() || last_decoded_type_ == AudioDecoder::kComfortNoise) {
1498 // Expand operation generates only noise.
1499 stats_->ExpandedNoiseSamples(length, is_new_concealment_event);
1500 } else {
1501 // Expand operation generates more than only noise.
1502 stats_->ExpandedVoiceSamples(length, is_new_concealment_event);
1503 }
1504
1505 last_mode_ = Mode::kExpand;
1506
1507 if (return_value < 0) {
1508 return return_value;
1509 }
1510
1511 sync_buffer_->PushBack(*algorithm_buffer_);
1512 algorithm_buffer_->Clear();
1513 }
1514 if (!play_dtmf) {
1515 dtmf_tone_generator_->Reset();
1516 }
1517
1518 if (!generated_noise_stopwatch_) {
1519 // Start a new stopwatch since we may be covering for a lost CNG packet.
1520 generated_noise_stopwatch_ = tick_timer_->GetNewStopwatch();
1521 }
1522
1523 return 0;
1524}
1525
1526int NetEqImpl::DoAccelerate(int16_t* decoded_buffer,
1527 size_t decoded_length,
1528 AudioDecoder::SpeechType speech_type,
1529 bool play_dtmf,
1530 bool fast_accelerate) {
1531 const size_t required_samples =
1532 static_cast<size_t>(240 * fs_mult_); // Must have 30 ms.
1533 size_t borrowed_samples_per_channel = 0;
1534 size_t num_channels = algorithm_buffer_->Channels();
1535 size_t decoded_length_per_channel = decoded_length / num_channels;
1536 if (decoded_length_per_channel < required_samples) {
1537 // Must move data from the `sync_buffer_` in order to get 30 ms.
1538 borrowed_samples_per_channel =
1539 static_cast<int>(required_samples - decoded_length_per_channel);
1540 memmove(&decoded_buffer[borrowed_samples_per_channel * num_channels],
1541 decoded_buffer, sizeof(int16_t) * decoded_length);
1542 sync_buffer_->ReadInterleavedFromEnd(borrowed_samples_per_channel,
1543 decoded_buffer);
1544 decoded_length = required_samples * num_channels;
1545 }
1546
1547 size_t samples_removed = 0;
1548 Accelerate::ReturnCodes return_code =
1549 accelerate_->Process(decoded_buffer, decoded_length, fast_accelerate,
1550 algorithm_buffer_.get(), &samples_removed);
1551 stats_->AcceleratedSamples(samples_removed);
1552 switch (return_code) {
1553 case Accelerate::kSuccess:
1554 last_mode_ = Mode::kAccelerateSuccess;
1555 break;
1556 case Accelerate::kSuccessLowEnergy:
1557 last_mode_ = Mode::kAccelerateLowEnergy;
1558 break;
1559 case Accelerate::kNoStretch:
1560 last_mode_ = Mode::kAccelerateFail;
1561 break;
1562 case Accelerate::kError:
1563 // TODO(hlundin): Map to Modes::kError instead?
1564 last_mode_ = Mode::kAccelerateFail;
1565 return kAccelerateError;
1566 }
1567
1568 if (borrowed_samples_per_channel > 0) {
1569 // Copy borrowed samples back to the `sync_buffer_`.
1570 size_t length = algorithm_buffer_->Size();
1571 if (length < borrowed_samples_per_channel) {
1572 // This destroys the beginning of the buffer, but will not cause any
1573 // problems.
1574 sync_buffer_->ReplaceAtIndex(
1575 *algorithm_buffer_,
1576 sync_buffer_->Size() - borrowed_samples_per_channel);
1577 sync_buffer_->PushFrontZeros(borrowed_samples_per_channel - length);
1578 algorithm_buffer_->PopFront(length);
1579 RTC_DCHECK(algorithm_buffer_->Empty())(algorithm_buffer_->Empty()) ? static_cast<void>(0) :
::webrtc::webrtc_checks_impl::FatalLogCall<false>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 1579, "algorithm_buffer_->Empty()") & ::webrtc::webrtc_checks_impl
::LogStreamer<>()
;
1580 } else {
1581 sync_buffer_->ReplaceAtIndex(
1582 *algorithm_buffer_, borrowed_samples_per_channel,
1583 sync_buffer_->Size() - borrowed_samples_per_channel);
1584 algorithm_buffer_->PopFront(borrowed_samples_per_channel);
1585 }
1586 }
1587
1588 // If last packet was decoded as an inband CNG, set mode to CNG instead.
1589 if (speech_type == AudioDecoder::kComfortNoise) {
1590 last_mode_ = Mode::kCodecInternalCng;
1591 }
1592 if (!play_dtmf) {
1593 dtmf_tone_generator_->Reset();
1594 }
1595 expand_->Reset();
1596 return 0;
1597}
1598
1599int NetEqImpl::DoPreemptiveExpand(int16_t* decoded_buffer,
1600 size_t decoded_length,
1601 AudioDecoder::SpeechType speech_type,
1602 bool play_dtmf) {
1603 const size_t required_samples =
1604 static_cast<size_t>(240 * fs_mult_); // Must have 30 ms.
1605 size_t num_channels = algorithm_buffer_->Channels();
1606 size_t borrowed_samples_per_channel = 0;
1607 size_t old_borrowed_samples_per_channel = 0;
1608 size_t decoded_length_per_channel = decoded_length / num_channels;
1609 if (decoded_length_per_channel < required_samples) {
1610 // Must move data from the `sync_buffer_` in order to get 30 ms.
1611 borrowed_samples_per_channel =
1612 required_samples - decoded_length_per_channel;
1613 // Calculate how many of these were already played out.
1614 old_borrowed_samples_per_channel =
1615 (borrowed_samples_per_channel > sync_buffer_->FutureLength())
1616 ? (borrowed_samples_per_channel - sync_buffer_->FutureLength())
1617 : 0;
1618 memmove(&decoded_buffer[borrowed_samples_per_channel * num_channels],
1619 decoded_buffer, sizeof(int16_t) * decoded_length);
1620 sync_buffer_->ReadInterleavedFromEnd(borrowed_samples_per_channel,
1621 decoded_buffer);
1622 decoded_length = required_samples * num_channels;
1623 }
1624
1625 size_t samples_added = 0;
1626 PreemptiveExpand::ReturnCodes return_code = preemptive_expand_->Process(
1627 decoded_buffer, decoded_length, old_borrowed_samples_per_channel,
1628 algorithm_buffer_.get(), &samples_added);
1629 stats_->PreemptiveExpandedSamples(samples_added);
1630 switch (return_code) {
1631 case PreemptiveExpand::kSuccess:
1632 last_mode_ = Mode::kPreemptiveExpandSuccess;
1633 break;
1634 case PreemptiveExpand::kSuccessLowEnergy:
1635 last_mode_ = Mode::kPreemptiveExpandLowEnergy;
1636 break;
1637 case PreemptiveExpand::kNoStretch:
1638 last_mode_ = Mode::kPreemptiveExpandFail;
1639 break;
1640 case PreemptiveExpand::kError:
1641 // TODO(hlundin): Map to Modes::kError instead?
1642 last_mode_ = Mode::kPreemptiveExpandFail;
1643 return kPreemptiveExpandError;
1644 }
1645
1646 if (borrowed_samples_per_channel > 0) {
1647 // Copy borrowed samples back to the `sync_buffer_`.
1648 sync_buffer_->ReplaceAtIndex(
1649 *algorithm_buffer_, borrowed_samples_per_channel,
1650 sync_buffer_->Size() - borrowed_samples_per_channel);
1651 algorithm_buffer_->PopFront(borrowed_samples_per_channel);
1652 }
1653
1654 // If last packet was decoded as an inband CNG, set mode to CNG instead.
1655 if (speech_type == AudioDecoder::kComfortNoise) {
1656 last_mode_ = Mode::kCodecInternalCng;
1657 }
1658 if (!play_dtmf) {
1659 dtmf_tone_generator_->Reset();
1660 }
1661 expand_->Reset();
1662 return 0;
1663}
1664
1665int NetEqImpl::DoRfc3389Cng(PacketList* packet_list, bool play_dtmf) {
1666 if (!packet_list->empty()) {
1667 // Must have exactly one SID frame at this point.
1668 RTC_DCHECK_EQ(packet_list->size(), 1)::webrtc::SafeEq((packet_list->size()), (1)) ? static_cast
<void>(0) : ::webrtc::webrtc_checks_impl::FatalLogCall<
true>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 1668, "packet_list->size()" " " "==" " " "1") & ::webrtc
::webrtc_checks_impl::LogStreamer<>() << (packet_list
->size()) << (1)
;
1669 const Packet& packet = packet_list->front();
1670 if (!decoder_database_->IsComfortNoise(packet.payload_type)) {
1671 RTC_LOG(LS_ERROR)!::webrtc::LogMessage::IsNoop<::webrtc::LS_ERROR>() &&
::webrtc::webrtc_logging_impl::LogCall() & ::webrtc::webrtc_logging_impl
::LogStreamer<>() << ::webrtc::webrtc_logging_impl
::LogMetadata("./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 1671, ::webrtc::LS_ERROR)
<< "Trying to decode non-CNG payload as CNG.";
1672 return kOtherError;
1673 }
1674 if (comfort_noise_->UpdateParameters(packet) ==
1675 ComfortNoise::kInternalError) {
1676 algorithm_buffer_->Zeros(output_size_samples_);
1677 return -comfort_noise_->internal_error_code();
1678 }
1679 }
1680 int cn_return =
1681 comfort_noise_->Generate(output_size_samples_, algorithm_buffer_.get());
1682 expand_->Reset();
1683 last_mode_ = Mode::kRfc3389Cng;
1684 if (!play_dtmf) {
1685 dtmf_tone_generator_->Reset();
1686 }
1687 if (cn_return == ComfortNoise::kInternalError) {
1688 RTC_LOG(LS_WARNING)!::webrtc::LogMessage::IsNoop<::webrtc::LS_WARNING>() &&
::webrtc::webrtc_logging_impl::LogCall() & ::webrtc::webrtc_logging_impl
::LogStreamer<>() << ::webrtc::webrtc_logging_impl
::LogMetadata("./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 1688, ::webrtc::LS_WARNING)
<< "Comfort noise generator returned error code: "
1689 << comfort_noise_->internal_error_code();
1690 return kComfortNoiseErrorCode;
1691 } else if (cn_return == ComfortNoise::kUnknownPayloadType) {
1692 return kUnknownRtpPayloadType;
1693 }
1694 return 0;
1695}
1696
1697void NetEqImpl::DoCodecInternalCng(const int16_t* decoded_buffer,
1698 size_t decoded_length) {
1699 RTC_DCHECK(normal_.get())(normal_.get()) ? static_cast<void>(0) : ::webrtc::webrtc_checks_impl
::FatalLogCall<false>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 1699, "normal_.get()") & ::webrtc::webrtc_checks_impl::
LogStreamer<>()
;
1700 normal_->Process(decoded_buffer, decoded_length, last_mode_,
1701 algorithm_buffer_.get());
1702 last_mode_ = Mode::kCodecInternalCng;
1703 expand_->Reset();
1704}
1705
1706int NetEqImpl::DoDtmf(const DtmfEvent& dtmf_event, bool* play_dtmf) {
1707 // This block of the code and the block further down, handling `dtmf_switch`
1708 // are commented out. Otherwise playing out-of-band DTMF would fail in VoE
1709 // test, DtmfTest.ManualSuccessfullySendsOutOfBandTelephoneEvents. This is
1710 // equivalent to `dtmf_switch` always be false.
1711 //
1712 // See http://webrtc-codereview.appspot.com/1195004/ for discussion
1713 // On this issue. This change might cause some glitches at the point of
1714 // switch from audio to DTMF. Issue 1545 is filed to track this.
1715 //
1716 // bool dtmf_switch = false;
1717 // if ((last_mode_ != Modes::kDtmf) &&
1718 // dtmf_tone_generator_->initialized()) {
1719 // // Special case; see below.
1720 // // We must catch this before calling Generate, since `initialized` is
1721 // // modified in that call.
1722 // dtmf_switch = true;
1723 // }
1724
1725 int dtmf_return_value = 0;
1726 if (!dtmf_tone_generator_->initialized()) {
1727 // Initialize if not already done.
1728 dtmf_return_value = dtmf_tone_generator_->Init(fs_hz_, dtmf_event.event_no,
1729 dtmf_event.volume);
1730 }
1731
1732 if (dtmf_return_value == 0) {
1733 // Generate DTMF signal.
1734 dtmf_return_value = dtmf_tone_generator_->Generate(output_size_samples_,
1735 algorithm_buffer_.get());
1736 }
1737
1738 if (dtmf_return_value < 0) {
1739 algorithm_buffer_->Zeros(output_size_samples_);
1740 return dtmf_return_value;
1741 }
1742
1743 // if (dtmf_switch) {
1744 // // This is the special case where the previous operation was DTMF
1745 // // overdub, but the current instruction is "regular" DTMF. We must make
1746 // // sure that the DTMF does not have any discontinuities. The first DTMF
1747 // // sample that we generate now must be played out immediately, therefore
1748 // // it must be copied to the speech buffer.
1749 // // TODO(hlundin): This code seems incorrect. (Legacy.) Write test and
1750 // // verify correct operation.
1751 // RTC_DCHECK_NOTREACHED();
1752 // // Must generate enough data to replace all of the `sync_buffer_`
1753 // // "future".
1754 // int required_length = sync_buffer_->FutureLength();
1755 // RTC_DCHECK(dtmf_tone_generator_->initialized());
1756 // dtmf_return_value = dtmf_tone_generator_->Generate(required_length,
1757 // algorithm_buffer_);
1758 // RTC_DCHECK((size_t) required_length == algorithm_buffer_->Size());
1759 // if (dtmf_return_value < 0) {
1760 // algorithm_buffer_->Zeros(output_size_samples_);
1761 // return dtmf_return_value;
1762 // }
1763 //
1764 // // Overwrite the "future" part of the speech buffer with the new DTMF
1765 // // data.
1766 // // TODO(hlundin): It seems that this overwriting has gone lost.
1767 // // Not adapted for multi-channel yet.
1768 // RTC_DCHECK(algorithm_buffer_->Channels() == 1);
1769 // if (algorithm_buffer_->Channels() != 1) {
1770 // RTC_LOG(LS_WARNING) << "DTMF not supported for more than one channel";
1771 // return kStereoNotSupported;
1772 // }
1773 // // Shuffle the remaining data to the beginning of algorithm buffer.
1774 // algorithm_buffer_->PopFront(sync_buffer_->FutureLength());
1775 // }
1776
1777 sync_buffer_->IncreaseEndTimestamp(
1778 static_cast<uint32_t>(output_size_samples_));
1779 expand_->Reset();
1780 last_mode_ = Mode::kDtmf;
1781
1782 // Set to false because the DTMF is already in the algorithm buffer.
1783 *play_dtmf = false;
1784 return 0;
1785}
1786
1787int NetEqImpl::DtmfOverdub(const DtmfEvent& dtmf_event,
1788 size_t num_channels,
1789 int16_t* output) const {
1790 size_t out_index = 0;
1791 size_t overdub_length = output_size_samples_; // Default value.
1792
1793 if (sync_buffer_->dtmf_index() > sync_buffer_->next_index()) {
1794 // Special operation for transition from "DTMF only" to "DTMF overdub".
1795 out_index =
1796 std::min(sync_buffer_->dtmf_index() - sync_buffer_->next_index(),
1797 output_size_samples_);
1798 overdub_length = output_size_samples_ - out_index;
1799 }
1800
1801 AudioMultiVector dtmf_output(num_channels);
1802 int dtmf_return_value = 0;
1803 if (!dtmf_tone_generator_->initialized()) {
1804 dtmf_return_value = dtmf_tone_generator_->Init(fs_hz_, dtmf_event.event_no,
1805 dtmf_event.volume);
1806 }
1807 if (dtmf_return_value == 0) {
1808 dtmf_return_value =
1809 dtmf_tone_generator_->Generate(overdub_length, &dtmf_output);
1810 RTC_DCHECK_EQ(overdub_length, dtmf_output.Size())::webrtc::SafeEq((overdub_length), (dtmf_output.Size())) ? static_cast
<void>(0) : ::webrtc::webrtc_checks_impl::FatalLogCall<
true>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 1810, "overdub_length" " " "==" " " "dtmf_output.Size()") &
::webrtc::webrtc_checks_impl::LogStreamer<>() <<
(overdub_length) << (dtmf_output.Size())
;
1811 }
1812 dtmf_output.ReadInterleaved(overdub_length, &output[out_index]);
1813 return dtmf_return_value < 0 ? dtmf_return_value : 0;
1814}
1815
1816int NetEqImpl::ExtractPackets(size_t required_samples,
1817 PacketList* packet_list) {
1818 bool next_packet_available = false;
1819
1820 const Packet* next_packet = packet_buffer_->PeekNextPacket();
1821 RTC_DCHECK(next_packet)(next_packet) ? static_cast<void>(0) : ::webrtc::webrtc_checks_impl
::FatalLogCall<false>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 1821, "next_packet") & ::webrtc::webrtc_checks_impl::LogStreamer
<>()
;
1822 if (!next_packet) {
1823 RTC_LOG(LS_ERROR)!::webrtc::LogMessage::IsNoop<::webrtc::LS_ERROR>() &&
::webrtc::webrtc_logging_impl::LogCall() & ::webrtc::webrtc_logging_impl
::LogStreamer<>() << ::webrtc::webrtc_logging_impl
::LogMetadata("./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 1823, ::webrtc::LS_ERROR)
<< "Packet buffer unexpectedly empty.";
1824 return -1;
1825 }
1826 uint32_t first_timestamp = next_packet->timestamp;
1827 size_t extracted_samples = 0;
1828
1829 // Packet extraction loop.
1830 do {
1831 timestamp_ = next_packet->timestamp;
1832 std::optional<Packet> packet = packet_buffer_->GetNextPacket();
1833 // `next_packet` may be invalid after the `packet_buffer_` operation.
1834 next_packet = nullptr;
1835 if (!packet) {
1836 RTC_LOG(LS_ERROR)!::webrtc::LogMessage::IsNoop<::webrtc::LS_ERROR>() &&
::webrtc::webrtc_logging_impl::LogCall() & ::webrtc::webrtc_logging_impl
::LogStreamer<>() << ::webrtc::webrtc_logging_impl
::LogMetadata("./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 1836, ::webrtc::LS_ERROR)
<< "Should always be able to extract a packet here";
1837 RTC_DCHECK_NOTREACHED()(false) ? static_cast<void>(0) : ::webrtc::webrtc_checks_impl
::FatalLogCall<false>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 1837, "false") & ::webrtc::webrtc_checks_impl::LogStreamer
<>()
; // Should always be able to extract a packet
1838 // here.
1839 return -1;
1840 }
1841 const uint64_t waiting_time_ms = packet->waiting_time->ElapsedMs();
1842 stats_->StoreWaitingTime(waiting_time_ms);
1843 RTC_DCHECK(!packet->empty())(!packet->empty()) ? static_cast<void>(0) : ::webrtc
::webrtc_checks_impl::FatalLogCall<false>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 1843, "!packet->empty()") & ::webrtc::webrtc_checks_impl
::LogStreamer<>()
;
1844
1845 const bool has_cng_packet =
1846 decoder_database_->IsComfortNoise(packet->payload_type);
1847 // Store number of extracted samples.
1848 size_t packet_duration = 0;
1849 if (packet->frame) {
1850 packet_duration = packet->frame->Duration();
1851 // TODO(ossu): Is this the correct way to track Opus FEC packets?
1852 if (packet->priority.codec_level > 0) {
1853 stats_->SecondaryDecodedSamples(dchecked_cast<int>(packet_duration));
1854 }
1855 } else if (!has_cng_packet) {
1856 RTC_LOG(LS_WARNING)!::webrtc::LogMessage::IsNoop<::webrtc::LS_WARNING>() &&
::webrtc::webrtc_logging_impl::LogCall() & ::webrtc::webrtc_logging_impl
::LogStreamer<>() << ::webrtc::webrtc_logging_impl
::LogMetadata("./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 1856, ::webrtc::LS_WARNING)
<< "Unknown payload type "
1857 << static_cast<int>(packet->payload_type);
1858 RTC_DCHECK_NOTREACHED()(false) ? static_cast<void>(0) : ::webrtc::webrtc_checks_impl
::FatalLogCall<false>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 1858, "false") & ::webrtc::webrtc_checks_impl::LogStreamer
<>()
;
1859 }
1860
1861 if (packet_duration == 0) {
1862 // Decoder did not return a packet duration. Assume that the packet
1863 // contains the same number of samples as the previous one.
1864 packet_duration = decoder_frame_length_;
1865 }
1866 extracted_samples = packet->timestamp - first_timestamp + packet_duration;
1867
1868 RTC_DCHECK(controller_)(controller_) ? static_cast<void>(0) : ::webrtc::webrtc_checks_impl
::FatalLogCall<false>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 1868, "controller_") & ::webrtc::webrtc_checks_impl::LogStreamer
<>()
;
1869 TimeDelta processing_time = TimeDelta::Zero();
1870
1871 if (packet->packet_info.has_value() &&
1872 !packet->packet_info->receive_time().IsMinusInfinity()) {
1873 processing_time =
1874 env_.clock().CurrentTime() - packet->packet_info->receive_time();
1875 }
1876
1877 stats_->JitterBufferDelay(
1878 packet_duration, waiting_time_ms, controller_->TargetLevelMs(),
1879 controller_->UnlimitedTargetLevelMs(), processing_time.us());
1880
1881 // Check what packet is available next.
1882 next_packet = packet_buffer_->PeekNextPacket();
1883 next_packet_available =
1884 next_packet && next_packet->payload_type == packet->payload_type &&
1885 next_packet->timestamp == packet->timestamp + packet_duration &&
1886 !has_cng_packet;
1887
1888 packet_list->push_back(std::move(*packet)); // Store packet in list.
1889 packet = std::nullopt; // Ensure it's never used after the move.
1890 } while (extracted_samples < required_samples && next_packet_available);
1891
1892 if (extracted_samples > 0) {
1893 // Delete old packets only when we are going to decode something. Otherwise,
1894 // we could end up in the situation where we never decode anything, since
1895 // all incoming packets are considered too old but the buffer will also
1896 // never be flooded and flushed.
1897 packet_buffer_->DiscardAllOldPackets(timestamp_);
1898 }
1899
1900 return dchecked_cast<int>(extracted_samples);
1901}
1902
1903void NetEqImpl::UpdatePlcComponents(int fs_hz, size_t channels) {
1904 // Delete objects and create new ones.
1905 expand_.reset(expand_factory_->Create(background_noise_.get(),
1906 sync_buffer_.get(), &random_vector_,
1907 stats_.get(), fs_hz, channels));
1908 merge_.reset(new Merge(fs_hz, channels, expand_.get(), sync_buffer_.get()));
1909}
1910
1911void NetEqImpl::SetSampleRateAndChannels(int fs_hz, size_t channels) {
1912 RTC_LOG(LS_VERBOSE)!::webrtc::LogMessage::IsNoop<::webrtc::LS_VERBOSE>() &&
::webrtc::webrtc_logging_impl::LogCall() & ::webrtc::webrtc_logging_impl
::LogStreamer<>() << ::webrtc::webrtc_logging_impl
::LogMetadata("./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 1912, ::webrtc::LS_VERBOSE)
<< "SetSampleRateAndChannels " << fs_hz << " "
1913 << channels;
1914 RTC_CHECK(fs_hz == 8000 || fs_hz == 16000 || fs_hz == 32000 ||(fs_hz == 8000 || fs_hz == 16000 || fs_hz == 32000 || fs_hz ==
48000) ? static_cast<void>(0) : ::webrtc::webrtc_checks_impl
::FatalLogCall<false>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 1915, "fs_hz == 8000 || fs_hz == 16000 || fs_hz == 32000 || fs_hz == 48000"
) & ::webrtc::webrtc_checks_impl::LogStreamer<>()
1915 fs_hz == 48000)(fs_hz == 8000 || fs_hz == 16000 || fs_hz == 32000 || fs_hz ==
48000) ? static_cast<void>(0) : ::webrtc::webrtc_checks_impl
::FatalLogCall<false>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 1915, "fs_hz == 8000 || fs_hz == 16000 || fs_hz == 32000 || fs_hz == 48000"
) & ::webrtc::webrtc_checks_impl::LogStreamer<>()
;
1916 RTC_CHECK_GT(channels, 0)::webrtc::SafeGt((channels), (0)) ? static_cast<void>(0
) : ::webrtc::webrtc_checks_impl::FatalLogCall<true>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 1916, "channels" " " ">" " " "0") & ::webrtc::webrtc_checks_impl
::LogStreamer<>() << (channels) << (0)
;
1917 RTC_CHECK_LE(channels, kMaxNumberOfAudioChannels)::webrtc::SafeLe((channels), (kMaxNumberOfAudioChannels)) ? static_cast
<void>(0) : ::webrtc::webrtc_checks_impl::FatalLogCall<
true>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 1917, "channels" " " "<=" " " "kMaxNumberOfAudioChannels"
) & ::webrtc::webrtc_checks_impl::LogStreamer<>() <<
(channels) << (kMaxNumberOfAudioChannels)
;
1918
1919 // The format must fit in an AudioFrame. Situations where this could
1920 // theoratically happen but aren't supported is e.g. if receiving 24 channels
1921 // of 10ms 48 kHz buffers.
1922 output_size_samples_ = SampleRateToDefaultChannelSize(fs_hz);
1923 RTC_CHECK_LE(channels * output_size_samples_,::webrtc::SafeLe((channels * output_size_samples_), (AudioFrame
::kMaxDataSizeSamples)) ? static_cast<void>(0) : ::webrtc
::webrtc_checks_impl::FatalLogCall<true>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 1924, "channels * output_size_samples_" " " "<=" " " "AudioFrame::kMaxDataSizeSamples"
) & ::webrtc::webrtc_checks_impl::LogStreamer<>() <<
(channels * output_size_samples_) << (AudioFrame::kMaxDataSizeSamples
)
1924 AudioFrame::kMaxDataSizeSamples)::webrtc::SafeLe((channels * output_size_samples_), (AudioFrame
::kMaxDataSizeSamples)) ? static_cast<void>(0) : ::webrtc
::webrtc_checks_impl::FatalLogCall<true>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 1924, "channels * output_size_samples_" " " "<=" " " "AudioFrame::kMaxDataSizeSamples"
) & ::webrtc::webrtc_checks_impl::LogStreamer<>() <<
(channels * output_size_samples_) << (AudioFrame::kMaxDataSizeSamples
)
;
1925
1926 // Before changing the sample rate, end and report any ongoing expand event.
1927 stats_->EndExpandEvent(fs_hz_);
1928 fs_hz_ = fs_hz;
1929 fs_mult_ = fs_hz / 8000;
1930 RTC_DCHECK_EQ(output_size_samples_,::webrtc::SafeEq((output_size_samples_), (static_cast<size_t
>(kOutputSizeMs * 8 * fs_mult_))) ? static_cast<void>
(0) : ::webrtc::webrtc_checks_impl::FatalLogCall<true>(
"./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 1931, "output_size_samples_" " " "==" " " "static_cast<size_t>(kOutputSizeMs * 8 * fs_mult_)"
) & ::webrtc::webrtc_checks_impl::LogStreamer<>() <<
(output_size_samples_) << (static_cast<size_t>(kOutputSizeMs
* 8 * fs_mult_))
1931 static_cast<size_t>(kOutputSizeMs * 8 * fs_mult_))::webrtc::SafeEq((output_size_samples_), (static_cast<size_t
>(kOutputSizeMs * 8 * fs_mult_))) ? static_cast<void>
(0) : ::webrtc::webrtc_checks_impl::FatalLogCall<true>(
"./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 1931, "output_size_samples_" " " "==" " " "static_cast<size_t>(kOutputSizeMs * 8 * fs_mult_)"
) & ::webrtc::webrtc_checks_impl::LogStreamer<>() <<
(output_size_samples_) << (static_cast<size_t>(kOutputSizeMs
* 8 * fs_mult_))
;
1932 decoder_frame_length_ = 3 * output_size_samples_; // Initialize to 30ms.
1933
1934 last_mode_ = Mode::kNormal;
1935
1936 ComfortNoiseDecoder* cng_decoder = decoder_database_->GetActiveCngDecoder();
1937 if (cng_decoder)
1938 cng_decoder->Reset();
1939
1940 // Delete algorithm buffer and create a new one.
1941 algorithm_buffer_.reset(new AudioMultiVector(channels));
1942
1943 // Delete sync buffer and create a new one.
1944 sync_buffer_.reset(new SyncBuffer(channels, kSyncBufferSize * fs_mult_));
1945
1946 // Delete BackgroundNoise object and create a new one.
1947 background_noise_.reset(new BackgroundNoise(channels));
1948
1949 // Reset random vector.
1950 random_vector_.Reset();
1951
1952 UpdatePlcComponents(fs_hz, channels);
1953
1954 // Move index so that we create a small set of future samples (all 0).
1955 sync_buffer_->set_next_index(sync_buffer_->next_index() -
1956 expand_->overlap_length());
1957
1958 normal_.reset(new Normal(fs_hz, decoder_database_.get(), *background_noise_,
1959 expand_.get(), stats_.get()));
1960 accelerate_.reset(
1961 accelerate_factory_->Create(fs_hz, channels, *background_noise_));
1962 preemptive_expand_.reset(preemptive_expand_factory_->Create(
1963 fs_hz, channels, *background_noise_, expand_->overlap_length()));
1964
1965 // Delete ComfortNoise object and create a new one.
1966 comfort_noise_.reset(
1967 new ComfortNoise(fs_hz, decoder_database_.get(), sync_buffer_.get()));
1968
1969 // Verify that `decoded_buffer_` is long enough.
1970 if (decoded_buffer_length_ < kMaxFrameSize * channels) {
1971 // Reallocate to larger size.
1972 decoded_buffer_length_ = kMaxFrameSize * channels;
1973 decoded_buffer_.reset(new int16_t[decoded_buffer_length_]);
1974 }
1975 RTC_CHECK(controller_)(controller_) ? static_cast<void>(0) : ::webrtc::webrtc_checks_impl
::FatalLogCall<false>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 1975, "controller_") & ::webrtc::webrtc_checks_impl::LogStreamer
<>()
<< "Unexpectedly found no NetEqController";
1976 controller_->SetSampleRate(fs_hz_, output_size_samples_);
1977}
1978
1979NetEqImpl::OutputType NetEqImpl::LastOutputType() {
1980 RTC_DCHECK(expand_.get())(expand_.get()) ? static_cast<void>(0) : ::webrtc::webrtc_checks_impl
::FatalLogCall<false>( "./../../../../../../third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc"
, 1980, "expand_.get()") & ::webrtc::webrtc_checks_impl::
LogStreamer<>()
;
1981 if (last_mode_ == Mode::kCodecInternalCng ||
1982 last_mode_ == Mode::kRfc3389Cng) {
1983 return OutputType::kCNG;
1984 } else if (last_mode_ == Mode::kExpand && expand_->MuteFactor(0) == 0) {
1985 // Expand mode has faded down to background noise only (very long expand).
1986 return OutputType::kPLCCNG;
1987 } else if (last_mode_ == Mode::kExpand) {
1988 return OutputType::kPLC;
1989 } else if (last_mode_ == Mode::kCodecPlc) {
1990 return OutputType::kCodecPLC;
1991 } else {
1992 return OutputType::kNormalSpeech;
1993 }
1994}
1995
1996NetEqController::PacketArrivedInfo NetEqImpl::ToPacketArrivedInfo(
1997 const Packet& packet) const {
1998 const DecoderDatabase::DecoderInfo* dec_info =
1999 decoder_database_->GetDecoderInfo(packet.payload_type);
2000
2001 NetEqController::PacketArrivedInfo info;
2002 info.is_cng_or_dtmf =
2003 dec_info && (dec_info->IsComfortNoise() || dec_info->IsDtmf());
2004 info.packet_length_samples =
2005 packet.frame ? packet.frame->Duration() : decoder_frame_length_;
2006 info.main_timestamp = packet.timestamp;
2007 info.main_sequence_number = packet.sequence_number;
2008 info.is_dtx = packet.frame && packet.frame->IsDtxPacket();
2009 info.buffer_flush = false;
2010 return info;
2011}
2012
2013void NetEqImpl::SetMaximumBufferPackets(size_t max_packets) {
2014 packet_buffer_->SetMaxNumberOfPackets(max_packets);
2015}
2016
2017void NetEqImpl::SetFastAccelerate(bool enable) {
2018 enable_fast_accelerate_ = enable;
2019}
2020
2021} // namespace webrtc