OLD | NEW |
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 Loading... |
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 |
OLD | NEW |