OLD | NEW |
| (Empty) |
1 /* | |
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/include/audio_coding_module_typedefs.
h" | |
19 #include "webrtc/modules/audio_coding/main/test/utility.h" | |
20 #include "webrtc/system_wrappers/include/trace.h" | |
21 #include "webrtc/test/testsupport/fileutils.h" | |
22 | |
23 #ifdef SUPPORT_RED_WB | |
24 #undef SUPPORT_RED_WB | |
25 #endif | |
26 | |
27 #ifdef SUPPORT_RED_SWB | |
28 #undef SUPPORT_RED_SWB | |
29 #endif | |
30 | |
31 #ifdef SUPPORT_RED_FB | |
32 #undef SUPPORT_RED_FB | |
33 #endif | |
34 | |
35 namespace webrtc { | |
36 | |
37 namespace { | |
38 const char kNameL16[] = "L16"; | |
39 const char kNamePCMU[] = "PCMU"; | |
40 const char kNameCN[] = "CN"; | |
41 const char kNameRED[] = "RED"; | |
42 | |
43 // These three are only used by code #ifdeffed on WEBRTC_CODEC_G722. | |
44 #ifdef WEBRTC_CODEC_G722 | |
45 const char kNameISAC[] = "ISAC"; | |
46 const char kNameG722[] = "G722"; | |
47 const char kNameOPUS[] = "opus"; | |
48 #endif | |
49 } | |
50 | |
51 TestRedFec::TestRedFec() | |
52 : _acmA(AudioCodingModule::Create(0)), | |
53 _acmB(AudioCodingModule::Create(1)), | |
54 _channelA2B(NULL), | |
55 _testCntr(0) { | |
56 } | |
57 | |
58 TestRedFec::~TestRedFec() { | |
59 if (_channelA2B != NULL) { | |
60 delete _channelA2B; | |
61 _channelA2B = NULL; | |
62 } | |
63 } | |
64 | |
65 void TestRedFec::Perform() { | |
66 const std::string file_name = webrtc::test::ResourcePath( | |
67 "audio_coding/testfile32kHz", "pcm"); | |
68 _inFileA.Open(file_name, 32000, "rb"); | |
69 | |
70 ASSERT_EQ(0, _acmA->InitializeReceiver()); | |
71 ASSERT_EQ(0, _acmB->InitializeReceiver()); | |
72 | |
73 uint8_t numEncoders = _acmA->NumberOfCodecs(); | |
74 CodecInst myCodecParam; | |
75 for (uint8_t n = 0; n < numEncoders; n++) { | |
76 EXPECT_EQ(0, _acmB->Codec(n, &myCodecParam)); | |
77 // Default number of channels is 2 for opus, so we change to 1 in this test. | |
78 if (!strcmp(myCodecParam.plname, "opus")) { | |
79 myCodecParam.channels = 1; | |
80 } | |
81 EXPECT_EQ(0, _acmB->RegisterReceiveCodec(myCodecParam)); | |
82 } | |
83 | |
84 // Create and connect the channel | |
85 _channelA2B = new Channel; | |
86 _acmA->RegisterTransportCallback(_channelA2B); | |
87 _channelA2B->RegisterReceiverACM(_acmB.get()); | |
88 | |
89 EXPECT_EQ(0, RegisterSendCodec('A', kNameL16, 8000)); | |
90 EXPECT_EQ(0, RegisterSendCodec('A', kNameCN, 8000)); | |
91 EXPECT_EQ(0, RegisterSendCodec('A', kNameRED)); | |
92 EXPECT_EQ(0, SetVAD(true, true, VADAggr)); | |
93 EXPECT_EQ(0, _acmA->SetREDStatus(true)); | |
94 EXPECT_TRUE(_acmA->REDStatus()); | |
95 | |
96 OpenOutFile(_testCntr); | |
97 Run(); | |
98 _outFileB.Close(); | |
99 | |
100 RegisterSendCodec('A', kNamePCMU, 8000); | |
101 // Switch to another 8 kHz codec, RED should remain switched on. | |
102 EXPECT_TRUE(_acmA->REDStatus()); | |
103 OpenOutFile(_testCntr); | |
104 Run(); | |
105 _outFileB.Close(); | |
106 | |
107 #ifndef WEBRTC_CODEC_G722 | |
108 EXPECT_TRUE(false); | |
109 printf("G722 needs to be activated to run this test\n"); | |
110 return; | |
111 #else | |
112 EXPECT_EQ(0, RegisterSendCodec('A', kNameG722, 16000)); | |
113 EXPECT_EQ(0, RegisterSendCodec('A', kNameCN, 16000)); | |
114 | |
115 #ifdef SUPPORT_RED_WB | |
116 // Switch codec, RED should remain. | |
117 EXPECT_TRUE(_acmA->REDStatus()); | |
118 #else | |
119 // Switch to a 16 kHz codec, RED should have been switched off. | |
120 EXPECT_FALSE(_acmA->REDStatus()); | |
121 #endif | |
122 | |
123 OpenOutFile(_testCntr); | |
124 EXPECT_EQ(0, SetVAD(true, true, VADAggr)); | |
125 EXPECT_EQ(0, _acmA->SetREDStatus(false)); | |
126 EXPECT_FALSE(_acmA->REDStatus()); | |
127 Run(); | |
128 #ifdef SUPPORT_RED_WB | |
129 EXPECT_EQ(0, _acmA->SetREDStatus(true)); | |
130 EXPECT_TRUE(_acmA->REDStatus()); | |
131 #else | |
132 EXPECT_EQ(-1, _acmA->SetREDStatus(true)); | |
133 EXPECT_FALSE(_acmA->REDStatus()); | |
134 #endif | |
135 Run(); | |
136 _outFileB.Close(); | |
137 | |
138 RegisterSendCodec('A', kNameISAC, 16000); | |
139 | |
140 #ifdef SUPPORT_RED_WB | |
141 // Switch codec, RED should remain. | |
142 EXPECT_TRUE(_acmA->REDStatus()); | |
143 #else | |
144 EXPECT_FALSE(_acmA->REDStatus()); | |
145 #endif | |
146 | |
147 OpenOutFile(_testCntr); | |
148 EXPECT_EQ(0, SetVAD(true, true, VADVeryAggr)); | |
149 EXPECT_EQ(0, _acmA->SetREDStatus(false)); | |
150 EXPECT_FALSE(_acmA->REDStatus()); | |
151 Run(); | |
152 _outFileB.Close(); | |
153 | |
154 #ifdef SUPPORT_RED_WB | |
155 EXPECT_EQ(0, _acmA->SetREDStatus(true)); | |
156 EXPECT_TRUE(_acmA->REDStatus()); | |
157 #else | |
158 EXPECT_EQ(-1, _acmA->SetREDStatus(true)); | |
159 EXPECT_FALSE(_acmA->REDStatus()); | |
160 #endif | |
161 OpenOutFile(_testCntr); | |
162 Run(); | |
163 _outFileB.Close(); | |
164 | |
165 RegisterSendCodec('A', kNameISAC, 32000); | |
166 | |
167 #if defined(SUPPORT_RED_SWB) && defined(SUPPORT_RED_WB) | |
168 // Switch codec, RED should remain. | |
169 EXPECT_TRUE(_acmA->REDStatus()); | |
170 #else | |
171 // Switch to a 32 kHz codec, RED should have been switched off. | |
172 EXPECT_FALSE(_acmA->REDStatus()); | |
173 #endif | |
174 | |
175 OpenOutFile(_testCntr); | |
176 EXPECT_EQ(0, SetVAD(true, true, VADVeryAggr)); | |
177 EXPECT_EQ(0, _acmA->SetREDStatus(false)); | |
178 EXPECT_FALSE(_acmA->REDStatus()); | |
179 Run(); | |
180 _outFileB.Close(); | |
181 | |
182 #ifdef SUPPORT_RED_SWB | |
183 EXPECT_EQ(0, _acmA->SetREDStatus(true)); | |
184 EXPECT_TRUE(_acmA->REDStatus()); | |
185 #else | |
186 EXPECT_EQ(-1, _acmA->SetREDStatus(true)); | |
187 EXPECT_FALSE(_acmA->REDStatus()); | |
188 #endif | |
189 OpenOutFile(_testCntr); | |
190 Run(); | |
191 _outFileB.Close(); | |
192 | |
193 RegisterSendCodec('A', kNameISAC, 32000); | |
194 EXPECT_EQ(0, SetVAD(false, false, VADNormal)); | |
195 | |
196 #if defined(SUPPORT_RED_SWB) && defined(SUPPORT_RED_WB) | |
197 OpenOutFile(_testCntr); | |
198 EXPECT_EQ(0, _acmA->SetREDStatus(true)); | |
199 EXPECT_TRUE(_acmA->REDStatus()); | |
200 Run(); | |
201 | |
202 RegisterSendCodec('A', kNameISAC, 16000); | |
203 EXPECT_TRUE(_acmA->REDStatus()); | |
204 Run(); | |
205 | |
206 RegisterSendCodec('A', kNameISAC, 32000); | |
207 EXPECT_TRUE(_acmA->REDStatus()); | |
208 Run(); | |
209 | |
210 RegisterSendCodec('A', kNameISAC, 16000); | |
211 EXPECT_TRUE(_acmA->REDStatus()); | |
212 Run(); | |
213 _outFileB.Close(); | |
214 #else | |
215 EXPECT_EQ(-1, _acmA->SetREDStatus(true)); | |
216 EXPECT_FALSE(_acmA->REDStatus()); | |
217 #endif | |
218 | |
219 _channelA2B->SetFECTestWithPacketLoss(true); | |
220 // Following tests are under packet losses. | |
221 | |
222 EXPECT_EQ(0, RegisterSendCodec('A', kNameG722)); | |
223 EXPECT_EQ(0, RegisterSendCodec('A', kNameCN, 16000)); | |
224 | |
225 #if defined(SUPPORT_RED_WB) && defined(SUPPORT_RED_SWB) | |
226 // Switch codec, RED should remain. | |
227 EXPECT_TRUE(_acmA->REDStatus()); | |
228 #else | |
229 // Switch to a 16 kHz codec, RED should have been switched off. | |
230 EXPECT_FALSE(_acmA->REDStatus()); | |
231 #endif | |
232 | |
233 OpenOutFile(_testCntr); | |
234 EXPECT_EQ(0, SetVAD(true, true, VADAggr)); | |
235 EXPECT_EQ(0, _acmA->SetREDStatus(false)); | |
236 EXPECT_FALSE(_acmA->REDStatus()); | |
237 Run(); | |
238 _outFileB.Close(); | |
239 | |
240 #ifdef SUPPORT_RED_WB | |
241 EXPECT_EQ(0, _acmA->SetREDStatus(true)); | |
242 EXPECT_TRUE(_acmA->REDStatus()); | |
243 #else | |
244 EXPECT_EQ(-1, _acmA->SetREDStatus(true)); | |
245 EXPECT_FALSE(_acmA->REDStatus()); | |
246 #endif | |
247 OpenOutFile(_testCntr); | |
248 Run(); | |
249 _outFileB.Close(); | |
250 | |
251 RegisterSendCodec('A', kNameISAC, 16000); | |
252 | |
253 #ifdef SUPPORT_RED_WB | |
254 // Switch codec, RED should remain. | |
255 EXPECT_TRUE(_acmA->REDStatus()); | |
256 #else | |
257 // Switch to a 16 kHz codec, RED should have been switched off. | |
258 EXPECT_FALSE(_acmA->REDStatus()); | |
259 #endif | |
260 | |
261 OpenOutFile(_testCntr); | |
262 EXPECT_EQ(0, SetVAD(true, true, VADVeryAggr)); | |
263 EXPECT_EQ(0, _acmA->SetREDStatus(false)); | |
264 EXPECT_FALSE(_acmA->REDStatus()); | |
265 Run(); | |
266 _outFileB.Close(); | |
267 #ifdef SUPPORT_RED_WB | |
268 EXPECT_EQ(0, _acmA->SetREDStatus(true)); | |
269 EXPECT_TRUE(_acmA->REDStatus()); | |
270 #else | |
271 EXPECT_EQ(-1, _acmA->SetREDStatus(true)); | |
272 EXPECT_FALSE(_acmA->REDStatus()); | |
273 #endif | |
274 OpenOutFile(_testCntr); | |
275 Run(); | |
276 _outFileB.Close(); | |
277 | |
278 RegisterSendCodec('A', kNameISAC, 32000); | |
279 | |
280 #if defined(SUPPORT_RED_SWB) && defined(SUPPORT_RED_WB) | |
281 // Switch codec, RED should remain. | |
282 EXPECT_TRUE(_acmA->REDStatus()); | |
283 #else | |
284 // Switch to a 32 kHz codec, RED should have been switched off. | |
285 EXPECT_FALSE(_acmA->REDStatus()); | |
286 #endif | |
287 | |
288 OpenOutFile(_testCntr); | |
289 EXPECT_EQ(0, SetVAD(true, true, VADVeryAggr)); | |
290 EXPECT_EQ(0, _acmA->SetREDStatus(false)); | |
291 EXPECT_FALSE(_acmA->REDStatus()); | |
292 #ifdef SUPPORT_RED_SWB | |
293 EXPECT_EQ(0, _acmA->SetREDStatus(true)); | |
294 EXPECT_TRUE(_acmA->REDStatus()); | |
295 #else | |
296 EXPECT_EQ(-1, _acmA->SetREDStatus(true)); | |
297 EXPECT_FALSE(_acmA->REDStatus()); | |
298 #endif | |
299 OpenOutFile(_testCntr); | |
300 Run(); | |
301 _outFileB.Close(); | |
302 | |
303 RegisterSendCodec('A', kNameISAC, 32000); | |
304 EXPECT_EQ(0, SetVAD(false, false, VADNormal)); | |
305 #if defined(SUPPORT_RED_SWB) && defined(SUPPORT_RED_WB) | |
306 OpenOutFile(_testCntr); | |
307 EXPECT_EQ(0, _acmA->SetREDStatus(true)); | |
308 EXPECT_TRUE(_acmA->REDStatus()); | |
309 Run(); | |
310 | |
311 RegisterSendCodec('A', kNameISAC, 16000); | |
312 EXPECT_TRUE(_acmA->REDStatus()); | |
313 Run(); | |
314 | |
315 RegisterSendCodec('A', kNameISAC, 32000); | |
316 EXPECT_TRUE(_acmA->REDStatus()); | |
317 Run(); | |
318 | |
319 RegisterSendCodec('A', kNameISAC, 16000); | |
320 EXPECT_TRUE(_acmA->REDStatus()); | |
321 Run(); | |
322 _outFileB.Close(); | |
323 #else | |
324 EXPECT_EQ(-1, _acmA->SetREDStatus(true)); | |
325 EXPECT_FALSE(_acmA->REDStatus()); | |
326 #endif | |
327 | |
328 #ifndef WEBRTC_CODEC_OPUS | |
329 EXPECT_TRUE(false); | |
330 printf("Opus needs to be activated to run this test\n"); | |
331 return; | |
332 #endif | |
333 | |
334 RegisterSendCodec('A', kNameOPUS, 48000); | |
335 | |
336 #if defined(SUPPORT_RED_FB) && defined(SUPPORT_RED_SWB) &&\ | |
337 defined(SUPPORT_RED_WB) | |
338 // Switch to codec, RED should remain switched on. | |
339 EXPECT_TRUE(_acmA->REDStatus()); | |
340 #else | |
341 EXPECT_FALSE(_acmA->REDStatus()); | |
342 #endif | |
343 | |
344 // _channelA2B imposes 25% packet loss rate. | |
345 EXPECT_EQ(0, _acmA->SetPacketLossRate(25)); | |
346 | |
347 #ifdef SUPPORT_RED_FB | |
348 EXPECT_EQ(0, _acmA->SetREDStatus(true)); | |
349 EXPECT_TRUE(_acmA->REDStatus()); | |
350 // Codec FEC and RED are mutually exclusive. | |
351 EXPECT_EQ(-1, _acmA->SetCodecFEC(true)); | |
352 | |
353 EXPECT_EQ(0, _acmA->SetREDStatus(false)); | |
354 EXPECT_EQ(0, _acmA->SetCodecFEC(true)); | |
355 | |
356 // Codec FEC and RED are mutually exclusive. | |
357 EXPECT_EQ(-1, _acmA->SetREDStatus(true)); | |
358 #else | |
359 EXPECT_EQ(-1, _acmA->SetREDStatus(true)); | |
360 EXPECT_FALSE(_acmA->REDStatus()); | |
361 EXPECT_EQ(0, _acmA->SetCodecFEC(true)); | |
362 #endif | |
363 | |
364 EXPECT_TRUE(_acmA->CodecFEC()); | |
365 OpenOutFile(_testCntr); | |
366 Run(); | |
367 | |
368 // Switch to L16 with RED. | |
369 RegisterSendCodec('A', kNameL16, 8000); | |
370 EXPECT_EQ(0, SetVAD(false, false, VADNormal)); | |
371 | |
372 // L16 does not support FEC, so FEC should be turned off automatically. | |
373 EXPECT_FALSE(_acmA->CodecFEC()); | |
374 | |
375 EXPECT_EQ(0, _acmA->SetREDStatus(true)); | |
376 EXPECT_TRUE(_acmA->REDStatus()); | |
377 Run(); | |
378 | |
379 // Switch to Opus again. | |
380 RegisterSendCodec('A', kNameOPUS, 48000); | |
381 #ifdef SUPPORT_RED_FB | |
382 // Switch to codec, RED should remain switched on. | |
383 EXPECT_TRUE(_acmA->REDStatus()); | |
384 #else | |
385 EXPECT_FALSE(_acmA->REDStatus()); | |
386 #endif | |
387 EXPECT_EQ(0, _acmA->SetREDStatus(false)); | |
388 EXPECT_EQ(0, _acmA->SetCodecFEC(false)); | |
389 Run(); | |
390 | |
391 EXPECT_EQ(0, _acmA->SetCodecFEC(true)); | |
392 _outFileB.Close(); | |
393 | |
394 // Codecs does not support internal FEC, cannot enable FEC. | |
395 RegisterSendCodec('A', kNameG722, 16000); | |
396 EXPECT_FALSE(_acmA->REDStatus()); | |
397 EXPECT_EQ(-1, _acmA->SetCodecFEC(true)); | |
398 EXPECT_FALSE(_acmA->CodecFEC()); | |
399 | |
400 RegisterSendCodec('A', kNameISAC, 16000); | |
401 EXPECT_FALSE(_acmA->REDStatus()); | |
402 EXPECT_EQ(-1, _acmA->SetCodecFEC(true)); | |
403 EXPECT_FALSE(_acmA->CodecFEC()); | |
404 | |
405 // Codecs does not support internal FEC, disable FEC does not trigger failure. | |
406 RegisterSendCodec('A', kNameG722, 16000); | |
407 EXPECT_FALSE(_acmA->REDStatus()); | |
408 EXPECT_EQ(0, _acmA->SetCodecFEC(false)); | |
409 EXPECT_FALSE(_acmA->CodecFEC()); | |
410 | |
411 RegisterSendCodec('A', kNameISAC, 16000); | |
412 EXPECT_FALSE(_acmA->REDStatus()); | |
413 EXPECT_EQ(0, _acmA->SetCodecFEC(false)); | |
414 EXPECT_FALSE(_acmA->CodecFEC()); | |
415 | |
416 #endif // defined(WEBRTC_CODEC_G722) | |
417 } | |
418 | |
419 int32_t TestRedFec::SetVAD(bool enableDTX, bool enableVAD, ACMVADMode vadMode) { | |
420 return _acmA->SetVAD(enableDTX, enableVAD, vadMode); | |
421 } | |
422 | |
423 int16_t TestRedFec::RegisterSendCodec(char side, const char* codecName, | |
424 int32_t samplingFreqHz) { | |
425 std::cout << std::flush; | |
426 AudioCodingModule* myACM; | |
427 switch (side) { | |
428 case 'A': { | |
429 myACM = _acmA.get(); | |
430 break; | |
431 } | |
432 case 'B': { | |
433 myACM = _acmB.get(); | |
434 break; | |
435 } | |
436 default: | |
437 return -1; | |
438 } | |
439 | |
440 if (myACM == NULL) { | |
441 assert(false); | |
442 return -1; | |
443 } | |
444 CodecInst myCodecParam; | |
445 EXPECT_GT(AudioCodingModule::Codec(codecName, &myCodecParam, | |
446 samplingFreqHz, 1), -1); | |
447 EXPECT_GT(myACM->RegisterSendCodec(myCodecParam), -1); | |
448 | |
449 // Initialization was successful. | |
450 return 0; | |
451 } | |
452 | |
453 void TestRedFec::Run() { | |
454 AudioFrame audioFrame; | |
455 int32_t outFreqHzB = _outFileB.SamplingFrequency(); | |
456 | |
457 while (!_inFileA.EndOfFile()) { | |
458 EXPECT_GT(_inFileA.Read10MsData(audioFrame), 0); | |
459 EXPECT_GE(_acmA->Add10MsData(audioFrame), 0); | |
460 EXPECT_EQ(0, _acmB->PlayoutData10Ms(outFreqHzB, &audioFrame)); | |
461 _outFileB.Write10MsData(audioFrame.data_, audioFrame.samples_per_channel_); | |
462 } | |
463 _inFileA.Rewind(); | |
464 } | |
465 | |
466 void TestRedFec::OpenOutFile(int16_t test_number) { | |
467 std::string file_name; | |
468 std::stringstream file_stream; | |
469 file_stream << webrtc::test::OutputPath(); | |
470 file_stream << "TestRedFec_outFile_"; | |
471 file_stream << test_number << ".pcm"; | |
472 file_name = file_stream.str(); | |
473 _outFileB.Open(file_name, 16000, "wb"); | |
474 } | |
475 | |
476 } // namespace webrtc | |
OLD | NEW |