blob: 09ff58e0de6263fe7f69a7a6b5f8dbb47279825e [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
11#include "EncodeDecodeTest.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000012
tina.legrand@webrtc.orgba468042012-08-17 10:38:28 +000013#include <sstream>
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +000014#include <stdio.h>
niklase@google.com470e71d2011-07-07 08:21:25 +000015#include <stdlib.h>
16#include <string.h>
tina.legrand@webrtc.org5e7ca602012-06-12 07:16:24 +000017#include <string>
18
19#include "gtest/gtest.h"
kjellander@webrtc.org543c3ea2011-11-23 12:20:35 +000020
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +000021#include "audio_coding_module.h"
kjellander@webrtc.org543c3ea2011-11-23 12:20:35 +000022#include "common_types.h"
kjellander@webrtc.org5490c712011-12-21 13:34:18 +000023#include "testsupport/fileutils.h"
tina.legrand@webrtc.org5e7ca602012-06-12 07:16:24 +000024#include "trace.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000025#include "utility.h"
26
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +000027namespace webrtc {
28
29TestPacketization::TestPacketization(RTPStream *rtpStream,
30 WebRtc_UWord16 frequency)
31 : _rtpStream(rtpStream),
32 _frequency(frequency),
33 _seqNo(0) {
niklase@google.com470e71d2011-07-07 08:21:25 +000034}
35
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +000036TestPacketization::~TestPacketization() { }
niklase@google.com470e71d2011-07-07 08:21:25 +000037
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +000038WebRtc_Word32 TestPacketization::SendData(
39 const FrameType /* frameType */,
40 const WebRtc_UWord8 payloadType,
41 const WebRtc_UWord32 timeStamp,
42 const WebRtc_UWord8* payloadData,
43 const WebRtc_UWord16 payloadSize,
44 const RTPFragmentationHeader* /* fragmentation */) {
45 _rtpStream->Write(payloadType, timeStamp, _seqNo++, payloadData, payloadSize,
46 _frequency);
47 return 1;
48}
niklase@google.com470e71d2011-07-07 08:21:25 +000049
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +000050Sender::Sender()
51 : _acm(NULL),
52 _pcmFile(),
53 _audioFrame(),
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +000054 _packetization(NULL) {
55}
56
57void Sender::Setup(AudioCodingModule *acm, RTPStream *rtpStream) {
58 acm->InitializeSender();
59 struct CodecInst sendCodec;
60 int noOfCodecs = acm->NumberOfCodecs();
61 int codecNo;
62
tina.legrand@webrtc.orgba468042012-08-17 10:38:28 +000063 // Open input file
64 const std::string file_name =
65 webrtc::test::ResourcePath("audio_coding/testfile32kHz", "pcm");
66 _pcmFile.Open(file_name, 32000, "rb");
67
68 // Set the codec for the current test.
69 if ((testMode == 0) || (testMode == 1)) {
70 // Set the codec id.
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +000071 codecNo = codeId;
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +000072 } else {
tina.legrand@webrtc.orgba468042012-08-17 10:38:28 +000073 // Choose codec on command line.
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +000074 printf("List of supported codec.\n");
75 for (int n = 0; n < noOfCodecs; n++) {
tina.legrand@webrtc.orgeb7ebf22013-02-20 15:57:31 +000076 acm->Codec(n, sendCodec);
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +000077 printf("%d %s\n", n, sendCodec.plname);
niklase@google.com470e71d2011-07-07 08:21:25 +000078 }
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +000079 printf("Choose your codec:");
80 ASSERT_GT(scanf("%d", &codecNo), 0);
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +000081 }
82
tina.legrand@webrtc.orgeb7ebf22013-02-20 15:57:31 +000083 acm->Codec(codecNo, sendCodec);
tina.legrand@webrtc.orgae1c4542012-03-12 08:41:30 +000084 if (!strcmp(sendCodec.plname, "CELT")) {
85 sendCodec.channels = 1;
86 }
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +000087 acm->RegisterSendCodec(sendCodec);
88 _packetization = new TestPacketization(rtpStream, sendCodec.plfreq);
89 if (acm->RegisterTransportCallback(_packetization) < 0) {
90 printf("Registering Transport Callback failed, for run: codecId: %d: --\n",
91 codeId);
92 }
93
tina.legrand@webrtc.orgba468042012-08-17 10:38:28 +000094 _acm = acm;
95}
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +000096
97void Sender::Teardown() {
98 _pcmFile.Close();
99 delete _packetization;
niklase@google.com470e71d2011-07-07 08:21:25 +0000100}
101
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000102bool Sender::Add10MsData() {
103 if (!_pcmFile.EndOfFile()) {
104 _pcmFile.Read10MsData(_audioFrame);
105 WebRtc_Word32 ok = _acm->Add10MsData(_audioFrame);
106 if (ok != 0) {
107 printf("Error calling Add10MsData: for run: codecId: %d\n", codeId);
108 exit(1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000109 }
110 return true;
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000111 }
112 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000113}
114
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000115bool Sender::Process() {
116 WebRtc_Word32 ok = _acm->Process();
117 if (ok < 0) {
118 printf("Error calling Add10MsData: for run: codecId: %d\n", codeId);
119 exit(1);
120 }
121 return true;
122}
niklase@google.com470e71d2011-07-07 08:21:25 +0000123
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000124void Sender::Run() {
125 while (true) {
126 if (!Add10MsData()) {
127 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000128 }
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000129 if (!Process()) { // This could be done in a processing thread
130 break;
131 }
132 }
133}
134
135Receiver::Receiver()
136 : _playoutLengthSmpls(WEBRTC_10MS_PCM_AUDIO),
137 _payloadSizeBytes(MAX_INCOMING_PAYLOAD) {
138}
139
140void Receiver::Setup(AudioCodingModule *acm, RTPStream *rtpStream) {
141 struct CodecInst recvCodec;
142 int noOfCodecs;
143 acm->InitializeReceiver();
144
145 noOfCodecs = acm->NumberOfCodecs();
146 for (int i = 0; i < noOfCodecs; i++) {
tina.legrand@webrtc.orgeb7ebf22013-02-20 15:57:31 +0000147 acm->Codec((WebRtc_UWord8) i, recvCodec);
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000148 if (acm->RegisterReceiveCodec(recvCodec) != 0) {
149 printf("Unable to register codec: for run: codecId: %d\n", codeId);
150 exit(1);
151 }
152 }
phoglund@webrtc.orgd1a860b2012-01-26 14:49:28 +0000153
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000154 int playSampFreq;
tina.legrand@webrtc.orgba468042012-08-17 10:38:28 +0000155 std::string file_name;
156 std::stringstream file_stream;
157 file_stream << webrtc::test::OutputPath() << "encodeDecode_out" <<
158 static_cast<int>(codeId) << ".pcm";
159 file_name = file_stream.str();
160 _rtpStream = rtpStream;
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000161
162 if (testMode == 1) {
163 playSampFreq=recvCodec.plfreq;
tina.legrand@webrtc.orgba468042012-08-17 10:38:28 +0000164 _pcmFile.Open(file_name, recvCodec.plfreq, "wb+");
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000165 } else if (testMode == 0) {
166 playSampFreq=32000;
tina.legrand@webrtc.orgba468042012-08-17 10:38:28 +0000167 _pcmFile.Open(file_name, 32000, "wb+");
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000168 } else {
169 printf("\nValid output frequencies:\n");
170 printf("8000\n16000\n32000\n-1,");
tina.legrand@webrtc.orgba468042012-08-17 10:38:28 +0000171 printf("which means output frequency equal to received signal frequency");
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000172 printf("\n\nChoose output sampling frequency: ");
173 ASSERT_GT(scanf("%d", &playSampFreq), 0);
tina.legrand@webrtc.orgba468042012-08-17 10:38:28 +0000174 file_name = webrtc::test::OutputPath() + "encodeDecode_out.pcm";
175 _pcmFile.Open(file_name, playSampFreq, "wb+");
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000176 }
phoglund@webrtc.orgd1a860b2012-01-26 14:49:28 +0000177
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000178 _realPayloadSizeBytes = 0;
179 _playoutBuffer = new WebRtc_Word16[WEBRTC_10MS_PCM_AUDIO];
180 _frequency = playSampFreq;
181 _acm = acm;
182 _firstTime = true;
183}
184
185void Receiver::Teardown() {
186 delete [] _playoutBuffer;
187 _pcmFile.Close();
188 if (testMode > 1)
189 Trace::ReturnTrace();
190}
191
192bool Receiver::IncomingPacket() {
193 if (!_rtpStream->EndOfFile()) {
194 if (_firstTime) {
195 _firstTime = false;
196 _realPayloadSizeBytes = _rtpStream->Read(&_rtpInfo, _incomingPayload,
197 _payloadSizeBytes, &_nextTime);
andrew@webrtc.org975e4a32012-01-17 19:27:33 +0000198 if (_realPayloadSizeBytes == 0) {
199 if (_rtpStream->EndOfFile()) {
200 _firstTime = true;
201 return true;
202 } else {
203 printf("Error in reading incoming payload.\n");
204 return false;
205 }
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000206 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000207 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000208
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000209 WebRtc_Word32 ok = _acm->IncomingPacket(_incomingPayload,
210 _realPayloadSizeBytes, _rtpInfo);
211 if (ok != 0) {
212 printf("Error when inserting packet to ACM, for run: codecId: %d\n",
213 codeId);
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000214 }
215 _realPayloadSizeBytes = _rtpStream->Read(&_rtpInfo, _incomingPayload,
216 _payloadSizeBytes, &_nextTime);
217 if (_realPayloadSizeBytes == 0 && _rtpStream->EndOfFile()) {
218 _firstTime = true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000219 }
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000220 }
221 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000222}
223
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000224bool Receiver::PlayoutData() {
225 AudioFrame audioFrame;
226
tina.legrand@webrtc.orgeb7ebf22013-02-20 15:57:31 +0000227 if (_acm->PlayoutData10Ms(_frequency, audioFrame) != 0) {
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000228 printf("Error when calling PlayoutData10Ms, for run: codecId: %d\n",
229 codeId);
230 exit(1);
231 }
232 if (_playoutLengthSmpls == 0) {
233 return false;
234 }
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000235 _pcmFile.Write10MsData(audioFrame.data_,
236 audioFrame.samples_per_channel_);
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000237 return true;
238}
239
240void Receiver::Run() {
241 WebRtc_UWord8 counter500Ms = 50;
242 WebRtc_UWord32 clock = 0;
243
244 while (counter500Ms > 0) {
245 if (clock == 0 || clock >= _nextTime) {
246 IncomingPacket();
247 if (clock == 0) {
248 clock = _nextTime;
249 }
250 }
251 if ((clock % 10) == 0) {
252 if (!PlayoutData()) {
253 clock++;
254 continue;
255 }
256 }
257 if (_rtpStream->EndOfFile()) {
258 counter500Ms--;
259 }
260 clock++;
261 }
262}
263
264EncodeDecodeTest::EncodeDecodeTest() {
265 _testMode = 2;
266 Trace::CreateTrace();
tina.legrand@webrtc.org5e7ca602012-06-12 07:16:24 +0000267 Trace::SetTraceFile((webrtc::test::OutputPath() +
268 "acm_encdec_trace.txt").c_str());
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000269}
270
271EncodeDecodeTest::EncodeDecodeTest(int testMode) {
272 //testMode == 0 for autotest
273 //testMode == 1 for testing all codecs/parameters
274 //testMode > 1 for specific user-input test (as it was used before)
275 _testMode = testMode;
276 if(_testMode != 0) {
277 Trace::CreateTrace();
tina.legrand@webrtc.org5e7ca602012-06-12 07:16:24 +0000278 Trace::SetTraceFile((webrtc::test::OutputPath() +
279 "acm_encdec_trace.txt").c_str());
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000280 }
281}
282
283void EncodeDecodeTest::Perform() {
284 if (_testMode == 0) {
285 printf("Running Encode/Decode Test");
286 WEBRTC_TRACE(webrtc::kTraceStateInfo, webrtc::kTraceAudioCoding, -1,
287 "---------- EncodeDecodeTest ----------");
288 }
289
290 int numCodecs = 1;
tina.legrand@webrtc.org45175852012-06-01 09:27:35 +0000291 int codePars[3]; // Frequency, packet size, rate.
292 int numPars[52]; // Number of codec parameters sets (freq, pacsize, rate)
293 // to test, for a given codec.
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000294
295 codePars[0] = 0;
296 codePars[1] = 0;
297 codePars[2] = 0;
298
tina.legrand@webrtc.org5b4f36d2012-06-01 14:51:28 +0000299 AudioCodingModule* acm = AudioCodingModule::Create(0);
tina.legrand@webrtc.org45175852012-06-01 09:27:35 +0000300 struct CodecInst sendCodecTmp;
tina.legrand@webrtc.org5b4f36d2012-06-01 14:51:28 +0000301 numCodecs = acm->NumberOfCodecs();
tina.legrand@webrtc.org45175852012-06-01 09:27:35 +0000302
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000303 if (_testMode == 1) {
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000304 printf("List of supported codec.\n");
tina.legrand@webrtc.org45175852012-06-01 09:27:35 +0000305 }
306 if (_testMode != 2) {
307 for (int n = 0; n < numCodecs; n++) {
tina.legrand@webrtc.orgeb7ebf22013-02-20 15:57:31 +0000308 acm->Codec(n, sendCodecTmp);
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000309 if (STR_CASE_CMP(sendCodecTmp.plname, "telephone-event") == 0) {
310 numPars[n] = 0;
311 } else if (STR_CASE_CMP(sendCodecTmp.plname, "cn") == 0) {
312 numPars[n] = 0;
313 } else if (STR_CASE_CMP(sendCodecTmp.plname, "red") == 0) {
314 numPars[n] = 0;
tina.legrand@webrtc.org45175852012-06-01 09:27:35 +0000315 } else if (sendCodecTmp.channels == 2) {
316 numPars[n] = 0;
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000317 } else {
318 numPars[n] = 1;
tina.legrand@webrtc.org45175852012-06-01 09:27:35 +0000319 if (_testMode == 1) {
320 printf("%d %s\n", n, sendCodecTmp.plname);
321 }
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000322 }
323 }
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000324 } else {
325 numCodecs = 1;
326 numPars[0] = 1;
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000327 }
328
329 _receiver.testMode = _testMode;
330
tina.legrand@webrtc.org45175852012-06-01 09:27:35 +0000331 // Loop over all mono codecs:
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000332 for (int codeId = 0; codeId < numCodecs; codeId++) {
tina.legrand@webrtc.org45175852012-06-01 09:27:35 +0000333 // Only encode using real mono encoders, not telephone-event and cng.
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000334 for (int loopPars = 1; loopPars <= numPars[codeId]; loopPars++) {
335 if (_testMode == 1) {
336 printf("\n");
337 printf("***FOR RUN: codeId: %d\n", codeId);
338 printf("\n");
339 } else if (_testMode == 0) {
340 printf(".");
341 }
342
343 EncodeToFile(1, codeId, codePars, _testMode);
344
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000345 RTPFile rtpFile;
kjellander@webrtc.org5490c712011-12-21 13:34:18 +0000346 std::string fileName = webrtc::test::OutputPath() + "outFile.rtp";
347 rtpFile.Open(fileName.c_str(), "rb");
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000348
349 _receiver.codeId = codeId;
350
351 rtpFile.ReadHeader();
352 _receiver.Setup(acm, &rtpFile);
353 _receiver.Run();
354 _receiver.Teardown();
355 rtpFile.Close();
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000356
357 if (_testMode == 1) {
358 printf("***COMPLETED RUN FOR: codecID: %d ***\n", codeId);
359 }
360 }
361 }
tina.legrand@webrtc.org5b4f36d2012-06-01 14:51:28 +0000362 AudioCodingModule::Destroy(acm);
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000363 if (_testMode == 0) {
364 printf("Done!\n");
365 }
366 if (_testMode == 1)
367 Trace::ReturnTrace();
368}
369
370void EncodeDecodeTest::EncodeToFile(int fileType, int codeId, int* codePars,
371 int testMode) {
tina.legrand@webrtc.org5b4f36d2012-06-01 14:51:28 +0000372 AudioCodingModule* acm = AudioCodingModule::Create(1);
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000373 RTPFile rtpFile;
kjellander@webrtc.org5490c712011-12-21 13:34:18 +0000374 std::string fileName = webrtc::test::OutputPath() + "outFile.rtp";
375 rtpFile.Open(fileName.c_str(), "wb+");
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000376 rtpFile.WriteHeader();
377
378 //for auto_test and logging
379 _sender.testMode = testMode;
380 _sender.codeId = codeId;
381
382 _sender.Setup(acm, &rtpFile);
383 struct CodecInst sendCodecInst;
tina.legrand@webrtc.orgeb7ebf22013-02-20 15:57:31 +0000384 if (acm->SendCodec(sendCodecInst) >= 0) {
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000385 _sender.Run();
386 }
387 _sender.Teardown();
388 rtpFile.Close();
389 AudioCodingModule::Destroy(acm);
390}
391
392} // namespace webrtc