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

Side by Side Diff: webrtc/modules/audio_processing/audio_processing_lock_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: Various changes making the test test what is desired. 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) 2014 The WebRTC project authors. All Rights Reserved.
hlundin-webrtc 2015/11/13 12:18:32 2015
peah-webrtc 2015/11/18 10:27:26 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 #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/config.h"
21 #include "webrtc/modules/audio_processing/test/test_utils.h"
22 #include "webrtc/modules/include/module_common_types.h"
23 #include "webrtc/system_wrappers/include/clock.h"
24 #include "webrtc/system_wrappers/include/event_wrapper.h"
25 #include "webrtc/system_wrappers/include/sleep.h"
26 #include "webrtc/system_wrappers/include/thread_wrapper.h"
27 #include "webrtc/test/random.h"
28 #include "webrtc/test/testsupport/perf_test.h"
29
30 namespace webrtc {
31
32 namespace {
33
34 class CallSimulator;
35
36 // Populates a float audio frame with random data.
hlundin-webrtc 2015/11/13 12:18:31 It seems to populate more than one frame. Make the
peah-webrtc 2015/11/18 10:27:26 It supports multiple channel frames, and I think i
37 void PopulateAudioFrame(float** frame,
hlundin-webrtc 2015/11/13 12:18:31 frame is an output parameter, it should go last in
peah-webrtc 2015/11/18 10:27:27 Done.
38 float amplitude,
39 size_t num_channels,
40 size_t samples_per_channel,
41 test::Random* rand_gen) {
42 for (size_t ch = 0; ch < num_channels; ch++) {
43 for (size_t k = 0; k < samples_per_channel; k++) {
44 // Store random 16 bit quantized float number between +-amplitude.
hlundin-webrtc 2015/11/13 12:18:32 Where does the 16-bit quantization happen? Is it i
peah-webrtc 2015/11/18 10:27:27 Sorry, that comment is completely wrong! Removed i
45 frame[ch][k] = amplitude * (2 * rand_gen->Rand<float>() - 1);
46 }
47 }
48 }
49
50 // Variant of echo canceller settings to use in the test.
51 enum class AecType { BasicWebRtcAecSettings, BasicWebRtcAecmSettings };
52
53 // Variables related to the audio data and formats.
54 struct AudioFrameData {
55 explicit AudioFrameData(int max_frame_size) {
hlundin-webrtc 2015/11/13 12:18:32 size_t
peah-webrtc 2015/11/18 10:27:26 Done.
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,
79 AecType aec_type,
80 int min_number_of_calls,
81 bool use_realtime_simulation)
82 : sample_rate_hz(sample_rate_hz),
83 aec_type(aec_type),
84 min_number_of_calls(min_number_of_calls),
85 use_realtime_simulation(use_realtime_simulation) {}
86 int sample_rate_hz = 16000;
87 AecType aec_type = AecType::BasicWebRtcAecSettings;
88 int min_number_of_calls = 300;
89 bool use_realtime_simulation;
hlundin-webrtc 2015/11/13 12:18:32 All members but this one has default values.
peah-webrtc 2015/11/18 10:27:26 Done.
90 };
91
92 // Handler for the frame counters.
93 class FrameCounters {
94 public:
95 int IncreaseRenderCounter() {
96 rtc::CritScope cs(&crit_);
97 render_count++;
98 return render_count;
99 }
100
101 int IncreaseCaptureCounter() {
102 rtc::CritScope cs(&crit_);
103 capture_count++;
104 return capture_count;
105 }
106
107 int GetCaptureCounter() {
108 rtc::CritScope cs(&crit_);
109 return capture_count;
110 }
111
112 int GetRenderCounter() {
113 rtc::CritScope cs(&crit_);
114 return render_count;
115 }
116
117 int CaptureMinusRenderCounters() {
118 rtc::CritScope cs(&crit_);
119 return capture_count - render_count;
120 }
121
122 int RenderMinusCaptureCounters() {
hlundin-webrtc 2015/11/13 12:18:32 Do you need both "minus" methods? And if you do, y
peah-webrtc 2015/11/18 10:27:25 It is mainly for convenience and to (tiny) increas
123 rtc::CritScope cs(&crit_);
124 return render_count - capture_count;
125 }
126
127 bool BothCountersExceedeThreshold(int threshold) {
128 rtc::CritScope cs(&crit_);
129 return (render_count > threshold && capture_count > threshold);
130 }
131
132 private:
133 rtc::CriticalSection crit_;
134 int render_count GUARDED_BY(crit_) = 0;
hlundin-webrtc 2015/11/13 12:18:32 Trailing underscore on both counter variables.
peah-webrtc 2015/11/18 10:27:26 Done.
135 int capture_count GUARDED_BY(crit_) = 0;
136 };
137
138 // Checker for whether the capture side has been called.
139 class CaptureSideCalledChecker {
hlundin-webrtc 2015/11/13 12:18:32 Generalize the name to make it shorter. Nothing wi
peah-webrtc 2015/11/18 10:27:26 Good point! I called it LockedFlag since it is doe
140 public:
141 bool CaptureSideCalled() {
hlundin-webrtc 2015/11/13 12:18:32 This is a simple "getter" function, albeit with a
peah-webrtc 2015/11/18 10:27:26 Done.
142 rtc::CritScope cs(&crit_);
143 return capture_side_called_;
144 }
145
146 void FlagCaptureSideCalled() {
hlundin-webrtc 2015/11/13 12:18:32 This is a "setter" with a lock. Name it such: void
peah-webrtc 2015/11/18 10:27:26 Done.
147 rtc::CritScope cs(&crit_);
148 capture_side_called_ = true;
149 }
150
151 private:
152 rtc::CriticalSection crit_;
153 bool capture_side_called_ GUARDED_BY(crit_) = false;
154 };
155
156 // Parent class for the thread processors.
157 class TimedThreadApiProcessor {
158 public:
159 TimedThreadApiProcessor(int max_frame_size,
160 test::Random* rand_gen,
161 FrameCounters* shared_counters_state,
162 CaptureSideCalledChecker* capture_call_checker,
163 CallSimulator* test_framework,
164 SimulationConfig* simulation_config,
165 AudioProcessing* apm,
166 int min_number_of_calls,
167 float input_level);
168 virtual ~TimedThreadApiProcessor() {}
169
170 bool ProcessClocked10msQuantum();
171 std::vector<int64_t> get_api_call_durations() const {
172 return api_call_durations_;
173 }
174 int64_t GetDurationStandardDeviation() const;
175 int64_t GetDurationAverage() const;
176
177 protected:
178 static const int kMaxCallDifference = 10;
179
180 void PrepareFrame();
181 void AddJitter(int max_jitter_microseconds, bool random_jitter);
182 virtual int Process() = 0;
183 virtual bool ReadyToProcess() = 0;
184
185 test::Random* rand_gen_ = nullptr;
186 FrameCounters* frame_counters_ = nullptr;
187 CaptureSideCalledChecker* capture_call_checker_ = nullptr;
188 CallSimulator* test_ = nullptr;
189 SimulationConfig* simulation_config_ = nullptr;
190 AudioProcessing* apm_ = nullptr;
191 AudioFrameData frame_data_;
192 webrtc::Clock* clock_;
193 int num_durations_to_store_;
194 std::vector<int64_t> api_call_durations_;
195 const float input_level_;
196 };
197
198 // Class for handling the capture side processing.
199 class CaptureProcessor : public TimedThreadApiProcessor {
hlundin-webrtc 2015/11/13 12:18:31 Mark this class final.
peah-webrtc 2015/11/18 10:27:26 Done.
200 public:
201 CaptureProcessor(int max_frame_size,
202 test::Random* rand_gen,
203 FrameCounters* shared_counters_state,
204 CaptureSideCalledChecker* capture_call_checker,
205 CallSimulator* test_framework,
206 SimulationConfig* simulation_config,
207 AudioProcessing* apm,
208 int min_number_of_calls,
209 float input_level);
210
211 private:
212 // Overrides from TimedThreadApiProcessor.
213 int Process() override;
214 bool ReadyToProcess() override;
215
216 bool first_capture_side_call_ = true;
217 };
218
219 // Class for handling the render side processing.
220 class RenderProcessor : public TimedThreadApiProcessor {
hlundin-webrtc 2015/11/13 12:18:31 Mark this class final.
peah-webrtc 2015/11/18 10:27:26 Done.
221 public:
222 RenderProcessor(int max_frame_size,
223 test::Random* rand_gen,
224 FrameCounters* shared_counters_state,
225 CaptureSideCalledChecker* capture_call_checker,
226 CallSimulator* test_framework,
227 SimulationConfig* simulation_config,
228 AudioProcessing* apm,
229 int min_number_of_calls,
230 float input_level);
231
232 private:
233 // Overrides from TimedThreadApiProcessor
234 int Process() override;
235 bool ReadyToProcess() override;
236
237 bool first_render_side_call_ = true;
238 };
239
240 // Class for managing the test simulation.
241 class CallSimulator {
hlundin-webrtc 2015/11/13 12:18:32 I think this class should be made a gtest fixture
peah-webrtc 2015/11/18 10:27:26 Done.
242 public:
243 explicit CallSimulator(SimulationConfig simulation_config);
244 EventTypeWrapper Run(int time_out_limit);
245
246 // Tests whether all the required render and capture side calls have been
247 // done.
248 void CheckIfSimulationDone() {
249 if (frame_counters_.BothCountersExceedeThreshold(
250 simulation_config_.min_number_of_calls)) {
251 test_complete_->Set();
252 }
253 }
254
255 const CaptureProcessor* GetCapture() const { return &capture_thread_state_; }
256 const RenderProcessor* GetRender() const { return &render_thread_state_; }
257 void SetUp();
258 void TearDown();
259
260 private:
261 static const int kMaxFrameSize = 480;
262 static const float kCaptureInputFloatLevel;
263 static const float kRenderInputFloatLevel;
264
265 // Thread callback for the render thread.
266 static bool RenderProcessorThreadFunc(void* context) {
267 return reinterpret_cast<CallSimulator*>(context)
268 ->render_thread_state_.ProcessClocked10msQuantum();
269 }
270
271 // Thread callback for the capture thread.
272 static bool CaptureProcessorThreadFunc(void* context) {
273 return reinterpret_cast<CallSimulator*>(context)
274 ->capture_thread_state_.ProcessClocked10msQuantum();
275 }
276
277 // Start the threads used in the test.
278 void StartThreads() {
279 ASSERT_TRUE(render_thread_->Start());
280 render_thread_->SetPriority(kRealtimePriority);
281 ASSERT_TRUE(capture_thread_->Start());
282 capture_thread_->SetPriority(kRealtimePriority);
283 }
284
285 // Event handler for the test.
286 const rtc::scoped_ptr<EventWrapper> test_complete_;
287
288 // Thread related variables.
289 rtc::scoped_ptr<ThreadWrapper> render_thread_;
290 rtc::scoped_ptr<ThreadWrapper> capture_thread_;
291 mutable test::Random rand_gen_;
hlundin-webrtc 2015/11/13 12:18:31 Why is this mutable?
peah-webrtc 2015/11/18 10:27:26 Done.
292
293 rtc::scoped_ptr<AudioProcessing> apm_;
294 SimulationConfig simulation_config_;
295 FrameCounters frame_counters_;
296 CaptureSideCalledChecker capture_call_checker_;
297 RenderProcessor render_thread_state_;
298 CaptureProcessor capture_thread_state_;
299 };
300
301 const float CallSimulator::kRenderInputFloatLevel = 0.5f;
302 const float CallSimulator::kCaptureInputFloatLevel = 0.03125f;
303
304 CallSimulator::CallSimulator(SimulationConfig simulation_config)
305 : test_complete_(EventWrapper::Create()),
306 render_thread_(ThreadWrapper::CreateThread(RenderProcessorThreadFunc,
307 this,
308 "render")),
309 capture_thread_(ThreadWrapper::CreateThread(CaptureProcessorThreadFunc,
310 this,
311 "capture")),
312 rand_gen_(42U),
313 apm_(AudioProcessingImpl::Create()),
hlundin-webrtc 2015/11/13 12:18:31 Create() may return null in case of failure. You c
peah-webrtc 2015/11/18 10:27:26 Done.
314 simulation_config_(simulation_config),
315 render_thread_state_(kMaxFrameSize,
316 &rand_gen_,
317 &frame_counters_,
318 &capture_call_checker_,
319 this,
320 &simulation_config_,
321 apm_.get(),
322 simulation_config_.min_number_of_calls,
323 kRenderInputFloatLevel),
324 capture_thread_state_(kMaxFrameSize,
325 &rand_gen_,
326 &frame_counters_,
327 &capture_call_checker_,
328 this,
329 &simulation_config_,
330 apm_.get(),
331 simulation_config_.min_number_of_calls,
332 kCaptureInputFloatLevel) {}
333
334 // Run the call simulation with a timeout.
335 EventTypeWrapper CallSimulator::Run(int time_out_limit) {
336 SetUp();
337 StartThreads();
hlundin-webrtc 2015/11/13 12:18:31 You should make sure that none of the ASSERT_TRUEs
peah-webrtc 2015/11/18 10:27:26 Done.
338 EventTypeWrapper result = test_complete_->Wait(time_out_limit);
339 TearDown();
340 return result;
341 }
342
343 // Simulator and APM setup.
344 void CallSimulator::SetUp() {
345 ASSERT_EQ(apm_->kNoError, apm_->level_estimator()->Enable(true));
346 ASSERT_EQ(apm_->kNoError, apm_->gain_control()->Enable(true));
347 ASSERT_EQ(apm_->kNoError,
348 apm_->gain_control()->set_mode(GainControl::kAdaptiveAnalog));
349 ASSERT_EQ(apm_->kNoError, apm_->gain_control()->Enable(true));
350 ASSERT_EQ(apm_->kNoError, apm_->noise_suppression()->Enable(true));
351 ASSERT_EQ(apm_->kNoError, apm_->voice_detection()->Enable(true));
352
353 Config config;
hlundin-webrtc 2015/11/13 12:18:31 Move the declaration down to within the else-claus
peah-webrtc 2015/11/18 10:27:26 Done.
354 if (simulation_config_.aec_type == AecType::BasicWebRtcAecmSettings) {
355 ASSERT_EQ(apm_->kNoError, apm_->echo_control_mobile()->Enable(true));
356 ASSERT_EQ(apm_->kNoError, apm_->echo_cancellation()->Enable(false));
357 } else {
358 ASSERT_EQ(apm_->kNoError, apm_->echo_control_mobile()->Enable(false));
359 ASSERT_EQ(apm_->kNoError, apm_->echo_cancellation()->Enable(true));
360 ASSERT_EQ(apm_->kNoError, apm_->echo_cancellation()->enable_metrics(true));
361 ASSERT_EQ(apm_->kNoError,
362 apm_->echo_cancellation()->enable_delay_logging(true));
363
364 config.Set<ExtendedFilter>(new ExtendedFilter(true));
365 config.Set<DelayAgnostic>(new DelayAgnostic(true));
366 apm_->SetExtraOptions(config);
367 }
368 }
369
370 void CallSimulator::TearDown() {
371 render_thread_->Stop();
372 capture_thread_->Stop();
373 }
374
375 TimedThreadApiProcessor::TimedThreadApiProcessor(
hlundin-webrtc 2015/11/13 12:18:32 I think you can define all the member methods with
peah-webrtc 2015/11/18 10:27:26 Did this on all methods apart from the Process() m
376 int max_frame_size,
377 test::Random* rand_gen,
378 FrameCounters* shared_counters_state,
379 CaptureSideCalledChecker* capture_call_checker,
380 CallSimulator* test_framework,
381 SimulationConfig* simulation_config,
382 AudioProcessing* apm,
383 int num_durations_to_store,
384 float input_level)
385 : rand_gen_(rand_gen),
386 frame_counters_(shared_counters_state),
387 capture_call_checker_(capture_call_checker),
388 test_(test_framework),
389 simulation_config_(simulation_config),
390 apm_(apm),
391 frame_data_(max_frame_size),
hlundin-webrtc 2015/11/13 12:18:31 No need to pass max_frame_size as a parameter; sim
peah-webrtc 2015/11/18 10:27:27 Done.
392 clock_(webrtc::Clock::GetRealTimeClock()),
393 num_durations_to_store_(num_durations_to_store),
394 api_call_durations_(num_durations_to_store_),
395 input_level_(input_level) {}
396
397 // Implements the callback functionality for the threads.
398 bool TimedThreadApiProcessor::ProcessClocked10msQuantum() {
399 PrepareFrame();
400
401 while (!ReadyToProcess()) {
402 AddJitter(2, true);
403 }
404
405 const int64_t start_time = clock_->TimeInMicroseconds();
406 Process();
407 const int64_t end_time = clock_->TimeInMicroseconds();
408 const int duration = static_cast<int>(end_time - start_time);
hlundin-webrtc 2015/11/13 12:18:31 duration_us, to convey the unit.
hlundin-webrtc 2015/11/13 12:18:32 use rtc::checked_cast<int> from base/safe_conversi
peah-webrtc 2015/11/18 10:27:26 Done.
peah-webrtc 2015/11/18 10:27:26 Done.
409 const int time_left_of_10_ms_quantum = 10000 - duration;
410
411 if (simulation_config_->use_realtime_simulation &&
412 time_left_of_10_ms_quantum > 0) {
413 AddJitter(time_left_of_10_ms_quantum, false);
414 }
415
416 test_->CheckIfSimulationDone();
417
418 return true;
419 }
420
421 int64_t TimedThreadApiProcessor::GetDurationStandardDeviation() const {
422 double variance = 0;
423 const int64_t average_duration = GetDurationAverage();
424 for (int64_t duration : api_call_durations_) {
425 int64_t tmp = duration - average_duration;
426 variance += static_cast<double>(tmp * tmp);
427 }
428 return static_cast<int64_t>(sqrt(variance / api_call_durations_.size()));
hlundin-webrtc 2015/11/13 12:18:32 rtc::checked_cast
peah-webrtc 2015/11/18 10:27:27 Done.
429 }
430
431 int64_t TimedThreadApiProcessor::GetDurationAverage() const {
432 int64_t average_duration = 0;
433 for (int64_t duration : api_call_durations_) {
434 average_duration += duration;
435 }
436 return average_duration / api_call_durations_.size();
437 }
438
439 void TimedThreadApiProcessor::PrepareFrame() {
440 // Prepare the audio input data and metadata.
441 frame_data_.input_stream_config.set_sample_rate_hz(
442 simulation_config_->sample_rate_hz);
443 frame_data_.input_stream_config.set_num_channels(1);
444 frame_data_.input_stream_config.set_has_keyboard(false);
445 PopulateAudioFrame(&frame_data_.input_frame[0], input_level_, 1,
446 (simulation_config_->sample_rate_hz *
447 AudioProcessing::kChunkSizeMs / 1000),
448 rand_gen_);
449
450 // Prepare the float audio output data and metadata.
451 frame_data_.output_stream_config.set_sample_rate_hz(
452 simulation_config_->sample_rate_hz);
453 frame_data_.output_stream_config.set_num_channels(1);
454 frame_data_.output_stream_config.set_has_keyboard(false);
455 }
456
457 void TimedThreadApiProcessor::AddJitter(int max_jitter_microseconds,
458 bool random_jitter) {
459 int min_method_duration;
460 if (random_jitter) {
461 min_method_duration = rand_gen_->Rand(0, max_jitter_microseconds);
462 } else {
463 min_method_duration = max_jitter_microseconds;
464 }
465
466 const int64_t start_time = clock_->TimeInMicroseconds();
hlundin-webrtc 2015/11/13 12:18:32 Please, comment on why you cannot just sleep.
peah-webrtc 2015/11/18 10:27:26 Very good point. As I never use this in the test a
467 int sum = 0;
468 while ((clock_->TimeInMicroseconds() - start_time) < min_method_duration) {
469 for (int k = 0; k < 100; ++k)
470 for (int j = 1; j < 100; ++j) {
471 sum += k % j;
472 sum = sum % 79;
473 }
474 if (sum > 100) {
475 printf("Will not be print out, just present in order to ensure");
476 printf("that sum is evaluated by the compiler\n");
477 }
478 }
479 }
480
481 CaptureProcessor::CaptureProcessor(
hlundin-webrtc 2015/11/13 12:18:32 There is a non-negligible overhead associated with
peah-webrtc 2015/11/18 10:27:25 Good point!!! Will implement it like that. Done.
482 int max_frame_size,
483 test::Random* rand_gen,
484 FrameCounters* shared_counters_state,
485 CaptureSideCalledChecker* capture_call_checker,
486 CallSimulator* test_framework,
487 SimulationConfig* simulation_config,
488 AudioProcessing* apm,
489 int num_durations_to_store,
490 float input_level)
491 : TimedThreadApiProcessor(max_frame_size,
492 rand_gen,
493 shared_counters_state,
494 capture_call_checker,
495 test_framework,
496 simulation_config,
497 apm,
498 num_durations_to_store,
499 input_level) {}
500
501 int CaptureProcessor::Process() {
502 // Set the stream delay
503 apm_->set_stream_delay_ms(30);
504
505 // Call and time the specified capture side API processing method.
506 const int64_t start_time = clock_->TimeInMicroseconds();
507 const int result = apm_->ProcessStream(
508 &frame_data_.input_frame[0], frame_data_.input_stream_config,
509 frame_data_.output_stream_config, &frame_data_.output_frame[0]);
510 const int64_t end_time = clock_->TimeInMicroseconds();
511
512 const int new_capture_counter = frame_counters_->IncreaseCaptureCounter();
513
514 if (new_capture_counter <= num_durations_to_store_) {
515 api_call_durations_[new_capture_counter - 1] = end_time - start_time;
hlundin-webrtc 2015/11/13 12:18:32 Why not just api_call_durations_.push_back(...)? Y
peah-webrtc 2015/11/18 10:27:26 Good and very valid point! Done.
516 }
517
518 if (first_capture_side_call_) {
519 // Flag that the capture side has been called at least once
520 // (needed to ensure that a capture call has been done
521 // before the first render call is performed (implicitly
522 // required by the APM API).
523 capture_call_checker_->FlagCaptureSideCalled();
524 first_capture_side_call_ = false;
525 }
526 return result;
527 }
528
529 bool CaptureProcessor::ReadyToProcess() {
530 return (frame_counters_->CaptureMinusRenderCounters() <= kMaxCallDifference);
531 }
532
533 RenderProcessor::RenderProcessor(int max_frame_size,
534 test::Random* rand_gen,
535 FrameCounters* shared_counters_state,
536 CaptureSideCalledChecker* capture_call_checker,
537 CallSimulator* test_framework,
538 SimulationConfig* simulation_config,
539 AudioProcessing* apm,
540 int num_durations_to_store,
541 float input_level)
542 : TimedThreadApiProcessor(max_frame_size,
543 rand_gen,
544 shared_counters_state,
545 capture_call_checker,
546 test_framework,
547 simulation_config,
548 apm,
549 num_durations_to_store,
550 input_level) {}
551
552 int RenderProcessor::Process() {
553 // Call and time the specified render side API processing method.
554 const int64_t start_time = clock_->TimeInMicroseconds();
555 const int result = apm_->ProcessReverseStream(
556 &frame_data_.input_frame[0], frame_data_.input_stream_config,
557 frame_data_.output_stream_config, &frame_data_.output_frame[0]);
558 const int64_t end_time = clock_->TimeInMicroseconds();
559
560 const int new_render_counter = frame_counters_->IncreaseRenderCounter();
561
562 if (new_render_counter <= num_durations_to_store_) {
563 api_call_durations_[new_render_counter - 1] = end_time - start_time;
564 }
565
566 return result;
567 }
568
569 bool RenderProcessor::ReadyToProcess() {
570 // Do not process until at least one capture call has been done.
571 // (implicitly required by the APM API).
572 if (first_render_side_call_ && !capture_call_checker_->CaptureSideCalled()) {
573 return false;
574 }
575
576 // Ensure that the number of render and capture calls do not differ too much.
577 if (frame_counters_->RenderMinusCaptureCounters() > kMaxCallDifference) {
578 return false;
579 }
580
581 first_render_side_call_ = false;
582 return true;
583 }
584
585 // Runs the simulation and reports the results.
586 void RunSimulation(SimulationConfig simulation_config,
587 int timeout,
588 bool print_durations) {
589 // Lambda function for printing out the simulation statistics.
590 auto print_simulation_statistics = [](
591 const TimedThreadApiProcessor* processor, std::string processor_name,
592 bool print_durations) {
593 const std::string modifier = "_api_call_duration";
594
595 // Lambda function for creating a test printout string.
596 auto create_mean_and_variance_string = [](int64_t average,
597 int64_t standard_dev) {
598 std::string s = std::to_string(average);
599 s += ",";
600 s += std::to_string(standard_dev);
601 return s;
602 };
603
604 webrtc::test::PrintResult(processor_name, modifier, "avg,stdev",
605 create_mean_and_variance_string(
606 processor->GetDurationAverage(),
607 processor->GetDurationStandardDeviation()),
608 "ms", false);
609
610 if (print_durations) {
611 std::vector<int64_t> durations = processor->get_api_call_durations();
612 std::string value_string = "";
613 for (int64_t duration : durations) {
614 value_string += std::to_string(duration) + ",";
615 }
616 webrtc::test::PrintResultList(processor_name, modifier, "durations",
617 value_string, "ms", false);
618 }
619 };
620
621 CallSimulator simulator(simulation_config);
622
623 // Run simulation and verify that it did not time out.
624 ASSERT_EQ(EventTypeWrapper::kEventSignaled, simulator.Run(timeout));
hlundin-webrtc 2015/11/13 12:18:32 Maybe EXPECT_EQ instead. It might still be interes
peah-webrtc 2015/11/18 10:27:27 Done.
625
626 print_simulation_statistics(simulator.GetRender(), "render", print_durations);
hlundin-webrtc 2015/11/13 12:18:32 To me it looks like the print_simulation_statistic
peah-webrtc 2015/11/18 10:27:26 Done.
627 print_simulation_statistics(simulator.GetCapture(), "capture",
628 print_durations);
629 }
630
631 const int kMaxFramesToProcess = 300;
632 const int32_t kTestTimeout = 3 * 10 * kMaxFramesToProcess;
633 const bool kUseTimedSimulation = false;
hlundin-webrtc 2015/11/13 12:18:32 I don't think it makes much sense to declare this
peah-webrtc 2015/11/18 10:27:26 Good points and I fully agree. This has been partl
634 const bool kPrintAllDurations = false;
635 } // anonymous namespace
636
637 TEST(AudioProcessingLockPerformanceTest, Aec8kHz) {
638 RunSimulation(SimulationConfig(8000, AecType::BasicWebRtcAecSettings,
639 kMaxFramesToProcess, kUseTimedSimulation),
640 kTestTimeout, kPrintAllDurations);
641 }
642
643 TEST(AudioProcessingLockPerformanceTest, Aec16kHz) {
644 RunSimulation(SimulationConfig(16000, AecType::BasicWebRtcAecSettings,
645 kMaxFramesToProcess, kUseTimedSimulation),
646 kTestTimeout, kPrintAllDurations);
647 }
648
649 TEST(AudioProcessingLockPerformanceTest, Aec32kHz) {
650 RunSimulation(SimulationConfig(32000, AecType::BasicWebRtcAecSettings,
651 kMaxFramesToProcess, kUseTimedSimulation),
652 kTestTimeout, kPrintAllDurations);
653 }
654
655 TEST(AudioProcessingLockPerformanceTest, Aec48kHz) {
656 RunSimulation(SimulationConfig(48000, AecType::BasicWebRtcAecSettings,
657 kMaxFramesToProcess, kUseTimedSimulation),
658 kTestTimeout, kPrintAllDurations);
659 }
660
661 TEST(AudioProcessingLockPerformanceTest, Aecm8kHz) {
662 RunSimulation(SimulationConfig(8000, AecType::BasicWebRtcAecmSettings,
663 kMaxFramesToProcess, true),
664 kTestTimeout, kPrintAllDurations);
665 }
666
667 TEST(AudioProcessingLockPerformanceTest, Aecm16kHz) {
668 RunSimulation(SimulationConfig(16000, AecType::BasicWebRtcAecmSettings,
669 kMaxFramesToProcess, true),
670 kTestTimeout, kPrintAllDurations);
671 }
672 } // 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