• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/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/include/audio_coding_module_typedefs.h"
19 #include "webrtc/modules/audio_coding/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 
TestRedFec()51 TestRedFec::TestRedFec()
52     : _acmA(AudioCodingModule::Create(0)),
53       _acmB(AudioCodingModule::Create(1)),
54       _channelA2B(NULL),
55       _testCntr(0) {
56 }
57 
~TestRedFec()58 TestRedFec::~TestRedFec() {
59   if (_channelA2B != NULL) {
60     delete _channelA2B;
61     _channelA2B = NULL;
62   }
63 }
64 
Perform()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 
SetVAD(bool enableDTX,bool enableVAD,ACMVADMode vadMode)419 int32_t TestRedFec::SetVAD(bool enableDTX, bool enableVAD, ACMVADMode vadMode) {
420   return _acmA->SetVAD(enableDTX, enableVAD, vadMode);
421 }
422 
RegisterSendCodec(char side,const char * codecName,int32_t samplingFreqHz)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 
Run()453 void TestRedFec::Run() {
454   AudioFrame audioFrame;
455   int32_t outFreqHzB = _outFileB.SamplingFrequency();
456   // Set test length to 500 ms (50 blocks of 10 ms each).
457   _inFileA.SetNum10MsBlocksToRead(50);
458   // Fast-forward 1 second (100 blocks) since the file starts with silence.
459   _inFileA.FastForward(100);
460 
461   while (!_inFileA.EndOfFile()) {
462     EXPECT_GT(_inFileA.Read10MsData(audioFrame), 0);
463     EXPECT_GE(_acmA->Add10MsData(audioFrame), 0);
464     EXPECT_EQ(0, _acmB->PlayoutData10Ms(outFreqHzB, &audioFrame));
465     _outFileB.Write10MsData(audioFrame.data_, audioFrame.samples_per_channel_);
466   }
467   _inFileA.Rewind();
468 }
469 
OpenOutFile(int16_t test_number)470 void TestRedFec::OpenOutFile(int16_t test_number) {
471   std::string file_name;
472   std::stringstream file_stream;
473   file_stream << webrtc::test::OutputPath();
474   file_stream << "TestRedFec_outFile_";
475   file_stream << test_number << ".pcm";
476   file_name = file_stream.str();
477   _outFileB.Open(file_name, 16000, "wb");
478 }
479 
480 }  // namespace webrtc
481