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

Side by Side Diff: media/audio/fake_audio_consumer_unittest.cc

Issue 14570002: Simple Jitter Test for AudioConverter. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 7 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 | Annotate | Revision Log
« no previous file with comments | « media/audio/fake_audio_consumer.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <cmath>
6
5 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/command_line.h"
6 #include "base/message_loop.h" 9 #include "base/message_loop.h"
10 #include "base/rand_util.h"
11 #include "base/run_loop.h"
12 #include "base/string_number_conversions.h"
13 #include "base/string_util.h"
14 #include "base/stringprintf.h"
7 #include "base/time.h" 15 #include "base/time.h"
8 #include "media/audio/audio_buffers_state.h" 16 #include "media/audio/audio_buffers_state.h"
9 #include "media/audio/fake_audio_consumer.h" 17 #include "media/audio/fake_audio_consumer.h"
10 #include "media/audio/simple_sources.h" 18 #include "media/audio/simple_sources.h"
19 #include "media/base/audio_converter.h"
11 #include "testing/gtest/include/gtest/gtest.h" 20 #include "testing/gtest/include/gtest/gtest.h"
12 21
13 namespace media { 22 namespace media {
14 23
15 static const int kTestCallbacks = 5; 24 static const int kTestCallbacks = 5;
16 25
26 // Switch to choose the runtime for the jitter test.
27 static const char kJitterRunTime[] = "jitter-runtime";
28 static const int kDefaultJitterRunTimeSeconds = 2;
29
30 // Switch to choose the buffer size or to emulate an OS for output buffer size.
31 // Valid values are <size_t>, WIN, MAC, LINUX.
32 static const char kJitterOutputSize[] = "jitter-output-size";
33
34 // Input buffer size.
35 static const char kJitterInputSize[] = "jitter-input-size";
36 static const int kDefaultJitterInputBufferSize = 2048;
37
17 class FakeAudioConsumerTest : public testing::Test { 38 class FakeAudioConsumerTest : public testing::Test {
18 public: 39 public:
19 FakeAudioConsumerTest() 40 FakeAudioConsumerTest()
20 : params_( 41 : params_(
21 AudioParameters::AUDIO_FAKE, CHANNEL_LAYOUT_STEREO, 44100, 8, 128), 42 AudioParameters::AUDIO_FAKE, CHANNEL_LAYOUT_STEREO, 44100, 8, 128),
22 fake_consumer_(message_loop_.message_loop_proxy(), params_), 43 fake_consumer_(message_loop_.message_loop_proxy(), params_),
23 source_(params_.channels(), 200.0, params_.sample_rate()) { 44 source_(params_.channels(), 200.0, params_.sample_rate()) {
24 time_between_callbacks_ = base::TimeDelta::FromMicroseconds( 45 time_between_callbacks_ = base::TimeDelta::FromMicroseconds(
25 params_.frames_per_buffer() * base::Time::kMicrosecondsPerSecond / 46 params_.frames_per_buffer() * base::Time::kMicrosecondsPerSecond /
26 static_cast<float>(params_.sample_rate())); 47 static_cast<float>(params_.sample_rate()));
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
132 // Issue a Stop() / Start() in between expected callbacks to maximize the 153 // Issue a Stop() / Start() in between expected callbacks to maximize the
133 // chance of catching the FakeAudioOutputStream doing the wrong thing. 154 // chance of catching the FakeAudioOutputStream doing the wrong thing.
134 message_loop_.PostDelayedTask(FROM_HERE, base::Bind( 155 message_loop_.PostDelayedTask(FROM_HERE, base::Bind(
135 &FakeAudioConsumerTest::StopStartOnAudioThread, 156 &FakeAudioConsumerTest::StopStartOnAudioThread,
136 base::Unretained(this)), time_between_callbacks_ / 2); 157 base::Unretained(this)), time_between_callbacks_ / 2);
137 158
138 // EndTest() will ensure the proper number of callbacks have occurred. 159 // EndTest() will ensure the proper number of callbacks have occurred.
139 message_loop_.Run(); 160 message_loop_.Run();
140 } 161 }
141 162
163 class JitterTest : public testing::Test, public AudioConverter::InputCallback {
164 public:
165 enum BufferSizeChoice { kCustom, kMac, kWin, kLinux };
166
167 JitterTest() {
168 std::string output_size(
169 CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
170 kJitterOutputSize));
171 if (LowerCaseEqualsASCII(output_size, "win")) {
172 buffer_size_choice_ = kWin;
173 } else if (LowerCaseEqualsASCII(output_size, "linux")) {
174 buffer_size_choice_ = kLinux;
175 } else if (LowerCaseEqualsASCII(output_size, "mac")) {
176 buffer_size_choice_ = kMac;
177 } else if (base::StringToInt(output_size, &custom_output_buffer_size_)) {
178 buffer_size_choice_ = kCustom;
179 } else {
180 buffer_size_choice_ = kCustom;
181 custom_output_buffer_size_ = kDefaultJitterInputBufferSize;
182 }
183
184 std::string input_size(
185 CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
186 kJitterInputSize));
187 if (!base::StringToInt(input_size, &input_buffer_size_))
188 input_buffer_size_ = kDefaultJitterInputBufferSize;
189
190 std::string jitter_run_time(
191 CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
192 kJitterRunTime));
193 if (!base::StringToInt(jitter_run_time, &jitter_run_time_secs_))
194 jitter_run_time_secs_ = kDefaultJitterRunTimeSeconds;
195 }
196
197 virtual ~JitterTest() {}
198
199 base::TimeDelta ExpectedTimeBetweenCallbacks(const AudioParameters& params) {
200 return base::TimeDelta::FromMicroseconds(
201 params.frames_per_buffer() * base::Time::kMicrosecondsPerSecond /
202 static_cast<float>(params.sample_rate()));
203 }
204
205 int ChooseOutputBufferSize(int output_sample_rate) {
206 switch (buffer_size_choice_) {
207 case kCustom:
208 return custom_output_buffer_size_;
209 case kMac: {
210 int buffer_size = 128;
211 if (output_sample_rate > 48000) {
212 // The default buffer size is too small for higher sample rates and
213 // may lead to glitching. Adjust upwards by multiples of the default
214 // size.
215 if (output_sample_rate <= 96000)
216 buffer_size *= 2;
217 else if (output_sample_rate <= 192000)
218 buffer_size *= 4;
219 }
220 return buffer_size;
221 }
222 case kWin:
223 return output_sample_rate / 100;
224 case kLinux:
225 return 512;
226 }
227 }
228
229 int ChooseInputBufferSize(float input_sample_rate, int output_buffer_size,
230 float output_sample_rate) {
231 return input_buffer_size_;
232 }
233
234 virtual double ProvideInput(AudioBus* audio_bus,
235 base::TimeDelta buffer_delay) {
236 if (first_run_) {
237 first_run_ = false;
238 last_call_ = base::Time::Now();
239 } else {
240 base::Time now = base::Time::Now();
241 time_between_callbacks_.push_back(now - last_call_);
242 last_call_ = now;
243 }
244
245 if (base::Time::Now() - start_ >
246 base::TimeDelta::FromSeconds(jitter_run_time_secs_)) {
247 consumer_->Stop();
248 run_loop_->Quit();
249 }
250
251 return 0;
252 }
253
254 protected:
255 MessageLoop message_loop_;
256 base::Time last_call_;
257 base::Time start_;
258 std::vector<base::TimeDelta> time_between_callbacks_;
259 scoped_ptr<FakeAudioConsumer> consumer_;
260 scoped_ptr<base::RunLoop> run_loop_;
261 bool first_run_;
262 BufferSizeChoice buffer_size_choice_;
263 int input_buffer_size_;
264 int custom_output_buffer_size_;
265 int jitter_run_time_secs_;
266
267 private:
268 DISALLOW_COPY_AND_ASSIGN(JitterTest);
269 };
270
271 TEST_F(JitterTest, Jitter) {
272 static const int kInputRates[] =
273 { 44100, 48000 };
274 static const int kOutputRates[] =
275 { 16000, 44100, 48000, 96000, 192000 };
276
277 MessageLoop message_loop;
278 for (size_t i = 0; i < arraysize(kInputRates); ++i) {
279 for (size_t j = 0; j < arraysize(kOutputRates); ++j) {
280 const int output_buffer_size = ChooseOutputBufferSize(kOutputRates[j]);
281 const int input_buffer_size = ChooseInputBufferSize(
282 kInputRates[i], output_buffer_size, kOutputRates[j]);
283
284 const AudioParameters input_params(
285 AudioParameters::AUDIO_FAKE, CHANNEL_LAYOUT_STEREO,
286 kInputRates[i], 16, input_buffer_size);
287 const AudioParameters output_params(
288 AudioParameters::AUDIO_FAKE, CHANNEL_LAYOUT_STEREO,
289 kOutputRates[j], 16, output_buffer_size);
290
291 consumer_.reset(new FakeAudioConsumer(
292 message_loop.message_loop_proxy(), output_params));
293 AudioConverter converter(input_params, output_params, false);
294 converter.AddInput(this);
295 consumer_->Start(
296 base::Bind(&AudioConverter::Convert, base::Unretained(&converter)));
297 run_loop_.reset(new base::RunLoop());
298 start_ = base::Time::Now();
299 first_run_ = true;
300 run_loop_->Run();
301
302 base::TimeDelta min = base::TimeDelta::FromSeconds(10000);
303 base::TimeDelta max = base::TimeDelta::FromSeconds(-10000);
304 base::TimeDelta avg;
305 int bad = 0;
306 for (size_t k = 0; k < time_between_callbacks_.size(); ++k) {
307 base::TimeDelta sample = time_between_callbacks_[k];
308 if (sample < min)
309 min = sample;
310 else if (sample > max)
311 max = sample;
312 avg += sample;
313 if (sample < base::TimeDelta::FromMilliseconds(5))
314 bad++;
315 }
316 avg /= time_between_callbacks_.size();
317
318 printf(
319 "rate=%d -> %d, size=%d -> %d, %d callbacks, %d bad, min=%f, "
320 "max=%f, avg=%f, expected=%f\n",
321 input_params.sample_rate(), output_params.sample_rate(),
322 input_params.frames_per_buffer(), output_params.frames_per_buffer(),
323 static_cast<int>(time_between_callbacks_.size()), bad,
324 min.InMillisecondsF(), max.InMillisecondsF(), avg.InMillisecondsF(),
325 ExpectedTimeBetweenCallbacks(input_params).InMillisecondsF());
326
327 time_between_callbacks_.clear();
328
329 }
330 }
331 }
332
142 } // namespace media 333 } // namespace media
OLDNEW
« no previous file with comments | « media/audio/fake_audio_consumer.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698