Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(132)

Side by Side Diff: webrtc/modules/audio_coding/main/acm2/audio_coding_module_unittest_oldapi.cc

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

Powered by Google App Engine
This is Rietveld 408576698