blob: 949507d3c465b94b4dfa5b80973a88612ecfce25 [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
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000030TestPacketization::TestPacketization(RTPStream *rtpStream, uint16_t frequency)
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +000031 : _rtpStream(rtpStream),
32 _frequency(frequency),
33 _seqNo(0) {
niklase@google.com470e71d2011-07-07 08:21:25 +000034}
35
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000036TestPacketization::~TestPacketization() {
37}
niklase@google.com470e71d2011-07-07 08:21:25 +000038
pbos@webrtc.org0946a562013-04-09 00:28:06 +000039int32_t TestPacketization::SendData(
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000040 const FrameType /* frameType */, const uint8_t payloadType,
41 const uint32_t timeStamp, const uint8_t* payloadData,
pbos@webrtc.org0946a562013-04-09 00:28:06 +000042 const uint16_t payloadSize,
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +000043 const RTPFragmentationHeader* /* fragmentation */) {
44 _rtpStream->Write(payloadType, timeStamp, _seqNo++, payloadData, payloadSize,
45 _frequency);
46 return 1;
47}
niklase@google.com470e71d2011-07-07 08:21:25 +000048
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +000049Sender::Sender()
50 : _acm(NULL),
51 _pcmFile(),
52 _audioFrame(),
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +000053 _packetization(NULL) {
54}
55
56void Sender::Setup(AudioCodingModule *acm, RTPStream *rtpStream) {
57 acm->InitializeSender();
58 struct CodecInst sendCodec;
59 int noOfCodecs = acm->NumberOfCodecs();
60 int codecNo;
61
tina.legrand@webrtc.orgba468042012-08-17 10:38:28 +000062 // Open input file
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000063 const std::string file_name = webrtc::test::ResourcePath(
64 "audio_coding/testfile32kHz", "pcm");
tina.legrand@webrtc.orgba468042012-08-17 10:38:28 +000065 _pcmFile.Open(file_name, 32000, "rb");
66
67 // Set the codec for the current test.
68 if ((testMode == 0) || (testMode == 1)) {
69 // Set the codec id.
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +000070 codecNo = codeId;
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +000071 } else {
tina.legrand@webrtc.orgba468042012-08-17 10:38:28 +000072 // Choose codec on command line.
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +000073 printf("List of supported codec.\n");
74 for (int n = 0; n < noOfCodecs; n++) {
tina.legrand@webrtc.org7a7a0082013-02-21 10:27:48 +000075 acm->Codec(n, &sendCodec);
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +000076 printf("%d %s\n", n, sendCodec.plname);
niklase@google.com470e71d2011-07-07 08:21:25 +000077 }
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +000078 printf("Choose your codec:");
79 ASSERT_GT(scanf("%d", &codecNo), 0);
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +000080 }
81
tina.legrand@webrtc.org7a7a0082013-02-21 10:27:48 +000082 acm->Codec(codecNo, &sendCodec);
tina.legrand@webrtc.orgae1c4542012-03-12 08:41:30 +000083 if (!strcmp(sendCodec.plname, "CELT")) {
84 sendCodec.channels = 1;
85 }
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +000086 acm->RegisterSendCodec(sendCodec);
87 _packetization = new TestPacketization(rtpStream, sendCodec.plfreq);
88 if (acm->RegisterTransportCallback(_packetization) < 0) {
89 printf("Registering Transport Callback failed, for run: codecId: %d: --\n",
90 codeId);
91 }
92
tina.legrand@webrtc.orgba468042012-08-17 10:38:28 +000093 _acm = acm;
94}
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +000095
96void Sender::Teardown() {
97 _pcmFile.Close();
98 delete _packetization;
niklase@google.com470e71d2011-07-07 08:21:25 +000099}
100
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000101bool Sender::Add10MsData() {
102 if (!_pcmFile.EndOfFile()) {
103 _pcmFile.Read10MsData(_audioFrame);
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000104 int32_t ok = _acm->Add10MsData(_audioFrame);
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000105 if (ok != 0) {
106 printf("Error calling Add10MsData: for run: codecId: %d\n", codeId);
107 exit(1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000108 }
109 return true;
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000110 }
111 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000112}
113
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000114bool Sender::Process() {
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000115 int32_t ok = _acm->Process();
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000116 if (ok < 0) {
117 printf("Error calling Add10MsData: for run: codecId: %d\n", codeId);
118 exit(1);
119 }
120 return true;
121}
niklase@google.com470e71d2011-07-07 08:21:25 +0000122
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000123void Sender::Run() {
124 while (true) {
125 if (!Add10MsData()) {
126 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000127 }
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000128 if (!Process()) { // This could be done in a processing thread
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000129 break;
130 }
131 }
132}
133
134Receiver::Receiver()
135 : _playoutLengthSmpls(WEBRTC_10MS_PCM_AUDIO),
136 _payloadSizeBytes(MAX_INCOMING_PAYLOAD) {
137}
138
139void Receiver::Setup(AudioCodingModule *acm, RTPStream *rtpStream) {
140 struct CodecInst recvCodec;
141 int noOfCodecs;
142 acm->InitializeReceiver();
143
144 noOfCodecs = acm->NumberOfCodecs();
145 for (int i = 0; i < noOfCodecs; i++) {
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000146 acm->Codec((uint8_t) i, &recvCodec);
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000147 if (acm->RegisterReceiveCodec(recvCodec) != 0) {
148 printf("Unable to register codec: for run: codecId: %d\n", codeId);
149 exit(1);
150 }
151 }
phoglund@webrtc.orgd1a860b2012-01-26 14:49:28 +0000152
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000153 int playSampFreq;
tina.legrand@webrtc.orgba468042012-08-17 10:38:28 +0000154 std::string file_name;
155 std::stringstream file_stream;
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000156 file_stream << webrtc::test::OutputPath() << "encodeDecode_out"
157 << static_cast<int>(codeId) << ".pcm";
tina.legrand@webrtc.orgba468042012-08-17 10:38:28 +0000158 file_name = file_stream.str();
159 _rtpStream = rtpStream;
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000160
161 if (testMode == 1) {
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000162 playSampFreq = recvCodec.plfreq;
tina.legrand@webrtc.orgba468042012-08-17 10:38:28 +0000163 _pcmFile.Open(file_name, recvCodec.plfreq, "wb+");
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000164 } else if (testMode == 0) {
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000165 playSampFreq = 32000;
tina.legrand@webrtc.orgba468042012-08-17 10:38:28 +0000166 _pcmFile.Open(file_name, 32000, "wb+");
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000167 } else {
168 printf("\nValid output frequencies:\n");
169 printf("8000\n16000\n32000\n-1,");
tina.legrand@webrtc.orgba468042012-08-17 10:38:28 +0000170 printf("which means output frequency equal to received signal frequency");
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000171 printf("\n\nChoose output sampling frequency: ");
172 ASSERT_GT(scanf("%d", &playSampFreq), 0);
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000173 file_name = webrtc::test::OutputPath() + "encodeDecode_out.pcm";
tina.legrand@webrtc.orgba468042012-08-17 10:38:28 +0000174 _pcmFile.Open(file_name, playSampFreq, "wb+");
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000175 }
phoglund@webrtc.orgd1a860b2012-01-26 14:49:28 +0000176
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000177 _realPayloadSizeBytes = 0;
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000178 _playoutBuffer = new int16_t[WEBRTC_10MS_PCM_AUDIO];
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000179 _frequency = playSampFreq;
180 _acm = acm;
181 _firstTime = true;
182}
183
184void Receiver::Teardown() {
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000185 delete[] _playoutBuffer;
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000186 _pcmFile.Close();
187 if (testMode > 1)
188 Trace::ReturnTrace();
189}
190
191bool Receiver::IncomingPacket() {
192 if (!_rtpStream->EndOfFile()) {
193 if (_firstTime) {
194 _firstTime = false;
195 _realPayloadSizeBytes = _rtpStream->Read(&_rtpInfo, _incomingPayload,
196 _payloadSizeBytes, &_nextTime);
andrew@webrtc.org975e4a32012-01-17 19:27:33 +0000197 if (_realPayloadSizeBytes == 0) {
198 if (_rtpStream->EndOfFile()) {
199 _firstTime = true;
200 return true;
201 } else {
202 printf("Error in reading incoming payload.\n");
203 return false;
204 }
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000205 }
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000206 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000207
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000208 int32_t ok = _acm->IncomingPacket(_incomingPayload, _realPayloadSizeBytes,
209 _rtpInfo);
210 if (ok != 0) {
211 printf("Error when inserting packet to ACM, for run: codecId: %d\n",
212 codeId);
213 }
214 _realPayloadSizeBytes = _rtpStream->Read(&_rtpInfo, _incomingPayload,
215 _payloadSizeBytes, &_nextTime);
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000216 if (_realPayloadSizeBytes == 0 && _rtpStream->EndOfFile()) {
217 _firstTime = true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000218 }
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000219 }
220 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000221}
222
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000223bool Receiver::PlayoutData() {
224 AudioFrame audioFrame;
225
tina.legrand@webrtc.org7a7a0082013-02-21 10:27:48 +0000226 if (_acm->PlayoutData10Ms(_frequency, &audioFrame) != 0) {
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000227 printf("Error when calling PlayoutData10Ms, for run: codecId: %d\n",
228 codeId);
229 exit(1);
230 }
231 if (_playoutLengthSmpls == 0) {
232 return false;
233 }
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000234 _pcmFile.Write10MsData(audioFrame.data_, audioFrame.samples_per_channel_);
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000235 return true;
236}
237
238void Receiver::Run() {
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000239 uint8_t counter500Ms = 50;
240 uint32_t clock = 0;
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000241
242 while (counter500Ms > 0) {
243 if (clock == 0 || clock >= _nextTime) {
244 IncomingPacket();
245 if (clock == 0) {
246 clock = _nextTime;
247 }
248 }
249 if ((clock % 10) == 0) {
250 if (!PlayoutData()) {
251 clock++;
252 continue;
253 }
254 }
255 if (_rtpStream->EndOfFile()) {
256 counter500Ms--;
257 }
258 clock++;
259 }
260}
261
262EncodeDecodeTest::EncodeDecodeTest() {
263 _testMode = 2;
264 Trace::CreateTrace();
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000265 Trace::SetTraceFile(
266 (webrtc::test::OutputPath() + "acm_encdec_trace.txt").c_str());
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000267}
268
269EncodeDecodeTest::EncodeDecodeTest(int testMode) {
270 //testMode == 0 for autotest
271 //testMode == 1 for testing all codecs/parameters
272 //testMode > 1 for specific user-input test (as it was used before)
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000273 _testMode = testMode;
274 if (_testMode != 0) {
275 Trace::CreateTrace();
276 Trace::SetTraceFile(
277 (webrtc::test::OutputPath() + "acm_encdec_trace.txt").c_str());
278 }
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000279}
280
281void EncodeDecodeTest::Perform() {
282 if (_testMode == 0) {
283 printf("Running Encode/Decode Test");
284 WEBRTC_TRACE(webrtc::kTraceStateInfo, webrtc::kTraceAudioCoding, -1,
285 "---------- EncodeDecodeTest ----------");
286 }
287
288 int numCodecs = 1;
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000289 int codePars[3]; // Frequency, packet size, rate.
290 int numPars[52]; // Number of codec parameters sets (freq, pacsize, rate)
291 // to test, for a given codec.
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000292
293 codePars[0] = 0;
294 codePars[1] = 0;
295 codePars[2] = 0;
296
tina.legrand@webrtc.org5b4f36d2012-06-01 14:51:28 +0000297 AudioCodingModule* acm = AudioCodingModule::Create(0);
tina.legrand@webrtc.org45175852012-06-01 09:27:35 +0000298 struct CodecInst sendCodecTmp;
tina.legrand@webrtc.org5b4f36d2012-06-01 14:51:28 +0000299 numCodecs = acm->NumberOfCodecs();
tina.legrand@webrtc.org45175852012-06-01 09:27:35 +0000300
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000301 if (_testMode == 1) {
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000302 printf("List of supported codec.\n");
tina.legrand@webrtc.org45175852012-06-01 09:27:35 +0000303 }
304 if (_testMode != 2) {
305 for (int n = 0; n < numCodecs; n++) {
tina.legrand@webrtc.org7a7a0082013-02-21 10:27:48 +0000306 acm->Codec(n, &sendCodecTmp);
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000307 if (STR_CASE_CMP(sendCodecTmp.plname, "telephone-event") == 0) {
308 numPars[n] = 0;
309 } else if (STR_CASE_CMP(sendCodecTmp.plname, "cn") == 0) {
310 numPars[n] = 0;
311 } else if (STR_CASE_CMP(sendCodecTmp.plname, "red") == 0) {
312 numPars[n] = 0;
tina.legrand@webrtc.org45175852012-06-01 09:27:35 +0000313 } else if (sendCodecTmp.channels == 2) {
314 numPars[n] = 0;
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000315 } else {
316 numPars[n] = 1;
tina.legrand@webrtc.org45175852012-06-01 09:27:35 +0000317 if (_testMode == 1) {
318 printf("%d %s\n", n, sendCodecTmp.plname);
319 }
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000320 }
321 }
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000322 } else {
323 numCodecs = 1;
324 numPars[0] = 1;
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000325 }
326
327 _receiver.testMode = _testMode;
328
tina.legrand@webrtc.org45175852012-06-01 09:27:35 +0000329 // Loop over all mono codecs:
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000330 for (int codeId = 0; codeId < numCodecs; codeId++) {
tina.legrand@webrtc.org45175852012-06-01 09:27:35 +0000331 // Only encode using real mono encoders, not telephone-event and cng.
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000332 for (int loopPars = 1; loopPars <= numPars[codeId]; loopPars++) {
333 if (_testMode == 1) {
334 printf("\n");
335 printf("***FOR RUN: codeId: %d\n", codeId);
336 printf("\n");
337 } else if (_testMode == 0) {
338 printf(".");
339 }
340
341 EncodeToFile(1, codeId, codePars, _testMode);
342
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000343 RTPFile rtpFile;
kjellander@webrtc.org5490c712011-12-21 13:34:18 +0000344 std::string fileName = webrtc::test::OutputPath() + "outFile.rtp";
345 rtpFile.Open(fileName.c_str(), "rb");
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000346
347 _receiver.codeId = codeId;
348
349 rtpFile.ReadHeader();
350 _receiver.Setup(acm, &rtpFile);
351 _receiver.Run();
352 _receiver.Teardown();
353 rtpFile.Close();
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000354
355 if (_testMode == 1) {
356 printf("***COMPLETED RUN FOR: codecID: %d ***\n", codeId);
357 }
358 }
359 }
tina.legrand@webrtc.org5b4f36d2012-06-01 14:51:28 +0000360 AudioCodingModule::Destroy(acm);
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000361 if (_testMode == 0) {
362 printf("Done!\n");
363 }
364 if (_testMode == 1)
365 Trace::ReturnTrace();
366}
367
368void EncodeDecodeTest::EncodeToFile(int fileType, int codeId, int* codePars,
369 int testMode) {
tina.legrand@webrtc.org5b4f36d2012-06-01 14:51:28 +0000370 AudioCodingModule* acm = AudioCodingModule::Create(1);
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000371 RTPFile rtpFile;
kjellander@webrtc.org5490c712011-12-21 13:34:18 +0000372 std::string fileName = webrtc::test::OutputPath() + "outFile.rtp";
373 rtpFile.Open(fileName.c_str(), "wb+");
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000374 rtpFile.WriteHeader();
375
376 //for auto_test and logging
377 _sender.testMode = testMode;
378 _sender.codeId = codeId;
379
380 _sender.Setup(acm, &rtpFile);
381 struct CodecInst sendCodecInst;
tina.legrand@webrtc.org7a7a0082013-02-21 10:27:48 +0000382 if (acm->SendCodec(&sendCodecInst) >= 0) {
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000383 _sender.Run();
384 }
385 _sender.Teardown();
386 rtpFile.Close();
387 AudioCodingModule::Destroy(acm);
388}
389
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000390} // namespace webrtc