blob: 679bd4db375aa11997857b7d8862d5abe528ec97 [file] [log] [blame]
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +00001/*
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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "modules/audio_coding/test/TestRedFec.h"
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +000012
13#include <assert.h>
14
Karl Wiberg5817d3d2018-04-06 10:06:42 +020015#include "api/audio_codecs/builtin_audio_decoder_factory.h"
Mirko Bonadei71207422017-09-15 13:58:09 +020016#include "common_types.h" // NOLINT(build/include)
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020017#include "modules/audio_coding/codecs/audio_format_conversion.h"
18#include "modules/audio_coding/include/audio_coding_module_typedefs.h"
19#include "modules/audio_coding/test/utility.h"
Jonas Olsson366a50c2018-09-06 13:41:30 +020020#include "rtc_base/strings/string_builder.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020021#include "test/testsupport/fileutils.h"
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +000022
23namespace webrtc {
24
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +000025namespace {
Karl Wiberg5817d3d2018-04-06 10:06:42 +020026
27const char kNameL16[] = "L16";
28const char kNamePCMU[] = "PCMU";
29const char kNameCN[] = "CN";
30const char kNameRED[] = "RED";
31const char kNameISAC[] = "ISAC";
32const char kNameG722[] = "G722";
33const char kNameOPUS[] = "opus";
34
35} // namespace
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +000036
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +000037TestRedFec::TestRedFec()
Karl Wiberg5817d3d2018-04-06 10:06:42 +020038 : _acmA(AudioCodingModule::Create(
39 AudioCodingModule::Config(CreateBuiltinAudioDecoderFactory()))),
40 _acmB(AudioCodingModule::Create(
41 AudioCodingModule::Config(CreateBuiltinAudioDecoderFactory()))),
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +000042 _channelA2B(NULL),
Karl Wiberg5817d3d2018-04-06 10:06:42 +020043 _testCntr(0) {}
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +000044
45TestRedFec::~TestRedFec() {
46 if (_channelA2B != NULL) {
47 delete _channelA2B;
48 _channelA2B = NULL;
49 }
50}
51
52void TestRedFec::Perform() {
53 const std::string file_name = webrtc::test::ResourcePath(
54 "audio_coding/testfile32kHz", "pcm");
55 _inFileA.Open(file_name, 32000, "rb");
56
57 ASSERT_EQ(0, _acmA->InitializeReceiver());
58 ASSERT_EQ(0, _acmB->InitializeReceiver());
59
60 uint8_t numEncoders = _acmA->NumberOfCodecs();
61 CodecInst myCodecParam;
62 for (uint8_t n = 0; n < numEncoders; n++) {
63 EXPECT_EQ(0, _acmB->Codec(n, &myCodecParam));
64 // Default number of channels is 2 for opus, so we change to 1 in this test.
65 if (!strcmp(myCodecParam.plname, "opus")) {
66 myCodecParam.channels = 1;
67 }
kwibergda2bf4e2016-10-24 13:47:09 -070068 EXPECT_EQ(true, _acmB->RegisterReceiveCodec(myCodecParam.pltype,
69 CodecInstToSdp(myCodecParam)));
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +000070 }
71
72 // Create and connect the channel
73 _channelA2B = new Channel;
74 _acmA->RegisterTransportCallback(_channelA2B);
75 _channelA2B->RegisterReceiverACM(_acmB.get());
76
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +000077 EXPECT_EQ(0, RegisterSendCodec('A', kNameL16, 8000));
78 EXPECT_EQ(0, RegisterSendCodec('A', kNameCN, 8000));
79 EXPECT_EQ(0, RegisterSendCodec('A', kNameRED));
80 EXPECT_EQ(0, SetVAD(true, true, VADAggr));
81 EXPECT_EQ(0, _acmA->SetREDStatus(true));
82 EXPECT_TRUE(_acmA->REDStatus());
83
84 OpenOutFile(_testCntr);
85 Run();
86 _outFileB.Close();
87
88 RegisterSendCodec('A', kNamePCMU, 8000);
89 // Switch to another 8 kHz codec, RED should remain switched on.
90 EXPECT_TRUE(_acmA->REDStatus());
91 OpenOutFile(_testCntr);
92 Run();
93 _outFileB.Close();
94
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +000095 EXPECT_EQ(0, RegisterSendCodec('A', kNameG722, 16000));
96 EXPECT_EQ(0, RegisterSendCodec('A', kNameCN, 16000));
97
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +000098 // Switch to a 16 kHz codec, RED should have been switched off.
99 EXPECT_FALSE(_acmA->REDStatus());
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000100
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000101 OpenOutFile(_testCntr);
102 EXPECT_EQ(0, SetVAD(true, true, VADAggr));
103 EXPECT_EQ(0, _acmA->SetREDStatus(false));
104 EXPECT_FALSE(_acmA->REDStatus());
105 Run();
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000106 EXPECT_EQ(-1, _acmA->SetREDStatus(true));
107 EXPECT_FALSE(_acmA->REDStatus());
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000108 Run();
109 _outFileB.Close();
110
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000111 RegisterSendCodec('A', kNameISAC, 16000);
112
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000113 EXPECT_FALSE(_acmA->REDStatus());
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000114
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000115 OpenOutFile(_testCntr);
116 EXPECT_EQ(0, SetVAD(true, true, VADVeryAggr));
117 EXPECT_EQ(0, _acmA->SetREDStatus(false));
118 EXPECT_FALSE(_acmA->REDStatus());
119 Run();
120 _outFileB.Close();
121
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000122 EXPECT_EQ(-1, _acmA->SetREDStatus(true));
123 EXPECT_FALSE(_acmA->REDStatus());
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000124 OpenOutFile(_testCntr);
125 Run();
126 _outFileB.Close();
127
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000128 RegisterSendCodec('A', kNameISAC, 32000);
129
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000130 // Switch to a 32 kHz codec, RED should have been switched off.
131 EXPECT_FALSE(_acmA->REDStatus());
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000132
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000133 OpenOutFile(_testCntr);
134 EXPECT_EQ(0, SetVAD(true, true, VADVeryAggr));
135 EXPECT_EQ(0, _acmA->SetREDStatus(false));
136 EXPECT_FALSE(_acmA->REDStatus());
137 Run();
138 _outFileB.Close();
139
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000140 EXPECT_EQ(-1, _acmA->SetREDStatus(true));
141 EXPECT_FALSE(_acmA->REDStatus());
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000142 OpenOutFile(_testCntr);
143 Run();
144 _outFileB.Close();
145
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000146 RegisterSendCodec('A', kNameISAC, 32000);
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000147 EXPECT_EQ(0, SetVAD(false, false, VADNormal));
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000148
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000149 EXPECT_EQ(-1, _acmA->SetREDStatus(true));
150 EXPECT_FALSE(_acmA->REDStatus());
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000151
152 _channelA2B->SetFECTestWithPacketLoss(true);
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000153 // Following tests are under packet losses.
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000154
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000155 EXPECT_EQ(0, RegisterSendCodec('A', kNameG722));
156 EXPECT_EQ(0, RegisterSendCodec('A', kNameCN, 16000));
157
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000158 // Switch to a 16 kHz codec, RED should have been switched off.
159 EXPECT_FALSE(_acmA->REDStatus());
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000160
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000161 OpenOutFile(_testCntr);
162 EXPECT_EQ(0, SetVAD(true, true, VADAggr));
163 EXPECT_EQ(0, _acmA->SetREDStatus(false));
164 EXPECT_FALSE(_acmA->REDStatus());
165 Run();
166 _outFileB.Close();
167
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000168 EXPECT_EQ(-1, _acmA->SetREDStatus(true));
169 EXPECT_FALSE(_acmA->REDStatus());
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000170 OpenOutFile(_testCntr);
171 Run();
172 _outFileB.Close();
173
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000174 RegisterSendCodec('A', kNameISAC, 16000);
175
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000176 // Switch to a 16 kHz codec, RED should have been switched off.
177 EXPECT_FALSE(_acmA->REDStatus());
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000178
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000179 OpenOutFile(_testCntr);
180 EXPECT_EQ(0, SetVAD(true, true, VADVeryAggr));
181 EXPECT_EQ(0, _acmA->SetREDStatus(false));
182 EXPECT_FALSE(_acmA->REDStatus());
183 Run();
184 _outFileB.Close();
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000185 EXPECT_EQ(-1, _acmA->SetREDStatus(true));
186 EXPECT_FALSE(_acmA->REDStatus());
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000187 OpenOutFile(_testCntr);
188 Run();
189 _outFileB.Close();
190
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000191 RegisterSendCodec('A', kNameISAC, 32000);
192
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000193 // Switch to a 32 kHz codec, RED should have been switched off.
194 EXPECT_FALSE(_acmA->REDStatus());
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000195
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000196 OpenOutFile(_testCntr);
197 EXPECT_EQ(0, SetVAD(true, true, VADVeryAggr));
198 EXPECT_EQ(0, _acmA->SetREDStatus(false));
199 EXPECT_FALSE(_acmA->REDStatus());
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000200 EXPECT_EQ(-1, _acmA->SetREDStatus(true));
201 EXPECT_FALSE(_acmA->REDStatus());
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000202 OpenOutFile(_testCntr);
203 Run();
204 _outFileB.Close();
205
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000206 RegisterSendCodec('A', kNameISAC, 32000);
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000207 EXPECT_EQ(0, SetVAD(false, false, VADNormal));
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000208 EXPECT_EQ(-1, _acmA->SetREDStatus(true));
209 EXPECT_FALSE(_acmA->REDStatus());
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000210
211#ifndef WEBRTC_CODEC_OPUS
212 EXPECT_TRUE(false);
213 printf("Opus needs to be activated to run this test\n");
214 return;
215#endif
216
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000217 RegisterSendCodec('A', kNameOPUS, 48000);
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000218
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000219 EXPECT_FALSE(_acmA->REDStatus());
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000220
221 // _channelA2B imposes 25% packet loss rate.
222 EXPECT_EQ(0, _acmA->SetPacketLossRate(25));
223
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000224 EXPECT_EQ(-1, _acmA->SetREDStatus(true));
225 EXPECT_FALSE(_acmA->REDStatus());
226 EXPECT_EQ(0, _acmA->SetCodecFEC(true));
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000227
228 EXPECT_TRUE(_acmA->CodecFEC());
229 OpenOutFile(_testCntr);
230 Run();
231
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000232 // Switch to L16 with RED.
233 RegisterSendCodec('A', kNameL16, 8000);
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000234 EXPECT_EQ(0, SetVAD(false, false, VADNormal));
235
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000236 // L16 does not support FEC, so FEC should be turned off automatically.
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000237 EXPECT_FALSE(_acmA->CodecFEC());
238
239 EXPECT_EQ(0, _acmA->SetREDStatus(true));
240 EXPECT_TRUE(_acmA->REDStatus());
241 Run();
242
243 // Switch to Opus again.
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000244 RegisterSendCodec('A', kNameOPUS, 48000);
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000245 EXPECT_FALSE(_acmA->REDStatus());
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000246 EXPECT_EQ(0, _acmA->SetREDStatus(false));
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000247 EXPECT_EQ(0, _acmA->SetCodecFEC(false));
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000248 Run();
249
250 EXPECT_EQ(0, _acmA->SetCodecFEC(true));
251 _outFileB.Close();
252
minyue@webrtc.org60fbd652014-09-25 14:36:30 +0000253 // Codecs does not support internal FEC, cannot enable FEC.
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000254 RegisterSendCodec('A', kNameG722, 16000);
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000255 EXPECT_FALSE(_acmA->REDStatus());
256 EXPECT_EQ(-1, _acmA->SetCodecFEC(true));
257 EXPECT_FALSE(_acmA->CodecFEC());
258
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000259 RegisterSendCodec('A', kNameISAC, 16000);
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000260 EXPECT_FALSE(_acmA->REDStatus());
261 EXPECT_EQ(-1, _acmA->SetCodecFEC(true));
262 EXPECT_FALSE(_acmA->CodecFEC());
minyue@webrtc.org60fbd652014-09-25 14:36:30 +0000263
264 // Codecs does not support internal FEC, disable FEC does not trigger failure.
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000265 RegisterSendCodec('A', kNameG722, 16000);
minyue@webrtc.org60fbd652014-09-25 14:36:30 +0000266 EXPECT_FALSE(_acmA->REDStatus());
267 EXPECT_EQ(0, _acmA->SetCodecFEC(false));
268 EXPECT_FALSE(_acmA->CodecFEC());
269
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000270 RegisterSendCodec('A', kNameISAC, 16000);
minyue@webrtc.org60fbd652014-09-25 14:36:30 +0000271 EXPECT_FALSE(_acmA->REDStatus());
272 EXPECT_EQ(0, _acmA->SetCodecFEC(false));
273 EXPECT_FALSE(_acmA->CodecFEC());
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000274}
275
276int32_t TestRedFec::SetVAD(bool enableDTX, bool enableVAD, ACMVADMode vadMode) {
277 return _acmA->SetVAD(enableDTX, enableVAD, vadMode);
278}
279
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000280int16_t TestRedFec::RegisterSendCodec(char side, const char* codecName,
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000281 int32_t samplingFreqHz) {
282 std::cout << std::flush;
283 AudioCodingModule* myACM;
284 switch (side) {
285 case 'A': {
286 myACM = _acmA.get();
287 break;
288 }
289 case 'B': {
290 myACM = _acmB.get();
291 break;
292 }
293 default:
294 return -1;
295 }
296
297 if (myACM == NULL) {
298 assert(false);
299 return -1;
300 }
301 CodecInst myCodecParam;
302 EXPECT_GT(AudioCodingModule::Codec(codecName, &myCodecParam,
303 samplingFreqHz, 1), -1);
304 EXPECT_GT(myACM->RegisterSendCodec(myCodecParam), -1);
305
306 // Initialization was successful.
307 return 0;
308}
309
310void TestRedFec::Run() {
311 AudioFrame audioFrame;
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000312 int32_t outFreqHzB = _outFileB.SamplingFrequency();
Henrik Lundin4d682082015-12-10 16:24:39 +0100313 // Set test length to 500 ms (50 blocks of 10 ms each).
314 _inFileA.SetNum10MsBlocksToRead(50);
315 // Fast-forward 1 second (100 blocks) since the file starts with silence.
316 _inFileA.FastForward(100);
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000317
318 while (!_inFileA.EndOfFile()) {
319 EXPECT_GT(_inFileA.Read10MsData(audioFrame), 0);
henrik.lundin@webrtc.orgf56c1622015-03-02 12:29:30 +0000320 EXPECT_GE(_acmA->Add10MsData(audioFrame), 0);
henrik.lundind4ccb002016-05-17 12:21:55 -0700321 bool muted;
322 EXPECT_EQ(0, _acmB->PlayoutData10Ms(outFreqHzB, &audioFrame, &muted));
323 ASSERT_FALSE(muted);
yujo36b1a5f2017-06-12 12:45:32 -0700324 _outFileB.Write10MsData(audioFrame.data(), audioFrame.samples_per_channel_);
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000325 }
326 _inFileA.Rewind();
327}
328
329void TestRedFec::OpenOutFile(int16_t test_number) {
330 std::string file_name;
Jonas Olsson366a50c2018-09-06 13:41:30 +0200331 rtc::StringBuilder file_stream;
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000332 file_stream << webrtc::test::OutputPath();
333 file_stream << "TestRedFec_outFile_";
334 file_stream << test_number << ".pcm";
335 file_name = file_stream.str();
336 _outFileB.Open(file_name, 16000, "wb");
337}
338
339} // namespace webrtc