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

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

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

Powered by Google App Engine
This is Rietveld 408576698