blob: 10498d8c5770b798b65fd998dd20192fecc8e525 [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
248 // Codecs does not support internal FEC.
249 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());
258}
259
260int32_t TestRedFec::SetVAD(bool enableDTX, bool enableVAD, ACMVADMode vadMode) {
261 return _acmA->SetVAD(enableDTX, enableVAD, vadMode);
262}
263
264int16_t TestRedFec::RegisterSendCodec(char side, char* codecName,
265 int32_t samplingFreqHz) {
266 std::cout << std::flush;
267 AudioCodingModule* myACM;
268 switch (side) {
269 case 'A': {
270 myACM = _acmA.get();
271 break;
272 }
273 case 'B': {
274 myACM = _acmB.get();
275 break;
276 }
277 default:
278 return -1;
279 }
280
281 if (myACM == NULL) {
282 assert(false);
283 return -1;
284 }
285 CodecInst myCodecParam;
286 EXPECT_GT(AudioCodingModule::Codec(codecName, &myCodecParam,
287 samplingFreqHz, 1), -1);
288 EXPECT_GT(myACM->RegisterSendCodec(myCodecParam), -1);
289
290 // Initialization was successful.
291 return 0;
292}
293
294void TestRedFec::Run() {
295 AudioFrame audioFrame;
296
297 uint16_t msecPassed = 0;
298 uint32_t secPassed = 0;
299 int32_t outFreqHzB = _outFileB.SamplingFrequency();
300
301 while (!_inFileA.EndOfFile()) {
302 EXPECT_GT(_inFileA.Read10MsData(audioFrame), 0);
303 EXPECT_EQ(0, _acmA->Add10MsData(audioFrame));
304 EXPECT_GT(_acmA->Process(), -1);
305 EXPECT_EQ(0, _acmB->PlayoutData10Ms(outFreqHzB, &audioFrame));
306 _outFileB.Write10MsData(audioFrame.data_, audioFrame.samples_per_channel_);
307 msecPassed += 10;
308 if (msecPassed >= 1000) {
309 msecPassed = 0;
310 secPassed++;
311 }
312 // Test that toggling RED on and off works.
313 if (((secPassed % 5) == 4) && (msecPassed == 0) && (_testCntr > 14)) {
314 EXPECT_EQ(0, _acmA->SetREDStatus(false));
315 }
316 if (((secPassed % 5) == 4) && (msecPassed >= 990) && (_testCntr > 14)) {
317 EXPECT_EQ(0, _acmA->SetREDStatus(true));
318 }
319 }
320 _inFileA.Rewind();
321}
322
323void TestRedFec::OpenOutFile(int16_t test_number) {
324 std::string file_name;
325 std::stringstream file_stream;
326 file_stream << webrtc::test::OutputPath();
327 file_stream << "TestRedFec_outFile_";
328 file_stream << test_number << ".pcm";
329 file_name = file_stream.str();
330 _outFileB.Open(file_name, 16000, "wb");
331}
332
333} // namespace webrtc