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

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