blob: 68dd671415ea3c49a9c6a367833684c7a58d3a5c [file] [log] [blame]
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +00001/*
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
ivoce10c82d2015-12-08 05:03:28 -080011#include <stdio.h>
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +000012#include <string.h>
kwiberg16c5a962016-02-15 02:27:22 -080013#include <memory>
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +000014#include <vector>
15
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020016#include "api/audio_codecs/audio_encoder.h"
17#include "api/audio_codecs/builtin_audio_decoder_factory.h"
Karl Wiberg7275e182017-10-25 09:57:40 +020018#include "api/audio_codecs/opus/audio_encoder_opus.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020019#include "modules/audio_coding/acm2/acm_receive_test.h"
20#include "modules/audio_coding/acm2/acm_send_test.h"
21#include "modules/audio_coding/codecs/audio_format_conversion.h"
22#include "modules/audio_coding/codecs/g711/audio_decoder_pcm.h"
23#include "modules/audio_coding/codecs/g711/audio_encoder_pcm.h"
24#include "modules/audio_coding/codecs/isac/main/include/audio_encoder_isac.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020025#include "modules/audio_coding/include/audio_coding_module.h"
26#include "modules/audio_coding/include/audio_coding_module_typedefs.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020027#include "modules/audio_coding/neteq/tools/audio_checksum.h"
28#include "modules/audio_coding/neteq/tools/audio_loop.h"
29#include "modules/audio_coding/neteq/tools/constant_pcm_packet_source.h"
30#include "modules/audio_coding/neteq/tools/input_audio_file.h"
31#include "modules/audio_coding/neteq/tools/output_audio_file.h"
32#include "modules/audio_coding/neteq/tools/output_wav_file.h"
33#include "modules/audio_coding/neteq/tools/packet.h"
34#include "modules/audio_coding/neteq/tools/rtp_file_source.h"
35#include "modules/include/module_common_types.h"
36#include "rtc_base/criticalsection.h"
37#include "rtc_base/md5digest.h"
38#include "rtc_base/platform_thread.h"
Niels Möller84255bb2017-10-06 13:43:23 +020039#include "rtc_base/refcountedobject.h"
Mirko Bonadei737e0732017-10-19 09:00:17 +020040#include "rtc_base/safe_conversions.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020041#include "rtc_base/thread_annotations.h"
42#include "system_wrappers/include/clock.h"
43#include "system_wrappers/include/event_wrapper.h"
44#include "system_wrappers/include/sleep.h"
45#include "test/gtest.h"
46#include "test/mock_audio_decoder.h"
47#include "test/mock_audio_encoder.h"
48#include "test/testsupport/fileutils.h"
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +000049
Karl Wiberg7e0c7d42015-05-18 14:52:29 +020050using ::testing::AtLeast;
51using ::testing::Invoke;
52using ::testing::_;
53
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +000054namespace webrtc {
55
henrik.lundin@webrtc.orgbb1219e2015-02-12 15:53:25 +000056namespace {
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +000057const int kSampleRateHz = 16000;
58const int kNumSamples10ms = kSampleRateHz / 100;
59const int kFrameSizeMs = 10; // Multiple of 10.
60const int kFrameSizeSamples = kFrameSizeMs / 10 * kNumSamples10ms;
61const int kPayloadSizeBytes = kFrameSizeSamples * sizeof(int16_t);
62const uint8_t kPayloadType = 111;
henrik.lundin@webrtc.orgbb1219e2015-02-12 15:53:25 +000063} // namespace
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +000064
65class RtpUtility {
66 public:
67 RtpUtility(int samples_per_packet, uint8_t payload_type)
68 : samples_per_packet_(samples_per_packet), payload_type_(payload_type) {}
69
70 virtual ~RtpUtility() {}
71
72 void Populate(WebRtcRTPHeader* rtp_header) {
73 rtp_header->header.sequenceNumber = 0xABCD;
74 rtp_header->header.timestamp = 0xABCDEF01;
75 rtp_header->header.payloadType = payload_type_;
76 rtp_header->header.markerBit = false;
77 rtp_header->header.ssrc = 0x1234;
78 rtp_header->header.numCSRCs = 0;
79 rtp_header->frameType = kAudioFrameSpeech;
80
81 rtp_header->header.payload_type_frequency = kSampleRateHz;
82 rtp_header->type.Audio.channel = 1;
83 rtp_header->type.Audio.isCNG = false;
84 }
85
86 void Forward(WebRtcRTPHeader* rtp_header) {
87 ++rtp_header->header.sequenceNumber;
88 rtp_header->header.timestamp += samples_per_packet_;
89 }
90
91 private:
92 int samples_per_packet_;
93 uint8_t payload_type_;
94};
95
henrik.lundin@webrtc.orgbb1219e2015-02-12 15:53:25 +000096class PacketizationCallbackStubOldApi : public AudioPacketizationCallback {
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +000097 public:
henrik.lundin@webrtc.orgbb1219e2015-02-12 15:53:25 +000098 PacketizationCallbackStubOldApi()
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +000099 : num_calls_(0),
pbos22993e12015-10-19 02:39:06 -0700100 last_frame_type_(kEmptyFrame),
henrik.lundin@webrtc.orgbb1219e2015-02-12 15:53:25 +0000101 last_payload_type_(-1),
Tommi9090e0b2016-01-20 13:39:36 +0100102 last_timestamp_(0) {}
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000103
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000104 int32_t SendData(FrameType frame_type,
105 uint8_t payload_type,
106 uint32_t timestamp,
107 const uint8_t* payload_data,
108 size_t payload_len_bytes,
109 const RTPFragmentationHeader* fragmentation) override {
Tommi9090e0b2016-01-20 13:39:36 +0100110 rtc::CritScope lock(&crit_sect_);
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000111 ++num_calls_;
henrik.lundin@webrtc.orgbb1219e2015-02-12 15:53:25 +0000112 last_frame_type_ = frame_type;
113 last_payload_type_ = payload_type;
henrik.lundin@webrtc.orgfc562e02015-03-18 07:32:13 +0000114 last_timestamp_ = timestamp;
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000115 last_payload_vec_.assign(payload_data, payload_data + payload_len_bytes);
116 return 0;
117 }
118
119 int num_calls() const {
Tommi9090e0b2016-01-20 13:39:36 +0100120 rtc::CritScope lock(&crit_sect_);
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000121 return num_calls_;
122 }
123
124 int last_payload_len_bytes() const {
Tommi9090e0b2016-01-20 13:39:36 +0100125 rtc::CritScope lock(&crit_sect_);
Mirko Bonadei737e0732017-10-19 09:00:17 +0200126 return rtc::checked_cast<int>(last_payload_vec_.size());
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000127 }
128
henrik.lundin@webrtc.orgbb1219e2015-02-12 15:53:25 +0000129 FrameType last_frame_type() const {
Tommi9090e0b2016-01-20 13:39:36 +0100130 rtc::CritScope lock(&crit_sect_);
henrik.lundin@webrtc.orgbb1219e2015-02-12 15:53:25 +0000131 return last_frame_type_;
132 }
133
134 int last_payload_type() const {
Tommi9090e0b2016-01-20 13:39:36 +0100135 rtc::CritScope lock(&crit_sect_);
henrik.lundin@webrtc.orgbb1219e2015-02-12 15:53:25 +0000136 return last_payload_type_;
137 }
138
henrik.lundin@webrtc.orgfc562e02015-03-18 07:32:13 +0000139 uint32_t last_timestamp() const {
Tommi9090e0b2016-01-20 13:39:36 +0100140 rtc::CritScope lock(&crit_sect_);
henrik.lundin@webrtc.orgfc562e02015-03-18 07:32:13 +0000141 return last_timestamp_;
142 }
143
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000144 void SwapBuffers(std::vector<uint8_t>* payload) {
Tommi9090e0b2016-01-20 13:39:36 +0100145 rtc::CritScope lock(&crit_sect_);
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000146 last_payload_vec_.swap(*payload);
147 }
148
149 private:
danilchap56359be2017-09-07 07:53:45 -0700150 int num_calls_ RTC_GUARDED_BY(crit_sect_);
151 FrameType last_frame_type_ RTC_GUARDED_BY(crit_sect_);
152 int last_payload_type_ RTC_GUARDED_BY(crit_sect_);
153 uint32_t last_timestamp_ RTC_GUARDED_BY(crit_sect_);
154 std::vector<uint8_t> last_payload_vec_ RTC_GUARDED_BY(crit_sect_);
pbos5ad935c2016-01-25 03:52:44 -0800155 rtc::CriticalSection crit_sect_;
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000156};
157
158class AudioCodingModuleTestOldApi : public ::testing::Test {
159 protected:
160 AudioCodingModuleTestOldApi()
solenbergc7b4a452017-09-28 07:37:11 -0700161 : rtp_utility_(new RtpUtility(kFrameSizeSamples, kPayloadType)),
henrik.lundin@webrtc.orgfc562e02015-03-18 07:32:13 +0000162 clock_(Clock::GetRealTimeClock()) {}
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000163
164 ~AudioCodingModuleTestOldApi() {}
165
166 void TearDown() {}
167
168 void SetUp() {
solenbergc7b4a452017-09-28 07:37:11 -0700169 acm_.reset(AudioCodingModule::Create(clock_));
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000170
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000171 rtp_utility_->Populate(&rtp_header_);
172
173 input_frame_.sample_rate_hz_ = kSampleRateHz;
174 input_frame_.num_channels_ = 1;
175 input_frame_.samples_per_channel_ = kSampleRateHz * 10 / 1000; // 10 ms.
kwiberg@webrtc.org2ebfac52015-01-14 10:51:54 +0000176 static_assert(kSampleRateHz * 10 / 1000 <= AudioFrame::kMaxDataSizeSamples,
177 "audio frame too small");
yujo36b1a5f2017-06-12 12:45:32 -0700178 input_frame_.Mute();
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000179
180 ASSERT_EQ(0, acm_->RegisterTransportCallback(&packet_cb_));
henrik.lundin@webrtc.orgfc562e02015-03-18 07:32:13 +0000181
182 SetUpL16Codec();
183 }
184
185 // Set up L16 codec.
186 virtual void SetUpL16Codec() {
Oskar Sundbom12ab00b2017-11-16 15:31:38 +0100187 audio_format_ = SdpAudioFormat("L16", kSampleRateHz, 1);
henrik.lundin@webrtc.orgfc562e02015-03-18 07:32:13 +0000188 ASSERT_EQ(0, AudioCodingModule::Codec("L16", &codec_, kSampleRateHz, 1));
189 codec_.pltype = kPayloadType;
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000190 }
191
192 virtual void RegisterCodec() {
kwiberg5adaf732016-10-04 09:33:27 -0700193 EXPECT_EQ(true, acm_->RegisterReceiveCodec(kPayloadType, *audio_format_));
194 EXPECT_EQ(0, acm_->RegisterSendCodec(codec_));
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000195 }
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;
henrik.lundind4ccb002016-05-17 12:21:55 -0700211 bool muted;
212 ASSERT_EQ(0, acm_->PlayoutData10Ms(-1, &audio_frame, &muted));
213 ASSERT_FALSE(muted);
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000214 }
215
216 virtual void InsertAudio() {
henrik.lundin@webrtc.orgf56c1622015-03-02 12:29:30 +0000217 ASSERT_GE(acm_->Add10MsData(input_frame_), 0);
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000218 input_frame_.timestamp_ += kNumSamples10ms;
219 }
220
henrik.lundin@webrtc.orgf56c1622015-03-02 12:29:30 +0000221 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.";
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000225 }
226
henrik.lundin@webrtc.orgfc562e02015-03-18 07:32:13 +0000227 virtual void InsertAudioAndVerifyEncoding() {
228 InsertAudio();
229 VerifyEncoding();
230 }
231
kwiberg16c5a962016-02-15 02:27:22 -0800232 std::unique_ptr<RtpUtility> rtp_utility_;
233 std::unique_ptr<AudioCodingModule> acm_;
henrik.lundin@webrtc.orgbb1219e2015-02-12 15:53:25 +0000234 PacketizationCallbackStubOldApi packet_cb_;
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000235 WebRtcRTPHeader rtp_header_;
236 AudioFrame input_frame_;
kwiberg5adaf732016-10-04 09:33:27 -0700237
238 // These two have to be kept in sync for now. In the future, we'll be able to
239 // eliminate the CodecInst and keep only the SdpAudioFormat.
240 rtc::Optional<SdpAudioFormat> audio_format_;
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000241 CodecInst codec_;
kwiberg5adaf732016-10-04 09:33:27 -0700242
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000243 Clock* clock_;
244};
245
246// Check if the statistics are initialized correctly. Before any call to ACM
247// all fields have to be zero.
Peter Boströme2976c82016-01-04 22:44:05 +0100248#if defined(WEBRTC_ANDROID)
249#define MAYBE_InitializedToZero DISABLED_InitializedToZero
250#else
251#define MAYBE_InitializedToZero InitializedToZero
252#endif
253TEST_F(AudioCodingModuleTestOldApi, MAYBE_InitializedToZero) {
henrik.lundin@webrtc.orgbb1219e2015-02-12 15:53:25 +0000254 RegisterCodec();
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000255 AudioDecodingCallStats stats;
256 acm_->GetDecodingCallStatistics(&stats);
257 EXPECT_EQ(0, stats.calls_to_neteq);
258 EXPECT_EQ(0, stats.calls_to_silence_generator);
259 EXPECT_EQ(0, stats.decoded_normal);
260 EXPECT_EQ(0, stats.decoded_cng);
261 EXPECT_EQ(0, stats.decoded_plc);
262 EXPECT_EQ(0, stats.decoded_plc_cng);
henrik.lundin63489782016-09-20 01:47:12 -0700263 EXPECT_EQ(0, stats.decoded_muted_output);
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000264}
265
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000266// Insert some packets and pull audio. Check statistics are valid. Then,
267// simulate packet loss and check if PLC and PLC-to-CNG statistics are
268// correctly updated.
Peter Boströme2976c82016-01-04 22:44:05 +0100269#if defined(WEBRTC_ANDROID)
270#define MAYBE_NetEqCalls DISABLED_NetEqCalls
271#else
272#define MAYBE_NetEqCalls NetEqCalls
273#endif
274TEST_F(AudioCodingModuleTestOldApi, MAYBE_NetEqCalls) {
henrik.lundin@webrtc.orgbb1219e2015-02-12 15:53:25 +0000275 RegisterCodec();
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000276 AudioDecodingCallStats stats;
277 const int kNumNormalCalls = 10;
278
279 for (int num_calls = 0; num_calls < kNumNormalCalls; ++num_calls) {
280 InsertPacketAndPullAudio();
281 }
282 acm_->GetDecodingCallStatistics(&stats);
283 EXPECT_EQ(kNumNormalCalls, stats.calls_to_neteq);
284 EXPECT_EQ(0, stats.calls_to_silence_generator);
285 EXPECT_EQ(kNumNormalCalls, stats.decoded_normal);
286 EXPECT_EQ(0, stats.decoded_cng);
287 EXPECT_EQ(0, stats.decoded_plc);
288 EXPECT_EQ(0, stats.decoded_plc_cng);
henrik.lundin63489782016-09-20 01:47:12 -0700289 EXPECT_EQ(0, stats.decoded_muted_output);
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000290
291 const int kNumPlc = 3;
292 const int kNumPlcCng = 5;
293
294 // Simulate packet-loss. NetEq first performs PLC then PLC fades to CNG.
295 for (int n = 0; n < kNumPlc + kNumPlcCng; ++n) {
296 PullAudio();
297 }
298 acm_->GetDecodingCallStatistics(&stats);
299 EXPECT_EQ(kNumNormalCalls + kNumPlc + kNumPlcCng, stats.calls_to_neteq);
300 EXPECT_EQ(0, stats.calls_to_silence_generator);
301 EXPECT_EQ(kNumNormalCalls, stats.decoded_normal);
302 EXPECT_EQ(0, stats.decoded_cng);
303 EXPECT_EQ(kNumPlc, stats.decoded_plc);
304 EXPECT_EQ(kNumPlcCng, stats.decoded_plc_cng);
henrik.lundin63489782016-09-20 01:47:12 -0700305 EXPECT_EQ(0, stats.decoded_muted_output);
306 // TODO(henrik.lundin) Add a test with muted state enabled.
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000307}
308
309TEST_F(AudioCodingModuleTestOldApi, VerifyOutputFrame) {
310 AudioFrame audio_frame;
311 const int kSampleRateHz = 32000;
henrik.lundind4ccb002016-05-17 12:21:55 -0700312 bool muted;
313 EXPECT_EQ(0, acm_->PlayoutData10Ms(kSampleRateHz, &audio_frame, &muted));
314 ASSERT_FALSE(muted);
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000315 EXPECT_EQ(0u, audio_frame.timestamp_);
Peter Kasting69558702016-01-12 16:26:35 -0800316 EXPECT_GT(audio_frame.num_channels_, 0u);
Peter Kastingdce40cf2015-08-24 14:52:23 -0700317 EXPECT_EQ(static_cast<size_t>(kSampleRateHz / 100),
318 audio_frame.samples_per_channel_);
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000319 EXPECT_EQ(kSampleRateHz, audio_frame.sample_rate_hz_);
320}
321
Tommi90edc652016-05-26 23:48:16 +0200322// The below test is temporarily disabled on Windows due to problems
323// with clang debug builds.
324// TODO(tommi): Re-enable when we've figured out what the problem is.
325// http://crbug.com/615050
kwiberg5377bc72016-10-04 13:46:56 -0700326#if !defined(WEBRTC_WIN) && defined(__clang__) && RTC_DCHECK_IS_ON && \
327 GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000328TEST_F(AudioCodingModuleTestOldApi, FailOnZeroDesiredFrequency) {
329 AudioFrame audio_frame;
henrik.lundind4ccb002016-05-17 12:21:55 -0700330 bool muted;
Tommi5771beb2016-05-26 21:51:30 +0200331 EXPECT_DEATH(acm_->PlayoutData10Ms(0, &audio_frame, &muted),
332 "dst_sample_rate_hz");
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000333}
Tommi5771beb2016-05-26 21:51:30 +0200334#endif
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000335
henrik.lundin@webrtc.orgbb1219e2015-02-12 15:53:25 +0000336// Checks that the transport callback is invoked once for each speech packet.
337// Also checks that the frame type is kAudioFrameSpeech.
338TEST_F(AudioCodingModuleTestOldApi, TransportCallbackIsInvokedForEachPacket) {
339 const int k10MsBlocksPerPacket = 3;
henrik.lundin@webrtc.orgfc562e02015-03-18 07:32:13 +0000340 codec_.pacsize = k10MsBlocksPerPacket * kSampleRateHz / 100;
henrik.lundin@webrtc.orgbb1219e2015-02-12 15:53:25 +0000341 RegisterCodec();
342 const int kLoops = 10;
343 for (int i = 0; i < kLoops; ++i) {
344 EXPECT_EQ(i / k10MsBlocksPerPacket, packet_cb_.num_calls());
345 if (packet_cb_.num_calls() > 0)
346 EXPECT_EQ(kAudioFrameSpeech, packet_cb_.last_frame_type());
henrik.lundin@webrtc.orgfc562e02015-03-18 07:32:13 +0000347 InsertAudioAndVerifyEncoding();
henrik.lundin@webrtc.orgbb1219e2015-02-12 15:53:25 +0000348 }
349 EXPECT_EQ(kLoops / k10MsBlocksPerPacket, packet_cb_.num_calls());
350 EXPECT_EQ(kAudioFrameSpeech, packet_cb_.last_frame_type());
351}
352
kwiberg98ab3a42015-09-30 21:54:21 -0700353#if defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX)
henrik.lundin@webrtc.orgfc562e02015-03-18 07:32:13 +0000354// Verifies that the RTP timestamp series is not reset when the codec is
355// changed.
Peter Boströme2976c82016-01-04 22:44:05 +0100356TEST_F(AudioCodingModuleTestOldApi, TimestampSeriesContinuesWhenCodecChanges) {
henrik.lundin@webrtc.orgfc562e02015-03-18 07:32:13 +0000357 RegisterCodec(); // This registers the default codec.
358 uint32_t expected_ts = input_frame_.timestamp_;
359 int blocks_per_packet = codec_.pacsize / (kSampleRateHz / 100);
360 // Encode 5 packets of the first codec type.
361 const int kNumPackets1 = 5;
362 for (int j = 0; j < kNumPackets1; ++j) {
363 for (int i = 0; i < blocks_per_packet; ++i) {
364 EXPECT_EQ(j, packet_cb_.num_calls());
365 InsertAudio();
366 }
367 EXPECT_EQ(j + 1, packet_cb_.num_calls());
368 EXPECT_EQ(expected_ts, packet_cb_.last_timestamp());
369 expected_ts += codec_.pacsize;
370 }
371
372 // Change codec.
373 ASSERT_EQ(0, AudioCodingModule::Codec("ISAC", &codec_, kSampleRateHz, 1));
374 RegisterCodec();
375 blocks_per_packet = codec_.pacsize / (kSampleRateHz / 100);
376 // Encode another 5 packets.
377 const int kNumPackets2 = 5;
378 for (int j = 0; j < kNumPackets2; ++j) {
379 for (int i = 0; i < blocks_per_packet; ++i) {
380 EXPECT_EQ(kNumPackets1 + j, packet_cb_.num_calls());
381 InsertAudio();
382 }
383 EXPECT_EQ(kNumPackets1 + j + 1, packet_cb_.num_calls());
384 EXPECT_EQ(expected_ts, packet_cb_.last_timestamp());
385 expected_ts += codec_.pacsize;
386 }
387}
Peter Boströme2976c82016-01-04 22:44:05 +0100388#endif
henrik.lundin@webrtc.orgfc562e02015-03-18 07:32:13 +0000389
henrik.lundin@webrtc.orgbb1219e2015-02-12 15:53:25 +0000390// Introduce this class to set different expectations on the number of encoded
391// bytes. This class expects all encoded packets to be 9 bytes (matching one
392// CNG SID frame) or 0 bytes. This test depends on |input_frame_| containing
henrik.lundin@webrtc.org34509d92015-02-16 16:02:17 +0000393// (near-)zero values. It also introduces a way to register comfort noise with
394// a custom payload type.
henrik.lundin@webrtc.orgbb1219e2015-02-12 15:53:25 +0000395class AudioCodingModuleTestWithComfortNoiseOldApi
396 : public AudioCodingModuleTestOldApi {
397 protected:
henrik.lundin@webrtc.org34509d92015-02-16 16:02:17 +0000398 void RegisterCngCodec(int rtp_payload_type) {
kwiberg5adaf732016-10-04 09:33:27 -0700399 EXPECT_EQ(true,
400 acm_->RegisterReceiveCodec(
401 rtp_payload_type, SdpAudioFormat("cn", kSampleRateHz, 1)));
402
henrik.lundin@webrtc.org34509d92015-02-16 16:02:17 +0000403 CodecInst codec;
kwiberg5adaf732016-10-04 09:33:27 -0700404 EXPECT_EQ(0, AudioCodingModule::Codec("CN", &codec, kSampleRateHz, 1));
henrik.lundin@webrtc.org34509d92015-02-16 16:02:17 +0000405 codec.pltype = rtp_payload_type;
kwiberg5adaf732016-10-04 09:33:27 -0700406 EXPECT_EQ(0, acm_->RegisterSendCodec(codec));
henrik.lundin@webrtc.org34509d92015-02-16 16:02:17 +0000407 }
408
henrik.lundin@webrtc.orgf56c1622015-03-02 12:29:30 +0000409 void VerifyEncoding() override {
410 int last_length = packet_cb_.last_payload_len_bytes();
411 EXPECT_TRUE(last_length == 9 || last_length == 0)
412 << "Last encoded packet was " << last_length << " bytes.";
413 }
414
henrik.lundin@webrtc.org34509d92015-02-16 16:02:17 +0000415 void DoTest(int blocks_per_packet, int cng_pt) {
416 const int kLoops = 40;
417 // This array defines the expected frame types, and when they should arrive.
418 // We expect a frame to arrive each time the speech encoder would have
419 // produced a packet, and once every 100 ms the frame should be non-empty,
420 // that is contain comfort noise.
421 const struct {
422 int ix;
423 FrameType type;
424 } expectation[] = {{2, kAudioFrameCN},
pbos22993e12015-10-19 02:39:06 -0700425 {5, kEmptyFrame},
426 {8, kEmptyFrame},
henrik.lundin@webrtc.org34509d92015-02-16 16:02:17 +0000427 {11, kAudioFrameCN},
pbos22993e12015-10-19 02:39:06 -0700428 {14, kEmptyFrame},
429 {17, kEmptyFrame},
henrik.lundin@webrtc.org34509d92015-02-16 16:02:17 +0000430 {20, kAudioFrameCN},
pbos22993e12015-10-19 02:39:06 -0700431 {23, kEmptyFrame},
432 {26, kEmptyFrame},
433 {29, kEmptyFrame},
henrik.lundin@webrtc.org34509d92015-02-16 16:02:17 +0000434 {32, kAudioFrameCN},
pbos22993e12015-10-19 02:39:06 -0700435 {35, kEmptyFrame},
436 {38, kEmptyFrame}};
henrik.lundin@webrtc.org34509d92015-02-16 16:02:17 +0000437 for (int i = 0; i < kLoops; ++i) {
438 int num_calls_before = packet_cb_.num_calls();
439 EXPECT_EQ(i / blocks_per_packet, num_calls_before);
henrik.lundin@webrtc.orgfc562e02015-03-18 07:32:13 +0000440 InsertAudioAndVerifyEncoding();
henrik.lundin@webrtc.org34509d92015-02-16 16:02:17 +0000441 int num_calls = packet_cb_.num_calls();
442 if (num_calls == num_calls_before + 1) {
443 EXPECT_EQ(expectation[num_calls - 1].ix, i);
444 EXPECT_EQ(expectation[num_calls - 1].type, packet_cb_.last_frame_type())
445 << "Wrong frame type for lap " << i;
446 EXPECT_EQ(cng_pt, packet_cb_.last_payload_type());
447 } else {
448 EXPECT_EQ(num_calls, num_calls_before);
449 }
450 }
451 }
henrik.lundin@webrtc.orgbb1219e2015-02-12 15:53:25 +0000452};
453
henrik.lundin@webrtc.org34509d92015-02-16 16:02:17 +0000454// Checks that the transport callback is invoked once per frame period of the
henrik.lundin@webrtc.orgbb1219e2015-02-12 15:53:25 +0000455// underlying speech encoder, even when comfort noise is produced.
pbos22993e12015-10-19 02:39:06 -0700456// Also checks that the frame type is kAudioFrameCN or kEmptyFrame.
henrik.lundin@webrtc.org34509d92015-02-16 16:02:17 +0000457// This test and the next check the same thing, but differ in the order of
458// speech codec and CNG registration.
henrik.lundin@webrtc.orgbb1219e2015-02-12 15:53:25 +0000459TEST_F(AudioCodingModuleTestWithComfortNoiseOldApi,
henrik.lundin@webrtc.org34509d92015-02-16 16:02:17 +0000460 TransportCallbackTestForComfortNoiseRegisterCngLast) {
henrik.lundin@webrtc.orgbb1219e2015-02-12 15:53:25 +0000461 const int k10MsBlocksPerPacket = 3;
henrik.lundin@webrtc.orgfc562e02015-03-18 07:32:13 +0000462 codec_.pacsize = k10MsBlocksPerPacket * kSampleRateHz / 100;
henrik.lundin@webrtc.orgbb1219e2015-02-12 15:53:25 +0000463 RegisterCodec();
henrik.lundin@webrtc.org34509d92015-02-16 16:02:17 +0000464 const int kCngPayloadType = 105;
465 RegisterCngCodec(kCngPayloadType);
henrik.lundin@webrtc.orgbb1219e2015-02-12 15:53:25 +0000466 ASSERT_EQ(0, acm_->SetVAD(true, true));
henrik.lundin@webrtc.org34509d92015-02-16 16:02:17 +0000467 DoTest(k10MsBlocksPerPacket, kCngPayloadType);
468}
469
470TEST_F(AudioCodingModuleTestWithComfortNoiseOldApi,
471 TransportCallbackTestForComfortNoiseRegisterCngFirst) {
472 const int k10MsBlocksPerPacket = 3;
henrik.lundin@webrtc.orgfc562e02015-03-18 07:32:13 +0000473 codec_.pacsize = k10MsBlocksPerPacket * kSampleRateHz / 100;
henrik.lundin@webrtc.org34509d92015-02-16 16:02:17 +0000474 const int kCngPayloadType = 105;
475 RegisterCngCodec(kCngPayloadType);
476 RegisterCodec();
477 ASSERT_EQ(0, acm_->SetVAD(true, true));
478 DoTest(k10MsBlocksPerPacket, kCngPayloadType);
henrik.lundin@webrtc.orgbb1219e2015-02-12 15:53:25 +0000479}
480
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000481// A multi-threaded test for ACM. This base class is using the PCM16b 16 kHz
482// codec, while the derive class AcmIsacMtTest is using iSAC.
483class AudioCodingModuleMtTestOldApi : public AudioCodingModuleTestOldApi {
484 protected:
485 static const int kNumPackets = 500;
486 static const int kNumPullCalls = 500;
487
488 AudioCodingModuleMtTestOldApi()
489 : AudioCodingModuleTestOldApi(),
Peter Boström8c38e8b2015-11-26 17:45:47 +0100490 send_thread_(CbSendThread, this, "send"),
491 insert_packet_thread_(CbInsertPacketThread, this, "insert_packet"),
492 pull_audio_thread_(CbPullAudioThread, this, "pull_audio"),
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000493 test_complete_(EventWrapper::Create()),
494 send_count_(0),
495 insert_packet_count_(0),
496 pull_audio_count_(0),
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000497 next_insert_packet_time_ms_(0),
498 fake_clock_(new SimulatedClock(0)) {
499 clock_ = fake_clock_.get();
500 }
501
502 void SetUp() {
503 AudioCodingModuleTestOldApi::SetUp();
henrik.lundin@webrtc.orgbb1219e2015-02-12 15:53:25 +0000504 RegisterCodec(); // Must be called before the threads start below.
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000505 StartThreads();
506 }
507
508 void StartThreads() {
Peter Boström8c38e8b2015-11-26 17:45:47 +0100509 send_thread_.Start();
510 send_thread_.SetPriority(rtc::kRealtimePriority);
511 insert_packet_thread_.Start();
512 insert_packet_thread_.SetPriority(rtc::kRealtimePriority);
513 pull_audio_thread_.Start();
514 pull_audio_thread_.SetPriority(rtc::kRealtimePriority);
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000515 }
516
517 void TearDown() {
518 AudioCodingModuleTestOldApi::TearDown();
Peter Boström8c38e8b2015-11-26 17:45:47 +0100519 pull_audio_thread_.Stop();
520 send_thread_.Stop();
521 insert_packet_thread_.Stop();
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000522 }
523
524 EventTypeWrapper RunTest() {
525 return test_complete_->Wait(10 * 60 * 1000); // 10 minutes' timeout.
526 }
527
528 virtual bool TestDone() {
529 if (packet_cb_.num_calls() > kNumPackets) {
Tommi9090e0b2016-01-20 13:39:36 +0100530 rtc::CritScope lock(&crit_sect_);
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000531 if (pull_audio_count_ > kNumPullCalls) {
532 // Both conditions for completion are met. End the test.
533 return true;
534 }
535 }
536 return false;
537 }
538
539 static bool CbSendThread(void* context) {
540 return reinterpret_cast<AudioCodingModuleMtTestOldApi*>(context)
541 ->CbSendImpl();
542 }
543
544 // The send thread doesn't have to care about the current simulated time,
545 // since only the AcmReceiver is using the clock.
546 bool CbSendImpl() {
547 SleepMs(1);
548 if (HasFatalFailure()) {
549 // End the test early if a fatal failure (ASSERT_*) has occurred.
550 test_complete_->Set();
551 }
552 ++send_count_;
henrik.lundin@webrtc.orgfc562e02015-03-18 07:32:13 +0000553 InsertAudioAndVerifyEncoding();
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000554 if (TestDone()) {
555 test_complete_->Set();
556 }
557 return true;
558 }
559
560 static bool CbInsertPacketThread(void* context) {
561 return reinterpret_cast<AudioCodingModuleMtTestOldApi*>(context)
562 ->CbInsertPacketImpl();
563 }
564
565 bool CbInsertPacketImpl() {
566 SleepMs(1);
567 {
Tommi9090e0b2016-01-20 13:39:36 +0100568 rtc::CritScope lock(&crit_sect_);
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000569 if (clock_->TimeInMilliseconds() < next_insert_packet_time_ms_) {
570 return true;
571 }
572 next_insert_packet_time_ms_ += 10;
573 }
574 // Now we're not holding the crit sect when calling ACM.
575 ++insert_packet_count_;
576 InsertPacket();
577 return true;
578 }
579
580 static bool CbPullAudioThread(void* context) {
581 return reinterpret_cast<AudioCodingModuleMtTestOldApi*>(context)
582 ->CbPullAudioImpl();
583 }
584
585 bool CbPullAudioImpl() {
586 SleepMs(1);
587 {
Tommi9090e0b2016-01-20 13:39:36 +0100588 rtc::CritScope lock(&crit_sect_);
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000589 // Don't let the insert thread fall behind.
590 if (next_insert_packet_time_ms_ < clock_->TimeInMilliseconds()) {
591 return true;
592 }
593 ++pull_audio_count_;
594 }
595 // Now we're not holding the crit sect when calling ACM.
596 PullAudio();
597 fake_clock_->AdvanceTimeMilliseconds(10);
598 return true;
599 }
600
Peter Boström8c38e8b2015-11-26 17:45:47 +0100601 rtc::PlatformThread send_thread_;
602 rtc::PlatformThread insert_packet_thread_;
603 rtc::PlatformThread pull_audio_thread_;
kwiberg16c5a962016-02-15 02:27:22 -0800604 const std::unique_ptr<EventWrapper> test_complete_;
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000605 int send_count_;
606 int insert_packet_count_;
danilchap56359be2017-09-07 07:53:45 -0700607 int pull_audio_count_ RTC_GUARDED_BY(crit_sect_);
pbos5ad935c2016-01-25 03:52:44 -0800608 rtc::CriticalSection crit_sect_;
danilchap56359be2017-09-07 07:53:45 -0700609 int64_t next_insert_packet_time_ms_ RTC_GUARDED_BY(crit_sect_);
kwiberg16c5a962016-02-15 02:27:22 -0800610 std::unique_ptr<SimulatedClock> fake_clock_;
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000611};
612
Peter Boströme2976c82016-01-04 22:44:05 +0100613#if defined(WEBRTC_IOS)
614#define MAYBE_DoTest DISABLED_DoTest
615#else
616#define MAYBE_DoTest DoTest
617#endif
618TEST_F(AudioCodingModuleMtTestOldApi, MAYBE_DoTest) {
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000619 EXPECT_EQ(kEventSignaled, RunTest());
620}
621
622// This is a multi-threaded ACM test using iSAC. The test encodes audio
623// from a PCM file. The most recent encoded frame is used as input to the
624// receiving part. Depending on timing, it may happen that the same RTP packet
625// is inserted into the receiver multiple times, but this is a valid use-case,
626// and simplifies the test code a lot.
627class AcmIsacMtTestOldApi : public AudioCodingModuleMtTestOldApi {
628 protected:
629 static const int kNumPackets = 500;
630 static const int kNumPullCalls = 500;
631
632 AcmIsacMtTestOldApi()
633 : AudioCodingModuleMtTestOldApi(), last_packet_number_(0) {}
634
635 ~AcmIsacMtTestOldApi() {}
636
nisseef8b61e2016-04-29 06:09:15 -0700637 void SetUp() override {
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000638 AudioCodingModuleTestOldApi::SetUp();
henrik.lundin@webrtc.orgbb1219e2015-02-12 15:53:25 +0000639 RegisterCodec(); // Must be called before the threads start below.
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000640
641 // Set up input audio source to read from specified file, loop after 5
642 // seconds, and deliver blocks of 10 ms.
643 const std::string input_file_name =
644 webrtc::test::ResourcePath("audio_coding/speech_mono_16kHz", "pcm");
645 audio_loop_.Init(input_file_name, 5 * kSampleRateHz, kNumSamples10ms);
646
647 // Generate one packet to have something to insert.
648 int loop_counter = 0;
649 while (packet_cb_.last_payload_len_bytes() == 0) {
650 InsertAudio();
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000651 ASSERT_LT(loop_counter++, 10);
652 }
653 // Set |last_packet_number_| to one less that |num_calls| so that the packet
654 // will be fetched in the next InsertPacket() call.
655 last_packet_number_ = packet_cb_.num_calls() - 1;
656
657 StartThreads();
658 }
659
henrik.lundin@webrtc.orgbb1219e2015-02-12 15:53:25 +0000660 void RegisterCodec() override {
kwiberg@webrtc.org2ebfac52015-01-14 10:51:54 +0000661 static_assert(kSampleRateHz == 16000, "test designed for iSAC 16 kHz");
Oskar Sundbom12ab00b2017-11-16 15:31:38 +0100662 audio_format_ = SdpAudioFormat("isac", kSampleRateHz, 1);
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000663 AudioCodingModule::Codec("ISAC", &codec_, kSampleRateHz, 1);
664 codec_.pltype = kPayloadType;
665
666 // Register iSAC codec in ACM, effectively unregistering the PCM16B codec
667 // registered in AudioCodingModuleTestOldApi::SetUp();
kwiberg5adaf732016-10-04 09:33:27 -0700668 EXPECT_EQ(true, acm_->RegisterReceiveCodec(kPayloadType, *audio_format_));
669 EXPECT_EQ(0, acm_->RegisterSendCodec(codec_));
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000670 }
671
nisseef8b61e2016-04-29 06:09:15 -0700672 void InsertPacket() override {
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000673 int num_calls = packet_cb_.num_calls(); // Store locally for thread safety.
674 if (num_calls > last_packet_number_) {
675 // Get the new payload out from the callback handler.
676 // Note that since we swap buffers here instead of directly inserting
677 // a pointer to the data in |packet_cb_|, we avoid locking the callback
678 // for the duration of the IncomingPacket() call.
679 packet_cb_.SwapBuffers(&last_payload_vec_);
680 ASSERT_GT(last_payload_vec_.size(), 0u);
681 rtp_utility_->Forward(&rtp_header_);
682 last_packet_number_ = num_calls;
683 }
684 ASSERT_GT(last_payload_vec_.size(), 0u);
685 ASSERT_EQ(
686 0,
687 acm_->IncomingPacket(
688 &last_payload_vec_[0], last_payload_vec_.size(), rtp_header_));
689 }
690
nisseef8b61e2016-04-29 06:09:15 -0700691 void InsertAudio() override {
kwiberg288886b2015-11-06 01:21:35 -0800692 // TODO(kwiberg): Use std::copy here. Might be complications because AFAICS
693 // this call confuses the number of samples with the number of bytes, and
694 // ends up copying only half of what it should.
yujo36b1a5f2017-06-12 12:45:32 -0700695 memcpy(input_frame_.mutable_data(), audio_loop_.GetNextBlock().data(),
kwiberg288886b2015-11-06 01:21:35 -0800696 kNumSamples10ms);
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000697 AudioCodingModuleTestOldApi::InsertAudio();
698 }
699
henrik.lundin@webrtc.orgf56c1622015-03-02 12:29:30 +0000700 // Override the verification function with no-op, since iSAC produces variable
701 // payload sizes.
702 void VerifyEncoding() override {}
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000703
704 // This method is the same as AudioCodingModuleMtTestOldApi::TestDone(), but
705 // here it is using the constants defined in this class (i.e., shorter test
706 // run).
nisseef8b61e2016-04-29 06:09:15 -0700707 bool TestDone() override {
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000708 if (packet_cb_.num_calls() > kNumPackets) {
Tommi9090e0b2016-01-20 13:39:36 +0100709 rtc::CritScope lock(&crit_sect_);
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000710 if (pull_audio_count_ > kNumPullCalls) {
711 // Both conditions for completion are met. End the test.
712 return true;
713 }
714 }
715 return false;
716 }
717
718 int last_packet_number_;
719 std::vector<uint8_t> last_payload_vec_;
720 test::AudioLoop audio_loop_;
721};
722
Peter Boströme2976c82016-01-04 22:44:05 +0100723#if defined(WEBRTC_IOS)
724#define MAYBE_DoTest DISABLED_DoTest
725#else
726#define MAYBE_DoTest DoTest
727#endif
728#if defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX)
729TEST_F(AcmIsacMtTestOldApi, MAYBE_DoTest) {
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000730 EXPECT_EQ(kEventSignaled, RunTest());
731}
Peter Boströme2976c82016-01-04 22:44:05 +0100732#endif
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000733
Henrik Lundina6aa6d92015-06-15 13:46:15 +0200734class AcmReRegisterIsacMtTestOldApi : public AudioCodingModuleTestOldApi {
735 protected:
736 static const int kRegisterAfterNumPackets = 5;
737 static const int kNumPackets = 10;
738 static const int kPacketSizeMs = 30;
739 static const int kPacketSizeSamples = kPacketSizeMs * 16;
740
741 AcmReRegisterIsacMtTestOldApi()
742 : AudioCodingModuleTestOldApi(),
Peter Boström8c38e8b2015-11-26 17:45:47 +0100743 receive_thread_(CbReceiveThread, this, "receive"),
744 codec_registration_thread_(CbCodecRegistrationThread,
745 this,
746 "codec_registration"),
Henrik Lundina6aa6d92015-06-15 13:46:15 +0200747 test_complete_(EventWrapper::Create()),
Henrik Lundina6aa6d92015-06-15 13:46:15 +0200748 codec_registered_(false),
749 receive_packet_count_(0),
750 next_insert_packet_time_ms_(0),
751 fake_clock_(new SimulatedClock(0)) {
kwiberg6ff045f2017-08-17 05:31:02 -0700752 AudioEncoderIsacFloatImpl::Config config;
Henrik Lundina6aa6d92015-06-15 13:46:15 +0200753 config.payload_type = kPayloadType;
kwiberg6ff045f2017-08-17 05:31:02 -0700754 isac_encoder_.reset(new AudioEncoderIsacFloatImpl(config));
Henrik Lundina6aa6d92015-06-15 13:46:15 +0200755 clock_ = fake_clock_.get();
756 }
757
nisseef8b61e2016-04-29 06:09:15 -0700758 void SetUp() override {
Henrik Lundina6aa6d92015-06-15 13:46:15 +0200759 AudioCodingModuleTestOldApi::SetUp();
760 // Set up input audio source to read from specified file, loop after 5
761 // seconds, and deliver blocks of 10 ms.
762 const std::string input_file_name =
763 webrtc::test::ResourcePath("audio_coding/speech_mono_16kHz", "pcm");
764 audio_loop_.Init(input_file_name, 5 * kSampleRateHz, kNumSamples10ms);
765 RegisterCodec(); // Must be called before the threads start below.
766 StartThreads();
767 }
768
769 void RegisterCodec() override {
770 static_assert(kSampleRateHz == 16000, "test designed for iSAC 16 kHz");
771 AudioCodingModule::Codec("ISAC", &codec_, kSampleRateHz, 1);
772 codec_.pltype = kPayloadType;
773
774 // Register iSAC codec in ACM, effectively unregistering the PCM16B codec
775 // registered in AudioCodingModuleTestOldApi::SetUp();
776 // Only register the decoder for now. The encoder is registered later.
kwibergda2bf4e2016-10-24 13:47:09 -0700777 ASSERT_EQ(true, acm_->RegisterReceiveCodec(codec_.pltype,
778 CodecInstToSdp(codec_)));
Henrik Lundina6aa6d92015-06-15 13:46:15 +0200779 }
780
781 void StartThreads() {
Peter Boström8c38e8b2015-11-26 17:45:47 +0100782 receive_thread_.Start();
783 receive_thread_.SetPriority(rtc::kRealtimePriority);
784 codec_registration_thread_.Start();
785 codec_registration_thread_.SetPriority(rtc::kRealtimePriority);
Henrik Lundina6aa6d92015-06-15 13:46:15 +0200786 }
787
nisseef8b61e2016-04-29 06:09:15 -0700788 void TearDown() override {
Henrik Lundina6aa6d92015-06-15 13:46:15 +0200789 AudioCodingModuleTestOldApi::TearDown();
Peter Boström8c38e8b2015-11-26 17:45:47 +0100790 receive_thread_.Stop();
791 codec_registration_thread_.Stop();
Henrik Lundina6aa6d92015-06-15 13:46:15 +0200792 }
793
794 EventTypeWrapper RunTest() {
795 return test_complete_->Wait(10 * 60 * 1000); // 10 minutes' timeout.
796 }
797
798 static bool CbReceiveThread(void* context) {
799 return reinterpret_cast<AcmReRegisterIsacMtTestOldApi*>(context)
800 ->CbReceiveImpl();
801 }
802
803 bool CbReceiveImpl() {
804 SleepMs(1);
ossu10a029e2016-03-01 00:41:31 -0800805 rtc::Buffer encoded;
Henrik Lundina6aa6d92015-06-15 13:46:15 +0200806 AudioEncoder::EncodedInfo info;
807 {
Tommi9090e0b2016-01-20 13:39:36 +0100808 rtc::CritScope lock(&crit_sect_);
Henrik Lundina6aa6d92015-06-15 13:46:15 +0200809 if (clock_->TimeInMilliseconds() < next_insert_packet_time_ms_) {
810 return true;
811 }
812 next_insert_packet_time_ms_ += kPacketSizeMs;
813 ++receive_packet_count_;
814
815 // Encode new frame.
816 uint32_t input_timestamp = rtp_header_.header.timestamp;
817 while (info.encoded_bytes == 0) {
kwiberg288886b2015-11-06 01:21:35 -0800818 info =
819 isac_encoder_->Encode(input_timestamp, audio_loop_.GetNextBlock(),
ossu10a029e2016-03-01 00:41:31 -0800820 &encoded);
Henrik Lundina6aa6d92015-06-15 13:46:15 +0200821 input_timestamp += 160; // 10 ms at 16 kHz.
822 }
823 EXPECT_EQ(rtp_header_.header.timestamp + kPacketSizeSamples,
824 input_timestamp);
825 EXPECT_EQ(rtp_header_.header.timestamp, info.encoded_timestamp);
826 EXPECT_EQ(rtp_header_.header.payloadType, info.payload_type);
827 }
828 // Now we're not holding the crit sect when calling ACM.
829
830 // Insert into ACM.
ossu10a029e2016-03-01 00:41:31 -0800831 EXPECT_EQ(0, acm_->IncomingPacket(encoded.data(), info.encoded_bytes,
Henrik Lundina6aa6d92015-06-15 13:46:15 +0200832 rtp_header_));
833
834 // Pull audio.
835 for (int i = 0; i < rtc::CheckedDivExact(kPacketSizeMs, 10); ++i) {
836 AudioFrame audio_frame;
henrik.lundind4ccb002016-05-17 12:21:55 -0700837 bool muted;
Henrik Lundina6aa6d92015-06-15 13:46:15 +0200838 EXPECT_EQ(0, acm_->PlayoutData10Ms(-1 /* default output frequency */,
henrik.lundind4ccb002016-05-17 12:21:55 -0700839 &audio_frame, &muted));
840 if (muted) {
841 ADD_FAILURE();
842 return false;
843 }
Henrik Lundina6aa6d92015-06-15 13:46:15 +0200844 fake_clock_->AdvanceTimeMilliseconds(10);
845 }
846 rtp_utility_->Forward(&rtp_header_);
847 return true;
848 }
849
850 static bool CbCodecRegistrationThread(void* context) {
851 return reinterpret_cast<AcmReRegisterIsacMtTestOldApi*>(context)
852 ->CbCodecRegistrationImpl();
853 }
854
855 bool CbCodecRegistrationImpl() {
856 SleepMs(1);
857 if (HasFatalFailure()) {
858 // End the test early if a fatal failure (ASSERT_*) has occurred.
859 test_complete_->Set();
860 }
Tommi9090e0b2016-01-20 13:39:36 +0100861 rtc::CritScope lock(&crit_sect_);
Henrik Lundina6aa6d92015-06-15 13:46:15 +0200862 if (!codec_registered_ &&
863 receive_packet_count_ > kRegisterAfterNumPackets) {
864 // Register the iSAC encoder.
865 EXPECT_EQ(0, acm_->RegisterSendCodec(codec_));
866 codec_registered_ = true;
867 }
868 if (codec_registered_ && receive_packet_count_ > kNumPackets) {
869 test_complete_->Set();
870 }
871 return true;
872 }
873
Peter Boström8c38e8b2015-11-26 17:45:47 +0100874 rtc::PlatformThread receive_thread_;
875 rtc::PlatformThread codec_registration_thread_;
kwiberg16c5a962016-02-15 02:27:22 -0800876 const std::unique_ptr<EventWrapper> test_complete_;
pbos5ad935c2016-01-25 03:52:44 -0800877 rtc::CriticalSection crit_sect_;
danilchap56359be2017-09-07 07:53:45 -0700878 bool codec_registered_ RTC_GUARDED_BY(crit_sect_);
879 int receive_packet_count_ RTC_GUARDED_BY(crit_sect_);
880 int64_t next_insert_packet_time_ms_ RTC_GUARDED_BY(crit_sect_);
kwiberg6ff045f2017-08-17 05:31:02 -0700881 std::unique_ptr<AudioEncoderIsacFloatImpl> isac_encoder_;
kwiberg16c5a962016-02-15 02:27:22 -0800882 std::unique_ptr<SimulatedClock> fake_clock_;
Henrik Lundina6aa6d92015-06-15 13:46:15 +0200883 test::AudioLoop audio_loop_;
884};
885
Peter Boströme2976c82016-01-04 22:44:05 +0100886#if defined(WEBRTC_IOS)
887#define MAYBE_DoTest DISABLED_DoTest
888#else
889#define MAYBE_DoTest DoTest
890#endif
891#if defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX)
892TEST_F(AcmReRegisterIsacMtTestOldApi, MAYBE_DoTest) {
Henrik Lundina6aa6d92015-06-15 13:46:15 +0200893 EXPECT_EQ(kEventSignaled, RunTest());
894}
Peter Boströme2976c82016-01-04 22:44:05 +0100895#endif
Henrik Lundina6aa6d92015-06-15 13:46:15 +0200896
henrikaa2c79402015-06-10 13:24:48 +0200897// Disabling all of these tests on iOS until file support has been added.
898// See https://code.google.com/p/webrtc/issues/detail?id=4752 for details.
899#if !defined(WEBRTC_IOS)
900
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000901class AcmReceiverBitExactnessOldApi : public ::testing::Test {
902 public:
kwiberg5b659c02015-12-11 07:33:59 -0800903 static std::string PlatformChecksum(std::string others,
904 std::string win64,
905 std::string android_arm32,
Henrik Lundinf474c192017-06-12 14:46:28 +0200906 std::string android_arm64,
907 std::string android_arm64_clang) {
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000908#if defined(_WIN32) && defined(WEBRTC_ARCH_64_BITS)
909 return win64;
kwiberg5b659c02015-12-11 07:33:59 -0800910#elif defined(WEBRTC_ANDROID) && defined(WEBRTC_ARCH_ARM)
911 return android_arm32;
912#elif defined(WEBRTC_ANDROID) && defined(WEBRTC_ARCH_ARM64)
Henrik Lundinf474c192017-06-12 14:46:28 +0200913#if defined(__clang__)
914 // Android ARM64 with Clang compiler
915 return android_arm64_clang;
916#else
917 // Android ARM64 with non-Clang compiler
kwiberg5b659c02015-12-11 07:33:59 -0800918 return android_arm64;
Henrik Lundinf474c192017-06-12 14:46:28 +0200919#endif // __clang__
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000920#else
921 return others;
922#endif
923 }
924
925 protected:
kwiberg4e14f092015-08-24 05:27:22 -0700926 struct ExternalDecoder {
927 int rtp_payload_type;
928 AudioDecoder* external_decoder;
929 int sample_rate_hz;
930 int num_channels;
henrik.lundin4cf61dd2015-12-09 06:20:58 -0800931 std::string name;
kwiberg4e14f092015-08-24 05:27:22 -0700932 };
933
kwiberg5adaf732016-10-04 09:33:27 -0700934 void Run(int output_freq_hz, const std::string& checksum_ref) {
935 Run(output_freq_hz, checksum_ref, CreateBuiltinAudioDecoderFactory(),
936 [](AudioCodingModule*) {});
937 }
938
kwiberg4e14f092015-08-24 05:27:22 -0700939 void Run(int output_freq_hz,
940 const std::string& checksum_ref,
kwiberg5adaf732016-10-04 09:33:27 -0700941 rtc::scoped_refptr<AudioDecoderFactory> decoder_factory,
942 rtc::FunctionView<void(AudioCodingModule*)> decoder_reg) {
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000943 const std::string input_file_name =
944 webrtc::test::ResourcePath("audio_coding/neteq_universal_new", "rtp");
kwiberg16c5a962016-02-15 02:27:22 -0800945 std::unique_ptr<test::RtpFileSource> packet_source(
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000946 test::RtpFileSource::Create(input_file_name));
947#ifdef WEBRTC_ANDROID
948 // Filter out iLBC and iSAC-swb since they are not supported on Android.
949 packet_source->FilterOutPayloadType(102); // iLBC.
950 packet_source->FilterOutPayloadType(104); // iSAC-swb.
951#endif
952
953 test::AudioChecksum checksum;
954 const std::string output_file_name =
955 webrtc::test::OutputPath() +
956 ::testing::UnitTest::GetInstance()
957 ->current_test_info()
958 ->test_case_name() +
959 "_" + ::testing::UnitTest::GetInstance()->current_test_info()->name() +
henrik.lundin24180012017-04-06 02:40:37 -0700960 "_output.wav";
961 test::OutputWavFile output_file(output_file_name, output_freq_hz);
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000962 test::AudioSinkFork output(&checksum, &output_file);
963
964 test::AcmReceiveTestOldApi test(
kwiberg5adaf732016-10-04 09:33:27 -0700965 packet_source.get(), &output, output_freq_hz,
966 test::AcmReceiveTestOldApi::kArbitraryChannels,
967 std::move(decoder_factory));
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000968 ASSERT_NO_FATAL_FAILURE(test.RegisterNetEqTestCodecs());
kwiberg5adaf732016-10-04 09:33:27 -0700969 decoder_reg(test.get_acm());
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000970 test.Run();
971
972 std::string checksum_string = checksum.Finish();
973 EXPECT_EQ(checksum_ref, checksum_string);
ivoce10c82d2015-12-08 05:03:28 -0800974
975 // Delete the output file.
976 remove(output_file_name.c_str());
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000977 }
978};
979
kwiberg866df662015-12-10 04:20:02 -0800980#if (defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX)) && \
Karl Wibergeb254b42017-11-01 15:08:12 +0100981 defined(WEBRTC_CODEC_ILBC)
Peter Boströme2976c82016-01-04 22:44:05 +0100982TEST_F(AcmReceiverBitExactnessOldApi, 8kHzOutput) {
soren9f2c18e2017-04-10 02:22:46 -0700983 Run(8000, PlatformChecksum("2adede965c6f87de7142c51552111d08",
984 "028c0fc414b1c9ab7e582dccdf381e98",
985 "36c95170c1393d4b765d1c17b61ef977",
Henrik Lundinf474c192017-06-12 14:46:28 +0200986 "4598140b5e4f7ee66c5adad609e65a3e",
987 "bac5db6dff44323be401060f1279a532"));
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000988}
989
Peter Boströme2976c82016-01-04 22:44:05 +0100990TEST_F(AcmReceiverBitExactnessOldApi, 16kHzOutput) {
soren9f2c18e2017-04-10 02:22:46 -0700991 Run(16000, PlatformChecksum("c2550a3db7632de409e8db0093df1c12",
992 "edd31f4b6665cd5b9041fb93f2316594",
993 "22128bca51650cb61c80bed63b595603",
Henrik Lundinf474c192017-06-12 14:46:28 +0200994 "f2aad418af974a3b1694d5ae5cc2c3c7",
995 "61c3cb9386b9503feebcb829c9be54bd"));
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000996}
997
Peter Boströme2976c82016-01-04 22:44:05 +0100998TEST_F(AcmReceiverBitExactnessOldApi, 32kHzOutput) {
soren9f2c18e2017-04-10 02:22:46 -0700999 Run(32000, PlatformChecksum("85e28d7950132d56f90b099c90f82153",
1000 "7b903f5c89997f271b405e63c245ef45",
1001 "8b8fc6c6fd1dcdcfb3dd90e1ce597f10",
Henrik Lundinf474c192017-06-12 14:46:28 +02001002 "100869c8dcde51346c2073e52a272d98",
1003 "fdec5301dc649a47d407382b587e14da"));
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +00001004}
1005
Peter Boströme2976c82016-01-04 22:44:05 +01001006TEST_F(AcmReceiverBitExactnessOldApi, 48kHzOutput) {
soren9f2c18e2017-04-10 02:22:46 -07001007 Run(48000, PlatformChecksum("ab611510e8fd6d5210a23cc04d3f0e8e",
1008 "d8609bc9b495d81f29779344c68bcc47",
1009 "ec5ebb90cda0ea5bb89e79d698af65de",
Henrik Lundinf474c192017-06-12 14:46:28 +02001010 "bd44bf97e7899186532f91235cef444d",
1011 "0baae2972cca142027d4af44f95f0bd5"));
kwiberg4e14f092015-08-24 05:27:22 -07001012}
1013
Peter Boströme2976c82016-01-04 22:44:05 +01001014TEST_F(AcmReceiverBitExactnessOldApi, 48kHzOutputExternalDecoder) {
kwiberg5adaf732016-10-04 09:33:27 -07001015 class ADFactory : public AudioDecoderFactory {
Peter Boströmd7b7ae82015-12-08 13:41:35 +01001016 public:
kwiberg5adaf732016-10-04 09:33:27 -07001017 ADFactory()
1018 : mock_decoder_(new MockAudioDecoder()),
1019 pcmu_decoder_(1),
1020 decode_forwarder_(&pcmu_decoder_),
1021 fact_(CreateBuiltinAudioDecoderFactory()) {
1022 // Set expectations on the mock decoder and also delegate the calls to
1023 // the real decoder.
1024 EXPECT_CALL(*mock_decoder_, IncomingPacket(_, _, _, _, _))
1025 .Times(AtLeast(1))
1026 .WillRepeatedly(
1027 Invoke(&pcmu_decoder_, &AudioDecoderPcmU::IncomingPacket));
1028 EXPECT_CALL(*mock_decoder_, SampleRateHz())
1029 .Times(AtLeast(1))
1030 .WillRepeatedly(
1031 Invoke(&pcmu_decoder_, &AudioDecoderPcmU::SampleRateHz));
1032 EXPECT_CALL(*mock_decoder_, Channels())
1033 .Times(AtLeast(1))
1034 .WillRepeatedly(Invoke(&pcmu_decoder_, &AudioDecoderPcmU::Channels));
1035 EXPECT_CALL(*mock_decoder_, DecodeInternal(_, _, _, _, _))
1036 .Times(AtLeast(1))
1037 .WillRepeatedly(Invoke(&decode_forwarder_, &DecodeForwarder::Decode));
1038 EXPECT_CALL(*mock_decoder_, HasDecodePlc())
1039 .Times(AtLeast(1))
1040 .WillRepeatedly(
1041 Invoke(&pcmu_decoder_, &AudioDecoderPcmU::HasDecodePlc));
1042 EXPECT_CALL(*mock_decoder_, PacketDuration(_, _))
1043 .Times(AtLeast(1))
1044 .WillRepeatedly(
1045 Invoke(&pcmu_decoder_, &AudioDecoderPcmU::PacketDuration));
1046 EXPECT_CALL(*mock_decoder_, Die());
1047 }
1048 std::vector<AudioCodecSpec> GetSupportedDecoders() override {
1049 return fact_->GetSupportedDecoders();
1050 }
kwibergd32bf752017-01-19 07:03:59 -08001051 bool IsSupportedDecoder(const SdpAudioFormat& format) override {
1052 return format.name == "MockPCMu" ? true
1053 : fact_->IsSupportedDecoder(format);
1054 }
kwiberg5adaf732016-10-04 09:33:27 -07001055 std::unique_ptr<AudioDecoder> MakeAudioDecoder(
1056 const SdpAudioFormat& format) override {
1057 return format.name == "MockPCMu" ? std::move(mock_decoder_)
1058 : fact_->MakeAudioDecoder(format);
Peter Boströmd7b7ae82015-12-08 13:41:35 +01001059 }
1060
1061 private:
kwiberg5adaf732016-10-04 09:33:27 -07001062 // Class intended to forward a call from a mock DecodeInternal to Decode on
1063 // the real decoder's Decode. DecodeInternal for the real decoder isn't
1064 // public.
1065 class DecodeForwarder {
1066 public:
henrik.lundinbf7c6202016-10-06 01:53:31 -07001067 explicit DecodeForwarder(AudioDecoder* decoder) : decoder_(decoder) {}
kwiberg5adaf732016-10-04 09:33:27 -07001068 int Decode(const uint8_t* encoded,
1069 size_t encoded_len,
1070 int sample_rate_hz,
1071 int16_t* decoded,
1072 AudioDecoder::SpeechType* speech_type) {
1073 return decoder_->Decode(encoded, encoded_len, sample_rate_hz,
1074 decoder_->PacketDuration(encoded, encoded_len) *
1075 decoder_->Channels() * sizeof(int16_t),
1076 decoded, speech_type);
1077 }
1078
1079 private:
1080 AudioDecoder* const decoder_;
1081 };
1082
1083 std::unique_ptr<MockAudioDecoder> mock_decoder_;
1084 AudioDecoderPcmU pcmu_decoder_;
1085 DecodeForwarder decode_forwarder_;
1086 rtc::scoped_refptr<AudioDecoderFactory> fact_; // Fallback factory.
Peter Boströmd7b7ae82015-12-08 13:41:35 +01001087 };
1088
kwiberg5adaf732016-10-04 09:33:27 -07001089 rtc::scoped_refptr<rtc::RefCountedObject<ADFactory>> factory(
1090 new rtc::RefCountedObject<ADFactory>);
soren9f2c18e2017-04-10 02:22:46 -07001091 Run(48000, PlatformChecksum("ab611510e8fd6d5210a23cc04d3f0e8e",
1092 "d8609bc9b495d81f29779344c68bcc47",
1093 "ec5ebb90cda0ea5bb89e79d698af65de",
Henrik Lundinf474c192017-06-12 14:46:28 +02001094 "bd44bf97e7899186532f91235cef444d",
1095 "0baae2972cca142027d4af44f95f0bd5"),
kwiberg5adaf732016-10-04 09:33:27 -07001096 factory, [](AudioCodingModule* acm) {
1097 acm->RegisterReceiveCodec(0, {"MockPCMu", 8000, 1});
1098 });
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +00001099}
Peter Boströme2976c82016-01-04 22:44:05 +01001100#endif
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +00001101
1102// This test verifies bit exactness for the send-side of ACM. The test setup is
1103// a chain of three different test classes:
1104//
1105// test::AcmSendTest -> AcmSenderBitExactness -> test::AcmReceiveTest
1106//
1107// The receiver side is driving the test by requesting new packets from
1108// AcmSenderBitExactness::NextPacket(). This method, in turn, asks for the
1109// packet from test::AcmSendTest::NextPacket, which inserts audio from the
1110// input file until one packet is produced. (The input file loops indefinitely.)
1111// Before passing the packet to the receiver, this test class verifies the
1112// packet header and updates a payload checksum with the new payload. The
1113// decoded output from the receiver is also verified with a (separate) checksum.
1114class AcmSenderBitExactnessOldApi : public ::testing::Test,
1115 public test::PacketSource {
1116 protected:
1117 static const int kTestDurationMs = 1000;
1118
1119 AcmSenderBitExactnessOldApi()
1120 : frame_size_rtp_timestamps_(0),
1121 packet_count_(0),
1122 payload_type_(0),
1123 last_sequence_number_(0),
1124 last_timestamp_(0) {}
1125
1126 // Sets up the test::AcmSendTest object. Returns true on success, otherwise
1127 // false.
1128 bool SetUpSender() {
1129 const std::string input_file_name =
1130 webrtc::test::ResourcePath("audio_coding/testfile32kHz", "pcm");
1131 // Note that |audio_source_| will loop forever. The test duration is set
1132 // explicitly by |kTestDurationMs|.
1133 audio_source_.reset(new test::InputAudioFile(input_file_name));
1134 static const int kSourceRateHz = 32000;
1135 send_test_.reset(new test::AcmSendTestOldApi(
1136 audio_source_.get(), kSourceRateHz, kTestDurationMs));
1137 return send_test_.get() != NULL;
1138 }
1139
1140 // Registers a send codec in the test::AcmSendTest object. Returns true on
1141 // success, false on failure.
1142 bool RegisterSendCodec(const char* payload_name,
1143 int sampling_freq_hz,
1144 int channels,
1145 int payload_type,
1146 int frame_size_samples,
1147 int frame_size_rtp_timestamps) {
1148 payload_type_ = payload_type;
1149 frame_size_rtp_timestamps_ = frame_size_rtp_timestamps;
1150 return send_test_->RegisterCodec(payload_name,
1151 sampling_freq_hz,
1152 channels,
1153 payload_type,
1154 frame_size_samples);
1155 }
1156
kwiberg12cfc9b2015-09-08 05:57:53 -07001157 bool RegisterExternalSendCodec(AudioEncoder* external_speech_encoder,
Karl Wiberg7e0c7d42015-05-18 14:52:29 +02001158 int payload_type) {
1159 payload_type_ = payload_type;
Mirko Bonadei737e0732017-10-19 09:00:17 +02001160 frame_size_rtp_timestamps_ = rtc::checked_cast<uint32_t>(
Karl Wiberg7e0c7d42015-05-18 14:52:29 +02001161 external_speech_encoder->Num10MsFramesInNextPacket() *
Mirko Bonadei737e0732017-10-19 09:00:17 +02001162 external_speech_encoder->RtpTimestampRateHz() / 100);
Karl Wiberg7e0c7d42015-05-18 14:52:29 +02001163 return send_test_->RegisterExternalCodec(external_speech_encoder);
1164 }
1165
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +00001166 // Runs the test. SetUpSender() and RegisterSendCodec() must have been called
1167 // before calling this method.
1168 void Run(const std::string& audio_checksum_ref,
1169 const std::string& payload_checksum_ref,
1170 int expected_packets,
1171 test::AcmReceiveTestOldApi::NumOutputChannels expected_channels) {
1172 // Set up the receiver used to decode the packets and verify the decoded
1173 // output.
1174 test::AudioChecksum audio_checksum;
1175 const std::string output_file_name =
1176 webrtc::test::OutputPath() +
1177 ::testing::UnitTest::GetInstance()
1178 ->current_test_info()
1179 ->test_case_name() +
1180 "_" + ::testing::UnitTest::GetInstance()->current_test_info()->name() +
henrik.lundin24180012017-04-06 02:40:37 -07001181 "_output.wav";
1182 const int kOutputFreqHz = 8000;
1183 test::OutputWavFile output_file(output_file_name, kOutputFreqHz);
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +00001184 // Have the output audio sent both to file and to the checksum calculator.
1185 test::AudioSinkFork output(&audio_checksum, &output_file);
kwiberg5adaf732016-10-04 09:33:27 -07001186 test::AcmReceiveTestOldApi receive_test(this, &output, kOutputFreqHz,
1187 expected_channels,
1188 CreateBuiltinAudioDecoderFactory());
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +00001189 ASSERT_NO_FATAL_FAILURE(receive_test.RegisterDefaultCodecs());
1190
1191 // This is where the actual test is executed.
1192 receive_test.Run();
1193
1194 // Extract and verify the audio checksum.
1195 std::string checksum_string = audio_checksum.Finish();
1196 EXPECT_EQ(audio_checksum_ref, checksum_string);
1197
1198 // Extract and verify the payload checksum.
1199 char checksum_result[rtc::Md5Digest::kSize];
1200 payload_checksum_.Finish(checksum_result, rtc::Md5Digest::kSize);
1201 checksum_string = rtc::hex_encode(checksum_result, rtc::Md5Digest::kSize);
1202 EXPECT_EQ(payload_checksum_ref, checksum_string);
1203
1204 // Verify number of packets produced.
1205 EXPECT_EQ(expected_packets, packet_count_);
ivoce10c82d2015-12-08 05:03:28 -08001206
1207 // Delete the output file.
1208 remove(output_file_name.c_str());
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +00001209 }
1210
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +00001211 // Inherited from test::PacketSource.
henrik.lundin46ba49c2016-05-24 22:50:47 -07001212 std::unique_ptr<test::Packet> NextPacket() override {
1213 auto packet = send_test_->NextPacket();
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +00001214 if (!packet)
1215 return NULL;
1216
henrik.lundin46ba49c2016-05-24 22:50:47 -07001217 VerifyPacket(packet.get());
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +00001218 // TODO(henrik.lundin) Save the packet to file as well.
1219
1220 // Pass it on to the caller. The caller becomes the owner of |packet|.
1221 return packet;
1222 }
1223
1224 // Verifies the packet.
1225 void VerifyPacket(const test::Packet* packet) {
1226 EXPECT_TRUE(packet->valid_header());
1227 // (We can check the header fields even if valid_header() is false.)
1228 EXPECT_EQ(payload_type_, packet->header().payloadType);
1229 if (packet_count_ > 0) {
1230 // This is not the first packet.
1231 uint16_t sequence_number_diff =
1232 packet->header().sequenceNumber - last_sequence_number_;
1233 EXPECT_EQ(1, sequence_number_diff);
1234 uint32_t timestamp_diff = packet->header().timestamp - last_timestamp_;
1235 EXPECT_EQ(frame_size_rtp_timestamps_, timestamp_diff);
1236 }
1237 ++packet_count_;
1238 last_sequence_number_ = packet->header().sequenceNumber;
1239 last_timestamp_ = packet->header().timestamp;
1240 // Update the checksum.
1241 payload_checksum_.Update(packet->payload(), packet->payload_length_bytes());
1242 }
1243
1244 void SetUpTest(const char* codec_name,
1245 int codec_sample_rate_hz,
1246 int channels,
1247 int payload_type,
1248 int codec_frame_size_samples,
1249 int codec_frame_size_rtp_timestamps) {
1250 ASSERT_TRUE(SetUpSender());
1251 ASSERT_TRUE(RegisterSendCodec(codec_name,
1252 codec_sample_rate_hz,
1253 channels,
1254 payload_type,
1255 codec_frame_size_samples,
1256 codec_frame_size_rtp_timestamps));
1257 }
1258
kwiberg12cfc9b2015-09-08 05:57:53 -07001259 void SetUpTestExternalEncoder(AudioEncoder* external_speech_encoder,
Karl Wiberg7e0c7d42015-05-18 14:52:29 +02001260 int payload_type) {
1261 ASSERT_TRUE(SetUpSender());
1262 ASSERT_TRUE(
1263 RegisterExternalSendCodec(external_speech_encoder, payload_type));
1264 }
1265
kwiberg16c5a962016-02-15 02:27:22 -08001266 std::unique_ptr<test::AcmSendTestOldApi> send_test_;
1267 std::unique_ptr<test::InputAudioFile> audio_source_;
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +00001268 uint32_t frame_size_rtp_timestamps_;
1269 int packet_count_;
1270 uint8_t payload_type_;
1271 uint16_t last_sequence_number_;
1272 uint32_t last_timestamp_;
1273 rtc::Md5Digest payload_checksum_;
1274};
1275
ossua1a040a2017-04-06 10:03:21 -07001276class AcmSenderBitExactnessNewApi : public AcmSenderBitExactnessOldApi {};
1277
Peter Boströme2976c82016-01-04 22:44:05 +01001278#if defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX)
1279TEST_F(AcmSenderBitExactnessOldApi, IsacWb30ms) {
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +00001280 ASSERT_NO_FATAL_FAILURE(SetUpTest("ISAC", 16000, 1, 103, 480, 480));
1281 Run(AcmReceiverBitExactnessOldApi::PlatformChecksum(
soren9f2c18e2017-04-10 02:22:46 -07001282 "2c9cb15d4ed55b5a0cadd04883bc73b0",
1283 "9336a9b993cbd8a751f0e8958e66c89c",
1284 "bd4682225f7c4ad5f2049f6769713ac2",
Henrik Lundinf474c192017-06-12 14:46:28 +02001285 "343f1f42be0607c61e6516aece424609",
1286 "2c9cb15d4ed55b5a0cadd04883bc73b0"),
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +00001287 AcmReceiverBitExactnessOldApi::PlatformChecksum(
kwiberg5b659c02015-12-11 07:33:59 -08001288 "3c79f16f34218271f3dca4e2b1dfe1bb",
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +00001289 "d42cb5195463da26c8129bbfe73a22e6",
1290 "83de248aea9c3c2bd680b6952401b4ca",
Henrik Lundinf474c192017-06-12 14:46:28 +02001291 "3c79f16f34218271f3dca4e2b1dfe1bb",
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +00001292 "3c79f16f34218271f3dca4e2b1dfe1bb"),
kwiberg5b659c02015-12-11 07:33:59 -08001293 33, test::AcmReceiveTestOldApi::kMonoOutput);
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +00001294}
1295
Peter Boströme2976c82016-01-04 22:44:05 +01001296TEST_F(AcmSenderBitExactnessOldApi, IsacWb60ms) {
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +00001297 ASSERT_NO_FATAL_FAILURE(SetUpTest("ISAC", 16000, 1, 103, 960, 960));
1298 Run(AcmReceiverBitExactnessOldApi::PlatformChecksum(
kwiberg5b659c02015-12-11 07:33:59 -08001299 "1ad29139a04782a33daad8c2b9b35875",
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +00001300 "14d63c5f08127d280e722e3191b73bdd",
soren9f2c18e2017-04-10 02:22:46 -07001301 "edcf26694c289e3d9691faf79b74f09f",
Henrik Lundinf474c192017-06-12 14:46:28 +02001302 "ef75e900e6f375e3061163c53fd09a63",
1303 "1ad29139a04782a33daad8c2b9b35875"),
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +00001304 AcmReceiverBitExactnessOldApi::PlatformChecksum(
kwiberg5b659c02015-12-11 07:33:59 -08001305 "9e0a0ab743ad987b55b8e14802769c56",
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +00001306 "ebe04a819d3a9d83a83a17f271e1139a",
1307 "97aeef98553b5a4b5a68f8b716e8eaf0",
Henrik Lundinf474c192017-06-12 14:46:28 +02001308 "9e0a0ab743ad987b55b8e14802769c56",
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +00001309 "9e0a0ab743ad987b55b8e14802769c56"),
kwiberg5b659c02015-12-11 07:33:59 -08001310 16, test::AcmReceiveTestOldApi::kMonoOutput);
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +00001311}
kwiberg98ab3a42015-09-30 21:54:21 -07001312#endif
1313
Peter Boströme2976c82016-01-04 22:44:05 +01001314#if defined(WEBRTC_ANDROID)
1315#define MAYBE_IsacSwb30ms DISABLED_IsacSwb30ms
1316#else
1317#define MAYBE_IsacSwb30ms IsacSwb30ms
1318#endif
1319#if defined(WEBRTC_CODEC_ISAC)
1320TEST_F(AcmSenderBitExactnessOldApi, MAYBE_IsacSwb30ms) {
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +00001321 ASSERT_NO_FATAL_FAILURE(SetUpTest("ISAC", 32000, 1, 104, 960, 960));
1322 Run(AcmReceiverBitExactnessOldApi::PlatformChecksum(
kwiberg5b659c02015-12-11 07:33:59 -08001323 "5683b58da0fbf2063c7adc2e6bfb3fb8",
1324 "2b3c387d06f00b7b7aad4c9be56fb83d", "android_arm32_audio",
Henrik Lundinf474c192017-06-12 14:46:28 +02001325 "android_arm64_audio", "android_arm64_clang_audio"),
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +00001326 AcmReceiverBitExactnessOldApi::PlatformChecksum(
kwiberg5b659c02015-12-11 07:33:59 -08001327 "ce86106a93419aefb063097108ec94ab",
1328 "bcc2041e7744c7ebd9f701866856849c", "android_arm32_payload",
Henrik Lundinf474c192017-06-12 14:46:28 +02001329 "android_arm64_payload", "android_arm64_clang_payload"),
kwiberg@webrtc.orgbe96bfb2015-02-19 15:10:20 +00001330 33, test::AcmReceiveTestOldApi::kMonoOutput);
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +00001331}
Peter Boströme2976c82016-01-04 22:44:05 +01001332#endif
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +00001333
1334TEST_F(AcmSenderBitExactnessOldApi, Pcm16_8000khz_10ms) {
1335 ASSERT_NO_FATAL_FAILURE(SetUpTest("L16", 8000, 1, 107, 80, 80));
1336 Run("de4a98e1406f8b798d99cd0704e862e2",
1337 "c1edd36339ce0326cc4550041ad719a0",
1338 100,
1339 test::AcmReceiveTestOldApi::kMonoOutput);
1340}
1341
1342TEST_F(AcmSenderBitExactnessOldApi, Pcm16_16000khz_10ms) {
1343 ASSERT_NO_FATAL_FAILURE(SetUpTest("L16", 16000, 1, 108, 160, 160));
1344 Run("ae646d7b68384a1269cc080dd4501916",
1345 "ad786526383178b08d80d6eee06e9bad",
1346 100,
1347 test::AcmReceiveTestOldApi::kMonoOutput);
1348}
1349
1350TEST_F(AcmSenderBitExactnessOldApi, Pcm16_32000khz_10ms) {
1351 ASSERT_NO_FATAL_FAILURE(SetUpTest("L16", 32000, 1, 109, 320, 320));
1352 Run("7fe325e8fbaf755e3c5df0b11a4774fb",
1353 "5ef82ea885e922263606c6fdbc49f651",
1354 100,
1355 test::AcmReceiveTestOldApi::kMonoOutput);
1356}
1357
1358TEST_F(AcmSenderBitExactnessOldApi, Pcm16_stereo_8000khz_10ms) {
1359 ASSERT_NO_FATAL_FAILURE(SetUpTest("L16", 8000, 2, 111, 80, 80));
1360 Run("fb263b74e7ac3de915474d77e4744ceb",
1361 "62ce5adb0d4965d0a52ec98ae7f98974",
1362 100,
1363 test::AcmReceiveTestOldApi::kStereoOutput);
1364}
1365
1366TEST_F(AcmSenderBitExactnessOldApi, Pcm16_stereo_16000khz_10ms) {
1367 ASSERT_NO_FATAL_FAILURE(SetUpTest("L16", 16000, 2, 112, 160, 160));
1368 Run("d09e9239553649d7ac93e19d304281fd",
1369 "41ca8edac4b8c71cd54fd9f25ec14870",
1370 100,
1371 test::AcmReceiveTestOldApi::kStereoOutput);
1372}
1373
1374TEST_F(AcmSenderBitExactnessOldApi, Pcm16_stereo_32000khz_10ms) {
1375 ASSERT_NO_FATAL_FAILURE(SetUpTest("L16", 32000, 2, 113, 320, 320));
1376 Run("5f025d4f390982cc26b3d92fe02e3044",
1377 "50e58502fb04421bf5b857dda4c96879",
1378 100,
1379 test::AcmReceiveTestOldApi::kStereoOutput);
1380}
1381
1382TEST_F(AcmSenderBitExactnessOldApi, Pcmu_20ms) {
1383 ASSERT_NO_FATAL_FAILURE(SetUpTest("PCMU", 8000, 1, 0, 160, 160));
1384 Run("81a9d4c0bb72e9becc43aef124c981e9",
1385 "8f9b8750bd80fe26b6cbf6659b89f0f9",
1386 50,
1387 test::AcmReceiveTestOldApi::kMonoOutput);
1388}
1389
1390TEST_F(AcmSenderBitExactnessOldApi, Pcma_20ms) {
1391 ASSERT_NO_FATAL_FAILURE(SetUpTest("PCMA", 8000, 1, 8, 160, 160));
1392 Run("39611f798969053925a49dc06d08de29",
1393 "6ad745e55aa48981bfc790d0eeef2dd1",
1394 50,
1395 test::AcmReceiveTestOldApi::kMonoOutput);
1396}
1397
1398TEST_F(AcmSenderBitExactnessOldApi, Pcmu_stereo_20ms) {
1399 ASSERT_NO_FATAL_FAILURE(SetUpTest("PCMU", 8000, 2, 110, 160, 160));
1400 Run("437bec032fdc5cbaa0d5175430af7b18",
1401 "60b6f25e8d1e74cb679cfe756dd9bca5",
1402 50,
1403 test::AcmReceiveTestOldApi::kStereoOutput);
1404}
1405
1406TEST_F(AcmSenderBitExactnessOldApi, Pcma_stereo_20ms) {
1407 ASSERT_NO_FATAL_FAILURE(SetUpTest("PCMA", 8000, 2, 118, 160, 160));
1408 Run("a5c6d83c5b7cedbeff734238220a4b0c",
1409 "92b282c83efd20e7eeef52ba40842cf7",
1410 50,
1411 test::AcmReceiveTestOldApi::kStereoOutput);
1412}
1413
Peter Boströme2976c82016-01-04 22:44:05 +01001414#if defined(WEBRTC_ANDROID)
1415#define MAYBE_Ilbc_30ms DISABLED_Ilbc_30ms
kwiberg98ab3a42015-09-30 21:54:21 -07001416#else
Peter Boströme2976c82016-01-04 22:44:05 +01001417#define MAYBE_Ilbc_30ms Ilbc_30ms
kwiberg98ab3a42015-09-30 21:54:21 -07001418#endif
Peter Boströme2976c82016-01-04 22:44:05 +01001419#if defined(WEBRTC_CODEC_ILBC)
1420TEST_F(AcmSenderBitExactnessOldApi, MAYBE_Ilbc_30ms) {
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +00001421 ASSERT_NO_FATAL_FAILURE(SetUpTest("ILBC", 8000, 1, 102, 240, 240));
1422 Run(AcmReceiverBitExactnessOldApi::PlatformChecksum(
1423 "7b6ec10910debd9af08011d3ed5249f7",
kwiberg5b659c02015-12-11 07:33:59 -08001424 "7b6ec10910debd9af08011d3ed5249f7", "android_arm32_audio",
Henrik Lundinf474c192017-06-12 14:46:28 +02001425 "android_arm64_audio", "android_arm64_clang_audio"),
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +00001426 AcmReceiverBitExactnessOldApi::PlatformChecksum(
1427 "cfae2e9f6aba96e145f2bcdd5050ce78",
kwiberg5b659c02015-12-11 07:33:59 -08001428 "cfae2e9f6aba96e145f2bcdd5050ce78", "android_arm32_payload",
Henrik Lundinf474c192017-06-12 14:46:28 +02001429 "android_arm64_payload", "android_arm64_clang_payload"),
kwiberg5b659c02015-12-11 07:33:59 -08001430 33, test::AcmReceiveTestOldApi::kMonoOutput);
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +00001431}
kwiberg98ab3a42015-09-30 21:54:21 -07001432#endif
1433
Peter Boströme2976c82016-01-04 22:44:05 +01001434#if defined(WEBRTC_ANDROID)
1435#define MAYBE_G722_20ms DISABLED_G722_20ms
1436#else
1437#define MAYBE_G722_20ms G722_20ms
1438#endif
Peter Boströme2976c82016-01-04 22:44:05 +01001439TEST_F(AcmSenderBitExactnessOldApi, MAYBE_G722_20ms) {
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +00001440 ASSERT_NO_FATAL_FAILURE(SetUpTest("G722", 16000, 1, 9, 320, 160));
1441 Run(AcmReceiverBitExactnessOldApi::PlatformChecksum(
dkirovbroadsofte851a9a2017-03-14 10:00:27 -07001442 "e99c89be49a46325d03c0d990c292d68",
1443 "e99c89be49a46325d03c0d990c292d68", "android_arm32_audio",
Henrik Lundinf474c192017-06-12 14:46:28 +02001444 "android_arm64_audio", "android_arm64_clang_audio"),
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +00001445 AcmReceiverBitExactnessOldApi::PlatformChecksum(
1446 "fc68a87e1380614e658087cb35d5ca10",
kwiberg5b659c02015-12-11 07:33:59 -08001447 "fc68a87e1380614e658087cb35d5ca10", "android_arm32_payload",
Henrik Lundinf474c192017-06-12 14:46:28 +02001448 "android_arm64_payload", "android_arm64_clang_payload"),
kwiberg5b659c02015-12-11 07:33:59 -08001449 50, test::AcmReceiveTestOldApi::kMonoOutput);
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +00001450}
1451
Peter Boströme2976c82016-01-04 22:44:05 +01001452#if defined(WEBRTC_ANDROID)
1453#define MAYBE_G722_stereo_20ms DISABLED_G722_stereo_20ms
1454#else
1455#define MAYBE_G722_stereo_20ms G722_stereo_20ms
1456#endif
Peter Boströme2976c82016-01-04 22:44:05 +01001457TEST_F(AcmSenderBitExactnessOldApi, MAYBE_G722_stereo_20ms) {
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +00001458 ASSERT_NO_FATAL_FAILURE(SetUpTest("G722", 16000, 2, 119, 320, 160));
1459 Run(AcmReceiverBitExactnessOldApi::PlatformChecksum(
dkirovbroadsofte851a9a2017-03-14 10:00:27 -07001460 "e280aed283e499d37091b481ca094807",
1461 "e280aed283e499d37091b481ca094807", "android_arm32_audio",
Henrik Lundinf474c192017-06-12 14:46:28 +02001462 "android_arm64_audio", "android_arm64_clang_audio"),
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +00001463 AcmReceiverBitExactnessOldApi::PlatformChecksum(
1464 "66516152eeaa1e650ad94ff85f668dac",
kwiberg5b659c02015-12-11 07:33:59 -08001465 "66516152eeaa1e650ad94ff85f668dac", "android_arm32_payload",
Henrik Lundinf474c192017-06-12 14:46:28 +02001466 "android_arm64_payload", "android_arm64_clang_payload"),
kwiberg5b659c02015-12-11 07:33:59 -08001467 50, test::AcmReceiveTestOldApi::kStereoOutput);
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +00001468}
1469
minyue-webrtc516711c2017-07-27 17:45:49 +02001470TEST_F(AcmSenderBitExactnessOldApi, Opus_stereo_20ms) {
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +00001471 ASSERT_NO_FATAL_FAILURE(SetUpTest("opus", 48000, 2, 120, 960, 960));
1472 Run(AcmReceiverBitExactnessOldApi::PlatformChecksum(
minyue-webrtcadb58b82017-07-26 17:59:59 +02001473 "3e285b74510e62062fbd8142dacd16e9",
1474 "3e285b74510e62062fbd8142dacd16e9",
1475 "439e97ad1932c49923b5da029c17dd5e",
1476 "038ec90f5f3fc2320f3090f8ecef6bb7",
1477 "038ec90f5f3fc2320f3090f8ecef6bb7"),
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +00001478 AcmReceiverBitExactnessOldApi::PlatformChecksum(
minyue-webrtcadb58b82017-07-26 17:59:59 +02001479 "78cf8f03157358acdc69f6835caa0d9b",
1480 "78cf8f03157358acdc69f6835caa0d9b",
1481 "ab88b1a049c36bdfeb7e8b057ef6982a",
1482 "27fef7b799393347ec3b5694369a1c36",
1483 "27fef7b799393347ec3b5694369a1c36"),
kwiberg5b659c02015-12-11 07:33:59 -08001484 50, test::AcmReceiveTestOldApi::kStereoOutput);
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +00001485}
1486
minyue-webrtcadb58b82017-07-26 17:59:59 +02001487TEST_F(AcmSenderBitExactnessNewApi, MAYBE_OpusFromFormat_stereo_20ms) {
Karl Wiberg7275e182017-10-25 09:57:40 +02001488 const auto config = AudioEncoderOpus::SdpToConfig(
1489 SdpAudioFormat("opus", 48000, 2, {{"stereo", "1"}}));
1490 const auto encoder = AudioEncoderOpus::MakeAudioEncoder(*config, 120);
1491 ASSERT_NO_FATAL_FAILURE(SetUpTestExternalEncoder(encoder.get(), 120));
ossua1a040a2017-04-06 10:03:21 -07001492 Run(AcmReceiverBitExactnessOldApi::PlatformChecksum(
minyue-webrtcadb58b82017-07-26 17:59:59 +02001493 "3e285b74510e62062fbd8142dacd16e9",
1494 "3e285b74510e62062fbd8142dacd16e9",
1495 "439e97ad1932c49923b5da029c17dd5e",
1496 "038ec90f5f3fc2320f3090f8ecef6bb7",
1497 "038ec90f5f3fc2320f3090f8ecef6bb7"),
ossua1a040a2017-04-06 10:03:21 -07001498 AcmReceiverBitExactnessOldApi::PlatformChecksum(
minyue-webrtcadb58b82017-07-26 17:59:59 +02001499 "78cf8f03157358acdc69f6835caa0d9b",
1500 "78cf8f03157358acdc69f6835caa0d9b",
1501 "ab88b1a049c36bdfeb7e8b057ef6982a",
1502 "27fef7b799393347ec3b5694369a1c36",
1503 "27fef7b799393347ec3b5694369a1c36"),
ossua1a040a2017-04-06 10:03:21 -07001504 50, test::AcmReceiveTestOldApi::kStereoOutput);
1505}
1506
minyue-webrtc516711c2017-07-27 17:45:49 +02001507TEST_F(AcmSenderBitExactnessOldApi, Opus_stereo_20ms_voip) {
minyue@webrtc.org7dba7862015-01-20 16:01:50 +00001508 ASSERT_NO_FATAL_FAILURE(SetUpTest("opus", 48000, 2, 120, 960, 960));
1509 // If not set, default will be kAudio in case of stereo.
Minyue Li092041c2015-05-11 12:19:35 +02001510 EXPECT_EQ(0, send_test_->acm()->SetOpusApplication(kVoip));
minyue@webrtc.org7dba7862015-01-20 16:01:50 +00001511 Run(AcmReceiverBitExactnessOldApi::PlatformChecksum(
minyue-webrtcadb58b82017-07-26 17:59:59 +02001512 "b0325df4e8104f04e03af23c0b75800e",
1513 "b0325df4e8104f04e03af23c0b75800e",
1514 "1c81121f5d9286a5a865d01dbab22ce8",
1515 "11d547f89142e9ef03f37d7ca7f32379",
1516 "11d547f89142e9ef03f37d7ca7f32379"),
minyue@webrtc.org7dba7862015-01-20 16:01:50 +00001517 AcmReceiverBitExactnessOldApi::PlatformChecksum(
minyue-webrtcadb58b82017-07-26 17:59:59 +02001518 "4eab2259b6fe24c22dd242a113e0b3d9",
1519 "4eab2259b6fe24c22dd242a113e0b3d9",
1520 "839ea60399447268ee0f0262a50b75fd",
1521 "1815fd5589cad0c6f6cf946c76b81aeb",
1522 "1815fd5589cad0c6f6cf946c76b81aeb"),
kwiberg5b659c02015-12-11 07:33:59 -08001523 50, test::AcmReceiveTestOldApi::kStereoOutput);
minyue@webrtc.org7dba7862015-01-20 16:01:50 +00001524}
1525
minyue-webrtc516711c2017-07-27 17:45:49 +02001526TEST_F(AcmSenderBitExactnessNewApi, OpusFromFormat_stereo_20ms_voip) {
Karl Wiberg7275e182017-10-25 09:57:40 +02001527 const auto config = AudioEncoderOpus::SdpToConfig(
1528 SdpAudioFormat("opus", 48000, 2, {{"stereo", "1"}}));
1529 const auto encoder = AudioEncoderOpus::MakeAudioEncoder(*config, 120);
1530 ASSERT_NO_FATAL_FAILURE(SetUpTestExternalEncoder(encoder.get(), 120));
ossua1a040a2017-04-06 10:03:21 -07001531 // If not set, default will be kAudio in case of stereo.
1532 EXPECT_EQ(0, send_test_->acm()->SetOpusApplication(kVoip));
1533 Run(AcmReceiverBitExactnessOldApi::PlatformChecksum(
minyue-webrtcadb58b82017-07-26 17:59:59 +02001534 "b0325df4e8104f04e03af23c0b75800e",
1535 "b0325df4e8104f04e03af23c0b75800e",
1536 "1c81121f5d9286a5a865d01dbab22ce8",
1537 "11d547f89142e9ef03f37d7ca7f32379",
1538 "11d547f89142e9ef03f37d7ca7f32379"),
ossua1a040a2017-04-06 10:03:21 -07001539 AcmReceiverBitExactnessOldApi::PlatformChecksum(
minyue-webrtcadb58b82017-07-26 17:59:59 +02001540 "4eab2259b6fe24c22dd242a113e0b3d9",
1541 "4eab2259b6fe24c22dd242a113e0b3d9",
1542 "839ea60399447268ee0f0262a50b75fd",
1543 "1815fd5589cad0c6f6cf946c76b81aeb",
1544 "1815fd5589cad0c6f6cf946c76b81aeb"),
ossua1a040a2017-04-06 10:03:21 -07001545 50, test::AcmReceiveTestOldApi::kStereoOutput);
1546}
1547
Ivo Creusenadf89b72015-04-29 16:03:33 +02001548// This test is for verifying the SetBitRate function. The bitrate is changed at
1549// the beginning, and the number of generated bytes are checked.
ossua1a040a2017-04-06 10:03:21 -07001550class AcmSetBitRateTest : public ::testing::Test {
Ivo Creusenadf89b72015-04-29 16:03:33 +02001551 protected:
1552 static const int kTestDurationMs = 1000;
1553
1554 // Sets up the test::AcmSendTest object. Returns true on success, otherwise
1555 // false.
1556 bool SetUpSender() {
1557 const std::string input_file_name =
1558 webrtc::test::ResourcePath("audio_coding/testfile32kHz", "pcm");
1559 // Note that |audio_source_| will loop forever. The test duration is set
1560 // explicitly by |kTestDurationMs|.
1561 audio_source_.reset(new test::InputAudioFile(input_file_name));
1562 static const int kSourceRateHz = 32000;
1563 send_test_.reset(new test::AcmSendTestOldApi(
1564 audio_source_.get(), kSourceRateHz, kTestDurationMs));
1565 return send_test_.get();
1566 }
1567
1568 // Registers a send codec in the test::AcmSendTest object. Returns true on
1569 // success, false on failure.
1570 virtual bool RegisterSendCodec(const char* payload_name,
1571 int sampling_freq_hz,
1572 int channels,
1573 int payload_type,
1574 int frame_size_samples,
1575 int frame_size_rtp_timestamps) {
1576 return send_test_->RegisterCodec(payload_name, sampling_freq_hz, channels,
1577 payload_type, frame_size_samples);
1578 }
1579
ossua1a040a2017-04-06 10:03:21 -07001580 bool RegisterExternalSendCodec(AudioEncoder* external_speech_encoder,
1581 int payload_type) {
1582 return send_test_->RegisterExternalCodec(external_speech_encoder);
1583 }
1584
1585 void RunInner(int expected_total_bits) {
Ivo Creusenadf89b72015-04-29 16:03:33 +02001586 int nr_bytes = 0;
henrik.lundin46ba49c2016-05-24 22:50:47 -07001587 while (std::unique_ptr<test::Packet> next_packet =
1588 send_test_->NextPacket()) {
Mirko Bonadei737e0732017-10-19 09:00:17 +02001589 nr_bytes += rtc::checked_cast<int>(next_packet->payload_length_bytes());
Ivo Creusenadf89b72015-04-29 16:03:33 +02001590 }
1591 EXPECT_EQ(expected_total_bits, nr_bytes * 8);
1592 }
1593
1594 void SetUpTest(const char* codec_name,
1595 int codec_sample_rate_hz,
1596 int channels,
1597 int payload_type,
1598 int codec_frame_size_samples,
1599 int codec_frame_size_rtp_timestamps) {
1600 ASSERT_TRUE(SetUpSender());
1601 ASSERT_TRUE(RegisterSendCodec(codec_name, codec_sample_rate_hz, channels,
1602 payload_type, codec_frame_size_samples,
1603 codec_frame_size_rtp_timestamps));
1604 }
1605
kwiberg16c5a962016-02-15 02:27:22 -08001606 std::unique_ptr<test::AcmSendTestOldApi> send_test_;
1607 std::unique_ptr<test::InputAudioFile> audio_source_;
Ivo Creusenadf89b72015-04-29 16:03:33 +02001608};
1609
ossua1a040a2017-04-06 10:03:21 -07001610class AcmSetBitRateOldApi : public AcmSetBitRateTest {
1611 protected:
1612 // Runs the test. SetUpSender() must have been called and a codec must be set
1613 // up before calling this method.
1614 void Run(int target_bitrate_bps, int expected_total_bits) {
1615 ASSERT_TRUE(send_test_->acm());
1616 send_test_->acm()->SetBitRate(target_bitrate_bps);
1617 RunInner(expected_total_bits);
1618 }
1619};
1620
1621class AcmSetBitRateNewApi : public AcmSetBitRateTest {
1622 protected:
1623 // Runs the test. SetUpSender() must have been called and a codec must be set
1624 // up before calling this method.
1625 void Run(int expected_total_bits) { RunInner(expected_total_bits); }
1626};
1627
minyue-webrtc516711c2017-07-27 17:45:49 +02001628TEST_F(AcmSetBitRateOldApi, Opus_48khz_20ms_10kbps) {
Ivo Creusenadf89b72015-04-29 16:03:33 +02001629 ASSERT_NO_FATAL_FAILURE(SetUpTest("opus", 48000, 1, 107, 960, 960));
1630#if defined(WEBRTC_ANDROID)
minyue-webrtcadb58b82017-07-26 17:59:59 +02001631 Run(10000, 8640);
Ivo Creusenadf89b72015-04-29 16:03:33 +02001632#else
minyue-webrtcadb58b82017-07-26 17:59:59 +02001633 Run(10000, 8680);
henrik.lundinbf7c6202016-10-06 01:53:31 -07001634#endif // WEBRTC_ANDROID
Ivo Creusenadf89b72015-04-29 16:03:33 +02001635}
1636
minyue-webrtc516711c2017-07-27 17:45:49 +02001637TEST_F(AcmSetBitRateNewApi, OpusFromFormat_48khz_20ms_10kbps) {
Karl Wiberg7275e182017-10-25 09:57:40 +02001638 const auto config = AudioEncoderOpus::SdpToConfig(
1639 SdpAudioFormat("opus", 48000, 2, {{"maxaveragebitrate", "10000"}}));
1640 const auto encoder = AudioEncoderOpus::MakeAudioEncoder(*config, 107);
ossua1a040a2017-04-06 10:03:21 -07001641 ASSERT_TRUE(SetUpSender());
Karl Wiberg7275e182017-10-25 09:57:40 +02001642 ASSERT_TRUE(RegisterExternalSendCodec(encoder.get(), 107));
ossua1a040a2017-04-06 10:03:21 -07001643#if defined(WEBRTC_ANDROID)
minyue-webrtcadb58b82017-07-26 17:59:59 +02001644 RunInner(8640);
ossua1a040a2017-04-06 10:03:21 -07001645#else
minyue-webrtcadb58b82017-07-26 17:59:59 +02001646 RunInner(8680);
ossua1a040a2017-04-06 10:03:21 -07001647#endif // WEBRTC_ANDROID
1648}
1649
minyue-webrtc516711c2017-07-27 17:45:49 +02001650TEST_F(AcmSetBitRateOldApi, Opus_48khz_20ms_50kbps) {
Ivo Creusenadf89b72015-04-29 16:03:33 +02001651 ASSERT_NO_FATAL_FAILURE(SetUpTest("opus", 48000, 1, 107, 960, 960));
1652#if defined(WEBRTC_ANDROID)
minyue-webrtcadb58b82017-07-26 17:59:59 +02001653 Run(50000, 45792);
Ivo Creusenadf89b72015-04-29 16:03:33 +02001654#else
minyue-webrtcadb58b82017-07-26 17:59:59 +02001655 Run(50000, 45520);
henrik.lundinbf7c6202016-10-06 01:53:31 -07001656#endif // WEBRTC_ANDROID
Ivo Creusenadf89b72015-04-29 16:03:33 +02001657}
1658
minyue-webrtc516711c2017-07-27 17:45:49 +02001659TEST_F(AcmSetBitRateNewApi, OpusFromFormat_48khz_20ms_50kbps) {
Karl Wiberg7275e182017-10-25 09:57:40 +02001660 const auto config = AudioEncoderOpus::SdpToConfig(
1661 SdpAudioFormat("opus", 48000, 2, {{"maxaveragebitrate", "50000"}}));
1662 const auto encoder = AudioEncoderOpus::MakeAudioEncoder(*config, 107);
ossua1a040a2017-04-06 10:03:21 -07001663 ASSERT_TRUE(SetUpSender());
Karl Wiberg7275e182017-10-25 09:57:40 +02001664 ASSERT_TRUE(RegisterExternalSendCodec(encoder.get(), 107));
ossua1a040a2017-04-06 10:03:21 -07001665#if defined(WEBRTC_ANDROID)
minyue-webrtcadb58b82017-07-26 17:59:59 +02001666 RunInner(45792);
ossua1a040a2017-04-06 10:03:21 -07001667#else
minyue-webrtcadb58b82017-07-26 17:59:59 +02001668 RunInner(45520);
ossua1a040a2017-04-06 10:03:21 -07001669#endif // WEBRTC_ANDROID
1670}
1671
Ivo Creusenadf89b72015-04-29 16:03:33 +02001672// The result on the Android platforms is inconsistent for this test case.
1673// On android_rel the result is different from android and android arm64 rel.
minyue-webrtc516711c2017-07-27 17:45:49 +02001674#if defined(WEBRTC_ANDROID)
Peter Boströme2976c82016-01-04 22:44:05 +01001675#define MAYBE_Opus_48khz_20ms_100kbps DISABLED_Opus_48khz_20ms_100kbps
ossua1a040a2017-04-06 10:03:21 -07001676#define MAYBE_OpusFromFormat_48khz_20ms_100kbps \
1677 DISABLED_OpusFromFormat_48khz_20ms_100kbps
Peter Boströme2976c82016-01-04 22:44:05 +01001678#else
1679#define MAYBE_Opus_48khz_20ms_100kbps Opus_48khz_20ms_100kbps
ossua1a040a2017-04-06 10:03:21 -07001680#define MAYBE_OpusFromFormat_48khz_20ms_100kbps \
1681 OpusFromFormat_48khz_20ms_100kbps
Peter Boströme2976c82016-01-04 22:44:05 +01001682#endif
minyue-webrtcadb58b82017-07-26 17:59:59 +02001683TEST_F(AcmSetBitRateOldApi, MAYBE_Opus_48khz_20ms_100kbps) {
Ivo Creusenadf89b72015-04-29 16:03:33 +02001684 ASSERT_NO_FATAL_FAILURE(SetUpTest("opus", 48000, 1, 107, 960, 960));
minyue-webrtcadb58b82017-07-26 17:59:59 +02001685 Run(100000, 100832);
Ivo Creusenadf89b72015-04-29 16:03:33 +02001686}
1687
minyue-webrtcadb58b82017-07-26 17:59:59 +02001688TEST_F(AcmSetBitRateNewApi, MAYBE_OpusFromFormat_48khz_20ms_100kbps) {
Karl Wiberg7275e182017-10-25 09:57:40 +02001689 const auto config = AudioEncoderOpus::SdpToConfig(
1690 SdpAudioFormat("opus", 48000, 2, {{"maxaveragebitrate", "100000"}}));
1691 const auto encoder = AudioEncoderOpus::MakeAudioEncoder(*config, 107);
ossua1a040a2017-04-06 10:03:21 -07001692 ASSERT_TRUE(SetUpSender());
Karl Wiberg7275e182017-10-25 09:57:40 +02001693 ASSERT_TRUE(RegisterExternalSendCodec(encoder.get(), 107));
minyue-webrtcadb58b82017-07-26 17:59:59 +02001694 RunInner(100832);
ossua1a040a2017-04-06 10:03:21 -07001695}
1696
Ivo Creusenadf89b72015-04-29 16:03:33 +02001697// These next 2 tests ensure that the SetBitRate function has no effect on PCM
1698TEST_F(AcmSetBitRateOldApi, Pcm16_8khz_10ms_8kbps) {
1699 ASSERT_NO_FATAL_FAILURE(SetUpTest("L16", 8000, 1, 107, 80, 80));
1700 Run(8000, 128000);
1701}
1702
1703TEST_F(AcmSetBitRateOldApi, Pcm16_8khz_10ms_32kbps) {
1704 ASSERT_NO_FATAL_FAILURE(SetUpTest("L16", 8000, 1, 107, 80, 80));
1705 Run(32000, 128000);
1706}
1707
1708// This test is for verifying the SetBitRate function. The bitrate is changed
1709// in the middle, and the number of generated bytes are before and after the
1710// change are checked.
1711class AcmChangeBitRateOldApi : public AcmSetBitRateOldApi {
1712 protected:
1713 AcmChangeBitRateOldApi() : sampling_freq_hz_(0), frame_size_samples_(0) {}
1714
1715 // Registers a send codec in the test::AcmSendTest object. Returns true on
1716 // success, false on failure.
1717 bool RegisterSendCodec(const char* payload_name,
1718 int sampling_freq_hz,
1719 int channels,
1720 int payload_type,
1721 int frame_size_samples,
1722 int frame_size_rtp_timestamps) override {
1723 frame_size_samples_ = frame_size_samples;
1724 sampling_freq_hz_ = sampling_freq_hz;
1725 return AcmSetBitRateOldApi::RegisterSendCodec(
1726 payload_name, sampling_freq_hz, channels, payload_type,
1727 frame_size_samples, frame_size_rtp_timestamps);
1728 }
1729
1730 // Runs the test. SetUpSender() and RegisterSendCodec() must have been called
1731 // before calling this method.
1732 void Run(int target_bitrate_bps,
1733 int expected_before_switch_bits,
1734 int expected_after_switch_bits) {
1735 ASSERT_TRUE(send_test_->acm());
1736 int nr_packets =
1737 sampling_freq_hz_ * kTestDurationMs / (frame_size_samples_ * 1000);
1738 int nr_bytes_before = 0, nr_bytes_after = 0;
1739 int packet_counter = 0;
henrik.lundin46ba49c2016-05-24 22:50:47 -07001740 while (std::unique_ptr<test::Packet> next_packet =
1741 send_test_->NextPacket()) {
Ivo Creusenadf89b72015-04-29 16:03:33 +02001742 if (packet_counter == nr_packets / 2)
1743 send_test_->acm()->SetBitRate(target_bitrate_bps);
1744 if (packet_counter < nr_packets / 2)
Mirko Bonadei737e0732017-10-19 09:00:17 +02001745 nr_bytes_before += rtc::checked_cast<int>(
1746 next_packet->payload_length_bytes());
Ivo Creusenadf89b72015-04-29 16:03:33 +02001747 else
Mirko Bonadei737e0732017-10-19 09:00:17 +02001748 nr_bytes_after += rtc::checked_cast<int>(
1749 next_packet->payload_length_bytes());
Ivo Creusenadf89b72015-04-29 16:03:33 +02001750 packet_counter++;
Ivo Creusenadf89b72015-04-29 16:03:33 +02001751 }
1752 EXPECT_EQ(expected_before_switch_bits, nr_bytes_before * 8);
1753 EXPECT_EQ(expected_after_switch_bits, nr_bytes_after * 8);
1754 }
1755
1756 uint32_t sampling_freq_hz_;
1757 uint32_t frame_size_samples_;
1758};
1759
minyue-webrtc516711c2017-07-27 17:45:49 +02001760TEST_F(AcmChangeBitRateOldApi, Opus_48khz_20ms_10kbps_2) {
Ivo Creusenadf89b72015-04-29 16:03:33 +02001761 ASSERT_NO_FATAL_FAILURE(SetUpTest("opus", 48000, 1, 107, 960, 960));
1762#if defined(WEBRTC_ANDROID)
minyue-webrtcadb58b82017-07-26 17:59:59 +02001763 Run(10000, 29512, 4800);
Ivo Creusenadf89b72015-04-29 16:03:33 +02001764#else
minyue-webrtcadb58b82017-07-26 17:59:59 +02001765 Run(10000, 32200, 5368);
henrik.lundinbf7c6202016-10-06 01:53:31 -07001766#endif // WEBRTC_ANDROID
Ivo Creusenadf89b72015-04-29 16:03:33 +02001767}
1768
minyue-webrtc516711c2017-07-27 17:45:49 +02001769TEST_F(AcmChangeBitRateOldApi, Opus_48khz_20ms_50kbps_2) {
Ivo Creusenadf89b72015-04-29 16:03:33 +02001770 ASSERT_NO_FATAL_FAILURE(SetUpTest("opus", 48000, 1, 107, 960, 960));
1771#if defined(WEBRTC_ANDROID)
minyue-webrtcadb58b82017-07-26 17:59:59 +02001772 Run(50000, 29512, 23304);
Ivo Creusenadf89b72015-04-29 16:03:33 +02001773#else
minyue-webrtcadb58b82017-07-26 17:59:59 +02001774 Run(50000, 32200, 23920);
henrik.lundinbf7c6202016-10-06 01:53:31 -07001775#endif // WEBRTC_ANDROID
Ivo Creusenadf89b72015-04-29 16:03:33 +02001776}
1777
minyue-webrtc516711c2017-07-27 17:45:49 +02001778TEST_F(AcmChangeBitRateOldApi, Opus_48khz_20ms_100kbps_2) {
Ivo Creusenadf89b72015-04-29 16:03:33 +02001779 ASSERT_NO_FATAL_FAILURE(SetUpTest("opus", 48000, 1, 107, 960, 960));
1780#if defined(WEBRTC_ANDROID)
flim64a7eab2016-08-12 04:36:05 -07001781 #if defined(WEBRTC_ARCH_ARM64)
minyue-webrtcadb58b82017-07-26 17:59:59 +02001782 Run(100000, 29512, 50440);
flim64a7eab2016-08-12 04:36:05 -07001783 #else
minyue-webrtcadb58b82017-07-26 17:59:59 +02001784 Run(100000, 29512, 50496);
henrik.lundinbf7c6202016-10-06 01:53:31 -07001785 #endif // WEBRTC_ARCH_ARM64
Ivo Creusenadf89b72015-04-29 16:03:33 +02001786#else
minyue-webrtcadb58b82017-07-26 17:59:59 +02001787 Run(100000, 32200, 50448);
henrik.lundinbf7c6202016-10-06 01:53:31 -07001788#endif // WEBRTC_ANDROID
Ivo Creusenadf89b72015-04-29 16:03:33 +02001789}
1790
1791// These next 2 tests ensure that the SetBitRate function has no effect on PCM
1792TEST_F(AcmChangeBitRateOldApi, Pcm16_8khz_10ms_8kbps) {
1793 ASSERT_NO_FATAL_FAILURE(SetUpTest("L16", 8000, 1, 107, 80, 80));
1794 Run(8000, 64000, 64000);
1795}
1796
1797TEST_F(AcmChangeBitRateOldApi, Pcm16_8khz_10ms_32kbps) {
1798 ASSERT_NO_FATAL_FAILURE(SetUpTest("L16", 8000, 1, 107, 80, 80));
1799 Run(32000, 64000, 64000);
1800}
1801
Karl Wiberg7e0c7d42015-05-18 14:52:29 +02001802TEST_F(AcmSenderBitExactnessOldApi, External_Pcmu_20ms) {
1803 CodecInst codec_inst;
1804 codec_inst.channels = 1;
1805 codec_inst.pacsize = 160;
1806 codec_inst.pltype = 0;
kwiberg12cfc9b2015-09-08 05:57:53 -07001807 AudioEncoderPcmU encoder(codec_inst);
1808 MockAudioEncoder mock_encoder;
Karl Wiberg7e0c7d42015-05-18 14:52:29 +02001809 // Set expectations on the mock encoder and also delegate the calls to the
1810 // real encoder.
kwiberg6030a122016-03-08 06:01:31 -08001811 EXPECT_CALL(mock_encoder, Die());
kwiberg12cfc9b2015-09-08 05:57:53 -07001812 EXPECT_CALL(mock_encoder, SampleRateHz())
1813 .Times(AtLeast(1))
1814 .WillRepeatedly(Invoke(&encoder, &AudioEncoderPcmU::SampleRateHz));
1815 EXPECT_CALL(mock_encoder, NumChannels())
1816 .Times(AtLeast(1))
1817 .WillRepeatedly(Invoke(&encoder, &AudioEncoderPcmU::NumChannels));
1818 EXPECT_CALL(mock_encoder, RtpTimestampRateHz())
1819 .Times(AtLeast(1))
1820 .WillRepeatedly(Invoke(&encoder, &AudioEncoderPcmU::RtpTimestampRateHz));
Karl Wiberg7e0c7d42015-05-18 14:52:29 +02001821 EXPECT_CALL(mock_encoder, Num10MsFramesInNextPacket())
1822 .Times(AtLeast(1))
kwiberg12cfc9b2015-09-08 05:57:53 -07001823 .WillRepeatedly(
1824 Invoke(&encoder, &AudioEncoderPcmU::Num10MsFramesInNextPacket));
henrik.lundin6b4a5642015-06-22 06:35:09 -07001825 EXPECT_CALL(mock_encoder, GetTargetBitrate())
1826 .Times(AtLeast(1))
kwiberg12cfc9b2015-09-08 05:57:53 -07001827 .WillRepeatedly(Invoke(&encoder, &AudioEncoderPcmU::GetTargetBitrate));
ossu4f43fcf2016-03-04 00:54:32 -08001828 EXPECT_CALL(mock_encoder, EncodeImpl(_, _, _))
kwiberg12cfc9b2015-09-08 05:57:53 -07001829 .Times(AtLeast(1))
ossu10a029e2016-03-01 00:41:31 -08001830 .WillRepeatedly(Invoke(&encoder,
1831 static_cast<
1832 AudioEncoder::EncodedInfo(AudioEncoder::*)(
1833 uint32_t,
1834 rtc::ArrayView<const int16_t>,
1835 rtc::Buffer*)>(&AudioEncoderPcmU::Encode)));
kwiberg4dc94112015-11-11 08:34:21 -08001836 EXPECT_CALL(mock_encoder, SetFec(_))
1837 .Times(AtLeast(1))
1838 .WillRepeatedly(Invoke(&encoder, &AudioEncoderPcmU::SetFec));
Karl Wiberg7e0c7d42015-05-18 14:52:29 +02001839 ASSERT_NO_FATAL_FAILURE(
1840 SetUpTestExternalEncoder(&mock_encoder, codec_inst.pltype));
1841 Run("81a9d4c0bb72e9becc43aef124c981e9", "8f9b8750bd80fe26b6cbf6659b89f0f9",
1842 50, test::AcmReceiveTestOldApi::kMonoOutput);
1843}
1844
henrik.lundin@webrtc.org81a78932014-10-14 10:49:58 +00001845// This test fixture is implemented to run ACM and change the desired output
1846// frequency during the call. The input packets are simply PCM16b-wb encoded
1847// payloads with a constant value of |kSampleValue|. The test fixture itself
1848// acts as PacketSource in between the receive test class and the constant-
1849// payload packet source class. The output is both written to file, and analyzed
1850// in this test fixture.
1851class AcmSwitchingOutputFrequencyOldApi : public ::testing::Test,
1852 public test::PacketSource,
1853 public test::AudioSink {
1854 protected:
henrik.lundin@webrtc.org99e561f2014-10-15 08:50:00 +00001855 static const size_t kTestNumPackets = 50;
henrik.lundin@webrtc.org81a78932014-10-14 10:49:58 +00001856 static const int kEncodedSampleRateHz = 16000;
1857 static const size_t kPayloadLenSamples = 30 * kEncodedSampleRateHz / 1000;
1858 static const int kPayloadType = 108; // Default payload type for PCM16b-wb.
1859
1860 AcmSwitchingOutputFrequencyOldApi()
1861 : first_output_(true),
1862 num_packets_(0),
1863 packet_source_(kPayloadLenSamples,
1864 kSampleValue,
1865 kEncodedSampleRateHz,
1866 kPayloadType),
henrik.lundin@webrtc.org99e561f2014-10-15 08:50:00 +00001867 output_freq_2_(0),
henrik.lundin@webrtc.org81a78932014-10-14 10:49:58 +00001868 has_toggled_(false) {}
1869
henrik.lundin@webrtc.org99e561f2014-10-15 08:50:00 +00001870 void Run(int output_freq_1, int output_freq_2, int toggle_period_ms) {
henrik.lundin@webrtc.org81a78932014-10-14 10:49:58 +00001871 // Set up the receiver used to decode the packets and verify the decoded
1872 // output.
1873 const std::string output_file_name =
1874 webrtc::test::OutputPath() +
1875 ::testing::UnitTest::GetInstance()
1876 ->current_test_info()
1877 ->test_case_name() +
1878 "_" + ::testing::UnitTest::GetInstance()->current_test_info()->name() +
1879 "_output.pcm";
1880 test::OutputAudioFile output_file(output_file_name);
1881 // Have the output audio sent both to file and to the WriteArray method in
1882 // this class.
1883 test::AudioSinkFork output(this, &output_file);
1884 test::AcmReceiveTestToggleOutputFreqOldApi receive_test(
1885 this,
1886 &output,
henrik.lundin@webrtc.org99e561f2014-10-15 08:50:00 +00001887 output_freq_1,
1888 output_freq_2,
henrik.lundin@webrtc.org81a78932014-10-14 10:49:58 +00001889 toggle_period_ms,
1890 test::AcmReceiveTestOldApi::kMonoOutput);
1891 ASSERT_NO_FATAL_FAILURE(receive_test.RegisterDefaultCodecs());
henrik.lundin@webrtc.org99e561f2014-10-15 08:50:00 +00001892 output_freq_2_ = output_freq_2;
henrik.lundin@webrtc.org81a78932014-10-14 10:49:58 +00001893
1894 // This is where the actual test is executed.
1895 receive_test.Run();
ivoce10c82d2015-12-08 05:03:28 -08001896
1897 // Delete output file.
1898 remove(output_file_name.c_str());
henrik.lundin@webrtc.org81a78932014-10-14 10:49:58 +00001899 }
1900
1901 // Inherited from test::PacketSource.
henrik.lundin46ba49c2016-05-24 22:50:47 -07001902 std::unique_ptr<test::Packet> NextPacket() override {
henrik.lundin@webrtc.org81a78932014-10-14 10:49:58 +00001903 // Check if it is time to terminate the test. The packet source is of type
1904 // ConstantPcmPacketSource, which is infinite, so we must end the test
1905 // "manually".
1906 if (num_packets_++ > kTestNumPackets) {
1907 EXPECT_TRUE(has_toggled_);
1908 return NULL; // Test ended.
1909 }
1910
1911 // Get the next packet from the source.
1912 return packet_source_.NextPacket();
1913 }
1914
1915 // Inherited from test::AudioSink.
nisseef8b61e2016-04-29 06:09:15 -07001916 bool WriteArray(const int16_t* audio, size_t num_samples) override {
henrik.lundin@webrtc.org81a78932014-10-14 10:49:58 +00001917 // Skip checking the first output frame, since it has a number of zeros
1918 // due to how NetEq is initialized.
1919 if (first_output_) {
1920 first_output_ = false;
1921 return true;
1922 }
1923 for (size_t i = 0; i < num_samples; ++i) {
1924 EXPECT_EQ(kSampleValue, audio[i]);
1925 }
1926 if (num_samples ==
henrik.lundin@webrtc.org99e561f2014-10-15 08:50:00 +00001927 static_cast<size_t>(output_freq_2_ / 100)) // Size of 10 ms frame.
henrik.lundin@webrtc.org81a78932014-10-14 10:49:58 +00001928 has_toggled_ = true;
1929 // The return value does not say if the values match the expectation, just
1930 // that the method could process the samples.
1931 return true;
1932 }
1933
1934 const int16_t kSampleValue = 1000;
1935 bool first_output_;
1936 size_t num_packets_;
1937 test::ConstantPcmPacketSource packet_source_;
henrik.lundin@webrtc.org99e561f2014-10-15 08:50:00 +00001938 int output_freq_2_;
henrik.lundin@webrtc.org81a78932014-10-14 10:49:58 +00001939 bool has_toggled_;
1940};
1941
1942TEST_F(AcmSwitchingOutputFrequencyOldApi, TestWithoutToggling) {
1943 Run(16000, 16000, 1000);
1944}
1945
henrik.lundin@webrtc.org913f7b82014-10-21 06:54:23 +00001946TEST_F(AcmSwitchingOutputFrequencyOldApi, Toggle16KhzTo32Khz) {
henrik.lundin@webrtc.org81a78932014-10-14 10:49:58 +00001947 Run(16000, 32000, 1000);
1948}
henrik.lundin@webrtc.org99e561f2014-10-15 08:50:00 +00001949
1950TEST_F(AcmSwitchingOutputFrequencyOldApi, Toggle32KhzTo16Khz) {
1951 Run(32000, 16000, 1000);
1952}
1953
henrik.lundin@webrtc.org913f7b82014-10-21 06:54:23 +00001954TEST_F(AcmSwitchingOutputFrequencyOldApi, Toggle16KhzTo8Khz) {
henrik.lundin@webrtc.org99e561f2014-10-15 08:50:00 +00001955 Run(16000, 8000, 1000);
1956}
1957
1958TEST_F(AcmSwitchingOutputFrequencyOldApi, Toggle8KhzTo16Khz) {
1959 Run(8000, 16000, 1000);
1960}
henrikaa2c79402015-06-10 13:24:48 +02001961
1962#endif
1963
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +00001964} // namespace webrtc