Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / webrtc / modules / audio_coding / main / test / EncodeDecodeTest.cc
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/EncodeDecodeTest.h"
12
13 #include <sstream>
14 #include <stdio.h>
15 #include <stdlib.h>
16
17 #include "testing/gtest/include/gtest/gtest.h"
18 #include "webrtc/common_types.h"
19 #include "webrtc/modules/audio_coding/main/interface/audio_coding_module.h"
20 #include "webrtc/modules/audio_coding/main/acm2/acm_common_defs.h"
21 #include "webrtc/modules/audio_coding/main/test/utility.h"
22 #include "webrtc/system_wrappers/interface/scoped_ptr.h"
23 #include "webrtc/system_wrappers/interface/trace.h"
24 #include "webrtc/test/testsupport/fileutils.h"
25
26 namespace webrtc {
27
28 TestPacketization::TestPacketization(RTPStream *rtpStream, uint16_t frequency)
29     : _rtpStream(rtpStream),
30       _frequency(frequency),
31       _seqNo(0) {
32 }
33
34 TestPacketization::~TestPacketization() {
35 }
36
37 int32_t TestPacketization::SendData(
38     const FrameType /* frameType */, const uint8_t payloadType,
39     const uint32_t timeStamp, const uint8_t* payloadData,
40     const uint16_t payloadSize,
41     const RTPFragmentationHeader* /* fragmentation */) {
42   _rtpStream->Write(payloadType, timeStamp, _seqNo++, payloadData, payloadSize,
43                     _frequency);
44   return 1;
45 }
46
47 Sender::Sender()
48     : _acm(NULL),
49       _pcmFile(),
50       _audioFrame(),
51       _packetization(NULL) {
52 }
53
54 void Sender::Setup(AudioCodingModule *acm, RTPStream *rtpStream,
55                    std::string in_file_name, int sample_rate, int channels) {
56   acm->InitializeSender();
57   struct CodecInst sendCodec;
58   int noOfCodecs = acm->NumberOfCodecs();
59   int codecNo;
60
61   // Open input file
62   const std::string file_name = webrtc::test::ResourcePath(in_file_name, "pcm");
63   _pcmFile.Open(file_name, sample_rate, "rb");
64   if (channels == 2) {
65     _pcmFile.ReadStereo(true);
66   }
67
68   // Set the codec for the current test.
69   if ((testMode == 0) || (testMode == 1)) {
70     // Set the codec id.
71     codecNo = codeId;
72   } else {
73     // Choose codec on command line.
74     printf("List of supported codec.\n");
75     for (int n = 0; n < noOfCodecs; n++) {
76       EXPECT_EQ(0, acm->Codec(n, &sendCodec));
77       printf("%d %s\n", n, sendCodec.plname);
78     }
79     printf("Choose your codec:");
80     ASSERT_GT(scanf("%d", &codecNo), 0);
81   }
82
83   EXPECT_EQ(0, acm->Codec(codecNo, &sendCodec));
84
85   sendCodec.channels = channels;
86
87   EXPECT_EQ(0, acm->RegisterSendCodec(sendCodec));
88   _packetization = new TestPacketization(rtpStream, sendCodec.plfreq);
89   EXPECT_EQ(0, acm->RegisterTransportCallback(_packetization));
90
91   _acm = acm;
92 }
93
94 void Sender::Teardown() {
95   _pcmFile.Close();
96   delete _packetization;
97 }
98
99 bool Sender::Add10MsData() {
100   if (!_pcmFile.EndOfFile()) {
101     EXPECT_GT(_pcmFile.Read10MsData(_audioFrame), 0);
102     int32_t ok = _acm->Add10MsData(_audioFrame);
103     EXPECT_EQ(0, ok);
104     if (ok != 0) {
105       return false;
106     }
107     return true;
108   }
109   return false;
110 }
111
112 void Sender::Run() {
113   while (true) {
114     if (!Add10MsData()) {
115       break;
116     }
117     EXPECT_GT(_acm->Process(), -1);
118   }
119 }
120
121 Receiver::Receiver()
122     : _playoutLengthSmpls(WEBRTC_10MS_PCM_AUDIO),
123       _payloadSizeBytes(MAX_INCOMING_PAYLOAD) {
124 }
125
126 void Receiver::Setup(AudioCodingModule *acm, RTPStream *rtpStream,
127                      std::string out_file_name, int channels) {
128   struct CodecInst recvCodec = CodecInst();
129   int noOfCodecs;
130   EXPECT_EQ(0, acm->InitializeReceiver());
131
132   noOfCodecs = acm->NumberOfCodecs();
133   for (int i = 0; i < noOfCodecs; i++) {
134     EXPECT_EQ(0, acm->Codec(i, &recvCodec));
135     if (recvCodec.channels == channels)
136       EXPECT_EQ(0, acm->RegisterReceiveCodec(recvCodec));
137     // Forces mono/stereo for Opus.
138     if (!strcmp(recvCodec.plname, "opus")) {
139       recvCodec.channels = channels;
140       EXPECT_EQ(0, acm->RegisterReceiveCodec(recvCodec));
141     }
142   }
143
144   int playSampFreq;
145   std::string file_name;
146   std::stringstream file_stream;
147   file_stream << webrtc::test::OutputPath() << out_file_name
148       << static_cast<int>(codeId) << ".pcm";
149   file_name = file_stream.str();
150   _rtpStream = rtpStream;
151
152   if (testMode == 1) {
153     playSampFreq = recvCodec.plfreq;
154     _pcmFile.Open(file_name, recvCodec.plfreq, "wb+");
155   } else if (testMode == 0) {
156     playSampFreq = 32000;
157     _pcmFile.Open(file_name, 32000, "wb+");
158   } else {
159     printf("\nValid output frequencies:\n");
160     printf("8000\n16000\n32000\n-1,");
161     printf("which means output frequency equal to received signal frequency");
162     printf("\n\nChoose output sampling frequency: ");
163     ASSERT_GT(scanf("%d", &playSampFreq), 0);
164     file_name = webrtc::test::OutputPath() + out_file_name + ".pcm";
165     _pcmFile.Open(file_name, playSampFreq, "wb+");
166   }
167
168   _realPayloadSizeBytes = 0;
169   _playoutBuffer = new int16_t[WEBRTC_10MS_PCM_AUDIO];
170   _frequency = playSampFreq;
171   _acm = acm;
172   _firstTime = true;
173 }
174
175 void Receiver::Teardown() {
176   delete[] _playoutBuffer;
177   _pcmFile.Close();
178   if (testMode > 1) {
179     Trace::ReturnTrace();
180   }
181 }
182
183 bool Receiver::IncomingPacket() {
184   if (!_rtpStream->EndOfFile()) {
185     if (_firstTime) {
186       _firstTime = false;
187       _realPayloadSizeBytes = _rtpStream->Read(&_rtpInfo, _incomingPayload,
188                                                _payloadSizeBytes, &_nextTime);
189       if (_realPayloadSizeBytes == 0) {
190         if (_rtpStream->EndOfFile()) {
191           _firstTime = true;
192           return true;
193         } else {
194           return false;
195         }
196       }
197     }
198
199     EXPECT_EQ(0, _acm->IncomingPacket(_incomingPayload, _realPayloadSizeBytes,
200                                       _rtpInfo));
201     _realPayloadSizeBytes = _rtpStream->Read(&_rtpInfo, _incomingPayload,
202                                              _payloadSizeBytes, &_nextTime);
203     if (_realPayloadSizeBytes == 0 && _rtpStream->EndOfFile()) {
204       _firstTime = true;
205     }
206   }
207   return true;
208 }
209
210 bool Receiver::PlayoutData() {
211   AudioFrame audioFrame;
212
213   int32_t ok =_acm->PlayoutData10Ms(_frequency, &audioFrame);
214   EXPECT_EQ(0, ok);
215   if (ok < 0){
216     return false;
217   }
218   if (_playoutLengthSmpls == 0) {
219     return false;
220   }
221   _pcmFile.Write10MsData(audioFrame.data_,
222       audioFrame.samples_per_channel_ * audioFrame.num_channels_);
223   return true;
224 }
225
226 void Receiver::Run() {
227   uint8_t counter500Ms = 50;
228   uint32_t clock = 0;
229
230   while (counter500Ms > 0) {
231     if (clock == 0 || clock >= _nextTime) {
232       EXPECT_TRUE(IncomingPacket());
233       if (clock == 0) {
234         clock = _nextTime;
235       }
236     }
237     if ((clock % 10) == 0) {
238       if (!PlayoutData()) {
239         clock++;
240         continue;
241       }
242     }
243     if (_rtpStream->EndOfFile()) {
244       counter500Ms--;
245     }
246     clock++;
247   }
248 }
249
250 EncodeDecodeTest::EncodeDecodeTest() {
251   _testMode = 2;
252   Trace::CreateTrace();
253   Trace::SetTraceFile(
254       (webrtc::test::OutputPath() + "acm_encdec_trace.txt").c_str());
255 }
256
257 EncodeDecodeTest::EncodeDecodeTest(int testMode) {
258   //testMode == 0 for autotest
259   //testMode == 1 for testing all codecs/parameters
260   //testMode > 1 for specific user-input test (as it was used before)
261   _testMode = testMode;
262   if (_testMode != 0) {
263     Trace::CreateTrace();
264     Trace::SetTraceFile(
265         (webrtc::test::OutputPath() + "acm_encdec_trace.txt").c_str());
266   }
267 }
268
269 void EncodeDecodeTest::Perform() {
270   int numCodecs = 1;
271   int codePars[3];  // Frequency, packet size, rate.
272   int numPars[52];  // Number of codec parameters sets (freq, pacsize, rate)
273                     // to test, for a given codec.
274
275   codePars[0] = 0;
276   codePars[1] = 0;
277   codePars[2] = 0;
278
279   scoped_ptr<AudioCodingModule> acm(AudioCodingModule::Create(0));
280   struct CodecInst sendCodecTmp;
281   numCodecs = acm->NumberOfCodecs();
282
283   if (_testMode != 2) {
284     for (int n = 0; n < numCodecs; n++) {
285       EXPECT_EQ(0, acm->Codec(n, &sendCodecTmp));
286       if (STR_CASE_CMP(sendCodecTmp.plname, "telephone-event") == 0) {
287         numPars[n] = 0;
288       } else if (STR_CASE_CMP(sendCodecTmp.plname, "cn") == 0) {
289         numPars[n] = 0;
290       } else if (STR_CASE_CMP(sendCodecTmp.plname, "red") == 0) {
291         numPars[n] = 0;
292       } else if (sendCodecTmp.channels == 2) {
293         numPars[n] = 0;
294       } else {
295         numPars[n] = 1;
296       }
297     }
298   } else {
299     numCodecs = 1;
300     numPars[0] = 1;
301   }
302
303   _receiver.testMode = _testMode;
304
305   // Loop over all mono codecs:
306   for (int codeId = 0; codeId < numCodecs; codeId++) {
307     // Only encode using real mono encoders, not telephone-event and cng.
308     for (int loopPars = 1; loopPars <= numPars[codeId]; loopPars++) {
309       // Encode all data to file.
310       EncodeToFile(1, codeId, codePars, _testMode);
311
312       RTPFile rtpFile;
313       std::string fileName = webrtc::test::OutputPath() + "outFile.rtp";
314       rtpFile.Open(fileName.c_str(), "rb");
315
316       _receiver.codeId = codeId;
317
318       rtpFile.ReadHeader();
319       _receiver.Setup(acm.get(), &rtpFile, "encodeDecode_out", 1);
320       _receiver.Run();
321       _receiver.Teardown();
322       rtpFile.Close();
323     }
324   }
325
326   // End tracing.
327   if (_testMode == 1) {
328     Trace::ReturnTrace();
329   }
330 }
331
332 void EncodeDecodeTest::EncodeToFile(int fileType, int codeId, int* codePars,
333                                     int testMode) {
334   scoped_ptr<AudioCodingModule> acm(AudioCodingModule::Create(1));
335   RTPFile rtpFile;
336   std::string fileName = webrtc::test::OutputPath() + "outFile.rtp";
337   rtpFile.Open(fileName.c_str(), "wb+");
338   rtpFile.WriteHeader();
339
340   // Store for auto_test and logging.
341   _sender.testMode = testMode;
342   _sender.codeId = codeId;
343
344   _sender.Setup(acm.get(), &rtpFile, "audio_coding/testfile32kHz", 32000, 1);
345   struct CodecInst sendCodecInst;
346   if (acm->SendCodec(&sendCodecInst) >= 0) {
347     _sender.Run();
348   }
349   _sender.Teardown();
350   rtpFile.Close();
351 }
352
353 }  // namespace webrtc