1 /*
2 * Copyright (c) 2014 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 <stdio.h>
12 #include <string.h>
13 #include <vector>
14
15 #include "testing/gtest/include/gtest/gtest.h"
16 #include "webrtc/base/md5digest.h"
17 #include "webrtc/base/platform_thread.h"
18 #include "webrtc/base/scoped_ptr.h"
19 #include "webrtc/base/thread_annotations.h"
20 #include "webrtc/modules/audio_coding/codecs/audio_encoder.h"
21 #include "webrtc/modules/audio_coding/codecs/g711/audio_decoder_pcm.h"
22 #include "webrtc/modules/audio_coding/codecs/g711/audio_encoder_pcm.h"
23 #include "webrtc/modules/audio_coding/codecs/isac/main/include/audio_encoder_isac.h"
24 #include "webrtc/modules/audio_coding/codecs/mock/mock_audio_encoder.h"
25 #include "webrtc/modules/audio_coding/acm2/acm_receive_test_oldapi.h"
26 #include "webrtc/modules/audio_coding/acm2/acm_send_test_oldapi.h"
27 #include "webrtc/modules/audio_coding/include/audio_coding_module.h"
28 #include "webrtc/modules/audio_coding/include/audio_coding_module_typedefs.h"
29 #include "webrtc/modules/audio_coding/neteq/audio_decoder_impl.h"
30 #include "webrtc/modules/audio_coding/neteq/mock/mock_audio_decoder.h"
31 #include "webrtc/modules/audio_coding/neteq/tools/audio_checksum.h"
32 #include "webrtc/modules/audio_coding/neteq/tools/audio_loop.h"
33 #include "webrtc/modules/audio_coding/neteq/tools/constant_pcm_packet_source.h"
34 #include "webrtc/modules/audio_coding/neteq/tools/input_audio_file.h"
35 #include "webrtc/modules/audio_coding/neteq/tools/output_audio_file.h"
36 #include "webrtc/modules/audio_coding/neteq/tools/packet.h"
37 #include "webrtc/modules/audio_coding/neteq/tools/rtp_file_source.h"
38 #include "webrtc/modules/include/module_common_types.h"
39 #include "webrtc/system_wrappers/include/clock.h"
40 #include "webrtc/system_wrappers/include/critical_section_wrapper.h"
41 #include "webrtc/system_wrappers/include/event_wrapper.h"
42 #include "webrtc/system_wrappers/include/sleep.h"
43 #include "webrtc/test/testsupport/fileutils.h"
44
45 using ::testing::AtLeast;
46 using ::testing::Invoke;
47 using ::testing::_;
48
49 namespace webrtc {
50
51 namespace {
52 const int kSampleRateHz = 16000;
53 const int kNumSamples10ms = kSampleRateHz / 100;
54 const int kFrameSizeMs = 10; // Multiple of 10.
55 const int kFrameSizeSamples = kFrameSizeMs / 10 * kNumSamples10ms;
56 const int kPayloadSizeBytes = kFrameSizeSamples * sizeof(int16_t);
57 const uint8_t kPayloadType = 111;
58 } // namespace
59
60 class RtpUtility {
61 public:
RtpUtility(int samples_per_packet,uint8_t payload_type)62 RtpUtility(int samples_per_packet, uint8_t payload_type)
63 : samples_per_packet_(samples_per_packet), payload_type_(payload_type) {}
64
~RtpUtility()65 virtual ~RtpUtility() {}
66
Populate(WebRtcRTPHeader * rtp_header)67 void Populate(WebRtcRTPHeader* rtp_header) {
68 rtp_header->header.sequenceNumber = 0xABCD;
69 rtp_header->header.timestamp = 0xABCDEF01;
70 rtp_header->header.payloadType = payload_type_;
71 rtp_header->header.markerBit = false;
72 rtp_header->header.ssrc = 0x1234;
73 rtp_header->header.numCSRCs = 0;
74 rtp_header->frameType = kAudioFrameSpeech;
75
76 rtp_header->header.payload_type_frequency = kSampleRateHz;
77 rtp_header->type.Audio.channel = 1;
78 rtp_header->type.Audio.isCNG = false;
79 }
80
Forward(WebRtcRTPHeader * rtp_header)81 void Forward(WebRtcRTPHeader* rtp_header) {
82 ++rtp_header->header.sequenceNumber;
83 rtp_header->header.timestamp += samples_per_packet_;
84 }
85
86 private:
87 int samples_per_packet_;
88 uint8_t payload_type_;
89 };
90
91 class PacketizationCallbackStubOldApi : public AudioPacketizationCallback {
92 public:
PacketizationCallbackStubOldApi()93 PacketizationCallbackStubOldApi()
94 : num_calls_(0),
95 last_frame_type_(kEmptyFrame),
96 last_payload_type_(-1),
97 last_timestamp_(0),
98 crit_sect_(CriticalSectionWrapper::CreateCriticalSection()) {}
99
SendData(FrameType frame_type,uint8_t payload_type,uint32_t timestamp,const uint8_t * payload_data,size_t payload_len_bytes,const RTPFragmentationHeader * fragmentation)100 int32_t SendData(FrameType frame_type,
101 uint8_t payload_type,
102 uint32_t timestamp,
103 const uint8_t* payload_data,
104 size_t payload_len_bytes,
105 const RTPFragmentationHeader* fragmentation) override {
106 CriticalSectionScoped lock(crit_sect_.get());
107 ++num_calls_;
108 last_frame_type_ = frame_type;
109 last_payload_type_ = payload_type;
110 last_timestamp_ = timestamp;
111 last_payload_vec_.assign(payload_data, payload_data + payload_len_bytes);
112 return 0;
113 }
114
num_calls() const115 int num_calls() const {
116 CriticalSectionScoped lock(crit_sect_.get());
117 return num_calls_;
118 }
119
last_payload_len_bytes() const120 int last_payload_len_bytes() const {
121 CriticalSectionScoped lock(crit_sect_.get());
122 return last_payload_vec_.size();
123 }
124
last_frame_type() const125 FrameType last_frame_type() const {
126 CriticalSectionScoped lock(crit_sect_.get());
127 return last_frame_type_;
128 }
129
last_payload_type() const130 int last_payload_type() const {
131 CriticalSectionScoped lock(crit_sect_.get());
132 return last_payload_type_;
133 }
134
last_timestamp() const135 uint32_t last_timestamp() const {
136 CriticalSectionScoped lock(crit_sect_.get());
137 return last_timestamp_;
138 }
139
SwapBuffers(std::vector<uint8_t> * payload)140 void SwapBuffers(std::vector<uint8_t>* payload) {
141 CriticalSectionScoped lock(crit_sect_.get());
142 last_payload_vec_.swap(*payload);
143 }
144
145 private:
146 int num_calls_ GUARDED_BY(crit_sect_);
147 FrameType last_frame_type_ GUARDED_BY(crit_sect_);
148 int last_payload_type_ GUARDED_BY(crit_sect_);
149 uint32_t last_timestamp_ GUARDED_BY(crit_sect_);
150 std::vector<uint8_t> last_payload_vec_ GUARDED_BY(crit_sect_);
151 const rtc::scoped_ptr<CriticalSectionWrapper> crit_sect_;
152 };
153
154 class AudioCodingModuleTestOldApi : public ::testing::Test {
155 protected:
AudioCodingModuleTestOldApi()156 AudioCodingModuleTestOldApi()
157 : id_(1),
158 rtp_utility_(new RtpUtility(kFrameSizeSamples, kPayloadType)),
159 clock_(Clock::GetRealTimeClock()) {}
160
~AudioCodingModuleTestOldApi()161 ~AudioCodingModuleTestOldApi() {}
162
TearDown()163 void TearDown() {}
164
SetUp()165 void SetUp() {
166 acm_.reset(AudioCodingModule::Create(id_, clock_));
167
168 rtp_utility_->Populate(&rtp_header_);
169
170 input_frame_.sample_rate_hz_ = kSampleRateHz;
171 input_frame_.num_channels_ = 1;
172 input_frame_.samples_per_channel_ = kSampleRateHz * 10 / 1000; // 10 ms.
173 static_assert(kSampleRateHz * 10 / 1000 <= AudioFrame::kMaxDataSizeSamples,
174 "audio frame too small");
175 memset(input_frame_.data_,
176 0,
177 input_frame_.samples_per_channel_ * sizeof(input_frame_.data_[0]));
178
179 ASSERT_EQ(0, acm_->RegisterTransportCallback(&packet_cb_));
180
181 SetUpL16Codec();
182 }
183
184 // Set up L16 codec.
SetUpL16Codec()185 virtual void SetUpL16Codec() {
186 ASSERT_EQ(0, AudioCodingModule::Codec("L16", &codec_, kSampleRateHz, 1));
187 codec_.pltype = kPayloadType;
188 }
189
RegisterCodec()190 virtual void RegisterCodec() {
191 ASSERT_EQ(0, acm_->RegisterReceiveCodec(codec_));
192 ASSERT_EQ(0, acm_->RegisterSendCodec(codec_));
193 }
194
InsertPacketAndPullAudio()195 virtual void InsertPacketAndPullAudio() {
196 InsertPacket();
197 PullAudio();
198 }
199
InsertPacket()200 virtual void InsertPacket() {
201 const uint8_t kPayload[kPayloadSizeBytes] = {0};
202 ASSERT_EQ(0,
203 acm_->IncomingPacket(kPayload, kPayloadSizeBytes, rtp_header_));
204 rtp_utility_->Forward(&rtp_header_);
205 }
206
PullAudio()207 virtual void PullAudio() {
208 AudioFrame audio_frame;
209 ASSERT_EQ(0, acm_->PlayoutData10Ms(-1, &audio_frame));
210 }
211
InsertAudio()212 virtual void InsertAudio() {
213 ASSERT_GE(acm_->Add10MsData(input_frame_), 0);
214 input_frame_.timestamp_ += kNumSamples10ms;
215 }
216
VerifyEncoding()217 virtual void VerifyEncoding() {
218 int last_length = packet_cb_.last_payload_len_bytes();
219 EXPECT_TRUE(last_length == 2 * codec_.pacsize || last_length == 0)
220 << "Last encoded packet was " << last_length << " bytes.";
221 }
222
InsertAudioAndVerifyEncoding()223 virtual void InsertAudioAndVerifyEncoding() {
224 InsertAudio();
225 VerifyEncoding();
226 }
227
228 const int id_;
229 rtc::scoped_ptr<RtpUtility> rtp_utility_;
230 rtc::scoped_ptr<AudioCodingModule> acm_;
231 PacketizationCallbackStubOldApi packet_cb_;
232 WebRtcRTPHeader rtp_header_;
233 AudioFrame input_frame_;
234 CodecInst codec_;
235 Clock* clock_;
236 };
237
238 // Check if the statistics are initialized correctly. Before any call to ACM
239 // all fields have to be zero.
240 #if defined(WEBRTC_ANDROID)
241 #define MAYBE_InitializedToZero DISABLED_InitializedToZero
242 #else
243 #define MAYBE_InitializedToZero InitializedToZero
244 #endif
TEST_F(AudioCodingModuleTestOldApi,MAYBE_InitializedToZero)245 TEST_F(AudioCodingModuleTestOldApi, MAYBE_InitializedToZero) {
246 RegisterCodec();
247 AudioDecodingCallStats stats;
248 acm_->GetDecodingCallStatistics(&stats);
249 EXPECT_EQ(0, stats.calls_to_neteq);
250 EXPECT_EQ(0, stats.calls_to_silence_generator);
251 EXPECT_EQ(0, stats.decoded_normal);
252 EXPECT_EQ(0, stats.decoded_cng);
253 EXPECT_EQ(0, stats.decoded_plc);
254 EXPECT_EQ(0, stats.decoded_plc_cng);
255 }
256
257 // Insert some packets and pull audio. Check statistics are valid. Then,
258 // simulate packet loss and check if PLC and PLC-to-CNG statistics are
259 // correctly updated.
260 #if defined(WEBRTC_ANDROID)
261 #define MAYBE_NetEqCalls DISABLED_NetEqCalls
262 #else
263 #define MAYBE_NetEqCalls NetEqCalls
264 #endif
TEST_F(AudioCodingModuleTestOldApi,MAYBE_NetEqCalls)265 TEST_F(AudioCodingModuleTestOldApi, MAYBE_NetEqCalls) {
266 RegisterCodec();
267 AudioDecodingCallStats stats;
268 const int kNumNormalCalls = 10;
269
270 for (int num_calls = 0; num_calls < kNumNormalCalls; ++num_calls) {
271 InsertPacketAndPullAudio();
272 }
273 acm_->GetDecodingCallStatistics(&stats);
274 EXPECT_EQ(kNumNormalCalls, stats.calls_to_neteq);
275 EXPECT_EQ(0, stats.calls_to_silence_generator);
276 EXPECT_EQ(kNumNormalCalls, stats.decoded_normal);
277 EXPECT_EQ(0, stats.decoded_cng);
278 EXPECT_EQ(0, stats.decoded_plc);
279 EXPECT_EQ(0, stats.decoded_plc_cng);
280
281 const int kNumPlc = 3;
282 const int kNumPlcCng = 5;
283
284 // Simulate packet-loss. NetEq first performs PLC then PLC fades to CNG.
285 for (int n = 0; n < kNumPlc + kNumPlcCng; ++n) {
286 PullAudio();
287 }
288 acm_->GetDecodingCallStatistics(&stats);
289 EXPECT_EQ(kNumNormalCalls + kNumPlc + kNumPlcCng, stats.calls_to_neteq);
290 EXPECT_EQ(0, stats.calls_to_silence_generator);
291 EXPECT_EQ(kNumNormalCalls, stats.decoded_normal);
292 EXPECT_EQ(0, stats.decoded_cng);
293 EXPECT_EQ(kNumPlc, stats.decoded_plc);
294 EXPECT_EQ(kNumPlcCng, stats.decoded_plc_cng);
295 }
296
TEST_F(AudioCodingModuleTestOldApi,VerifyOutputFrame)297 TEST_F(AudioCodingModuleTestOldApi, VerifyOutputFrame) {
298 AudioFrame audio_frame;
299 const int kSampleRateHz = 32000;
300 EXPECT_EQ(0, acm_->PlayoutData10Ms(kSampleRateHz, &audio_frame));
301 EXPECT_EQ(id_, audio_frame.id_);
302 EXPECT_EQ(0u, audio_frame.timestamp_);
303 EXPECT_GT(audio_frame.num_channels_, 0u);
304 EXPECT_EQ(static_cast<size_t>(kSampleRateHz / 100),
305 audio_frame.samples_per_channel_);
306 EXPECT_EQ(kSampleRateHz, audio_frame.sample_rate_hz_);
307 }
308
TEST_F(AudioCodingModuleTestOldApi,FailOnZeroDesiredFrequency)309 TEST_F(AudioCodingModuleTestOldApi, FailOnZeroDesiredFrequency) {
310 AudioFrame audio_frame;
311 EXPECT_EQ(-1, acm_->PlayoutData10Ms(0, &audio_frame));
312 }
313
314 // Checks that the transport callback is invoked once for each speech packet.
315 // Also checks that the frame type is kAudioFrameSpeech.
TEST_F(AudioCodingModuleTestOldApi,TransportCallbackIsInvokedForEachPacket)316 TEST_F(AudioCodingModuleTestOldApi, TransportCallbackIsInvokedForEachPacket) {
317 const int k10MsBlocksPerPacket = 3;
318 codec_.pacsize = k10MsBlocksPerPacket * kSampleRateHz / 100;
319 RegisterCodec();
320 const int kLoops = 10;
321 for (int i = 0; i < kLoops; ++i) {
322 EXPECT_EQ(i / k10MsBlocksPerPacket, packet_cb_.num_calls());
323 if (packet_cb_.num_calls() > 0)
324 EXPECT_EQ(kAudioFrameSpeech, packet_cb_.last_frame_type());
325 InsertAudioAndVerifyEncoding();
326 }
327 EXPECT_EQ(kLoops / k10MsBlocksPerPacket, packet_cb_.num_calls());
328 EXPECT_EQ(kAudioFrameSpeech, packet_cb_.last_frame_type());
329 }
330
331 #if defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX)
332 // Verifies that the RTP timestamp series is not reset when the codec is
333 // changed.
TEST_F(AudioCodingModuleTestOldApi,TimestampSeriesContinuesWhenCodecChanges)334 TEST_F(AudioCodingModuleTestOldApi, TimestampSeriesContinuesWhenCodecChanges) {
335 RegisterCodec(); // This registers the default codec.
336 uint32_t expected_ts = input_frame_.timestamp_;
337 int blocks_per_packet = codec_.pacsize / (kSampleRateHz / 100);
338 // Encode 5 packets of the first codec type.
339 const int kNumPackets1 = 5;
340 for (int j = 0; j < kNumPackets1; ++j) {
341 for (int i = 0; i < blocks_per_packet; ++i) {
342 EXPECT_EQ(j, packet_cb_.num_calls());
343 InsertAudio();
344 }
345 EXPECT_EQ(j + 1, packet_cb_.num_calls());
346 EXPECT_EQ(expected_ts, packet_cb_.last_timestamp());
347 expected_ts += codec_.pacsize;
348 }
349
350 // Change codec.
351 ASSERT_EQ(0, AudioCodingModule::Codec("ISAC", &codec_, kSampleRateHz, 1));
352 RegisterCodec();
353 blocks_per_packet = codec_.pacsize / (kSampleRateHz / 100);
354 // Encode another 5 packets.
355 const int kNumPackets2 = 5;
356 for (int j = 0; j < kNumPackets2; ++j) {
357 for (int i = 0; i < blocks_per_packet; ++i) {
358 EXPECT_EQ(kNumPackets1 + j, packet_cb_.num_calls());
359 InsertAudio();
360 }
361 EXPECT_EQ(kNumPackets1 + j + 1, packet_cb_.num_calls());
362 EXPECT_EQ(expected_ts, packet_cb_.last_timestamp());
363 expected_ts += codec_.pacsize;
364 }
365 }
366 #endif
367
368 // Introduce this class to set different expectations on the number of encoded
369 // bytes. This class expects all encoded packets to be 9 bytes (matching one
370 // CNG SID frame) or 0 bytes. This test depends on |input_frame_| containing
371 // (near-)zero values. It also introduces a way to register comfort noise with
372 // a custom payload type.
373 class AudioCodingModuleTestWithComfortNoiseOldApi
374 : public AudioCodingModuleTestOldApi {
375 protected:
RegisterCngCodec(int rtp_payload_type)376 void RegisterCngCodec(int rtp_payload_type) {
377 CodecInst codec;
378 AudioCodingModule::Codec("CN", &codec, kSampleRateHz, 1);
379 codec.pltype = rtp_payload_type;
380 ASSERT_EQ(0, acm_->RegisterReceiveCodec(codec));
381 ASSERT_EQ(0, acm_->RegisterSendCodec(codec));
382 }
383
VerifyEncoding()384 void VerifyEncoding() override {
385 int last_length = packet_cb_.last_payload_len_bytes();
386 EXPECT_TRUE(last_length == 9 || last_length == 0)
387 << "Last encoded packet was " << last_length << " bytes.";
388 }
389
DoTest(int blocks_per_packet,int cng_pt)390 void DoTest(int blocks_per_packet, int cng_pt) {
391 const int kLoops = 40;
392 // This array defines the expected frame types, and when they should arrive.
393 // We expect a frame to arrive each time the speech encoder would have
394 // produced a packet, and once every 100 ms the frame should be non-empty,
395 // that is contain comfort noise.
396 const struct {
397 int ix;
398 FrameType type;
399 } expectation[] = {{2, kAudioFrameCN},
400 {5, kEmptyFrame},
401 {8, kEmptyFrame},
402 {11, kAudioFrameCN},
403 {14, kEmptyFrame},
404 {17, kEmptyFrame},
405 {20, kAudioFrameCN},
406 {23, kEmptyFrame},
407 {26, kEmptyFrame},
408 {29, kEmptyFrame},
409 {32, kAudioFrameCN},
410 {35, kEmptyFrame},
411 {38, kEmptyFrame}};
412 for (int i = 0; i < kLoops; ++i) {
413 int num_calls_before = packet_cb_.num_calls();
414 EXPECT_EQ(i / blocks_per_packet, num_calls_before);
415 InsertAudioAndVerifyEncoding();
416 int num_calls = packet_cb_.num_calls();
417 if (num_calls == num_calls_before + 1) {
418 EXPECT_EQ(expectation[num_calls - 1].ix, i);
419 EXPECT_EQ(expectation[num_calls - 1].type, packet_cb_.last_frame_type())
420 << "Wrong frame type for lap " << i;
421 EXPECT_EQ(cng_pt, packet_cb_.last_payload_type());
422 } else {
423 EXPECT_EQ(num_calls, num_calls_before);
424 }
425 }
426 }
427 };
428
429 // Checks that the transport callback is invoked once per frame period of the
430 // underlying speech encoder, even when comfort noise is produced.
431 // Also checks that the frame type is kAudioFrameCN or kEmptyFrame.
432 // This test and the next check the same thing, but differ in the order of
433 // speech codec and CNG registration.
TEST_F(AudioCodingModuleTestWithComfortNoiseOldApi,TransportCallbackTestForComfortNoiseRegisterCngLast)434 TEST_F(AudioCodingModuleTestWithComfortNoiseOldApi,
435 TransportCallbackTestForComfortNoiseRegisterCngLast) {
436 const int k10MsBlocksPerPacket = 3;
437 codec_.pacsize = k10MsBlocksPerPacket * kSampleRateHz / 100;
438 RegisterCodec();
439 const int kCngPayloadType = 105;
440 RegisterCngCodec(kCngPayloadType);
441 ASSERT_EQ(0, acm_->SetVAD(true, true));
442 DoTest(k10MsBlocksPerPacket, kCngPayloadType);
443 }
444
TEST_F(AudioCodingModuleTestWithComfortNoiseOldApi,TransportCallbackTestForComfortNoiseRegisterCngFirst)445 TEST_F(AudioCodingModuleTestWithComfortNoiseOldApi,
446 TransportCallbackTestForComfortNoiseRegisterCngFirst) {
447 const int k10MsBlocksPerPacket = 3;
448 codec_.pacsize = k10MsBlocksPerPacket * kSampleRateHz / 100;
449 const int kCngPayloadType = 105;
450 RegisterCngCodec(kCngPayloadType);
451 RegisterCodec();
452 ASSERT_EQ(0, acm_->SetVAD(true, true));
453 DoTest(k10MsBlocksPerPacket, kCngPayloadType);
454 }
455
456 // A multi-threaded test for ACM. This base class is using the PCM16b 16 kHz
457 // codec, while the derive class AcmIsacMtTest is using iSAC.
458 class AudioCodingModuleMtTestOldApi : public AudioCodingModuleTestOldApi {
459 protected:
460 static const int kNumPackets = 500;
461 static const int kNumPullCalls = 500;
462
AudioCodingModuleMtTestOldApi()463 AudioCodingModuleMtTestOldApi()
464 : AudioCodingModuleTestOldApi(),
465 send_thread_(CbSendThread, this, "send"),
466 insert_packet_thread_(CbInsertPacketThread, this, "insert_packet"),
467 pull_audio_thread_(CbPullAudioThread, this, "pull_audio"),
468 test_complete_(EventWrapper::Create()),
469 send_count_(0),
470 insert_packet_count_(0),
471 pull_audio_count_(0),
472 crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
473 next_insert_packet_time_ms_(0),
474 fake_clock_(new SimulatedClock(0)) {
475 clock_ = fake_clock_.get();
476 }
477
SetUp()478 void SetUp() {
479 AudioCodingModuleTestOldApi::SetUp();
480 RegisterCodec(); // Must be called before the threads start below.
481 StartThreads();
482 }
483
StartThreads()484 void StartThreads() {
485 send_thread_.Start();
486 send_thread_.SetPriority(rtc::kRealtimePriority);
487 insert_packet_thread_.Start();
488 insert_packet_thread_.SetPriority(rtc::kRealtimePriority);
489 pull_audio_thread_.Start();
490 pull_audio_thread_.SetPriority(rtc::kRealtimePriority);
491 }
492
TearDown()493 void TearDown() {
494 AudioCodingModuleTestOldApi::TearDown();
495 pull_audio_thread_.Stop();
496 send_thread_.Stop();
497 insert_packet_thread_.Stop();
498 }
499
RunTest()500 EventTypeWrapper RunTest() {
501 return test_complete_->Wait(10 * 60 * 1000); // 10 minutes' timeout.
502 }
503
TestDone()504 virtual bool TestDone() {
505 if (packet_cb_.num_calls() > kNumPackets) {
506 CriticalSectionScoped lock(crit_sect_.get());
507 if (pull_audio_count_ > kNumPullCalls) {
508 // Both conditions for completion are met. End the test.
509 return true;
510 }
511 }
512 return false;
513 }
514
CbSendThread(void * context)515 static bool CbSendThread(void* context) {
516 return reinterpret_cast<AudioCodingModuleMtTestOldApi*>(context)
517 ->CbSendImpl();
518 }
519
520 // The send thread doesn't have to care about the current simulated time,
521 // since only the AcmReceiver is using the clock.
CbSendImpl()522 bool CbSendImpl() {
523 SleepMs(1);
524 if (HasFatalFailure()) {
525 // End the test early if a fatal failure (ASSERT_*) has occurred.
526 test_complete_->Set();
527 }
528 ++send_count_;
529 InsertAudioAndVerifyEncoding();
530 if (TestDone()) {
531 test_complete_->Set();
532 }
533 return true;
534 }
535
CbInsertPacketThread(void * context)536 static bool CbInsertPacketThread(void* context) {
537 return reinterpret_cast<AudioCodingModuleMtTestOldApi*>(context)
538 ->CbInsertPacketImpl();
539 }
540
CbInsertPacketImpl()541 bool CbInsertPacketImpl() {
542 SleepMs(1);
543 {
544 CriticalSectionScoped lock(crit_sect_.get());
545 if (clock_->TimeInMilliseconds() < next_insert_packet_time_ms_) {
546 return true;
547 }
548 next_insert_packet_time_ms_ += 10;
549 }
550 // Now we're not holding the crit sect when calling ACM.
551 ++insert_packet_count_;
552 InsertPacket();
553 return true;
554 }
555
CbPullAudioThread(void * context)556 static bool CbPullAudioThread(void* context) {
557 return reinterpret_cast<AudioCodingModuleMtTestOldApi*>(context)
558 ->CbPullAudioImpl();
559 }
560
CbPullAudioImpl()561 bool CbPullAudioImpl() {
562 SleepMs(1);
563 {
564 CriticalSectionScoped lock(crit_sect_.get());
565 // Don't let the insert thread fall behind.
566 if (next_insert_packet_time_ms_ < clock_->TimeInMilliseconds()) {
567 return true;
568 }
569 ++pull_audio_count_;
570 }
571 // Now we're not holding the crit sect when calling ACM.
572 PullAudio();
573 fake_clock_->AdvanceTimeMilliseconds(10);
574 return true;
575 }
576
577 rtc::PlatformThread send_thread_;
578 rtc::PlatformThread insert_packet_thread_;
579 rtc::PlatformThread pull_audio_thread_;
580 const rtc::scoped_ptr<EventWrapper> test_complete_;
581 int send_count_;
582 int insert_packet_count_;
583 int pull_audio_count_ GUARDED_BY(crit_sect_);
584 const rtc::scoped_ptr<CriticalSectionWrapper> crit_sect_;
585 int64_t next_insert_packet_time_ms_ GUARDED_BY(crit_sect_);
586 rtc::scoped_ptr<SimulatedClock> fake_clock_;
587 };
588
589 #if defined(WEBRTC_IOS)
590 #define MAYBE_DoTest DISABLED_DoTest
591 #else
592 #define MAYBE_DoTest DoTest
593 #endif
TEST_F(AudioCodingModuleMtTestOldApi,MAYBE_DoTest)594 TEST_F(AudioCodingModuleMtTestOldApi, MAYBE_DoTest) {
595 EXPECT_EQ(kEventSignaled, RunTest());
596 }
597
598 // This is a multi-threaded ACM test using iSAC. The test encodes audio
599 // from a PCM file. The most recent encoded frame is used as input to the
600 // receiving part. Depending on timing, it may happen that the same RTP packet
601 // is inserted into the receiver multiple times, but this is a valid use-case,
602 // and simplifies the test code a lot.
603 class AcmIsacMtTestOldApi : public AudioCodingModuleMtTestOldApi {
604 protected:
605 static const int kNumPackets = 500;
606 static const int kNumPullCalls = 500;
607
AcmIsacMtTestOldApi()608 AcmIsacMtTestOldApi()
609 : AudioCodingModuleMtTestOldApi(), last_packet_number_(0) {}
610
~AcmIsacMtTestOldApi()611 ~AcmIsacMtTestOldApi() {}
612
SetUp()613 void SetUp() {
614 AudioCodingModuleTestOldApi::SetUp();
615 RegisterCodec(); // Must be called before the threads start below.
616
617 // Set up input audio source to read from specified file, loop after 5
618 // seconds, and deliver blocks of 10 ms.
619 const std::string input_file_name =
620 webrtc::test::ResourcePath("audio_coding/speech_mono_16kHz", "pcm");
621 audio_loop_.Init(input_file_name, 5 * kSampleRateHz, kNumSamples10ms);
622
623 // Generate one packet to have something to insert.
624 int loop_counter = 0;
625 while (packet_cb_.last_payload_len_bytes() == 0) {
626 InsertAudio();
627 ASSERT_LT(loop_counter++, 10);
628 }
629 // Set |last_packet_number_| to one less that |num_calls| so that the packet
630 // will be fetched in the next InsertPacket() call.
631 last_packet_number_ = packet_cb_.num_calls() - 1;
632
633 StartThreads();
634 }
635
RegisterCodec()636 void RegisterCodec() override {
637 static_assert(kSampleRateHz == 16000, "test designed for iSAC 16 kHz");
638 AudioCodingModule::Codec("ISAC", &codec_, kSampleRateHz, 1);
639 codec_.pltype = kPayloadType;
640
641 // Register iSAC codec in ACM, effectively unregistering the PCM16B codec
642 // registered in AudioCodingModuleTestOldApi::SetUp();
643 ASSERT_EQ(0, acm_->RegisterReceiveCodec(codec_));
644 ASSERT_EQ(0, acm_->RegisterSendCodec(codec_));
645 }
646
InsertPacket()647 void InsertPacket() {
648 int num_calls = packet_cb_.num_calls(); // Store locally for thread safety.
649 if (num_calls > last_packet_number_) {
650 // Get the new payload out from the callback handler.
651 // Note that since we swap buffers here instead of directly inserting
652 // a pointer to the data in |packet_cb_|, we avoid locking the callback
653 // for the duration of the IncomingPacket() call.
654 packet_cb_.SwapBuffers(&last_payload_vec_);
655 ASSERT_GT(last_payload_vec_.size(), 0u);
656 rtp_utility_->Forward(&rtp_header_);
657 last_packet_number_ = num_calls;
658 }
659 ASSERT_GT(last_payload_vec_.size(), 0u);
660 ASSERT_EQ(
661 0,
662 acm_->IncomingPacket(
663 &last_payload_vec_[0], last_payload_vec_.size(), rtp_header_));
664 }
665
InsertAudio()666 void InsertAudio() {
667 // TODO(kwiberg): Use std::copy here. Might be complications because AFAICS
668 // this call confuses the number of samples with the number of bytes, and
669 // ends up copying only half of what it should.
670 memcpy(input_frame_.data_, audio_loop_.GetNextBlock().data(),
671 kNumSamples10ms);
672 AudioCodingModuleTestOldApi::InsertAudio();
673 }
674
675 // Override the verification function with no-op, since iSAC produces variable
676 // payload sizes.
VerifyEncoding()677 void VerifyEncoding() override {}
678
679 // This method is the same as AudioCodingModuleMtTestOldApi::TestDone(), but
680 // here it is using the constants defined in this class (i.e., shorter test
681 // run).
TestDone()682 virtual bool TestDone() {
683 if (packet_cb_.num_calls() > kNumPackets) {
684 CriticalSectionScoped lock(crit_sect_.get());
685 if (pull_audio_count_ > kNumPullCalls) {
686 // Both conditions for completion are met. End the test.
687 return true;
688 }
689 }
690 return false;
691 }
692
693 int last_packet_number_;
694 std::vector<uint8_t> last_payload_vec_;
695 test::AudioLoop audio_loop_;
696 };
697
698 #if defined(WEBRTC_IOS)
699 #define MAYBE_DoTest DISABLED_DoTest
700 #else
701 #define MAYBE_DoTest DoTest
702 #endif
703 #if defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX)
TEST_F(AcmIsacMtTestOldApi,MAYBE_DoTest)704 TEST_F(AcmIsacMtTestOldApi, MAYBE_DoTest) {
705 EXPECT_EQ(kEventSignaled, RunTest());
706 }
707 #endif
708
709 class AcmReRegisterIsacMtTestOldApi : public AudioCodingModuleTestOldApi {
710 protected:
711 static const int kRegisterAfterNumPackets = 5;
712 static const int kNumPackets = 10;
713 static const int kPacketSizeMs = 30;
714 static const int kPacketSizeSamples = kPacketSizeMs * 16;
715
AcmReRegisterIsacMtTestOldApi()716 AcmReRegisterIsacMtTestOldApi()
717 : AudioCodingModuleTestOldApi(),
718 receive_thread_(CbReceiveThread, this, "receive"),
719 codec_registration_thread_(CbCodecRegistrationThread,
720 this,
721 "codec_registration"),
722 test_complete_(EventWrapper::Create()),
723 crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
724 codec_registered_(false),
725 receive_packet_count_(0),
726 next_insert_packet_time_ms_(0),
727 fake_clock_(new SimulatedClock(0)) {
728 AudioEncoderIsac::Config config;
729 config.payload_type = kPayloadType;
730 isac_encoder_.reset(new AudioEncoderIsac(config));
731 clock_ = fake_clock_.get();
732 }
733
SetUp()734 void SetUp() {
735 AudioCodingModuleTestOldApi::SetUp();
736 // Set up input audio source to read from specified file, loop after 5
737 // seconds, and deliver blocks of 10 ms.
738 const std::string input_file_name =
739 webrtc::test::ResourcePath("audio_coding/speech_mono_16kHz", "pcm");
740 audio_loop_.Init(input_file_name, 5 * kSampleRateHz, kNumSamples10ms);
741 RegisterCodec(); // Must be called before the threads start below.
742 StartThreads();
743 }
744
RegisterCodec()745 void RegisterCodec() override {
746 static_assert(kSampleRateHz == 16000, "test designed for iSAC 16 kHz");
747 AudioCodingModule::Codec("ISAC", &codec_, kSampleRateHz, 1);
748 codec_.pltype = kPayloadType;
749
750 // Register iSAC codec in ACM, effectively unregistering the PCM16B codec
751 // registered in AudioCodingModuleTestOldApi::SetUp();
752 // Only register the decoder for now. The encoder is registered later.
753 ASSERT_EQ(0, acm_->RegisterReceiveCodec(codec_));
754 }
755
StartThreads()756 void StartThreads() {
757 receive_thread_.Start();
758 receive_thread_.SetPriority(rtc::kRealtimePriority);
759 codec_registration_thread_.Start();
760 codec_registration_thread_.SetPriority(rtc::kRealtimePriority);
761 }
762
TearDown()763 void TearDown() {
764 AudioCodingModuleTestOldApi::TearDown();
765 receive_thread_.Stop();
766 codec_registration_thread_.Stop();
767 }
768
RunTest()769 EventTypeWrapper RunTest() {
770 return test_complete_->Wait(10 * 60 * 1000); // 10 minutes' timeout.
771 }
772
CbReceiveThread(void * context)773 static bool CbReceiveThread(void* context) {
774 return reinterpret_cast<AcmReRegisterIsacMtTestOldApi*>(context)
775 ->CbReceiveImpl();
776 }
777
CbReceiveImpl()778 bool CbReceiveImpl() {
779 SleepMs(1);
780 const size_t max_encoded_bytes = isac_encoder_->MaxEncodedBytes();
781 rtc::scoped_ptr<uint8_t[]> encoded(new uint8_t[max_encoded_bytes]);
782 AudioEncoder::EncodedInfo info;
783 {
784 CriticalSectionScoped lock(crit_sect_.get());
785 if (clock_->TimeInMilliseconds() < next_insert_packet_time_ms_) {
786 return true;
787 }
788 next_insert_packet_time_ms_ += kPacketSizeMs;
789 ++receive_packet_count_;
790
791 // Encode new frame.
792 uint32_t input_timestamp = rtp_header_.header.timestamp;
793 while (info.encoded_bytes == 0) {
794 info =
795 isac_encoder_->Encode(input_timestamp, audio_loop_.GetNextBlock(),
796 max_encoded_bytes, encoded.get());
797 input_timestamp += 160; // 10 ms at 16 kHz.
798 }
799 EXPECT_EQ(rtp_header_.header.timestamp + kPacketSizeSamples,
800 input_timestamp);
801 EXPECT_EQ(rtp_header_.header.timestamp, info.encoded_timestamp);
802 EXPECT_EQ(rtp_header_.header.payloadType, info.payload_type);
803 }
804 // Now we're not holding the crit sect when calling ACM.
805
806 // Insert into ACM.
807 EXPECT_EQ(0, acm_->IncomingPacket(encoded.get(), info.encoded_bytes,
808 rtp_header_));
809
810 // Pull audio.
811 for (int i = 0; i < rtc::CheckedDivExact(kPacketSizeMs, 10); ++i) {
812 AudioFrame audio_frame;
813 EXPECT_EQ(0, acm_->PlayoutData10Ms(-1 /* default output frequency */,
814 &audio_frame));
815 fake_clock_->AdvanceTimeMilliseconds(10);
816 }
817 rtp_utility_->Forward(&rtp_header_);
818 return true;
819 }
820
CbCodecRegistrationThread(void * context)821 static bool CbCodecRegistrationThread(void* context) {
822 return reinterpret_cast<AcmReRegisterIsacMtTestOldApi*>(context)
823 ->CbCodecRegistrationImpl();
824 }
825
CbCodecRegistrationImpl()826 bool CbCodecRegistrationImpl() {
827 SleepMs(1);
828 if (HasFatalFailure()) {
829 // End the test early if a fatal failure (ASSERT_*) has occurred.
830 test_complete_->Set();
831 }
832 CriticalSectionScoped lock(crit_sect_.get());
833 if (!codec_registered_ &&
834 receive_packet_count_ > kRegisterAfterNumPackets) {
835 // Register the iSAC encoder.
836 EXPECT_EQ(0, acm_->RegisterSendCodec(codec_));
837 codec_registered_ = true;
838 }
839 if (codec_registered_ && receive_packet_count_ > kNumPackets) {
840 test_complete_->Set();
841 }
842 return true;
843 }
844
845 rtc::PlatformThread receive_thread_;
846 rtc::PlatformThread codec_registration_thread_;
847 const rtc::scoped_ptr<EventWrapper> test_complete_;
848 const rtc::scoped_ptr<CriticalSectionWrapper> crit_sect_;
849 bool codec_registered_ GUARDED_BY(crit_sect_);
850 int receive_packet_count_ GUARDED_BY(crit_sect_);
851 int64_t next_insert_packet_time_ms_ GUARDED_BY(crit_sect_);
852 rtc::scoped_ptr<AudioEncoderIsac> isac_encoder_;
853 rtc::scoped_ptr<SimulatedClock> fake_clock_;
854 test::AudioLoop audio_loop_;
855 };
856
857 #if defined(WEBRTC_IOS)
858 #define MAYBE_DoTest DISABLED_DoTest
859 #else
860 #define MAYBE_DoTest DoTest
861 #endif
862 #if defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX)
TEST_F(AcmReRegisterIsacMtTestOldApi,MAYBE_DoTest)863 TEST_F(AcmReRegisterIsacMtTestOldApi, MAYBE_DoTest) {
864 EXPECT_EQ(kEventSignaled, RunTest());
865 }
866 #endif
867
868 // Disabling all of these tests on iOS until file support has been added.
869 // See https://code.google.com/p/webrtc/issues/detail?id=4752 for details.
870 #if !defined(WEBRTC_IOS)
871
872 class AcmReceiverBitExactnessOldApi : public ::testing::Test {
873 public:
PlatformChecksum(std::string others,std::string win64,std::string android_arm32,std::string android_arm64)874 static std::string PlatformChecksum(std::string others,
875 std::string win64,
876 std::string android_arm32,
877 std::string android_arm64) {
878 #if defined(_WIN32) && defined(WEBRTC_ARCH_64_BITS)
879 return win64;
880 #elif defined(WEBRTC_ANDROID) && defined(WEBRTC_ARCH_ARM)
881 return android_arm32;
882 #elif defined(WEBRTC_ANDROID) && defined(WEBRTC_ARCH_ARM64)
883 return android_arm64;
884 #else
885 return others;
886 #endif
887 }
888
889 protected:
890 struct ExternalDecoder {
891 int rtp_payload_type;
892 AudioDecoder* external_decoder;
893 int sample_rate_hz;
894 int num_channels;
895 std::string name;
896 };
897
Run(int output_freq_hz,const std::string & checksum_ref,const std::vector<ExternalDecoder> & external_decoders)898 void Run(int output_freq_hz,
899 const std::string& checksum_ref,
900 const std::vector<ExternalDecoder>& external_decoders) {
901 const std::string input_file_name =
902 webrtc::test::ResourcePath("audio_coding/neteq_universal_new", "rtp");
903 rtc::scoped_ptr<test::RtpFileSource> packet_source(
904 test::RtpFileSource::Create(input_file_name));
905 #ifdef WEBRTC_ANDROID
906 // Filter out iLBC and iSAC-swb since they are not supported on Android.
907 packet_source->FilterOutPayloadType(102); // iLBC.
908 packet_source->FilterOutPayloadType(104); // iSAC-swb.
909 #endif
910
911 test::AudioChecksum checksum;
912 const std::string output_file_name =
913 webrtc::test::OutputPath() +
914 ::testing::UnitTest::GetInstance()
915 ->current_test_info()
916 ->test_case_name() +
917 "_" + ::testing::UnitTest::GetInstance()->current_test_info()->name() +
918 "_output.pcm";
919 test::OutputAudioFile output_file(output_file_name);
920 test::AudioSinkFork output(&checksum, &output_file);
921
922 test::AcmReceiveTestOldApi test(
923 packet_source.get(),
924 &output,
925 output_freq_hz,
926 test::AcmReceiveTestOldApi::kArbitraryChannels);
927 ASSERT_NO_FATAL_FAILURE(test.RegisterNetEqTestCodecs());
928 for (const auto& ed : external_decoders) {
929 ASSERT_EQ(0, test.RegisterExternalReceiveCodec(
930 ed.rtp_payload_type, ed.external_decoder,
931 ed.sample_rate_hz, ed.num_channels, ed.name));
932 }
933 test.Run();
934
935 std::string checksum_string = checksum.Finish();
936 EXPECT_EQ(checksum_ref, checksum_string);
937
938 // Delete the output file.
939 remove(output_file_name.c_str());
940 }
941 };
942
943 #if (defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX)) && \
944 defined(WEBRTC_CODEC_ILBC) && defined(WEBRTC_CODEC_G722)
945 TEST_F(AcmReceiverBitExactnessOldApi, 8kHzOutput) {
946 Run(8000, PlatformChecksum("908002dc01fc4eb1d2be24eb1d3f354b",
947 "dcee98c623b147ebe1b40dd30efa896e",
948 "adc92e173f908f93b96ba5844209815a",
949 "ba16137d3a5a1e637252289c57522bfe"),
950 std::vector<ExternalDecoder>());
951 }
952
953 TEST_F(AcmReceiverBitExactnessOldApi, 16kHzOutput) {
954 Run(16000, PlatformChecksum("a909560b5ca49fa472b17b7b277195e9",
955 "f790e7a8cce4e2c8b7bb5e0e4c5dac0d",
956 "8cffa6abcb3e18e33b9d857666dff66a",
957 "66ee001e23534d4dcf5d0f81f916c93b"),
958 std::vector<ExternalDecoder>());
959 }
960
961 TEST_F(AcmReceiverBitExactnessOldApi, 32kHzOutput) {
962 Run(32000, PlatformChecksum("441aab4b347fb3db4e9244337aca8d8e",
963 "306e0d990ee6e92de3fbecc0123ece37",
964 "3e126fe894720c3f85edadcc91964ba5",
965 "9c6ff204b14152c48fe41d5ab757943b"),
966 std::vector<ExternalDecoder>());
967 }
968
969 TEST_F(AcmReceiverBitExactnessOldApi, 48kHzOutput) {
970 Run(48000, PlatformChecksum("4ee2730fa1daae755e8a8fd3abd779ec",
971 "aa7c232f63a67b2a72703593bdd172e0",
972 "0155665e93067c4e89256b944dd11999",
973 "fc4f0da8844cd808d822bbddf3b9c285"),
974 std::vector<ExternalDecoder>());
975 }
976
977 TEST_F(AcmReceiverBitExactnessOldApi, 48kHzOutputExternalDecoder) {
978 // Class intended to forward a call from a mock DecodeInternal to Decode on
979 // the real decoder's Decode. DecodeInternal for the real decoder isn't
980 // public.
981 class DecodeForwarder {
982 public:
DecodeForwarder(AudioDecoder * decoder)983 DecodeForwarder(AudioDecoder* decoder) : decoder_(decoder) {}
Decode(const uint8_t * encoded,size_t encoded_len,int sample_rate_hz,int16_t * decoded,AudioDecoder::SpeechType * speech_type)984 int Decode(const uint8_t* encoded,
985 size_t encoded_len,
986 int sample_rate_hz,
987 int16_t* decoded,
988 AudioDecoder::SpeechType* speech_type) {
989 return decoder_->Decode(encoded, encoded_len, sample_rate_hz,
990 decoder_->PacketDuration(encoded, encoded_len) *
991 decoder_->Channels() * sizeof(int16_t),
992 decoded, speech_type);
993 }
994
995 private:
996 AudioDecoder* const decoder_;
997 };
998
999 AudioDecoderPcmU decoder(1);
1000 DecodeForwarder decode_forwarder(&decoder);
1001 MockAudioDecoder mock_decoder;
1002 // Set expectations on the mock decoder and also delegate the calls to the
1003 // real decoder.
1004 EXPECT_CALL(mock_decoder, IncomingPacket(_, _, _, _, _))
1005 .Times(AtLeast(1))
1006 .WillRepeatedly(Invoke(&decoder, &AudioDecoderPcmU::IncomingPacket));
1007 EXPECT_CALL(mock_decoder, Channels())
1008 .Times(AtLeast(1))
1009 .WillRepeatedly(Invoke(&decoder, &AudioDecoderPcmU::Channels));
1010 EXPECT_CALL(mock_decoder, DecodeInternal(_, _, _, _, _))
1011 .Times(AtLeast(1))
1012 .WillRepeatedly(Invoke(&decode_forwarder, &DecodeForwarder::Decode));
1013 EXPECT_CALL(mock_decoder, HasDecodePlc())
1014 .Times(AtLeast(1))
1015 .WillRepeatedly(Invoke(&decoder, &AudioDecoderPcmU::HasDecodePlc));
1016 EXPECT_CALL(mock_decoder, PacketDuration(_, _))
1017 .Times(AtLeast(1))
1018 .WillRepeatedly(Invoke(&decoder, &AudioDecoderPcmU::PacketDuration));
1019 ExternalDecoder ed;
1020 ed.rtp_payload_type = 0;
1021 ed.external_decoder = &mock_decoder;
1022 ed.sample_rate_hz = 8000;
1023 ed.num_channels = 1;
1024 ed.name = "MockPCMU";
1025 std::vector<ExternalDecoder> external_decoders;
1026 external_decoders.push_back(ed);
1027
1028 Run(48000, PlatformChecksum("4ee2730fa1daae755e8a8fd3abd779ec",
1029 "aa7c232f63a67b2a72703593bdd172e0",
1030 "0155665e93067c4e89256b944dd11999",
1031 "fc4f0da8844cd808d822bbddf3b9c285"),
1032 external_decoders);
1033
1034 EXPECT_CALL(mock_decoder, Die());
1035 }
1036 #endif
1037
1038 // This test verifies bit exactness for the send-side of ACM. The test setup is
1039 // a chain of three different test classes:
1040 //
1041 // test::AcmSendTest -> AcmSenderBitExactness -> test::AcmReceiveTest
1042 //
1043 // The receiver side is driving the test by requesting new packets from
1044 // AcmSenderBitExactness::NextPacket(). This method, in turn, asks for the
1045 // packet from test::AcmSendTest::NextPacket, which inserts audio from the
1046 // input file until one packet is produced. (The input file loops indefinitely.)
1047 // Before passing the packet to the receiver, this test class verifies the
1048 // packet header and updates a payload checksum with the new payload. The
1049 // decoded output from the receiver is also verified with a (separate) checksum.
1050 class AcmSenderBitExactnessOldApi : public ::testing::Test,
1051 public test::PacketSource {
1052 protected:
1053 static const int kTestDurationMs = 1000;
1054
AcmSenderBitExactnessOldApi()1055 AcmSenderBitExactnessOldApi()
1056 : frame_size_rtp_timestamps_(0),
1057 packet_count_(0),
1058 payload_type_(0),
1059 last_sequence_number_(0),
1060 last_timestamp_(0) {}
1061
1062 // Sets up the test::AcmSendTest object. Returns true on success, otherwise
1063 // false.
SetUpSender()1064 bool SetUpSender() {
1065 const std::string input_file_name =
1066 webrtc::test::ResourcePath("audio_coding/testfile32kHz", "pcm");
1067 // Note that |audio_source_| will loop forever. The test duration is set
1068 // explicitly by |kTestDurationMs|.
1069 audio_source_.reset(new test::InputAudioFile(input_file_name));
1070 static const int kSourceRateHz = 32000;
1071 send_test_.reset(new test::AcmSendTestOldApi(
1072 audio_source_.get(), kSourceRateHz, kTestDurationMs));
1073 return send_test_.get() != NULL;
1074 }
1075
1076 // Registers a send codec in the test::AcmSendTest object. Returns true on
1077 // success, false on failure.
RegisterSendCodec(const char * payload_name,int sampling_freq_hz,int channels,int payload_type,int frame_size_samples,int frame_size_rtp_timestamps)1078 bool RegisterSendCodec(const char* payload_name,
1079 int sampling_freq_hz,
1080 int channels,
1081 int payload_type,
1082 int frame_size_samples,
1083 int frame_size_rtp_timestamps) {
1084 payload_type_ = payload_type;
1085 frame_size_rtp_timestamps_ = frame_size_rtp_timestamps;
1086 return send_test_->RegisterCodec(payload_name,
1087 sampling_freq_hz,
1088 channels,
1089 payload_type,
1090 frame_size_samples);
1091 }
1092
RegisterExternalSendCodec(AudioEncoder * external_speech_encoder,int payload_type)1093 bool RegisterExternalSendCodec(AudioEncoder* external_speech_encoder,
1094 int payload_type) {
1095 payload_type_ = payload_type;
1096 frame_size_rtp_timestamps_ =
1097 external_speech_encoder->Num10MsFramesInNextPacket() *
1098 external_speech_encoder->RtpTimestampRateHz() / 100;
1099 return send_test_->RegisterExternalCodec(external_speech_encoder);
1100 }
1101
1102 // Runs the test. SetUpSender() and RegisterSendCodec() must have been called
1103 // before calling this method.
Run(const std::string & audio_checksum_ref,const std::string & payload_checksum_ref,int expected_packets,test::AcmReceiveTestOldApi::NumOutputChannels expected_channels)1104 void Run(const std::string& audio_checksum_ref,
1105 const std::string& payload_checksum_ref,
1106 int expected_packets,
1107 test::AcmReceiveTestOldApi::NumOutputChannels expected_channels) {
1108 // Set up the receiver used to decode the packets and verify the decoded
1109 // output.
1110 test::AudioChecksum audio_checksum;
1111 const std::string output_file_name =
1112 webrtc::test::OutputPath() +
1113 ::testing::UnitTest::GetInstance()
1114 ->current_test_info()
1115 ->test_case_name() +
1116 "_" + ::testing::UnitTest::GetInstance()->current_test_info()->name() +
1117 "_output.pcm";
1118 test::OutputAudioFile output_file(output_file_name);
1119 // Have the output audio sent both to file and to the checksum calculator.
1120 test::AudioSinkFork output(&audio_checksum, &output_file);
1121 const int kOutputFreqHz = 8000;
1122 test::AcmReceiveTestOldApi receive_test(
1123 this, &output, kOutputFreqHz, expected_channels);
1124 ASSERT_NO_FATAL_FAILURE(receive_test.RegisterDefaultCodecs());
1125
1126 // This is where the actual test is executed.
1127 receive_test.Run();
1128
1129 // Extract and verify the audio checksum.
1130 std::string checksum_string = audio_checksum.Finish();
1131 EXPECT_EQ(audio_checksum_ref, checksum_string);
1132
1133 // Extract and verify the payload checksum.
1134 char checksum_result[rtc::Md5Digest::kSize];
1135 payload_checksum_.Finish(checksum_result, rtc::Md5Digest::kSize);
1136 checksum_string = rtc::hex_encode(checksum_result, rtc::Md5Digest::kSize);
1137 EXPECT_EQ(payload_checksum_ref, checksum_string);
1138
1139 // Verify number of packets produced.
1140 EXPECT_EQ(expected_packets, packet_count_);
1141
1142 // Delete the output file.
1143 remove(output_file_name.c_str());
1144 }
1145
1146 // Returns a pointer to the next packet. Returns NULL if the source is
1147 // depleted (i.e., the test duration is exceeded), or if an error occurred.
1148 // Inherited from test::PacketSource.
NextPacket()1149 test::Packet* NextPacket() override {
1150 // Get the next packet from AcmSendTest. Ownership of |packet| is
1151 // transferred to this method.
1152 test::Packet* packet = send_test_->NextPacket();
1153 if (!packet)
1154 return NULL;
1155
1156 VerifyPacket(packet);
1157 // TODO(henrik.lundin) Save the packet to file as well.
1158
1159 // Pass it on to the caller. The caller becomes the owner of |packet|.
1160 return packet;
1161 }
1162
1163 // Verifies the packet.
VerifyPacket(const test::Packet * packet)1164 void VerifyPacket(const test::Packet* packet) {
1165 EXPECT_TRUE(packet->valid_header());
1166 // (We can check the header fields even if valid_header() is false.)
1167 EXPECT_EQ(payload_type_, packet->header().payloadType);
1168 if (packet_count_ > 0) {
1169 // This is not the first packet.
1170 uint16_t sequence_number_diff =
1171 packet->header().sequenceNumber - last_sequence_number_;
1172 EXPECT_EQ(1, sequence_number_diff);
1173 uint32_t timestamp_diff = packet->header().timestamp - last_timestamp_;
1174 EXPECT_EQ(frame_size_rtp_timestamps_, timestamp_diff);
1175 }
1176 ++packet_count_;
1177 last_sequence_number_ = packet->header().sequenceNumber;
1178 last_timestamp_ = packet->header().timestamp;
1179 // Update the checksum.
1180 payload_checksum_.Update(packet->payload(), packet->payload_length_bytes());
1181 }
1182
SetUpTest(const char * codec_name,int codec_sample_rate_hz,int channels,int payload_type,int codec_frame_size_samples,int codec_frame_size_rtp_timestamps)1183 void SetUpTest(const char* codec_name,
1184 int codec_sample_rate_hz,
1185 int channels,
1186 int payload_type,
1187 int codec_frame_size_samples,
1188 int codec_frame_size_rtp_timestamps) {
1189 ASSERT_TRUE(SetUpSender());
1190 ASSERT_TRUE(RegisterSendCodec(codec_name,
1191 codec_sample_rate_hz,
1192 channels,
1193 payload_type,
1194 codec_frame_size_samples,
1195 codec_frame_size_rtp_timestamps));
1196 }
1197
SetUpTestExternalEncoder(AudioEncoder * external_speech_encoder,int payload_type)1198 void SetUpTestExternalEncoder(AudioEncoder* external_speech_encoder,
1199 int payload_type) {
1200 ASSERT_TRUE(SetUpSender());
1201 ASSERT_TRUE(
1202 RegisterExternalSendCodec(external_speech_encoder, payload_type));
1203 }
1204
1205 rtc::scoped_ptr<test::AcmSendTestOldApi> send_test_;
1206 rtc::scoped_ptr<test::InputAudioFile> audio_source_;
1207 uint32_t frame_size_rtp_timestamps_;
1208 int packet_count_;
1209 uint8_t payload_type_;
1210 uint16_t last_sequence_number_;
1211 uint32_t last_timestamp_;
1212 rtc::Md5Digest payload_checksum_;
1213 };
1214
1215 #if defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX)
TEST_F(AcmSenderBitExactnessOldApi,IsacWb30ms)1216 TEST_F(AcmSenderBitExactnessOldApi, IsacWb30ms) {
1217 ASSERT_NO_FATAL_FAILURE(SetUpTest("ISAC", 16000, 1, 103, 480, 480));
1218 Run(AcmReceiverBitExactnessOldApi::PlatformChecksum(
1219 "0b58f9eeee43d5891f5f6c75e77984a3",
1220 "c7e5bdadfa2871df95639fcc297cf23d",
1221 "0499ca260390769b3172136faad925b9",
1222 "866abf524acd2807efbe65e133c23f95"),
1223 AcmReceiverBitExactnessOldApi::PlatformChecksum(
1224 "3c79f16f34218271f3dca4e2b1dfe1bb",
1225 "d42cb5195463da26c8129bbfe73a22e6",
1226 "83de248aea9c3c2bd680b6952401b4ca",
1227 "3c79f16f34218271f3dca4e2b1dfe1bb"),
1228 33, test::AcmReceiveTestOldApi::kMonoOutput);
1229 }
1230
TEST_F(AcmSenderBitExactnessOldApi,IsacWb60ms)1231 TEST_F(AcmSenderBitExactnessOldApi, IsacWb60ms) {
1232 ASSERT_NO_FATAL_FAILURE(SetUpTest("ISAC", 16000, 1, 103, 960, 960));
1233 Run(AcmReceiverBitExactnessOldApi::PlatformChecksum(
1234 "1ad29139a04782a33daad8c2b9b35875",
1235 "14d63c5f08127d280e722e3191b73bdd",
1236 "8da003e16c5371af2dc2be79a50f9076",
1237 "ef75e900e6f375e3061163c53fd09a63"),
1238 AcmReceiverBitExactnessOldApi::PlatformChecksum(
1239 "9e0a0ab743ad987b55b8e14802769c56",
1240 "ebe04a819d3a9d83a83a17f271e1139a",
1241 "97aeef98553b5a4b5a68f8b716e8eaf0",
1242 "9e0a0ab743ad987b55b8e14802769c56"),
1243 16, test::AcmReceiveTestOldApi::kMonoOutput);
1244 }
1245 #endif
1246
1247 #if defined(WEBRTC_ANDROID)
1248 #define MAYBE_IsacSwb30ms DISABLED_IsacSwb30ms
1249 #else
1250 #define MAYBE_IsacSwb30ms IsacSwb30ms
1251 #endif
1252 #if defined(WEBRTC_CODEC_ISAC)
TEST_F(AcmSenderBitExactnessOldApi,MAYBE_IsacSwb30ms)1253 TEST_F(AcmSenderBitExactnessOldApi, MAYBE_IsacSwb30ms) {
1254 ASSERT_NO_FATAL_FAILURE(SetUpTest("ISAC", 32000, 1, 104, 960, 960));
1255 Run(AcmReceiverBitExactnessOldApi::PlatformChecksum(
1256 "5683b58da0fbf2063c7adc2e6bfb3fb8",
1257 "2b3c387d06f00b7b7aad4c9be56fb83d", "android_arm32_audio",
1258 "android_arm64_audio"),
1259 AcmReceiverBitExactnessOldApi::PlatformChecksum(
1260 "ce86106a93419aefb063097108ec94ab",
1261 "bcc2041e7744c7ebd9f701866856849c", "android_arm32_payload",
1262 "android_arm64_payload"),
1263 33, test::AcmReceiveTestOldApi::kMonoOutput);
1264 }
1265 #endif
1266
TEST_F(AcmSenderBitExactnessOldApi,Pcm16_8000khz_10ms)1267 TEST_F(AcmSenderBitExactnessOldApi, Pcm16_8000khz_10ms) {
1268 ASSERT_NO_FATAL_FAILURE(SetUpTest("L16", 8000, 1, 107, 80, 80));
1269 Run("de4a98e1406f8b798d99cd0704e862e2",
1270 "c1edd36339ce0326cc4550041ad719a0",
1271 100,
1272 test::AcmReceiveTestOldApi::kMonoOutput);
1273 }
1274
TEST_F(AcmSenderBitExactnessOldApi,Pcm16_16000khz_10ms)1275 TEST_F(AcmSenderBitExactnessOldApi, Pcm16_16000khz_10ms) {
1276 ASSERT_NO_FATAL_FAILURE(SetUpTest("L16", 16000, 1, 108, 160, 160));
1277 Run("ae646d7b68384a1269cc080dd4501916",
1278 "ad786526383178b08d80d6eee06e9bad",
1279 100,
1280 test::AcmReceiveTestOldApi::kMonoOutput);
1281 }
1282
TEST_F(AcmSenderBitExactnessOldApi,Pcm16_32000khz_10ms)1283 TEST_F(AcmSenderBitExactnessOldApi, Pcm16_32000khz_10ms) {
1284 ASSERT_NO_FATAL_FAILURE(SetUpTest("L16", 32000, 1, 109, 320, 320));
1285 Run("7fe325e8fbaf755e3c5df0b11a4774fb",
1286 "5ef82ea885e922263606c6fdbc49f651",
1287 100,
1288 test::AcmReceiveTestOldApi::kMonoOutput);
1289 }
1290
TEST_F(AcmSenderBitExactnessOldApi,Pcm16_stereo_8000khz_10ms)1291 TEST_F(AcmSenderBitExactnessOldApi, Pcm16_stereo_8000khz_10ms) {
1292 ASSERT_NO_FATAL_FAILURE(SetUpTest("L16", 8000, 2, 111, 80, 80));
1293 Run("fb263b74e7ac3de915474d77e4744ceb",
1294 "62ce5adb0d4965d0a52ec98ae7f98974",
1295 100,
1296 test::AcmReceiveTestOldApi::kStereoOutput);
1297 }
1298
TEST_F(AcmSenderBitExactnessOldApi,Pcm16_stereo_16000khz_10ms)1299 TEST_F(AcmSenderBitExactnessOldApi, Pcm16_stereo_16000khz_10ms) {
1300 ASSERT_NO_FATAL_FAILURE(SetUpTest("L16", 16000, 2, 112, 160, 160));
1301 Run("d09e9239553649d7ac93e19d304281fd",
1302 "41ca8edac4b8c71cd54fd9f25ec14870",
1303 100,
1304 test::AcmReceiveTestOldApi::kStereoOutput);
1305 }
1306
TEST_F(AcmSenderBitExactnessOldApi,Pcm16_stereo_32000khz_10ms)1307 TEST_F(AcmSenderBitExactnessOldApi, Pcm16_stereo_32000khz_10ms) {
1308 ASSERT_NO_FATAL_FAILURE(SetUpTest("L16", 32000, 2, 113, 320, 320));
1309 Run("5f025d4f390982cc26b3d92fe02e3044",
1310 "50e58502fb04421bf5b857dda4c96879",
1311 100,
1312 test::AcmReceiveTestOldApi::kStereoOutput);
1313 }
1314
TEST_F(AcmSenderBitExactnessOldApi,Pcmu_20ms)1315 TEST_F(AcmSenderBitExactnessOldApi, Pcmu_20ms) {
1316 ASSERT_NO_FATAL_FAILURE(SetUpTest("PCMU", 8000, 1, 0, 160, 160));
1317 Run("81a9d4c0bb72e9becc43aef124c981e9",
1318 "8f9b8750bd80fe26b6cbf6659b89f0f9",
1319 50,
1320 test::AcmReceiveTestOldApi::kMonoOutput);
1321 }
1322
TEST_F(AcmSenderBitExactnessOldApi,Pcma_20ms)1323 TEST_F(AcmSenderBitExactnessOldApi, Pcma_20ms) {
1324 ASSERT_NO_FATAL_FAILURE(SetUpTest("PCMA", 8000, 1, 8, 160, 160));
1325 Run("39611f798969053925a49dc06d08de29",
1326 "6ad745e55aa48981bfc790d0eeef2dd1",
1327 50,
1328 test::AcmReceiveTestOldApi::kMonoOutput);
1329 }
1330
TEST_F(AcmSenderBitExactnessOldApi,Pcmu_stereo_20ms)1331 TEST_F(AcmSenderBitExactnessOldApi, Pcmu_stereo_20ms) {
1332 ASSERT_NO_FATAL_FAILURE(SetUpTest("PCMU", 8000, 2, 110, 160, 160));
1333 Run("437bec032fdc5cbaa0d5175430af7b18",
1334 "60b6f25e8d1e74cb679cfe756dd9bca5",
1335 50,
1336 test::AcmReceiveTestOldApi::kStereoOutput);
1337 }
1338
TEST_F(AcmSenderBitExactnessOldApi,Pcma_stereo_20ms)1339 TEST_F(AcmSenderBitExactnessOldApi, Pcma_stereo_20ms) {
1340 ASSERT_NO_FATAL_FAILURE(SetUpTest("PCMA", 8000, 2, 118, 160, 160));
1341 Run("a5c6d83c5b7cedbeff734238220a4b0c",
1342 "92b282c83efd20e7eeef52ba40842cf7",
1343 50,
1344 test::AcmReceiveTestOldApi::kStereoOutput);
1345 }
1346
1347 #if defined(WEBRTC_ANDROID)
1348 #define MAYBE_Ilbc_30ms DISABLED_Ilbc_30ms
1349 #else
1350 #define MAYBE_Ilbc_30ms Ilbc_30ms
1351 #endif
1352 #if defined(WEBRTC_CODEC_ILBC)
TEST_F(AcmSenderBitExactnessOldApi,MAYBE_Ilbc_30ms)1353 TEST_F(AcmSenderBitExactnessOldApi, MAYBE_Ilbc_30ms) {
1354 ASSERT_NO_FATAL_FAILURE(SetUpTest("ILBC", 8000, 1, 102, 240, 240));
1355 Run(AcmReceiverBitExactnessOldApi::PlatformChecksum(
1356 "7b6ec10910debd9af08011d3ed5249f7",
1357 "7b6ec10910debd9af08011d3ed5249f7", "android_arm32_audio",
1358 "android_arm64_audio"),
1359 AcmReceiverBitExactnessOldApi::PlatformChecksum(
1360 "cfae2e9f6aba96e145f2bcdd5050ce78",
1361 "cfae2e9f6aba96e145f2bcdd5050ce78", "android_arm32_payload",
1362 "android_arm64_payload"),
1363 33, test::AcmReceiveTestOldApi::kMonoOutput);
1364 }
1365 #endif
1366
1367 #if defined(WEBRTC_ANDROID)
1368 #define MAYBE_G722_20ms DISABLED_G722_20ms
1369 #else
1370 #define MAYBE_G722_20ms G722_20ms
1371 #endif
1372 #if defined(WEBRTC_CODEC_G722)
TEST_F(AcmSenderBitExactnessOldApi,MAYBE_G722_20ms)1373 TEST_F(AcmSenderBitExactnessOldApi, MAYBE_G722_20ms) {
1374 ASSERT_NO_FATAL_FAILURE(SetUpTest("G722", 16000, 1, 9, 320, 160));
1375 Run(AcmReceiverBitExactnessOldApi::PlatformChecksum(
1376 "7d759436f2533582950d148b5161a36c",
1377 "7d759436f2533582950d148b5161a36c", "android_arm32_audio",
1378 "android_arm64_audio"),
1379 AcmReceiverBitExactnessOldApi::PlatformChecksum(
1380 "fc68a87e1380614e658087cb35d5ca10",
1381 "fc68a87e1380614e658087cb35d5ca10", "android_arm32_payload",
1382 "android_arm64_payload"),
1383 50, test::AcmReceiveTestOldApi::kMonoOutput);
1384 }
1385 #endif
1386
1387 #if defined(WEBRTC_ANDROID)
1388 #define MAYBE_G722_stereo_20ms DISABLED_G722_stereo_20ms
1389 #else
1390 #define MAYBE_G722_stereo_20ms G722_stereo_20ms
1391 #endif
1392 #if defined(WEBRTC_CODEC_G722)
TEST_F(AcmSenderBitExactnessOldApi,MAYBE_G722_stereo_20ms)1393 TEST_F(AcmSenderBitExactnessOldApi, MAYBE_G722_stereo_20ms) {
1394 ASSERT_NO_FATAL_FAILURE(SetUpTest("G722", 16000, 2, 119, 320, 160));
1395 Run(AcmReceiverBitExactnessOldApi::PlatformChecksum(
1396 "7190ee718ab3d80eca181e5f7140c210",
1397 "7190ee718ab3d80eca181e5f7140c210", "android_arm32_audio",
1398 "android_arm64_audio"),
1399 AcmReceiverBitExactnessOldApi::PlatformChecksum(
1400 "66516152eeaa1e650ad94ff85f668dac",
1401 "66516152eeaa1e650ad94ff85f668dac", "android_arm32_payload",
1402 "android_arm64_payload"),
1403 50, test::AcmReceiveTestOldApi::kStereoOutput);
1404 }
1405 #endif
1406
TEST_F(AcmSenderBitExactnessOldApi,Opus_stereo_20ms)1407 TEST_F(AcmSenderBitExactnessOldApi, Opus_stereo_20ms) {
1408 ASSERT_NO_FATAL_FAILURE(SetUpTest("opus", 48000, 2, 120, 960, 960));
1409 Run(AcmReceiverBitExactnessOldApi::PlatformChecksum(
1410 "855041f2490b887302bce9d544731849",
1411 "855041f2490b887302bce9d544731849",
1412 "1e1a0fce893fef2d66886a7f09e2ebce",
1413 "7417a66c28be42d5d9b2d64e0c191585"),
1414 AcmReceiverBitExactnessOldApi::PlatformChecksum(
1415 "d781cce1ab986b618d0da87226cdde30",
1416 "d781cce1ab986b618d0da87226cdde30",
1417 "1a1fe04dd12e755949987c8d729fb3e0",
1418 "47b0b04f1d03076b857c86c72c2c298b"),
1419 50, test::AcmReceiveTestOldApi::kStereoOutput);
1420 }
1421
TEST_F(AcmSenderBitExactnessOldApi,Opus_stereo_20ms_voip)1422 TEST_F(AcmSenderBitExactnessOldApi, Opus_stereo_20ms_voip) {
1423 ASSERT_NO_FATAL_FAILURE(SetUpTest("opus", 48000, 2, 120, 960, 960));
1424 // If not set, default will be kAudio in case of stereo.
1425 EXPECT_EQ(0, send_test_->acm()->SetOpusApplication(kVoip));
1426 Run(AcmReceiverBitExactnessOldApi::PlatformChecksum(
1427 "9b9e12bc3cc793740966e11cbfa8b35b",
1428 "9b9e12bc3cc793740966e11cbfa8b35b",
1429 "57412a4b5771d19ff03ec35deffe7067",
1430 "7ad0bbefcaa87e23187bf4a56d2f3513"),
1431 AcmReceiverBitExactnessOldApi::PlatformChecksum(
1432 "c7340b1189652ab6b5e80dade7390cb4",
1433 "c7340b1189652ab6b5e80dade7390cb4",
1434 "cdfe85939c411d12b61701c566e22d26",
1435 "7a678fbe46df5bf0c67e88264a2d9275"),
1436 50, test::AcmReceiveTestOldApi::kStereoOutput);
1437 }
1438
1439 // This test is for verifying the SetBitRate function. The bitrate is changed at
1440 // the beginning, and the number of generated bytes are checked.
1441 class AcmSetBitRateOldApi : public ::testing::Test {
1442 protected:
1443 static const int kTestDurationMs = 1000;
1444
1445 // Sets up the test::AcmSendTest object. Returns true on success, otherwise
1446 // false.
SetUpSender()1447 bool SetUpSender() {
1448 const std::string input_file_name =
1449 webrtc::test::ResourcePath("audio_coding/testfile32kHz", "pcm");
1450 // Note that |audio_source_| will loop forever. The test duration is set
1451 // explicitly by |kTestDurationMs|.
1452 audio_source_.reset(new test::InputAudioFile(input_file_name));
1453 static const int kSourceRateHz = 32000;
1454 send_test_.reset(new test::AcmSendTestOldApi(
1455 audio_source_.get(), kSourceRateHz, kTestDurationMs));
1456 return send_test_.get();
1457 }
1458
1459 // Registers a send codec in the test::AcmSendTest object. Returns true on
1460 // success, false on failure.
RegisterSendCodec(const char * payload_name,int sampling_freq_hz,int channels,int payload_type,int frame_size_samples,int frame_size_rtp_timestamps)1461 virtual bool RegisterSendCodec(const char* payload_name,
1462 int sampling_freq_hz,
1463 int channels,
1464 int payload_type,
1465 int frame_size_samples,
1466 int frame_size_rtp_timestamps) {
1467 return send_test_->RegisterCodec(payload_name, sampling_freq_hz, channels,
1468 payload_type, frame_size_samples);
1469 }
1470
1471 // Runs the test. SetUpSender() and RegisterSendCodec() must have been called
1472 // before calling this method.
Run(int target_bitrate_bps,int expected_total_bits)1473 void Run(int target_bitrate_bps, int expected_total_bits) {
1474 ASSERT_TRUE(send_test_->acm());
1475 send_test_->acm()->SetBitRate(target_bitrate_bps);
1476 int nr_bytes = 0;
1477 while (test::Packet* next_packet = send_test_->NextPacket()) {
1478 nr_bytes += next_packet->payload_length_bytes();
1479 delete next_packet;
1480 }
1481 EXPECT_EQ(expected_total_bits, nr_bytes * 8);
1482 }
1483
SetUpTest(const char * codec_name,int codec_sample_rate_hz,int channels,int payload_type,int codec_frame_size_samples,int codec_frame_size_rtp_timestamps)1484 void SetUpTest(const char* codec_name,
1485 int codec_sample_rate_hz,
1486 int channels,
1487 int payload_type,
1488 int codec_frame_size_samples,
1489 int codec_frame_size_rtp_timestamps) {
1490 ASSERT_TRUE(SetUpSender());
1491 ASSERT_TRUE(RegisterSendCodec(codec_name, codec_sample_rate_hz, channels,
1492 payload_type, codec_frame_size_samples,
1493 codec_frame_size_rtp_timestamps));
1494 }
1495
1496 rtc::scoped_ptr<test::AcmSendTestOldApi> send_test_;
1497 rtc::scoped_ptr<test::InputAudioFile> audio_source_;
1498 };
1499
TEST_F(AcmSetBitRateOldApi,Opus_48khz_20ms_10kbps)1500 TEST_F(AcmSetBitRateOldApi, Opus_48khz_20ms_10kbps) {
1501 ASSERT_NO_FATAL_FAILURE(SetUpTest("opus", 48000, 1, 107, 960, 960));
1502 #if defined(WEBRTC_ANDROID)
1503 Run(10000, 9328);
1504 #else
1505 Run(10000, 9072);
1506 #endif // WEBRTC_ANDROID
1507
1508 }
1509
TEST_F(AcmSetBitRateOldApi,Opus_48khz_20ms_50kbps)1510 TEST_F(AcmSetBitRateOldApi, Opus_48khz_20ms_50kbps) {
1511 ASSERT_NO_FATAL_FAILURE(SetUpTest("opus", 48000, 1, 107, 960, 960));
1512 #if defined(WEBRTC_ANDROID)
1513 Run(50000, 47952);
1514 #else
1515 Run(50000, 49600);
1516 #endif // WEBRTC_ANDROID
1517 }
1518
1519 // The result on the Android platforms is inconsistent for this test case.
1520 // On android_rel the result is different from android and android arm64 rel.
1521 #if defined(WEBRTC_ANDROID)
1522 #define MAYBE_Opus_48khz_20ms_100kbps DISABLED_Opus_48khz_20ms_100kbps
1523 #else
1524 #define MAYBE_Opus_48khz_20ms_100kbps Opus_48khz_20ms_100kbps
1525 #endif
TEST_F(AcmSetBitRateOldApi,MAYBE_Opus_48khz_20ms_100kbps)1526 TEST_F(AcmSetBitRateOldApi, MAYBE_Opus_48khz_20ms_100kbps) {
1527 ASSERT_NO_FATAL_FAILURE(SetUpTest("opus", 48000, 1, 107, 960, 960));
1528 Run(100000, 100888);
1529 }
1530
1531 // These next 2 tests ensure that the SetBitRate function has no effect on PCM
TEST_F(AcmSetBitRateOldApi,Pcm16_8khz_10ms_8kbps)1532 TEST_F(AcmSetBitRateOldApi, Pcm16_8khz_10ms_8kbps) {
1533 ASSERT_NO_FATAL_FAILURE(SetUpTest("L16", 8000, 1, 107, 80, 80));
1534 Run(8000, 128000);
1535 }
1536
TEST_F(AcmSetBitRateOldApi,Pcm16_8khz_10ms_32kbps)1537 TEST_F(AcmSetBitRateOldApi, Pcm16_8khz_10ms_32kbps) {
1538 ASSERT_NO_FATAL_FAILURE(SetUpTest("L16", 8000, 1, 107, 80, 80));
1539 Run(32000, 128000);
1540 }
1541
1542 // This test is for verifying the SetBitRate function. The bitrate is changed
1543 // in the middle, and the number of generated bytes are before and after the
1544 // change are checked.
1545 class AcmChangeBitRateOldApi : public AcmSetBitRateOldApi {
1546 protected:
AcmChangeBitRateOldApi()1547 AcmChangeBitRateOldApi() : sampling_freq_hz_(0), frame_size_samples_(0) {}
1548
1549 // Registers a send codec in the test::AcmSendTest object. Returns true on
1550 // success, false on failure.
RegisterSendCodec(const char * payload_name,int sampling_freq_hz,int channels,int payload_type,int frame_size_samples,int frame_size_rtp_timestamps)1551 bool RegisterSendCodec(const char* payload_name,
1552 int sampling_freq_hz,
1553 int channels,
1554 int payload_type,
1555 int frame_size_samples,
1556 int frame_size_rtp_timestamps) override {
1557 frame_size_samples_ = frame_size_samples;
1558 sampling_freq_hz_ = sampling_freq_hz;
1559 return AcmSetBitRateOldApi::RegisterSendCodec(
1560 payload_name, sampling_freq_hz, channels, payload_type,
1561 frame_size_samples, frame_size_rtp_timestamps);
1562 }
1563
1564 // Runs the test. SetUpSender() and RegisterSendCodec() must have been called
1565 // before calling this method.
Run(int target_bitrate_bps,int expected_before_switch_bits,int expected_after_switch_bits)1566 void Run(int target_bitrate_bps,
1567 int expected_before_switch_bits,
1568 int expected_after_switch_bits) {
1569 ASSERT_TRUE(send_test_->acm());
1570 int nr_packets =
1571 sampling_freq_hz_ * kTestDurationMs / (frame_size_samples_ * 1000);
1572 int nr_bytes_before = 0, nr_bytes_after = 0;
1573 int packet_counter = 0;
1574 while (test::Packet* next_packet = send_test_->NextPacket()) {
1575 if (packet_counter == nr_packets / 2)
1576 send_test_->acm()->SetBitRate(target_bitrate_bps);
1577 if (packet_counter < nr_packets / 2)
1578 nr_bytes_before += next_packet->payload_length_bytes();
1579 else
1580 nr_bytes_after += next_packet->payload_length_bytes();
1581 packet_counter++;
1582 delete next_packet;
1583 }
1584 EXPECT_EQ(expected_before_switch_bits, nr_bytes_before * 8);
1585 EXPECT_EQ(expected_after_switch_bits, nr_bytes_after * 8);
1586 }
1587
1588 uint32_t sampling_freq_hz_;
1589 uint32_t frame_size_samples_;
1590 };
1591
TEST_F(AcmChangeBitRateOldApi,Opus_48khz_20ms_10kbps)1592 TEST_F(AcmChangeBitRateOldApi, Opus_48khz_20ms_10kbps) {
1593 ASSERT_NO_FATAL_FAILURE(SetUpTest("opus", 48000, 1, 107, 960, 960));
1594 #if defined(WEBRTC_ANDROID)
1595 Run(10000, 32200, 5496);
1596 #else
1597 Run(10000, 32200, 5432);
1598 #endif // WEBRTC_ANDROID
1599 }
1600
TEST_F(AcmChangeBitRateOldApi,Opus_48khz_20ms_50kbps)1601 TEST_F(AcmChangeBitRateOldApi, Opus_48khz_20ms_50kbps) {
1602 ASSERT_NO_FATAL_FAILURE(SetUpTest("opus", 48000, 1, 107, 960, 960));
1603 #if defined(WEBRTC_ANDROID)
1604 Run(50000, 32200, 24912);
1605 #else
1606 Run(50000, 32200, 24792);
1607 #endif // WEBRTC_ANDROID
1608 }
1609
TEST_F(AcmChangeBitRateOldApi,Opus_48khz_20ms_100kbps)1610 TEST_F(AcmChangeBitRateOldApi, Opus_48khz_20ms_100kbps) {
1611 ASSERT_NO_FATAL_FAILURE(SetUpTest("opus", 48000, 1, 107, 960, 960));
1612 #if defined(WEBRTC_ANDROID)
1613 Run(100000, 32200, 51480);
1614 #else
1615 Run(100000, 32200, 50584);
1616 #endif // WEBRTC_ANDROID
1617 }
1618
1619 // These next 2 tests ensure that the SetBitRate function has no effect on PCM
TEST_F(AcmChangeBitRateOldApi,Pcm16_8khz_10ms_8kbps)1620 TEST_F(AcmChangeBitRateOldApi, Pcm16_8khz_10ms_8kbps) {
1621 ASSERT_NO_FATAL_FAILURE(SetUpTest("L16", 8000, 1, 107, 80, 80));
1622 Run(8000, 64000, 64000);
1623 }
1624
TEST_F(AcmChangeBitRateOldApi,Pcm16_8khz_10ms_32kbps)1625 TEST_F(AcmChangeBitRateOldApi, Pcm16_8khz_10ms_32kbps) {
1626 ASSERT_NO_FATAL_FAILURE(SetUpTest("L16", 8000, 1, 107, 80, 80));
1627 Run(32000, 64000, 64000);
1628 }
1629
TEST_F(AcmSenderBitExactnessOldApi,External_Pcmu_20ms)1630 TEST_F(AcmSenderBitExactnessOldApi, External_Pcmu_20ms) {
1631 CodecInst codec_inst;
1632 codec_inst.channels = 1;
1633 codec_inst.pacsize = 160;
1634 codec_inst.pltype = 0;
1635 AudioEncoderPcmU encoder(codec_inst);
1636 MockAudioEncoder mock_encoder;
1637 // Set expectations on the mock encoder and also delegate the calls to the
1638 // real encoder.
1639 EXPECT_CALL(mock_encoder, MaxEncodedBytes())
1640 .Times(AtLeast(1))
1641 .WillRepeatedly(Invoke(&encoder, &AudioEncoderPcmU::MaxEncodedBytes));
1642 EXPECT_CALL(mock_encoder, SampleRateHz())
1643 .Times(AtLeast(1))
1644 .WillRepeatedly(Invoke(&encoder, &AudioEncoderPcmU::SampleRateHz));
1645 EXPECT_CALL(mock_encoder, NumChannels())
1646 .Times(AtLeast(1))
1647 .WillRepeatedly(Invoke(&encoder, &AudioEncoderPcmU::NumChannels));
1648 EXPECT_CALL(mock_encoder, RtpTimestampRateHz())
1649 .Times(AtLeast(1))
1650 .WillRepeatedly(Invoke(&encoder, &AudioEncoderPcmU::RtpTimestampRateHz));
1651 EXPECT_CALL(mock_encoder, Num10MsFramesInNextPacket())
1652 .Times(AtLeast(1))
1653 .WillRepeatedly(
1654 Invoke(&encoder, &AudioEncoderPcmU::Num10MsFramesInNextPacket));
1655 EXPECT_CALL(mock_encoder, GetTargetBitrate())
1656 .Times(AtLeast(1))
1657 .WillRepeatedly(Invoke(&encoder, &AudioEncoderPcmU::GetTargetBitrate));
1658 EXPECT_CALL(mock_encoder, EncodeInternal(_, _, _, _))
1659 .Times(AtLeast(1))
1660 .WillRepeatedly(Invoke(&encoder, &AudioEncoderPcmU::EncodeInternal));
1661 EXPECT_CALL(mock_encoder, SetFec(_))
1662 .Times(AtLeast(1))
1663 .WillRepeatedly(Invoke(&encoder, &AudioEncoderPcmU::SetFec));
1664 ASSERT_NO_FATAL_FAILURE(
1665 SetUpTestExternalEncoder(&mock_encoder, codec_inst.pltype));
1666 Run("81a9d4c0bb72e9becc43aef124c981e9", "8f9b8750bd80fe26b6cbf6659b89f0f9",
1667 50, test::AcmReceiveTestOldApi::kMonoOutput);
1668 }
1669
1670 // This test fixture is implemented to run ACM and change the desired output
1671 // frequency during the call. The input packets are simply PCM16b-wb encoded
1672 // payloads with a constant value of |kSampleValue|. The test fixture itself
1673 // acts as PacketSource in between the receive test class and the constant-
1674 // payload packet source class. The output is both written to file, and analyzed
1675 // in this test fixture.
1676 class AcmSwitchingOutputFrequencyOldApi : public ::testing::Test,
1677 public test::PacketSource,
1678 public test::AudioSink {
1679 protected:
1680 static const size_t kTestNumPackets = 50;
1681 static const int kEncodedSampleRateHz = 16000;
1682 static const size_t kPayloadLenSamples = 30 * kEncodedSampleRateHz / 1000;
1683 static const int kPayloadType = 108; // Default payload type for PCM16b-wb.
1684
AcmSwitchingOutputFrequencyOldApi()1685 AcmSwitchingOutputFrequencyOldApi()
1686 : first_output_(true),
1687 num_packets_(0),
1688 packet_source_(kPayloadLenSamples,
1689 kSampleValue,
1690 kEncodedSampleRateHz,
1691 kPayloadType),
1692 output_freq_2_(0),
1693 has_toggled_(false) {}
1694
Run(int output_freq_1,int output_freq_2,int toggle_period_ms)1695 void Run(int output_freq_1, int output_freq_2, int toggle_period_ms) {
1696 // Set up the receiver used to decode the packets and verify the decoded
1697 // output.
1698 const std::string output_file_name =
1699 webrtc::test::OutputPath() +
1700 ::testing::UnitTest::GetInstance()
1701 ->current_test_info()
1702 ->test_case_name() +
1703 "_" + ::testing::UnitTest::GetInstance()->current_test_info()->name() +
1704 "_output.pcm";
1705 test::OutputAudioFile output_file(output_file_name);
1706 // Have the output audio sent both to file and to the WriteArray method in
1707 // this class.
1708 test::AudioSinkFork output(this, &output_file);
1709 test::AcmReceiveTestToggleOutputFreqOldApi receive_test(
1710 this,
1711 &output,
1712 output_freq_1,
1713 output_freq_2,
1714 toggle_period_ms,
1715 test::AcmReceiveTestOldApi::kMonoOutput);
1716 ASSERT_NO_FATAL_FAILURE(receive_test.RegisterDefaultCodecs());
1717 output_freq_2_ = output_freq_2;
1718
1719 // This is where the actual test is executed.
1720 receive_test.Run();
1721
1722 // Delete output file.
1723 remove(output_file_name.c_str());
1724 }
1725
1726 // Inherited from test::PacketSource.
NextPacket()1727 test::Packet* NextPacket() override {
1728 // Check if it is time to terminate the test. The packet source is of type
1729 // ConstantPcmPacketSource, which is infinite, so we must end the test
1730 // "manually".
1731 if (num_packets_++ > kTestNumPackets) {
1732 EXPECT_TRUE(has_toggled_);
1733 return NULL; // Test ended.
1734 }
1735
1736 // Get the next packet from the source.
1737 return packet_source_.NextPacket();
1738 }
1739
1740 // Inherited from test::AudioSink.
WriteArray(const int16_t * audio,size_t num_samples)1741 bool WriteArray(const int16_t* audio, size_t num_samples) {
1742 // Skip checking the first output frame, since it has a number of zeros
1743 // due to how NetEq is initialized.
1744 if (first_output_) {
1745 first_output_ = false;
1746 return true;
1747 }
1748 for (size_t i = 0; i < num_samples; ++i) {
1749 EXPECT_EQ(kSampleValue, audio[i]);
1750 }
1751 if (num_samples ==
1752 static_cast<size_t>(output_freq_2_ / 100)) // Size of 10 ms frame.
1753 has_toggled_ = true;
1754 // The return value does not say if the values match the expectation, just
1755 // that the method could process the samples.
1756 return true;
1757 }
1758
1759 const int16_t kSampleValue = 1000;
1760 bool first_output_;
1761 size_t num_packets_;
1762 test::ConstantPcmPacketSource packet_source_;
1763 int output_freq_2_;
1764 bool has_toggled_;
1765 };
1766
TEST_F(AcmSwitchingOutputFrequencyOldApi,TestWithoutToggling)1767 TEST_F(AcmSwitchingOutputFrequencyOldApi, TestWithoutToggling) {
1768 Run(16000, 16000, 1000);
1769 }
1770
TEST_F(AcmSwitchingOutputFrequencyOldApi,Toggle16KhzTo32Khz)1771 TEST_F(AcmSwitchingOutputFrequencyOldApi, Toggle16KhzTo32Khz) {
1772 Run(16000, 32000, 1000);
1773 }
1774
TEST_F(AcmSwitchingOutputFrequencyOldApi,Toggle32KhzTo16Khz)1775 TEST_F(AcmSwitchingOutputFrequencyOldApi, Toggle32KhzTo16Khz) {
1776 Run(32000, 16000, 1000);
1777 }
1778
TEST_F(AcmSwitchingOutputFrequencyOldApi,Toggle16KhzTo8Khz)1779 TEST_F(AcmSwitchingOutputFrequencyOldApi, Toggle16KhzTo8Khz) {
1780 Run(16000, 8000, 1000);
1781 }
1782
TEST_F(AcmSwitchingOutputFrequencyOldApi,Toggle8KhzTo16Khz)1783 TEST_F(AcmSwitchingOutputFrequencyOldApi, Toggle8KhzTo16Khz) {
1784 Run(8000, 16000, 1000);
1785 }
1786
1787 #endif
1788
1789 } // namespace webrtc
1790