blob: 4ff1a431e1c47f064258bf4f8b6219187a5099c5 [file] [log] [blame]
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +00001/*
2 * Copyright (c) 2011 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
Ivo Creusen3ce44a32019-10-31 14:38:11 +010011#include "api/neteq/neteq.h"
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000012
pbos@webrtc.org3ecc1622014-03-07 15:23:34 +000013#include <math.h>
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000014#include <stdlib.h>
15#include <string.h> // memset
16
turaj@webrtc.org8d1cdaa2014-04-11 18:47:55 +000017#include <algorithm>
kwiberg2d0c3322016-02-14 09:28:33 -080018#include <memory>
turaj@webrtc.org78b41a02013-11-22 20:27:07 +000019#include <set>
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000020#include <string>
21#include <vector>
22
Mirko Bonadei2ab97f62019-07-18 13:44:12 +020023#include "absl/flags/flag.h"
Fredrik Solenbergbbf21a32018-04-12 22:44:09 +020024#include "api/audio/audio_frame.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020025#include "api/audio_codecs/builtin_audio_decoder_factory.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020026#include "modules/audio_coding/codecs/pcm16b/pcm16b.h"
Yves Gerey3a65f392019-11-11 18:05:42 +010027#include "modules/audio_coding/neteq/test/neteq_decoding_test.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020028#include "modules/audio_coding/neteq/tools/audio_loop.h"
Henrik Lundin7687ad52018-07-02 10:14:46 +020029#include "modules/audio_coding/neteq/tools/neteq_packet_source_input.h"
30#include "modules/audio_coding/neteq/tools/neteq_test.h"
Yves Gerey3e707812018-11-28 16:47:49 +010031#include "modules/include/module_common_types_public.h"
Niels Möller53382cb2018-11-27 14:05:08 +010032#include "modules/rtp_rtcp/include/rtcp_statistics.h"
Yves Gerey3e707812018-11-28 16:47:49 +010033#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020034#include "rtc_base/ignore_wundef.h"
Steve Anton10542f22019-01-11 09:11:00 -080035#include "rtc_base/message_digest.h"
Karl Wiberge40468b2017-11-22 10:42:26 +010036#include "rtc_base/numerics/safe_conversions.h"
Jonas Olsson366a50c2018-09-06 13:41:30 +020037#include "rtc_base/strings/string_builder.h"
Niels Möllera12c42a2018-07-25 16:05:48 +020038#include "rtc_base/system/arch.h"
Henrik Lundine9619f82017-11-27 14:05:27 +010039#include "test/field_trial.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020040#include "test/gtest.h"
Steve Anton10542f22019-01-11 09:11:00 -080041#include "test/testsupport/file_utils.h"
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000042
Mirko Bonadei2ab97f62019-07-18 13:44:12 +020043ABSL_FLAG(bool, gen_ref, false, "Generate reference files.");
turaj@webrtc.orga6101d72013-10-01 22:01:09 +000044
kwiberg5adaf732016-10-04 09:33:27 -070045namespace webrtc {
46
Ivo Creusenf1053ba2022-01-31 12:50:29 +010047#if defined(WEBRTC_LINUX) && defined(WEBRTC_ARCH_X86_64) && \
48 defined(WEBRTC_NETEQ_UNITTEST_BITEXACT) && \
49 (defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX)) && \
50 defined(WEBRTC_CODEC_ILBC)
minyue5f026d02015-12-16 07:36:04 -080051#define MAYBE_TestBitExactness TestBitExactness
kwiberg98ab3a42015-09-30 21:54:21 -070052#else
minyue5f026d02015-12-16 07:36:04 -080053#define MAYBE_TestBitExactness DISABLED_TestBitExactness
kwiberg98ab3a42015-09-30 21:54:21 -070054#endif
minyue5f026d02015-12-16 07:36:04 -080055TEST_F(NetEqDecodingTest, MAYBE_TestBitExactness) {
minyue49c454e2016-01-08 11:30:14 -080056 const std::string input_rtp_file =
57 webrtc::test::ResourcePath("audio_coding/neteq_universal_new", "rtp");
henrik.lundin@webrtc.org4e4b0982014-08-11 14:48:49 +000058
Jakob Ivarssonfa68ac02021-11-09 12:58:45 +010059 const std::string output_checksum =
Ivo Creusenf1053ba2022-01-31 12:50:29 +010060 "ba4fae83a52f5e9d95b0910f05d540114285697b";
minyue4f906772016-04-29 11:05:14 -070061
Jakob Ivarssonfa68ac02021-11-09 12:58:45 +010062 const std::string network_stats_checksum =
Ivo Creusenf1053ba2022-01-31 12:50:29 +010063 "fa878a8464ef1cb3d01503b7f927c3e2ce6f02c4";
minyue4f906772016-04-29 11:05:14 -070064
Yves Gerey665174f2018-06-19 15:03:05 +020065 DecodeAndCompare(input_rtp_file, output_checksum, network_stats_checksum,
Mirko Bonadei2ab97f62019-07-18 13:44:12 +020066 absl::GetFlag(FLAGS_gen_ref));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000067}
68
Ivo Creusenf1053ba2022-01-31 12:50:29 +010069#if defined(WEBRTC_LINUX) && defined(WEBRTC_ARCH_X86_64) && \
70 defined(WEBRTC_NETEQ_UNITTEST_BITEXACT) && defined(WEBRTC_CODEC_OPUS)
minyue93c08b72015-12-22 09:57:41 -080071#define MAYBE_TestOpusBitExactness TestOpusBitExactness
72#else
73#define MAYBE_TestOpusBitExactness DISABLED_TestOpusBitExactness
74#endif
Ivo Creusenf1053ba2022-01-31 12:50:29 +010075TEST_F(NetEqDecodingTest, MAYBE_TestOpusBitExactness) {
minyue93c08b72015-12-22 09:57:41 -080076 const std::string input_rtp_file =
77 webrtc::test::ResourcePath("audio_coding/neteq_opus", "rtp");
minyue93c08b72015-12-22 09:57:41 -080078
Ivo Creusenf1053ba2022-01-31 12:50:29 +010079 // The checksum depends on SSE being enabled, the second part is the non-SSE
80 // checksum.
81 const std::string output_checksum =
82 "6e23d8827ae54ca352e1448ae363bdfd2878c78e|"
83 "47cddbf3494b0233f48cb350676e704807237545";
minyue4f906772016-04-29 11:05:14 -070084
Yves Gerey75e22902019-09-06 03:07:55 +020085 const std::string network_stats_checksum =
Ivo Creusenf1053ba2022-01-31 12:50:29 +010086 "f89a9533dbb35a4c449b44c3ed120f7f1c7f90b6";
minyue4f906772016-04-29 11:05:14 -070087
Yves Gerey665174f2018-06-19 15:03:05 +020088 DecodeAndCompare(input_rtp_file, output_checksum, network_stats_checksum,
Mirko Bonadei2ab97f62019-07-18 13:44:12 +020089 absl::GetFlag(FLAGS_gen_ref));
minyue93c08b72015-12-22 09:57:41 -080090}
91
Ivo Creusenf1053ba2022-01-31 12:50:29 +010092#if defined(WEBRTC_LINUX) && defined(WEBRTC_ARCH_X86_64) && \
93 defined(WEBRTC_NETEQ_UNITTEST_BITEXACT) && defined(WEBRTC_CODEC_OPUS)
94#define MAYBE_TestOpusDtxBitExactness TestOpusDtxBitExactness
95#else
96#define MAYBE_TestOpusDtxBitExactness DISABLED_TestOpusDtxBitExactness
97#endif
98TEST_F(NetEqDecodingTest, MAYBE_TestOpusDtxBitExactness) {
Henrik Lundine9619f82017-11-27 14:05:27 +010099 const std::string input_rtp_file =
100 webrtc::test::ResourcePath("audio_coding/neteq_opus_dtx", "rtp");
101
Ivo Creusenf1053ba2022-01-31 12:50:29 +0100102 // The checksum depends on SSE being enabled, the second part is the non-SSE
103 // checksum.
104 const std::string output_checksum =
105 "5cea4a8e750842ac67b79e8e2ce6a0a1c01f8130|"
106 "e97e32a77355e7ce46a2dc2f43bf1c2805530fcb";
Henrik Lundine9619f82017-11-27 14:05:27 +0100107
108 const std::string network_stats_checksum =
Ivo Creusenf1053ba2022-01-31 12:50:29 +0100109 "dc8447b9fee1a21fd5d1f4045d62b982a3fb0215";
Henrik Lundine9619f82017-11-27 14:05:27 +0100110
Henrik Lundine9619f82017-11-27 14:05:27 +0100111 DecodeAndCompare(input_rtp_file, output_checksum, network_stats_checksum,
Mirko Bonadei2ab97f62019-07-18 13:44:12 +0200112 absl::GetFlag(FLAGS_gen_ref));
Henrik Lundine9619f82017-11-27 14:05:27 +0100113}
114
henrik.lundin@webrtc.org7cbc4f92014-10-07 06:37:39 +0000115// Use fax mode to avoid time-scaling. This is to simplify the testing of
116// packet waiting times in the packet buffer.
117class NetEqDecodingTestFaxMode : public NetEqDecodingTest {
118 protected:
119 NetEqDecodingTestFaxMode() : NetEqDecodingTest() {
Henrik Lundin7687ad52018-07-02 10:14:46 +0200120 config_.for_test_no_time_stretching = true;
henrik.lundin@webrtc.org7cbc4f92014-10-07 06:37:39 +0000121 }
Gustaf Ullbergb0a02072017-10-02 12:00:34 +0200122 void TestJitterBufferDelay(bool apply_packet_loss);
henrik.lundin@webrtc.org7cbc4f92014-10-07 06:37:39 +0000123};
124
125TEST_F(NetEqDecodingTestFaxMode, TestFrameWaitingTimeStatistics) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000126 // Insert 30 dummy packets at once. Each packet contains 10 ms 16 kHz audio.
127 size_t num_frames = 30;
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000128 const size_t kSamples = 10 * 16;
129 const size_t kPayloadBytes = kSamples * 2;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000130 for (size_t i = 0; i < num_frames; ++i) {
kwibergee2bac22015-11-11 10:34:00 -0800131 const uint8_t payload[kPayloadBytes] = {0};
henrik.lundin246ef3e2017-04-24 09:14:32 -0700132 RTPHeader rtp_info;
Mirko Bonadeia8110272017-10-18 14:22:50 +0200133 rtp_info.sequenceNumber = rtc::checked_cast<uint16_t>(i);
134 rtp_info.timestamp = rtc::checked_cast<uint32_t>(i * kSamples);
henrik.lundin246ef3e2017-04-24 09:14:32 -0700135 rtp_info.ssrc = 0x1234; // Just an arbitrary SSRC.
136 rtp_info.payloadType = 94; // PCM16b WB codec.
137 rtp_info.markerBit = 0;
Karl Wiberg45eb1352019-10-10 14:23:00 +0200138 ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000139 }
140 // Pull out all data.
141 for (size_t i = 0; i < num_frames; ++i) {
henrik.lundin7a926812016-05-12 13:51:28 -0700142 bool muted;
143 ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &muted));
henrik.lundin6d8e0112016-03-04 10:34:21 -0800144 ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000145 }
146
Henrik Lundin1bb8cf82015-08-25 13:08:04 +0200147 NetEqNetworkStatistics stats;
148 EXPECT_EQ(0, neteq_->NetworkStatistics(&stats));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000149 // Since all frames are dumped into NetEQ at once, but pulled out with 10 ms
150 // spacing (per definition), we expect the delay to increase with 10 ms for
Henrik Lundin1bb8cf82015-08-25 13:08:04 +0200151 // each packet. Thus, we are calculating the statistics for a series from 10
152 // to 300, in steps of 10 ms.
153 EXPECT_EQ(155, stats.mean_waiting_time_ms);
154 EXPECT_EQ(155, stats.median_waiting_time_ms);
155 EXPECT_EQ(10, stats.min_waiting_time_ms);
156 EXPECT_EQ(300, stats.max_waiting_time_ms);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000157
158 // Check statistics again and make sure it's been reset.
Henrik Lundin1bb8cf82015-08-25 13:08:04 +0200159 EXPECT_EQ(0, neteq_->NetworkStatistics(&stats));
160 EXPECT_EQ(-1, stats.mean_waiting_time_ms);
161 EXPECT_EQ(-1, stats.median_waiting_time_ms);
162 EXPECT_EQ(-1, stats.min_waiting_time_ms);
163 EXPECT_EQ(-1, stats.max_waiting_time_ms);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000164}
165
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000166
henrik.lundin@webrtc.orgb4e80e02014-05-15 07:14:00 +0000167TEST_F(NetEqDecodingTest, LongCngWithNegativeClockDrift) {
henrik.lundin@webrtc.orgfcfc6a92014-02-13 11:42:28 +0000168 // Apply a clock drift of -25 ms / s (sender faster than receiver).
169 const double kDriftFactor = 1000.0 / (1000.0 + 25.0);
henrik.lundin@webrtc.org24779fe2014-03-14 12:40:05 +0000170 const double kNetworkFreezeTimeMs = 0.0;
171 const bool kGetAudioDuringFreezeRecovery = false;
172 const int kDelayToleranceMs = 20;
173 const int kMaxTimeToSpeechMs = 100;
Yves Gerey665174f2018-06-19 15:03:05 +0200174 LongCngWithClockDrift(kDriftFactor, kNetworkFreezeTimeMs,
175 kGetAudioDuringFreezeRecovery, kDelayToleranceMs,
henrik.lundin@webrtc.org24779fe2014-03-14 12:40:05 +0000176 kMaxTimeToSpeechMs);
henrik.lundin@webrtc.orgfcfc6a92014-02-13 11:42:28 +0000177}
178
henrik.lundin@webrtc.orgb4e80e02014-05-15 07:14:00 +0000179TEST_F(NetEqDecodingTest, LongCngWithPositiveClockDrift) {
henrik.lundin@webrtc.orgfcfc6a92014-02-13 11:42:28 +0000180 // Apply a clock drift of +25 ms / s (sender slower than receiver).
181 const double kDriftFactor = 1000.0 / (1000.0 - 25.0);
henrik.lundin@webrtc.org24779fe2014-03-14 12:40:05 +0000182 const double kNetworkFreezeTimeMs = 0.0;
183 const bool kGetAudioDuringFreezeRecovery = false;
Jakob Ivarsson507f4342019-09-03 13:04:41 +0200184 const int kDelayToleranceMs = 40;
henrik.lundin@webrtc.org24779fe2014-03-14 12:40:05 +0000185 const int kMaxTimeToSpeechMs = 100;
Yves Gerey665174f2018-06-19 15:03:05 +0200186 LongCngWithClockDrift(kDriftFactor, kNetworkFreezeTimeMs,
187 kGetAudioDuringFreezeRecovery, kDelayToleranceMs,
henrik.lundin@webrtc.org24779fe2014-03-14 12:40:05 +0000188 kMaxTimeToSpeechMs);
189}
190
henrik.lundin@webrtc.orgb4e80e02014-05-15 07:14:00 +0000191TEST_F(NetEqDecodingTest, LongCngWithNegativeClockDriftNetworkFreeze) {
henrik.lundin@webrtc.org24779fe2014-03-14 12:40:05 +0000192 // Apply a clock drift of -25 ms / s (sender faster than receiver).
193 const double kDriftFactor = 1000.0 / (1000.0 + 25.0);
194 const double kNetworkFreezeTimeMs = 5000.0;
195 const bool kGetAudioDuringFreezeRecovery = false;
Jakob Ivarssona36c5912019-06-27 10:12:02 +0200196 const int kDelayToleranceMs = 60;
henrik.lundin@webrtc.org24779fe2014-03-14 12:40:05 +0000197 const int kMaxTimeToSpeechMs = 200;
Yves Gerey665174f2018-06-19 15:03:05 +0200198 LongCngWithClockDrift(kDriftFactor, kNetworkFreezeTimeMs,
199 kGetAudioDuringFreezeRecovery, kDelayToleranceMs,
henrik.lundin@webrtc.org24779fe2014-03-14 12:40:05 +0000200 kMaxTimeToSpeechMs);
201}
202
henrik.lundin@webrtc.orgb4e80e02014-05-15 07:14:00 +0000203TEST_F(NetEqDecodingTest, LongCngWithPositiveClockDriftNetworkFreeze) {
henrik.lundin@webrtc.org24779fe2014-03-14 12:40:05 +0000204 // Apply a clock drift of +25 ms / s (sender slower than receiver).
205 const double kDriftFactor = 1000.0 / (1000.0 - 25.0);
206 const double kNetworkFreezeTimeMs = 5000.0;
207 const bool kGetAudioDuringFreezeRecovery = false;
Jakob Ivarsson507f4342019-09-03 13:04:41 +0200208 const int kDelayToleranceMs = 40;
henrik.lundin@webrtc.org24779fe2014-03-14 12:40:05 +0000209 const int kMaxTimeToSpeechMs = 100;
Yves Gerey665174f2018-06-19 15:03:05 +0200210 LongCngWithClockDrift(kDriftFactor, kNetworkFreezeTimeMs,
211 kGetAudioDuringFreezeRecovery, kDelayToleranceMs,
henrik.lundin@webrtc.org24779fe2014-03-14 12:40:05 +0000212 kMaxTimeToSpeechMs);
213}
214
henrik.lundin@webrtc.orgb4e80e02014-05-15 07:14:00 +0000215TEST_F(NetEqDecodingTest, LongCngWithPositiveClockDriftNetworkFreezeExtraPull) {
henrik.lundin@webrtc.org24779fe2014-03-14 12:40:05 +0000216 // Apply a clock drift of +25 ms / s (sender slower than receiver).
217 const double kDriftFactor = 1000.0 / (1000.0 - 25.0);
218 const double kNetworkFreezeTimeMs = 5000.0;
219 const bool kGetAudioDuringFreezeRecovery = true;
Jakob Ivarsson507f4342019-09-03 13:04:41 +0200220 const int kDelayToleranceMs = 40;
henrik.lundin@webrtc.org24779fe2014-03-14 12:40:05 +0000221 const int kMaxTimeToSpeechMs = 100;
Yves Gerey665174f2018-06-19 15:03:05 +0200222 LongCngWithClockDrift(kDriftFactor, kNetworkFreezeTimeMs,
223 kGetAudioDuringFreezeRecovery, kDelayToleranceMs,
henrik.lundin@webrtc.org24779fe2014-03-14 12:40:05 +0000224 kMaxTimeToSpeechMs);
225}
226
henrik.lundin@webrtc.orgb4e80e02014-05-15 07:14:00 +0000227TEST_F(NetEqDecodingTest, LongCngWithoutClockDrift) {
henrik.lundin@webrtc.org24779fe2014-03-14 12:40:05 +0000228 const double kDriftFactor = 1.0; // No drift.
229 const double kNetworkFreezeTimeMs = 0.0;
230 const bool kGetAudioDuringFreezeRecovery = false;
231 const int kDelayToleranceMs = 10;
232 const int kMaxTimeToSpeechMs = 50;
Yves Gerey665174f2018-06-19 15:03:05 +0200233 LongCngWithClockDrift(kDriftFactor, kNetworkFreezeTimeMs,
234 kGetAudioDuringFreezeRecovery, kDelayToleranceMs,
henrik.lundin@webrtc.org24779fe2014-03-14 12:40:05 +0000235 kMaxTimeToSpeechMs);
henrik.lundin@webrtc.orgfcfc6a92014-02-13 11:42:28 +0000236}
237
henrik.lundin@webrtc.orgb4e80e02014-05-15 07:14:00 +0000238TEST_F(NetEqDecodingTest, UnknownPayloadType) {
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000239 const size_t kPayloadBytes = 100;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000240 uint8_t payload[kPayloadBytes] = {0};
henrik.lundin246ef3e2017-04-24 09:14:32 -0700241 RTPHeader rtp_info;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000242 PopulateRtpInfo(0, 0, &rtp_info);
henrik.lundin246ef3e2017-04-24 09:14:32 -0700243 rtp_info.payloadType = 1; // Not registered as a decoder.
Karl Wiberg45eb1352019-10-10 14:23:00 +0200244 EXPECT_EQ(NetEq::kFail, neteq_->InsertPacket(rtp_info, payload));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000245}
246
Peter Boströme2976c82016-01-04 22:44:05 +0100247#if defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX)
ivoc72c08ed2016-01-20 07:26:24 -0800248#define MAYBE_DecoderError DecoderError
249#else
250#define MAYBE_DecoderError DISABLED_DecoderError
251#endif
252
Peter Boströme2976c82016-01-04 22:44:05 +0100253TEST_F(NetEqDecodingTest, MAYBE_DecoderError) {
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000254 const size_t kPayloadBytes = 100;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000255 uint8_t payload[kPayloadBytes] = {0};
henrik.lundin246ef3e2017-04-24 09:14:32 -0700256 RTPHeader rtp_info;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000257 PopulateRtpInfo(0, 0, &rtp_info);
henrik.lundin246ef3e2017-04-24 09:14:32 -0700258 rtp_info.payloadType = 103; // iSAC, but the payload is invalid.
Karl Wiberg45eb1352019-10-10 14:23:00 +0200259 EXPECT_EQ(0, neteq_->InsertPacket(rtp_info, payload));
Artem Titovd00ce742021-07-28 20:00:17 +0200260 // Set all of `out_data_` to 1, and verify that it was set to 0 by the call
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000261 // to GetAudio.
yujo36b1a5f2017-06-12 12:45:32 -0700262 int16_t* out_frame_data = out_frame_.mutable_data();
henrik.lundin6d8e0112016-03-04 10:34:21 -0800263 for (size_t i = 0; i < AudioFrame::kMaxDataSizeSamples; ++i) {
yujo36b1a5f2017-06-12 12:45:32 -0700264 out_frame_data[i] = 1;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000265 }
henrik.lundin7a926812016-05-12 13:51:28 -0700266 bool muted;
267 EXPECT_EQ(NetEq::kFail, neteq_->GetAudio(&out_frame_, &muted));
268 ASSERT_FALSE(muted);
ivoc72c08ed2016-01-20 07:26:24 -0800269
yujo36b1a5f2017-06-12 12:45:32 -0700270 // Verify that the first 160 samples are set to 0.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000271 static const int kExpectedOutputLength = 160; // 10 ms at 16 kHz sample rate.
yujo36b1a5f2017-06-12 12:45:32 -0700272 const int16_t* const_out_frame_data = out_frame_.data();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000273 for (int i = 0; i < kExpectedOutputLength; ++i) {
Jonas Olsson366a50c2018-09-06 13:41:30 +0200274 rtc::StringBuilder ss;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000275 ss << "i = " << i;
276 SCOPED_TRACE(ss.str()); // Print out the parameter values on failure.
yujo36b1a5f2017-06-12 12:45:32 -0700277 EXPECT_EQ(0, const_out_frame_data[i]);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000278 }
279}
280
henrik.lundin@webrtc.orgb4e80e02014-05-15 07:14:00 +0000281TEST_F(NetEqDecodingTest, GetAudioBeforeInsertPacket) {
Artem Titovd00ce742021-07-28 20:00:17 +0200282 // Set all of `out_data_` to 1, and verify that it was set to 0 by the call
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000283 // to GetAudio.
yujo36b1a5f2017-06-12 12:45:32 -0700284 int16_t* out_frame_data = out_frame_.mutable_data();
henrik.lundin6d8e0112016-03-04 10:34:21 -0800285 for (size_t i = 0; i < AudioFrame::kMaxDataSizeSamples; ++i) {
yujo36b1a5f2017-06-12 12:45:32 -0700286 out_frame_data[i] = 1;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000287 }
henrik.lundin7a926812016-05-12 13:51:28 -0700288 bool muted;
289 EXPECT_EQ(0, neteq_->GetAudio(&out_frame_, &muted));
290 ASSERT_FALSE(muted);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000291 // Verify that the first block of samples is set to 0.
292 static const int kExpectedOutputLength =
293 kInitSampleRateHz / 100; // 10 ms at initial sample rate.
yujo36b1a5f2017-06-12 12:45:32 -0700294 const int16_t* const_out_frame_data = out_frame_.data();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000295 for (int i = 0; i < kExpectedOutputLength; ++i) {
Jonas Olsson366a50c2018-09-06 13:41:30 +0200296 rtc::StringBuilder ss;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000297 ss << "i = " << i;
298 SCOPED_TRACE(ss.str()); // Print out the parameter values on failure.
yujo36b1a5f2017-06-12 12:45:32 -0700299 EXPECT_EQ(0, const_out_frame_data[i]);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000300 }
henrik.lundind89814b2015-11-23 06:49:25 -0800301 // Verify that the sample rate did not change from the initial configuration.
302 EXPECT_EQ(config_.sample_rate_hz, neteq_->last_output_sample_rate_hz());
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000303}
turaj@webrtc.orgff43c852013-09-25 00:07:27 +0000304
henrik.lundin@webrtc.org9b8102c2014-08-21 08:27:44 +0000305class NetEqBgnTest : public NetEqDecodingTest {
henrik.lundin@webrtc.orgea257842014-08-07 12:27:37 +0000306 protected:
henrik.lundin@webrtc.org9b8102c2014-08-21 08:27:44 +0000307 void CheckBgn(int sampling_rate_hz) {
Peter Kastingdce40cf2015-08-24 14:52:23 -0700308 size_t expected_samples_per_channel = 0;
henrik.lundin@webrtc.orgea257842014-08-07 12:27:37 +0000309 uint8_t payload_type = 0xFF; // Invalid.
310 if (sampling_rate_hz == 8000) {
311 expected_samples_per_channel = kBlockSize8kHz;
312 payload_type = 93; // PCM 16, 8 kHz.
313 } else if (sampling_rate_hz == 16000) {
314 expected_samples_per_channel = kBlockSize16kHz;
315 payload_type = 94; // PCM 16, 16 kHZ.
316 } else if (sampling_rate_hz == 32000) {
317 expected_samples_per_channel = kBlockSize32kHz;
318 payload_type = 95; // PCM 16, 32 kHz.
319 } else {
320 ASSERT_TRUE(false); // Unsupported test case.
321 }
turaj@webrtc.orgff43c852013-09-25 00:07:27 +0000322
henrik.lundin6d8e0112016-03-04 10:34:21 -0800323 AudioFrame output;
henrik.lundin@webrtc.org9b8102c2014-08-21 08:27:44 +0000324 test::AudioLoop input;
325 // We are using the same 32 kHz input file for all tests, regardless of
Artem Titovd00ce742021-07-28 20:00:17 +0200326 // `sampling_rate_hz`. The output may sound weird, but the test is still
henrik.lundin@webrtc.org9b8102c2014-08-21 08:27:44 +0000327 // valid.
328 ASSERT_TRUE(input.Init(
329 webrtc::test::ResourcePath("audio_coding/testfile32kHz", "pcm"),
330 10 * sampling_rate_hz, // Max 10 seconds loop length.
Peter Kastingdce40cf2015-08-24 14:52:23 -0700331 expected_samples_per_channel));
henrik.lundin@webrtc.orgea257842014-08-07 12:27:37 +0000332
333 // Payload of 10 ms of PCM16 32 kHz.
334 uint8_t payload[kBlockSize32kHz * sizeof(int16_t)];
henrik.lundin246ef3e2017-04-24 09:14:32 -0700335 RTPHeader rtp_info;
henrik.lundin@webrtc.orgea257842014-08-07 12:27:37 +0000336 PopulateRtpInfo(0, 0, &rtp_info);
henrik.lundin246ef3e2017-04-24 09:14:32 -0700337 rtp_info.payloadType = payload_type;
henrik.lundin@webrtc.orgea257842014-08-07 12:27:37 +0000338
henrik.lundin7a926812016-05-12 13:51:28 -0700339 bool muted;
henrik.lundin@webrtc.orgea257842014-08-07 12:27:37 +0000340 for (int n = 0; n < 10; ++n) { // Insert few packets and get audio.
kwiberg288886b2015-11-06 01:21:35 -0800341 auto block = input.GetNextBlock();
342 ASSERT_EQ(expected_samples_per_channel, block.size());
343 size_t enc_len_bytes =
344 WebRtcPcm16b_Encode(block.data(), block.size(), payload);
henrik.lundin@webrtc.org9b8102c2014-08-21 08:27:44 +0000345 ASSERT_EQ(enc_len_bytes, expected_samples_per_channel * 2);
346
Karl Wiberg45eb1352019-10-10 14:23:00 +0200347 ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, rtc::ArrayView<const uint8_t>(
348 payload, enc_len_bytes)));
henrik.lundin6d8e0112016-03-04 10:34:21 -0800349 output.Reset();
henrik.lundin7a926812016-05-12 13:51:28 -0700350 ASSERT_EQ(0, neteq_->GetAudio(&output, &muted));
henrik.lundin6d8e0112016-03-04 10:34:21 -0800351 ASSERT_EQ(1u, output.num_channels_);
352 ASSERT_EQ(expected_samples_per_channel, output.samples_per_channel_);
henrik.lundin55480f52016-03-08 02:37:57 -0800353 ASSERT_EQ(AudioFrame::kNormalSpeech, output.speech_type_);
henrik.lundin@webrtc.orgea257842014-08-07 12:27:37 +0000354
355 // Next packet.
Yves Gerey665174f2018-06-19 15:03:05 +0200356 rtp_info.timestamp +=
357 rtc::checked_cast<uint32_t>(expected_samples_per_channel);
henrik.lundin246ef3e2017-04-24 09:14:32 -0700358 rtp_info.sequenceNumber++;
henrik.lundin@webrtc.orgea257842014-08-07 12:27:37 +0000359 }
360
henrik.lundin6d8e0112016-03-04 10:34:21 -0800361 output.Reset();
henrik.lundin@webrtc.orgea257842014-08-07 12:27:37 +0000362
363 // Get audio without inserting packets, expecting PLC and PLC-to-CNG. Pull
364 // one frame without checking speech-type. This is the first frame pulled
365 // without inserting any packet, and might not be labeled as PLC.
henrik.lundin7a926812016-05-12 13:51:28 -0700366 ASSERT_EQ(0, neteq_->GetAudio(&output, &muted));
henrik.lundin6d8e0112016-03-04 10:34:21 -0800367 ASSERT_EQ(1u, output.num_channels_);
368 ASSERT_EQ(expected_samples_per_channel, output.samples_per_channel_);
henrik.lundin@webrtc.orgea257842014-08-07 12:27:37 +0000369
370 // To be able to test the fading of background noise we need at lease to
371 // pull 611 frames.
372 const int kFadingThreshold = 611;
373
374 // Test several CNG-to-PLC packet for the expected behavior. The number 20
375 // is arbitrary, but sufficiently large to test enough number of frames.
376 const int kNumPlcToCngTestFrames = 20;
377 bool plc_to_cng = false;
378 for (int n = 0; n < kFadingThreshold + kNumPlcToCngTestFrames; ++n) {
henrik.lundin6d8e0112016-03-04 10:34:21 -0800379 output.Reset();
yujo36b1a5f2017-06-12 12:45:32 -0700380 // Set to non-zero.
381 memset(output.mutable_data(), 1, AudioFrame::kMaxDataSizeBytes);
henrik.lundin7a926812016-05-12 13:51:28 -0700382 ASSERT_EQ(0, neteq_->GetAudio(&output, &muted));
383 ASSERT_FALSE(muted);
henrik.lundin6d8e0112016-03-04 10:34:21 -0800384 ASSERT_EQ(1u, output.num_channels_);
385 ASSERT_EQ(expected_samples_per_channel, output.samples_per_channel_);
henrik.lundin55480f52016-03-08 02:37:57 -0800386 if (output.speech_type_ == AudioFrame::kPLCCNG) {
henrik.lundin@webrtc.orgea257842014-08-07 12:27:37 +0000387 plc_to_cng = true;
388 double sum_squared = 0;
yujo36b1a5f2017-06-12 12:45:32 -0700389 const int16_t* output_data = output.data();
henrik.lundin6d8e0112016-03-04 10:34:21 -0800390 for (size_t k = 0;
391 k < output.num_channels_ * output.samples_per_channel_; ++k)
yujo36b1a5f2017-06-12 12:45:32 -0700392 sum_squared += output_data[k] * output_data[k];
Henrik Lundin67190172018-04-20 15:34:48 +0200393 EXPECT_EQ(0, sum_squared);
henrik.lundin@webrtc.orgea257842014-08-07 12:27:37 +0000394 } else {
henrik.lundin55480f52016-03-08 02:37:57 -0800395 EXPECT_EQ(AudioFrame::kPLC, output.speech_type_);
henrik.lundin@webrtc.orgea257842014-08-07 12:27:37 +0000396 }
397 }
398 EXPECT_TRUE(plc_to_cng); // Just to be sure that PLC-to-CNG has occurred.
399 }
400};
401
Henrik Lundin67190172018-04-20 15:34:48 +0200402TEST_F(NetEqBgnTest, RunTest) {
henrik.lundin@webrtc.org9b8102c2014-08-21 08:27:44 +0000403 CheckBgn(8000);
404 CheckBgn(16000);
405 CheckBgn(32000);
406}
henrik.lundin@webrtc.orgea257842014-08-07 12:27:37 +0000407
turaj@webrtc.org78b41a02013-11-22 20:27:07 +0000408TEST_F(NetEqDecodingTest, SequenceNumberWrap) {
409 // Start with a sequence number that will soon wrap.
410 std::set<uint16_t> drop_seq_numbers; // Don't drop any packets.
411 WrapTest(0xFFFF - 10, 0, drop_seq_numbers, true, false);
412}
413
414TEST_F(NetEqDecodingTest, SequenceNumberWrapAndDrop) {
415 // Start with a sequence number that will soon wrap.
416 std::set<uint16_t> drop_seq_numbers;
417 drop_seq_numbers.insert(0xFFFF);
418 drop_seq_numbers.insert(0x0);
419 WrapTest(0xFFFF - 10, 0, drop_seq_numbers, true, false);
420}
421
422TEST_F(NetEqDecodingTest, TimestampWrap) {
423 // Start with a timestamp that will soon wrap.
424 std::set<uint16_t> drop_seq_numbers;
425 WrapTest(0, 0xFFFFFFFF - 3000, drop_seq_numbers, false, true);
426}
427
428TEST_F(NetEqDecodingTest, TimestampAndSequenceNumberWrap) {
429 // Start with a timestamp and a sequence number that will wrap at the same
430 // time.
431 std::set<uint16_t> drop_seq_numbers;
432 WrapTest(0xFFFF - 10, 0xFFFFFFFF - 5000, drop_seq_numbers, true, true);
433}
434
Yves Gerey3a65f392019-11-11 18:05:42 +0100435TEST_F(NetEqDecodingTest, DiscardDuplicateCng) {
henrik.lundin@webrtc.orgca8cb952014-03-12 10:26:52 +0000436 uint16_t seq_no = 0;
437 uint32_t timestamp = 0;
438 const int kFrameSizeMs = 10;
439 const int kSampleRateKhz = 16;
440 const int kSamples = kFrameSizeMs * kSampleRateKhz;
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000441 const size_t kPayloadBytes = kSamples * 2;
henrik.lundin@webrtc.orgca8cb952014-03-12 10:26:52 +0000442
Yves Gerey665174f2018-06-19 15:03:05 +0200443 const int algorithmic_delay_samples =
444 std::max(algorithmic_delay_ms_ * kSampleRateKhz, 5 * kSampleRateKhz / 8);
henrik.lundin@webrtc.orgc93437e2014-12-01 11:42:42 +0000445 // Insert three speech packets. Three are needed to get the frame length
henrik.lundin@webrtc.orgca8cb952014-03-12 10:26:52 +0000446 // correct.
henrik.lundin@webrtc.orgca8cb952014-03-12 10:26:52 +0000447 uint8_t payload[kPayloadBytes] = {0};
henrik.lundin246ef3e2017-04-24 09:14:32 -0700448 RTPHeader rtp_info;
henrik.lundin7a926812016-05-12 13:51:28 -0700449 bool muted;
henrik.lundin@webrtc.orgca8cb952014-03-12 10:26:52 +0000450 for (int i = 0; i < 3; ++i) {
451 PopulateRtpInfo(seq_no, timestamp, &rtp_info);
Karl Wiberg45eb1352019-10-10 14:23:00 +0200452 ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload));
henrik.lundin@webrtc.orgca8cb952014-03-12 10:26:52 +0000453 ++seq_no;
454 timestamp += kSamples;
455
456 // Pull audio once.
henrik.lundin7a926812016-05-12 13:51:28 -0700457 ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &muted));
henrik.lundin6d8e0112016-03-04 10:34:21 -0800458 ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_);
henrik.lundin@webrtc.orgca8cb952014-03-12 10:26:52 +0000459 }
460 // Verify speech output.
henrik.lundin55480f52016-03-08 02:37:57 -0800461 EXPECT_EQ(AudioFrame::kNormalSpeech, out_frame_.speech_type_);
henrik.lundin@webrtc.orgca8cb952014-03-12 10:26:52 +0000462
463 // Insert same CNG packet twice.
464 const int kCngPeriodMs = 100;
465 const int kCngPeriodSamples = kCngPeriodMs * kSampleRateKhz;
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000466 size_t payload_len;
henrik.lundin@webrtc.orgca8cb952014-03-12 10:26:52 +0000467 PopulateCng(seq_no, timestamp, &rtp_info, payload, &payload_len);
468 // This is the first time this CNG packet is inserted.
Karl Wiberg45eb1352019-10-10 14:23:00 +0200469 ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, rtc::ArrayView<const uint8_t>(
470 payload, payload_len)));
henrik.lundin@webrtc.orgca8cb952014-03-12 10:26:52 +0000471
472 // Pull audio once and make sure CNG is played.
henrik.lundin7a926812016-05-12 13:51:28 -0700473 ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &muted));
henrik.lundin6d8e0112016-03-04 10:34:21 -0800474 ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_);
henrik.lundin55480f52016-03-08 02:37:57 -0800475 EXPECT_EQ(AudioFrame::kCNG, out_frame_.speech_type_);
henrik.lundin114c1b32017-04-26 07:47:32 -0700476 EXPECT_FALSE(
477 neteq_->GetPlayoutTimestamp()); // Returns empty value during CNG.
henrik.lundin0d96ab72016-04-06 12:28:26 -0700478 EXPECT_EQ(timestamp - algorithmic_delay_samples,
479 out_frame_.timestamp_ + out_frame_.samples_per_channel_);
henrik.lundin@webrtc.orgca8cb952014-03-12 10:26:52 +0000480
481 // Insert the same CNG packet again. Note that at this point it is old, since
482 // we have already decoded the first copy of it.
Karl Wiberg45eb1352019-10-10 14:23:00 +0200483 ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, rtc::ArrayView<const uint8_t>(
484 payload, payload_len)));
henrik.lundin@webrtc.orgca8cb952014-03-12 10:26:52 +0000485
Artem Titovd00ce742021-07-28 20:00:17 +0200486 // Pull audio until we have played `kCngPeriodMs` of CNG. Start at 10 ms since
henrik.lundin@webrtc.orgca8cb952014-03-12 10:26:52 +0000487 // we have already pulled out CNG once.
488 for (int cng_time_ms = 10; cng_time_ms < kCngPeriodMs; cng_time_ms += 10) {
henrik.lundin7a926812016-05-12 13:51:28 -0700489 ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &muted));
henrik.lundin6d8e0112016-03-04 10:34:21 -0800490 ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_);
henrik.lundin55480f52016-03-08 02:37:57 -0800491 EXPECT_EQ(AudioFrame::kCNG, out_frame_.speech_type_);
henrik.lundin114c1b32017-04-26 07:47:32 -0700492 EXPECT_FALSE(
493 neteq_->GetPlayoutTimestamp()); // Returns empty value during CNG.
turaj@webrtc.org8d1cdaa2014-04-11 18:47:55 +0000494 EXPECT_EQ(timestamp - algorithmic_delay_samples,
henrik.lundin0d96ab72016-04-06 12:28:26 -0700495 out_frame_.timestamp_ + out_frame_.samples_per_channel_);
henrik.lundin@webrtc.orgca8cb952014-03-12 10:26:52 +0000496 }
497
henrik.lundin@webrtc.orgca8cb952014-03-12 10:26:52 +0000498 ++seq_no;
499 timestamp += kCngPeriodSamples;
Jakob Ivarssonfa68ac02021-11-09 12:58:45 +0100500 uint32_t first_speech_timestamp = timestamp;
501 // Insert speech again.
502 for (int i = 0; i < 3; ++i) {
503 PopulateRtpInfo(seq_no, timestamp, &rtp_info);
504 ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload));
505 ++seq_no;
506 timestamp += kSamples;
507 }
henrik.lundin@webrtc.orgca8cb952014-03-12 10:26:52 +0000508
509 // Pull audio once and verify that the output is speech again.
henrik.lundin7a926812016-05-12 13:51:28 -0700510 ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &muted));
henrik.lundin6d8e0112016-03-04 10:34:21 -0800511 ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_);
henrik.lundin55480f52016-03-08 02:37:57 -0800512 EXPECT_EQ(AudioFrame::kNormalSpeech, out_frame_.speech_type_);
Danil Chapovalovb6021232018-06-19 13:26:36 +0200513 absl::optional<uint32_t> playout_timestamp = neteq_->GetPlayoutTimestamp();
henrik.lundin0d96ab72016-04-06 12:28:26 -0700514 ASSERT_TRUE(playout_timestamp);
Jakob Ivarssonfa68ac02021-11-09 12:58:45 +0100515 EXPECT_EQ(first_speech_timestamp + kSamples - algorithmic_delay_samples,
henrik.lundin0d96ab72016-04-06 12:28:26 -0700516 *playout_timestamp);
wu@webrtc.org94454b72014-06-05 20:34:08 +0000517}
518
henrik.lundin@webrtc.orgc93437e2014-12-01 11:42:42 +0000519TEST_F(NetEqDecodingTest, CngFirst) {
520 uint16_t seq_no = 0;
521 uint32_t timestamp = 0;
522 const int kFrameSizeMs = 10;
523 const int kSampleRateKhz = 16;
524 const int kSamples = kFrameSizeMs * kSampleRateKhz;
525 const int kPayloadBytes = kSamples * 2;
526 const int kCngPeriodMs = 100;
527 const int kCngPeriodSamples = kCngPeriodMs * kSampleRateKhz;
528 size_t payload_len;
529
530 uint8_t payload[kPayloadBytes] = {0};
henrik.lundin246ef3e2017-04-24 09:14:32 -0700531 RTPHeader rtp_info;
henrik.lundin@webrtc.orgc93437e2014-12-01 11:42:42 +0000532
533 PopulateCng(seq_no, timestamp, &rtp_info, payload, &payload_len);
Karl Wiberg45eb1352019-10-10 14:23:00 +0200534 ASSERT_EQ(NetEq::kOK,
535 neteq_->InsertPacket(
536 rtp_info, rtc::ArrayView<const uint8_t>(payload, payload_len)));
henrik.lundin@webrtc.orgc93437e2014-12-01 11:42:42 +0000537 ++seq_no;
538 timestamp += kCngPeriodSamples;
539
540 // Pull audio once and make sure CNG is played.
henrik.lundin7a926812016-05-12 13:51:28 -0700541 bool muted;
542 ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &muted));
henrik.lundin6d8e0112016-03-04 10:34:21 -0800543 ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_);
henrik.lundin55480f52016-03-08 02:37:57 -0800544 EXPECT_EQ(AudioFrame::kCNG, out_frame_.speech_type_);
henrik.lundin@webrtc.orgc93437e2014-12-01 11:42:42 +0000545
546 // Insert some speech packets.
henrik.lundin549d80b2016-08-25 00:44:24 -0700547 const uint32_t first_speech_timestamp = timestamp;
548 int timeout_counter = 0;
549 do {
550 ASSERT_LT(timeout_counter++, 20) << "Test timed out";
henrik.lundin@webrtc.orgc93437e2014-12-01 11:42:42 +0000551 PopulateRtpInfo(seq_no, timestamp, &rtp_info);
Karl Wiberg45eb1352019-10-10 14:23:00 +0200552 ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload));
henrik.lundin@webrtc.orgc93437e2014-12-01 11:42:42 +0000553 ++seq_no;
554 timestamp += kSamples;
555
556 // Pull audio once.
henrik.lundin7a926812016-05-12 13:51:28 -0700557 ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &muted));
henrik.lundin6d8e0112016-03-04 10:34:21 -0800558 ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_);
henrik.lundin549d80b2016-08-25 00:44:24 -0700559 } while (!IsNewerTimestamp(out_frame_.timestamp_, first_speech_timestamp));
henrik.lundin@webrtc.orgc93437e2014-12-01 11:42:42 +0000560 // Verify speech output.
henrik.lundin55480f52016-03-08 02:37:57 -0800561 EXPECT_EQ(AudioFrame::kNormalSpeech, out_frame_.speech_type_);
henrik.lundin@webrtc.orgc93437e2014-12-01 11:42:42 +0000562}
henrik.lundin7a926812016-05-12 13:51:28 -0700563
564class NetEqDecodingTestWithMutedState : public NetEqDecodingTest {
565 public:
566 NetEqDecodingTestWithMutedState() : NetEqDecodingTest() {
567 config_.enable_muted_state = true;
568 }
569
570 protected:
571 static constexpr size_t kSamples = 10 * 16;
572 static constexpr size_t kPayloadBytes = kSamples * 2;
573
574 void InsertPacket(uint32_t rtp_timestamp) {
575 uint8_t payload[kPayloadBytes] = {0};
henrik.lundin246ef3e2017-04-24 09:14:32 -0700576 RTPHeader rtp_info;
henrik.lundin7a926812016-05-12 13:51:28 -0700577 PopulateRtpInfo(0, rtp_timestamp, &rtp_info);
Karl Wiberg45eb1352019-10-10 14:23:00 +0200578 EXPECT_EQ(0, neteq_->InsertPacket(rtp_info, payload));
henrik.lundin7a926812016-05-12 13:51:28 -0700579 }
580
henrik.lundin42feb512016-09-20 06:51:40 -0700581 void InsertCngPacket(uint32_t rtp_timestamp) {
582 uint8_t payload[kPayloadBytes] = {0};
henrik.lundin246ef3e2017-04-24 09:14:32 -0700583 RTPHeader rtp_info;
henrik.lundin42feb512016-09-20 06:51:40 -0700584 size_t payload_len;
585 PopulateCng(0, rtp_timestamp, &rtp_info, payload, &payload_len);
Karl Wiberg45eb1352019-10-10 14:23:00 +0200586 EXPECT_EQ(NetEq::kOK,
587 neteq_->InsertPacket(rtp_info, rtc::ArrayView<const uint8_t>(
588 payload, payload_len)));
henrik.lundin42feb512016-09-20 06:51:40 -0700589 }
590
henrik.lundin7a926812016-05-12 13:51:28 -0700591 bool GetAudioReturnMuted() {
592 bool muted;
593 EXPECT_EQ(0, neteq_->GetAudio(&out_frame_, &muted));
594 return muted;
595 }
596
597 void GetAudioUntilMuted() {
598 while (!GetAudioReturnMuted()) {
599 ASSERT_LT(counter_++, 1000) << "Test timed out";
600 }
601 }
602
603 void GetAudioUntilNormal() {
604 bool muted = false;
605 while (out_frame_.speech_type_ != AudioFrame::kNormalSpeech) {
606 EXPECT_EQ(0, neteq_->GetAudio(&out_frame_, &muted));
607 ASSERT_LT(counter_++, 1000) << "Test timed out";
608 }
609 EXPECT_FALSE(muted);
610 }
611
612 int counter_ = 0;
613};
614
615// Verifies that NetEq goes in and out of muted state as expected.
616TEST_F(NetEqDecodingTestWithMutedState, MutedState) {
617 // Insert one speech packet.
618 InsertPacket(0);
619 // Pull out audio once and expect it not to be muted.
620 EXPECT_FALSE(GetAudioReturnMuted());
621 // Pull data until faded out.
622 GetAudioUntilMuted();
henrik.lundina4491072017-07-06 05:23:53 -0700623 EXPECT_TRUE(out_frame_.muted());
henrik.lundin7a926812016-05-12 13:51:28 -0700624
625 // Verify that output audio is not written during muted mode. Other parameters
626 // should be correct, though.
627 AudioFrame new_frame;
yujo36b1a5f2017-06-12 12:45:32 -0700628 int16_t* frame_data = new_frame.mutable_data();
629 for (size_t i = 0; i < AudioFrame::kMaxDataSizeSamples; i++) {
630 frame_data[i] = 17;
henrik.lundin7a926812016-05-12 13:51:28 -0700631 }
632 bool muted;
633 EXPECT_EQ(0, neteq_->GetAudio(&new_frame, &muted));
634 EXPECT_TRUE(muted);
henrik.lundina4491072017-07-06 05:23:53 -0700635 EXPECT_TRUE(out_frame_.muted());
yujo36b1a5f2017-06-12 12:45:32 -0700636 for (size_t i = 0; i < AudioFrame::kMaxDataSizeSamples; i++) {
637 EXPECT_EQ(17, frame_data[i]);
henrik.lundin7a926812016-05-12 13:51:28 -0700638 }
639 EXPECT_EQ(out_frame_.timestamp_ + out_frame_.samples_per_channel_,
640 new_frame.timestamp_);
641 EXPECT_EQ(out_frame_.samples_per_channel_, new_frame.samples_per_channel_);
642 EXPECT_EQ(out_frame_.sample_rate_hz_, new_frame.sample_rate_hz_);
643 EXPECT_EQ(out_frame_.num_channels_, new_frame.num_channels_);
644 EXPECT_EQ(out_frame_.speech_type_, new_frame.speech_type_);
645 EXPECT_EQ(out_frame_.vad_activity_, new_frame.vad_activity_);
646
647 // Insert new data. Timestamp is corrected for the time elapsed since the last
648 // packet. Verify that normal operation resumes.
649 InsertPacket(kSamples * counter_);
650 GetAudioUntilNormal();
henrik.lundina4491072017-07-06 05:23:53 -0700651 EXPECT_FALSE(out_frame_.muted());
henrik.lundin612c25e2016-05-25 08:21:04 -0700652
653 NetEqNetworkStatistics stats;
654 EXPECT_EQ(0, neteq_->NetworkStatistics(&stats));
655 // NetEqNetworkStatistics::expand_rate tells the fraction of samples that were
656 // concealment samples, in Q14 (16384 = 100%) .The vast majority should be
657 // concealment samples in this test.
658 EXPECT_GT(stats.expand_rate, 14000);
659 // And, it should be greater than the speech_expand_rate.
660 EXPECT_GT(stats.expand_rate, stats.speech_expand_rate);
henrik.lundin7a926812016-05-12 13:51:28 -0700661}
662
663// Verifies that NetEq goes out of muted state when given a delayed packet.
664TEST_F(NetEqDecodingTestWithMutedState, MutedStateDelayedPacket) {
665 // Insert one speech packet.
666 InsertPacket(0);
667 // Pull out audio once and expect it not to be muted.
668 EXPECT_FALSE(GetAudioReturnMuted());
669 // Pull data until faded out.
670 GetAudioUntilMuted();
671 // Insert new data. Timestamp is only corrected for the half of the time
672 // elapsed since the last packet. That is, the new packet is delayed. Verify
673 // that normal operation resumes.
674 InsertPacket(kSamples * counter_ / 2);
675 GetAudioUntilNormal();
676}
677
678// Verifies that NetEq goes out of muted state when given a future packet.
679TEST_F(NetEqDecodingTestWithMutedState, MutedStateFuturePacket) {
680 // Insert one speech packet.
681 InsertPacket(0);
682 // Pull out audio once and expect it not to be muted.
683 EXPECT_FALSE(GetAudioReturnMuted());
684 // Pull data until faded out.
685 GetAudioUntilMuted();
686 // Insert new data. Timestamp is over-corrected for the time elapsed since the
687 // last packet. That is, the new packet is too early. Verify that normal
688 // operation resumes.
689 InsertPacket(kSamples * counter_ * 2);
690 GetAudioUntilNormal();
691}
692
693// Verifies that NetEq goes out of muted state when given an old packet.
694TEST_F(NetEqDecodingTestWithMutedState, MutedStateOldPacket) {
695 // Insert one speech packet.
696 InsertPacket(0);
697 // Pull out audio once and expect it not to be muted.
698 EXPECT_FALSE(GetAudioReturnMuted());
699 // Pull data until faded out.
700 GetAudioUntilMuted();
701
702 EXPECT_NE(AudioFrame::kNormalSpeech, out_frame_.speech_type_);
Jakob Ivarsson80fb9782020-10-09 13:41:06 +0200703 // Insert a few packets which are older than the first packet.
704 for (int i = 0; i < 5; ++i) {
705 InsertPacket(kSamples * (i - 1000));
706 }
henrik.lundin7a926812016-05-12 13:51:28 -0700707 EXPECT_FALSE(GetAudioReturnMuted());
708 EXPECT_EQ(AudioFrame::kNormalSpeech, out_frame_.speech_type_);
709}
710
henrik.lundin42feb512016-09-20 06:51:40 -0700711// Verifies that NetEq doesn't enter muted state when CNG mode is active and the
712// packet stream is suspended for a long time.
713TEST_F(NetEqDecodingTestWithMutedState, DoNotMuteExtendedCngWithoutPackets) {
714 // Insert one CNG packet.
715 InsertCngPacket(0);
716
717 // Pull 10 seconds of audio (10 ms audio generated per lap).
718 for (int i = 0; i < 1000; ++i) {
719 bool muted;
720 EXPECT_EQ(0, neteq_->GetAudio(&out_frame_, &muted));
721 ASSERT_FALSE(muted);
722 }
723 EXPECT_EQ(AudioFrame::kCNG, out_frame_.speech_type_);
724}
725
726// Verifies that NetEq goes back to normal after a long CNG period with the
727// packet stream suspended.
728TEST_F(NetEqDecodingTestWithMutedState, RecoverAfterExtendedCngWithoutPackets) {
729 // Insert one CNG packet.
730 InsertCngPacket(0);
731
732 // Pull 10 seconds of audio (10 ms audio generated per lap).
733 for (int i = 0; i < 1000; ++i) {
734 bool muted;
735 EXPECT_EQ(0, neteq_->GetAudio(&out_frame_, &muted));
736 }
737
738 // Insert new data. Timestamp is corrected for the time elapsed since the last
739 // packet. Verify that normal operation resumes.
740 InsertPacket(kSamples * counter_);
741 GetAudioUntilNormal();
742}
743
henrik.lundin7a926812016-05-12 13:51:28 -0700744namespace {
745::testing::AssertionResult AudioFramesEqualExceptData(const AudioFrame& a,
746 const AudioFrame& b) {
747 if (a.timestamp_ != b.timestamp_)
748 return ::testing::AssertionFailure() << "timestamp_ diff (" << a.timestamp_
749 << " != " << b.timestamp_ << ")";
750 if (a.sample_rate_hz_ != b.sample_rate_hz_)
Yves Gerey665174f2018-06-19 15:03:05 +0200751 return ::testing::AssertionFailure()
752 << "sample_rate_hz_ diff (" << a.sample_rate_hz_
753 << " != " << b.sample_rate_hz_ << ")";
henrik.lundin7a926812016-05-12 13:51:28 -0700754 if (a.samples_per_channel_ != b.samples_per_channel_)
755 return ::testing::AssertionFailure()
756 << "samples_per_channel_ diff (" << a.samples_per_channel_
757 << " != " << b.samples_per_channel_ << ")";
758 if (a.num_channels_ != b.num_channels_)
Yves Gerey665174f2018-06-19 15:03:05 +0200759 return ::testing::AssertionFailure()
760 << "num_channels_ diff (" << a.num_channels_
761 << " != " << b.num_channels_ << ")";
henrik.lundin7a926812016-05-12 13:51:28 -0700762 if (a.speech_type_ != b.speech_type_)
Yves Gerey665174f2018-06-19 15:03:05 +0200763 return ::testing::AssertionFailure()
764 << "speech_type_ diff (" << a.speech_type_
765 << " != " << b.speech_type_ << ")";
henrik.lundin7a926812016-05-12 13:51:28 -0700766 if (a.vad_activity_ != b.vad_activity_)
Yves Gerey665174f2018-06-19 15:03:05 +0200767 return ::testing::AssertionFailure()
768 << "vad_activity_ diff (" << a.vad_activity_
769 << " != " << b.vad_activity_ << ")";
henrik.lundin7a926812016-05-12 13:51:28 -0700770 return ::testing::AssertionSuccess();
771}
772
773::testing::AssertionResult AudioFramesEqual(const AudioFrame& a,
774 const AudioFrame& b) {
775 ::testing::AssertionResult res = AudioFramesEqualExceptData(a, b);
776 if (!res)
777 return res;
Yves Gerey665174f2018-06-19 15:03:05 +0200778 if (memcmp(a.data(), b.data(),
779 a.samples_per_channel_ * a.num_channels_ * sizeof(*a.data())) !=
780 0) {
henrik.lundin7a926812016-05-12 13:51:28 -0700781 return ::testing::AssertionFailure() << "data_ diff";
782 }
783 return ::testing::AssertionSuccess();
784}
785
786} // namespace
787
788TEST_F(NetEqDecodingTestTwoInstances, CompareMutedStateOnOff) {
789 ASSERT_FALSE(config_.enable_muted_state);
790 config2_.enable_muted_state = true;
791 CreateSecondInstance();
792
793 // Insert one speech packet into both NetEqs.
794 const size_t kSamples = 10 * 16;
795 const size_t kPayloadBytes = kSamples * 2;
796 uint8_t payload[kPayloadBytes] = {0};
henrik.lundin246ef3e2017-04-24 09:14:32 -0700797 RTPHeader rtp_info;
henrik.lundin7a926812016-05-12 13:51:28 -0700798 PopulateRtpInfo(0, 0, &rtp_info);
Karl Wiberg45eb1352019-10-10 14:23:00 +0200799 EXPECT_EQ(0, neteq_->InsertPacket(rtp_info, payload));
800 EXPECT_EQ(0, neteq2_->InsertPacket(rtp_info, payload));
henrik.lundin7a926812016-05-12 13:51:28 -0700801
802 AudioFrame out_frame1, out_frame2;
803 bool muted;
804 for (int i = 0; i < 1000; ++i) {
Jonas Olsson366a50c2018-09-06 13:41:30 +0200805 rtc::StringBuilder ss;
henrik.lundin7a926812016-05-12 13:51:28 -0700806 ss << "i = " << i;
807 SCOPED_TRACE(ss.str()); // Print out the loop iterator on failure.
808 EXPECT_EQ(0, neteq_->GetAudio(&out_frame1, &muted));
809 EXPECT_FALSE(muted);
810 EXPECT_EQ(0, neteq2_->GetAudio(&out_frame2, &muted));
811 if (muted) {
812 EXPECT_TRUE(AudioFramesEqualExceptData(out_frame1, out_frame2));
813 } else {
814 EXPECT_TRUE(AudioFramesEqual(out_frame1, out_frame2));
815 }
816 }
817 EXPECT_TRUE(muted);
818
819 // Insert new data. Timestamp is corrected for the time elapsed since the last
820 // packet.
Jakob Ivarsson80fb9782020-10-09 13:41:06 +0200821 for (int i = 0; i < 5; ++i) {
822 PopulateRtpInfo(0, kSamples * 1000 + kSamples * i, &rtp_info);
823 EXPECT_EQ(0, neteq_->InsertPacket(rtp_info, payload));
824 EXPECT_EQ(0, neteq2_->InsertPacket(rtp_info, payload));
825 }
henrik.lundin7a926812016-05-12 13:51:28 -0700826
827 int counter = 0;
828 while (out_frame1.speech_type_ != AudioFrame::kNormalSpeech) {
829 ASSERT_LT(counter++, 1000) << "Test timed out";
Jonas Olsson366a50c2018-09-06 13:41:30 +0200830 rtc::StringBuilder ss;
henrik.lundin7a926812016-05-12 13:51:28 -0700831 ss << "counter = " << counter;
832 SCOPED_TRACE(ss.str()); // Print out the loop iterator on failure.
833 EXPECT_EQ(0, neteq_->GetAudio(&out_frame1, &muted));
834 EXPECT_FALSE(muted);
835 EXPECT_EQ(0, neteq2_->GetAudio(&out_frame2, &muted));
836 if (muted) {
837 EXPECT_TRUE(AudioFramesEqualExceptData(out_frame1, out_frame2));
838 } else {
839 EXPECT_TRUE(AudioFramesEqual(out_frame1, out_frame2));
840 }
841 }
842 EXPECT_FALSE(muted);
843}
844
henrik.lundin114c1b32017-04-26 07:47:32 -0700845TEST_F(NetEqDecodingTest, LastDecodedTimestampsEmpty) {
846 EXPECT_TRUE(neteq_->LastDecodedTimestamps().empty());
847
848 // Pull out data once.
849 AudioFrame output;
850 bool muted;
851 ASSERT_EQ(0, neteq_->GetAudio(&output, &muted));
852
853 EXPECT_TRUE(neteq_->LastDecodedTimestamps().empty());
854}
855
856TEST_F(NetEqDecodingTest, LastDecodedTimestampsOneDecoded) {
857 // Insert one packet with PCM16b WB data (this is what PopulateRtpInfo does by
858 // default). Make the length 10 ms.
859 constexpr size_t kPayloadSamples = 16 * 10;
860 constexpr size_t kPayloadBytes = 2 * kPayloadSamples;
861 uint8_t payload[kPayloadBytes] = {0};
862
863 RTPHeader rtp_info;
864 constexpr uint32_t kRtpTimestamp = 0x1234;
865 PopulateRtpInfo(0, kRtpTimestamp, &rtp_info);
Karl Wiberg45eb1352019-10-10 14:23:00 +0200866 EXPECT_EQ(0, neteq_->InsertPacket(rtp_info, payload));
henrik.lundin114c1b32017-04-26 07:47:32 -0700867
868 // Pull out data once.
869 AudioFrame output;
870 bool muted;
871 ASSERT_EQ(0, neteq_->GetAudio(&output, &muted));
872
873 EXPECT_EQ(std::vector<uint32_t>({kRtpTimestamp}),
874 neteq_->LastDecodedTimestamps());
875
876 // Nothing decoded on the second call.
877 ASSERT_EQ(0, neteq_->GetAudio(&output, &muted));
878 EXPECT_TRUE(neteq_->LastDecodedTimestamps().empty());
879}
880
881TEST_F(NetEqDecodingTest, LastDecodedTimestampsTwoDecoded) {
882 // Insert two packets with PCM16b WB data (this is what PopulateRtpInfo does
883 // by default). Make the length 5 ms so that NetEq must decode them both in
884 // the same GetAudio call.
885 constexpr size_t kPayloadSamples = 16 * 5;
886 constexpr size_t kPayloadBytes = 2 * kPayloadSamples;
887 uint8_t payload[kPayloadBytes] = {0};
888
889 RTPHeader rtp_info;
890 constexpr uint32_t kRtpTimestamp1 = 0x1234;
891 PopulateRtpInfo(0, kRtpTimestamp1, &rtp_info);
Karl Wiberg45eb1352019-10-10 14:23:00 +0200892 EXPECT_EQ(0, neteq_->InsertPacket(rtp_info, payload));
henrik.lundin114c1b32017-04-26 07:47:32 -0700893 constexpr uint32_t kRtpTimestamp2 = kRtpTimestamp1 + kPayloadSamples;
894 PopulateRtpInfo(1, kRtpTimestamp2, &rtp_info);
Karl Wiberg45eb1352019-10-10 14:23:00 +0200895 EXPECT_EQ(0, neteq_->InsertPacket(rtp_info, payload));
henrik.lundin114c1b32017-04-26 07:47:32 -0700896
897 // Pull out data once.
898 AudioFrame output;
899 bool muted;
900 ASSERT_EQ(0, neteq_->GetAudio(&output, &muted));
901
902 EXPECT_EQ(std::vector<uint32_t>({kRtpTimestamp1, kRtpTimestamp2}),
903 neteq_->LastDecodedTimestamps());
904}
905
Gustaf Ullberg9a2e9062017-09-18 09:28:20 +0200906TEST_F(NetEqDecodingTest, TestConcealmentEvents) {
907 const int kNumConcealmentEvents = 19;
908 const size_t kSamples = 10 * 16;
909 const size_t kPayloadBytes = kSamples * 2;
910 int seq_no = 0;
911 RTPHeader rtp_info;
912 rtp_info.ssrc = 0x1234; // Just an arbitrary SSRC.
913 rtp_info.payloadType = 94; // PCM16b WB codec.
914 rtp_info.markerBit = 0;
915 const uint8_t payload[kPayloadBytes] = {0};
916 bool muted;
917
918 for (int i = 0; i < kNumConcealmentEvents; i++) {
919 // Insert some packets of 10 ms size.
920 for (int j = 0; j < 10; j++) {
921 rtp_info.sequenceNumber = seq_no++;
922 rtp_info.timestamp = rtp_info.sequenceNumber * kSamples;
Karl Wiberg45eb1352019-10-10 14:23:00 +0200923 neteq_->InsertPacket(rtp_info, payload);
Gustaf Ullberg9a2e9062017-09-18 09:28:20 +0200924 neteq_->GetAudio(&out_frame_, &muted);
925 }
926
927 // Lose a number of packets.
928 int num_lost = 1 + i;
929 for (int j = 0; j < num_lost; j++) {
930 seq_no++;
931 neteq_->GetAudio(&out_frame_, &muted);
932 }
933 }
934
935 // Check number of concealment events.
936 NetEqLifetimeStatistics stats = neteq_->GetLifetimeStatistics();
937 EXPECT_EQ(kNumConcealmentEvents, static_cast<int>(stats.concealment_events));
938}
939
Gustaf Ullbergb0a02072017-10-02 12:00:34 +0200940// Test that the jitter buffer delay stat is computed correctly.
941void NetEqDecodingTestFaxMode::TestJitterBufferDelay(bool apply_packet_loss) {
942 const int kNumPackets = 10;
943 const int kDelayInNumPackets = 2;
944 const int kPacketLenMs = 10; // All packets are of 10 ms size.
945 const size_t kSamples = kPacketLenMs * 16;
946 const size_t kPayloadBytes = kSamples * 2;
947 RTPHeader rtp_info;
948 rtp_info.ssrc = 0x1234; // Just an arbitrary SSRC.
949 rtp_info.payloadType = 94; // PCM16b WB codec.
950 rtp_info.markerBit = 0;
951 const uint8_t payload[kPayloadBytes] = {0};
952 bool muted;
953 int packets_sent = 0;
954 int packets_received = 0;
955 int expected_delay = 0;
Artem Titove618cc92020-03-11 11:18:54 +0100956 int expected_target_delay = 0;
Chen Xing0acffb52019-01-15 15:46:29 +0100957 uint64_t expected_emitted_count = 0;
Gustaf Ullbergb0a02072017-10-02 12:00:34 +0200958 while (packets_received < kNumPackets) {
959 // Insert packet.
960 if (packets_sent < kNumPackets) {
961 rtp_info.sequenceNumber = packets_sent++;
962 rtp_info.timestamp = rtp_info.sequenceNumber * kSamples;
Karl Wiberg45eb1352019-10-10 14:23:00 +0200963 neteq_->InsertPacket(rtp_info, payload);
Gustaf Ullbergb0a02072017-10-02 12:00:34 +0200964 }
965
966 // Get packet.
967 if (packets_sent > kDelayInNumPackets) {
968 neteq_->GetAudio(&out_frame_, &muted);
969 packets_received++;
970
971 // The delay reported by the jitter buffer never exceeds
972 // the number of samples previously fetched with GetAudio
973 // (hence the min()).
974 int packets_delay = std::min(packets_received, kDelayInNumPackets + 1);
975
976 // The increase of the expected delay is the product of
977 // the current delay of the jitter buffer in ms * the
978 // number of samples that are sent for play out.
979 int current_delay_ms = packets_delay * kPacketLenMs;
980 expected_delay += current_delay_ms * kSamples;
Artem Titove618cc92020-03-11 11:18:54 +0100981 expected_target_delay += neteq_->TargetDelayMs() * kSamples;
Chen Xing0acffb52019-01-15 15:46:29 +0100982 expected_emitted_count += kSamples;
Gustaf Ullbergb0a02072017-10-02 12:00:34 +0200983 }
984 }
985
986 if (apply_packet_loss) {
987 // Extra call to GetAudio to cause concealment.
988 neteq_->GetAudio(&out_frame_, &muted);
989 }
990
991 // Check jitter buffer delay.
992 NetEqLifetimeStatistics stats = neteq_->GetLifetimeStatistics();
Artem Titove618cc92020-03-11 11:18:54 +0100993 EXPECT_EQ(expected_delay,
994 rtc::checked_cast<int>(stats.jitter_buffer_delay_ms));
Chen Xing0acffb52019-01-15 15:46:29 +0100995 EXPECT_EQ(expected_emitted_count, stats.jitter_buffer_emitted_count);
Artem Titove618cc92020-03-11 11:18:54 +0100996 EXPECT_EQ(expected_target_delay,
997 rtc::checked_cast<int>(stats.jitter_buffer_target_delay_ms));
Gustaf Ullbergb0a02072017-10-02 12:00:34 +0200998}
999
1000TEST_F(NetEqDecodingTestFaxMode, TestJitterBufferDelayWithoutLoss) {
1001 TestJitterBufferDelay(false);
1002}
1003
1004TEST_F(NetEqDecodingTestFaxMode, TestJitterBufferDelayWithLoss) {
1005 TestJitterBufferDelay(true);
1006}
1007
Jakob Ivarsson26c59ff2019-02-28 09:55:49 +01001008TEST_F(NetEqDecodingTestFaxMode, TestJitterBufferDelayWithAcceleration) {
1009 const int kPacketLenMs = 10; // All packets are of 10 ms size.
1010 const size_t kSamples = kPacketLenMs * 16;
1011 const size_t kPayloadBytes = kSamples * 2;
1012 RTPHeader rtp_info;
1013 rtp_info.ssrc = 0x1234; // Just an arbitrary SSRC.
1014 rtp_info.payloadType = 94; // PCM16b WB codec.
1015 rtp_info.markerBit = 0;
1016 const uint8_t payload[kPayloadBytes] = {0};
1017
Artem Titove618cc92020-03-11 11:18:54 +01001018 int expected_target_delay = neteq_->TargetDelayMs() * kSamples;
Karl Wiberg45eb1352019-10-10 14:23:00 +02001019 neteq_->InsertPacket(rtp_info, payload);
Jakob Ivarsson26c59ff2019-02-28 09:55:49 +01001020
1021 bool muted;
1022 neteq_->GetAudio(&out_frame_, &muted);
1023
1024 rtp_info.sequenceNumber += 1;
1025 rtp_info.timestamp += kSamples;
Karl Wiberg45eb1352019-10-10 14:23:00 +02001026 neteq_->InsertPacket(rtp_info, payload);
Jakob Ivarsson26c59ff2019-02-28 09:55:49 +01001027 rtp_info.sequenceNumber += 1;
1028 rtp_info.timestamp += kSamples;
Karl Wiberg45eb1352019-10-10 14:23:00 +02001029 neteq_->InsertPacket(rtp_info, payload);
Jakob Ivarsson26c59ff2019-02-28 09:55:49 +01001030
Artem Titove618cc92020-03-11 11:18:54 +01001031 expected_target_delay += neteq_->TargetDelayMs() * 2 * kSamples;
Jakob Ivarsson26c59ff2019-02-28 09:55:49 +01001032 // We have two packets in the buffer and kAccelerate operation will
1033 // extract 20 ms of data.
Tommi3cc68ec2021-06-09 19:30:41 +02001034 neteq_->GetAudio(&out_frame_, &muted, nullptr, NetEq::Operation::kAccelerate);
Jakob Ivarsson26c59ff2019-02-28 09:55:49 +01001035
1036 // Check jitter buffer delay.
1037 NetEqLifetimeStatistics stats = neteq_->GetLifetimeStatistics();
1038 EXPECT_EQ(10 * kSamples * 3, stats.jitter_buffer_delay_ms);
1039 EXPECT_EQ(kSamples * 3, stats.jitter_buffer_emitted_count);
Artem Titove618cc92020-03-11 11:18:54 +01001040 EXPECT_EQ(expected_target_delay,
1041 rtc::checked_cast<int>(stats.jitter_buffer_target_delay_ms));
Jakob Ivarsson26c59ff2019-02-28 09:55:49 +01001042}
1043
Henrik Lundin7687ad52018-07-02 10:14:46 +02001044namespace test {
Henrik Lundin7687ad52018-07-02 10:14:46 +02001045TEST(NetEqNoTimeStretchingMode, RunTest) {
1046 NetEq::Config config;
1047 config.for_test_no_time_stretching = true;
1048 auto codecs = NetEqTest::StandardDecoderMap();
Henrik Lundin7687ad52018-07-02 10:14:46 +02001049 NetEqPacketSourceInput::RtpHeaderExtensionMap rtp_ext_map = {
1050 {1, kRtpExtensionAudioLevel},
1051 {3, kRtpExtensionAbsoluteSendTime},
1052 {5, kRtpExtensionTransportSequenceNumber},
1053 {7, kRtpExtensionVideoContentType},
1054 {8, kRtpExtensionVideoTiming}};
1055 std::unique_ptr<NetEqInput> input(new NetEqRtpDumpInput(
1056 webrtc::test::ResourcePath("audio_coding/neteq_universal_new", "rtp"),
Bjorn Terelius5350d1c2018-10-11 16:51:23 +02001057 rtp_ext_map, absl::nullopt /*No SSRC filter*/));
Henrik Lundin7687ad52018-07-02 10:14:46 +02001058 std::unique_ptr<TimeLimitedNetEqInput> input_time_limit(
1059 new TimeLimitedNetEqInput(std::move(input), 20000));
1060 std::unique_ptr<AudioSink> output(new VoidAudioSink);
1061 NetEqTest::Callbacks callbacks;
Ivo Creusencee751a2020-01-16 17:17:09 +01001062 NetEqTest test(config, CreateBuiltinAudioDecoderFactory(), codecs,
1063 /*text_log=*/nullptr, /*neteq_factory=*/nullptr,
1064 /*input=*/std::move(input_time_limit), std::move(output),
1065 callbacks);
Henrik Lundin7687ad52018-07-02 10:14:46 +02001066 test.Run();
1067 const auto stats = test.SimulationStats();
1068 EXPECT_EQ(0, stats.accelerate_rate);
1069 EXPECT_EQ(0, stats.preemptive_rate);
1070}
Henrik Lundin7687ad52018-07-02 10:14:46 +02001071
1072} // namespace test
henrik.lundin@webrtc.orge7ce4372014-01-09 14:01:55 +00001073} // namespace webrtc