blob: c4f9a4706778c8a01caff5caa50309ff858a17a3 [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
tina.legrand@webrtc.orgae1c4542012-03-12 08:41:30 +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
tina.legrand@webrtc.org73222cf2013-03-15 13:29:17 +000011#include "webrtc/modules/audio_coding/main/test/EncodeDecodeTest.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000012
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +000013#include <stdio.h>
niklase@google.com470e71d2011-07-07 08:21:25 +000014#include <stdlib.h>
15#include <string.h>
tina.legrand@webrtc.org73222cf2013-03-15 13:29:17 +000016
17#include <sstream>
tina.legrand@webrtc.org5e7ca602012-06-12 07:16:24 +000018#include <string>
19
tina.legrand@webrtc.org73222cf2013-03-15 13:29:17 +000020#include "testing/gtest/include/gtest/gtest.h"
21#include "webrtc/common_types.h"
22#include "webrtc/modules/audio_coding/main/interface/audio_coding_module.h"
23#include "webrtc/modules/audio_coding/main/source/acm_common_defs.h"
24#include "webrtc/modules/audio_coding/main/test/utility.h"
25#include "webrtc/system_wrappers/interface/trace.h"
26#include "webrtc/test/testsupport/fileutils.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000027
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +000028namespace webrtc {
29
30TestPacketization::TestPacketization(RTPStream *rtpStream,
31 WebRtc_UWord16 frequency)
32 : _rtpStream(rtpStream),
33 _frequency(frequency),
34 _seqNo(0) {
niklase@google.com470e71d2011-07-07 08:21:25 +000035}
36
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +000037TestPacketization::~TestPacketization() { }
niklase@google.com470e71d2011-07-07 08:21:25 +000038
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +000039WebRtc_Word32 TestPacketization::SendData(
40 const FrameType /* frameType */,
41 const WebRtc_UWord8 payloadType,
42 const WebRtc_UWord32 timeStamp,
43 const WebRtc_UWord8* payloadData,
44 const WebRtc_UWord16 payloadSize,
45 const RTPFragmentationHeader* /* fragmentation */) {
46 _rtpStream->Write(payloadType, timeStamp, _seqNo++, payloadData, payloadSize,
47 _frequency);
48 return 1;
49}
niklase@google.com470e71d2011-07-07 08:21:25 +000050
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +000051Sender::Sender()
52 : _acm(NULL),
53 _pcmFile(),
54 _audioFrame(),
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +000055 _packetization(NULL) {
56}
57
58void Sender::Setup(AudioCodingModule *acm, RTPStream *rtpStream) {
59 acm->InitializeSender();
60 struct CodecInst sendCodec;
61 int noOfCodecs = acm->NumberOfCodecs();
62 int codecNo;
63
tina.legrand@webrtc.orgba468042012-08-17 10:38:28 +000064 // Open input file
65 const std::string file_name =
66 webrtc::test::ResourcePath("audio_coding/testfile32kHz", "pcm");
67 _pcmFile.Open(file_name, 32000, "rb");
68
69 // Set the codec for the current test.
70 if ((testMode == 0) || (testMode == 1)) {
71 // Set the codec id.
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +000072 codecNo = codeId;
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +000073 } else {
tina.legrand@webrtc.orgba468042012-08-17 10:38:28 +000074 // Choose codec on command line.
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +000075 printf("List of supported codec.\n");
76 for (int n = 0; n < noOfCodecs; n++) {
tina.legrand@webrtc.org7a7a0082013-02-21 10:27:48 +000077 acm->Codec(n, &sendCodec);
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +000078 printf("%d %s\n", n, sendCodec.plname);
niklase@google.com470e71d2011-07-07 08:21:25 +000079 }
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +000080 printf("Choose your codec:");
81 ASSERT_GT(scanf("%d", &codecNo), 0);
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +000082 }
83
tina.legrand@webrtc.org7a7a0082013-02-21 10:27:48 +000084 acm->Codec(codecNo, &sendCodec);
tina.legrand@webrtc.orgae1c4542012-03-12 08:41:30 +000085 if (!strcmp(sendCodec.plname, "CELT")) {
86 sendCodec.channels = 1;
87 }
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +000088 acm->RegisterSendCodec(sendCodec);
89 _packetization = new TestPacketization(rtpStream, sendCodec.plfreq);
90 if (acm->RegisterTransportCallback(_packetization) < 0) {
91 printf("Registering Transport Callback failed, for run: codecId: %d: --\n",
92 codeId);
93 }
94
tina.legrand@webrtc.orgba468042012-08-17 10:38:28 +000095 _acm = acm;
96}
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +000097
98void Sender::Teardown() {
99 _pcmFile.Close();
100 delete _packetization;
niklase@google.com470e71d2011-07-07 08:21:25 +0000101}
102
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000103bool Sender::Add10MsData() {
104 if (!_pcmFile.EndOfFile()) {
105 _pcmFile.Read10MsData(_audioFrame);
106 WebRtc_Word32 ok = _acm->Add10MsData(_audioFrame);
107 if (ok != 0) {
108 printf("Error calling Add10MsData: for run: codecId: %d\n", codeId);
109 exit(1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000110 }
111 return true;
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000112 }
113 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000114}
115
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000116bool Sender::Process() {
117 WebRtc_Word32 ok = _acm->Process();
118 if (ok < 0) {
119 printf("Error calling Add10MsData: for run: codecId: %d\n", codeId);
120 exit(1);
121 }
122 return true;
123}
niklase@google.com470e71d2011-07-07 08:21:25 +0000124
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000125void Sender::Run() {
126 while (true) {
127 if (!Add10MsData()) {
128 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000129 }
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000130 if (!Process()) { // This could be done in a processing thread
131 break;
132 }
133 }
134}
135
136Receiver::Receiver()
137 : _playoutLengthSmpls(WEBRTC_10MS_PCM_AUDIO),
138 _payloadSizeBytes(MAX_INCOMING_PAYLOAD) {
139}
140
141void Receiver::Setup(AudioCodingModule *acm, RTPStream *rtpStream) {
142 struct CodecInst recvCodec;
143 int noOfCodecs;
144 acm->InitializeReceiver();
145
146 noOfCodecs = acm->NumberOfCodecs();
147 for (int i = 0; i < noOfCodecs; i++) {
tina.legrand@webrtc.org7a7a0082013-02-21 10:27:48 +0000148 acm->Codec((WebRtc_UWord8) i, &recvCodec);
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000149 if (acm->RegisterReceiveCodec(recvCodec) != 0) {
150 printf("Unable to register codec: for run: codecId: %d\n", codeId);
151 exit(1);
152 }
153 }
phoglund@webrtc.orgd1a860b2012-01-26 14:49:28 +0000154
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000155 int playSampFreq;
tina.legrand@webrtc.orgba468042012-08-17 10:38:28 +0000156 std::string file_name;
157 std::stringstream file_stream;
158 file_stream << webrtc::test::OutputPath() << "encodeDecode_out" <<
159 static_cast<int>(codeId) << ".pcm";
160 file_name = file_stream.str();
161 _rtpStream = rtpStream;
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000162
163 if (testMode == 1) {
164 playSampFreq=recvCodec.plfreq;
tina.legrand@webrtc.orgba468042012-08-17 10:38:28 +0000165 _pcmFile.Open(file_name, recvCodec.plfreq, "wb+");
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000166 } else if (testMode == 0) {
167 playSampFreq=32000;
tina.legrand@webrtc.orgba468042012-08-17 10:38:28 +0000168 _pcmFile.Open(file_name, 32000, "wb+");
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000169 } else {
170 printf("\nValid output frequencies:\n");
171 printf("8000\n16000\n32000\n-1,");
tina.legrand@webrtc.orgba468042012-08-17 10:38:28 +0000172 printf("which means output frequency equal to received signal frequency");
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000173 printf("\n\nChoose output sampling frequency: ");
174 ASSERT_GT(scanf("%d", &playSampFreq), 0);
tina.legrand@webrtc.orgba468042012-08-17 10:38:28 +0000175 file_name = webrtc::test::OutputPath() + "encodeDecode_out.pcm";
176 _pcmFile.Open(file_name, playSampFreq, "wb+");
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000177 }
phoglund@webrtc.orgd1a860b2012-01-26 14:49:28 +0000178
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000179 _realPayloadSizeBytes = 0;
180 _playoutBuffer = new WebRtc_Word16[WEBRTC_10MS_PCM_AUDIO];
181 _frequency = playSampFreq;
182 _acm = acm;
183 _firstTime = true;
184}
185
186void Receiver::Teardown() {
187 delete [] _playoutBuffer;
188 _pcmFile.Close();
189 if (testMode > 1)
190 Trace::ReturnTrace();
191}
192
193bool Receiver::IncomingPacket() {
194 if (!_rtpStream->EndOfFile()) {
195 if (_firstTime) {
196 _firstTime = false;
197 _realPayloadSizeBytes = _rtpStream->Read(&_rtpInfo, _incomingPayload,
198 _payloadSizeBytes, &_nextTime);
andrew@webrtc.org975e4a32012-01-17 19:27:33 +0000199 if (_realPayloadSizeBytes == 0) {
200 if (_rtpStream->EndOfFile()) {
201 _firstTime = true;
202 return true;
203 } else {
204 printf("Error in reading incoming payload.\n");
205 return false;
206 }
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000207 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000208 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000209
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000210 WebRtc_Word32 ok = _acm->IncomingPacket(_incomingPayload,
211 _realPayloadSizeBytes, _rtpInfo);
212 if (ok != 0) {
213 printf("Error when inserting packet to ACM, for run: codecId: %d\n",
214 codeId);
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000215 }
216 _realPayloadSizeBytes = _rtpStream->Read(&_rtpInfo, _incomingPayload,
217 _payloadSizeBytes, &_nextTime);
218 if (_realPayloadSizeBytes == 0 && _rtpStream->EndOfFile()) {
219 _firstTime = true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000220 }
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000221 }
222 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000223}
224
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000225bool Receiver::PlayoutData() {
226 AudioFrame audioFrame;
227
tina.legrand@webrtc.org7a7a0082013-02-21 10:27:48 +0000228 if (_acm->PlayoutData10Ms(_frequency, &audioFrame) != 0) {
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000229 printf("Error when calling PlayoutData10Ms, for run: codecId: %d\n",
230 codeId);
231 exit(1);
232 }
233 if (_playoutLengthSmpls == 0) {
234 return false;
235 }
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000236 _pcmFile.Write10MsData(audioFrame.data_,
237 audioFrame.samples_per_channel_);
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000238 return true;
239}
240
241void Receiver::Run() {
242 WebRtc_UWord8 counter500Ms = 50;
243 WebRtc_UWord32 clock = 0;
244
245 while (counter500Ms > 0) {
246 if (clock == 0 || clock >= _nextTime) {
247 IncomingPacket();
248 if (clock == 0) {
249 clock = _nextTime;
250 }
251 }
252 if ((clock % 10) == 0) {
253 if (!PlayoutData()) {
254 clock++;
255 continue;
256 }
257 }
258 if (_rtpStream->EndOfFile()) {
259 counter500Ms--;
260 }
261 clock++;
262 }
263}
264
265EncodeDecodeTest::EncodeDecodeTest() {
266 _testMode = 2;
267 Trace::CreateTrace();
tina.legrand@webrtc.org5e7ca602012-06-12 07:16:24 +0000268 Trace::SetTraceFile((webrtc::test::OutputPath() +
269 "acm_encdec_trace.txt").c_str());
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000270}
271
272EncodeDecodeTest::EncodeDecodeTest(int testMode) {
273 //testMode == 0 for autotest
274 //testMode == 1 for testing all codecs/parameters
275 //testMode > 1 for specific user-input test (as it was used before)
276 _testMode = testMode;
277 if(_testMode != 0) {
278 Trace::CreateTrace();
tina.legrand@webrtc.org5e7ca602012-06-12 07:16:24 +0000279 Trace::SetTraceFile((webrtc::test::OutputPath() +
280 "acm_encdec_trace.txt").c_str());
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000281 }
282}
283
284void EncodeDecodeTest::Perform() {
285 if (_testMode == 0) {
286 printf("Running Encode/Decode Test");
287 WEBRTC_TRACE(webrtc::kTraceStateInfo, webrtc::kTraceAudioCoding, -1,
288 "---------- EncodeDecodeTest ----------");
289 }
290
291 int numCodecs = 1;
tina.legrand@webrtc.org45175852012-06-01 09:27:35 +0000292 int codePars[3]; // Frequency, packet size, rate.
293 int numPars[52]; // Number of codec parameters sets (freq, pacsize, rate)
294 // to test, for a given codec.
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000295
296 codePars[0] = 0;
297 codePars[1] = 0;
298 codePars[2] = 0;
299
tina.legrand@webrtc.org5b4f36d2012-06-01 14:51:28 +0000300 AudioCodingModule* acm = AudioCodingModule::Create(0);
tina.legrand@webrtc.org45175852012-06-01 09:27:35 +0000301 struct CodecInst sendCodecTmp;
tina.legrand@webrtc.org5b4f36d2012-06-01 14:51:28 +0000302 numCodecs = acm->NumberOfCodecs();
tina.legrand@webrtc.org45175852012-06-01 09:27:35 +0000303
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000304 if (_testMode == 1) {
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000305 printf("List of supported codec.\n");
tina.legrand@webrtc.org45175852012-06-01 09:27:35 +0000306 }
307 if (_testMode != 2) {
308 for (int n = 0; n < numCodecs; n++) {
tina.legrand@webrtc.org7a7a0082013-02-21 10:27:48 +0000309 acm->Codec(n, &sendCodecTmp);
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000310 if (STR_CASE_CMP(sendCodecTmp.plname, "telephone-event") == 0) {
311 numPars[n] = 0;
312 } else if (STR_CASE_CMP(sendCodecTmp.plname, "cn") == 0) {
313 numPars[n] = 0;
314 } else if (STR_CASE_CMP(sendCodecTmp.plname, "red") == 0) {
315 numPars[n] = 0;
tina.legrand@webrtc.org45175852012-06-01 09:27:35 +0000316 } else if (sendCodecTmp.channels == 2) {
317 numPars[n] = 0;
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000318 } else {
319 numPars[n] = 1;
tina.legrand@webrtc.org45175852012-06-01 09:27:35 +0000320 if (_testMode == 1) {
321 printf("%d %s\n", n, sendCodecTmp.plname);
322 }
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000323 }
324 }
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000325 } else {
326 numCodecs = 1;
327 numPars[0] = 1;
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000328 }
329
330 _receiver.testMode = _testMode;
331
tina.legrand@webrtc.org45175852012-06-01 09:27:35 +0000332 // Loop over all mono codecs:
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000333 for (int codeId = 0; codeId < numCodecs; codeId++) {
tina.legrand@webrtc.org45175852012-06-01 09:27:35 +0000334 // Only encode using real mono encoders, not telephone-event and cng.
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000335 for (int loopPars = 1; loopPars <= numPars[codeId]; loopPars++) {
336 if (_testMode == 1) {
337 printf("\n");
338 printf("***FOR RUN: codeId: %d\n", codeId);
339 printf("\n");
340 } else if (_testMode == 0) {
341 printf(".");
342 }
343
344 EncodeToFile(1, codeId, codePars, _testMode);
345
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000346 RTPFile rtpFile;
kjellander@webrtc.org5490c712011-12-21 13:34:18 +0000347 std::string fileName = webrtc::test::OutputPath() + "outFile.rtp";
348 rtpFile.Open(fileName.c_str(), "rb");
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000349
350 _receiver.codeId = codeId;
351
352 rtpFile.ReadHeader();
353 _receiver.Setup(acm, &rtpFile);
354 _receiver.Run();
355 _receiver.Teardown();
356 rtpFile.Close();
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000357
358 if (_testMode == 1) {
359 printf("***COMPLETED RUN FOR: codecID: %d ***\n", codeId);
360 }
361 }
362 }
tina.legrand@webrtc.org5b4f36d2012-06-01 14:51:28 +0000363 AudioCodingModule::Destroy(acm);
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000364 if (_testMode == 0) {
365 printf("Done!\n");
366 }
367 if (_testMode == 1)
368 Trace::ReturnTrace();
369}
370
371void EncodeDecodeTest::EncodeToFile(int fileType, int codeId, int* codePars,
372 int testMode) {
tina.legrand@webrtc.org5b4f36d2012-06-01 14:51:28 +0000373 AudioCodingModule* acm = AudioCodingModule::Create(1);
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000374 RTPFile rtpFile;
kjellander@webrtc.org5490c712011-12-21 13:34:18 +0000375 std::string fileName = webrtc::test::OutputPath() + "outFile.rtp";
376 rtpFile.Open(fileName.c_str(), "wb+");
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000377 rtpFile.WriteHeader();
378
379 //for auto_test and logging
380 _sender.testMode = testMode;
381 _sender.codeId = codeId;
382
383 _sender.Setup(acm, &rtpFile);
384 struct CodecInst sendCodecInst;
tina.legrand@webrtc.org7a7a0082013-02-21 10:27:48 +0000385 if (acm->SendCodec(&sendCodecInst) >= 0) {
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000386 _sender.Run();
387 }
388 _sender.Teardown();
389 rtpFile.Close();
390 AudioCodingModule::Destroy(acm);
391}
392
393} // namespace webrtc