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

Unified 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, 8 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « media/audio/fake_audio_consumer.cc ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: media/audio/fake_audio_consumer_unittest.cc
diff --git a/media/audio/fake_audio_consumer_unittest.cc b/media/audio/fake_audio_consumer_unittest.cc
index 362686cd6fb01b9d3887ef99b0e052339c337a30..39f99a8fa1a3c744438146b018e9c64cf9a1b5cd 100644
--- a/media/audio/fake_audio_consumer_unittest.cc
+++ b/media/audio/fake_audio_consumer_unittest.cc
@@ -2,18 +2,39 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <cmath>
+
#include "base/bind.h"
+#include "base/command_line.h"
#include "base/message_loop.h"
+#include "base/rand_util.h"
+#include "base/run_loop.h"
+#include "base/string_number_conversions.h"
+#include "base/string_util.h"
+#include "base/stringprintf.h"
#include "base/time.h"
#include "media/audio/audio_buffers_state.h"
#include "media/audio/fake_audio_consumer.h"
#include "media/audio/simple_sources.h"
+#include "media/base/audio_converter.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace media {
static const int kTestCallbacks = 5;
+// Switch to choose the runtime for the jitter test.
+static const char kJitterRunTime[] = "jitter-runtime";
+static const int kDefaultJitterRunTimeSeconds = 2;
+
+// Switch to choose the buffer size or to emulate an OS for output buffer size.
+// Valid values are <size_t>, WIN, MAC, LINUX.
+static const char kJitterOutputSize[] = "jitter-output-size";
+
+// Input buffer size.
+static const char kJitterInputSize[] = "jitter-input-size";
+static const int kDefaultJitterInputBufferSize = 2048;
+
class FakeAudioConsumerTest : public testing::Test {
public:
FakeAudioConsumerTest()
@@ -139,4 +160,174 @@ TEST_F(FakeAudioConsumerTest, StartStopClearsCallbacks) {
message_loop_.Run();
}
+class JitterTest : public testing::Test, public AudioConverter::InputCallback {
+ public:
+ enum BufferSizeChoice { kCustom, kMac, kWin, kLinux };
+
+ JitterTest() {
+ std::string output_size(
+ CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+ kJitterOutputSize));
+ if (LowerCaseEqualsASCII(output_size, "win")) {
+ buffer_size_choice_ = kWin;
+ } else if (LowerCaseEqualsASCII(output_size, "linux")) {
+ buffer_size_choice_ = kLinux;
+ } else if (LowerCaseEqualsASCII(output_size, "mac")) {
+ buffer_size_choice_ = kMac;
+ } else if (base::StringToInt(output_size, &custom_output_buffer_size_)) {
+ buffer_size_choice_ = kCustom;
+ } else {
+ buffer_size_choice_ = kCustom;
+ custom_output_buffer_size_ = kDefaultJitterInputBufferSize;
+ }
+
+ std::string input_size(
+ CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+ kJitterInputSize));
+ if (!base::StringToInt(input_size, &input_buffer_size_))
+ input_buffer_size_ = kDefaultJitterInputBufferSize;
+
+ std::string jitter_run_time(
+ CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+ kJitterRunTime));
+ if (!base::StringToInt(jitter_run_time, &jitter_run_time_secs_))
+ jitter_run_time_secs_ = kDefaultJitterRunTimeSeconds;
+ }
+
+ virtual ~JitterTest() {}
+
+ base::TimeDelta ExpectedTimeBetweenCallbacks(const AudioParameters& params) {
+ return base::TimeDelta::FromMicroseconds(
+ params.frames_per_buffer() * base::Time::kMicrosecondsPerSecond /
+ static_cast<float>(params.sample_rate()));
+ }
+
+ int ChooseOutputBufferSize(int output_sample_rate) {
+ switch (buffer_size_choice_) {
+ case kCustom:
+ return custom_output_buffer_size_;
+ case kMac: {
+ int buffer_size = 128;
+ if (output_sample_rate > 48000) {
+ // The default buffer size is too small for higher sample rates and
+ // may lead to glitching. Adjust upwards by multiples of the default
+ // size.
+ if (output_sample_rate <= 96000)
+ buffer_size *= 2;
+ else if (output_sample_rate <= 192000)
+ buffer_size *= 4;
+ }
+ return buffer_size;
+ }
+ case kWin:
+ return output_sample_rate / 100;
+ case kLinux:
+ return 512;
+ }
+ }
+
+ int ChooseInputBufferSize(float input_sample_rate, int output_buffer_size,
+ float output_sample_rate) {
+ return input_buffer_size_;
+ }
+
+ virtual double ProvideInput(AudioBus* audio_bus,
+ base::TimeDelta buffer_delay) {
+ if (first_run_) {
+ first_run_ = false;
+ last_call_ = base::Time::Now();
+ } else {
+ base::Time now = base::Time::Now();
+ time_between_callbacks_.push_back(now - last_call_);
+ last_call_ = now;
+ }
+
+ if (base::Time::Now() - start_ >
+ base::TimeDelta::FromSeconds(jitter_run_time_secs_)) {
+ consumer_->Stop();
+ run_loop_->Quit();
+ }
+
+ return 0;
+ }
+
+ protected:
+ MessageLoop message_loop_;
+ base::Time last_call_;
+ base::Time start_;
+ std::vector<base::TimeDelta> time_between_callbacks_;
+ scoped_ptr<FakeAudioConsumer> consumer_;
+ scoped_ptr<base::RunLoop> run_loop_;
+ bool first_run_;
+ BufferSizeChoice buffer_size_choice_;
+ int input_buffer_size_;
+ int custom_output_buffer_size_;
+ int jitter_run_time_secs_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(JitterTest);
+};
+
+TEST_F(JitterTest, Jitter) {
+ static const int kInputRates[] =
+ { 44100, 48000 };
+ static const int kOutputRates[] =
+ { 16000, 44100, 48000, 96000, 192000 };
+
+ MessageLoop message_loop;
+ for (size_t i = 0; i < arraysize(kInputRates); ++i) {
+ for (size_t j = 0; j < arraysize(kOutputRates); ++j) {
+ const int output_buffer_size = ChooseOutputBufferSize(kOutputRates[j]);
+ const int input_buffer_size = ChooseInputBufferSize(
+ kInputRates[i], output_buffer_size, kOutputRates[j]);
+
+ const AudioParameters input_params(
+ AudioParameters::AUDIO_FAKE, CHANNEL_LAYOUT_STEREO,
+ kInputRates[i], 16, input_buffer_size);
+ const AudioParameters output_params(
+ AudioParameters::AUDIO_FAKE, CHANNEL_LAYOUT_STEREO,
+ kOutputRates[j], 16, output_buffer_size);
+
+ consumer_.reset(new FakeAudioConsumer(
+ message_loop.message_loop_proxy(), output_params));
+ AudioConverter converter(input_params, output_params, false);
+ converter.AddInput(this);
+ consumer_->Start(
+ base::Bind(&AudioConverter::Convert, base::Unretained(&converter)));
+ run_loop_.reset(new base::RunLoop());
+ start_ = base::Time::Now();
+ first_run_ = true;
+ run_loop_->Run();
+
+ base::TimeDelta min = base::TimeDelta::FromSeconds(10000);
+ base::TimeDelta max = base::TimeDelta::FromSeconds(-10000);
+ base::TimeDelta avg;
+ int bad = 0;
+ for (size_t k = 0; k < time_between_callbacks_.size(); ++k) {
+ base::TimeDelta sample = time_between_callbacks_[k];
+ if (sample < min)
+ min = sample;
+ else if (sample > max)
+ max = sample;
+ avg += sample;
+ if (sample < base::TimeDelta::FromMilliseconds(5))
+ bad++;
+ }
+ avg /= time_between_callbacks_.size();
+
+ printf(
+ "rate=%d -> %d, size=%d -> %d, %d callbacks, %d bad, min=%f, "
+ "max=%f, avg=%f, expected=%f\n",
+ input_params.sample_rate(), output_params.sample_rate(),
+ input_params.frames_per_buffer(), output_params.frames_per_buffer(),
+ static_cast<int>(time_between_callbacks_.size()), bad,
+ min.InMillisecondsF(), max.InMillisecondsF(), avg.InMillisecondsF(),
+ ExpectedTimeBetweenCallbacks(input_params).InMillisecondsF());
+
+ time_between_callbacks_.clear();
+
+ }
+ }
+}
+
} // namespace media
« 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