Chromium Code Reviews| Index: webrtc/modules/audio_processing/audio_processing_impl_locking_unittest.cc |
| diff --git a/webrtc/modules/audio_processing/audio_processing_impl_locking_unittest.cc b/webrtc/modules/audio_processing/audio_processing_impl_locking_unittest.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..e08d311a1ac0c0616296f799b787fbc8671b9d20 |
| --- /dev/null |
| +++ b/webrtc/modules/audio_processing/audio_processing_impl_locking_unittest.cc |
| @@ -0,0 +1,1151 @@ |
| +/* |
| + * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. |
| + * |
| + * Use of this source code is governed by a BSD-style license |
| + * that can be found in the LICENSE file in the root of the source |
| + * tree. An additional intellectual property rights grant can be found |
| + * in the file PATENTS. All contributing project authors may |
| + * be found in the AUTHORS file in the root of the source tree. |
| + */ |
| + |
| +#include "webrtc/modules/audio_processing/audio_processing_impl.h" |
| + |
| +#include <algorithm> |
| +#include <vector> |
| + |
| +#include "testing/gmock/include/gmock/gmock.h" |
| +#include "testing/gtest/include/gtest/gtest.h" |
| +#include "webrtc/base/criticalsection.h" |
| +#include "webrtc/config.h" |
| +#include "webrtc/modules/audio_processing/test/test_utils.h" |
| +#include "webrtc/modules/interface/module_common_types.h" |
| +#include "webrtc/system_wrappers/include/event_wrapper.h" |
| +#include "webrtc/system_wrappers/include/sleep.h" |
| +#include "webrtc/system_wrappers/include/thread_wrapper.h" |
| +#include "webrtc/test/random.h" |
| + |
| +namespace webrtc { |
| + |
| +namespace { |
| + |
| +class AudioProcessingImplLockTest; |
| + |
| +// Sleeps a random time between 0 and max_sleep milliseconds. |
| +void SleepRandomMs(int max_sleep, test::Random* rand_gen) { |
| + int sleeptime = rand_gen->Rand(0, max_sleep); |
| + SleepMs(sleeptime); |
| +} |
| + |
| +// Populates a float audio frame with random data. |
| +void PopulateAudioFrame(float** frame, |
| + float amplitude, |
| + size_t num_channels, |
| + size_t samples_per_channel, |
| + test::Random* rand_gen) { |
| + for (size_t ch = 0; ch < num_channels; ch++) { |
| + for (size_t k = 0; k < samples_per_channel; k++) { |
| + // Store random 16 bit quantized float number between the specified |
| + // limits. |
| + frame[ch][k] = amplitude * |
| + static_cast<float>(rand_gen->Rand(-32767 - 1, 32767)) / |
| + 32768.0f; |
| + } |
| + } |
| +} |
| + |
| +// Populates an audioframe frame of AudioFrame type with random data. |
| +void PopulateAudioFrame(AudioFrame* frame, |
| + int16_t amplitude, |
| + test::Random* rand_gen) { |
| + ASSERT_GT(amplitude, 0); |
| + ASSERT_LE(amplitude, 32767); |
| + for (int ch = 0; ch < frame->num_channels_; ch++) { |
| + for (int k = 0; k < static_cast<int>(frame->samples_per_channel_); k++) { |
| + // Store random 16 bit quantized float number between -(amplitude+1) and |
| + // amplitude. |
| + frame->data_[k * ch] = rand_gen->Rand(-amplitude - 1, amplitude); |
| + } |
| + } |
| +} |
| + |
| +// Type of the render thread APM API call to use in the test. |
| +enum class RenderApiImpl { |
| + ProcessReverseStreamImpl1, |
| + ProcessReverseStreamImpl2, |
| + AnalyzeReverseStreamImpl1, |
| + AnalyzeReverseStreamImpl2 |
| +}; |
| + |
| +// Type of the capture thread APM API call to use in the test. |
| +enum class CaptureApiImpl { |
| + ProcessStreamImpl1, |
| + ProcessStreamImpl2, |
| + ProcessStreamImpl3 |
| +}; |
| + |
| +// The runtime parameter setting scheme to use in the test. |
| +enum class RuntimeParameterSettingScheme { |
| + SparseStreamMetadataChangeScheme, |
| + ExtremeStreamMetadataChangeScheme, |
| + FixedMonoStreamMetadataScheme, |
| + FixedStereoStreamMetadataScheme |
| +}; |
| + |
| +// Variant of echo canceller settings to use in the test. |
| +enum class AecType { |
| + BasicWebRtcAecSettings, |
| + AecTurnedOff, |
| + BasicWebRtcAecSettingsWithExtentedFilter, |
| + BasicWebRtcAecSettingsWithDelayAgnosticAec, |
| + BasicWebRtcAecSettingsWithAecMobile |
| +}; |
| + |
| +// Variables related to the audio data and formats. |
| +struct AudioFrameData { |
| + explicit AudioFrameData(int max_frame_size) { |
| + // Set up the two-dimensional arrays needed for the APM API calls. |
| + input_framechannels.resize(2 * max_frame_size); |
| + input_frame.resize(2); |
| + input_frame[0] = &input_framechannels[0]; |
| + input_frame[1] = &input_framechannels[max_frame_size]; |
| + |
| + output_frame_channels.resize(2 * max_frame_size); |
| + output_frame.resize(2); |
| + output_frame[0] = &output_frame_channels[0]; |
| + output_frame[1] = &output_frame_channels[max_frame_size]; |
| + } |
| + |
| + AudioFrame frame; |
| + std::vector<float*> output_frame; |
| + std::vector<float> output_frame_channels; |
| + AudioProcessing::ChannelLayout output_channel_layout; |
| + int input_sample_rate_hz = 16000; |
| + int input_number_of_channels; |
| + std::vector<float*> input_frame; |
| + std::vector<float> input_framechannels; |
| + AudioProcessing::ChannelLayout input_channel_layout; |
| + int output_sample_rate_hz = 16000; |
| + int output_number_of_channels; |
| + StreamConfig input_stream_config; |
| + StreamConfig output_stream_config; |
| + int input_samples_per_channel; |
| + int output_samples_per_channel; |
| +}; |
| + |
| +// The configuration for the test. |
| +struct TestConfig { |
| + // Test case generator for the test configurations to use in the brief tests. |
| + static std::vector<TestConfig> GenerateBriefTestConfigs() { |
| + std::vector<TestConfig> test_configs; |
| + for (int aec = static_cast<int>( |
| + AecType::BasicWebRtcAecSettingsWithDelayAgnosticAec); |
| + aec <= static_cast<int>(AecType::BasicWebRtcAecSettingsWithAecMobile); |
| + aec++) { |
| + TestConfig test_config; |
| + |
| + test_config.min_number_of_calls = 300; |
| + |
| + // Perform tests only with the extreme runtime parameter setting scheme. |
| + test_config.runtime_parameter_setting_scheme = |
| + RuntimeParameterSettingScheme::ExtremeStreamMetadataChangeScheme; |
| + |
| + // Only test 16 kHz for this test suite. |
| + test_config.initial_sample_rate_hz = 16000; |
| + |
| + // Create test config for the second processing API function set. |
| + test_config.render_api_function = |
| + RenderApiImpl::ProcessReverseStreamImpl2; |
| + test_config.capture_api_function = CaptureApiImpl::ProcessStreamImpl2; |
| + |
| + // Create test config for the first processing API function set. |
| + test_configs.push_back(test_config); |
| + test_config.render_api_function = |
| + RenderApiImpl::AnalyzeReverseStreamImpl2; |
| + test_config.capture_api_function = CaptureApiImpl::ProcessStreamImpl3; |
| + test_configs.push_back(test_config); |
| + } |
| + |
| + // Return the created test configurations. |
| + return test_configs; |
| + } |
| + |
| + // Checker for whether the a test configuration is valid. |
| + static bool ValidTestConfig(const TestConfig& test_config) { |
| + return ((((test_config.render_api_function == |
| + RenderApiImpl::ProcessReverseStreamImpl1) || |
| + (test_config.render_api_function == |
| + RenderApiImpl::AnalyzeReverseStreamImpl1)) && |
| + (test_config.capture_api_function == |
| + CaptureApiImpl::ProcessStreamImpl1)) || |
| + (((test_config.render_api_function != |
| + RenderApiImpl::ProcessReverseStreamImpl1) && |
| + (test_config.render_api_function != |
| + RenderApiImpl::AnalyzeReverseStreamImpl1)) && |
| + (test_config.capture_api_function != |
| + CaptureApiImpl::ProcessStreamImpl1))); |
| + } |
| + |
| + // Test case generator for the test configurations to use in the extensive |
| + // tests. |
| + static std::vector<TestConfig> GenerateExtensiveTestConfigs() { |
| + std::vector<TestConfig> test_configs; |
| + std::vector<TestConfig> tmp_test_configs; |
| + |
| + // Create test configurations for al the render API function |
| + // implementations. |
| + for (int render = |
| + static_cast<int>(RenderApiImpl::ProcessReverseStreamImpl1); |
| + render <= static_cast<int>(RenderApiImpl::AnalyzeReverseStreamImpl2); |
| + render++) { |
| + TestConfig test_config; |
| + test_config.render_api_function = static_cast<RenderApiImpl>(render); |
| + test_configs.push_back(test_config); |
| + } |
| + |
| + // Set the miminum number of calls for the test configurations. |
| + for (TestConfig& test_config : test_configs) { |
| + test_config.min_number_of_calls = 10000; |
| + } |
| + |
| + // Combine the existing set of test configurations with the capture API |
| + // function implementations. |
| + tmp_test_configs.swap(test_configs); |
| + test_configs.clear(); |
| + for (TestConfig test_config : tmp_test_configs) { |
| + for (int capture = static_cast<int>(CaptureApiImpl::ProcessStreamImpl1); |
| + capture <= static_cast<int>(CaptureApiImpl::ProcessStreamImpl3); |
| + capture++) { |
| + test_config.capture_api_function = static_cast<CaptureApiImpl>(capture); |
| + test_configs.push_back(test_config); |
| + } |
| + } |
| + |
| + // Combine the existing set of test configurations with the AEC |
| + // configurations. |
| + tmp_test_configs.swap(test_configs); |
| + test_configs.clear(); |
| + for (TestConfig test_config : tmp_test_configs) { |
| + for (int aec = static_cast<int>(AecType::BasicWebRtcAecSettings); |
| + aec <= |
| + static_cast<int>(AecType::BasicWebRtcAecSettingsWithAecMobile); |
| + aec++) { |
| + test_config.aec_type = static_cast<AecType>(aec); |
| + test_configs.push_back(test_config); |
| + } |
| + } |
| + |
| + // Combine the existing set of test configurations with the parameter |
| + // setting schemes. |
| + tmp_test_configs.swap(test_configs); |
| + test_configs.clear(); |
| + for (TestConfig test_config : tmp_test_configs) { |
| + for (int scheme = static_cast<int>( |
| + RuntimeParameterSettingScheme::SparseStreamMetadataChangeScheme); |
| + scheme <= |
| + static_cast<int>( |
| + RuntimeParameterSettingScheme::FixedStereoStreamMetadataScheme); |
| + scheme++) { |
| + // Only produce test configs with compatible render and capture API |
| + // calls. |
| + if (ValidTestConfig(test_config)) { |
| + // Add test configs with different initial sample rates and |
| + // parameter setting schemes. |
| + test_config.runtime_parameter_setting_scheme = |
| + static_cast<RuntimeParameterSettingScheme>(scheme); |
| + test_configs.push_back(test_config); |
| + } |
| + } |
| + } |
| + |
| + // Replicate the test configurations for all possible initial sample rates. |
| + tmp_test_configs.swap(test_configs); |
| + test_configs.clear(); |
| + for (TestConfig test_config : tmp_test_configs) { |
| + test_config.initial_sample_rate_hz = 8000; |
| + test_configs.push_back(test_config); |
| + |
| + test_config.initial_sample_rate_hz = 16000; |
| + test_configs.push_back(test_config); |
| + |
| + if (test_config.aec_type != |
| + AecType::BasicWebRtcAecSettingsWithAecMobile) { |
| + test_config.initial_sample_rate_hz = 32000; |
| + test_configs.push_back(test_config); |
| + |
| + test_config.initial_sample_rate_hz = 48000; |
| + test_configs.push_back(test_config); |
| + } |
| + |
| + test_config.initial_sample_rate_hz = 8000; |
| + test_configs.push_back(test_config); |
| + |
| + test_config.initial_sample_rate_hz = 16000; |
| + test_configs.push_back(test_config); |
| + } |
| + |
| + // Return the created test configurations. |
| + return test_configs; |
| + } |
| + |
| + RenderApiImpl render_api_function; |
| + CaptureApiImpl capture_api_function; |
| + RuntimeParameterSettingScheme runtime_parameter_setting_scheme; |
| + int initial_sample_rate_hz; |
| + AecType aec_type; |
| + int min_number_of_calls; |
| +}; |
| + |
| +// Handler for the frame counters. |
| +class FrameCounters { |
| + public: |
| + void IncreaseRenderCounter() { |
| + rtc::CritScope cs(&crit_); |
| + render_count++; |
| + } |
| + |
| + void IncreaseCaptureCounter() { |
| + rtc::CritScope cs(&crit_); |
| + capture_count++; |
| + } |
| + |
| + int GetCaptureCounter() { |
| + rtc::CritScope cs(&crit_); |
| + return capture_count; |
| + } |
| + |
| + int GetRenderCounter() { |
| + rtc::CritScope cs(&crit_); |
| + return capture_count; |
| + } |
| + |
| + int CaptureMinusRenderCounters() { |
| + rtc::CritScope cs(&crit_); |
| + return capture_count - render_count; |
| + } |
| + |
| + bool BothCountersExceedeThreshold(int threshold) { |
| + rtc::CritScope cs(&crit_); |
| + return (render_count > threshold && capture_count > threshold); |
| + } |
| + |
| + private: |
| + rtc::CriticalSection crit_; |
| + int render_count GUARDED_BY(crit_) = 0; |
| + int capture_count GUARDED_BY(crit_) = 0; |
| +}; |
| + |
| +// Checker for whether the capture side has been called. |
| +class CaptureSideCalledChecker { |
| + public: |
| + bool CaptureSideCalled() { |
| + rtc::CritScope cs(&crit_); |
| + return capture_side_called_; |
| + } |
| + |
| + void FlagCaptureSideCalled() { |
| + rtc::CritScope cs(&crit_); |
| + capture_side_called_ = true; |
| + } |
| + |
| + private: |
| + rtc::CriticalSection crit_; |
| + bool capture_side_called_ GUARDED_BY(crit_) = false; |
| +}; |
| + |
| +// Class for handling the capture side processing. |
| +class CaptureProcessor { |
| + public: |
| + CaptureProcessor(int max_frame_size, |
| + test::Random* rand_gen, |
| + FrameCounters* shared_counters_state, |
| + CaptureSideCalledChecker* capture_call_checker, |
| + AudioProcessingImplLockTest* test_framework, |
| + TestConfig* test_config, |
| + AudioProcessing* apm); |
| + |
| + bool Process(); |
| + |
| + private: |
| + static const int kMaxCallDifference = 10; |
| + static const float kCaptureInputFloatLevel; |
| + static const int kCaptureInputFixLevel = 1024; |
| + |
| + void CallApmCaptureSide(); |
| + void PrepareFrame(); |
| + void ApplyRuntimeSettingScheme(); |
| + |
| + test::Random* rand_gen_; |
| + FrameCounters* frame_counters_; |
| + CaptureSideCalledChecker* capture_call_checker_; |
| + AudioProcessingImplLockTest* test_; |
| + TestConfig* test_config_; |
| + AudioProcessing* apm_; |
| + AudioFrameData frame_data_; |
| +}; |
| + |
| +// Class for handling the stats processing. |
| +class StatsProcessor { |
| + public: |
| + StatsProcessor(test::Random* rand_gen, |
| + TestConfig* test_config, |
| + AudioProcessing* apm); |
| + |
| + bool Process(); |
| + |
| + private: |
| + test::Random* rand_gen_; |
| + TestConfig* test_config_; |
| + AudioProcessing* apm_; |
| +}; |
| + |
| +// Class for handling the render side processing. |
| +class RenderProcessor { |
| + public: |
| + RenderProcessor(int max_frame_size, |
| + test::Random* rand_gen, |
| + FrameCounters* shared_counters_state, |
| + CaptureSideCalledChecker* capture_call_checker, |
| + AudioProcessingImplLockTest* test_framework, |
| + TestConfig* test_config, |
| + AudioProcessing* apm); |
| + |
| + bool Process(); |
| + |
| + private: |
| + static const int kMaxCallDifference = 10; |
| + static const int kRenderInputFixLevel = 16384; |
| + static const float kRenderInputFloatLevel; |
| + |
| + void CallApmRenderSide(); |
| + void ApplyRuntimeSettingScheme(); |
| + void PrepareFrame(); |
| + |
| + test::Random* rand_gen_; |
| + FrameCounters* frame_counters_; |
| + CaptureSideCalledChecker* capture_call_checker_; |
| + AudioProcessingImplLockTest* test_; |
| + TestConfig* test_config_; |
| + AudioProcessing* apm_; |
| + bool first_render_side_call_ = true; |
| + AudioFrameData frame_data_; |
| +}; |
| + |
| +// Class for implementing the tests of the locks in the audio processing module. |
| +class AudioProcessingImplLockTest |
| + : public ::testing::TestWithParam<TestConfig> { |
| + public: |
| + AudioProcessingImplLockTest(); |
| + EventTypeWrapper RunTest(); |
| + void SetUp() override; |
| + void TearDown() override; |
| + void CheckTestCompleteness(); |
| + |
| + private: |
| + static const int kTestTimeOutLimit = 10 * 60 * 1000; |
| + static const int kMaxFrameSize = 480; |
| + |
| + // Thread callback for the render thread |
| + static bool RenderProcessorCallback(void* context) { |
| + return reinterpret_cast<AudioProcessingImplLockTest*>(context) |
| + ->render_thread_state_.Process(); |
| + } |
| + |
| + // Thread callback for the capture thread |
| + static bool CaptureProcessorCallback(void* context) { |
| + return reinterpret_cast<AudioProcessingImplLockTest*>(context) |
| + ->capture_thread_state_.Process(); |
| + } |
| + |
| + // Thread callback for the stats thread |
| + static bool StatsProcessorCallback(void* context) { |
| + return reinterpret_cast<AudioProcessingImplLockTest*>(context) |
| + ->stats_thread_state_.Process(); |
| + } |
| + |
| + // Tests whether all the required render and capture side calls have been |
| + // done. |
| + bool TestDone() { |
| + return frame_counters_.BothCountersExceedeThreshold( |
| + test_config_.min_number_of_calls); |
| + } |
| + |
| + // Start the threads used in the test. |
| + void StartThreads() { |
| + ASSERT_TRUE(render_thread_->Start()); |
| + render_thread_->SetPriority(kRealtimePriority); |
| + ASSERT_TRUE(capture_thread_->Start()); |
| + capture_thread_->SetPriority(kRealtimePriority); |
| + ASSERT_TRUE(stats_thread_->Start()); |
| + stats_thread_->SetPriority(kNormalPriority); |
| + } |
| + |
| + // Event handler for the test. |
| + const rtc::scoped_ptr<EventWrapper> test_complete_; |
| + |
| + // Thread related variables. |
| + rtc::scoped_ptr<ThreadWrapper> render_thread_; |
| + rtc::scoped_ptr<ThreadWrapper> capture_thread_; |
| + rtc::scoped_ptr<ThreadWrapper> stats_thread_; |
| + mutable test::Random rand_gen_; |
| + |
| + rtc::scoped_ptr<AudioProcessing> apm_; |
| + TestConfig test_config_; |
| + FrameCounters frame_counters_; |
| + CaptureSideCalledChecker capture_call_checker_; |
| + RenderProcessor render_thread_state_; |
| + CaptureProcessor capture_thread_state_; |
| + StatsProcessor stats_thread_state_; |
| +}; |
| + |
| +AudioProcessingImplLockTest::AudioProcessingImplLockTest() |
| + : test_complete_(EventWrapper::Create()), |
| + render_thread_( |
| + ThreadWrapper::CreateThread(RenderProcessorCallback, this, "render")), |
| + capture_thread_(ThreadWrapper::CreateThread(CaptureProcessorCallback, |
| + this, |
| + "capture")), |
| + stats_thread_( |
| + ThreadWrapper::CreateThread(StatsProcessorCallback, this, "stats")), |
| + rand_gen_(42U), |
| + apm_(AudioProcessingImpl::Create()), |
| + render_thread_state_(kMaxFrameSize, |
| + &rand_gen_, |
| + &frame_counters_, |
| + &capture_call_checker_, |
| + this, |
| + &test_config_, |
| + apm_.get()), |
| + capture_thread_state_(kMaxFrameSize, |
| + &rand_gen_, |
| + &frame_counters_, |
| + &capture_call_checker_, |
| + this, |
| + &test_config_, |
| + apm_.get()), |
| + stats_thread_state_(&rand_gen_, &test_config_, apm_.get()) {} |
| + |
| +// Run the test with a timeout. |
| +EventTypeWrapper AudioProcessingImplLockTest::RunTest() { |
| + StartThreads(); |
| + return test_complete_->Wait(kTestTimeOutLimit); |
| +} |
| + |
| +// Setup of test and APM. |
| +void AudioProcessingImplLockTest::SetUp() { |
| + // apm_.reset(AudioProcessingImpl::Create()); |
| + test_config_ = static_cast<TestConfig>(GetParam()); |
| + |
| + ASSERT_EQ(apm_->kNoError, apm_->level_estimator()->Enable(true)); |
| + ASSERT_EQ(apm_->kNoError, apm_->gain_control()->Enable(true)); |
| + |
| + ASSERT_EQ(apm_->kNoError, |
| + apm_->gain_control()->set_mode(GainControl::kAdaptiveAnalog)); |
| + ASSERT_EQ(apm_->kNoError, apm_->gain_control()->Enable(true)); |
| + |
| + ASSERT_EQ(apm_->kNoError, apm_->noise_suppression()->Enable(true)); |
| + ASSERT_EQ(apm_->kNoError, apm_->voice_detection()->Enable(true)); |
| + |
| + Config config; |
| + if (test_config_.aec_type == AecType::AecTurnedOff) { |
| + ASSERT_EQ(apm_->kNoError, apm_->echo_control_mobile()->Enable(false)); |
| + ASSERT_EQ(apm_->kNoError, apm_->echo_cancellation()->Enable(false)); |
| + } else if (test_config_.aec_type == |
| + AecType::BasicWebRtcAecSettingsWithAecMobile) { |
| + ASSERT_EQ(apm_->kNoError, apm_->echo_control_mobile()->Enable(true)); |
| + ASSERT_EQ(apm_->kNoError, apm_->echo_cancellation()->Enable(false)); |
| + } else { |
| + ASSERT_EQ(apm_->kNoError, apm_->echo_control_mobile()->Enable(false)); |
| + ASSERT_EQ(apm_->kNoError, apm_->echo_cancellation()->Enable(true)); |
| + ASSERT_EQ(apm_->kNoError, apm_->echo_cancellation()->enable_metrics(true)); |
| + ASSERT_EQ(apm_->kNoError, |
| + apm_->echo_cancellation()->enable_delay_logging(true)); |
| + |
| + config.Set<ExtendedFilter>( |
| + new ExtendedFilter(test_config_.aec_type == |
| + AecType::BasicWebRtcAecSettingsWithExtentedFilter)); |
| + |
| + config.Set<DelayAgnostic>( |
| + new DelayAgnostic(test_config_.aec_type == |
| + AecType::BasicWebRtcAecSettingsWithDelayAgnosticAec)); |
| + |
| + apm_->SetExtraOptions(config); |
| + } |
| +} |
| + |
| +void AudioProcessingImplLockTest::TearDown() { |
| + render_thread_->Stop(); |
| + capture_thread_->Stop(); |
| + stats_thread_->Stop(); |
| +} |
| + |
| +StatsProcessor::StatsProcessor(test::Random* rand_gen, |
| + TestConfig* test_config, |
| + AudioProcessing* apm) |
| + : rand_gen_(rand_gen), test_config_(test_config), apm_(apm) {} |
| + |
| +// Implements the callback functionality for the statistics |
| +// collection thread. |
| +bool StatsProcessor::Process() { |
| + SleepRandomMs(100, rand_gen_); |
| + |
| + EXPECT_EQ(apm_->echo_cancellation()->is_enabled(), |
| + ((test_config_->aec_type != AecType::AecTurnedOff) && |
| + (test_config_->aec_type != |
| + AecType::BasicWebRtcAecSettingsWithAecMobile))); |
| + apm_->echo_cancellation()->stream_drift_samples(); |
| + EXPECT_EQ(apm_->echo_control_mobile()->is_enabled(), |
| + (test_config_->aec_type != AecType::AecTurnedOff) && |
| + (test_config_->aec_type == |
| + AecType::BasicWebRtcAecSettingsWithAecMobile)); |
| + EXPECT_TRUE(apm_->gain_control()->is_enabled()); |
| + apm_->gain_control()->stream_analog_level(); |
| + EXPECT_TRUE(apm_->noise_suppression()->is_enabled()); |
| + float speech_probablitity = apm_->noise_suppression()->speech_probability(); |
| + EXPECT_TRUE(speech_probablitity < (apm_->kUnsupportedFunctionError + 0.5f) || |
| + speech_probablitity >= 0); |
| + apm_->voice_detection()->is_enabled(); |
| + |
| + return true; |
| +} |
| + |
| +const float CaptureProcessor::kCaptureInputFloatLevel = 0.03125f; |
| + |
| +// Applies the capture side processing API call. |
| +void CaptureProcessor::CallApmCaptureSide() { |
| + // Prepare a proper capture side processing API call input. |
| + PrepareFrame(); |
| + |
| + // Set the stream delay |
| + apm_->set_stream_delay_ms(30); |
| + |
| + // Call the specified capture side API processing method. |
| + int result = AudioProcessing::kNoError; |
| + switch (test_config_->capture_api_function) { |
| + case CaptureApiImpl::ProcessStreamImpl1: |
| + result = apm_->ProcessStream(&frame_data_.frame); |
| + break; |
| + case CaptureApiImpl::ProcessStreamImpl2: |
| + result = apm_->ProcessStream( |
| + &frame_data_.input_frame[0], frame_data_.input_samples_per_channel, |
| + frame_data_.input_sample_rate_hz, frame_data_.input_channel_layout, |
| + frame_data_.output_sample_rate_hz, frame_data_.output_channel_layout, |
| + &frame_data_.output_frame[0]); |
| + break; |
| + case CaptureApiImpl::ProcessStreamImpl3: |
| + result = apm_->ProcessStream( |
| + &frame_data_.input_frame[0], frame_data_.input_stream_config, |
| + frame_data_.output_stream_config, &frame_data_.output_frame[0]); |
| + break; |
| + default: |
| + assert(false); |
|
the sun
2015/11/04 12:36:40
FAIL(), RTC_NOTREACHED() or ASSERT_TRUE(false)
peah-webrtc
2015/11/05 10:10:09
Done.
kwiberg-webrtc
2015/11/05 10:15:23
Nit: I still count three assert()s in the latest p
peah-webrtc
2015/11/05 10:21:55
Done.
peah-webrtc
2015/11/05 10:21:55
Great! Thanks!
Done.
|
| + } |
| + |
| + // Check the return code for error. |
| + ASSERT_EQ(AudioProcessing::kNoError, result); |
| +} |
| + |
| +// Applies any runtime capture APM API calls and audio stream characteristics |
| +// specified by the scheme for the test. |
| +void CaptureProcessor::ApplyRuntimeSettingScheme() { |
| + const int capture_count_local = frame_counters_->GetCaptureCounter(); |
| + |
| + // Update the number of channels and sample rates for the input and output. |
| + // Note that the counts frequencies for when to set parameters |
| + // are set using prime numbers in order to ensure that the |
| + // permutation scheme in the parameter setting changes. |
| + switch (test_config_->runtime_parameter_setting_scheme) { |
| + case RuntimeParameterSettingScheme::SparseStreamMetadataChangeScheme: |
| + if (capture_count_local == 0) |
| + frame_data_.input_sample_rate_hz = 16000; |
| + else if (capture_count_local % 11 == 0) |
| + frame_data_.input_sample_rate_hz = 32000; |
| + else if (capture_count_local % 73 == 0) |
| + frame_data_.input_sample_rate_hz = 48000; |
| + else if (capture_count_local % 89 == 0) |
| + frame_data_.input_sample_rate_hz = 16000; |
| + else if (capture_count_local % 97 == 0) |
| + frame_data_.input_sample_rate_hz = 8000; |
| + |
| + if (capture_count_local == 0) |
| + frame_data_.input_number_of_channels = 1; |
| + else if (capture_count_local % 4 == 0) |
| + frame_data_.input_number_of_channels = |
| + (frame_data_.input_number_of_channels == 1 ? 2 : 1); |
| + |
| + if (capture_count_local == 0) |
| + frame_data_.output_sample_rate_hz = 16000; |
| + else if (capture_count_local % 5 == 0) |
| + frame_data_.output_sample_rate_hz = 32000; |
| + else if (capture_count_local % 47 == 0) |
| + frame_data_.output_sample_rate_hz = 48000; |
| + else if (capture_count_local % 53 == 0) |
| + frame_data_.output_sample_rate_hz = 16000; |
| + else if (capture_count_local % 71 == 0) |
| + frame_data_.output_sample_rate_hz = 8000; |
| + |
| + if (capture_count_local == 0) |
| + frame_data_.output_number_of_channels = 1; |
| + else if (capture_count_local % 8 == 0) |
| + frame_data_.output_number_of_channels = |
| + (frame_data_.output_number_of_channels == 1 ? 2 : 1); |
| + break; |
| + case RuntimeParameterSettingScheme::ExtremeStreamMetadataChangeScheme: |
| + if (capture_count_local % 2 == 0) { |
| + frame_data_.input_number_of_channels = 1; |
| + frame_data_.input_sample_rate_hz = 16000; |
| + frame_data_.output_number_of_channels = 1; |
| + frame_data_.output_sample_rate_hz = 16000; |
| + } else { |
| + frame_data_.input_number_of_channels = |
| + (frame_data_.input_number_of_channels == 1 ? 2 : 1); |
| + if (frame_data_.input_sample_rate_hz == 8000) |
| + frame_data_.input_sample_rate_hz = 16000; |
| + else if (frame_data_.input_sample_rate_hz == 16000) |
| + frame_data_.input_sample_rate_hz = 32000; |
| + else if (frame_data_.input_sample_rate_hz == 32000) |
| + frame_data_.input_sample_rate_hz = 48000; |
| + else if (frame_data_.input_sample_rate_hz == 48000) |
| + frame_data_.input_sample_rate_hz = 8000; |
| + |
| + frame_data_.output_number_of_channels = |
| + (frame_data_.output_number_of_channels == 1 ? 2 : 1); |
| + if (frame_data_.output_sample_rate_hz == 8000) |
| + frame_data_.output_sample_rate_hz = 16000; |
| + else if (frame_data_.output_sample_rate_hz == 16000) |
| + frame_data_.output_sample_rate_hz = 32000; |
| + else if (frame_data_.output_sample_rate_hz == 32000) |
| + frame_data_.output_sample_rate_hz = 48000; |
| + else if (frame_data_.output_sample_rate_hz == 48000) |
| + frame_data_.output_sample_rate_hz = 8000; |
| + } |
| + break; |
| + case RuntimeParameterSettingScheme::FixedMonoStreamMetadataScheme: |
| + if (capture_count_local == 0) { |
| + frame_data_.input_sample_rate_hz = 16000; |
| + frame_data_.input_number_of_channels = 1; |
| + frame_data_.output_sample_rate_hz = 16000; |
| + frame_data_.output_number_of_channels = 1; |
| + } |
| + break; |
| + case RuntimeParameterSettingScheme::FixedStereoStreamMetadataScheme: |
| + if (capture_count_local == 0) { |
| + frame_data_.input_sample_rate_hz = 16000; |
| + frame_data_.input_number_of_channels = 2; |
| + frame_data_.output_sample_rate_hz = 16000; |
| + frame_data_.output_number_of_channels = 2; |
| + } |
| + |
| + break; |
| + default: |
| + assert(false); |
| + } |
| + |
| + // Call any specified runtime APM setter and |
| + // getter calls. |
| + switch (test_config_->runtime_parameter_setting_scheme) { |
| + case RuntimeParameterSettingScheme::SparseStreamMetadataChangeScheme: |
| + case RuntimeParameterSettingScheme::FixedMonoStreamMetadataScheme: |
| + break; |
| + case RuntimeParameterSettingScheme::ExtremeStreamMetadataChangeScheme: |
| + case RuntimeParameterSettingScheme::FixedStereoStreamMetadataScheme: |
| + if (capture_count_local % 2 == 0) { |
| + ASSERT_EQ(AudioProcessing::Error::kNoError, |
| + apm_->set_stream_delay_ms(30)); |
| + apm_->set_stream_key_pressed(true); |
| + apm_->set_output_will_be_muted(true); |
| + apm_->set_delay_offset_ms(15); |
| + EXPECT_EQ(apm_->delay_offset_ms(), 15); |
| + EXPECT_GE(apm_->num_reverse_channels(), 0); |
| + EXPECT_LE(apm_->num_reverse_channels(), 2); |
| + } else { |
| + ASSERT_EQ(AudioProcessing::Error::kNoError, |
| + apm_->set_stream_delay_ms(50)); |
| + apm_->set_stream_key_pressed(false); |
| + apm_->set_output_will_be_muted(false); |
| + apm_->set_delay_offset_ms(20); |
| + EXPECT_EQ(apm_->delay_offset_ms(), 20); |
| + apm_->delay_offset_ms(); |
| + apm_->num_reverse_channels(); |
| + EXPECT_GE(apm_->num_reverse_channels(), 0); |
| + EXPECT_LE(apm_->num_reverse_channels(), 2); |
| + } |
| + break; |
| + default: |
| + FAIL(); |
| + } |
| + |
| + // Restric the number of output channels not to exceed |
| + // the number of input channels. |
| + frame_data_.output_number_of_channels = |
| + std::min(frame_data_.output_number_of_channels, |
| + frame_data_.input_number_of_channels); |
| +} |
| + |
| +// Prepares a frame with relevant audio data and metadata. |
| +void CaptureProcessor::PrepareFrame() { |
| + // Restrict to a common fixed sample rate if the AudioFrame |
| + // interface is used. |
| + if (test_config_->capture_api_function == |
| + CaptureApiImpl::ProcessStreamImpl1) { |
| + frame_data_.input_sample_rate_hz = test_config_->initial_sample_rate_hz; |
| + frame_data_.output_sample_rate_hz = test_config_->initial_sample_rate_hz; |
| + } |
| + |
| + // Prepare the audioframe data and metadata. |
| + frame_data_.input_samples_per_channel = |
| + frame_data_.input_sample_rate_hz * AudioProcessing::kChunkSizeMs / 1000; |
| + frame_data_.frame.sample_rate_hz_ = frame_data_.input_sample_rate_hz; |
| + frame_data_.frame.num_channels_ = frame_data_.input_number_of_channels; |
| + frame_data_.frame.samples_per_channel_ = |
| + frame_data_.input_samples_per_channel; |
| + memset(frame_data_.frame.data_, 0, frame_data_.input_samples_per_channel * |
| + sizeof(frame_data_.frame.data_[0])); |
| + PopulateAudioFrame(&frame_data_.frame, kCaptureInputFixLevel, rand_gen_); |
| + |
| + // Prepare the float audio input data and metadata. |
| + frame_data_.input_stream_config.set_sample_rate_hz( |
| + frame_data_.input_sample_rate_hz); |
| + frame_data_.input_stream_config.set_num_channels( |
| + frame_data_.input_number_of_channels); |
| + frame_data_.input_stream_config.set_has_keyboard(false); |
| + PopulateAudioFrame(&frame_data_.input_frame[0], kCaptureInputFloatLevel, |
| + frame_data_.input_number_of_channels, |
| + frame_data_.input_samples_per_channel, rand_gen_); |
| + frame_data_.input_channel_layout = |
| + (frame_data_.input_number_of_channels == 1 |
| + ? AudioProcessing::ChannelLayout::kMonoAndKeyboard |
| + : AudioProcessing::ChannelLayout::kStereoAndKeyboard); |
| + |
| + // Prepare the float audio output data and metadata. |
| + frame_data_.output_samples_per_channel = |
| + frame_data_.output_sample_rate_hz * AudioProcessing::kChunkSizeMs / 1000; |
| + frame_data_.output_stream_config.set_sample_rate_hz( |
| + frame_data_.output_sample_rate_hz); |
| + frame_data_.output_stream_config.set_num_channels( |
| + frame_data_.output_number_of_channels); |
| + frame_data_.output_stream_config.set_has_keyboard(false); |
| + frame_data_.output_channel_layout = |
| + (frame_data_.output_number_of_channels == 1 |
| + ? AudioProcessing::ChannelLayout::kMono |
| + : AudioProcessing::ChannelLayout::kStereo); |
| +} |
| + |
| +// Implements the callback functionality for the capture thread. |
| +bool CaptureProcessor::Process() { |
| + // Sleep a random time to simulate thread jitter. |
| + SleepRandomMs(3, rand_gen_); |
| + |
| + // End the test is complete. |
| + test_->CheckTestCompleteness(); |
| + |
| + // Ensure that there are not more capture side calls than render side |
| + // calls. |
| + if (capture_call_checker_->CaptureSideCalled()) { |
| + while (kMaxCallDifference < frame_counters_->CaptureMinusRenderCounters()) { |
| + SleepMs(1); |
| + } |
| + } |
| + |
| + // Apply any specified capture side APM non-processing runtime calls. |
| + ApplyRuntimeSettingScheme(); |
| + |
| + // Apply the capture side processing call. |
| + CallApmCaptureSide(); |
| + |
| + // Increase the number of capture-side calls. |
| + frame_counters_->IncreaseCaptureCounter(); |
| + |
| + // Flag that the capture side has been called at least once |
| + // (needed to ensure that a capture call has been done |
| + // before the first render call is performed (implicitly |
| + // required by the APM API). |
| + capture_call_checker_->FlagCaptureSideCalled(); |
| + |
| + return true; |
| +} |
| + |
| +CaptureProcessor::CaptureProcessor( |
| + int max_frame_size, |
| + test::Random* rand_gen, |
| + FrameCounters* shared_counters_state, |
| + CaptureSideCalledChecker* capture_call_checker, |
| + AudioProcessingImplLockTest* test_framework, |
| + TestConfig* test_config, |
| + AudioProcessing* apm) |
| + : rand_gen_(rand_gen), |
| + frame_counters_(shared_counters_state), |
| + capture_call_checker_(capture_call_checker), |
| + test_(test_framework), |
| + test_config_(test_config), |
| + apm_(apm), |
| + frame_data_(max_frame_size) {} |
| + |
| +const float RenderProcessor::kRenderInputFloatLevel = 0.5f; |
| + |
| +RenderProcessor::RenderProcessor(int max_frame_size, |
| + test::Random* rand_gen, |
| + FrameCounters* shared_counters_state, |
| + CaptureSideCalledChecker* capture_call_checker, |
| + AudioProcessingImplLockTest* test_framework, |
| + TestConfig* test_config, |
| + AudioProcessing* apm) |
| + : rand_gen_(rand_gen), |
| + frame_counters_(shared_counters_state), |
| + capture_call_checker_(capture_call_checker), |
| + test_(test_framework), |
| + test_config_(test_config), |
| + apm_(apm), |
| + frame_data_(max_frame_size) {} |
| + |
| +// Prepares the render side frame and the accompanying metadata |
| +// with the appropriate information. |
| +void RenderProcessor::PrepareFrame() { |
| + // Restrict to a common fixed sample rate if the AudioFrame interface is |
| + // used. |
| + if ((test_config_->render_api_function == |
| + RenderApiImpl::AnalyzeReverseStreamImpl1) || |
| + (test_config_->render_api_function == |
| + RenderApiImpl::ProcessReverseStreamImpl1) || |
| + (test_config_->aec_type != |
| + AecType::BasicWebRtcAecSettingsWithAecMobile)) { |
| + frame_data_.input_sample_rate_hz = test_config_->initial_sample_rate_hz; |
| + frame_data_.output_sample_rate_hz = test_config_->initial_sample_rate_hz; |
| + } |
| + |
| + // Prepare the audioframe data and metadata |
| + frame_data_.input_samples_per_channel = |
| + frame_data_.input_sample_rate_hz * AudioProcessing::kChunkSizeMs / 1000; |
| + frame_data_.frame.sample_rate_hz_ = frame_data_.input_sample_rate_hz; |
| + frame_data_.frame.num_channels_ = frame_data_.input_number_of_channels; |
| + frame_data_.frame.samples_per_channel_ = |
| + frame_data_.input_samples_per_channel; |
| + memset(frame_data_.frame.data_, 0, frame_data_.input_samples_per_channel * |
| + sizeof(frame_data_.frame.data_[0])); |
| + PopulateAudioFrame(&frame_data_.frame, kRenderInputFixLevel, rand_gen_); |
| + |
| + // Prepare the float audio input data and metadata. |
| + frame_data_.input_stream_config.set_sample_rate_hz( |
| + frame_data_.input_sample_rate_hz); |
| + frame_data_.input_stream_config.set_num_channels( |
| + frame_data_.input_number_of_channels); |
| + frame_data_.input_stream_config.set_has_keyboard(false); |
| + PopulateAudioFrame(&frame_data_.input_frame[0], kRenderInputFloatLevel, |
| + frame_data_.input_number_of_channels, |
| + frame_data_.input_samples_per_channel, rand_gen_); |
| + frame_data_.input_channel_layout = |
| + (frame_data_.input_number_of_channels == 1 |
| + ? AudioProcessing::ChannelLayout::kMono |
| + : AudioProcessing::ChannelLayout::kStereo); |
| + |
| + // Prepare the float audio output data and metadata. |
| + frame_data_.output_samples_per_channel = |
| + frame_data_.output_sample_rate_hz * AudioProcessing::kChunkSizeMs / 1000; |
| + frame_data_.output_stream_config.set_sample_rate_hz( |
| + frame_data_.output_sample_rate_hz); |
| + frame_data_.output_stream_config.set_num_channels( |
| + frame_data_.output_number_of_channels); |
| + frame_data_.output_stream_config.set_has_keyboard(false); |
| + frame_data_.output_channel_layout = |
| + (frame_data_.output_number_of_channels == 1 |
| + ? AudioProcessing::ChannelLayout::kMono |
| + : AudioProcessing::ChannelLayout::kStereo); |
| +} |
| + |
| +// Makes the render side processing API call. |
| +void RenderProcessor::CallApmRenderSide() { |
| + // Prepare a proper render side processing API call input. |
| + PrepareFrame(); |
| + |
| + // Call the specified render side API processing method. |
| + int result = AudioProcessing::kNoError; |
| + switch (test_config_->render_api_function) { |
| + case RenderApiImpl::ProcessReverseStreamImpl1: |
| + result = apm_->ProcessReverseStream(&frame_data_.frame); |
| + break; |
| + case RenderApiImpl::ProcessReverseStreamImpl2: |
| + result = apm_->ProcessReverseStream( |
| + &frame_data_.input_frame[0], frame_data_.input_stream_config, |
| + frame_data_.output_stream_config, &frame_data_.output_frame[0]); |
| + break; |
| + case RenderApiImpl::AnalyzeReverseStreamImpl1: |
| + result = apm_->AnalyzeReverseStream(&frame_data_.frame); |
| + break; |
| + case RenderApiImpl::AnalyzeReverseStreamImpl2: |
| + result = apm_->AnalyzeReverseStream( |
| + &frame_data_.input_frame[0], frame_data_.input_samples_per_channel, |
| + frame_data_.input_sample_rate_hz, frame_data_.input_channel_layout); |
| + break; |
| + default: |
| + assert(false); |
| + } |
| + |
| + // Check the return code for error. |
| + ASSERT_EQ(AudioProcessing::kNoError, result); |
| +} |
| + |
| +// Applies any render capture side APM API calls and audio stream |
| +// characteristics |
| +// specified by the scheme for the test. |
| +void RenderProcessor::ApplyRuntimeSettingScheme() { |
| + const int render_count_local = frame_counters_->GetRenderCounter(); |
| + |
| + // Update the number of channels and sample rates for the input and output. |
| + // Note that the counts frequencies for when to set parameters |
| + // are set using prime numbers in order to ensure that the |
| + // permutation scheme in the parameter setting changes. |
| + switch (test_config_->runtime_parameter_setting_scheme) { |
| + case RuntimeParameterSettingScheme::SparseStreamMetadataChangeScheme: |
| + if (render_count_local == 0) |
| + frame_data_.input_sample_rate_hz = 16000; |
| + else if (render_count_local % 47 == 0) |
| + frame_data_.input_sample_rate_hz = 32000; |
| + else if (render_count_local % 71 == 0) |
| + frame_data_.input_sample_rate_hz = 48000; |
| + else if (render_count_local % 79 == 0) |
| + frame_data_.input_sample_rate_hz = 16000; |
| + else if (render_count_local % 83 == 0) |
| + frame_data_.input_sample_rate_hz = 8000; |
| + |
| + if (render_count_local == 0) |
| + frame_data_.input_number_of_channels = 1; |
| + else if (render_count_local % 4 == 0) |
| + frame_data_.input_number_of_channels = |
| + (frame_data_.input_number_of_channels == 1 ? 2 : 1); |
| + |
| + if (render_count_local == 0) |
| + frame_data_.output_sample_rate_hz = 16000; |
| + else if (render_count_local % 17 == 0) |
| + frame_data_.output_sample_rate_hz = 32000; |
| + else if (render_count_local % 19 == 0) |
| + frame_data_.output_sample_rate_hz = 48000; |
| + else if (render_count_local % 29 == 0) |
| + frame_data_.output_sample_rate_hz = 16000; |
| + else if (render_count_local % 61 == 0) |
| + frame_data_.output_sample_rate_hz = 8000; |
| + |
| + if (render_count_local == 0) |
| + frame_data_.output_number_of_channels = 1; |
| + else if (render_count_local % 8 == 0) |
| + frame_data_.output_number_of_channels = |
| + (frame_data_.output_number_of_channels == 1 ? 2 : 1); |
| + break; |
| + case RuntimeParameterSettingScheme::ExtremeStreamMetadataChangeScheme: |
| + if (render_count_local == 0) { |
| + frame_data_.input_number_of_channels = 1; |
| + frame_data_.input_sample_rate_hz = 16000; |
| + frame_data_.output_number_of_channels = 1; |
| + frame_data_.output_sample_rate_hz = 16000; |
| + } else { |
| + frame_data_.input_number_of_channels = |
| + (frame_data_.input_number_of_channels == 1 ? 2 : 1); |
| + if (frame_data_.input_sample_rate_hz == 8000) |
| + frame_data_.input_sample_rate_hz = 16000; |
| + else if (frame_data_.input_sample_rate_hz == 16000) |
| + frame_data_.input_sample_rate_hz = 32000; |
| + else if (frame_data_.input_sample_rate_hz == 32000) |
| + frame_data_.input_sample_rate_hz = 48000; |
| + else if (frame_data_.input_sample_rate_hz == 48000) |
| + frame_data_.input_sample_rate_hz = 8000; |
| + |
| + frame_data_.output_number_of_channels = |
| + (frame_data_.output_number_of_channels == 1 ? 2 : 1); |
| + if (frame_data_.output_sample_rate_hz == 8000) |
| + frame_data_.output_sample_rate_hz = 16000; |
| + else if (frame_data_.output_sample_rate_hz == 16000) |
| + frame_data_.output_sample_rate_hz = 32000; |
| + else if (frame_data_.output_sample_rate_hz == 32000) |
| + frame_data_.output_sample_rate_hz = 48000; |
| + else if (frame_data_.output_sample_rate_hz == 48000) |
| + frame_data_.output_sample_rate_hz = 8000; |
| + } |
| + break; |
| + case RuntimeParameterSettingScheme::FixedMonoStreamMetadataScheme: |
| + if (render_count_local == 0) { |
| + frame_data_.input_sample_rate_hz = 16000; |
| + frame_data_.input_number_of_channels = 1; |
| + frame_data_.output_sample_rate_hz = 16000; |
| + frame_data_.output_number_of_channels = 1; |
| + } |
| + break; |
| + case RuntimeParameterSettingScheme::FixedStereoStreamMetadataScheme: |
| + if (render_count_local == 0) { |
| + frame_data_.input_sample_rate_hz = 16000; |
| + frame_data_.input_number_of_channels = 2; |
| + frame_data_.output_sample_rate_hz = 16000; |
| + frame_data_.output_number_of_channels = 2; |
| + } |
| + |
| + break; |
| + default: |
| + assert(false); |
| + } |
| + |
| + // Restric the number of output channels not to exceed |
| + // the number of input channels. |
| + frame_data_.output_number_of_channels = |
| + std::min(frame_data_.output_number_of_channels, |
| + frame_data_.input_number_of_channels); |
| +} |
| + |
| +// Implements the callback functionality for the render thread. |
| +bool RenderProcessor::Process() { |
| + // Conditional wait to ensure that a capture call has been done |
| + // before the first render call is performed (implicitly |
| + // required by the APM API). |
| + if (first_render_side_call_) { |
| + while (!capture_call_checker_->CaptureSideCalled()) { |
| + SleepRandomMs(3, rand_gen_); |
| + } |
| + |
| + first_render_side_call_ = false; |
| + } |
| + |
| + // Sleep a random time to simulate thread jitter. |
| + SleepRandomMs(3, rand_gen_); |
| + |
| + // End the test early if a fatal failure (ASSERT_*) has occurred. |
| + test_->CheckTestCompleteness(); |
| + |
| + // Ensure that the number of render and capture calls do not |
| + // differ too much. |
| + while (kMaxCallDifference < -frame_counters_->CaptureMinusRenderCounters()) { |
| + SleepMs(1); |
| + } |
| + |
| + // Apply any specified render side APM non-processing runtime calls. |
| + ApplyRuntimeSettingScheme(); |
| + |
| + // Apply the render side processing call. |
| + CallApmRenderSide(); |
| + |
| + // Increase the number of render-side calls. |
| + frame_counters_->IncreaseRenderCounter(); |
| + |
| + return true; |
| +} |
| + |
| +void AudioProcessingImplLockTest::CheckTestCompleteness() { |
| + if (HasFatalFailure() || TestDone()) { |
| + test_complete_->Set(); |
| + } |
| +} |
| + |
| +} // anonymous namespace |
| + |
| +TEST_P(AudioProcessingImplLockTest, LockTest) { |
| + // Run test and verify that it did not time out. |
| + ASSERT_EQ(kEventSignaled, RunTest()); |
| +} |
| + |
| +// Instantiate tests from the extreme test configuration set. |
| +INSTANTIATE_TEST_CASE_P( |
| + DISABLED_AudioProcessingImplLockExtensive, |
| + AudioProcessingImplLockTest, |
| + ::testing::ValuesIn(TestConfig::GenerateExtensiveTestConfigs())); |
| + |
| +INSTANTIATE_TEST_CASE_P( |
| + AudioProcessingImplLockBrief, |
| + AudioProcessingImplLockTest, |
| + ::testing::ValuesIn(TestConfig::GenerateBriefTestConfigs())); |
| + |
| +} // namespace webrtc |