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