blob: 71d34867ac1078c47d4e0efe5f12ac90a193c87a [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"
20#include "test/testsupport/fileutils.h"
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +000021
22namespace webrtc {
23
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +000024namespace {
Karl Wiberg5817d3d2018-04-06 10:06:42 +020025
26const char kNameL16[] = "L16";
27const char kNamePCMU[] = "PCMU";
28const char kNameCN[] = "CN";
29const char kNameRED[] = "RED";
30const char kNameISAC[] = "ISAC";
31const char kNameG722[] = "G722";
32const char kNameOPUS[] = "opus";
33
34} // namespace
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +000035
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +000036TestRedFec::TestRedFec()
Karl Wiberg5817d3d2018-04-06 10:06:42 +020037 : _acmA(AudioCodingModule::Create(
38 AudioCodingModule::Config(CreateBuiltinAudioDecoderFactory()))),
39 _acmB(AudioCodingModule::Create(
40 AudioCodingModule::Config(CreateBuiltinAudioDecoderFactory()))),
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +000041 _channelA2B(NULL),
Karl Wiberg5817d3d2018-04-06 10:06:42 +020042 _testCntr(0) {}
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +000043
44TestRedFec::~TestRedFec() {
45 if (_channelA2B != NULL) {
46 delete _channelA2B;
47 _channelA2B = NULL;
48 }
49}
50
51void TestRedFec::Perform() {
52 const std::string file_name = webrtc::test::ResourcePath(
53 "audio_coding/testfile32kHz", "pcm");
54 _inFileA.Open(file_name, 32000, "rb");
55
56 ASSERT_EQ(0, _acmA->InitializeReceiver());
57 ASSERT_EQ(0, _acmB->InitializeReceiver());
58
59 uint8_t numEncoders = _acmA->NumberOfCodecs();
60 CodecInst myCodecParam;
61 for (uint8_t n = 0; n < numEncoders; n++) {
62 EXPECT_EQ(0, _acmB->Codec(n, &myCodecParam));
63 // Default number of channels is 2 for opus, so we change to 1 in this test.
64 if (!strcmp(myCodecParam.plname, "opus")) {
65 myCodecParam.channels = 1;
66 }
kwibergda2bf4e2016-10-24 13:47:09 -070067 EXPECT_EQ(true, _acmB->RegisterReceiveCodec(myCodecParam.pltype,
68 CodecInstToSdp(myCodecParam)));
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +000069 }
70
71 // Create and connect the channel
72 _channelA2B = new Channel;
73 _acmA->RegisterTransportCallback(_channelA2B);
74 _channelA2B->RegisterReceiverACM(_acmB.get());
75
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +000076 EXPECT_EQ(0, RegisterSendCodec('A', kNameL16, 8000));
77 EXPECT_EQ(0, RegisterSendCodec('A', kNameCN, 8000));
78 EXPECT_EQ(0, RegisterSendCodec('A', kNameRED));
79 EXPECT_EQ(0, SetVAD(true, true, VADAggr));
80 EXPECT_EQ(0, _acmA->SetREDStatus(true));
81 EXPECT_TRUE(_acmA->REDStatus());
82
83 OpenOutFile(_testCntr);
84 Run();
85 _outFileB.Close();
86
87 RegisterSendCodec('A', kNamePCMU, 8000);
88 // Switch to another 8 kHz codec, RED should remain switched on.
89 EXPECT_TRUE(_acmA->REDStatus());
90 OpenOutFile(_testCntr);
91 Run();
92 _outFileB.Close();
93
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +000094 EXPECT_EQ(0, RegisterSendCodec('A', kNameG722, 16000));
95 EXPECT_EQ(0, RegisterSendCodec('A', kNameCN, 16000));
96
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +000097 // Switch to a 16 kHz codec, RED should have been switched off.
98 EXPECT_FALSE(_acmA->REDStatus());
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +000099
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000100 OpenOutFile(_testCntr);
101 EXPECT_EQ(0, SetVAD(true, true, VADAggr));
102 EXPECT_EQ(0, _acmA->SetREDStatus(false));
103 EXPECT_FALSE(_acmA->REDStatus());
104 Run();
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000105 EXPECT_EQ(-1, _acmA->SetREDStatus(true));
106 EXPECT_FALSE(_acmA->REDStatus());
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000107 Run();
108 _outFileB.Close();
109
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000110 RegisterSendCodec('A', kNameISAC, 16000);
111
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000112 EXPECT_FALSE(_acmA->REDStatus());
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000113
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000114 OpenOutFile(_testCntr);
115 EXPECT_EQ(0, SetVAD(true, true, VADVeryAggr));
116 EXPECT_EQ(0, _acmA->SetREDStatus(false));
117 EXPECT_FALSE(_acmA->REDStatus());
118 Run();
119 _outFileB.Close();
120
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000121 EXPECT_EQ(-1, _acmA->SetREDStatus(true));
122 EXPECT_FALSE(_acmA->REDStatus());
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000123 OpenOutFile(_testCntr);
124 Run();
125 _outFileB.Close();
126
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000127 RegisterSendCodec('A', kNameISAC, 32000);
128
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000129 // Switch to a 32 kHz codec, RED should have been switched off.
130 EXPECT_FALSE(_acmA->REDStatus());
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000131
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000132 OpenOutFile(_testCntr);
133 EXPECT_EQ(0, SetVAD(true, true, VADVeryAggr));
134 EXPECT_EQ(0, _acmA->SetREDStatus(false));
135 EXPECT_FALSE(_acmA->REDStatus());
136 Run();
137 _outFileB.Close();
138
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000139 EXPECT_EQ(-1, _acmA->SetREDStatus(true));
140 EXPECT_FALSE(_acmA->REDStatus());
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000141 OpenOutFile(_testCntr);
142 Run();
143 _outFileB.Close();
144
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000145 RegisterSendCodec('A', kNameISAC, 32000);
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000146 EXPECT_EQ(0, SetVAD(false, false, VADNormal));
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000147
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000148 EXPECT_EQ(-1, _acmA->SetREDStatus(true));
149 EXPECT_FALSE(_acmA->REDStatus());
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000150
151 _channelA2B->SetFECTestWithPacketLoss(true);
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000152 // Following tests are under packet losses.
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000153
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000154 EXPECT_EQ(0, RegisterSendCodec('A', kNameG722));
155 EXPECT_EQ(0, RegisterSendCodec('A', kNameCN, 16000));
156
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000157 // Switch to a 16 kHz codec, RED should have been switched off.
158 EXPECT_FALSE(_acmA->REDStatus());
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000159
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000160 OpenOutFile(_testCntr);
161 EXPECT_EQ(0, SetVAD(true, true, VADAggr));
162 EXPECT_EQ(0, _acmA->SetREDStatus(false));
163 EXPECT_FALSE(_acmA->REDStatus());
164 Run();
165 _outFileB.Close();
166
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000167 EXPECT_EQ(-1, _acmA->SetREDStatus(true));
168 EXPECT_FALSE(_acmA->REDStatus());
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000169 OpenOutFile(_testCntr);
170 Run();
171 _outFileB.Close();
172
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000173 RegisterSendCodec('A', kNameISAC, 16000);
174
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000175 // Switch to a 16 kHz codec, RED should have been switched off.
176 EXPECT_FALSE(_acmA->REDStatus());
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000177
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000178 OpenOutFile(_testCntr);
179 EXPECT_EQ(0, SetVAD(true, true, VADVeryAggr));
180 EXPECT_EQ(0, _acmA->SetREDStatus(false));
181 EXPECT_FALSE(_acmA->REDStatus());
182 Run();
183 _outFileB.Close();
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000184 EXPECT_EQ(-1, _acmA->SetREDStatus(true));
185 EXPECT_FALSE(_acmA->REDStatus());
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000186 OpenOutFile(_testCntr);
187 Run();
188 _outFileB.Close();
189
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000190 RegisterSendCodec('A', kNameISAC, 32000);
191
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000192 // Switch to a 32 kHz codec, RED should have been switched off.
193 EXPECT_FALSE(_acmA->REDStatus());
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000194
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000195 OpenOutFile(_testCntr);
196 EXPECT_EQ(0, SetVAD(true, true, VADVeryAggr));
197 EXPECT_EQ(0, _acmA->SetREDStatus(false));
198 EXPECT_FALSE(_acmA->REDStatus());
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000199 EXPECT_EQ(-1, _acmA->SetREDStatus(true));
200 EXPECT_FALSE(_acmA->REDStatus());
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000201 OpenOutFile(_testCntr);
202 Run();
203 _outFileB.Close();
204
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000205 RegisterSendCodec('A', kNameISAC, 32000);
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000206 EXPECT_EQ(0, SetVAD(false, false, VADNormal));
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000207 EXPECT_EQ(-1, _acmA->SetREDStatus(true));
208 EXPECT_FALSE(_acmA->REDStatus());
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000209
210#ifndef WEBRTC_CODEC_OPUS
211 EXPECT_TRUE(false);
212 printf("Opus needs to be activated to run this test\n");
213 return;
214#endif
215
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000216 RegisterSendCodec('A', kNameOPUS, 48000);
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000217
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000218 EXPECT_FALSE(_acmA->REDStatus());
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000219
220 // _channelA2B imposes 25% packet loss rate.
221 EXPECT_EQ(0, _acmA->SetPacketLossRate(25));
222
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000223 EXPECT_EQ(-1, _acmA->SetREDStatus(true));
224 EXPECT_FALSE(_acmA->REDStatus());
225 EXPECT_EQ(0, _acmA->SetCodecFEC(true));
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000226
227 EXPECT_TRUE(_acmA->CodecFEC());
228 OpenOutFile(_testCntr);
229 Run();
230
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000231 // Switch to L16 with RED.
232 RegisterSendCodec('A', kNameL16, 8000);
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000233 EXPECT_EQ(0, SetVAD(false, false, VADNormal));
234
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000235 // L16 does not support FEC, so FEC should be turned off automatically.
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000236 EXPECT_FALSE(_acmA->CodecFEC());
237
238 EXPECT_EQ(0, _acmA->SetREDStatus(true));
239 EXPECT_TRUE(_acmA->REDStatus());
240 Run();
241
242 // Switch to Opus again.
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000243 RegisterSendCodec('A', kNameOPUS, 48000);
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000244 EXPECT_FALSE(_acmA->REDStatus());
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000245 EXPECT_EQ(0, _acmA->SetREDStatus(false));
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000246 EXPECT_EQ(0, _acmA->SetCodecFEC(false));
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000247 Run();
248
249 EXPECT_EQ(0, _acmA->SetCodecFEC(true));
250 _outFileB.Close();
251
minyue@webrtc.org60fbd652014-09-25 14:36:30 +0000252 // Codecs does not support internal FEC, cannot enable FEC.
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000253 RegisterSendCodec('A', kNameG722, 16000);
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000254 EXPECT_FALSE(_acmA->REDStatus());
255 EXPECT_EQ(-1, _acmA->SetCodecFEC(true));
256 EXPECT_FALSE(_acmA->CodecFEC());
257
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000258 RegisterSendCodec('A', kNameISAC, 16000);
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000259 EXPECT_FALSE(_acmA->REDStatus());
260 EXPECT_EQ(-1, _acmA->SetCodecFEC(true));
261 EXPECT_FALSE(_acmA->CodecFEC());
minyue@webrtc.org60fbd652014-09-25 14:36:30 +0000262
263 // Codecs does not support internal FEC, disable FEC does not trigger failure.
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000264 RegisterSendCodec('A', kNameG722, 16000);
minyue@webrtc.org60fbd652014-09-25 14:36:30 +0000265 EXPECT_FALSE(_acmA->REDStatus());
266 EXPECT_EQ(0, _acmA->SetCodecFEC(false));
267 EXPECT_FALSE(_acmA->CodecFEC());
268
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000269 RegisterSendCodec('A', kNameISAC, 16000);
minyue@webrtc.org60fbd652014-09-25 14:36:30 +0000270 EXPECT_FALSE(_acmA->REDStatus());
271 EXPECT_EQ(0, _acmA->SetCodecFEC(false));
272 EXPECT_FALSE(_acmA->CodecFEC());
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000273}
274
275int32_t TestRedFec::SetVAD(bool enableDTX, bool enableVAD, ACMVADMode vadMode) {
276 return _acmA->SetVAD(enableDTX, enableVAD, vadMode);
277}
278
minyue@webrtc.org41d2bef2015-03-23 12:57:45 +0000279int16_t TestRedFec::RegisterSendCodec(char side, const char* codecName,
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000280 int32_t samplingFreqHz) {
281 std::cout << std::flush;
282 AudioCodingModule* myACM;
283 switch (side) {
284 case 'A': {
285 myACM = _acmA.get();
286 break;
287 }
288 case 'B': {
289 myACM = _acmB.get();
290 break;
291 }
292 default:
293 return -1;
294 }
295
296 if (myACM == NULL) {
297 assert(false);
298 return -1;
299 }
300 CodecInst myCodecParam;
301 EXPECT_GT(AudioCodingModule::Codec(codecName, &myCodecParam,
302 samplingFreqHz, 1), -1);
303 EXPECT_GT(myACM->RegisterSendCodec(myCodecParam), -1);
304
305 // Initialization was successful.
306 return 0;
307}
308
309void TestRedFec::Run() {
310 AudioFrame audioFrame;
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000311 int32_t outFreqHzB = _outFileB.SamplingFrequency();
Henrik Lundin4d682082015-12-10 16:24:39 +0100312 // Set test length to 500 ms (50 blocks of 10 ms each).
313 _inFileA.SetNum10MsBlocksToRead(50);
314 // Fast-forward 1 second (100 blocks) since the file starts with silence.
315 _inFileA.FastForward(100);
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000316
317 while (!_inFileA.EndOfFile()) {
318 EXPECT_GT(_inFileA.Read10MsData(audioFrame), 0);
henrik.lundin@webrtc.orgf56c1622015-03-02 12:29:30 +0000319 EXPECT_GE(_acmA->Add10MsData(audioFrame), 0);
henrik.lundind4ccb002016-05-17 12:21:55 -0700320 bool muted;
321 EXPECT_EQ(0, _acmB->PlayoutData10Ms(outFreqHzB, &audioFrame, &muted));
322 ASSERT_FALSE(muted);
yujo36b1a5f2017-06-12 12:45:32 -0700323 _outFileB.Write10MsData(audioFrame.data(), audioFrame.samples_per_channel_);
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000324 }
325 _inFileA.Rewind();
326}
327
328void TestRedFec::OpenOutFile(int16_t test_number) {
329 std::string file_name;
330 std::stringstream file_stream;
331 file_stream << webrtc::test::OutputPath();
332 file_stream << "TestRedFec_outFile_";
333 file_stream << test_number << ".pcm";
334 file_name = file_stream.str();
335 _outFileB.Open(file_name, 16000, "wb");
336}
337
338} // namespace webrtc