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

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

Issue 1436553004: Created a test that reports the statistics for the duration of APM stream processing API calls. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Renamed test file and moved to new build target 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/webrtc_tests.gypi » ('j') | webrtc/webrtc_tests.gypi » ('J')
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 #include "webrtc/modules/audio_processing/audio_processing_impl.h"
11
12 #include <math.h>
13
14 #include <algorithm>
15 #include <vector>
16
17 #include "testing/gtest/include/gtest/gtest.h"
18 #include "webrtc/base/array_view.h"
19 #include "webrtc/base/criticalsection.h"
20 #include "webrtc/base/safe_conversions.h"
21 #include "webrtc/config.h"
22 #include "webrtc/modules/audio_processing/test/test_utils.h"
23 #include "webrtc/modules/include/module_common_types.h"
24 #include "webrtc/system_wrappers/include/clock.h"
25 #include "webrtc/system_wrappers/include/event_wrapper.h"
26 #include "webrtc/system_wrappers/include/sleep.h"
27 #include "webrtc/system_wrappers/include/thread_wrapper.h"
28 #include "webrtc/test/random.h"
29 #include "webrtc/test/testsupport/perf_test.h"
30
31 namespace webrtc {
32
33 namespace {
34
35 static const bool kPrintAllDurations = false;
36
37 class CallSimulator;
38
39 // Type of the render thread APM API call to use in the test.
40 enum class ProcessorType { kRender, kCapture };
41
42 // Variant of APM processing settings to use in the test.
43 enum class SettingsType {
44 kDefaultApmDesktop,
45 kDefaultApmMobile,
46 kDefaultApmDesktopAndBeamformer,
47 kDefaultApmDesktopAndIntelligibilityEnhancer,
48 kAllSubmodulesTurnedOff,
49 kDefaultDesktopApmWithoutDelayAgnostic,
50 kDefaultDesktopApmWithoutExtendedFilter
51 };
52
53 // Variables related to the audio data and formats.
54 struct AudioFrameData {
55 explicit AudioFrameData(size_t max_frame_size) {
56 // Set up the two-dimensional arrays needed for the APM API calls.
57 input_framechannels.resize(2 * max_frame_size);
58 input_frame.resize(2);
59 input_frame[0] = &input_framechannels[0];
60 input_frame[1] = &input_framechannels[max_frame_size];
61
62 output_frame_channels.resize(2 * max_frame_size);
63 output_frame.resize(2);
64 output_frame[0] = &output_frame_channels[0];
65 output_frame[1] = &output_frame_channels[max_frame_size];
66 }
67
68 std::vector<float> output_frame_channels;
69 std::vector<float*> output_frame;
70 std::vector<float> input_framechannels;
71 std::vector<float*> input_frame;
72 StreamConfig input_stream_config;
73 StreamConfig output_stream_config;
74 };
75
76 // The configuration for the test.
77 struct SimulationConfig {
78 SimulationConfig(int sample_rate_hz, SettingsType simulation_settings)
79 : sample_rate_hz(sample_rate_hz),
80 simulation_settings(simulation_settings) {}
81
82 static std::vector<SimulationConfig> GenerateSimulationConfigs() {
83 std::vector<SimulationConfig> simulation_configs;
84
85 const SettingsType desktop_settings[] = {
86 SettingsType::kDefaultApmDesktop, SettingsType::kAllSubmodulesTurnedOff,
87 SettingsType::kDefaultDesktopApmWithoutDelayAgnostic,
88 SettingsType::kDefaultDesktopApmWithoutExtendedFilter};
89
90 const int desktop_sample_rates[] = {8000, 16000, 32000, 48000};
91
92 for (auto sample_rate : desktop_sample_rates) {
93 for (auto settings : desktop_settings) {
94 simulation_configs.push_back(SimulationConfig(sample_rate, settings));
95 }
96 }
97
98 const SettingsType intelligibility_enhancer_settings[] = {
99 SettingsType::kDefaultApmDesktopAndIntelligibilityEnhancer};
100
101 const int intelligibility_enhancer_sample_rates[] = {8000, 16000, 32000,
102 48000};
103
104 for (auto sample_rate : intelligibility_enhancer_sample_rates) {
105 for (auto settings : intelligibility_enhancer_settings) {
106 simulation_configs.push_back(SimulationConfig(sample_rate, settings));
107 }
108 }
109
110 const SettingsType beamformer_settings[] = {
111 SettingsType::kDefaultApmDesktopAndBeamformer};
112
113 const int beamformer_sample_rates[] = {8000, 16000, 32000, 48000};
114
115 for (auto sample_rate : beamformer_sample_rates) {
116 for (auto settings : beamformer_settings) {
117 simulation_configs.push_back(SimulationConfig(sample_rate, settings));
118 }
119 }
120
121 const SettingsType mobile_settings[] = {SettingsType::kDefaultApmMobile};
122
123 const int mobile_sample_rates[] = {8000, 16000};
124
125 for (auto sample_rate : mobile_sample_rates) {
126 for (auto settings : mobile_settings) {
127 simulation_configs.push_back(SimulationConfig(sample_rate, settings));
128 }
129 }
130
131 return simulation_configs;
132 }
133
134 std::string SettingsDescription() const {
135 std::string description;
136 switch (simulation_settings) {
137 case SettingsType::kDefaultApmMobile:
138 description = "DefaultApmMobile";
139 break;
140 case SettingsType::kDefaultApmDesktop:
141 description = "DefaultApmDesktop";
142 break;
143 case SettingsType::kDefaultApmDesktopAndBeamformer:
144 description = "DefaultApmDesktopAndBeamformer";
145 break;
146 case SettingsType::kDefaultApmDesktopAndIntelligibilityEnhancer:
147 description = "DefaultApmDesktopAndIntelligibilityEnhancer";
148 break;
149 case SettingsType::kAllSubmodulesTurnedOff:
150 description = "AllSubmodulesOff";
151 break;
152 case SettingsType::kDefaultDesktopApmWithoutDelayAgnostic:
153 description = "DefaultDesktopApmWithoutDelayAgnostic";
154 break;
155 case SettingsType::kDefaultDesktopApmWithoutExtendedFilter:
156 description = "DefaultDesktopApmWithoutExtendedFilter";
157 break;
158 }
159 return description;
160 }
161
162 const int sample_rate_hz = 16000;
163 const SettingsType simulation_settings = SettingsType::kDefaultApmDesktop;
164 };
165
166 // Handler for the frame counters.
167 class FrameCounters {
168 public:
169 void IncreaseRenderCounter() {
170 rtc::CritScope cs(&crit_);
171 render_count_++;
172 }
173
174 void IncreaseCaptureCounter() {
175 rtc::CritScope cs(&crit_);
176 capture_count_++;
177 }
178
179 int GetCaptureCounter() const {
180 rtc::CritScope cs(&crit_);
181 return capture_count_;
182 }
183
184 int GetRenderCounter() const {
185 rtc::CritScope cs(&crit_);
186 return render_count_;
187 }
188
189 int CaptureMinusRenderCounters() const {
190 rtc::CritScope cs(&crit_);
191 return capture_count_ - render_count_;
192 }
193
194 int RenderMinusCaptureCounters() const {
195 return -CaptureMinusRenderCounters();
196 }
197
198 bool BothCountersExceedeThreshold(int threshold) const {
199 rtc::CritScope cs(&crit_);
200 return (render_count_ > threshold && capture_count_ > threshold);
201 }
202
203 private:
204 mutable rtc::CriticalSection crit_;
205 int render_count_ GUARDED_BY(crit_) = 0;
206 int capture_count_ GUARDED_BY(crit_) = 0;
207 };
208
209 // Class that protects a flag using a lock.
210 class LockedFlag {
211 public:
212 bool get_flag() const {
213 rtc::CritScope cs(&crit_);
214 return flag_;
215 }
216
217 void set_flag() {
218 rtc::CritScope cs(&crit_);
219 flag_ = true;
220 }
221
222 private:
223 mutable rtc::CriticalSection crit_;
224 bool flag_ GUARDED_BY(crit_) = false;
225 };
226
227 // Parent class for the thread processors.
228 class TimedThreadApiProcessor {
229 public:
230 TimedThreadApiProcessor(ProcessorType processor_type,
231 test::Random* rand_gen,
232 FrameCounters* shared_counters_state,
233 LockedFlag* capture_call_checker,
234 CallSimulator* test_framework,
235 const SimulationConfig* simulation_config,
236 AudioProcessing* apm,
237 int num_durations_to_store,
238 float input_level,
239 int num_channels)
240 : rand_gen_(rand_gen),
241 frame_counters_(shared_counters_state),
242 capture_call_checker_(capture_call_checker),
243 test_(test_framework),
244 simulation_config_(simulation_config),
245 apm_(apm),
246 frame_data_(kMaxFrameSize),
247 clock_(webrtc::Clock::GetRealTimeClock()),
248 num_durations_to_store_(num_durations_to_store),
249 input_level_(input_level),
250 processor_type_(processor_type),
251 num_channels_(num_channels) {
252 api_call_durations_.reserve(num_durations_to_store_);
253 }
254
255 // Implements the callback functionality for the threads.
256 bool Process();
257
258 // Method for printing out the simulation statistics.
259 void print_processor_statistics(std::string processor_name) const {
260 const std::string modifier = "_api_call_duration";
261
262 // Lambda function for creating a test printout string.
263 auto create_mean_and_std_string = [](int64_t average,
264 int64_t standard_dev) {
265 std::string s = std::to_string(average);
266 s += ", ";
267 s += std::to_string(standard_dev);
268 return s;
269 };
270
271 const std::string sample_rate_name =
272 "_" + std::to_string(simulation_config_->sample_rate_hz) + "Hz";
273
274 webrtc::test::PrintResultMeanAndError(
275 "apm_timing", sample_rate_name, processor_name,
276 create_mean_and_std_string(GetDurationAverage(),
277 GetDurationStandardDeviation()),
278 "us", false);
279
280 if (kPrintAllDurations) {
281 std::string value_string = "";
282 for (int64_t duration : api_call_durations_) {
283 value_string += std::to_string(duration) + ",";
284 }
285 webrtc::test::PrintResultList("apm_call_durations", sample_rate_name,
286 processor_name, value_string, "us", false);
287 }
288 }
289
290 void AddDuration(int64_t duration) {
291 if (api_call_durations_.size() < num_durations_to_store_) {
292 api_call_durations_.push_back(duration);
293 }
294 }
295
296 private:
297 static const int kMaxCallDifference = 10;
298 static const int kMaxFrameSize = 480;
299 static const int kNumInitializationFrames = 5;
300
301 int64_t GetDurationStandardDeviation() const {
302 double variance = 0;
303 const int64_t average_duration = GetDurationAverage();
304 for (size_t k = kNumInitializationFrames; k < api_call_durations_.size();
305 k++) {
306 int64_t tmp = api_call_durations_[k] - average_duration;
307 variance += static_cast<double>(tmp * tmp);
308 }
309 return (api_call_durations_.size() > (kNumInitializationFrames - 1)
310 ? rtc::checked_cast<int64_t>(
311 sqrt(variance / (api_call_durations_.size() -
312 kNumInitializationFrames)))
313 : -1);
314 }
315
316 int64_t GetDurationAverage() const {
317 int64_t average_duration = 0;
318 for (size_t k = kNumInitializationFrames; k < api_call_durations_.size();
319 k++) {
320 average_duration += api_call_durations_[k];
321 }
322 return (api_call_durations_.size() > (kNumInitializationFrames - 1)
323 ? average_duration /
324 (api_call_durations_.size() - kNumInitializationFrames)
325 : -1);
326 }
327
328 int ProcessCapture() {
329 // Set the stream delay.
330 apm_->set_stream_delay_ms(30);
331
332 // Call and time the specified capture side API processing method.
333 const int64_t start_time = clock_->TimeInMicroseconds();
334 const int result = apm_->ProcessStream(
335 &frame_data_.input_frame[0], frame_data_.input_stream_config,
336 frame_data_.output_stream_config, &frame_data_.output_frame[0]);
337 const int64_t end_time = clock_->TimeInMicroseconds();
338
339 frame_counters_->IncreaseCaptureCounter();
340
341 AddDuration(end_time - start_time);
342
343 if (first_process_call_) {
344 // Flag that the capture side has been called at least once
345 // (needed to ensure that a capture call has been done
346 // before the first render call is performed (implicitly
347 // required by the APM API).
348 capture_call_checker_->set_flag();
349 first_process_call_ = false;
350 }
351 return result;
352 }
353
354 bool ReadyToProcessCapture() {
355 return (frame_counters_->CaptureMinusRenderCounters() <=
356 kMaxCallDifference);
357 }
358
359 int ProcessRender() {
360 // Call and time the specified render side API processing method.
361 const int64_t start_time = clock_->TimeInMicroseconds();
362 const int result = apm_->ProcessReverseStream(
363 &frame_data_.input_frame[0], frame_data_.input_stream_config,
364 frame_data_.output_stream_config, &frame_data_.output_frame[0]);
365 const int64_t end_time = clock_->TimeInMicroseconds();
366 frame_counters_->IncreaseRenderCounter();
367
368 AddDuration(end_time - start_time);
369
370 return result;
371 }
372
373 bool ReadyToProcessRender() {
374 // Do not process until at least one capture call has been done.
375 // (implicitly required by the APM API).
376 if (first_process_call_ && !capture_call_checker_->get_flag()) {
377 return false;
378 }
379
380 // Ensure that the number of render and capture calls do not differ too
381 // much.
382 if (frame_counters_->RenderMinusCaptureCounters() > kMaxCallDifference) {
383 return false;
384 }
385
386 first_process_call_ = false;
387 return true;
388 }
389
390 void PrepareFrame() {
391 // Lambda function for populating a float multichannel audio frame
392 // with random data.
393 auto populate_audio_frame = [](float amplitude, size_t num_channels,
394 size_t samples_per_channel,
395 test::Random* rand_gen, float** frame) {
396 for (size_t ch = 0; ch < num_channels; ch++) {
397 for (size_t k = 0; k < samples_per_channel; k++) {
398 // Store random float number with a value between +-amplitude.
399 frame[ch][k] = amplitude * (2 * rand_gen->Rand<float>() - 1);
400 }
401 }
402 };
403
404 // Prepare the audio input data and metadata.
405 frame_data_.input_stream_config.set_sample_rate_hz(
406 simulation_config_->sample_rate_hz);
407 frame_data_.input_stream_config.set_num_channels(num_channels_);
408 frame_data_.input_stream_config.set_has_keyboard(false);
409 populate_audio_frame(input_level_, num_channels_,
410 (simulation_config_->sample_rate_hz *
411 AudioProcessing::kChunkSizeMs / 1000),
412 rand_gen_, &frame_data_.input_frame[0]);
413
414 // Prepare the float audio output data and metadata.
415 frame_data_.output_stream_config.set_sample_rate_hz(
416 simulation_config_->sample_rate_hz);
417 frame_data_.output_stream_config.set_num_channels(1);
418 frame_data_.output_stream_config.set_has_keyboard(false);
419 }
420
421 bool ReadyToProcess() {
422 switch (processor_type_) {
423 case ProcessorType::kRender:
424 return ReadyToProcessRender();
425 break;
426 case ProcessorType::kCapture:
427 return ReadyToProcessCapture();
428 break;
429 }
430 }
431
432 test::Random* rand_gen_ = nullptr;
433 FrameCounters* frame_counters_ = nullptr;
434 LockedFlag* capture_call_checker_ = nullptr;
435 CallSimulator* test_ = nullptr;
436 const SimulationConfig* const simulation_config_ = nullptr;
437 AudioProcessing* apm_ = nullptr;
438 AudioFrameData frame_data_;
439 webrtc::Clock* clock_;
440 const size_t num_durations_to_store_;
441 std::vector<int64_t> api_call_durations_;
442 const float input_level_;
443 bool first_process_call_ = true;
444 const ProcessorType processor_type_;
445 const int num_channels_ = 1;
446 };
447
448 // Class for managing the test simulation.
449 class CallSimulator : public ::testing::TestWithParam<SimulationConfig> {
450 public:
451 CallSimulator()
452 : test_complete_(EventWrapper::Create()),
453 render_thread_(ThreadWrapper::CreateThread(RenderProcessorThreadFunc,
454 this,
455 "render")),
456 capture_thread_(ThreadWrapper::CreateThread(CaptureProcessorThreadFunc,
457 this,
458 "capture")),
459 rand_gen_(42U),
460 simulation_config_(static_cast<SimulationConfig>(GetParam())) {}
461
462 // Run the call simulation with a timeout.
463 EventTypeWrapper Run() {
464 StartThreads();
465
466 EventTypeWrapper result = test_complete_->Wait(kTestTimeout);
467
468 render_thread_state_->print_processor_statistics(
469 simulation_config_.SettingsDescription() + "_render");
470 capture_thread_state_->print_processor_statistics(
471 simulation_config_.SettingsDescription() + "_capture");
472
473 return result;
474 }
475
476 // Tests whether all the required render and capture side calls have been
477 // done.
478 void MaybeEndTest() {
479 if (frame_counters_.BothCountersExceedeThreshold(kMinNumFramesToProcess)) {
480 test_complete_->Set();
481 }
482 }
483
484 private:
485 static const float kCaptureInputFloatLevel;
486 static const float kRenderInputFloatLevel;
487 static const int kMinNumFramesToProcess = 150;
488 static const int32_t kTestTimeout = 3 * 10 * kMinNumFramesToProcess;
489
490 // ::testing::TestWithParam<> implementation.
491 void TearDown() override {
492 render_thread_->Stop();
493 capture_thread_->Stop();
494 }
495
496 // Simulator and APM setup.
497 void SetUp() override {
498 // Lambda function for setting the default APM runtime settings for desktop.
499 auto set_default_desktop_apm_runtime_settings = [](AudioProcessing* apm) {
500 ASSERT_EQ(apm->kNoError, apm->level_estimator()->Enable(true));
501 ASSERT_EQ(apm->kNoError, apm->gain_control()->Enable(true));
502 ASSERT_EQ(apm->kNoError,
503 apm->gain_control()->set_mode(GainControl::kAdaptiveAnalog));
504 ASSERT_EQ(apm->kNoError, apm->gain_control()->Enable(true));
505 ASSERT_EQ(apm->kNoError, apm->noise_suppression()->Enable(true));
506 ASSERT_EQ(apm->kNoError, apm->voice_detection()->Enable(true));
507 ASSERT_EQ(apm->kNoError, apm->echo_control_mobile()->Enable(false));
508 ASSERT_EQ(apm->kNoError, apm->echo_cancellation()->Enable(true));
509 ASSERT_EQ(apm->kNoError, apm->echo_cancellation()->enable_metrics(true));
510 ASSERT_EQ(apm->kNoError,
511 apm->echo_cancellation()->enable_delay_logging(true));
512 };
513
514 // Lambda function for setting the default APM runtime settings for mobile.
515 auto set_default_mobile_apm_runtime_settings = [](AudioProcessing* apm) {
516 ASSERT_EQ(apm->kNoError, apm->level_estimator()->Enable(true));
517 ASSERT_EQ(apm->kNoError, apm->gain_control()->Enable(true));
518 ASSERT_EQ(apm->kNoError,
519 apm->gain_control()->set_mode(GainControl::kAdaptiveAnalog));
520 ASSERT_EQ(apm->kNoError, apm->gain_control()->Enable(true));
521 ASSERT_EQ(apm->kNoError, apm->noise_suppression()->Enable(true));
522 ASSERT_EQ(apm->kNoError, apm->voice_detection()->Enable(true));
523 ASSERT_EQ(apm->kNoError, apm->echo_control_mobile()->Enable(true));
524 ASSERT_EQ(apm->kNoError, apm->echo_cancellation()->Enable(false));
525 };
526
527 // Lambda function for turning off all of the APM runtime settings
528 // submodules.
529 auto turn_off_default_apm_runtime_settings = [](AudioProcessing* apm) {
530 ASSERT_EQ(apm->kNoError, apm->level_estimator()->Enable(false));
531 ASSERT_EQ(apm->kNoError, apm->gain_control()->Enable(false));
532 ASSERT_EQ(apm->kNoError,
533 apm->gain_control()->set_mode(GainControl::kAdaptiveAnalog));
534 ASSERT_EQ(apm->kNoError, apm->gain_control()->Enable(false));
535 ASSERT_EQ(apm->kNoError, apm->noise_suppression()->Enable(false));
536 ASSERT_EQ(apm->kNoError, apm->voice_detection()->Enable(false));
537 ASSERT_EQ(apm->kNoError, apm->echo_control_mobile()->Enable(false));
538 ASSERT_EQ(apm->kNoError, apm->echo_cancellation()->Enable(false));
539 ASSERT_EQ(apm->kNoError, apm->echo_cancellation()->enable_metrics(false));
540 ASSERT_EQ(apm->kNoError,
541 apm->echo_cancellation()->enable_delay_logging(false));
542 };
543
544 // Lambda function for adding default desktop APM settings to a config.
545 auto add_default_desktop_config = [](Config* config) {
546 config->Set<ExtendedFilter>(new ExtendedFilter(true));
547 config->Set<DelayAgnostic>(new DelayAgnostic(true));
548 };
549
550 // Lambda function for adding beamformer settings to a config.
551 auto add_beamformer_config = [](Config* config) {
552 const size_t num_mics = 2;
553 const std::vector<Point> array_geometry =
554 ParseArrayGeometry("0 0 0 0.05 0 0", num_mics);
555 RTC_CHECK_EQ(array_geometry.size(), num_mics);
556
557 config->Set<Beamforming>(
558 new Beamforming(true, array_geometry,
559 SphericalPointf(DegreesToRadians(90), 0.f, 1.f)));
560 };
561
562 int num_capture_channels = 1;
563 switch (simulation_config_.simulation_settings) {
564 case SettingsType::kDefaultApmMobile: {
565 apm_.reset(AudioProcessingImpl::Create());
566 ASSERT_TRUE(!!apm_);
567 set_default_mobile_apm_runtime_settings(apm_.get());
568 break;
569 }
570 case SettingsType::kDefaultApmDesktop: {
571 Config config;
572 add_default_desktop_config(&config);
573 apm_.reset(AudioProcessingImpl::Create(config));
574 ASSERT_TRUE(!!apm_);
575 set_default_desktop_apm_runtime_settings(apm_.get());
576 apm_->SetExtraOptions(config);
577 break;
578 }
579 case SettingsType::kDefaultApmDesktopAndBeamformer: {
580 Config config;
581 add_beamformer_config(&config);
582 add_default_desktop_config(&config);
583 apm_.reset(AudioProcessingImpl::Create(config));
584 ASSERT_TRUE(!!apm_);
585 set_default_desktop_apm_runtime_settings(apm_.get());
586 apm_->SetExtraOptions(config);
587 num_capture_channels = 2;
588 break;
589 }
590 case SettingsType::kDefaultApmDesktopAndIntelligibilityEnhancer: {
591 Config config;
592 config.Set<Intelligibility>(new Intelligibility(true));
593 add_default_desktop_config(&config);
594 apm_.reset(AudioProcessingImpl::Create(config));
595 ASSERT_TRUE(!!apm_);
596 set_default_desktop_apm_runtime_settings(apm_.get());
597 apm_->SetExtraOptions(config);
598 break;
599 }
600 case SettingsType::kAllSubmodulesTurnedOff: {
601 apm_.reset(AudioProcessingImpl::Create());
602 ASSERT_TRUE(!!apm_);
603 turn_off_default_apm_runtime_settings(apm_.get());
604 break;
605 }
606 case SettingsType::kDefaultDesktopApmWithoutDelayAgnostic: {
607 Config config;
608 config.Set<ExtendedFilter>(new ExtendedFilter(true));
609 config.Set<DelayAgnostic>(new DelayAgnostic(false));
610 apm_.reset(AudioProcessingImpl::Create(config));
611 ASSERT_TRUE(!!apm_);
612 set_default_desktop_apm_runtime_settings(apm_.get());
613 apm_->SetExtraOptions(config);
614 break;
615 }
616 case SettingsType::kDefaultDesktopApmWithoutExtendedFilter: {
617 Config config;
618 config.Set<ExtendedFilter>(new ExtendedFilter(false));
619 config.Set<DelayAgnostic>(new DelayAgnostic(true));
620 apm_.reset(AudioProcessingImpl::Create(config));
621 ASSERT_TRUE(!!apm_);
622 set_default_desktop_apm_runtime_settings(apm_.get());
623 apm_->SetExtraOptions(config);
624 break;
625 }
626 }
627
628 render_thread_state_.reset(new TimedThreadApiProcessor(
629 ProcessorType::kRender, &rand_gen_, &frame_counters_,
630 &capture_call_checker_, this, &simulation_config_, apm_.get(),
631 kMinNumFramesToProcess, kRenderInputFloatLevel, 1));
632 capture_thread_state_.reset(new TimedThreadApiProcessor(
633 ProcessorType::kCapture, &rand_gen_, &frame_counters_,
634 &capture_call_checker_, this, &simulation_config_, apm_.get(),
635 kMinNumFramesToProcess, kCaptureInputFloatLevel, num_capture_channels));
636 }
637
638 // Thread callback for the render thread.
639 static bool RenderProcessorThreadFunc(void* context) {
640 return reinterpret_cast<CallSimulator*>(context)
641 ->render_thread_state_->Process();
642 }
643
644 // Thread callback for the capture thread.
645 static bool CaptureProcessorThreadFunc(void* context) {
646 return reinterpret_cast<CallSimulator*>(context)
647 ->capture_thread_state_->Process();
648 }
649
650 // Start the threads used in the test.
651 void StartThreads() {
652 ASSERT_NO_FATAL_FAILURE(render_thread_->Start());
653 render_thread_->SetPriority(kRealtimePriority);
654 ASSERT_NO_FATAL_FAILURE(capture_thread_->Start());
655 capture_thread_->SetPriority(kRealtimePriority);
656 }
657
658 // Event handler for the test.
659 const rtc::scoped_ptr<EventWrapper> test_complete_;
660
661 // Thread related variables.
662 rtc::scoped_ptr<ThreadWrapper> render_thread_;
663 rtc::scoped_ptr<ThreadWrapper> capture_thread_;
664 test::Random rand_gen_;
665
666 rtc::scoped_ptr<AudioProcessing> apm_;
667 const SimulationConfig simulation_config_;
668 FrameCounters frame_counters_;
669 LockedFlag capture_call_checker_;
670 rtc::scoped_ptr<TimedThreadApiProcessor> render_thread_state_;
671 rtc::scoped_ptr<TimedThreadApiProcessor> capture_thread_state_;
672 };
673
674 // Implements the callback functionality for the threads.
675 bool TimedThreadApiProcessor::Process() {
676 PrepareFrame();
677
678 // Wait in a spinlock manner until it is ok to start processing.
679 // Note that SleepMs is not applicable since it only allows sleeping
680 // on a millisecond basis which is too long.
681 while (!ReadyToProcess()) {
682 }
683
684 int result = AudioProcessing::kNoError;
685 switch (processor_type_) {
686 case ProcessorType::kRender:
687 result = ProcessRender();
688 break;
689 case ProcessorType::kCapture:
690 result = ProcessCapture();
691 break;
692 }
693
694 EXPECT_EQ(result, AudioProcessing::kNoError);
695
696 test_->MaybeEndTest();
697
698 return true;
699 }
700
701 const float CallSimulator::kRenderInputFloatLevel = 0.5f;
702 const float CallSimulator::kCaptureInputFloatLevel = 0.03125f;
703 } // anonymous namespace
704
705 TEST_P(CallSimulator, ApiCallDurationTest) {
706 // Run test and verify that it did not time out.
707 EXPECT_EQ(kEventSignaled, Run());
708 }
709
710 INSTANTIATE_TEST_CASE_P(
711 AudioProcessingPerformanceTest,
712 CallSimulator,
713 ::testing::ValuesIn(SimulationConfig::GenerateSimulationConfigs()));
714
715 } // namespace webrtc
OLDNEW
« no previous file with comments | « no previous file | webrtc/webrtc_tests.gypi » ('j') | webrtc/webrtc_tests.gypi » ('J')

Powered by Google App Engine
This is Rietveld 408576698