blob: 8f6ef9d89c6bec25081d85170751ca1ec8506efe [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
11#include "webrtc/modules/audio_coding/main/test/TestRedFec.h"
12
13#include <assert.h>
14
15#include "webrtc/common.h"
16#include "webrtc/common_types.h"
17#include "webrtc/engine_configurations.h"
18#include "webrtc/modules/audio_coding/main/interface/audio_coding_module_typedefs.h"
19#include "webrtc/modules/audio_coding/main/test/utility.h"
20#include "webrtc/system_wrappers/interface/trace.h"
21#include "webrtc/test/testsupport/fileutils.h"
22
23namespace webrtc {
24
25TestRedFec::TestRedFec()
26 : _acmA(AudioCodingModule::Create(0)),
27 _acmB(AudioCodingModule::Create(1)),
28 _channelA2B(NULL),
29 _testCntr(0) {
30}
31
32TestRedFec::~TestRedFec() {
33 if (_channelA2B != NULL) {
34 delete _channelA2B;
35 _channelA2B = NULL;
36 }
37}
38
39void TestRedFec::Perform() {
40 const std::string file_name = webrtc::test::ResourcePath(
41 "audio_coding/testfile32kHz", "pcm");
42 _inFileA.Open(file_name, 32000, "rb");
43
44 ASSERT_EQ(0, _acmA->InitializeReceiver());
45 ASSERT_EQ(0, _acmB->InitializeReceiver());
46
47 uint8_t numEncoders = _acmA->NumberOfCodecs();
48 CodecInst myCodecParam;
49 for (uint8_t n = 0; n < numEncoders; n++) {
50 EXPECT_EQ(0, _acmB->Codec(n, &myCodecParam));
51 // Default number of channels is 2 for opus, so we change to 1 in this test.
52 if (!strcmp(myCodecParam.plname, "opus")) {
53 myCodecParam.channels = 1;
54 }
55 EXPECT_EQ(0, _acmB->RegisterReceiveCodec(myCodecParam));
56 }
57
58 // Create and connect the channel
59 _channelA2B = new Channel;
60 _acmA->RegisterTransportCallback(_channelA2B);
61 _channelA2B->RegisterReceiverACM(_acmB.get());
62
63#ifndef WEBRTC_CODEC_G722
64 EXPECT_TRUE(false);
65 printf("G722 needs to be activated to run this test\n");
66 return;
67#endif
68 char nameG722[] = "G722";
69 EXPECT_EQ(0, RegisterSendCodec('A', nameG722, 16000));
70 char nameCN[] = "CN";
71 EXPECT_EQ(0, RegisterSendCodec('A', nameCN, 16000));
72 char nameRED[] = "RED";
73 EXPECT_EQ(0, RegisterSendCodec('A', nameRED));
74 OpenOutFile(_testCntr);
75 EXPECT_EQ(0, SetVAD(true, true, VADAggr));
76 EXPECT_EQ(0, _acmA->SetREDStatus(false));
77 EXPECT_FALSE(_acmA->REDStatus());
78 Run();
79 _outFileB.Close();
80
81 EXPECT_EQ(0, _acmA->SetREDStatus(true));
82 EXPECT_TRUE(_acmA->REDStatus());
83 OpenOutFile(_testCntr);
84 Run();
85 _outFileB.Close();
86
87 char nameISAC[] = "iSAC";
88 RegisterSendCodec('A', nameISAC, 16000);
89 OpenOutFile(_testCntr);
90 EXPECT_EQ(0, SetVAD(true, true, VADVeryAggr));
91 EXPECT_EQ(0, _acmA->SetREDStatus(false));
92 EXPECT_FALSE(_acmA->REDStatus());
93 Run();
94 _outFileB.Close();
95
96 EXPECT_EQ(0, _acmA->SetREDStatus(true));
97 EXPECT_TRUE(_acmA->REDStatus());
98 OpenOutFile(_testCntr);
99 Run();
100 _outFileB.Close();
101
102 RegisterSendCodec('A', nameISAC, 32000);
103 OpenOutFile(_testCntr);
104 EXPECT_EQ(0, SetVAD(true, true, VADVeryAggr));
105 EXPECT_EQ(0, _acmA->SetREDStatus(false));
106 EXPECT_FALSE(_acmA->REDStatus());
107 Run();
108 _outFileB.Close();
109
110 EXPECT_EQ(0, _acmA->SetREDStatus(true));
111 EXPECT_TRUE(_acmA->REDStatus());
112 OpenOutFile(_testCntr);
113 Run();
114 _outFileB.Close();
115
116 RegisterSendCodec('A', nameISAC, 32000);
117 OpenOutFile(_testCntr);
118 EXPECT_EQ(0, SetVAD(false, false, VADNormal));
119 EXPECT_EQ(0, _acmA->SetREDStatus(true));
120 EXPECT_TRUE(_acmA->REDStatus());
121 Run();
122
123 RegisterSendCodec('A', nameISAC, 16000);
124 EXPECT_TRUE(_acmA->REDStatus());
125 Run();
126
127 RegisterSendCodec('A', nameISAC, 32000);
128 EXPECT_TRUE(_acmA->REDStatus());
129 Run();
130
131 RegisterSendCodec('A', nameISAC, 16000);
132 EXPECT_TRUE(_acmA->REDStatus());
133 Run();
134 _outFileB.Close();
135
136 _channelA2B->SetFECTestWithPacketLoss(true);
137
138 EXPECT_EQ(0, RegisterSendCodec('A', nameG722));
139 EXPECT_EQ(0, RegisterSendCodec('A', nameCN, 16000));
140 OpenOutFile(_testCntr);
141 EXPECT_EQ(0, SetVAD(true, true, VADAggr));
142 EXPECT_EQ(0, _acmA->SetREDStatus(false));
143 EXPECT_FALSE(_acmA->REDStatus());
144 Run();
145 _outFileB.Close();
146
147 EXPECT_EQ(0, _acmA->SetREDStatus(true));
148 EXPECT_TRUE(_acmA->REDStatus());
149 OpenOutFile(_testCntr);
150 Run();
151 _outFileB.Close();
152
153 RegisterSendCodec('A', nameISAC, 16000);
154 OpenOutFile(_testCntr);
155 EXPECT_EQ(0, SetVAD(true, true, VADVeryAggr));
156 EXPECT_EQ(0, _acmA->SetREDStatus(false));
157 EXPECT_FALSE(_acmA->REDStatus());
158 Run();
159 _outFileB.Close();
160
161 EXPECT_EQ(0, _acmA->SetREDStatus(true));
162 EXPECT_TRUE(_acmA->REDStatus());
163 OpenOutFile(_testCntr);
164 Run();
165 _outFileB.Close();
166
167 RegisterSendCodec('A', nameISAC, 32000);
168 OpenOutFile(_testCntr);
169 EXPECT_EQ(0, SetVAD(true, true, VADVeryAggr));
170 EXPECT_EQ(0, _acmA->SetREDStatus(false));
171 EXPECT_FALSE(_acmA->REDStatus());
172 Run();
173 _outFileB.Close();
174
175 EXPECT_EQ(0, _acmA->SetREDStatus(true));
176 EXPECT_TRUE(_acmA->REDStatus());
177 OpenOutFile(_testCntr);
178 Run();
179 _outFileB.Close();
180
181 RegisterSendCodec('A', nameISAC, 32000);
182 OpenOutFile(_testCntr);
183 EXPECT_EQ(0, SetVAD(false, false, VADNormal));
184 EXPECT_EQ(0, _acmA->SetREDStatus(true));
185 EXPECT_TRUE(_acmA->REDStatus());
186 Run();
187
188 RegisterSendCodec('A', nameISAC, 16000);
189 EXPECT_TRUE(_acmA->REDStatus());
190 Run();
191
192 RegisterSendCodec('A', nameISAC, 32000);
193 EXPECT_TRUE(_acmA->REDStatus());
194 Run();
195
196 RegisterSendCodec('A', nameISAC, 16000);
197 EXPECT_TRUE(_acmA->REDStatus());
198 Run();
199 _outFileB.Close();
200
201#ifndef WEBRTC_CODEC_OPUS
202 EXPECT_TRUE(false);
203 printf("Opus needs to be activated to run this test\n");
204 return;
205#endif
206
207 char nameOpus[] = "opus";
208 RegisterSendCodec('A', nameOpus, 48000);
209
210 EXPECT_TRUE(_acmA->REDStatus());
211
212 // _channelA2B imposes 25% packet loss rate.
213 EXPECT_EQ(0, _acmA->SetPacketLossRate(25));
214
215 // Codec FEC and RED are mutually exclusive.
216 EXPECT_EQ(-1, _acmA->SetCodecFEC(true));
217
218 EXPECT_EQ(0, _acmA->SetREDStatus(false));
219 EXPECT_EQ(0, _acmA->SetCodecFEC(true));
220
221 // Codec FEC and RED are mutually exclusive.
222 EXPECT_EQ(-1, _acmA->SetREDStatus(true));
223
224 EXPECT_TRUE(_acmA->CodecFEC());
225 OpenOutFile(_testCntr);
226 Run();
227
228 // Switch to ISAC with RED.
229 RegisterSendCodec('A', nameISAC, 32000);
230 EXPECT_EQ(0, SetVAD(false, false, VADNormal));
231
232 // ISAC does not support FEC, so FEC should be turned off automatically.
233 EXPECT_FALSE(_acmA->CodecFEC());
234
235 EXPECT_EQ(0, _acmA->SetREDStatus(true));
236 EXPECT_TRUE(_acmA->REDStatus());
237 Run();
238
239 // Switch to Opus again.
240 RegisterSendCodec('A', nameOpus, 48000);
241 EXPECT_EQ(0, _acmA->SetCodecFEC(false));
242 EXPECT_EQ(0, _acmA->SetREDStatus(false));
243 Run();
244
245 EXPECT_EQ(0, _acmA->SetCodecFEC(true));
246 _outFileB.Close();
247
minyue@webrtc.org60fbd652014-09-25 14:36:30 +0000248 // Codecs does not support internal FEC, cannot enable FEC.
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000249 RegisterSendCodec('A', nameG722, 16000);
250 EXPECT_FALSE(_acmA->REDStatus());
251 EXPECT_EQ(-1, _acmA->SetCodecFEC(true));
252 EXPECT_FALSE(_acmA->CodecFEC());
253
254 RegisterSendCodec('A', nameISAC, 16000);
255 EXPECT_FALSE(_acmA->REDStatus());
256 EXPECT_EQ(-1, _acmA->SetCodecFEC(true));
257 EXPECT_FALSE(_acmA->CodecFEC());
minyue@webrtc.org60fbd652014-09-25 14:36:30 +0000258
259 // Codecs does not support internal FEC, disable FEC does not trigger failure.
260 RegisterSendCodec('A', nameG722, 16000);
261 EXPECT_FALSE(_acmA->REDStatus());
262 EXPECT_EQ(0, _acmA->SetCodecFEC(false));
263 EXPECT_FALSE(_acmA->CodecFEC());
264
265 RegisterSendCodec('A', nameISAC, 16000);
266 EXPECT_FALSE(_acmA->REDStatus());
267 EXPECT_EQ(0, _acmA->SetCodecFEC(false));
268 EXPECT_FALSE(_acmA->CodecFEC());
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000269}
270
271int32_t TestRedFec::SetVAD(bool enableDTX, bool enableVAD, ACMVADMode vadMode) {
272 return _acmA->SetVAD(enableDTX, enableVAD, vadMode);
273}
274
275int16_t TestRedFec::RegisterSendCodec(char side, char* codecName,
276 int32_t samplingFreqHz) {
277 std::cout << std::flush;
278 AudioCodingModule* myACM;
279 switch (side) {
280 case 'A': {
281 myACM = _acmA.get();
282 break;
283 }
284 case 'B': {
285 myACM = _acmB.get();
286 break;
287 }
288 default:
289 return -1;
290 }
291
292 if (myACM == NULL) {
293 assert(false);
294 return -1;
295 }
296 CodecInst myCodecParam;
297 EXPECT_GT(AudioCodingModule::Codec(codecName, &myCodecParam,
298 samplingFreqHz, 1), -1);
299 EXPECT_GT(myACM->RegisterSendCodec(myCodecParam), -1);
300
301 // Initialization was successful.
302 return 0;
303}
304
305void TestRedFec::Run() {
306 AudioFrame audioFrame;
307
308 uint16_t msecPassed = 0;
309 uint32_t secPassed = 0;
310 int32_t outFreqHzB = _outFileB.SamplingFrequency();
311
312 while (!_inFileA.EndOfFile()) {
313 EXPECT_GT(_inFileA.Read10MsData(audioFrame), 0);
henrik.lundin@webrtc.orgf56c1622015-03-02 12:29:30 +0000314 EXPECT_GE(_acmA->Add10MsData(audioFrame), 0);
minyue@webrtc.orgaa5ea1c2014-05-23 15:16:51 +0000315 EXPECT_EQ(0, _acmB->PlayoutData10Ms(outFreqHzB, &audioFrame));
316 _outFileB.Write10MsData(audioFrame.data_, audioFrame.samples_per_channel_);
317 msecPassed += 10;
318 if (msecPassed >= 1000) {
319 msecPassed = 0;
320 secPassed++;
321 }
322 // Test that toggling RED on and off works.
323 if (((secPassed % 5) == 4) && (msecPassed == 0) && (_testCntr > 14)) {
324 EXPECT_EQ(0, _acmA->SetREDStatus(false));
325 }
326 if (((secPassed % 5) == 4) && (msecPassed >= 990) && (_testCntr > 14)) {
327 EXPECT_EQ(0, _acmA->SetREDStatus(true));
328 }
329 }
330 _inFileA.Rewind();
331}
332
333void TestRedFec::OpenOutFile(int16_t test_number) {
334 std::string file_name;
335 std::stringstream file_stream;
336 file_stream << webrtc::test::OutputPath();
337 file_stream << "TestRedFec_outFile_";
338 file_stream << test_number << ".pcm";
339 file_name = file_stream.str();
340 _outFileB.Open(file_name, 16000, "wb");
341}
342
343} // namespace webrtc