Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 /* | |
| 2 * Copyright (c) 2015 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 "webrtc/modules/audio_processing/audio_processing_impl.h" | |
| 12 | |
| 13 #include <algorithm> | |
| 14 #include <vector> | |
| 15 | |
| 16 #include "testing/gmock/include/gmock/gmock.h" | |
| 17 #include "testing/gtest/include/gtest/gtest.h" | |
| 18 #include "webrtc/base/criticalsection.h" | |
| 19 #include "webrtc/config.h" | |
| 20 #include "webrtc/modules/audio_processing/test/test_utils.h" | |
| 21 #include "webrtc/modules/interface/module_common_types.h" | |
| 22 #include "webrtc/system_wrappers/include/event_wrapper.h" | |
| 23 #include "webrtc/system_wrappers/include/sleep.h" | |
| 24 #include "webrtc/system_wrappers/include/thread_wrapper.h" | |
| 25 #include "webrtc/test/random.h" | |
| 26 | |
| 27 namespace webrtc { | |
| 28 | |
| 29 namespace { | |
| 30 | |
| 31 // Type of the render thread APM API call to use in the test. | |
| 32 enum class RenderApiFunctionImplementation { | |
| 33 ProcessReverseStreamImplementation1, | |
| 34 ProcessReverseStreamImplementation2, | |
| 35 AnalyzeReverseStreamImplementation1, | |
| 36 AnalyzeReverseStreamImplementation2 | |
| 37 }; | |
|
the sun
2015/10/29 10:31:30
nit: space between the enum declarations
peah-webrtc
2015/10/29 14:26:51
Done.
| |
| 38 // Type of the capture thread APM API call to use in the test. | |
| 39 enum class CaptureApiFunctionImplementation { | |
| 40 ProcessStreamImplementation1, | |
| 41 ProcessStreamImplementation2, | |
| 42 ProcessStreamImplementation3 | |
| 43 }; | |
| 44 // The runtime parameter setting scheme to use in the test. | |
| 45 enum class RuntimeParameterSettingScheme { | |
| 46 SparseStreamMetadataChangeScheme, | |
| 47 ExtremeStreamMetadataChangeScheme, | |
| 48 FixedMonoStreamMetadataScheme, | |
| 49 FixedStereoStreamMetadataScheme | |
| 50 }; | |
| 51 enum class AecType { | |
| 52 BasicWebRtcAecSettings, | |
| 53 AecTurnedOff, | |
| 54 BasicWebRtcAecSettingsWithExtentedFilter, | |
| 55 BasicWebRtcAecSettingsWithDelayAgnosticAec, | |
| 56 BasicWebRtcAecSettingsWithAecMobile | |
| 57 }; | |
| 58 | |
| 59 // The configuration for the test to use. | |
| 60 struct TestConfig { | |
| 61 RenderApiFunctionImplementation render_api_function; | |
| 62 CaptureApiFunctionImplementation capture_api_function; | |
| 63 RuntimeParameterSettingScheme runtime_parameter_setting_scheme; | |
| 64 int initial_sample_rate_hz; | |
| 65 AecType aec_type; | |
| 66 int min_number_of_calls; | |
| 67 }; | |
| 68 | |
| 69 // Class for implementing the tests of the locks in the audio processing module. | |
| 70 class AudioProcessingImpLockTest : public ::testing::TestWithParam<TestConfig> { | |
| 71 public: | |
| 72 AudioProcessingImpLockTest() | |
| 73 : test_complete_(EventWrapper::Create()), | |
| 74 render_thread_( | |
| 75 ThreadWrapper::CreateThread(RenderThread, this, "render")), | |
| 76 capture_thread_( | |
| 77 ThreadWrapper::CreateThread(CaptureThread, this, "capture")), | |
| 78 stats_thread_(ThreadWrapper::CreateThread(StatsThread, this, "stats")), | |
| 79 rand_gen_(42U) { | |
| 80 // Set up the two-dimensional arrays needed for the APM API calls. | |
|
the sun
2015/10/29 10:31:30
Why doesn't this setting up go in the c-tors of th
peah-webrtc
2015/10/29 14:26:51
Done.
| |
| 81 capture_thread_state_.input_framechannels_.resize(2 * 480); | |
|
the sun
2015/10/29 10:31:30
nit: Use a constant for 480
peah-webrtc
2015/10/29 14:26:51
Done.
| |
| 82 capture_thread_state_.input_frame.resize(2); | |
| 83 capture_thread_state_.input_frame[0] = | |
| 84 &capture_thread_state_.input_framechannels_[0]; | |
| 85 capture_thread_state_.input_frame[1] = | |
| 86 &capture_thread_state_.input_framechannels_[480]; | |
| 87 | |
| 88 capture_thread_state_.output_frame_channels.resize(2 * 480); | |
| 89 capture_thread_state_.output_frame.resize(2); | |
| 90 capture_thread_state_.output_frame[0] = | |
| 91 &capture_thread_state_.output_frame_channels[0]; | |
| 92 capture_thread_state_.output_frame[1] = | |
| 93 &capture_thread_state_.output_frame_channels[480]; | |
| 94 | |
| 95 render_thread_state_.input_frame_channels.resize(2 * 480); | |
| 96 render_thread_state_.input_frame.resize(2); | |
| 97 render_thread_state_.input_frame[0] = | |
| 98 &render_thread_state_.input_frame_channels[0]; | |
| 99 render_thread_state_.input_frame[1] = | |
| 100 &render_thread_state_.input_frame_channels[480]; | |
| 101 | |
| 102 render_thread_state_.output_frame_channels.resize(2 * 480); | |
| 103 render_thread_state_.output_frame.resize(2); | |
| 104 render_thread_state_.output_frame[0] = | |
| 105 &render_thread_state_.output_frame_channels[0]; | |
| 106 render_thread_state_.output_frame[1] = | |
| 107 &render_thread_state_.output_frame_channels[480]; | |
| 108 } | |
| 109 | |
| 110 // Run the test with a timeout. | |
| 111 EventTypeWrapper RunTest() { | |
| 112 StartThreads(); | |
| 113 return test_complete_->Wait(kTestTimeOutLimit); | |
| 114 } | |
| 115 | |
| 116 void SetUp() override { | |
| 117 apm_.reset(AudioProcessingImpl::Create()); | |
| 118 test_config_ = static_cast<TestConfig>(GetParam()); | |
| 119 | |
| 120 ASSERT_EQ(apm_->kNoError, apm_->level_estimator()->Enable(true)); | |
| 121 ASSERT_EQ(apm_->kNoError, apm_->gain_control()->Enable(true)); | |
| 122 | |
| 123 ASSERT_EQ(apm_->kNoError, | |
| 124 apm_->gain_control()->set_mode(GainControl::kAdaptiveAnalog)); | |
| 125 ASSERT_EQ(apm_->kNoError, apm_->gain_control()->Enable(true)); | |
| 126 ASSERT_EQ(apm_->kNoError, | |
| 127 apm_->gain_control()->set_mode(GainControl::kFixedDigital)); | |
| 128 | |
| 129 ASSERT_EQ(apm_->kNoError, apm_->noise_suppression()->Enable(true)); | |
| 130 ASSERT_EQ(apm_->kNoError, apm_->voice_detection()->Enable(true)); | |
| 131 | |
| 132 Config config; | |
| 133 if (test_config_.aec_type == AecType::AecTurnedOff) { | |
| 134 ASSERT_EQ(apm_->kNoError, apm_->echo_control_mobile()->Enable(false)); | |
| 135 ASSERT_EQ(apm_->kNoError, apm_->echo_cancellation()->Enable(false)); | |
| 136 } else { | |
| 137 if (test_config_.aec_type == | |
| 138 AecType::BasicWebRtcAecSettingsWithAecMobile) { | |
| 139 ASSERT_EQ(apm_->kNoError, apm_->echo_control_mobile()->Enable(true)); | |
| 140 ASSERT_EQ(apm_->kNoError, apm_->echo_cancellation()->Enable(false)); | |
| 141 } else { | |
| 142 ASSERT_EQ(apm_->kNoError, apm_->echo_control_mobile()->Enable(false)); | |
| 143 ASSERT_EQ(apm_->kNoError, apm_->echo_cancellation()->Enable(true)); | |
| 144 ASSERT_EQ(apm_->kNoError, | |
| 145 apm_->echo_cancellation()->enable_metrics(true)); | |
| 146 ASSERT_EQ(apm_->kNoError, | |
| 147 apm_->echo_cancellation()->enable_delay_logging(true)); | |
| 148 | |
| 149 config.Set<ExtendedFilter>(new ExtendedFilter( | |
| 150 test_config_.aec_type == | |
| 151 AecType::BasicWebRtcAecSettingsWithExtentedFilter)); | |
| 152 | |
| 153 config.Set<DelayAgnostic>(new DelayAgnostic( | |
| 154 test_config_.aec_type == | |
| 155 AecType::BasicWebRtcAecSettingsWithDelayAgnosticAec)); | |
| 156 | |
| 157 apm_->SetExtraOptions(config); | |
| 158 } | |
| 159 } | |
| 160 } | |
| 161 | |
| 162 void TearDown() override { | |
| 163 render_thread_->Stop(); | |
| 164 capture_thread_->Stop(); | |
| 165 stats_thread_->Stop(); | |
| 166 } | |
| 167 | |
| 168 // Function for generating the test configurations to use in the brief tests. | |
| 169 static std::vector<TestConfig> GenerateBriefTestConfigs() { | |
|
the sun
2015/10/29 10:31:30
Move this function out of this class. Maybe put it
peah-webrtc
2015/10/29 14:26:51
Done.
| |
| 170 std::vector<TestConfig> test_configs; | |
| 171 for (int aec = static_cast<int>( | |
| 172 AecType::BasicWebRtcAecSettingsWithDelayAgnosticAec); | |
| 173 aec <= static_cast<int>(AecType::BasicWebRtcAecSettingsWithAecMobile); | |
| 174 aec++) { | |
| 175 TestConfig test_config; | |
| 176 | |
| 177 test_config.min_number_of_calls = 300; | |
| 178 | |
| 179 // Perform tests only with the extreme runtime parameter setting scheme. | |
| 180 test_config.runtime_parameter_setting_scheme = | |
| 181 RuntimeParameterSettingScheme::ExtremeStreamMetadataChangeScheme; | |
| 182 | |
| 183 // Only test 16 kHz for this test suite. | |
| 184 test_config.initial_sample_rate_hz = 16000; | |
| 185 | |
| 186 // Create test config for the second processing API function set. | |
| 187 test_config.render_api_function = | |
| 188 RenderApiFunctionImplementation::ProcessReverseStreamImplementation2; | |
| 189 test_config.capture_api_function = | |
| 190 CaptureApiFunctionImplementation::ProcessStreamImplementation2; | |
| 191 | |
| 192 // Create test config for the first processing API function set. | |
| 193 test_configs.push_back(test_config); | |
| 194 test_config.render_api_function = | |
| 195 RenderApiFunctionImplementation::AnalyzeReverseStreamImplementation2; | |
| 196 test_config.capture_api_function = | |
| 197 CaptureApiFunctionImplementation::ProcessStreamImplementation3; | |
| 198 test_configs.push_back(test_config); | |
| 199 } | |
| 200 | |
| 201 // Return the created test configurations. | |
| 202 return test_configs; | |
| 203 } | |
| 204 | |
| 205 // Function for generating the test configurations to use in the extensive | |
| 206 // tests. | |
| 207 static std::vector<TestConfig> GenerateExtensiveTestConfigs() { | |
|
the sun
2015/10/29 10:31:30
Move out of this class. Into TestConfig?
peah-webrtc
2015/10/29 14:26:51
Done.
| |
| 208 std::vector<TestConfig> test_configs; | |
| 209 // Loop over all possible test configurations. | |
| 210 for (int render = static_cast<int>(RenderApiFunctionImplementation:: | |
| 211 ProcessReverseStreamImplementation1); | |
| 212 render <= static_cast<int>(RenderApiFunctionImplementation:: | |
| 213 AnalyzeReverseStreamImplementation2); | |
| 214 render++) | |
| 215 for (int capture = static_cast<int>( | |
| 216 CaptureApiFunctionImplementation::ProcessStreamImplementation1); | |
| 217 capture <= | |
| 218 static_cast<int>( | |
| 219 CaptureApiFunctionImplementation::ProcessStreamImplementation3); | |
| 220 capture++) | |
| 221 for (int aec = static_cast<int>(AecType::BasicWebRtcAecSettings); | |
| 222 aec <= | |
| 223 static_cast<int>(AecType::BasicWebRtcAecSettingsWithAecMobile); | |
| 224 aec++) | |
| 225 for (int scheme = | |
| 226 static_cast<int>(RuntimeParameterSettingScheme:: | |
| 227 SparseStreamMetadataChangeScheme); | |
| 228 scheme <= static_cast<int>(RuntimeParameterSettingScheme:: | |
| 229 FixedStereoStreamMetadataScheme); | |
| 230 scheme++) { | |
| 231 TestConfig test_config; | |
| 232 test_config.min_number_of_calls = 10000; | |
| 233 | |
| 234 test_config.render_api_function = | |
| 235 static_cast<RenderApiFunctionImplementation>(render); | |
| 236 test_config.capture_api_function = | |
| 237 static_cast<CaptureApiFunctionImplementation>(capture); | |
| 238 test_config.aec_type = static_cast<AecType>(aec); | |
| 239 | |
| 240 // Check that the selected render and capture API calls are | |
| 241 // compatible | |
| 242 if ((((test_config.render_api_function == | |
| 243 RenderApiFunctionImplementation:: | |
| 244 ProcessReverseStreamImplementation1) || | |
| 245 (test_config.render_api_function == | |
| 246 RenderApiFunctionImplementation:: | |
| 247 AnalyzeReverseStreamImplementation1)) && | |
| 248 (test_config.capture_api_function == | |
| 249 CaptureApiFunctionImplementation:: | |
| 250 ProcessStreamImplementation1)) || | |
| 251 (((test_config.render_api_function != | |
| 252 RenderApiFunctionImplementation:: | |
| 253 ProcessReverseStreamImplementation1) && | |
| 254 (test_config.render_api_function != | |
| 255 RenderApiFunctionImplementation:: | |
| 256 AnalyzeReverseStreamImplementation1)) && | |
| 257 (test_config.capture_api_function != | |
| 258 CaptureApiFunctionImplementation:: | |
| 259 ProcessStreamImplementation1))) { | |
| 260 // For the compatible render and capture function combinations | |
| 261 // add test configs with different initial sample rates and | |
| 262 // parameter setting schemes. | |
| 263 test_config.runtime_parameter_setting_scheme = | |
| 264 static_cast<RuntimeParameterSettingScheme>(scheme); | |
| 265 | |
| 266 test_config.initial_sample_rate_hz = 8000; | |
| 267 test_configs.push_back(test_config); | |
| 268 | |
| 269 test_config.initial_sample_rate_hz = 16000; | |
| 270 test_configs.push_back(test_config); | |
| 271 | |
| 272 if (test_config.aec_type != | |
| 273 AecType::BasicWebRtcAecSettingsWithAecMobile) { | |
| 274 test_config.initial_sample_rate_hz = 32000; | |
| 275 test_configs.push_back(test_config); | |
| 276 | |
| 277 test_config.initial_sample_rate_hz = 48000; | |
| 278 test_configs.push_back(test_config); | |
| 279 } | |
| 280 } | |
| 281 } | |
| 282 // Return the created test configurations. | |
| 283 return test_configs; | |
| 284 } | |
| 285 | |
| 286 private: | |
| 287 static const int kTestTimeOutLimit = 10 * 60 * 1000; | |
| 288 static const int kMaxCallDifference = 10; | |
| 289 static const float kRenderInputFloatLevel; | |
| 290 static const float kCaptureInputFloatLevel; | |
| 291 static const int kRenderInputFixLevel = 16384; | |
| 292 static const int kCaptureInputFixLevel = 1024; | |
| 293 | |
| 294 // Generates random number between -(amplitude+1) and amplitude | |
| 295 int16_t GenerateRandomInt16(int16_t amplitude) const { | |
| 296 return rand_gen_.Rand(-amplitude, amplitude); | |
|
hlundin-webrtc
2015/10/29 09:13:22
Does this really generate "random number between -
peah-webrtc
2015/10/29 14:26:51
Good find! Fixed!
Done.
| |
| 297 } | |
| 298 | |
| 299 // Populates a float audio frame with random data. | |
| 300 void PopulateAudioFrame(float** frame, | |
| 301 float amplitude, | |
| 302 size_t num_channels, | |
| 303 size_t samples_per_channel) const { | |
| 304 for (size_t ch = 0; ch < num_channels; ch++) { | |
| 305 for (size_t k = 0; k < samples_per_channel; k++) { | |
| 306 // Store random 16 bit quantized float number between the specified | |
| 307 // limits. | |
| 308 frame[ch][k] = amplitude * | |
| 309 static_cast<float>(GenerateRandomInt16(32767)) / | |
| 310 32768.0f; | |
| 311 } | |
| 312 } | |
| 313 } | |
| 314 | |
| 315 // Populates an audioframe frame of AudioFrame type with random data. | |
| 316 void PopulateAudioFrame(AudioFrame* frame, int16_t amplitude) const { | |
| 317 ASSERT_GT(amplitude, 0); | |
| 318 ASSERT_LE(amplitude, 32767); | |
| 319 for (int ch = 0; ch < frame->num_channels_; ch++) { | |
| 320 for (int k = 0; k < static_cast<int>(frame->samples_per_channel_); k++) { | |
| 321 // Store random 16 bit quantized float number between -1 and 1. | |
| 322 frame->data_[k * ch] = GenerateRandomInt16(amplitude); | |
| 323 } | |
| 324 } | |
| 325 } | |
| 326 | |
| 327 // Thread callback for the render thread | |
| 328 static bool RenderThread(void* context) { | |
| 329 return reinterpret_cast<AudioProcessingImpLockTest*>(context) | |
| 330 ->RenderThreadImpl(); | |
| 331 } | |
| 332 | |
| 333 // Thread callback for the capture thread | |
| 334 static bool CaptureThread(void* context) { | |
| 335 return reinterpret_cast<AudioProcessingImpLockTest*>(context) | |
| 336 ->CaptureThreadImpl(); | |
| 337 } | |
| 338 | |
| 339 // Thread callback for the stats thread | |
| 340 static bool StatsThread(void* context) { | |
| 341 return reinterpret_cast<AudioProcessingImpLockTest*>(context) | |
| 342 ->StatsThreadImpl(); | |
| 343 } | |
| 344 | |
| 345 // Tests whether all the required render and capture side calls have been | |
| 346 // done. | |
| 347 bool TestDone() { | |
| 348 rtc::CritScope cs(&crit_); | |
| 349 return ((shared_thread_counter_state_.render_count > | |
| 350 test_config_.min_number_of_calls) && | |
| 351 (shared_thread_counter_state_.capture_count > | |
| 352 test_config_.min_number_of_calls)); | |
| 353 } | |
| 354 | |
| 355 // Sleeps a random time between 0 and max_sleep milliseconds. | |
| 356 void SleepRandomMs(int max_sleep) const { | |
| 357 int sleeptime = rand_gen_.Rand(0, max_sleep); | |
| 358 SleepMs(sleeptime); | |
| 359 } | |
| 360 | |
| 361 // Implements the callback functionality for the statistics | |
| 362 // collection thread. | |
| 363 bool StatsThreadImpl() { | |
| 364 SleepRandomMs(100); | |
| 365 | |
| 366 EXPECT_EQ(apm_->echo_cancellation()->is_enabled(), | |
| 367 ((test_config_.aec_type != AecType::AecTurnedOff) && | |
| 368 (test_config_.aec_type != | |
| 369 AecType::BasicWebRtcAecSettingsWithAecMobile))); | |
| 370 apm_->echo_cancellation()->stream_drift_samples(); | |
| 371 EXPECT_EQ(apm_->echo_control_mobile()->is_enabled(), | |
| 372 (test_config_.aec_type != AecType::AecTurnedOff) && | |
| 373 (test_config_.aec_type == | |
| 374 AecType::BasicWebRtcAecSettingsWithAecMobile)); | |
| 375 EXPECT_TRUE(apm_->gain_control()->is_enabled()); | |
| 376 apm_->gain_control()->stream_analog_level(); | |
| 377 EXPECT_TRUE(apm_->noise_suppression()->is_enabled()); | |
| 378 float speech_probablitity = apm_->noise_suppression()->speech_probability(); | |
| 379 EXPECT_TRUE(speech_probablitity < (apm_->kUnsupportedFunctionError + 0.5f || | |
| 380 speech_probablitity >= 0)); | |
| 381 apm_->voice_detection()->is_enabled(); | |
| 382 | |
| 383 return true; | |
| 384 } | |
| 385 | |
| 386 // Implements the callback functionality for the render thread. | |
| 387 bool RenderThreadImpl() { | |
| 388 // Conditional wait to ensure that a capture call has been done | |
| 389 // before the first render call is performed (implicitly | |
| 390 // required by the APM API). | |
| 391 if (render_thread_state_.first_render_side_call_) { | |
| 392 bool capture_side_called_local; | |
| 393 do { | |
| 394 { | |
| 395 rtc::CritScope cs(&crit_initial_sync_); | |
| 396 capture_side_called_local = | |
| 397 shared_thread_init_state_.capture_side_called; | |
| 398 } | |
| 399 SleepRandomMs(3); | |
| 400 } while (!capture_side_called_local); | |
| 401 | |
| 402 render_thread_state_.first_render_side_call_ = false; | |
| 403 } | |
| 404 | |
| 405 // Sleep a random time to simulate thread jitter. | |
| 406 SleepRandomMs(3); | |
| 407 | |
| 408 // End the test early if a fatal failure (ASSERT_*) has occurred. | |
| 409 if (HasFatalFailure()) | |
| 410 test_complete_->Set(); | |
| 411 | |
| 412 // Ensure that the number of render and capture calls do not | |
| 413 // differ too much. | |
| 414 int frame_counter_difference; | |
| 415 do { | |
| 416 { | |
| 417 rtc::CritScope cs(&crit_); | |
| 418 frame_counter_difference = | |
| 419 (shared_thread_counter_state_.render_count - | |
| 420 (shared_thread_counter_state_.capture_count + kMaxCallDifference)); | |
| 421 } | |
| 422 if (frame_counter_difference > 0) | |
| 423 SleepMs(1); | |
| 424 } while (frame_counter_difference > 0); | |
| 425 | |
| 426 // Apply any specified render side APM non-processing runtime calls. | |
| 427 ApplyRenderRuntimeSettingScheme(); | |
| 428 | |
| 429 // Apply the render side processing call. | |
| 430 CallRenderSide(); | |
| 431 | |
| 432 // Increase the number of render-side calls. | |
| 433 rtc::CritScope cs(&crit_); | |
| 434 shared_thread_counter_state_.render_count++; | |
| 435 | |
| 436 return true; | |
| 437 } | |
| 438 | |
| 439 // Makes the capture side processing API call. | |
| 440 void CallCaptureSide() { | |
| 441 // Prepare a proper capture side processing API call input. | |
| 442 PrepareCaptureFrame(); | |
| 443 | |
| 444 // Set the stream delay | |
| 445 apm_->set_stream_delay_ms(30); | |
| 446 | |
| 447 // Call the specified capture side API processing method. | |
| 448 int result = AudioProcessing::kNoError; | |
| 449 switch (test_config_.capture_api_function) { | |
| 450 case CaptureApiFunctionImplementation::ProcessStreamImplementation1: | |
| 451 result = apm_->ProcessStream(&capture_thread_state_.frame); | |
| 452 break; | |
| 453 case CaptureApiFunctionImplementation::ProcessStreamImplementation2: | |
| 454 result = | |
| 455 apm_->ProcessStream(&capture_thread_state_.input_frame[0], | |
| 456 capture_thread_state_.input_samples_per_channel, | |
| 457 capture_thread_state_.input_sample_rate_hz, | |
| 458 capture_thread_state_.input_channel_layout, | |
| 459 capture_thread_state_.output_sample_rate_hz, | |
| 460 capture_thread_state_.output_channel_layout, | |
| 461 &capture_thread_state_.output_frame[0]); | |
| 462 break; | |
| 463 case CaptureApiFunctionImplementation::ProcessStreamImplementation3: | |
| 464 result = apm_->ProcessStream(&capture_thread_state_.input_frame[0], | |
| 465 capture_thread_state_.input_stream_config, | |
| 466 capture_thread_state_.output_stream_config, | |
| 467 &capture_thread_state_.output_frame[0]); | |
| 468 break; | |
| 469 default: | |
| 470 assert(false); | |
| 471 } | |
| 472 | |
| 473 // Check the return code for error. | |
| 474 ASSERT_EQ(AudioProcessing::kNoError, result); | |
| 475 } | |
| 476 | |
| 477 // Prepares the render side frame and the accompanying metadata | |
| 478 // with the appropriate information. | |
| 479 void PrepareRenderFrame() { | |
| 480 // Restrict to a common fixed sample rate if the AudioFrame interface is | |
| 481 // used. | |
| 482 if ((test_config_.render_api_function == | |
| 483 RenderApiFunctionImplementation:: | |
| 484 AnalyzeReverseStreamImplementation1) || | |
| 485 (test_config_.render_api_function == | |
| 486 RenderApiFunctionImplementation:: | |
| 487 ProcessReverseStreamImplementation1) || | |
| 488 (test_config_.aec_type != | |
| 489 AecType::BasicWebRtcAecSettingsWithAecMobile)) { | |
| 490 render_thread_state_.input_sample_rate_hz = | |
| 491 test_config_.initial_sample_rate_hz; | |
| 492 render_thread_state_.output_sample_rate_hz = | |
| 493 test_config_.initial_sample_rate_hz; | |
| 494 } | |
| 495 | |
| 496 // Prepare the audioframe data and metadata | |
| 497 render_thread_state_.input_samples_per_channel = | |
| 498 render_thread_state_.input_sample_rate_hz * | |
| 499 AudioProcessing::kChunkSizeMs / 1000; | |
| 500 render_thread_state_.frame.sample_rate_hz_ = | |
| 501 render_thread_state_.input_sample_rate_hz; | |
| 502 render_thread_state_.frame.num_channels_ = | |
| 503 render_thread_state_.input_number_of_channels; | |
| 504 render_thread_state_.frame.samples_per_channel_ = | |
| 505 render_thread_state_.input_samples_per_channel; | |
| 506 memset(render_thread_state_.frame.data_, 0, | |
| 507 render_thread_state_.input_samples_per_channel * | |
| 508 sizeof(render_thread_state_.frame.data_[0])); | |
| 509 PopulateAudioFrame(&render_thread_state_.frame, kRenderInputFixLevel); | |
| 510 | |
| 511 // Prepare the float audio input data and metadata. | |
| 512 render_thread_state_.input_stream_config.set_sample_rate_hz( | |
| 513 render_thread_state_.input_sample_rate_hz); | |
| 514 render_thread_state_.input_stream_config.set_num_channels( | |
| 515 render_thread_state_.input_number_of_channels); | |
| 516 render_thread_state_.input_stream_config.set_has_keyboard(false); | |
| 517 PopulateAudioFrame(&render_thread_state_.input_frame[0], | |
| 518 kRenderInputFloatLevel, | |
| 519 render_thread_state_.input_number_of_channels, | |
| 520 render_thread_state_.input_samples_per_channel); | |
| 521 render_thread_state_.input_channel_layout = | |
| 522 (render_thread_state_.input_number_of_channels == 1 | |
| 523 ? AudioProcessing::ChannelLayout::kMono | |
| 524 : AudioProcessing::ChannelLayout::kStereo); | |
| 525 | |
| 526 // Prepare the float audio output data and metadata. | |
| 527 render_thread_state_.output_samples_per_channel = | |
| 528 render_thread_state_.output_sample_rate_hz * | |
| 529 AudioProcessing::kChunkSizeMs / 1000; | |
| 530 render_thread_state_.output_stream_config.set_sample_rate_hz( | |
| 531 render_thread_state_.output_sample_rate_hz); | |
| 532 render_thread_state_.output_stream_config.set_num_channels( | |
| 533 render_thread_state_.output_number_of_channels); | |
| 534 render_thread_state_.output_stream_config.set_has_keyboard(false); | |
| 535 render_thread_state_.output_channel_layout = | |
| 536 (render_thread_state_.output_number_of_channels == 1 | |
| 537 ? AudioProcessing::ChannelLayout::kMono | |
| 538 : AudioProcessing::ChannelLayout::kStereo); | |
| 539 } | |
| 540 | |
| 541 void PrepareCaptureFrame() { | |
| 542 // Restrict to a common fixed sample rate if the AudioFrame | |
| 543 // interface is used. | |
| 544 if (test_config_.capture_api_function == | |
| 545 CaptureApiFunctionImplementation::ProcessStreamImplementation1) { | |
| 546 capture_thread_state_.input_sample_rate_hz = | |
| 547 test_config_.initial_sample_rate_hz; | |
| 548 capture_thread_state_.output_sample_rate_hz = | |
| 549 test_config_.initial_sample_rate_hz; | |
| 550 } | |
| 551 | |
| 552 // Prepare the audioframe data and metadata. | |
| 553 capture_thread_state_.input_samples_per_channel = | |
| 554 capture_thread_state_.input_sample_rate_hz * | |
| 555 AudioProcessing::kChunkSizeMs / 1000; | |
| 556 capture_thread_state_.frame.sample_rate_hz_ = | |
| 557 capture_thread_state_.input_sample_rate_hz; | |
| 558 capture_thread_state_.frame.num_channels_ = | |
| 559 capture_thread_state_.input_number_of_channels; | |
| 560 capture_thread_state_.frame.samples_per_channel_ = | |
| 561 capture_thread_state_.input_samples_per_channel; | |
| 562 memset(capture_thread_state_.frame.data_, 0, | |
| 563 capture_thread_state_.input_samples_per_channel * | |
| 564 sizeof(capture_thread_state_.frame.data_[0])); | |
| 565 PopulateAudioFrame(&capture_thread_state_.frame, kCaptureInputFixLevel); | |
| 566 | |
| 567 // Prepare the float audio input data and metadata. | |
| 568 capture_thread_state_.input_stream_config.set_sample_rate_hz( | |
| 569 capture_thread_state_.input_sample_rate_hz); | |
| 570 capture_thread_state_.input_stream_config.set_num_channels( | |
| 571 capture_thread_state_.input_number_of_channels); | |
| 572 capture_thread_state_.input_stream_config.set_has_keyboard(false); | |
| 573 PopulateAudioFrame(&capture_thread_state_.input_frame[0], | |
| 574 kCaptureInputFloatLevel, | |
| 575 capture_thread_state_.input_number_of_channels, | |
| 576 capture_thread_state_.input_samples_per_channel); | |
| 577 capture_thread_state_.input_channel_layout = | |
| 578 (capture_thread_state_.input_number_of_channels == 1 | |
| 579 ? AudioProcessing::ChannelLayout::kMonoAndKeyboard | |
| 580 : AudioProcessing::ChannelLayout::kStereoAndKeyboard); | |
| 581 | |
| 582 // Prepare the float audio output data and metadata. | |
| 583 capture_thread_state_.output_samples_per_channel = | |
| 584 capture_thread_state_.output_sample_rate_hz * | |
| 585 AudioProcessing::kChunkSizeMs / 1000; | |
| 586 capture_thread_state_.output_stream_config.set_sample_rate_hz( | |
| 587 capture_thread_state_.output_sample_rate_hz); | |
| 588 capture_thread_state_.output_stream_config.set_num_channels( | |
| 589 capture_thread_state_.output_number_of_channels); | |
| 590 capture_thread_state_.output_stream_config.set_has_keyboard(false); | |
| 591 capture_thread_state_.output_channel_layout = | |
| 592 (capture_thread_state_.output_number_of_channels == 1 | |
| 593 ? AudioProcessing::ChannelLayout::kMono | |
| 594 : AudioProcessing::ChannelLayout::kStereo); | |
| 595 } | |
| 596 | |
| 597 // Applies any render capture APM API calls and audio stream characteristics | |
| 598 // specified by the scheme for the test. | |
| 599 void ApplyRenderRuntimeSettingScheme() { | |
| 600 const int render_count_local = [this] { | |
| 601 rtc::CritScope cs(&crit_); | |
| 602 return shared_thread_counter_state_.render_count; | |
| 603 }(); | |
| 604 | |
| 605 // Update the number of channels and sample rates for the input and output. | |
| 606 // Note that the counts frequencies for when to set parameters | |
| 607 // are set using prime numbers in order to ensure that the | |
| 608 // permutation scheme in the parameter setting changes. | |
| 609 switch (test_config_.runtime_parameter_setting_scheme) { | |
| 610 case RuntimeParameterSettingScheme::SparseStreamMetadataChangeScheme: | |
| 611 if (render_count_local == 0) | |
| 612 render_thread_state_.input_sample_rate_hz = 16000; | |
| 613 else if (render_count_local % 47 == 0) | |
| 614 render_thread_state_.input_sample_rate_hz = 32000; | |
| 615 else if (render_count_local % 71 == 0) | |
| 616 render_thread_state_.input_sample_rate_hz = 48000; | |
| 617 else if (render_count_local % 79 == 0) | |
| 618 render_thread_state_.input_sample_rate_hz = 16000; | |
| 619 else if (render_count_local % 83 == 0) | |
| 620 render_thread_state_.input_sample_rate_hz = 8000; | |
| 621 | |
| 622 if (render_count_local == 0) | |
| 623 render_thread_state_.input_number_of_channels = 1; | |
| 624 else if (render_count_local % 4 == 0) | |
| 625 render_thread_state_.input_number_of_channels = | |
| 626 (render_thread_state_.input_number_of_channels == 1 ? 2 : 1); | |
| 627 | |
| 628 if (render_count_local == 0) | |
| 629 render_thread_state_.output_sample_rate_hz = 16000; | |
| 630 else if (render_count_local % 17 == 0) | |
| 631 render_thread_state_.output_sample_rate_hz = 32000; | |
| 632 else if (render_count_local % 19 == 0) | |
| 633 render_thread_state_.output_sample_rate_hz = 48000; | |
| 634 else if (render_count_local % 29 == 0) | |
| 635 render_thread_state_.output_sample_rate_hz = 16000; | |
| 636 else if (render_count_local % 61 == 0) | |
| 637 render_thread_state_.output_sample_rate_hz = 8000; | |
| 638 | |
| 639 if (render_count_local == 0) | |
| 640 render_thread_state_.output_number_of_channels = 1; | |
| 641 else if (render_count_local % 8 == 0) | |
| 642 render_thread_state_.output_number_of_channels = | |
| 643 (render_thread_state_.output_number_of_channels == 1 ? 2 : 1); | |
| 644 break; | |
| 645 case RuntimeParameterSettingScheme::ExtremeStreamMetadataChangeScheme: | |
| 646 if (render_count_local == 0) { | |
| 647 render_thread_state_.input_number_of_channels = 1; | |
| 648 render_thread_state_.input_sample_rate_hz = 16000; | |
| 649 render_thread_state_.output_number_of_channels = 1; | |
| 650 render_thread_state_.output_sample_rate_hz = 16000; | |
| 651 } else { | |
| 652 render_thread_state_.input_number_of_channels = | |
| 653 (render_thread_state_.input_number_of_channels == 1 ? 2 : 1); | |
| 654 if (render_thread_state_.input_sample_rate_hz == 8000) | |
| 655 render_thread_state_.input_sample_rate_hz = 16000; | |
| 656 else if (render_thread_state_.input_sample_rate_hz == 16000) | |
| 657 render_thread_state_.input_sample_rate_hz = 32000; | |
| 658 else if (render_thread_state_.input_sample_rate_hz == 32000) | |
| 659 render_thread_state_.input_sample_rate_hz = 48000; | |
| 660 else if (render_thread_state_.input_sample_rate_hz == 48000) | |
| 661 render_thread_state_.input_sample_rate_hz = 8000; | |
| 662 | |
| 663 render_thread_state_.output_number_of_channels = | |
| 664 (render_thread_state_.output_number_of_channels == 1 ? 2 : 1); | |
| 665 if (render_thread_state_.output_sample_rate_hz == 8000) | |
| 666 render_thread_state_.output_sample_rate_hz = 16000; | |
| 667 else if (render_thread_state_.output_sample_rate_hz == 16000) | |
| 668 render_thread_state_.output_sample_rate_hz = 32000; | |
| 669 else if (render_thread_state_.output_sample_rate_hz == 32000) | |
| 670 render_thread_state_.output_sample_rate_hz = 48000; | |
| 671 else if (render_thread_state_.output_sample_rate_hz == 48000) | |
| 672 render_thread_state_.output_sample_rate_hz = 8000; | |
| 673 } | |
| 674 break; | |
| 675 case RuntimeParameterSettingScheme::FixedMonoStreamMetadataScheme: | |
| 676 if (render_count_local == 0) { | |
| 677 render_thread_state_.input_sample_rate_hz = 16000; | |
| 678 render_thread_state_.input_number_of_channels = 1; | |
| 679 render_thread_state_.output_sample_rate_hz = 16000; | |
| 680 render_thread_state_.output_number_of_channels = 1; | |
| 681 } | |
| 682 break; | |
| 683 case RuntimeParameterSettingScheme::FixedStereoStreamMetadataScheme: | |
| 684 if (render_count_local == 0) { | |
| 685 render_thread_state_.input_sample_rate_hz = 16000; | |
| 686 render_thread_state_.input_number_of_channels = 2; | |
| 687 render_thread_state_.output_sample_rate_hz = 16000; | |
| 688 render_thread_state_.output_number_of_channels = 2; | |
| 689 } | |
| 690 | |
| 691 break; | |
| 692 default: | |
| 693 assert(false); | |
| 694 } | |
| 695 | |
| 696 // Restric the number of output channels not to exceed | |
| 697 // the number of input channels. | |
| 698 render_thread_state_.output_number_of_channels = | |
| 699 std::min(render_thread_state_.output_number_of_channels, | |
| 700 render_thread_state_.input_number_of_channels); | |
| 701 } | |
| 702 | |
| 703 // Applies any runtime capture APM API calls and audio stream characteristics | |
| 704 // specified by the scheme for the test. | |
| 705 void ApplyCaptureRuntimeSettingScheme() { | |
| 706 const int capture_count_local = [this] { | |
| 707 rtc::CritScope cs(&crit_); | |
| 708 return shared_thread_counter_state_.capture_count; | |
| 709 }(); | |
| 710 | |
| 711 // Update the number of channels and sample rates for the input and output. | |
| 712 // Note that the counts frequencies for when to set parameters | |
| 713 // are set using prime numbers in order to ensure that the | |
| 714 // permutation scheme in the parameter setting changes. | |
| 715 switch (test_config_.runtime_parameter_setting_scheme) { | |
| 716 case RuntimeParameterSettingScheme::SparseStreamMetadataChangeScheme: | |
| 717 if (capture_count_local == 0) | |
| 718 capture_thread_state_.input_sample_rate_hz = 16000; | |
| 719 else if (capture_count_local % 11 == 0) | |
| 720 capture_thread_state_.input_sample_rate_hz = 32000; | |
| 721 else if (capture_count_local % 73 == 0) | |
| 722 capture_thread_state_.input_sample_rate_hz = 48000; | |
| 723 else if (capture_count_local % 89 == 0) | |
| 724 capture_thread_state_.input_sample_rate_hz = 16000; | |
| 725 else if (capture_count_local % 97 == 0) | |
| 726 capture_thread_state_.input_sample_rate_hz = 8000; | |
| 727 | |
| 728 if (capture_count_local == 0) | |
| 729 capture_thread_state_.input_number_of_channels = 1; | |
| 730 else if (capture_count_local % 4 == 0) | |
| 731 capture_thread_state_.input_number_of_channels = | |
| 732 (capture_thread_state_.input_number_of_channels == 1 ? 2 : 1); | |
| 733 | |
| 734 if (capture_count_local == 0) | |
| 735 capture_thread_state_.output_sample_rate_hz = 16000; | |
| 736 else if (capture_count_local % 5 == 0) | |
| 737 capture_thread_state_.output_sample_rate_hz = 32000; | |
| 738 else if (capture_count_local % 47 == 0) | |
| 739 capture_thread_state_.output_sample_rate_hz = 48000; | |
| 740 else if (capture_count_local % 53 == 0) | |
| 741 capture_thread_state_.output_sample_rate_hz = 16000; | |
| 742 else if (capture_count_local % 71 == 0) | |
| 743 capture_thread_state_.output_sample_rate_hz = 8000; | |
| 744 | |
| 745 if (capture_count_local == 0) | |
| 746 capture_thread_state_.output_number_of_channels = 1; | |
| 747 else if (capture_count_local % 8 == 0) | |
| 748 capture_thread_state_.output_number_of_channels = | |
| 749 (capture_thread_state_.output_number_of_channels == 1 ? 2 : 1); | |
| 750 break; | |
| 751 case RuntimeParameterSettingScheme::ExtremeStreamMetadataChangeScheme: | |
| 752 if (capture_count_local % 2 == 0) { | |
| 753 capture_thread_state_.input_number_of_channels = 1; | |
| 754 capture_thread_state_.input_sample_rate_hz = 16000; | |
| 755 capture_thread_state_.output_number_of_channels = 1; | |
| 756 capture_thread_state_.output_sample_rate_hz = 16000; | |
| 757 } else { | |
| 758 capture_thread_state_.input_number_of_channels = | |
| 759 (capture_thread_state_.input_number_of_channels == 1 ? 2 : 1); | |
| 760 if (capture_thread_state_.input_sample_rate_hz == 8000) | |
| 761 capture_thread_state_.input_sample_rate_hz = 16000; | |
| 762 else if (capture_thread_state_.input_sample_rate_hz == 16000) | |
| 763 capture_thread_state_.input_sample_rate_hz = 32000; | |
| 764 else if (capture_thread_state_.input_sample_rate_hz == 32000) | |
| 765 capture_thread_state_.input_sample_rate_hz = 48000; | |
| 766 else if (capture_thread_state_.input_sample_rate_hz == 48000) | |
| 767 capture_thread_state_.input_sample_rate_hz = 8000; | |
| 768 | |
| 769 capture_thread_state_.output_number_of_channels = | |
| 770 (capture_thread_state_.output_number_of_channels == 1 ? 2 : 1); | |
| 771 if (capture_thread_state_.output_sample_rate_hz == 8000) | |
| 772 capture_thread_state_.output_sample_rate_hz = 16000; | |
| 773 else if (capture_thread_state_.output_sample_rate_hz == 16000) | |
| 774 capture_thread_state_.output_sample_rate_hz = 32000; | |
| 775 else if (capture_thread_state_.output_sample_rate_hz == 32000) | |
| 776 capture_thread_state_.output_sample_rate_hz = 48000; | |
| 777 else if (capture_thread_state_.output_sample_rate_hz == 48000) | |
| 778 capture_thread_state_.output_sample_rate_hz = 8000; | |
| 779 } | |
| 780 break; | |
| 781 case RuntimeParameterSettingScheme::FixedMonoStreamMetadataScheme: | |
| 782 if (capture_count_local == 0) { | |
| 783 capture_thread_state_.input_sample_rate_hz = 16000; | |
| 784 capture_thread_state_.input_number_of_channels = 1; | |
| 785 capture_thread_state_.output_sample_rate_hz = 16000; | |
| 786 capture_thread_state_.output_number_of_channels = 1; | |
| 787 } | |
| 788 break; | |
| 789 case RuntimeParameterSettingScheme::FixedStereoStreamMetadataScheme: | |
| 790 if (capture_count_local == 0) { | |
| 791 capture_thread_state_.input_sample_rate_hz = 16000; | |
| 792 capture_thread_state_.input_number_of_channels = 2; | |
| 793 capture_thread_state_.output_sample_rate_hz = 16000; | |
| 794 capture_thread_state_.output_number_of_channels = 2; | |
| 795 } | |
| 796 | |
| 797 break; | |
| 798 default: | |
| 799 assert(false); | |
| 800 } | |
| 801 | |
| 802 // Call any specified runtime APM setter and | |
| 803 // getter calls. | |
| 804 switch (test_config_.runtime_parameter_setting_scheme) { | |
| 805 case RuntimeParameterSettingScheme::SparseStreamMetadataChangeScheme: | |
| 806 case RuntimeParameterSettingScheme::FixedMonoStreamMetadataScheme: | |
| 807 break; | |
| 808 case RuntimeParameterSettingScheme::ExtremeStreamMetadataChangeScheme: | |
| 809 case RuntimeParameterSettingScheme::FixedStereoStreamMetadataScheme: | |
| 810 if ((capture_count_local % 2) == 0) { | |
| 811 ASSERT_EQ(AudioProcessing::Error::kNoError, | |
| 812 apm_->set_stream_delay_ms(30)); | |
| 813 apm_->set_stream_key_pressed(true); | |
| 814 apm_->set_output_will_be_muted(true); | |
| 815 apm_->set_delay_offset_ms(15); | |
| 816 EXPECT_EQ(apm_->delay_offset_ms(), 15); | |
| 817 EXPECT_GE(apm_->num_reverse_channels(), 0); | |
| 818 EXPECT_LE(apm_->num_reverse_channels(), 2); | |
| 819 } else { | |
| 820 ASSERT_EQ(AudioProcessing::Error::kNoError, | |
| 821 apm_->set_stream_delay_ms(50)); | |
| 822 apm_->set_stream_key_pressed(false); | |
| 823 apm_->set_output_will_be_muted(false); | |
| 824 apm_->set_delay_offset_ms(20); | |
| 825 EXPECT_EQ(apm_->delay_offset_ms(), 20); | |
| 826 apm_->delay_offset_ms(); | |
| 827 apm_->num_reverse_channels(); | |
| 828 EXPECT_GE(apm_->num_reverse_channels(), 0); | |
| 829 EXPECT_LE(apm_->num_reverse_channels(), 2); | |
| 830 } | |
| 831 break; | |
| 832 default: | |
| 833 FAIL(); | |
| 834 } | |
| 835 | |
| 836 // Restric the number of output channels not to exceed | |
| 837 // the number of input channels. | |
| 838 capture_thread_state_.output_number_of_channels = | |
| 839 std::min(capture_thread_state_.output_number_of_channels, | |
| 840 capture_thread_state_.input_number_of_channels); | |
| 841 } | |
| 842 | |
| 843 // Makes the render side processing API call. | |
| 844 void CallRenderSide() { | |
| 845 // Prepare a proper render side processing API call input. | |
| 846 PrepareRenderFrame(); | |
| 847 | |
| 848 // Call the specified render side API processing method. | |
| 849 int result = AudioProcessing::kNoError; | |
| 850 switch (test_config_.render_api_function) { | |
| 851 case RenderApiFunctionImplementation::ProcessReverseStreamImplementation1: | |
| 852 result = apm_->ProcessReverseStream(&render_thread_state_.frame); | |
| 853 break; | |
| 854 case RenderApiFunctionImplementation::ProcessReverseStreamImplementation2: | |
| 855 result = apm_->ProcessReverseStream( | |
| 856 &render_thread_state_.input_frame[0], | |
| 857 render_thread_state_.input_stream_config, | |
| 858 render_thread_state_.output_stream_config, | |
| 859 &render_thread_state_.output_frame[0]); | |
| 860 break; | |
| 861 case RenderApiFunctionImplementation::AnalyzeReverseStreamImplementation1: | |
| 862 result = apm_->AnalyzeReverseStream(&render_thread_state_.frame); | |
| 863 break; | |
| 864 case RenderApiFunctionImplementation::AnalyzeReverseStreamImplementation2: | |
| 865 result = apm_->AnalyzeReverseStream( | |
| 866 &render_thread_state_.input_frame[0], | |
| 867 render_thread_state_.input_samples_per_channel, | |
| 868 render_thread_state_.input_sample_rate_hz, | |
| 869 render_thread_state_.input_channel_layout); | |
| 870 break; | |
| 871 default: | |
| 872 assert(false); | |
| 873 } | |
| 874 | |
| 875 // Check the return code for error. | |
| 876 ASSERT_EQ(AudioProcessing::kNoError, result); | |
| 877 } | |
| 878 | |
| 879 // Implements the callback functionality for the capture thread. | |
| 880 bool CaptureThreadImpl() { | |
| 881 // Sleep a random time to simulate thread jitter. | |
| 882 SleepRandomMs(3); | |
| 883 | |
| 884 // End the test early if a fatal failure (ASSERT_*) has occurred. | |
| 885 if (HasFatalFailure()) | |
| 886 test_complete_->Set(); | |
| 887 | |
| 888 // Ensure that there are not more capture side calls than render side | |
| 889 // calls. | |
| 890 int frame_counter_difference; | |
| 891 do { | |
| 892 { | |
| 893 rtc::CritScope cs(&crit_); | |
| 894 frame_counter_difference = shared_thread_counter_state_.capture_count - | |
| 895 shared_thread_counter_state_.render_count; | |
| 896 } | |
| 897 if (frame_counter_difference > 0) | |
| 898 SleepMs(1); | |
| 899 } while (frame_counter_difference > 0); | |
| 900 | |
| 901 // Apply any specified capture side APM non-processing runtime calls. | |
| 902 ApplyCaptureRuntimeSettingScheme(); | |
| 903 | |
| 904 // Apply the capture side processing call. | |
| 905 CallCaptureSide(); | |
| 906 | |
| 907 // Increase the number of capture-side calls. | |
| 908 { | |
| 909 rtc::CritScope cs(&crit_); | |
| 910 shared_thread_counter_state_.capture_count++; | |
| 911 } | |
| 912 | |
| 913 // Check if the test is done. | |
| 914 if (TestDone()) | |
| 915 test_complete_->Set(); | |
| 916 | |
| 917 // Flag that the capture side has been called at least once | |
| 918 // (needed to ensure that a capture call has been done | |
| 919 // before the first render call is performed (implicitly | |
| 920 // required by the APM API). | |
| 921 { | |
| 922 rtc::CritScope cs(&crit_initial_sync_); | |
| 923 shared_thread_init_state_.capture_side_called = true; | |
| 924 } | |
| 925 | |
| 926 return true; | |
| 927 } | |
| 928 | |
| 929 // Start the threads used in the test. | |
| 930 void StartThreads() { | |
| 931 ASSERT_TRUE(render_thread_->Start()); | |
| 932 render_thread_->SetPriority(kRealtimePriority); | |
| 933 ASSERT_TRUE(capture_thread_->Start()); | |
| 934 capture_thread_->SetPriority(kRealtimePriority); | |
| 935 ASSERT_TRUE(stats_thread_->Start()); | |
| 936 stats_thread_->SetPriority(kNormalPriority); | |
| 937 } | |
| 938 | |
| 939 // Event handler for the test. | |
| 940 const rtc::scoped_ptr<EventWrapper> test_complete_; | |
| 941 | |
| 942 // Thread related variables. | |
| 943 rtc::CriticalSection crit_; | |
| 944 rtc::CriticalSection crit_initial_sync_; | |
| 945 rtc::scoped_ptr<ThreadWrapper> render_thread_; | |
| 946 rtc::scoped_ptr<ThreadWrapper> capture_thread_; | |
| 947 rtc::scoped_ptr<ThreadWrapper> stats_thread_; | |
| 948 mutable test::Random rand_gen_; | |
| 949 | |
| 950 // The APM object. | |
| 951 rtc::scoped_ptr<AudioProcessing> apm_; | |
| 952 | |
| 953 // The test configuration. | |
| 954 TestConfig test_config_; | |
| 955 | |
| 956 // Variables shared by the threads during the whole test. | |
| 957 struct { | |
| 958 int render_count = 0; | |
| 959 int capture_count = 0; | |
| 960 } shared_thread_counter_state_ GUARDED_BY(crit_); | |
| 961 | |
| 962 // Variable shared by the threads during the initialization phase. | |
| 963 struct { | |
| 964 bool capture_side_called; | |
| 965 } shared_thread_init_state_ GUARDED_BY(crit_initial_sync_); | |
| 966 | |
| 967 // Variables only used on the capture side thread. | |
| 968 struct { | |
| 969 // Variables related to the capture side audio data and formats. | |
| 970 AudioFrame frame; | |
| 971 std::vector<float*> output_frame; | |
| 972 std::vector<float> output_frame_channels; | |
| 973 AudioProcessing::ChannelLayout output_channel_layout; | |
| 974 int input_sample_rate_hz = 16000; | |
| 975 int input_number_of_channels; | |
| 976 std::vector<float*> input_frame; | |
| 977 std::vector<float> input_framechannels_; | |
| 978 AudioProcessing::ChannelLayout input_channel_layout; | |
| 979 int output_sample_rate_hz = 16000; | |
| 980 int output_number_of_channels; | |
| 981 StreamConfig input_stream_config; | |
| 982 StreamConfig output_stream_config; | |
| 983 int input_samples_per_channel; | |
| 984 int output_samples_per_channel; | |
| 985 } capture_thread_state_; | |
| 986 | |
| 987 // Variables only used on the render side thread. | |
| 988 struct { | |
| 989 bool first_render_side_call_ = true; | |
| 990 | |
| 991 // Variables related to the render side audio data and formats. | |
| 992 AudioFrame frame; | |
| 993 std::vector<float*> output_frame; | |
| 994 std::vector<float> output_frame_channels; | |
| 995 AudioProcessing::ChannelLayout output_channel_layout; | |
| 996 int input_sample_rate_hz = 16000; | |
| 997 int input_number_of_channels; | |
| 998 std::vector<float*> input_frame; | |
| 999 std::vector<float> input_frame_channels; | |
| 1000 AudioProcessing::ChannelLayout input_channel_layout; | |
| 1001 int output_sample_rate_hz = 16000; | |
| 1002 int output_number_of_channels; | |
| 1003 StreamConfig input_stream_config; | |
| 1004 StreamConfig output_stream_config; | |
| 1005 int input_samples_per_channel; | |
| 1006 int output_samples_per_channel; | |
| 1007 } render_thread_state_; | |
| 1008 }; | |
| 1009 | |
| 1010 const float AudioProcessingImpLockTest::kRenderInputFloatLevel = 0.5f; | |
| 1011 const float AudioProcessingImpLockTest::kCaptureInputFloatLevel = 0.03125f; | |
| 1012 | |
| 1013 } // anonymous namespace | |
| 1014 | |
| 1015 TEST_P(AudioProcessingImpLockTest, LockTest) { | |
| 1016 // Run test and verify that it did not time out. | |
| 1017 ASSERT_EQ(kEventSignaled, RunTest()); | |
| 1018 } | |
| 1019 | |
| 1020 // Instantiate tests from the extreme test configuration set. | |
| 1021 INSTANTIATE_TEST_CASE_P( | |
| 1022 DISABLED_AudioProcessingImpLockExtensive, | |
| 1023 AudioProcessingImpLockTest, | |
| 1024 ::testing::ValuesIn( | |
| 1025 AudioProcessingImpLockTest::GenerateExtensiveTestConfigs())); | |
| 1026 | |
| 1027 INSTANTIATE_TEST_CASE_P( | |
| 1028 AudioProcessingImpLockBrief, | |
| 1029 AudioProcessingImpLockTest, | |
| 1030 ::testing::ValuesIn( | |
| 1031 AudioProcessingImpLockTest::GenerateBriefTestConfigs())); | |
| 1032 | |
| 1033 } // namespace webrtc | |
| OLD | NEW |