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

Side by Side Diff: webrtc/modules/audio_processing/audio_processing_impl_locking_unittest.cc

Issue 1394803002: Unittest for the locking in APM (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Disabled the brief lock test as it does not yet pass through memory sanitizer (until the new lock s… Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | webrtc/modules/modules.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright (c) 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/gtest/include/gtest/gtest.h"
17 #include "webrtc/base/array_view.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/include/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 class AudioProcessingImplLockTest;
32
33 // Sleeps a random time between 0 and max_sleep milliseconds.
34 void SleepRandomMs(int max_sleep, test::Random* rand_gen) {
35 int sleeptime = rand_gen->Rand(0, max_sleep);
36 SleepMs(sleeptime);
37 }
38
39 // Populates a float audio frame with random data.
40 void PopulateAudioFrame(float** frame,
41 float amplitude,
42 size_t num_channels,
43 size_t samples_per_channel,
44 test::Random* rand_gen) {
45 for (size_t ch = 0; ch < num_channels; ch++) {
46 for (size_t k = 0; k < samples_per_channel; k++) {
47 // Store random 16 bit quantized float number between +-amplitude.
48 frame[ch][k] = amplitude * (2 * rand_gen->Rand<float>() - 1);
49 }
50 }
51 }
52
53 // Populates an audioframe frame of AudioFrame type with random data.
54 void PopulateAudioFrame(AudioFrame* frame,
55 int16_t amplitude,
56 test::Random* rand_gen) {
57 ASSERT_GT(amplitude, 0);
58 ASSERT_LE(amplitude, 32767);
59 for (int ch = 0; ch < frame->num_channels_; ch++) {
60 for (int k = 0; k < static_cast<int>(frame->samples_per_channel_); k++) {
61 // Store random 16 bit number between -(amplitude+1) and
62 // amplitude.
63 frame->data_[k * ch] = rand_gen->Rand(2 * amplitude + 1) - amplitude - 1;
64 }
65 }
66 }
67
68 // Type of the render thread APM API call to use in the test.
69 enum class RenderApiImpl {
70 ProcessReverseStreamImpl1,
71 ProcessReverseStreamImpl2,
72 AnalyzeReverseStreamImpl1,
73 AnalyzeReverseStreamImpl2
74 };
75
76 // Type of the capture thread APM API call to use in the test.
77 enum class CaptureApiImpl {
78 ProcessStreamImpl1,
79 ProcessStreamImpl2,
80 ProcessStreamImpl3
81 };
82
83 // The runtime parameter setting scheme to use in the test.
84 enum class RuntimeParameterSettingScheme {
85 SparseStreamMetadataChangeScheme,
86 ExtremeStreamMetadataChangeScheme,
87 FixedMonoStreamMetadataScheme,
88 FixedStereoStreamMetadataScheme
89 };
90
91 // Variant of echo canceller settings to use in the test.
92 enum class AecType {
93 BasicWebRtcAecSettings,
94 AecTurnedOff,
95 BasicWebRtcAecSettingsWithExtentedFilter,
96 BasicWebRtcAecSettingsWithDelayAgnosticAec,
97 BasicWebRtcAecSettingsWithAecMobile
98 };
99
100 // Variables related to the audio data and formats.
101 struct AudioFrameData {
102 explicit AudioFrameData(int max_frame_size) {
103 // Set up the two-dimensional arrays needed for the APM API calls.
104 input_framechannels.resize(2 * max_frame_size);
105 input_frame.resize(2);
106 input_frame[0] = &input_framechannels[0];
107 input_frame[1] = &input_framechannels[max_frame_size];
108
109 output_frame_channels.resize(2 * max_frame_size);
110 output_frame.resize(2);
111 output_frame[0] = &output_frame_channels[0];
112 output_frame[1] = &output_frame_channels[max_frame_size];
113 }
114
115 AudioFrame frame;
116 std::vector<float*> output_frame;
117 std::vector<float> output_frame_channels;
118 AudioProcessing::ChannelLayout output_channel_layout =
119 AudioProcessing::ChannelLayout::kMono;
120 int input_sample_rate_hz = 16000;
121 int input_number_of_channels = -1;
122 std::vector<float*> input_frame;
123 std::vector<float> input_framechannels;
124 AudioProcessing::ChannelLayout input_channel_layout =
125 AudioProcessing::ChannelLayout::kMono;
126 int output_sample_rate_hz = 16000;
127 int output_number_of_channels = -1;
128 StreamConfig input_stream_config;
129 StreamConfig output_stream_config;
130 int input_samples_per_channel = -1;
131 int output_samples_per_channel = -1;
132 };
133
134 // The configuration for the test.
135 struct TestConfig {
136 // Test case generator for the test configurations to use in the brief tests.
137 static std::vector<TestConfig> GenerateBriefTestConfigs() {
138 std::vector<TestConfig> test_configs;
139 AecType aec_types[] = {AecType::BasicWebRtcAecSettingsWithDelayAgnosticAec,
140 AecType::BasicWebRtcAecSettingsWithAecMobile};
141 for (auto aec_type : aec_types) {
142 TestConfig test_config;
143 test_config.aec_type = aec_type;
144
145 test_config.min_number_of_calls = 300;
146
147 // Perform tests only with the extreme runtime parameter setting scheme.
148 test_config.runtime_parameter_setting_scheme =
149 RuntimeParameterSettingScheme::ExtremeStreamMetadataChangeScheme;
150
151 // Only test 16 kHz for this test suite.
152 test_config.initial_sample_rate_hz = 16000;
153
154 // Create test config for the second processing API function set.
155 test_config.render_api_function =
156 RenderApiImpl::ProcessReverseStreamImpl2;
157 test_config.capture_api_function = CaptureApiImpl::ProcessStreamImpl2;
158
159 // Create test config for the first processing API function set.
160 test_configs.push_back(test_config);
161 test_config.render_api_function =
162 RenderApiImpl::AnalyzeReverseStreamImpl2;
163 test_config.capture_api_function = CaptureApiImpl::ProcessStreamImpl3;
164 test_configs.push_back(test_config);
165 }
166
167 // Return the created test configurations.
168 return test_configs;
169 }
170
171 // Test case generator for the test configurations to use in the extensive
172 // tests.
173 static std::vector<TestConfig> GenerateExtensiveTestConfigs() {
174 // Lambda functions for the test config generation.
175 auto add_processing_apis = [](TestConfig test_config) {
176 struct AllowedApiCallCombinations {
177 RenderApiImpl render_api;
178 CaptureApiImpl capture_api;
179 };
180
181 const AllowedApiCallCombinations api_calls[] = {
182 {RenderApiImpl::ProcessReverseStreamImpl1,
183 CaptureApiImpl::ProcessStreamImpl1},
184 {RenderApiImpl::AnalyzeReverseStreamImpl1,
185 CaptureApiImpl::ProcessStreamImpl1},
186 {RenderApiImpl::ProcessReverseStreamImpl2,
187 CaptureApiImpl::ProcessStreamImpl2},
188 {RenderApiImpl::ProcessReverseStreamImpl2,
189 CaptureApiImpl::ProcessStreamImpl3},
190 {RenderApiImpl::AnalyzeReverseStreamImpl2,
191 CaptureApiImpl::ProcessStreamImpl2},
192 {RenderApiImpl::AnalyzeReverseStreamImpl2,
193 CaptureApiImpl::ProcessStreamImpl3}};
194 std::vector<TestConfig> out;
195 for (auto api_call : api_calls) {
196 test_config.render_api_function = api_call.render_api;
197 test_config.capture_api_function = api_call.capture_api;
198 out.push_back(test_config);
199 }
200 return out;
201 };
202
203 auto add_aec_settings = [](const std::vector<TestConfig>& in) {
204 std::vector<TestConfig> out;
205 AecType aec_types[] = {
206 AecType::BasicWebRtcAecSettings, AecType::AecTurnedOff,
207 AecType::BasicWebRtcAecSettingsWithExtentedFilter,
208 AecType::BasicWebRtcAecSettingsWithDelayAgnosticAec,
209 AecType::BasicWebRtcAecSettingsWithAecMobile};
210 for (auto test_config : in) {
211 for (auto aec_type : aec_types) {
212 test_config.aec_type = aec_type;
213 out.push_back(test_config);
214 }
215 }
216 return out;
217 };
218
219 auto add_settings_scheme = [](const std::vector<TestConfig>& in) {
220 std::vector<TestConfig> out;
221 RuntimeParameterSettingScheme schemes[] = {
222 RuntimeParameterSettingScheme::SparseStreamMetadataChangeScheme,
223 RuntimeParameterSettingScheme::ExtremeStreamMetadataChangeScheme,
224 RuntimeParameterSettingScheme::FixedMonoStreamMetadataScheme,
225 RuntimeParameterSettingScheme::FixedStereoStreamMetadataScheme};
226
227 for (auto test_config : in) {
228 for (auto scheme : schemes) {
229 test_config.runtime_parameter_setting_scheme = scheme;
230 out.push_back(test_config);
231 }
232 }
233 return out;
234 };
235
236 auto add_sample_rates = [](const std::vector<TestConfig>& in) {
237 const int sample_rates[] = {8000, 16000, 32000, 48000};
238
239 std::vector<TestConfig> out;
240 for (auto test_config : in) {
241 auto available_rates =
242 (test_config.aec_type ==
243 AecType::BasicWebRtcAecSettingsWithAecMobile
244 ? rtc::ArrayView<const int>(sample_rates, 2)
245 : rtc::ArrayView<const int>(sample_rates));
246
247 for (auto rate : available_rates) {
248 test_config.initial_sample_rate_hz = rate;
249 out.push_back(test_config);
250 }
251 }
252 return out;
253 };
254
255 // Generate test configurations of the relevant combinations of the
256 // parameters to
257 // test.
258 TestConfig test_config;
259 test_config.min_number_of_calls = 10000;
260 return add_sample_rates(add_settings_scheme(
261 add_aec_settings(add_processing_apis(test_config))));
262 }
263
264 RenderApiImpl render_api_function = RenderApiImpl::ProcessReverseStreamImpl2;
265 CaptureApiImpl capture_api_function = CaptureApiImpl::ProcessStreamImpl2;
266 RuntimeParameterSettingScheme runtime_parameter_setting_scheme =
267 RuntimeParameterSettingScheme::ExtremeStreamMetadataChangeScheme;
268 int initial_sample_rate_hz = 16000;
269 AecType aec_type = AecType::BasicWebRtcAecSettingsWithDelayAgnosticAec;
270 int min_number_of_calls = 300;
271 };
272
273 // Handler for the frame counters.
274 class FrameCounters {
275 public:
276 void IncreaseRenderCounter() {
277 rtc::CritScope cs(&crit_);
278 render_count++;
279 }
280
281 void IncreaseCaptureCounter() {
282 rtc::CritScope cs(&crit_);
283 capture_count++;
284 }
285
286 int GetCaptureCounter() {
287 rtc::CritScope cs(&crit_);
288 return capture_count;
289 }
290
291 int GetRenderCounter() {
292 rtc::CritScope cs(&crit_);
293 return render_count;
294 }
295
296 int CaptureMinusRenderCounters() {
297 rtc::CritScope cs(&crit_);
298 return capture_count - render_count;
299 }
300
301 bool BothCountersExceedeThreshold(int threshold) {
302 rtc::CritScope cs(&crit_);
303 return (render_count > threshold && capture_count > threshold);
304 }
305
306 private:
307 rtc::CriticalSection crit_;
308 int render_count GUARDED_BY(crit_) = 0;
309 int capture_count GUARDED_BY(crit_) = 0;
310 };
311
312 // Checker for whether the capture side has been called.
313 class CaptureSideCalledChecker {
314 public:
315 bool CaptureSideCalled() {
316 rtc::CritScope cs(&crit_);
317 return capture_side_called_;
318 }
319
320 void FlagCaptureSideCalled() {
321 rtc::CritScope cs(&crit_);
322 capture_side_called_ = true;
323 }
324
325 private:
326 rtc::CriticalSection crit_;
327 bool capture_side_called_ GUARDED_BY(crit_) = false;
328 };
329
330 // Class for handling the capture side processing.
331 class CaptureProcessor {
332 public:
333 CaptureProcessor(int max_frame_size,
334 test::Random* rand_gen,
335 FrameCounters* shared_counters_state,
336 CaptureSideCalledChecker* capture_call_checker,
337 AudioProcessingImplLockTest* test_framework,
338 TestConfig* test_config,
339 AudioProcessing* apm);
340 bool Process();
341
342 private:
343 static const int kMaxCallDifference = 10;
344 static const float kCaptureInputFloatLevel;
345 static const int kCaptureInputFixLevel = 1024;
346
347 void PrepareFrame();
348 void CallApmCaptureSide();
349 void ApplyRuntimeSettingScheme();
350
351 test::Random* rand_gen_ = nullptr;
352 FrameCounters* frame_counters_ = nullptr;
353 CaptureSideCalledChecker* capture_call_checker_ = nullptr;
354 AudioProcessingImplLockTest* test_ = nullptr;
355 TestConfig* test_config_ = nullptr;
356 AudioProcessing* apm_ = nullptr;
357 AudioFrameData frame_data_;
358 };
359
360 // Class for handling the stats processing.
361 class StatsProcessor {
362 public:
363 StatsProcessor(test::Random* rand_gen,
364 TestConfig* test_config,
365 AudioProcessing* apm);
366 bool Process();
367
368 private:
369 test::Random* rand_gen_ = nullptr;
370 TestConfig* test_config_ = nullptr;
371 AudioProcessing* apm_ = nullptr;
372 };
373
374 // Class for handling the render side processing.
375 class RenderProcessor {
376 public:
377 RenderProcessor(int max_frame_size,
378 test::Random* rand_gen,
379 FrameCounters* shared_counters_state,
380 CaptureSideCalledChecker* capture_call_checker,
381 AudioProcessingImplLockTest* test_framework,
382 TestConfig* test_config,
383 AudioProcessing* apm);
384 bool Process();
385
386 private:
387 static const int kMaxCallDifference = 10;
388 static const int kRenderInputFixLevel = 16384;
389 static const float kRenderInputFloatLevel;
390
391 void PrepareFrame();
392 void CallApmRenderSide();
393 void ApplyRuntimeSettingScheme();
394
395 test::Random* rand_gen_ = nullptr;
396 FrameCounters* frame_counters_ = nullptr;
397 CaptureSideCalledChecker* capture_call_checker_ = nullptr;
398 AudioProcessingImplLockTest* test_ = nullptr;
399 TestConfig* test_config_ = nullptr;
400 AudioProcessing* apm_ = nullptr;
401 bool first_render_side_call_ = true;
402 AudioFrameData frame_data_;
403 };
404
405 class AudioProcessingImplLockTest
406 : public ::testing::TestWithParam<TestConfig> {
407 public:
408 AudioProcessingImplLockTest();
409 EventTypeWrapper RunTest();
410 void CheckTestCompleteness();
411
412 private:
413 static const int kTestTimeOutLimit = 10 * 60 * 1000;
414 static const int kMaxFrameSize = 480;
415
416 // ::testing::TestWithParam<> implementation
417 void SetUp() override;
418 void TearDown() override;
419
420 // Thread callback for the render thread
421 static bool RenderProcessorThreadFunc(void* context) {
422 return reinterpret_cast<AudioProcessingImplLockTest*>(context)
423 ->render_thread_state_.Process();
424 }
425
426 // Thread callback for the capture thread
427 static bool CaptureProcessorThreadFunc(void* context) {
428 return reinterpret_cast<AudioProcessingImplLockTest*>(context)
429 ->capture_thread_state_.Process();
430 }
431
432 // Thread callback for the stats thread
433 static bool StatsProcessorThreadFunc(void* context) {
434 return reinterpret_cast<AudioProcessingImplLockTest*>(context)
435 ->stats_thread_state_.Process();
436 }
437
438 // Tests whether all the required render and capture side calls have been
439 // done.
440 bool TestDone() {
441 return frame_counters_.BothCountersExceedeThreshold(
442 test_config_.min_number_of_calls);
443 }
444
445 // Start the threads used in the test.
446 void StartThreads() {
447 ASSERT_TRUE(render_thread_->Start());
448 render_thread_->SetPriority(kRealtimePriority);
449 ASSERT_TRUE(capture_thread_->Start());
450 capture_thread_->SetPriority(kRealtimePriority);
451 ASSERT_TRUE(stats_thread_->Start());
452 stats_thread_->SetPriority(kNormalPriority);
453 }
454
455 // Event handler for the test.
456 const rtc::scoped_ptr<EventWrapper> test_complete_;
457
458 // Thread related variables.
459 rtc::scoped_ptr<ThreadWrapper> render_thread_;
460 rtc::scoped_ptr<ThreadWrapper> capture_thread_;
461 rtc::scoped_ptr<ThreadWrapper> stats_thread_;
462 mutable test::Random rand_gen_;
463
464 rtc::scoped_ptr<AudioProcessing> apm_;
465 TestConfig test_config_;
466 FrameCounters frame_counters_;
467 CaptureSideCalledChecker capture_call_checker_;
468 RenderProcessor render_thread_state_;
469 CaptureProcessor capture_thread_state_;
470 StatsProcessor stats_thread_state_;
471 };
472
473 AudioProcessingImplLockTest::AudioProcessingImplLockTest()
474 : test_complete_(EventWrapper::Create()),
475 render_thread_(ThreadWrapper::CreateThread(RenderProcessorThreadFunc,
476 this,
477 "render")),
478 capture_thread_(ThreadWrapper::CreateThread(CaptureProcessorThreadFunc,
479 this,
480 "capture")),
481 stats_thread_(
482 ThreadWrapper::CreateThread(StatsProcessorThreadFunc, this, "stats")),
483 rand_gen_(42U),
484 apm_(AudioProcessingImpl::Create()),
485 render_thread_state_(kMaxFrameSize,
486 &rand_gen_,
487 &frame_counters_,
488 &capture_call_checker_,
489 this,
490 &test_config_,
491 apm_.get()),
492 capture_thread_state_(kMaxFrameSize,
493 &rand_gen_,
494 &frame_counters_,
495 &capture_call_checker_,
496 this,
497 &test_config_,
498 apm_.get()),
499 stats_thread_state_(&rand_gen_, &test_config_, apm_.get()) {}
500
501 // Run the test with a timeout.
502 EventTypeWrapper AudioProcessingImplLockTest::RunTest() {
503 StartThreads();
504 return test_complete_->Wait(kTestTimeOutLimit);
505 }
506
507 void AudioProcessingImplLockTest::CheckTestCompleteness() {
508 if (HasFatalFailure() || TestDone()) {
509 test_complete_->Set();
510 }
511 }
512
513 // Setup of test and APM.
514 void AudioProcessingImplLockTest::SetUp() {
515 test_config_ = static_cast<TestConfig>(GetParam());
516
517 ASSERT_EQ(apm_->kNoError, apm_->level_estimator()->Enable(true));
518 ASSERT_EQ(apm_->kNoError, apm_->gain_control()->Enable(true));
519
520 ASSERT_EQ(apm_->kNoError,
521 apm_->gain_control()->set_mode(GainControl::kAdaptiveAnalog));
522 ASSERT_EQ(apm_->kNoError, apm_->gain_control()->Enable(true));
523
524 ASSERT_EQ(apm_->kNoError, apm_->noise_suppression()->Enable(true));
525 ASSERT_EQ(apm_->kNoError, apm_->voice_detection()->Enable(true));
526
527 Config config;
528 if (test_config_.aec_type == AecType::AecTurnedOff) {
529 ASSERT_EQ(apm_->kNoError, apm_->echo_control_mobile()->Enable(false));
530 ASSERT_EQ(apm_->kNoError, apm_->echo_cancellation()->Enable(false));
531 } else if (test_config_.aec_type ==
532 AecType::BasicWebRtcAecSettingsWithAecMobile) {
533 ASSERT_EQ(apm_->kNoError, apm_->echo_control_mobile()->Enable(true));
534 ASSERT_EQ(apm_->kNoError, apm_->echo_cancellation()->Enable(false));
535 } else {
536 ASSERT_EQ(apm_->kNoError, apm_->echo_control_mobile()->Enable(false));
537 ASSERT_EQ(apm_->kNoError, apm_->echo_cancellation()->Enable(true));
538 ASSERT_EQ(apm_->kNoError, apm_->echo_cancellation()->enable_metrics(true));
539 ASSERT_EQ(apm_->kNoError,
540 apm_->echo_cancellation()->enable_delay_logging(true));
541
542 config.Set<ExtendedFilter>(
543 new ExtendedFilter(test_config_.aec_type ==
544 AecType::BasicWebRtcAecSettingsWithExtentedFilter));
545
546 config.Set<DelayAgnostic>(
547 new DelayAgnostic(test_config_.aec_type ==
548 AecType::BasicWebRtcAecSettingsWithDelayAgnosticAec));
549
550 apm_->SetExtraOptions(config);
551 }
552 }
553
554 void AudioProcessingImplLockTest::TearDown() {
555 render_thread_->Stop();
556 capture_thread_->Stop();
557 stats_thread_->Stop();
558 }
559
560 StatsProcessor::StatsProcessor(test::Random* rand_gen,
561 TestConfig* test_config,
562 AudioProcessing* apm)
563 : rand_gen_(rand_gen), test_config_(test_config), apm_(apm) {}
564
565 // Implements the callback functionality for the statistics
566 // collection thread.
567 bool StatsProcessor::Process() {
568 SleepRandomMs(100, rand_gen_);
569
570 EXPECT_EQ(apm_->echo_cancellation()->is_enabled(),
571 ((test_config_->aec_type != AecType::AecTurnedOff) &&
572 (test_config_->aec_type !=
573 AecType::BasicWebRtcAecSettingsWithAecMobile)));
574 apm_->echo_cancellation()->stream_drift_samples();
575 EXPECT_EQ(apm_->echo_control_mobile()->is_enabled(),
576 (test_config_->aec_type != AecType::AecTurnedOff) &&
577 (test_config_->aec_type ==
578 AecType::BasicWebRtcAecSettingsWithAecMobile));
579 EXPECT_TRUE(apm_->gain_control()->is_enabled());
580 apm_->gain_control()->stream_analog_level();
581 EXPECT_TRUE(apm_->noise_suppression()->is_enabled());
582
583 // The below return values are not testable.
584 apm_->noise_suppression()->speech_probability();
585 apm_->voice_detection()->is_enabled();
586
587 return true;
588 }
589
590 const float CaptureProcessor::kCaptureInputFloatLevel = 0.03125f;
591
592 CaptureProcessor::CaptureProcessor(
593 int max_frame_size,
594 test::Random* rand_gen,
595 FrameCounters* shared_counters_state,
596 CaptureSideCalledChecker* capture_call_checker,
597 AudioProcessingImplLockTest* test_framework,
598 TestConfig* test_config,
599 AudioProcessing* apm)
600 : rand_gen_(rand_gen),
601 frame_counters_(shared_counters_state),
602 capture_call_checker_(capture_call_checker),
603 test_(test_framework),
604 test_config_(test_config),
605 apm_(apm),
606 frame_data_(max_frame_size) {}
607
608 // Implements the callback functionality for the capture thread.
609 bool CaptureProcessor::Process() {
610 // Sleep a random time to simulate thread jitter.
611 SleepRandomMs(3, rand_gen_);
612
613 // End the test if complete.
614 test_->CheckTestCompleteness();
615
616 // Ensure that there are not more capture side calls than render side
617 // calls.
618 if (capture_call_checker_->CaptureSideCalled()) {
619 while (kMaxCallDifference < frame_counters_->CaptureMinusRenderCounters()) {
620 SleepMs(1);
621 }
622 }
623
624 // Apply any specified capture side APM non-processing runtime calls.
625 ApplyRuntimeSettingScheme();
626
627 // Apply the capture side processing call.
628 CallApmCaptureSide();
629
630 // Increase the number of capture-side calls.
631 frame_counters_->IncreaseCaptureCounter();
632
633 // Flag that the capture side has been called at least once
634 // (needed to ensure that a capture call has been done
635 // before the first render call is performed (implicitly
636 // required by the APM API).
637 capture_call_checker_->FlagCaptureSideCalled();
638
639 return true;
640 }
641
642 // Prepares a frame with relevant audio data and metadata.
643 void CaptureProcessor::PrepareFrame() {
644 // Restrict to a common fixed sample rate if the AudioFrame
645 // interface is used.
646 if (test_config_->capture_api_function ==
647 CaptureApiImpl::ProcessStreamImpl1) {
648 frame_data_.input_sample_rate_hz = test_config_->initial_sample_rate_hz;
649 frame_data_.output_sample_rate_hz = test_config_->initial_sample_rate_hz;
650 }
651
652 // Prepare the audioframe data and metadata.
653 frame_data_.input_samples_per_channel =
654 frame_data_.input_sample_rate_hz * AudioProcessing::kChunkSizeMs / 1000;
655 frame_data_.frame.sample_rate_hz_ = frame_data_.input_sample_rate_hz;
656 frame_data_.frame.num_channels_ = frame_data_.input_number_of_channels;
657 frame_data_.frame.samples_per_channel_ =
658 frame_data_.input_samples_per_channel;
659 PopulateAudioFrame(&frame_data_.frame, kCaptureInputFixLevel, rand_gen_);
660
661 // Prepare the float audio input data and metadata.
662 frame_data_.input_stream_config.set_sample_rate_hz(
663 frame_data_.input_sample_rate_hz);
664 frame_data_.input_stream_config.set_num_channels(
665 frame_data_.input_number_of_channels);
666 frame_data_.input_stream_config.set_has_keyboard(false);
667 PopulateAudioFrame(&frame_data_.input_frame[0], kCaptureInputFloatLevel,
668 frame_data_.input_number_of_channels,
669 frame_data_.input_samples_per_channel, rand_gen_);
670 frame_data_.input_channel_layout =
671 (frame_data_.input_number_of_channels == 1
672 ? AudioProcessing::ChannelLayout::kMono
673 : AudioProcessing::ChannelLayout::kStereo);
674
675 // Prepare the float audio output data and metadata.
676 frame_data_.output_samples_per_channel =
677 frame_data_.output_sample_rate_hz * AudioProcessing::kChunkSizeMs / 1000;
678 frame_data_.output_stream_config.set_sample_rate_hz(
679 frame_data_.output_sample_rate_hz);
680 frame_data_.output_stream_config.set_num_channels(
681 frame_data_.output_number_of_channels);
682 frame_data_.output_stream_config.set_has_keyboard(false);
683 frame_data_.output_channel_layout =
684 (frame_data_.output_number_of_channels == 1
685 ? AudioProcessing::ChannelLayout::kMono
686 : AudioProcessing::ChannelLayout::kStereo);
687 }
688
689 // Applies the capture side processing API call.
690 void CaptureProcessor::CallApmCaptureSide() {
691 // Prepare a proper capture side processing API call input.
692 PrepareFrame();
693
694 // Set the stream delay
695 apm_->set_stream_delay_ms(30);
696
697 // Call the specified capture side API processing method.
698 int result = AudioProcessing::kNoError;
699 switch (test_config_->capture_api_function) {
700 case CaptureApiImpl::ProcessStreamImpl1:
701 result = apm_->ProcessStream(&frame_data_.frame);
702 break;
703 case CaptureApiImpl::ProcessStreamImpl2:
704 result = apm_->ProcessStream(
705 &frame_data_.input_frame[0], frame_data_.input_samples_per_channel,
706 frame_data_.input_sample_rate_hz, frame_data_.input_channel_layout,
707 frame_data_.output_sample_rate_hz, frame_data_.output_channel_layout,
708 &frame_data_.output_frame[0]);
709 break;
710 case CaptureApiImpl::ProcessStreamImpl3:
711 result = apm_->ProcessStream(
712 &frame_data_.input_frame[0], frame_data_.input_stream_config,
713 frame_data_.output_stream_config, &frame_data_.output_frame[0]);
714 break;
715 default:
716 FAIL();
717 }
718
719 // Check the return code for error.
720 ASSERT_EQ(AudioProcessing::kNoError, result);
721 }
722
723 // Applies any runtime capture APM API calls and audio stream characteristics
724 // specified by the scheme for the test.
725 void CaptureProcessor::ApplyRuntimeSettingScheme() {
726 const int capture_count_local = frame_counters_->GetCaptureCounter();
727
728 // Update the number of channels and sample rates for the input and output.
729 // Note that the counts frequencies for when to set parameters
730 // are set using prime numbers in order to ensure that the
731 // permutation scheme in the parameter setting changes.
732 switch (test_config_->runtime_parameter_setting_scheme) {
733 case RuntimeParameterSettingScheme::SparseStreamMetadataChangeScheme:
734 if (capture_count_local == 0)
735 frame_data_.input_sample_rate_hz = 16000;
736 else if (capture_count_local % 11 == 0)
737 frame_data_.input_sample_rate_hz = 32000;
738 else if (capture_count_local % 73 == 0)
739 frame_data_.input_sample_rate_hz = 48000;
740 else if (capture_count_local % 89 == 0)
741 frame_data_.input_sample_rate_hz = 16000;
742 else if (capture_count_local % 97 == 0)
743 frame_data_.input_sample_rate_hz = 8000;
744
745 if (capture_count_local == 0)
746 frame_data_.input_number_of_channels = 1;
747 else if (capture_count_local % 4 == 0)
748 frame_data_.input_number_of_channels =
749 (frame_data_.input_number_of_channels == 1 ? 2 : 1);
750
751 if (capture_count_local == 0)
752 frame_data_.output_sample_rate_hz = 16000;
753 else if (capture_count_local % 5 == 0)
754 frame_data_.output_sample_rate_hz = 32000;
755 else if (capture_count_local % 47 == 0)
756 frame_data_.output_sample_rate_hz = 48000;
757 else if (capture_count_local % 53 == 0)
758 frame_data_.output_sample_rate_hz = 16000;
759 else if (capture_count_local % 71 == 0)
760 frame_data_.output_sample_rate_hz = 8000;
761
762 if (capture_count_local == 0)
763 frame_data_.output_number_of_channels = 1;
764 else if (capture_count_local % 8 == 0)
765 frame_data_.output_number_of_channels =
766 (frame_data_.output_number_of_channels == 1 ? 2 : 1);
767 break;
768 case RuntimeParameterSettingScheme::ExtremeStreamMetadataChangeScheme:
769 if (capture_count_local % 2 == 0) {
770 frame_data_.input_number_of_channels = 1;
771 frame_data_.input_sample_rate_hz = 16000;
772 frame_data_.output_number_of_channels = 1;
773 frame_data_.output_sample_rate_hz = 16000;
774 } else {
775 frame_data_.input_number_of_channels =
776 (frame_data_.input_number_of_channels == 1 ? 2 : 1);
777 if (frame_data_.input_sample_rate_hz == 8000)
778 frame_data_.input_sample_rate_hz = 16000;
779 else if (frame_data_.input_sample_rate_hz == 16000)
780 frame_data_.input_sample_rate_hz = 32000;
781 else if (frame_data_.input_sample_rate_hz == 32000)
782 frame_data_.input_sample_rate_hz = 48000;
783 else if (frame_data_.input_sample_rate_hz == 48000)
784 frame_data_.input_sample_rate_hz = 8000;
785
786 frame_data_.output_number_of_channels =
787 (frame_data_.output_number_of_channels == 1 ? 2 : 1);
788 if (frame_data_.output_sample_rate_hz == 8000)
789 frame_data_.output_sample_rate_hz = 16000;
790 else if (frame_data_.output_sample_rate_hz == 16000)
791 frame_data_.output_sample_rate_hz = 32000;
792 else if (frame_data_.output_sample_rate_hz == 32000)
793 frame_data_.output_sample_rate_hz = 48000;
794 else if (frame_data_.output_sample_rate_hz == 48000)
795 frame_data_.output_sample_rate_hz = 8000;
796 }
797 break;
798 case RuntimeParameterSettingScheme::FixedMonoStreamMetadataScheme:
799 if (capture_count_local == 0) {
800 frame_data_.input_sample_rate_hz = 16000;
801 frame_data_.input_number_of_channels = 1;
802 frame_data_.output_sample_rate_hz = 16000;
803 frame_data_.output_number_of_channels = 1;
804 }
805 break;
806 case RuntimeParameterSettingScheme::FixedStereoStreamMetadataScheme:
807 if (capture_count_local == 0) {
808 frame_data_.input_sample_rate_hz = 16000;
809 frame_data_.input_number_of_channels = 2;
810 frame_data_.output_sample_rate_hz = 16000;
811 frame_data_.output_number_of_channels = 2;
812 }
813 break;
814 default:
815 FAIL();
816 }
817
818 // Call any specified runtime APM setter and
819 // getter calls.
820 switch (test_config_->runtime_parameter_setting_scheme) {
821 case RuntimeParameterSettingScheme::SparseStreamMetadataChangeScheme:
822 case RuntimeParameterSettingScheme::FixedMonoStreamMetadataScheme:
823 break;
824 case RuntimeParameterSettingScheme::ExtremeStreamMetadataChangeScheme:
825 case RuntimeParameterSettingScheme::FixedStereoStreamMetadataScheme:
826 if (capture_count_local % 2 == 0) {
827 ASSERT_EQ(AudioProcessing::Error::kNoError,
828 apm_->set_stream_delay_ms(30));
829 apm_->set_stream_key_pressed(true);
830 apm_->set_output_will_be_muted(true);
831 apm_->set_delay_offset_ms(15);
832 EXPECT_EQ(apm_->delay_offset_ms(), 15);
833 EXPECT_GE(apm_->num_reverse_channels(), 0);
834 EXPECT_LE(apm_->num_reverse_channels(), 2);
835 } else {
836 ASSERT_EQ(AudioProcessing::Error::kNoError,
837 apm_->set_stream_delay_ms(50));
838 apm_->set_stream_key_pressed(false);
839 apm_->set_output_will_be_muted(false);
840 apm_->set_delay_offset_ms(20);
841 EXPECT_EQ(apm_->delay_offset_ms(), 20);
842 apm_->delay_offset_ms();
843 apm_->num_reverse_channels();
844 EXPECT_GE(apm_->num_reverse_channels(), 0);
845 EXPECT_LE(apm_->num_reverse_channels(), 2);
846 }
847 break;
848 default:
849 FAIL();
850 }
851
852 // Restric the number of output channels not to exceed
853 // the number of input channels.
854 frame_data_.output_number_of_channels =
855 std::min(frame_data_.output_number_of_channels,
856 frame_data_.input_number_of_channels);
857 }
858
859 const float RenderProcessor::kRenderInputFloatLevel = 0.5f;
860
861 RenderProcessor::RenderProcessor(int max_frame_size,
862 test::Random* rand_gen,
863 FrameCounters* shared_counters_state,
864 CaptureSideCalledChecker* capture_call_checker,
865 AudioProcessingImplLockTest* test_framework,
866 TestConfig* test_config,
867 AudioProcessing* apm)
868 : rand_gen_(rand_gen),
869 frame_counters_(shared_counters_state),
870 capture_call_checker_(capture_call_checker),
871 test_(test_framework),
872 test_config_(test_config),
873 apm_(apm),
874 frame_data_(max_frame_size) {}
875
876 // Implements the callback functionality for the render thread.
877 bool RenderProcessor::Process() {
878 // Conditional wait to ensure that a capture call has been done
879 // before the first render call is performed (implicitly
880 // required by the APM API).
881 if (first_render_side_call_) {
882 while (!capture_call_checker_->CaptureSideCalled()) {
883 SleepRandomMs(3, rand_gen_);
884 }
885
886 first_render_side_call_ = false;
887 }
888
889 // Sleep a random time to simulate thread jitter.
890 SleepRandomMs(3, rand_gen_);
891
892 // End the test early if a fatal failure (ASSERT_*) has occurred.
893 test_->CheckTestCompleteness();
894
895 // Ensure that the number of render and capture calls do not
896 // differ too much.
897 while (kMaxCallDifference < -frame_counters_->CaptureMinusRenderCounters()) {
898 SleepMs(1);
899 }
900
901 // Apply any specified render side APM non-processing runtime calls.
902 ApplyRuntimeSettingScheme();
903
904 // Apply the render side processing call.
905 CallApmRenderSide();
906
907 // Increase the number of render-side calls.
908 frame_counters_->IncreaseRenderCounter();
909
910 return true;
911 }
912
913 // Prepares the render side frame and the accompanying metadata
914 // with the appropriate information.
915 void RenderProcessor::PrepareFrame() {
916 // Restrict to a common fixed sample rate if the AudioFrame interface is
917 // used.
918 if ((test_config_->render_api_function ==
919 RenderApiImpl::AnalyzeReverseStreamImpl1) ||
920 (test_config_->render_api_function ==
921 RenderApiImpl::ProcessReverseStreamImpl1) ||
922 (test_config_->aec_type !=
923 AecType::BasicWebRtcAecSettingsWithAecMobile)) {
924 frame_data_.input_sample_rate_hz = test_config_->initial_sample_rate_hz;
925 frame_data_.output_sample_rate_hz = test_config_->initial_sample_rate_hz;
926 }
927
928 // Prepare the audioframe data and metadata
929 frame_data_.input_samples_per_channel =
930 frame_data_.input_sample_rate_hz * AudioProcessing::kChunkSizeMs / 1000;
931 frame_data_.frame.sample_rate_hz_ = frame_data_.input_sample_rate_hz;
932 frame_data_.frame.num_channels_ = frame_data_.input_number_of_channels;
933 frame_data_.frame.samples_per_channel_ =
934 frame_data_.input_samples_per_channel;
935 PopulateAudioFrame(&frame_data_.frame, kRenderInputFixLevel, rand_gen_);
936
937 // Prepare the float audio input data and metadata.
938 frame_data_.input_stream_config.set_sample_rate_hz(
939 frame_data_.input_sample_rate_hz);
940 frame_data_.input_stream_config.set_num_channels(
941 frame_data_.input_number_of_channels);
942 frame_data_.input_stream_config.set_has_keyboard(false);
943 PopulateAudioFrame(&frame_data_.input_frame[0], kRenderInputFloatLevel,
944 frame_data_.input_number_of_channels,
945 frame_data_.input_samples_per_channel, rand_gen_);
946 frame_data_.input_channel_layout =
947 (frame_data_.input_number_of_channels == 1
948 ? AudioProcessing::ChannelLayout::kMono
949 : AudioProcessing::ChannelLayout::kStereo);
950
951 // Prepare the float audio output data and metadata.
952 frame_data_.output_samples_per_channel =
953 frame_data_.output_sample_rate_hz * AudioProcessing::kChunkSizeMs / 1000;
954 frame_data_.output_stream_config.set_sample_rate_hz(
955 frame_data_.output_sample_rate_hz);
956 frame_data_.output_stream_config.set_num_channels(
957 frame_data_.output_number_of_channels);
958 frame_data_.output_stream_config.set_has_keyboard(false);
959 frame_data_.output_channel_layout =
960 (frame_data_.output_number_of_channels == 1
961 ? AudioProcessing::ChannelLayout::kMono
962 : AudioProcessing::ChannelLayout::kStereo);
963 }
964
965 // Makes the render side processing API call.
966 void RenderProcessor::CallApmRenderSide() {
967 // Prepare a proper render side processing API call input.
968 PrepareFrame();
969
970 // Call the specified render side API processing method.
971 int result = AudioProcessing::kNoError;
972 switch (test_config_->render_api_function) {
973 case RenderApiImpl::ProcessReverseStreamImpl1:
974 result = apm_->ProcessReverseStream(&frame_data_.frame);
975 break;
976 case RenderApiImpl::ProcessReverseStreamImpl2:
977 result = apm_->ProcessReverseStream(
978 &frame_data_.input_frame[0], frame_data_.input_stream_config,
979 frame_data_.output_stream_config, &frame_data_.output_frame[0]);
980 break;
981 case RenderApiImpl::AnalyzeReverseStreamImpl1:
982 result = apm_->AnalyzeReverseStream(&frame_data_.frame);
983 break;
984 case RenderApiImpl::AnalyzeReverseStreamImpl2:
985 result = apm_->AnalyzeReverseStream(
986 &frame_data_.input_frame[0], frame_data_.input_samples_per_channel,
987 frame_data_.input_sample_rate_hz, frame_data_.input_channel_layout);
988 break;
989 default:
990 FAIL();
991 }
992
993 // Check the return code for error.
994 ASSERT_EQ(AudioProcessing::kNoError, result);
995 }
996
997 // Applies any render capture side APM API calls and audio stream
998 // characteristics
999 // specified by the scheme for the test.
1000 void RenderProcessor::ApplyRuntimeSettingScheme() {
1001 const int render_count_local = frame_counters_->GetRenderCounter();
1002
1003 // Update the number of channels and sample rates for the input and output.
1004 // Note that the counts frequencies for when to set parameters
1005 // are set using prime numbers in order to ensure that the
1006 // permutation scheme in the parameter setting changes.
1007 switch (test_config_->runtime_parameter_setting_scheme) {
1008 case RuntimeParameterSettingScheme::SparseStreamMetadataChangeScheme:
1009 if (render_count_local == 0)
1010 frame_data_.input_sample_rate_hz = 16000;
1011 else if (render_count_local % 47 == 0)
1012 frame_data_.input_sample_rate_hz = 32000;
1013 else if (render_count_local % 71 == 0)
1014 frame_data_.input_sample_rate_hz = 48000;
1015 else if (render_count_local % 79 == 0)
1016 frame_data_.input_sample_rate_hz = 16000;
1017 else if (render_count_local % 83 == 0)
1018 frame_data_.input_sample_rate_hz = 8000;
1019
1020 if (render_count_local == 0)
1021 frame_data_.input_number_of_channels = 1;
1022 else if (render_count_local % 4 == 0)
1023 frame_data_.input_number_of_channels =
1024 (frame_data_.input_number_of_channels == 1 ? 2 : 1);
1025
1026 if (render_count_local == 0)
1027 frame_data_.output_sample_rate_hz = 16000;
1028 else if (render_count_local % 17 == 0)
1029 frame_data_.output_sample_rate_hz = 32000;
1030 else if (render_count_local % 19 == 0)
1031 frame_data_.output_sample_rate_hz = 48000;
1032 else if (render_count_local % 29 == 0)
1033 frame_data_.output_sample_rate_hz = 16000;
1034 else if (render_count_local % 61 == 0)
1035 frame_data_.output_sample_rate_hz = 8000;
1036
1037 if (render_count_local == 0)
1038 frame_data_.output_number_of_channels = 1;
1039 else if (render_count_local % 8 == 0)
1040 frame_data_.output_number_of_channels =
1041 (frame_data_.output_number_of_channels == 1 ? 2 : 1);
1042 break;
1043 case RuntimeParameterSettingScheme::ExtremeStreamMetadataChangeScheme:
1044 if (render_count_local == 0) {
1045 frame_data_.input_number_of_channels = 1;
1046 frame_data_.input_sample_rate_hz = 16000;
1047 frame_data_.output_number_of_channels = 1;
1048 frame_data_.output_sample_rate_hz = 16000;
1049 } else {
1050 frame_data_.input_number_of_channels =
1051 (frame_data_.input_number_of_channels == 1 ? 2 : 1);
1052 if (frame_data_.input_sample_rate_hz == 8000)
1053 frame_data_.input_sample_rate_hz = 16000;
1054 else if (frame_data_.input_sample_rate_hz == 16000)
1055 frame_data_.input_sample_rate_hz = 32000;
1056 else if (frame_data_.input_sample_rate_hz == 32000)
1057 frame_data_.input_sample_rate_hz = 48000;
1058 else if (frame_data_.input_sample_rate_hz == 48000)
1059 frame_data_.input_sample_rate_hz = 8000;
1060
1061 frame_data_.output_number_of_channels =
1062 (frame_data_.output_number_of_channels == 1 ? 2 : 1);
1063 if (frame_data_.output_sample_rate_hz == 8000)
1064 frame_data_.output_sample_rate_hz = 16000;
1065 else if (frame_data_.output_sample_rate_hz == 16000)
1066 frame_data_.output_sample_rate_hz = 32000;
1067 else if (frame_data_.output_sample_rate_hz == 32000)
1068 frame_data_.output_sample_rate_hz = 48000;
1069 else if (frame_data_.output_sample_rate_hz == 48000)
1070 frame_data_.output_sample_rate_hz = 8000;
1071 }
1072 break;
1073 case RuntimeParameterSettingScheme::FixedMonoStreamMetadataScheme:
1074 if (render_count_local == 0) {
1075 frame_data_.input_sample_rate_hz = 16000;
1076 frame_data_.input_number_of_channels = 1;
1077 frame_data_.output_sample_rate_hz = 16000;
1078 frame_data_.output_number_of_channels = 1;
1079 }
1080 break;
1081 case RuntimeParameterSettingScheme::FixedStereoStreamMetadataScheme:
1082 if (render_count_local == 0) {
1083 frame_data_.input_sample_rate_hz = 16000;
1084 frame_data_.input_number_of_channels = 2;
1085 frame_data_.output_sample_rate_hz = 16000;
1086 frame_data_.output_number_of_channels = 2;
1087 }
1088 break;
1089 default:
1090 FAIL();
1091 }
1092
1093 // Restric the number of output channels not to exceed
1094 // the number of input channels.
1095 frame_data_.output_number_of_channels =
1096 std::min(frame_data_.output_number_of_channels,
1097 frame_data_.input_number_of_channels);
1098 }
1099
1100 } // anonymous namespace
1101
1102 TEST_P(AudioProcessingImplLockTest, LockTest) {
1103 // Run test and verify that it did not time out.
1104 ASSERT_EQ(kEventSignaled, RunTest());
1105 }
1106
1107 // Instantiate tests from the extreme test configuration set.
1108 INSTANTIATE_TEST_CASE_P(
1109 DISABLED_AudioProcessingImplLockExtensive,
1110 AudioProcessingImplLockTest,
1111 ::testing::ValuesIn(TestConfig::GenerateExtensiveTestConfigs()));
1112
1113 INSTANTIATE_TEST_CASE_P(
1114 DISABLED_AudioProcessingImplLockBrief,
1115 AudioProcessingImplLockTest,
1116 ::testing::ValuesIn(TestConfig::GenerateBriefTestConfigs()));
1117
1118 } // namespace webrtc
OLDNEW
« no previous file with comments | « no previous file | webrtc/modules/modules.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698