blob: fcca3748df72c397fbdfe1e225463219e07a7349 [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
andrew@webrtc.org63a50982012-05-02 23:56:37 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
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 "TestVADDTX.h"
12
niklase@google.com470e71d2011-07-07 08:21:25 +000013#include <iostream>
kjellander@webrtc.org5490c712011-12-21 13:34:18 +000014
15#include "audio_coding_module_typedefs.h"
16#include "common_types.h"
17#include "engine_configurations.h"
18#include "testsupport/fileutils.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000019#include "trace.h"
kjellander@webrtc.org5490c712011-12-21 13:34:18 +000020#include "utility.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000021
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +000022namespace webrtc {
niklase@google.com470e71d2011-07-07 08:21:25 +000023
24TestVADDTX::TestVADDTX(int testMode):
25_acmA(NULL),
26_acmB(NULL),
27_channelA2B(NULL),
28_testResults(0)
29{
30 //testMode == 1 for more extensive testing
31 //testMode == 0 for quick test (autotest)
32 _testMode = testMode;
33}
34
niklase@google.com470e71d2011-07-07 08:21:25 +000035TestVADDTX::~TestVADDTX()
36{
37 if(_acmA != NULL)
38 {
39 AudioCodingModule::Destroy(_acmA);
40 _acmA = NULL;
41 }
42 if(_acmB != NULL)
43 {
44 AudioCodingModule::Destroy(_acmB);
45 _acmB = NULL;
46 }
47 if(_channelA2B != NULL)
48 {
49 delete _channelA2B;
50 _channelA2B = NULL;
51 }
52}
53
54void TestVADDTX::Perform()
55{
niklase@google.com470e71d2011-07-07 08:21:25 +000056 if(_testMode == 0)
57 {
58 printf("Running VAD/DTX Test");
59 WEBRTC_TRACE(webrtc::kTraceStateInfo, webrtc::kTraceAudioCoding, -1,
60 "---------- TestVADDTX ----------");
61 }
tina.legrand@webrtc.orgba468042012-08-17 10:38:28 +000062
63 const std::string file_name =
64 webrtc::test::ResourcePath("audio_coding/testfile32kHz", "pcm");
65 _inFileA.Open(file_name, 32000, "rb");
niklase@google.com470e71d2011-07-07 08:21:25 +000066
67 _acmA = AudioCodingModule::Create(0);
68 _acmB = AudioCodingModule::Create(1);
69
70 _acmA->InitializeReceiver();
71 _acmB->InitializeReceiver();
72
73 WebRtc_UWord8 numEncoders = _acmA->NumberOfCodecs();
74 CodecInst myCodecParam;
75 if(_testMode != 0)
76 {
77 printf("Registering codecs at receiver... \n");
78 }
79 for(WebRtc_UWord8 n = 0; n < numEncoders; n++)
80 {
81 _acmB->Codec(n, myCodecParam);
82 if(_testMode != 0)
83 {
84 printf("%s\n", myCodecParam.plname);
85 }
86 _acmB->RegisterReceiveCodec(myCodecParam);
87 }
88
89 // Create and connect the channel
phoglund@webrtc.orgd1a860b2012-01-26 14:49:28 +000090 _channelA2B = new Channel;
niklase@google.com470e71d2011-07-07 08:21:25 +000091 _acmA->RegisterTransportCallback(_channelA2B);
92 _channelA2B->RegisterReceiverACM(_acmB);
93
94 _acmA->RegisterVADCallback(&_monitor);
95
96
97 WebRtc_Word16 testCntr = 1;
niklase@google.com470e71d2011-07-07 08:21:25 +000098 WebRtc_Word16 testResults = 0;
99
100#ifdef WEBRTC_CODEC_ISAC
101 // Open outputfile
102 OpenOutFile(testCntr++);
103
104 // Register iSAC WB as send codec
105 char nameISAC[] = "ISAC";
106 RegisterSendCodec('A', nameISAC, 16000);
107
108 // Run the five test cased
109 runTestCases();
110
111 // Close file
112 _outFileB.Close();
113
114 // Open outputfile
115 OpenOutFile(testCntr++);
116
117 // Register iSAC SWB as send codec
118 RegisterSendCodec('A', nameISAC, 32000);
119
120 // Run the five test cased
121 runTestCases();
122
123 // Close file
124 _outFileB.Close();
125#endif
126#ifdef WEBRTC_CODEC_ILBC
127 // Open outputfile
128 OpenOutFile(testCntr++);
129
130 // Register iLBC as send codec
131 char nameILBC[] = "ilbc";
132 RegisterSendCodec('A', nameILBC);
133
134 // Run the five test cased
135 runTestCases();
136
137 // Close file
138 _outFileB.Close();
139
140#endif
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000141#ifdef WEBRTC_CODEC_OPUS
142 // Open outputfile
143 OpenOutFile(testCntr++);
144
145 // Register Opus as send codec
146 char nameOPUS[] = "opus";
147 RegisterSendCodec('A', nameOPUS);
148
149 // Run the five test cased
150 runTestCases();
151
152 // Close file
153 _outFileB.Close();
154
155#endif
niklase@google.com470e71d2011-07-07 08:21:25 +0000156 if(_testMode) {
157 printf("Done!\n");
158 }
159
160 printf("VAD/DTX test completed with %d subtests failed\n", testResults);
161 if (testResults > 0)
162 {
tina.legrand@webrtc.org2e096922011-08-18 06:20:30 +0000163 printf("Press return\n\n");
niklase@google.com470e71d2011-07-07 08:21:25 +0000164 getchar();
165 }
166}
167
168void TestVADDTX::runTestCases()
169{
170 if(_testMode != 0)
171 {
172 CodecInst myCodecParam;
173 _acmA->SendCodec(myCodecParam);
174 printf("%s\n", myCodecParam.plname);
175 }
176 else
177 {
178 printf(".");
179 }
180 // #1 DTX = OFF, VAD = ON, VADNormal
181 if(_testMode != 0)
182 printf("Test #1 ");
183 SetVAD(false, true, VADNormal);
184 Run();
185 _testResults += VerifyTest();
phoglund@webrtc.orgd1a860b2012-01-26 14:49:28 +0000186
niklase@google.com470e71d2011-07-07 08:21:25 +0000187 // #2 DTX = OFF, VAD = ON, VADAggr
188 if(_testMode != 0)
189 printf("Test #2 ");
190 SetVAD(false, true, VADAggr);
191 Run();
192 _testResults += VerifyTest();
phoglund@webrtc.orgd1a860b2012-01-26 14:49:28 +0000193
niklase@google.com470e71d2011-07-07 08:21:25 +0000194 // #3 DTX = ON, VAD = ON, VADLowBitrate
195 if(_testMode != 0)
196 printf("Test #3 ");
197 SetVAD(true, true, VADLowBitrate);
198 Run();
199 _testResults += VerifyTest();
200
201 // #4 DTX = ON, VAD = ON, VADVeryAggr
202 if(_testMode != 0)
203 printf("Test #4 ");
204 SetVAD(true, true, VADVeryAggr);
205 Run();
206 _testResults += VerifyTest();
207
208 // #5 DTX = ON, VAD = OFF, VADNormal
209 if(_testMode != 0)
210 printf("Test #5 ");
211 SetVAD(true, false, VADNormal);
212 Run();
213 _testResults += VerifyTest();
214
215}
216void TestVADDTX::runTestInternalDTX()
217{
218 // #6 DTX = ON, VAD = ON, VADNormal
219 if(_testMode != 0)
220 printf("Test #6 ");
221
222 SetVAD(true, true, VADNormal);
223 if(_acmA->ReplaceInternalDTXWithWebRtc(true) < 0) {
224 printf("Was not able to replace DTX since CN was not registered\n");
225 }
226 Run();
227 _testResults += VerifyTest();
228}
229
230void TestVADDTX::SetVAD(bool statusDTX, bool statusVAD, WebRtc_Word16 vadMode)
231{
niklase@google.com470e71d2011-07-07 08:21:25 +0000232 bool dtxEnabled, vadEnabled;
233 ACMVADMode vadModeSet;
phoglund@webrtc.orgd1a860b2012-01-26 14:49:28 +0000234
235 if (_acmA->SetVAD(statusDTX, statusVAD, (ACMVADMode) vadMode) < 0) {
236 assert(false);
237 }
238 if (_acmA->VAD(dtxEnabled, vadEnabled, vadModeSet) < 0) {
239 assert(false);
240 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000241
242 if(_testMode != 0)
243 {
phoglund@webrtc.orgd1a860b2012-01-26 14:49:28 +0000244 if(statusDTX != dtxEnabled)
niklase@google.com470e71d2011-07-07 08:21:25 +0000245 {
phoglund@webrtc.orgd1a860b2012-01-26 14:49:28 +0000246 printf("DTX: %s not the same as requested: %s\n",
niklase@google.com470e71d2011-07-07 08:21:25 +0000247 dtxEnabled? "ON":"OFF", dtxEnabled? "OFF":"ON");
248 }
tina.legrand@webrtc.org2e096922011-08-18 06:20:30 +0000249 if(((statusVAD == true) && (vadEnabled == false)) ||
250 ((statusVAD == false) && (vadEnabled == false) &&
251 (statusDTX == true)))
niklase@google.com470e71d2011-07-07 08:21:25 +0000252 {
phoglund@webrtc.orgd1a860b2012-01-26 14:49:28 +0000253 printf("VAD: %s not the same as requested: %s\n",
niklase@google.com470e71d2011-07-07 08:21:25 +0000254 vadEnabled? "ON":"OFF", vadEnabled? "OFF":"ON");
tina.legrand@webrtc.org2e096922011-08-18 06:20:30 +0000255 }
phoglund@webrtc.orgd1a860b2012-01-26 14:49:28 +0000256 if(vadModeSet != vadMode)
niklase@google.com470e71d2011-07-07 08:21:25 +0000257 {
phoglund@webrtc.orgd1a860b2012-01-26 14:49:28 +0000258 printf("VAD mode: %d not the same as requested: %d\n",
niklase@google.com470e71d2011-07-07 08:21:25 +0000259 (WebRtc_Word16)vadModeSet, (WebRtc_Word16)vadMode);
260 }
261 }
262
263 // Requested VAD/DTX settings
264 _setStruct.statusDTX = statusDTX;
265 _setStruct.statusVAD = statusVAD;
266 _setStruct.vadMode = (ACMVADMode) vadMode;
267
268 // VAD settings after setting VAD in ACM
269 _getStruct.statusDTX = dtxEnabled;
270 _getStruct.statusVAD = vadEnabled;
271 _getStruct.vadMode = vadModeSet;
272
273}
274
275VADDTXstruct TestVADDTX::GetVAD()
276{
277 VADDTXstruct retStruct;
niklase@google.com470e71d2011-07-07 08:21:25 +0000278 bool dtxEnabled, vadEnabled;
279 ACMVADMode vadModeSet;
280
phoglund@webrtc.orgd1a860b2012-01-26 14:49:28 +0000281 if (_acmA->VAD(dtxEnabled, vadEnabled, vadModeSet) < 0) {
282 assert(false);
283 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000284
285 retStruct.statusDTX = dtxEnabled;
286 retStruct.statusVAD = vadEnabled;
287 retStruct.vadMode = vadModeSet;
288 return retStruct;
289}
290
phoglund@webrtc.orgd1a860b2012-01-26 14:49:28 +0000291WebRtc_Word16 TestVADDTX::RegisterSendCodec(char side,
292 char* codecName,
niklase@google.com470e71d2011-07-07 08:21:25 +0000293 WebRtc_Word32 samplingFreqHz,
294 WebRtc_Word32 rateKbps)
295{
296 if(_testMode != 0)
297 {
298 printf("Registering %s for side %c\n", codecName, side);
299 }
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000300 std::cout << std::flush;
niklase@google.com470e71d2011-07-07 08:21:25 +0000301 AudioCodingModule* myACM;
302 switch(side)
303 {
304 case 'A':
305 {
306 myACM = _acmA;
307 break;
308 }
309 case 'B':
310 {
311 myACM = _acmB;
312 break;
313 }
314 default:
315 return -1;
316 }
317
318 if(myACM == NULL)
319 {
320 return -1;
321 }
phoglund@webrtc.orgd1a860b2012-01-26 14:49:28 +0000322
niklase@google.com470e71d2011-07-07 08:21:25 +0000323 CodecInst myCodecParam;
phoglund@webrtc.orgd1a860b2012-01-26 14:49:28 +0000324 for(WebRtc_Word16 codecCntr = 0; codecCntr < myACM->NumberOfCodecs();
niklase@google.com470e71d2011-07-07 08:21:25 +0000325 codecCntr++)
326 {
327 CHECK_ERROR(myACM->Codec((WebRtc_UWord8)codecCntr, myCodecParam));
328 if(!STR_CASE_CMP(myCodecParam.plname, codecName))
329 {
330 if((samplingFreqHz == -1) || (myCodecParam.plfreq == samplingFreqHz))
331 {
332 if((rateKbps == -1) || (myCodecParam.rate == rateKbps))
333 {
334 break;
335 }
336 }
337 }
338 }
339
340 CHECK_ERROR(myACM->RegisterSendCodec(myCodecParam));
341
342 // initialization was succesful
343 return 0;
344}
345
346void TestVADDTX::Run()
347{
348 AudioFrame audioFrame;
349
350 WebRtc_UWord16 SamplesIn10MsecA = _inFileA.PayloadLength10Ms();
351 WebRtc_UWord32 timestampA = 1;
352 WebRtc_Word32 outFreqHzB = _outFileB.SamplingFrequency();
353
354 while(!_inFileA.EndOfFile())
355 {
356 _inFileA.Read10MsData(audioFrame);
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000357 audioFrame.timestamp_ = timestampA;
niklase@google.com470e71d2011-07-07 08:21:25 +0000358 timestampA += SamplesIn10MsecA;
359 CHECK_ERROR(_acmA->Add10MsData(audioFrame));
360
361 CHECK_ERROR(_acmA->Process());
362
363 CHECK_ERROR(_acmB->PlayoutData10Ms(outFreqHzB, audioFrame));
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000364 _outFileB.Write10MsData(audioFrame.data_, audioFrame.samples_per_channel_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000365 }
366#ifdef PRINT_STAT
367 _monitor.PrintStatistics(_testMode);
368#endif
369 _inFileA.Rewind();
370 _monitor.GetStatistics(_statCounter);
371 _monitor.ResetStatistics();
372}
373
tina.legrand@webrtc.orgba468042012-08-17 10:38:28 +0000374void TestVADDTX::OpenOutFile(WebRtc_Word16 test_number) {
375 std::string file_name;
376 std::stringstream file_stream;
377 file_stream << webrtc::test::OutputPath();
378 if (_testMode == 0) {
379 file_stream << "testVADDTX_autoFile_";
380 } else {
381 file_stream << "testVADDTX_outFile_";
382 }
383 file_stream << test_number << ".pcm";
384 file_name = file_stream.str();
385 _outFileB.Open(file_name, 16000, "wb");
niklase@google.com470e71d2011-07-07 08:21:25 +0000386}
387
388
389WebRtc_Word16 TestVADDTX::VerifyTest()
390{
391 // Verify empty frame result
392 WebRtc_UWord8 statusEF = 0;
393 WebRtc_UWord8 vadPattern = 0;
394 WebRtc_UWord8 emptyFramePattern[6];
395 CodecInst myCodecParam;
396 _acmA->SendCodec(myCodecParam);
397 bool dtxInUse = true;
398 bool isReplaced = false;
399 if ((STR_CASE_CMP(myCodecParam.plname,"G729") == 0) ||
400 (STR_CASE_CMP(myCodecParam.plname,"G723") == 0) ||
401 (STR_CASE_CMP(myCodecParam.plname,"AMR") == 0) ||
402 (STR_CASE_CMP(myCodecParam.plname,"AMR-wb") == 0) ||
phoglund@webrtc.orgd1a860b2012-01-26 14:49:28 +0000403 (STR_CASE_CMP(myCodecParam.plname,"speex") == 0))
niklase@google.com470e71d2011-07-07 08:21:25 +0000404 {
405 _acmA->IsInternalDTXReplacedWithWebRtc(isReplaced);
406 if (!isReplaced)
407 {
408 dtxInUse = false;
409 }
410 }
phoglund@webrtc.orgd1a860b2012-01-26 14:49:28 +0000411
niklase@google.com470e71d2011-07-07 08:21:25 +0000412 // Check for error in VAD/DTX settings
413 if (_getStruct.statusDTX != _setStruct.statusDTX){
414 // DTX status doesn't match expected
415 vadPattern |= 4;
416 }
417 if (_getStruct.statusDTX){
418 if ((!_getStruct.statusVAD && dtxInUse) || (!dtxInUse && (_getStruct.statusVAD !=_setStruct.statusVAD)))
phoglund@webrtc.orgd1a860b2012-01-26 14:49:28 +0000419 {
niklase@google.com470e71d2011-07-07 08:21:25 +0000420 // Missmatch in VAD setting
421 vadPattern |= 2;
422 }
423 } else {
424 if (_getStruct.statusVAD != _setStruct.statusVAD){
phoglund@webrtc.orgd1a860b2012-01-26 14:49:28 +0000425 // VAD status doesn't match expected
niklase@google.com470e71d2011-07-07 08:21:25 +0000426 vadPattern |= 2;
427 }
428 }
429 if (_getStruct.vadMode != _setStruct.vadMode){
430 // VAD Mode doesn't match expected
431 vadPattern |= 1;
432 }
433
434 // Set expected empty frame pattern
435 int ii;
436 for (ii = 0; ii < 6; ii++) {
437 emptyFramePattern[ii] = 0;
438 }
439 emptyFramePattern[0] = 1; // "kNoEncoding", not important to check. Codecs with packetsize != 80 samples will get this output.
440 emptyFramePattern[1] = 1; // Expect to always receive some frames labeled "kActiveNormalEncoded"
441 emptyFramePattern[2] = (((!_getStruct.statusDTX && _getStruct.statusVAD) || (!dtxInUse && _getStruct.statusDTX))); // "kPassiveNormalEncoded"
442 emptyFramePattern[3] = ((_getStruct.statusDTX && dtxInUse && (_acmA->SendFrequency() == 8000))); // "kPassiveDTXNB"
443 emptyFramePattern[4] = ((_getStruct.statusDTX && dtxInUse && (_acmA->SendFrequency() == 16000))); // "kPassiveDTXWB"
444 emptyFramePattern[5] = ((_getStruct.statusDTX && dtxInUse && (_acmA->SendFrequency() == 32000))); // "kPassiveDTXSWB"
445
446 // Check pattern 1-5 (skip 0)
447 for (int ii = 1; ii < 6; ii++)
448 {
449 if (emptyFramePattern[ii])
450 {
451 statusEF |= (_statCounter[ii] == 0);
452 }
453 else
454 {
455 statusEF |= (_statCounter[ii] > 0);
456 }
457 }
458 if ((statusEF == 0) && (vadPattern == 0))
459 {
460 if(_testMode != 0)
461 {
462 printf(" Test OK!\n");
463 }
464 return 0;
465 }
466 else
467 {
468 if (statusEF)
469 {
470 printf("\t\t\tUnexpected empty frame result!\n");
471 }
472 if (vadPattern)
473 {
474 printf("\t\t\tUnexpected SetVAD() result!\tDTX: %d\tVAD: %d\tMode: %d\n", (vadPattern >> 2) & 1, (vadPattern >> 1) & 1, vadPattern & 1);
475 }
476 return 1;
477 }
478}
479
480ActivityMonitor::ActivityMonitor()
481{
482 _counter[0] = _counter[1] = _counter[2] = _counter[3] = _counter[4] = _counter[5] = 0;
483}
484
485ActivityMonitor::~ActivityMonitor()
486{
487}
488
489WebRtc_Word32 ActivityMonitor::InFrameType(WebRtc_Word16 frameType)
490{
491 _counter[frameType]++;
492 return 0;
493}
494
495void ActivityMonitor::PrintStatistics(int testMode)
496{
497 if(testMode != 0)
498 {
499 printf("\n");
500 printf("kActiveNormalEncoded kPassiveNormalEncoded kPassiveDTXWB kPassiveDTXNB kPassiveDTXSWB kFrameEmpty\n");
501
502 printf("%19u", _counter[1]);
503 printf("%22u", _counter[2]);
504 printf("%14u", _counter[3]);
505 printf("%14u", _counter[4]);
506 printf("%14u", _counter[5]);
507 printf("%11u", _counter[0]);
508
509 printf("\n\n");
510 }
511}
512
513void ActivityMonitor::ResetStatistics()
514{
515 _counter[0] = _counter[1] = _counter[2] = _counter[3] = _counter[4] = _counter[5] = 0;
516}
517
518void ActivityMonitor::GetStatistics(WebRtc_UWord32* getCounter)
519{
520 for (int ii = 0; ii < 6; ii++)
521 {
522 getCounter[ii] = _counter[ii];
523 }
524}
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000525
526} // namespace webrtc