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

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: Created 5 years, 2 months 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) 2014 The WebRTC project authors. All Rights Reserved.
kwiberg-webrtc 2015/10/08 13:25:22 Use the present year without rounding down to the
peah-webrtc 2015/10/13 06:58:39 Done.
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/config.h"
19 #include "webrtc/base/criticalsection.h"
ivoc 2015/10/09 15:47:15 These should be in alphabetical order, I think.
peah-webrtc 2015/10/13 06:58:40 Done.
20 #include "webrtc/modules/audio_processing/test/test_utils.h"
21 #include "webrtc/modules/interface/module_common_types.h"
22 #include "webrtc/system_wrappers/interface/event_wrapper.h"
23 #include "webrtc/system_wrappers/interface/sleep.h"
24 #include "webrtc/system_wrappers/interface/thread_wrapper.h"
25
26 namespace webrtc {
27
28 namespace {
29
30 // Holds the type of the render thread APM API call to use in the test.
31 enum class RenderApiFunction {
32 ProcessReverseStream1,
33 ProcessReverseStream2,
34 AnalyzeReverseStream1,
35 AnalyzeReverseStream2
36 };
37 // Holds the type of the capture thread APM API call to use in the test.
38 enum class CaptureApiFunction {
39 ProcessStream1,
40 ProcessStream2,
41 ProcessStream3
42 };
43 // Holds the runtime parameter setting scheme to use in the test.
44 enum class RuntimeParameterSettingScheme { Scheme1, Scheme2, Scheme3, Scheme4 };
ivoc 2015/10/09 15:47:15 I think these enums are a bit cryptic. Is it possi
peah-webrtc 2015/10/13 06:58:39 Done.
peah-webrtc 2015/10/13 06:58:39 Good point! Should be better now!
45 enum class AecType { Aec, NoAec, AecExtFilter, AecDelayAgnostic, Aecm };
46
47 // Holds the configuration for the test to use.
kwiberg-webrtc 2015/10/08 13:25:21 You can probably drop the "Holds the" in all these
peah-webrtc 2015/10/13 06:58:40 Done.
48 struct TestConfig {
49 RenderApiFunction render_api_function;
50 CaptureApiFunction capture_api_function;
51 RuntimeParameterSettingScheme runtime_parameter_setting_scheme;
52 int initial_sample_rate;
53 AecType aec_type;
54 };
55
56 // Class for implementing the tests of the locks in the audio processing module.
57 class AudioProcessingImpLockTest : public ::testing::TestWithParam<TestConfig> {
58 public:
59 AudioProcessingImpLockTest()
60 : render_thread_(
61 ThreadWrapper::CreateThread(CbRenderThread, this, "render")),
62 capture_thread_(
63 ThreadWrapper::CreateThread(CbCaptureThread, this, "capture")),
64 stats_thread_(
65 ThreadWrapper::CreateThread(CbStatsThread, this, "stats")),
66 render_count_(0),
67 capture_count_(0),
68 first_render_side_call_(true),
69 capture_side_called_(false),
70 test_complete_(EventWrapper::Create()),
71 render_seed(42),
72 capture_seed(37),
73 stats_seed(75),
74 capture_input_sample_rate_hz_(16000),
75 capture_output_sample_rate_hz_(16000),
76 render_input_sample_rate_hz_(16000),
77 render_output_sample_rate_hz_(16000) {
78 // Create the dynamic two-dimensional arrays needed for the APM API calls.
79 capture_input_frame_ = new float*[2];
80 capture_input_frame_[0] = new float[480];
81 capture_input_frame_[1] = new float[480];
82 capture_output_frame_ = new float*[2];
83 capture_output_frame_[0] = new float[480];
84 capture_output_frame_[1] = new float[480];
85 render_input_frame_ = new float*[2];
86 render_input_frame_[0] = new float[480];
87 render_input_frame_[1] = new float[480];
88 render_output_frame_ = new float*[2];
89 render_output_frame_[0] = new float[480];
90 render_output_frame_[1] = new float[480];
91 }
92
93 virtual ~AudioProcessingImpLockTest() {
94 // Delete the dynamic two-dimensional arrays needed for the APM API calls.
95 delete[] capture_input_frame_[0];
96 delete[] capture_input_frame_[1];
97 delete[] capture_input_frame_;
98
99 delete[] capture_output_frame_[0];
100 delete[] capture_output_frame_[1];
101 delete[] capture_output_frame_;
102
103 delete[] render_input_frame_[0];
104 delete[] render_input_frame_[1];
105 delete[] render_input_frame_;
106
107 delete[] render_output_frame_[0];
108 delete[] render_output_frame_[1];
109 delete[] render_output_frame_;
kwiberg-webrtc 2015/10/08 13:25:22 Use scoped_ptrs to hold these. Or even better: sin
ivoc 2015/10/09 15:47:15 vectors are another option.
peah-webrtc 2015/10/13 06:58:39 Done.
peah-webrtc 2015/10/13 06:58:39 Good point! Now I changed to a scheme using vector
peah-webrtc 2015/10/13 06:58:40 Done.
110 }
111
112 // Run the test with a timeout.
113 EventTypeWrapper RunTest() {
114 StartThreads();
115 return test_complete_->Wait(kTestTimeOutLimit);
116 }
117
118 virtual void SetUp() {
119 apm_.reset(AudioProcessingImpl::Create());
120 test_config_ = static_cast<TestConfig>(GetParam());
121
122 Config config;
123 bool use_config = false;
kwiberg-webrtc 2015/10/08 13:25:22 Move line 123 to 144, to reduce the scope of use_c
peah-webrtc 2015/10/13 06:58:40 Done.
124
125 EXPECT_EQ(apm_->kNoError, apm_->level_estimator()->Enable(true));
126 EXPECT_EQ(apm_->kNoError, apm_->gain_control()->Enable(true));
127
128 EXPECT_EQ(apm_->kNoError,
129 apm_->gain_control()->set_mode(GainControl::kAdaptiveAnalog));
130 EXPECT_EQ(apm_->kNoError, apm_->gain_control()->Enable(true));
131 EXPECT_EQ(apm_->kNoError,
132 apm_->gain_control()->set_mode(GainControl::kFixedDigital));
133
134 EXPECT_EQ(apm_->kNoError, apm_->noise_suppression()->Enable(true));
135 EXPECT_EQ(apm_->kNoError, apm_->voice_detection()->Enable(true));
136
137 if (test_config_.aec_type == AecType::NoAec) {
138 EXPECT_EQ(apm_->kNoError, apm_->echo_control_mobile()->Enable(false));
139 EXPECT_EQ(apm_->kNoError, apm_->echo_cancellation()->Enable(false));
140 } else {
141 if (test_config_.aec_type == AecType::Aecm) {
142 EXPECT_EQ(apm_->kNoError, apm_->echo_control_mobile()->Enable(true));
143 } else {
144 EXPECT_EQ(apm_->kNoError, apm_->echo_cancellation()->Enable(true));
145 EXPECT_EQ(apm_->kNoError,
146 apm_->echo_cancellation()->enable_metrics(true));
147 EXPECT_EQ(apm_->kNoError,
148 apm_->echo_cancellation()->enable_delay_logging(true));
149
150 if (test_config_.aec_type == AecType::AecExtFilter) {
151 config.Set<ExtendedFilter>(new ExtendedFilter(true));
152 use_config = true;
153 }
154
155 if (test_config_.aec_type == AecType::AecDelayAgnostic) {
156 config.Set<DelayAgnostic>(new DelayAgnostic(true));
157 use_config = true;
158 }
159
160 if (use_config)
161 apm_->SetExtraOptions(config);
162 }
163 }
164 }
165
166 virtual void TearDown() {
167 render_thread_->Stop();
168 capture_thread_->Stop();
169 stats_thread_->Stop();
170 }
171
172 // Function for generating the test configurations to use in the tests
173 static std::vector<TestConfig> GenerateTestConfigs() {
174 std::vector<TestConfig> test_configs;
175 // Loop over all possible test configurations
176 for (int render =
177 static_cast<int>(RenderApiFunction::ProcessReverseStream1);
178 render <= static_cast<int>(RenderApiFunction::AnalyzeReverseStream2);
179 render++)
180 for (int capture = static_cast<int>(CaptureApiFunction::ProcessStream1);
181 capture <= static_cast<int>(CaptureApiFunction::ProcessStream3);
182 capture++)
183 for (int aec = static_cast<int>(AecType::Aec);
184 aec <= static_cast<int>(AecType::Aecm); aec++)
185 for (int scheme =
186 static_cast<int>(RuntimeParameterSettingScheme::Scheme1);
187 scheme <=
188 static_cast<int>(RuntimeParameterSettingScheme::Scheme4);
189 scheme++) {
190 TestConfig test_config;
191 test_config.render_api_function =
192 static_cast<RenderApiFunction>(render);
193 test_config.capture_api_function =
194 static_cast<CaptureApiFunction>(capture);
195 test_config.aec_type = static_cast<AecType>(aec);
196
197 // Check that the selected render and capture API calls are
198 // compatible
199 if ((((test_config.render_api_function ==
200 RenderApiFunction::ProcessReverseStream1) ||
201 (test_config.render_api_function ==
202 RenderApiFunction::AnalyzeReverseStream1)) &&
203 (test_config.capture_api_function ==
204 CaptureApiFunction::ProcessStream1)) ||
205 (((test_config.render_api_function !=
206 RenderApiFunction::ProcessReverseStream1) &&
207 (test_config.render_api_function !=
208 RenderApiFunction::AnalyzeReverseStream1)) &&
209 (test_config.capture_api_function !=
210 CaptureApiFunction::ProcessStream1))) {
211 // For the compatible render and capture function combinations
212 // add test configs with different initial sample rates and
213 // parameter setting schemes
214 test_config.runtime_parameter_setting_scheme =
215 static_cast<RuntimeParameterSettingScheme>(scheme);
216
217 test_config.initial_sample_rate = 8000;
218 test_configs.push_back(test_config);
219
220 test_config.initial_sample_rate = 16000;
221 test_configs.push_back(test_config);
222
223 if (test_config.aec_type != AecType::Aecm) {
224 test_config.initial_sample_rate = 32000;
225 test_configs.push_back(test_config);
226
227 test_config.initial_sample_rate = 48000;
228 test_configs.push_back(test_config);
229 }
230 }
231 }
232 // Return the created test configurations
233 return test_configs;
234 }
235
236 private:
237 const int kMinNumCalls = 10000;
238 const int kTestTimeOutLimit = 10 * 60 * 1000;
239 const int kMaxCallDifference = 10;
240 const float kRenderInputFloatLevel = 0.5f;
241 const float kCaptureInputFloatLevel = 0.03125f;
242 const int kRenderInputFixLevel = 16384;
243 const int kCaptureInputFixLevel = 1024;
kwiberg-webrtc 2015/10/08 13:25:21 static const for all of these?
peah-webrtc 2015/10/13 06:58:39 Done.
244
245 // Populates a float audio frame with random data.
246 static void PopulateAudioFrame(float** frame,
247 int max_absolute_value,
the sun 2015/10/08 12:38:10 amplitude?
peah-webrtc 2015/10/13 06:58:39 Done.
248 int num_channels,
249 int samples_per_channel,
250 unsigned int* seed) {
251 for (int ch = 0; ch < num_channels; ch++)
the sun 2015/10/08 12:38:10 Please, always use braces.
peah-webrtc 2015/10/13 06:58:39 Done.
252 for (int k = 0; k < samples_per_channel; k++) {
253 // Store random 16 bit quantized float number between the specified
254 // limits.
255 frame[ch][k] =
256 static_cast<float>((rand_r(seed) % (32768 + 32768 + 1)) - 32768) /
ivoc 2015/10/09 15:47:15 I don't understand the "+ 1" here. A 16 bit value
peah-webrtc 2015/10/26 07:34:40 You are totally correct in that! It is now rewritt
257 32768.0f;
258 frame[ch][k] *= max_absolute_value;
259 }
260 }
261
262 // Populates an audioframe frame of AudioFrame type with random data.
263 static void PopulateAudioFrame(AudioFrame* frame,
264 int max_absolute_value,
265 unsigned int* seed) {
266 for (int ch = 0; ch < frame->num_channels_; ch++)
267 for (int k = 0; k < static_cast<int>(frame->samples_per_channel_); k++)
268 // Store random 16 bit quantized float number between -1 and 1.
the sun 2015/10/08 12:38:09 Assert on the range of max_absolute_value, plus ch
peah-webrtc 2015/10/13 06:58:39 Done.
269 frame->data_[k * ch] =
270 ((rand_r(seed) % (max_absolute_value + max_absolute_value + 1)) -
271 (max_absolute_value + 1));
the sun 2015/10/08 12:38:09 This computation is not correct. Say that max_abso
kwiberg-webrtc 2015/10/08 13:25:22 I recognize this from 15 lines ago. Subroutine?
ivoc 2015/10/09 15:47:15 Not exactly the same, there's no division and conv
peah-webrtc 2015/10/13 06:58:39 You are definitely correct. I now limited the rang
peah-webrtc 2015/10/13 06:58:39 Done.
peah-webrtc 2015/10/13 06:58:39 Done.
peah-webrtc 2015/10/13 06:58:39 Done.
peah-webrtc 2015/10/13 06:58:40 I think it should be correct now.
272 }
273
274 // Thread callback for the render thread
275 static bool CbRenderThread(void* context) {
276 return reinterpret_cast<AudioProcessingImpLockTest*>(context)
277 ->CbRenderImpl();
278 }
279
280 // Thread callback for the capture thread
281 static bool CbCaptureThread(void* context) {
282 return reinterpret_cast<AudioProcessingImpLockTest*>(context)
283 ->CbCaptureImpl();
284 }
285
286 // Thread callback for the stats thread
287 static bool CbStatsThread(void* context) {
288 return reinterpret_cast<AudioProcessingImpLockTest*>(context)
289 ->CbStatsImpl();
290 }
291
292 // Tests whether all the required render and capture side calls have been
293 // done.
294 bool TestDone() {
295 rtc::CritScope cs(&crit_);
296 if ((render_count_ > kMinNumCalls) && (capture_count_ > kMinNumCalls))
297 return true;
298 return false;
kwiberg-webrtc 2015/10/08 13:25:21 Just return (render_count_ > kMinNumCalls) && (
peah-webrtc 2015/10/13 06:58:40 Done.
299 }
300
301 // Sleeps a random time.
kwiberg-webrtc 2015/10/08 13:25:21 Time unit?
peah-webrtc 2015/10/13 06:58:40 Done.
302 static void SleepRandomTime(int max_sleep, unsigned int* seed) {
303 int sleeptime = rand_r(seed) % (max_sleep + 1);
304 SleepMs(sleeptime);
305 }
306
307 // Implements the callback functionality for the statistics
308 // collection thread.
309 bool CbStatsImpl() {
310 SleepRandomTime(100, &stats_seed);
311
312 (void)apm_->echo_cancellation()->is_enabled();
313 (void)apm_->echo_cancellation()->stream_drift_samples();
314 (void)apm_->echo_control_mobile()->is_enabled();
315 (void)apm_->gain_control()->is_enabled();
316 (void)apm_->gain_control()->stream_analog_level();
317 (void)apm_->noise_suppression()->is_enabled();
318 (void)apm_->noise_suppression()->speech_probability();
319 (void)apm_->voice_detection()->is_enabled();
320
321 return true;
322 }
323
324 // Implements the callback functionality for the render thread.
325 bool CbRenderImpl() {
326 // Conditional wait to ensure that a capture call has been done
327 // before the first render call is performed (implicitly
328 // required by the APM API).
329 if (first_render_side_call_) {
330 bool capture_side_called_local;
331 do {
332 {
333 rtc::CritScope cs(&crit_initial_sync_);
334 capture_side_called_local = capture_side_called_;
335 }
336 SleepRandomTime(3, &render_seed);
337 } while (!capture_side_called_local);
338
339 first_render_side_call_ = false;
340 }
341
342 // Sleep a random time to simulate thread jitter.
343 SleepRandomTime(3, &render_seed);
344
345 // End the test early if a fatal failure (ASSERT_*) has occurred.
346 if (HasFatalFailure())
347 test_complete_->Set();
348
349 // Ensure that the number of render and capture calls do not
350 // differ too much.
351 int frame_counter_difference;
352 do {
353 {
354 rtc::CritScope cs(&crit_);
355 frame_counter_difference =
356 render_count_ - (capture_count_ + kMaxCallDifference);
357 }
358 if (frame_counter_difference > 0)
359 SleepMs(1);
360 } while (frame_counter_difference > 0);
361
362 // End the test early if a fatal failure (ASSERT_*) has occurred.
363 if (HasFatalFailure())
364 test_complete_->Set();
365
366 // Apply any specified render side APM non-processing runtime calls.
367 ApplyRenderRuntimeSettingScheme();
368
369 // Apply the render side processing call.
370 CallRenderSide();
371
372 // End the test early if a fatal failure (ASSERT_*) has occurred.
373 if (HasFatalFailure())
374 test_complete_->Set();
375
376 // Increase the number of render-side calls.
377 rtc::CritScope cs(&crit_);
378 render_count_++;
379
380 return true;
381 }
382
383 // Makes the capture side processing API call.
384 void CallCaptureSide() {
385 // Prepare a proper capture side processing API call input.
386 PrepareCaptureFrame();
387
388 // Set the stream delay
389 (void)apm_->set_stream_delay_ms(30);
ivoc 2015/10/09 15:47:15 What does this (void) thing do?
peah-webrtc 2015/10/13 06:58:40 Done.
peah-webrtc 2015/10/13 06:58:40 It explicitly discards the output of the function,
390
391 // Call the specified capture side API processing method.
392 int result = AudioProcessing::kNoError;
393 switch (test_config_.capture_api_function) {
394 case CaptureApiFunction::ProcessStream1:
395 result = apm_->ProcessStream(&capture_frame_);
396 break;
397 case CaptureApiFunction::ProcessStream2:
398 result = apm_->ProcessStream(
399 capture_input_frame_, capture_input_samples_per_channel_,
400 capture_input_sample_rate_hz_, capture_input_channel_layout_,
401 capture_output_sample_rate_hz_, capture_output_channel_layout_,
402 capture_output_frame_);
403 break;
404 case CaptureApiFunction::ProcessStream3:
405 result = apm_->ProcessStream(
406 capture_input_frame_, capture_input_stream_config_,
407 capture_output_stream_config_, capture_output_frame_);
408 break;
409 default:
410 assert(false);
ivoc 2015/10/09 15:47:15 Shouldn't this be something like ASSERT_TRUE(false
peah-webrtc 2015/10/13 06:58:39 Done.
peah-webrtc 2015/10/13 06:58:39 Good point! Added that!
411 }
412
413 // Check the return code for error.
414 EXPECT_EQ(AudioProcessing::kNoError, result);
415 }
416
417 // Prepares the render side frame and the accompanying metadata
418 // with the appropriate information.
419 void PrepareRenderFrame() {
420 // Restrict to a common fixed sample rate if the AudioFrame interface is
421 // used.
422 if ((test_config_.render_api_function ==
423 RenderApiFunction::AnalyzeReverseStream1) ||
424 (test_config_.render_api_function ==
425 RenderApiFunction::ProcessReverseStream1) ||
426 (test_config_.aec_type != AecType::Aecm)) {
427 render_input_sample_rate_hz_ = test_config_.initial_sample_rate;
428 render_output_sample_rate_hz_ = test_config_.initial_sample_rate;
429 }
430
431 // Prepare the audioframe data and metadata
432 render_input_samples_per_channel_ =
433 render_input_sample_rate_hz_ * AudioProcessing::kChunkSizeMs / 1000;
434 render_frame_.sample_rate_hz_ = render_input_sample_rate_hz_;
435 render_frame_.num_channels_ = render_input_number_of_channels_;
436 render_frame_.samples_per_channel_ = render_input_samples_per_channel_;
437 memset(render_frame_.data_, 0,
438 render_input_samples_per_channel_ * sizeof(render_frame_.data_[0]));
439 PopulateAudioFrame(&render_frame_, kRenderInputFixLevel, &render_seed);
440
441 // Prepare the float audio input data and metadata.
442 render_input_stream_config_.set_sample_rate_hz(
443 render_input_sample_rate_hz_);
444 render_input_stream_config_.set_num_channels(
445 render_input_number_of_channels_);
446 render_input_stream_config_.set_has_keyboard(false);
447 PopulateAudioFrame(render_input_frame_, kRenderInputFloatLevel,
448 render_input_number_of_channels_,
449 render_input_samples_per_channel_, &render_seed);
450 render_input_channel_layout_ =
451 (render_input_number_of_channels_ == 1
452 ? AudioProcessing::ChannelLayout::kMono
453 : AudioProcessing::ChannelLayout::kStereo);
454
455 // Prepare the float audio output data and metadata.
456 render_output_samples_per_channel_ =
457 render_output_sample_rate_hz_ * AudioProcessing::kChunkSizeMs / 1000;
458 render_output_stream_config_.set_sample_rate_hz(
459 render_output_sample_rate_hz_);
460 render_output_stream_config_.set_num_channels(
461 render_output_number_of_channels_);
462 render_output_stream_config_.set_has_keyboard(false);
463 render_output_channel_layout_ =
464 (render_output_number_of_channels_ == 1
465 ? AudioProcessing::ChannelLayout::kMono
466 : AudioProcessing::ChannelLayout::kStereo);
467 }
468
469 void PrepareCaptureFrame() {
470 // Restrict to a common fixed sample rate if the AudioFrame
471 // interface is used.
472 if (test_config_.capture_api_function ==
473 CaptureApiFunction::ProcessStream1) {
474 capture_input_sample_rate_hz_ = test_config_.initial_sample_rate;
475 capture_output_sample_rate_hz_ = test_config_.initial_sample_rate;
476 }
477
478 // Prepare the audioframe data and metadata.
479 capture_input_samples_per_channel_ =
480 capture_input_sample_rate_hz_ * AudioProcessing::kChunkSizeMs / 1000;
481 capture_frame_.sample_rate_hz_ = capture_input_sample_rate_hz_;
482 capture_frame_.num_channels_ = capture_input_number_of_channels_;
483 capture_frame_.samples_per_channel_ = capture_input_samples_per_channel_;
484 memset(capture_frame_.data_, 0, capture_input_samples_per_channel_ *
485 sizeof(capture_frame_.data_[0]));
486 PopulateAudioFrame(&capture_frame_, kCaptureInputFixLevel, &capture_seed);
487
488 // Prepare the float audio input data and metadata.
489 capture_input_stream_config_.set_sample_rate_hz(
490 capture_input_sample_rate_hz_);
491 capture_input_stream_config_.set_num_channels(
492 capture_input_number_of_channels_);
493 capture_input_stream_config_.set_has_keyboard(false);
494 PopulateAudioFrame(capture_input_frame_, kCaptureInputFloatLevel,
495 capture_input_number_of_channels_,
496 capture_input_samples_per_channel_, &capture_seed);
497 capture_input_channel_layout_ =
498 (capture_input_number_of_channels_ == 1
499 ? AudioProcessing::ChannelLayout::kMonoAndKeyboard
500 : AudioProcessing::ChannelLayout::kStereoAndKeyboard);
501
502 // Prepare the float audio output data and metadata.
503 capture_output_samples_per_channel_ =
504 capture_output_sample_rate_hz_ * AudioProcessing::kChunkSizeMs / 1000;
505 capture_output_stream_config_.set_sample_rate_hz(
506 capture_output_sample_rate_hz_);
507 capture_output_stream_config_.set_num_channels(
508 capture_output_number_of_channels_);
509 capture_output_stream_config_.set_has_keyboard(false);
510 capture_output_channel_layout_ =
511 (capture_output_number_of_channels_ == 1
512 ? AudioProcessing::ChannelLayout::kMono
513 : AudioProcessing::ChannelLayout::kStereo);
514 }
515
516 // Applies any render capture APM API calls and audio stream characteristics
517 // specified by the scheme for the test.
518 void ApplyRenderRuntimeSettingScheme() {
519 int render_count_local;
520 {
521 rtc::CritScope cs(&crit_);
522 render_count_local = render_count_;
523 }
kwiberg-webrtc 2015/10/08 13:25:22 If you want, you can write it like this: const
peah-webrtc 2015/10/13 06:58:39 That looks awesome! Unfortunately it seems that we
kwiberg-webrtc 2015/10/13 09:35:12 It looks like that rule is going to get the obviou
peah-webrtc 2015/10/14 07:57:13 Great! That worked super!
524
525 // Update the number of channels and sample rates for the input and output.
526 switch (test_config_.runtime_parameter_setting_scheme) {
527 case RuntimeParameterSettingScheme::Scheme1:
528 if (render_count_local == 0)
529 render_input_sample_rate_hz_ = 16000;
530 else if ((render_count_local % 47) == 0)
kwiberg-webrtc 2015/10/08 13:25:22 Drop the extra parentheses.
peah-webrtc 2015/10/13 06:58:39 Done.
531 render_input_sample_rate_hz_ = 32000;
532 else if ((render_count_local % 71) == 0)
533 render_input_sample_rate_hz_ = 48000;
534 else if ((render_count_local % 79) == 0)
535 render_input_sample_rate_hz_ = 16000;
536 else if ((render_count_local % 83) == 0)
537 render_input_sample_rate_hz_ = 8000;
kwiberg-webrtc 2015/10/08 13:25:22 Where do all these numbers come from?
ivoc 2015/10/09 15:47:15 Looks very confusing indeed, needs some comments t
peah-webrtc 2015/10/13 06:58:39 Please let me know if the comment is sufficient!
peah-webrtc 2015/10/13 06:58:39 They are prime numbers that are chosen in order to
538
539 if (render_count_local == 0)
540 render_input_number_of_channels_ = 1;
541 else if ((render_count_local % 4) == 0)
542 render_input_number_of_channels_ =
543 (render_input_number_of_channels_ == 1 ? 2 : 1);
544
545 if (render_count_local == 0)
546 render_output_sample_rate_hz_ = 16000;
547 else if ((render_count_local % 17) == 0)
548 render_output_sample_rate_hz_ = 32000;
549 else if ((render_count_local % 19) == 0)
550 render_output_sample_rate_hz_ = 48000;
551 else if ((render_count_local % 29) == 0)
552 render_output_sample_rate_hz_ = 16000;
553 else if ((render_count_local % 61) == 0)
554 render_output_sample_rate_hz_ = 8000;
555
556 if (render_count_local == 0)
557 render_output_number_of_channels_ = 1;
558 else if ((render_count_local % 8) == 0)
559 render_output_number_of_channels_ =
560 (render_output_number_of_channels_ == 1 ? 2 : 1);
561 break;
562 case RuntimeParameterSettingScheme::Scheme2:
563 if (render_count_local == 0) {
564 render_input_number_of_channels_ = 1;
565 render_input_sample_rate_hz_ = 16000;
566 render_output_number_of_channels_ = 1;
567 render_output_sample_rate_hz_ = 16000;
568 } else {
569 render_input_number_of_channels_ =
570 (render_input_number_of_channels_ == 1 ? 2 : 1);
571 if (render_input_sample_rate_hz_ == 8000)
572 render_input_sample_rate_hz_ = 16000;
573 else if (render_input_sample_rate_hz_ == 16000)
574 render_input_sample_rate_hz_ = 32000;
575 else if (render_input_sample_rate_hz_ == 32000)
576 render_input_sample_rate_hz_ = 48000;
577 else if (render_input_sample_rate_hz_ == 48000)
578 render_input_sample_rate_hz_ = 8000;
579
580 render_output_number_of_channels_ =
581 (render_output_number_of_channels_ == 1 ? 2 : 1);
582 if (render_output_sample_rate_hz_ == 8000)
583 render_output_sample_rate_hz_ = 16000;
584 else if (render_output_sample_rate_hz_ == 16000)
585 render_output_sample_rate_hz_ = 32000;
586 else if (render_output_sample_rate_hz_ == 32000)
587 render_output_sample_rate_hz_ = 48000;
588 else if (render_output_sample_rate_hz_ == 48000)
589 render_output_sample_rate_hz_ = 8000;
590 }
591 break;
592 case RuntimeParameterSettingScheme::Scheme3:
593 if (render_count_local == 0) {
594 render_input_sample_rate_hz_ = 16000;
595 render_input_number_of_channels_ = 1;
596 render_output_sample_rate_hz_ = 16000;
597 render_output_number_of_channels_ = 1;
598 }
599 break;
600 case RuntimeParameterSettingScheme::Scheme4:
601 if (render_count_local == 0) {
602 render_input_sample_rate_hz_ = 16000;
603 render_input_number_of_channels_ = 2;
604 render_output_sample_rate_hz_ = 16000;
605 render_output_number_of_channels_ = 2;
606 }
607
608 break;
609 default:
610 assert(false);
611 }
612
613 // Restric the number of output channels not to exceed
614 // the number of input channels.
615 render_output_number_of_channels_ = std::min(
616 render_output_number_of_channels_, render_input_number_of_channels_);
617 }
618
619 // Applies any runtime capture APM API calls and audio stream characteristics
620 // specified by the scheme for the test.
621 void ApplyCaptureRuntimeSettingScheme() {
622 int capture_count_local;
623 {
624 rtc::CritScope cs(&crit_);
625 capture_count_local = capture_count_;
626 }
627
628 // Update the number of channels and sample rates for the input and output.
629 switch (test_config_.runtime_parameter_setting_scheme) {
630 case RuntimeParameterSettingScheme::Scheme1:
631 if (capture_count_local == 0)
632 capture_input_sample_rate_hz_ = 16000;
633 else if ((capture_count_local % 11) == 0)
634 capture_input_sample_rate_hz_ = 32000;
635 else if ((capture_count_local % 73) == 0)
636 capture_input_sample_rate_hz_ = 48000;
637 else if ((capture_count_local % 89) == 0)
638 capture_input_sample_rate_hz_ = 16000;
639 else if ((capture_count_local % 97) == 0)
640 capture_input_sample_rate_hz_ = 8000;
641
642 if (capture_count_local == 0)
643 capture_input_number_of_channels_ = 1;
644 else if ((capture_count_local % 4) == 0)
645 capture_input_number_of_channels_ =
646 (capture_input_number_of_channels_ == 1 ? 2 : 1);
647
648 if (capture_count_local == 0)
649 capture_output_sample_rate_hz_ = 16000;
650 else if ((capture_count_local % 5) == 0)
651 capture_output_sample_rate_hz_ = 32000;
652 else if ((capture_count_local % 47) == 0)
653 capture_output_sample_rate_hz_ = 48000;
654 else if ((capture_count_local % 53) == 0)
655 capture_output_sample_rate_hz_ = 16000;
656 else if ((capture_count_local % 71) == 0)
657 capture_output_sample_rate_hz_ = 8000;
658
659 if (capture_count_local == 0)
660 capture_output_number_of_channels_ = 1;
661 else if ((capture_count_local % 8) == 0)
662 capture_output_number_of_channels_ =
663 (capture_output_number_of_channels_ == 1 ? 2 : 1);
664 break;
665 case RuntimeParameterSettingScheme::Scheme2:
666 if ((capture_count_local % 2) == 0) {
667 capture_input_number_of_channels_ = 1;
668 capture_input_sample_rate_hz_ = 16000;
669 capture_output_number_of_channels_ = 1;
670 capture_output_sample_rate_hz_ = 16000;
671 } else {
672 capture_input_number_of_channels_ =
673 (capture_input_number_of_channels_ == 1 ? 2 : 1);
674 if (capture_input_sample_rate_hz_ == 8000)
675 capture_input_sample_rate_hz_ = 16000;
676 else if (capture_input_sample_rate_hz_ == 16000)
677 capture_input_sample_rate_hz_ = 32000;
678 else if (capture_input_sample_rate_hz_ == 32000)
679 capture_input_sample_rate_hz_ = 48000;
680 else if (capture_input_sample_rate_hz_ == 48000)
681 capture_input_sample_rate_hz_ = 8000;
682
683 capture_output_number_of_channels_ =
684 (capture_output_number_of_channels_ == 1 ? 2 : 1);
685 if (capture_output_sample_rate_hz_ == 8000)
686 capture_output_sample_rate_hz_ = 16000;
687 else if (capture_output_sample_rate_hz_ == 16000)
688 capture_output_sample_rate_hz_ = 32000;
689 else if (capture_output_sample_rate_hz_ == 32000)
690 capture_output_sample_rate_hz_ = 48000;
691 else if (capture_output_sample_rate_hz_ == 48000)
692 capture_output_sample_rate_hz_ = 8000;
693 }
694 break;
695 case RuntimeParameterSettingScheme::Scheme3:
696 if (capture_count_local == 0) {
697 capture_input_sample_rate_hz_ = 16000;
698 capture_input_number_of_channels_ = 1;
699 capture_output_sample_rate_hz_ = 16000;
700 capture_output_number_of_channels_ = 1;
701 }
702 break;
703 case RuntimeParameterSettingScheme::Scheme4:
704 if (capture_count_local == 0) {
705 capture_input_sample_rate_hz_ = 16000;
706 capture_input_number_of_channels_ = 2;
707 capture_output_sample_rate_hz_ = 16000;
708 capture_output_number_of_channels_ = 2;
709 }
710
711 break;
712 default:
713 assert(false);
714 }
715
716 // Call any specified runtime APM setter and
717 // getter calls.
718 switch (test_config_.runtime_parameter_setting_scheme) {
719 case RuntimeParameterSettingScheme::Scheme1:
720 case RuntimeParameterSettingScheme::Scheme3:
721 break;
722 case RuntimeParameterSettingScheme::Scheme2:
723 case RuntimeParameterSettingScheme::Scheme4:
724 if ((capture_count_local % 2) == 0) {
725 (void)apm_->set_stream_delay_ms(30);
726 apm_->set_stream_key_pressed(true);
727 apm_->set_output_will_be_muted(true);
728 apm_->set_delay_offset_ms(15);
729 (void)apm_->delay_offset_ms();
730 apm_->set_output_will_be_muted(true);
731 (void)apm_->num_reverse_channels();
732 } else {
733 (void)apm_->set_stream_delay_ms(50);
734 apm_->set_stream_key_pressed(false);
735 apm_->set_output_will_be_muted(false);
736 apm_->set_delay_offset_ms(20);
737 (void)apm_->delay_offset_ms();
738 apm_->set_output_will_be_muted(false);
739 (void)apm_->num_reverse_channels();
740 }
741 break;
742 default:
743 assert(false);
744 }
745
746 // Restric the number of output channels not to exceed
747 // the number of input channels.
748 capture_output_number_of_channels_ = std::min(
749 capture_output_number_of_channels_, capture_input_number_of_channels_);
750 }
751
752 // Makes the render side processing API call.
753 void CallRenderSide() {
754 // Prepare a proper render side processing API call input.
755 PrepareRenderFrame();
756
757 // Call the specified render side API processing method.
758 int result = AudioProcessing::kNoError;
759 switch (test_config_.render_api_function) {
760 case RenderApiFunction::ProcessReverseStream1:
761 result = apm_->ProcessReverseStream(&render_frame_);
762 break;
763 case RenderApiFunction::ProcessReverseStream2:
764 result = apm_->ProcessReverseStream(
765 render_input_frame_, render_input_stream_config_,
766 render_output_stream_config_, render_output_frame_);
767 break;
768 case RenderApiFunction::AnalyzeReverseStream1:
769 result = apm_->AnalyzeReverseStream(&render_frame_);
770 break;
771 case RenderApiFunction::AnalyzeReverseStream2:
772 result = apm_->AnalyzeReverseStream(
773 render_input_frame_, render_input_samples_per_channel_,
774 render_input_sample_rate_hz_, render_input_channel_layout_);
775 break;
776 default:
777 assert(false);
778 }
779
780 // Check the return code for error.
781 EXPECT_EQ(AudioProcessing::kNoError, result);
782 }
783
784 // Implements the callback functionality for the capture thread.
785 bool CbCaptureImpl() {
786 // Sleep a random time to simulate thread jitter.
787 SleepRandomTime(3, &capture_seed);
788
789 // End the test early if a fatal failure (ASSERT_*) has occurred.
790 if (HasFatalFailure())
791 test_complete_->Set();
792
793 // Ensure that there are not more capture side calls than render side
794 // calls.
795 int frame_counter_difference;
796 do {
797 {
798 rtc::CritScope cs(&crit_);
799 frame_counter_difference = capture_count_ - render_count_;
800 }
801 if (frame_counter_difference > 0)
802 SleepMs(1);
803 } while (frame_counter_difference > 0);
804
805 // End the test early if a fatal failure (ASSERT_*) has occurred.
806 if (HasFatalFailure())
807 test_complete_->Set();
808
809 // Apply any specified capture side APM non-processing runtime calls.
810 ApplyCaptureRuntimeSettingScheme();
811
812 // Apply the capture side processing call.
813 CallCaptureSide();
814
815 // End the test early if a fatal failure (ASSERT_*) has occurred.
816 if (HasFatalFailure())
817 test_complete_->Set();
818
819 // Increase the number of capture-side calls.
820 {
821 rtc::CritScope cs(&crit_);
822 capture_count_++;
823 }
824
825 // Check if the test is done.
826 if (TestDone())
827 test_complete_->Set();
828
829 // Flag that the capture side has been called at least once
830 // (needed to ensure that a capture call has been done
831 // before the first render call is performed (implicitly
832 // required by the APM API).
833 {
834 rtc::CritScope cs(&crit_initial_sync_);
835 capture_side_called_ = true;
836 }
837
838 return true;
839 }
840
841 // Start the threads used in the test.
842 void StartThreads() {
843 ASSERT_TRUE(render_thread_->Start());
844 render_thread_->SetPriority(kRealtimePriority);
845 ASSERT_TRUE(capture_thread_->Start());
846 capture_thread_->SetPriority(kRealtimePriority);
847 ASSERT_TRUE(stats_thread_->Start());
848 stats_thread_->SetPriority(kNormalPriority);
849 }
850
851 rtc::CriticalSection crit_;
852 rtc::CriticalSection crit_initial_sync_;
853 rtc::scoped_ptr<ThreadWrapper> render_thread_;
854 rtc::scoped_ptr<ThreadWrapper> capture_thread_;
855 rtc::scoped_ptr<ThreadWrapper> stats_thread_;
856 int render_count_ GUARDED_BY(crit_);
857 int capture_count_ GUARDED_BY(crit_);
858 bool first_render_side_call_;
859 bool capture_side_called_ GUARDED_BY(crit_initial_sync_);
860 const rtc::scoped_ptr<EventWrapper> test_complete_;
861 rtc::scoped_ptr<AudioProcessing> apm_;
862 TestConfig test_config_;
863 AudioFrame render_frame_;
864 AudioFrame capture_frame_;
865 unsigned int render_seed;
866 unsigned int capture_seed;
867 unsigned int stats_seed;
868
869 // Variables related to the capture side audio data and formats.
870 float** capture_output_frame_;
871 AudioProcessing::ChannelLayout capture_output_channel_layout_;
872 int capture_input_sample_rate_hz_;
873 int capture_input_number_of_channels_;
874 float** capture_input_frame_;
875 AudioProcessing::ChannelLayout capture_input_channel_layout_;
876 int capture_output_sample_rate_hz_;
877 int capture_output_number_of_channels_;
878 StreamConfig capture_input_stream_config_;
879 StreamConfig capture_output_stream_config_;
880 int capture_input_samples_per_channel_;
881 int capture_output_samples_per_channel_;
882
883 // Variables related to the render side audio data and formats.
884 float** render_output_frame_;
885 AudioProcessing::ChannelLayout render_output_channel_layout_;
886 int render_input_sample_rate_hz_;
887 int render_input_number_of_channels_;
888 float** render_input_frame_;
889 AudioProcessing::ChannelLayout render_input_channel_layout_;
890 int render_output_sample_rate_hz_;
891 int render_output_number_of_channels_;
892 StreamConfig render_input_stream_config_;
893 StreamConfig render_output_stream_config_;
894 int render_input_samples_per_channel_;
895 int render_output_samples_per_channel_;
kwiberg-webrtc 2015/10/08 13:25:22 This is a large pile of member variables. Any chan
peah-webrtc 2015/10/13 06:58:40 Done.
896 };
897
898 } // anonymous namespace
899
900 TEST_P(AudioProcessingImpLockTest, LockTest) {
901 // Run test and verify that it did not time out.
902 EXPECT_EQ(kEventSignaled, RunTest());
903 }
904
905 // Instantiate tests from the test configurations provided by the generator.
906 INSTANTIATE_TEST_CASE_P(
907 DISABLED_AudioProcessingImpLockTestAllCombinations,
908 AudioProcessingImpLockTest,
909 ::testing::ValuesIn(AudioProcessingImpLockTest::GenerateTestConfigs()));
910
911 } // 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