summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
Diffstat (limited to 'media')
-rw-r--r--media/base/audio_renderer_mixer.cc85
-rw-r--r--media/base/audio_renderer_mixer.h35
-rw-r--r--media/base/audio_renderer_mixer_input.cc23
-rw-r--r--media/base/audio_renderer_mixer_input.h29
-rw-r--r--media/base/audio_renderer_mixer_input_unittest.cc65
-rw-r--r--media/base/audio_renderer_mixer_unittest.cc306
-rw-r--r--media/base/fake_audio_render_callback.cc29
-rw-r--r--media/base/fake_audio_render_callback.h23
-rw-r--r--media/base/mock_audio_renderer_sink.cc17
-rw-r--r--media/base/mock_audio_renderer_sink.h41
-rw-r--r--media/filters/audio_renderer_impl_unittest.cc23
-rw-r--r--media/media.gyp6
12 files changed, 394 insertions, 288 deletions
diff --git a/media/base/audio_renderer_mixer.cc b/media/base/audio_renderer_mixer.cc
index 5b89aa4..6d23faa 100644
--- a/media/base/audio_renderer_mixer.cc
+++ b/media/base/audio_renderer_mixer.cc
@@ -4,17 +4,35 @@
#include "media/base/audio_renderer_mixer.h"
+#include "base/bind.h"
+#include "base/bind_helpers.h"
#include "base/logging.h"
+#include "media/audio/audio_util.h"
+#include "media/base/limits.h"
namespace media {
AudioRendererMixer::AudioRendererMixer(
- const AudioParameters& params, const scoped_refptr<AudioRendererSink>& sink)
- : audio_parameters_(params),
- audio_sink_(sink) {
- // TODO(dalecurtis): Once we have resampling we'll need to pass on a different
- // set of AudioParameters than the ones we're given.
- audio_sink_->Initialize(audio_parameters_, this);
+ const AudioParameters& input_params, const AudioParameters& output_params,
+ const scoped_refptr<AudioRendererSink>& sink)
+ : audio_sink_(sink),
+ current_audio_delay_milliseconds_(0) {
+ // Sanity check sample rates.
+ DCHECK_LE(input_params.sample_rate(), limits::kMaxSampleRate);
+ DCHECK_GE(input_params.sample_rate(), limits::kMinSampleRate);
+ DCHECK_LE(output_params.sample_rate(), limits::kMaxSampleRate);
+ DCHECK_GE(output_params.sample_rate(), limits::kMinSampleRate);
+
+ // Only resample if necessary since it's expensive.
+ if (input_params.sample_rate() != output_params.sample_rate()) {
+ resampler_.reset(new MultiChannelResampler(
+ output_params.channels(),
+ input_params.sample_rate() / static_cast<double>(
+ output_params.sample_rate()),
+ base::Bind(&AudioRendererMixer::ProvideInput, base::Unretained(this))));
+ }
+
+ audio_sink_->Initialize(output_params, this);
audio_sink_->Start();
}
@@ -22,6 +40,11 @@ AudioRendererMixer::~AudioRendererMixer() {
// AudioRendererSinks must be stopped before being destructed.
audio_sink_->Stop();
+ // Clean up |mixer_input_audio_data_|.
+ for (size_t i = 0; i < mixer_input_audio_data_.size(); ++i)
+ delete [] mixer_input_audio_data_[i];
+ mixer_input_audio_data_.clear();
+
// Ensures that all mixer inputs have stopped themselves prior to destruction
// and have called RemoveMixerInput().
DCHECK_EQ(mixer_inputs_.size(), 0U);
@@ -42,11 +65,40 @@ void AudioRendererMixer::RemoveMixerInput(
int AudioRendererMixer::Render(const std::vector<float*>& audio_data,
int number_of_frames,
int audio_delay_milliseconds) {
+ current_audio_delay_milliseconds_ = audio_delay_milliseconds;
+
+ if (resampler_.get())
+ resampler_->Resample(audio_data, number_of_frames);
+ else
+ ProvideInput(audio_data, number_of_frames);
+
+ // Always return the full number of frames requested, ProvideInput() will pad
+ // with silence if it wasn't able to acquire enough data.
+ return number_of_frames;
+}
+
+void AudioRendererMixer::ProvideInput(const std::vector<float*>& audio_data,
+ int number_of_frames) {
base::AutoLock auto_lock(mixer_inputs_lock_);
+ // Allocate staging area for each mixer input's audio data on first call. We
+ // won't know how much to allocate until here because of resampling.
+ if (mixer_input_audio_data_.size() == 0) {
+ // TODO(dalecurtis): If we switch to AVX/SSE optimization, we'll need to
+ // allocate these on 32-byte boundaries and ensure they're sized % 32 bytes.
+ mixer_input_audio_data_.reserve(audio_data.size());
+ for (size_t i = 0; i < audio_data.size(); ++i)
+ mixer_input_audio_data_.push_back(new float[number_of_frames]);
+ mixer_input_audio_data_size_ = number_of_frames;
+ }
+
+ // Sanity check our inputs.
+ DCHECK_LE(number_of_frames, mixer_input_audio_data_size_);
+ DCHECK_EQ(audio_data.size(), mixer_input_audio_data_.size());
+
// Zero |audio_data| so we're mixing into a clean buffer and return silence if
// we couldn't get enough data from our inputs.
- for (int i = 0; i < audio_parameters_.channels(); ++i)
+ for (size_t i = 0; i < audio_data.size(); ++i)
memset(audio_data[i], 0, number_of_frames * sizeof(*audio_data[i]));
// Have each mixer render its data into an output buffer then mix the result.
@@ -57,24 +109,21 @@ int AudioRendererMixer::Render(const std::vector<float*>& audio_data,
double volume;
input->GetVolume(&volume);
- // Nothing to do if the input isn't playing or the volume is zero.
- if (!input->playing() || volume == 0.0f)
+ // Nothing to do if the input isn't playing.
+ if (!input->playing())
continue;
- const std::vector<float*>& mixer_input_audio_data = input->audio_data();
-
int frames_filled = input->callback()->Render(
- mixer_input_audio_data, number_of_frames, audio_delay_milliseconds);
+ mixer_input_audio_data_, number_of_frames,
+ current_audio_delay_milliseconds_);
if (frames_filled == 0)
continue;
- // TODO(dalecurtis): Resample audio data.
-
// Volume adjust and mix each mixer input into |audio_data| after rendering.
// TODO(dalecurtis): Optimize with NEON/SSE/AVX vector_fmac from FFmpeg.
- for (int j = 0; j < audio_parameters_.channels(); ++j) {
+ for (size_t j = 0; j < audio_data.size(); ++j) {
float* dest = audio_data[j];
- float* source = mixer_input_audio_data[j];
+ float* source = mixer_input_audio_data_[j];
for (int k = 0; k < frames_filled; ++k)
dest[k] += source[k] * static_cast<float>(volume);
}
@@ -82,10 +131,6 @@ int AudioRendererMixer::Render(const std::vector<float*>& audio_data,
// No need to clamp values as InterleaveFloatToInt() will take care of this
// for us later when data is transferred to the browser process.
}
-
- // Always return the full number of frames requested, padded with silence if
- // we couldn't get enough data.
- return number_of_frames;
}
void AudioRendererMixer::OnRenderError() {
diff --git a/media/base/audio_renderer_mixer.h b/media/base/audio_renderer_mixer.h
index 32102ff..76e68bc 100644
--- a/media/base/audio_renderer_mixer.h
+++ b/media/base/audio_renderer_mixer.h
@@ -8,32 +8,30 @@
#include <set>
#include <vector>
-#include "base/memory/ref_counted.h"
#include "base/synchronization/lock.h"
#include "media/base/audio_renderer_mixer_input.h"
#include "media/base/audio_renderer_sink.h"
+#include "media/base/multi_channel_resampler.h"
namespace media {
// Mixes a set of AudioRendererMixerInputs into a single output stream which is
// funneled into a single shared AudioRendererSink; saving a bundle on renderer
-// side resources.
-// TODO(dalecurtis): Update documentation once resampling is available.
+// side resources. Resampling is done post-mixing as it is the most expensive
+// process. If the input sample rate matches the audio hardware sample rate, no
+// resampling is done.
class MEDIA_EXPORT AudioRendererMixer
- : public base::RefCountedThreadSafe<AudioRendererMixer>,
- NON_EXPORTED_BASE(public AudioRendererSink::RenderCallback) {
+ : NON_EXPORTED_BASE(public AudioRendererSink::RenderCallback) {
public:
- AudioRendererMixer(const AudioParameters& params,
+ AudioRendererMixer(const AudioParameters& input_params,
+ const AudioParameters& output_params,
const scoped_refptr<AudioRendererSink>& sink);
+ virtual ~AudioRendererMixer();
// Add or remove a mixer input from mixing; called by AudioRendererMixerInput.
void AddMixerInput(const scoped_refptr<AudioRendererMixerInput>& input);
void RemoveMixerInput(const scoped_refptr<AudioRendererMixerInput>& input);
- protected:
- friend class base::RefCountedThreadSafe<AudioRendererMixer>;
- virtual ~AudioRendererMixer();
-
private:
// AudioRendererSink::RenderCallback implementation.
virtual int Render(const std::vector<float*>& audio_data,
@@ -41,8 +39,11 @@ class MEDIA_EXPORT AudioRendererMixer
int audio_delay_milliseconds) OVERRIDE;
virtual void OnRenderError() OVERRIDE;
- // AudioParameters this mixer was constructed with.
- AudioParameters audio_parameters_;
+ // Handles mixing and volume adjustment. Renders |number_of_frames| into
+ // |audio_data|. When resampling is necessary, ProvideInput() will be called
+ // by MultiChannelResampler when more data is necessary.
+ void ProvideInput(const std::vector<float*>& audio_data,
+ int number_of_frames);
// Output sink for this mixer.
scoped_refptr<AudioRendererSink> audio_sink_;
@@ -54,6 +55,16 @@ class MEDIA_EXPORT AudioRendererMixer
AudioRendererMixerInputSet mixer_inputs_;
base::Lock mixer_inputs_lock_;
+ // Vector for rendering audio data from each mixer input.
+ int mixer_input_audio_data_size_;
+ std::vector<float*> mixer_input_audio_data_;
+
+ // Handles resampling post-mixing.
+ scoped_ptr<MultiChannelResampler> resampler_;
+
+ // The audio delay in milliseconds received by the last Render() call.
+ int current_audio_delay_milliseconds_;
+
DISALLOW_COPY_AND_ASSIGN(AudioRendererMixer);
};
diff --git a/media/base/audio_renderer_mixer_input.cc b/media/base/audio_renderer_mixer_input.cc
index 8eef689..ec0c019 100644
--- a/media/base/audio_renderer_mixer_input.cc
+++ b/media/base/audio_renderer_mixer_input.cc
@@ -10,35 +10,26 @@
namespace media {
AudioRendererMixerInput::AudioRendererMixerInput(
- const scoped_refptr<AudioRendererMixer>& mixer)
+ const GetMixerCB& get_mixer_cb, const RemoveMixerCB& remove_mixer_cb)
: playing_(false),
initialized_(false),
volume_(1.0f),
- mixer_(mixer),
+ get_mixer_cb_(get_mixer_cb),
+ remove_mixer_cb_(remove_mixer_cb),
callback_(NULL) {
}
AudioRendererMixerInput::~AudioRendererMixerInput() {
- if (!initialized_)
- return;
-
- // Clean up |audio_data_|.
- for (size_t i = 0; i < audio_data_.size(); ++i)
- delete [] audio_data_[i];
- audio_data_.clear();
+ // Mixer is no longer safe to use after |remove_mixer_cb_| has been called.
+ remove_mixer_cb_.Run(params_);
}
void AudioRendererMixerInput::Initialize(
const AudioParameters& params,
AudioRendererSink::RenderCallback* callback) {
DCHECK(!initialized_);
-
- // TODO(dalecurtis): If we switch to AVX/SSE optimization, we'll need to
- // allocate these on 32-byte boundaries and ensure they're sized % 32 bytes.
- audio_data_.reserve(params.channels());
- for (int i = 0; i < params.channels(); ++i)
- audio_data_.push_back(new float[params.frames_per_buffer()]);
-
+ params_ = params;
+ mixer_ = get_mixer_cb_.Run(params_);
callback_ = callback;
initialized_ = true;
}
diff --git a/media/base/audio_renderer_mixer_input.h b/media/base/audio_renderer_mixer_input.h
index 7e8c9f1..5813a97 100644
--- a/media/base/audio_renderer_mixer_input.h
+++ b/media/base/audio_renderer_mixer_input.h
@@ -7,6 +7,7 @@
#include <vector>
+#include "base/callback.h"
#include "media/base/audio_renderer_sink.h"
namespace media {
@@ -16,12 +17,13 @@ class AudioRendererMixer;
class MEDIA_EXPORT AudioRendererMixerInput
: NON_EXPORTED_BASE(public AudioRendererSink) {
public:
- explicit AudioRendererMixerInput(
- const scoped_refptr<AudioRendererMixer>& mixer);
+ typedef base::Callback<AudioRendererMixer*(
+ const AudioParameters& params)> GetMixerCB;
+ typedef base::Callback<void(const AudioParameters& params)> RemoveMixerCB;
+
+ AudioRendererMixerInput(
+ const GetMixerCB& get_mixer_cb, const RemoveMixerCB& remove_mixer_cb);
- // Each input should manage its own data buffer. The mixer will call this
- // method when it needs a buffer for rendering.
- const std::vector<float*>& audio_data() { return audio_data_; }
AudioRendererSink::RenderCallback* callback() { return callback_; }
bool playing() { return playing_; }
@@ -43,16 +45,21 @@ class MEDIA_EXPORT AudioRendererMixerInput
bool initialized_;
double volume_;
- // AudioRendererMixer is reference counted by all its AudioRendererMixerInputs
- // and is destroyed when all AudioRendererMixerInputs have called RemoveMixer.
- scoped_refptr<AudioRendererMixer> mixer_;
+ // Callbacks provided during construction which allow AudioRendererMixerInput
+ // to retrieve a mixer during Initialize() and notify when it's done with it.
+ GetMixerCB get_mixer_cb_;
+ RemoveMixerCB remove_mixer_cb_;
+
+ // AudioParameters received during Initialize().
+ AudioParameters params_;
+
+ // AudioRendererMixer provided through |get_mixer_cb_| during Initialize(),
+ // guaranteed to live (at least) until |remove_mixer_cb_| is called.
+ AudioRendererMixer* mixer_;
// Source of audio data which is provided to the mixer.
AudioRendererSink::RenderCallback* callback_;
- // Vector for rendering audio data which will be used by the mixer.
- std::vector<float*> audio_data_;
-
DISALLOW_COPY_AND_ASSIGN(AudioRendererMixerInput);
};
diff --git a/media/base/audio_renderer_mixer_input_unittest.cc b/media/base/audio_renderer_mixer_input_unittest.cc
index b57b7cc..48b2232 100644
--- a/media/base/audio_renderer_mixer_input_unittest.cc
+++ b/media/base/audio_renderer_mixer_input_unittest.cc
@@ -2,11 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "media/audio/audio_util.h"
-#include "media/audio/null_audio_sink.h"
+#include "base/bind.h"
+#include "base/bind_helpers.h"
#include "media/base/audio_renderer_mixer.h"
#include "media/base/audio_renderer_mixer_input.h"
#include "media/base/fake_audio_render_callback.h"
+#include "media/base/mock_audio_renderer_sink.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -14,46 +15,56 @@ namespace media {
static const int kBitsPerChannel = 16;
static const int kSampleRate = 48000;
+static const int kBufferSize = 8192;
static const ChannelLayout kChannelLayout = CHANNEL_LAYOUT_STEREO;
-class AudioRendererMixerInputTest : public ::testing::Test {
+class AudioRendererMixerInputTest : public testing::Test {
public:
AudioRendererMixerInputTest() {
audio_parameters_ = AudioParameters(
AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, kSampleRate,
- kBitsPerChannel, GetHighLatencyOutputBufferSize(kSampleRate));
-
- mixer_ = new AudioRendererMixer(audio_parameters_, new NullAudioSink());
- mixer_input_ = new AudioRendererMixerInput(mixer_);
- fake_callback_.reset(new FakeAudioRenderCallback(audio_parameters_));
+ kBitsPerChannel, kBufferSize);
+
+ mixer_input_ = new AudioRendererMixerInput(
+ base::Bind(
+ &AudioRendererMixerInputTest::GetMixer, base::Unretained(this)),
+ base::Bind(
+ &AudioRendererMixerInputTest::RemoveMixer, base::Unretained(this)));
+ fake_callback_.reset(new FakeAudioRenderCallback(0));
mixer_input_->Initialize(audio_parameters_, fake_callback_.get());
+ EXPECT_CALL(*this, RemoveMixer(testing::_));
}
- // Render audio_parameters_.frames_per_buffer() frames into |audio_data_| and
- // verify the result against |check_value|.
- void RenderAndValidateAudioData(float check_value) {
- const std::vector<float*>& audio_data = mixer_input_->audio_data();
-
- ASSERT_EQ(fake_callback_->Render(
- audio_data, audio_parameters_.frames_per_buffer(), 0),
- audio_parameters_.frames_per_buffer());
+ AudioRendererMixer* GetMixer(const AudioParameters& params) {
+ if (!mixer_.get()) {
+ scoped_refptr<MockAudioRendererSink> sink = new MockAudioRendererSink();
+ EXPECT_CALL(*sink, Start());
+ EXPECT_CALL(*sink, Stop());
- for (size_t i = 0; i < audio_data.size(); ++i)
- for (int j = 0; j < audio_parameters_.frames_per_buffer(); j++)
- ASSERT_FLOAT_EQ(check_value, audio_data[i][j]);
+ mixer_.reset(new AudioRendererMixer(
+ audio_parameters_, audio_parameters_, sink));
+ }
+ return mixer_.get();
}
+ MOCK_METHOD1(RemoveMixer, void(const AudioParameters&));
+
protected:
virtual ~AudioRendererMixerInputTest() {}
AudioParameters audio_parameters_;
- scoped_refptr<AudioRendererMixer> mixer_;
+ scoped_ptr<AudioRendererMixer> mixer_;
scoped_refptr<AudioRendererMixerInput> mixer_input_;
scoped_ptr<FakeAudioRenderCallback> fake_callback_;
DISALLOW_COPY_AND_ASSIGN(AudioRendererMixerInputTest);
};
+// Test callback() works as expected.
+TEST_F(AudioRendererMixerInputTest, GetCallback) {
+ EXPECT_EQ(mixer_input_->callback(), fake_callback_.get());
+}
+
// Test that getting and setting the volume work as expected.
TEST_F(AudioRendererMixerInputTest, GetSetVolume) {
// Starting volume should be 0.
@@ -67,20 +78,6 @@ TEST_F(AudioRendererMixerInputTest, GetSetVolume) {
EXPECT_EQ(volume, kVolume);
}
-// Test audio_data() is allocated correctly.
-TEST_F(AudioRendererMixerInputTest, GetAudioData) {
- RenderAndValidateAudioData(fake_callback_->fill_value());
-
- // TODO(dalecurtis): Perform alignment and size checks when we switch over to
- // FFmpeg optimized vector_fmac.
-}
-
-// Test callback() works as expected.
-TEST_F(AudioRendererMixerInputTest, GetCallback) {
- EXPECT_EQ(mixer_input_->callback(), fake_callback_.get());
- RenderAndValidateAudioData(fake_callback_->fill_value());
-}
-
// Test Start()/Play()/Pause()/Stop()/playing() all work as expected. Also
// implicitly tests that AddMixerInput() and RemoveMixerInput() work without
// crashing; functional tests for these methods are in AudioRendererMixerTest.
diff --git a/media/base/audio_renderer_mixer_unittest.cc b/media/base/audio_renderer_mixer_unittest.cc
index e897bbf..9f46dc1 100644
--- a/media/base/audio_renderer_mixer_unittest.cc
+++ b/media/base/audio_renderer_mixer_unittest.cc
@@ -2,99 +2,117 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// MSVC++ requires this to be set before any other includes to get M_PI.
+#define _USE_MATH_DEFINES
#include <cmath>
+#include "base/bind.h"
+#include "base/bind_helpers.h"
#include "base/memory/scoped_ptr.h"
-#include "media/audio/audio_util.h"
+#include "base/memory/scoped_vector.h"
#include "media/base/audio_renderer_mixer.h"
#include "media/base/audio_renderer_mixer_input.h"
#include "media/base/fake_audio_render_callback.h"
+#include "media/base/mock_audio_renderer_sink.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace media {
// Parameters which control the many input case tests.
-static const int kMixerInputs = 64;
-static const int kMixerCycles = 32;
+static const int kMixerInputs = 8;
+static const int kMixerCycles = 3;
+// Parameters used for testing.
static const int kBitsPerChannel = 16;
-static const int kSampleRate = 48000;
static const ChannelLayout kChannelLayout = CHANNEL_LAYOUT_STEREO;
+static const int kHighLatencyBufferSize = 8192;
+static const int kLowLatencyBufferSize = 256;
-// Multiple rounds of addition result in precision loss with float values, so we
-// need an epsilon such that if for all x f(x) = sum(x, m) and g(x) = m * x then
-// fabs(f - g) < kEpsilon. The kEpsilon below has been tested with m < 128.
-static const float kEpsilon = 0.00015f;
+// Number of full sine wave cycles for each Render() call.
+static const int kSineCycles = 4;
-class MockAudioRendererSink : public AudioRendererSink {
+// Tuple of <input sampling rate, output sampling rate, epsilon>.
+typedef std::tr1::tuple<int, int, double> AudioRendererMixerTestData;
+class AudioRendererMixerTest
+ : public testing::TestWithParam<AudioRendererMixerTestData> {
public:
- MOCK_METHOD0(Start, void());
- MOCK_METHOD0(Stop, void());
- MOCK_METHOD1(Pause, void(bool flush));
- MOCK_METHOD0(Play, void());
- MOCK_METHOD1(SetPlaybackRate, void(float rate));
- MOCK_METHOD1(SetVolume, bool(double volume));
- MOCK_METHOD1(GetVolume, void(double* volume));
-
- void Initialize(const media::AudioParameters& params,
- AudioRendererSink::RenderCallback* renderer) OVERRIDE {
- // TODO(dalecurtis): Once we have resampling we need to ensure we are given
- // an AudioParameters which reflects the hardware settings.
- callback_ = renderer;
- };
-
- AudioRendererSink::RenderCallback* callback() {
- return callback_;
- }
-
- void SimulateRenderError() {
- callback_->OnRenderError();
- }
+ AudioRendererMixerTest()
+ : epsilon_(std::tr1::get<2>(GetParam())),
+ half_fill_(false) {
+ // Create input and output parameters based on test parameters.
+ input_parameters_ = AudioParameters(
+ AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout,
+ std::tr1::get<0>(GetParam()), kBitsPerChannel, kHighLatencyBufferSize);
+ output_parameters_ = AudioParameters(
+ AudioParameters::AUDIO_PCM_LOW_LATENCY, kChannelLayout,
+ std::tr1::get<1>(GetParam()), 16, kLowLatencyBufferSize);
- protected:
- virtual ~MockAudioRendererSink() {}
-
- AudioRendererSink::RenderCallback* callback_;
-};
-
-class AudioRendererMixerTest : public ::testing::Test {
- public:
- AudioRendererMixerTest() {
- audio_parameters_ = AudioParameters(
- AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, kSampleRate,
- kBitsPerChannel, GetHighLatencyOutputBufferSize(kSampleRate));
sink_ = new MockAudioRendererSink();
EXPECT_CALL(*sink_, Start());
EXPECT_CALL(*sink_, Stop());
- mixer_ = new AudioRendererMixer(audio_parameters_, sink_);
+ mixer_.reset(new AudioRendererMixer(
+ input_parameters_, output_parameters_, sink_));
mixer_callback_ = sink_->callback();
// TODO(dalecurtis): If we switch to AVX/SSE optimization, we'll need to
// allocate these on 32-byte boundaries and ensure they're sized % 32 bytes.
- audio_data_.reserve(audio_parameters_.channels());
- for (int i = 0; i < audio_parameters_.channels(); ++i)
- audio_data_.push_back(new float[audio_parameters_.frames_per_buffer()]);
+ audio_data_.reserve(output_parameters_.channels());
+ for (int i = 0; i < output_parameters_.channels(); ++i)
+ audio_data_.push_back(new float[output_parameters_.frames_per_buffer()]);
+
+ // TODO(dalecurtis): If we switch to AVX/SSE optimization, we'll need to
+ // allocate these on 32-byte boundaries and ensure they're sized % 32 bytes.
+ expected_audio_data_.reserve(output_parameters_.channels());
+ for (int i = 0; i < output_parameters_.channels(); ++i) {
+ expected_audio_data_.push_back(
+ new float[output_parameters_.frames_per_buffer()]);
+ }
+
+ // Allocate one callback for generating expected results.
+ double step = kSineCycles / static_cast<double>(
+ output_parameters_.frames_per_buffer());
+ expected_callback_.reset(new FakeAudioRenderCallback(step));
+ }
- fake_callback_.reset(new FakeAudioRenderCallback(audio_parameters_));
+ AudioRendererMixer* GetMixer(const AudioParameters& params) {
+ return mixer_.get();
}
+ MOCK_METHOD1(RemoveMixer, void(const AudioParameters&));
+
void InitializeInputs(int count) {
+ mixer_inputs_.reserve(count);
+ fake_callbacks_.reserve(count);
+
+ // Setup FakeAudioRenderCallback step to compensate for resampling.
+ double scale_factor = input_parameters_.sample_rate()
+ / static_cast<double>(output_parameters_.sample_rate());
+ double step = kSineCycles / (scale_factor *
+ static_cast<double>(output_parameters_.frames_per_buffer()));
+
for (int i = 0; i < count; ++i) {
- scoped_refptr<AudioRendererMixerInput> mixer_input(
- new AudioRendererMixerInput(mixer_));
- mixer_input->Initialize(audio_parameters_, fake_callback_.get());
- mixer_input->SetVolume(1.0f);
- mixer_inputs_.push_back(mixer_input);
+ fake_callbacks_.push_back(new FakeAudioRenderCallback(step));
+ mixer_inputs_.push_back(new AudioRendererMixerInput(
+ base::Bind(&AudioRendererMixerTest::GetMixer,
+ base::Unretained(this)),
+ base::Bind(&AudioRendererMixerTest::RemoveMixer,
+ base::Unretained(this))));
+ mixer_inputs_[i]->Initialize(input_parameters_, fake_callbacks_[i]);
+ mixer_inputs_[i]->SetVolume(1.0f);
}
+ EXPECT_CALL(*this, RemoveMixer(testing::_)).Times(count);
}
- bool ValidateAudioData(int start_index, int frames, float check_value) {
+ bool ValidateAudioData(int index, int frames, float scale) {
for (size_t i = 0; i < audio_data_.size(); ++i) {
- for (int j = start_index; j < frames; j++) {
- if (fabs(audio_data_[i][j] - check_value) > kEpsilon) {
- EXPECT_NEAR(check_value, audio_data_[i][j], kEpsilon)
+ for (int j = index; j < frames; j++) {
+ double error = fabs(
+ audio_data_[i][j] - expected_audio_data_[i][j] * scale);
+ if (error > epsilon_) {
+ EXPECT_NEAR(
+ expected_audio_data_[i][j] * scale, audio_data_[i][j], epsilon_)
<< " i=" << i << ", j=" << j;
return false;
}
@@ -103,20 +121,47 @@ class AudioRendererMixerTest : public ::testing::Test {
return true;
}
- // Render audio_parameters_.frames_per_buffer() frames into |audio_data_| and
- // verify the result against |check_value|.
- bool RenderAndValidateAudioData(float check_value) {
- int frames = mixer_callback_->Render(
- audio_data_, audio_parameters_.frames_per_buffer(), 0);
- return frames == audio_parameters_.frames_per_buffer() && ValidateAudioData(
- 0, audio_parameters_.frames_per_buffer(), check_value);
+ bool RenderAndValidateAudioData(float scale) {
+ int request_frames = output_parameters_.frames_per_buffer();
+
+ // Half fill won't be exactly half when resampling since the resampler
+ // will have enough data to fill out more of the buffer based on its
+ // internal buffer and kernel size. So special case some of the checks.
+ bool resampling = input_parameters_.sample_rate()
+ != output_parameters_.sample_rate();
+
+ if (half_fill_) {
+ for (size_t i = 0; i < fake_callbacks_.size(); ++i)
+ fake_callbacks_[i]->set_half_fill(true);
+ expected_callback_->set_half_fill(true);
+ }
+
+ // Render actual audio data.
+ int frames = mixer_callback_->Render(audio_data_, request_frames, 0);
+ if (frames != request_frames)
+ return false;
+
+ // Render expected audio data (without scaling).
+ expected_callback_->Render(expected_audio_data_, request_frames, 0);
+
+ if (half_fill_) {
+ // Verify first half of audio data for both resampling and non-resampling.
+ if (!ValidateAudioData(0, frames / 2, scale))
+ return false;
+ // Verify silence in the second half if we're not resampling.
+ if (!resampling)
+ return ValidateAudioData(frames / 2, frames, 0);
+ return true;
+ } else {
+ return ValidateAudioData(0, frames, scale);
+ }
}
// Fill |audio_data_| fully with |value|.
void FillAudioData(float value) {
for (size_t i = 0; i < audio_data_.size(); ++i)
std::fill(audio_data_[i],
- audio_data_[i] + audio_parameters_.frames_per_buffer(), value);
+ audio_data_[i] + output_parameters_.frames_per_buffer(), value);
}
// Verify silence when mixer inputs are in pre-Start() and post-Start().
@@ -148,27 +193,14 @@ class AudioRendererMixerTest : public ::testing::Test {
void PlayTest(int inputs) {
InitializeInputs(inputs);
- for (size_t i = 0; i < mixer_inputs_.size(); ++i)
+ // Play() all mixer inputs and ensure we get the right values.
+ for (size_t i = 0; i < mixer_inputs_.size(); ++i) {
mixer_inputs_[i]->Start();
-
- // Play() all even numbered mixer inputs and ensure we get the right value.
- for (size_t i = 0; i < mixer_inputs_.size(); i += 2)
mixer_inputs_[i]->Play();
- for (int i = 0; i < kMixerCycles; ++i) {
- fake_callback_->NextFillValue();
- ASSERT_TRUE(RenderAndValidateAudioData(
- fake_callback_->fill_value() * std::max(
- mixer_inputs_.size() / 2, static_cast<size_t>(1))));
}
- // Play() all mixer inputs and ensure we still get the right values.
- for (size_t i = 1; i < mixer_inputs_.size(); i += 2)
- mixer_inputs_[i]->Play();
- for (int i = 0; i < kMixerCycles; ++i) {
- fake_callback_->NextFillValue();
- ASSERT_TRUE(RenderAndValidateAudioData(
- fake_callback_->fill_value() * mixer_inputs_.size()));
- }
+ for (int i = 0; i < kMixerCycles; ++i)
+ ASSERT_TRUE(RenderAndValidateAudioData(mixer_inputs_.size()));
for (size_t i = 0; i < mixer_inputs_.size(); ++i)
mixer_inputs_[i]->Stop();
@@ -190,11 +222,8 @@ class AudioRendererMixerTest : public ::testing::Test {
total_scale += volume;
EXPECT_TRUE(mixer_inputs_[i]->SetVolume(volume));
}
- for (int i = 0; i < kMixerCycles; ++i) {
- fake_callback_->NextFillValue();
- ASSERT_TRUE(RenderAndValidateAudioData(
- fake_callback_->fill_value() * total_scale));
- }
+ for (int i = 0; i < kMixerCycles; ++i)
+ ASSERT_TRUE(RenderAndValidateAudioData(total_scale));
for (size_t i = 0; i < mixer_inputs_.size(); ++i)
mixer_inputs_[i]->Stop();
@@ -203,7 +232,6 @@ class AudioRendererMixerTest : public ::testing::Test {
// Verify output when mixer inputs can only partially fulfill a Render().
void PlayPartialRenderTest(int inputs) {
InitializeInputs(inputs);
- int frames = audio_parameters_.frames_per_buffer();
for (size_t i = 0; i < mixer_inputs_.size(); ++i) {
mixer_inputs_[i]->Start();
@@ -211,16 +239,8 @@ class AudioRendererMixerTest : public ::testing::Test {
}
// Verify a properly filled buffer when half filled (remainder zeroed).
- fake_callback_->set_half_fill(true);
- for (int i = 0; i < kMixerCycles; ++i) {
- fake_callback_->NextFillValue();
- ASSERT_EQ(mixer_callback_->Render(audio_data_, frames, 0), frames);
- ASSERT_TRUE(ValidateAudioData(
- 0, frames / 2, fake_callback_->fill_value() * mixer_inputs_.size()));
- ASSERT_TRUE(ValidateAudioData(
- frames / 2, frames, 0.0f));
- }
- fake_callback_->set_half_fill(false);
+ half_fill_ = true;
+ ASSERT_TRUE(RenderAndValidateAudioData(mixer_inputs_.size()));
for (size_t i = 0; i < mixer_inputs_.size(); ++i)
mixer_inputs_[i]->Stop();
@@ -238,17 +258,8 @@ class AudioRendererMixerTest : public ::testing::Test {
// Pause() all even numbered mixer inputs and ensure we get the right value.
for (size_t i = 0; i < mixer_inputs_.size(); i += 2)
mixer_inputs_[i]->Pause(false);
- for (int i = 0; i < kMixerCycles; ++i) {
- fake_callback_->NextFillValue();
- ASSERT_TRUE(RenderAndValidateAudioData(
- fake_callback_->fill_value() * (mixer_inputs_.size() / 2)));
- }
-
- // Pause() all the inputs and verify we get silence back.
- for (size_t i = 1; i < mixer_inputs_.size(); i += 2)
- mixer_inputs_[i]->Pause(false);
- FillAudioData(1.0f);
- EXPECT_TRUE(RenderAndValidateAudioData(0.0f));
+ for (int i = 0; i < kMixerCycles; ++i)
+ ASSERT_TRUE(RenderAndValidateAudioData(mixer_inputs_.size() / 2));
for (size_t i = 0; i < mixer_inputs_.size(); ++i)
mixer_inputs_[i]->Stop();
@@ -276,84 +287,89 @@ class AudioRendererMixerTest : public ::testing::Test {
}
scoped_refptr<MockAudioRendererSink> sink_;
- scoped_refptr<AudioRendererMixer> mixer_;
+ scoped_ptr<AudioRendererMixer> mixer_;
AudioRendererSink::RenderCallback* mixer_callback_;
- scoped_ptr<FakeAudioRenderCallback> fake_callback_;
- AudioParameters audio_parameters_;
+ AudioParameters input_parameters_;
+ AudioParameters output_parameters_;
std::vector<float*> audio_data_;
+ std::vector<float*> expected_audio_data_;
std::vector< scoped_refptr<AudioRendererMixerInput> > mixer_inputs_;
+ ScopedVector<FakeAudioRenderCallback> fake_callbacks_;
+ scoped_ptr<FakeAudioRenderCallback> expected_callback_;
+ double epsilon_;
+ bool half_fill_;
DISALLOW_COPY_AND_ASSIGN(AudioRendererMixerTest);
};
// Verify a mixer with no inputs returns silence for all requested frames.
-TEST_F(AudioRendererMixerTest, NoInputs) {
+TEST_P(AudioRendererMixerTest, NoInputs) {
FillAudioData(1.0f);
EXPECT_TRUE(RenderAndValidateAudioData(0.0f));
}
// Test mixer output with one input in the pre-Start() and post-Start() state.
-TEST_F(AudioRendererMixerTest, OneInputStart) {
+TEST_P(AudioRendererMixerTest, OneInputStart) {
StartTest(1);
}
// Test mixer output with many inputs in the pre-Start() and post-Start() state.
-TEST_F(AudioRendererMixerTest, ManyInputStart) {
+TEST_P(AudioRendererMixerTest, ManyInputStart) {
StartTest(kMixerInputs);
}
// Test mixer output with one input in the post-Play() state.
-TEST_F(AudioRendererMixerTest, OneInputPlay) {
+TEST_P(AudioRendererMixerTest, OneInputPlay) {
PlayTest(1);
}
// Test mixer output with many inputs in the post-Play() state.
-TEST_F(AudioRendererMixerTest, ManyInputPlay) {
+TEST_P(AudioRendererMixerTest, ManyInputPlay) {
PlayTest(kMixerInputs);
}
// Test volume adjusted mixer output with one input in the post-Play() state.
-TEST_F(AudioRendererMixerTest, OneInputPlayVolumeAdjusted) {
+TEST_P(AudioRendererMixerTest, OneInputPlayVolumeAdjusted) {
PlayVolumeAdjustedTest(1);
}
// Test volume adjusted mixer output with many inputs in the post-Play() state.
-TEST_F(AudioRendererMixerTest, ManyInputPlayVolumeAdjusted) {
+TEST_P(AudioRendererMixerTest, ManyInputPlayVolumeAdjusted) {
PlayVolumeAdjustedTest(kMixerInputs);
}
// Test mixer output with one input and partial Render() in post-Play() state.
-TEST_F(AudioRendererMixerTest, OneInputPlayPartialRender) {
+TEST_P(AudioRendererMixerTest, OneInputPlayPartialRender) {
PlayPartialRenderTest(1);
}
// Test mixer output with many inputs and partial Render() in post-Play() state.
-TEST_F(AudioRendererMixerTest, ManyInputPlayPartialRender) {
+TEST_P(AudioRendererMixerTest, ManyInputPlayPartialRender) {
PlayPartialRenderTest(kMixerInputs);
}
// Test mixer output with one input in the post-Pause() state.
-TEST_F(AudioRendererMixerTest, OneInputPause) {
+TEST_P(AudioRendererMixerTest, OneInputPause) {
PauseTest(1);
}
// Test mixer output with many inputs in the post-Pause() state.
-TEST_F(AudioRendererMixerTest, ManyInputPause) {
+TEST_P(AudioRendererMixerTest, ManyInputPause) {
PauseTest(kMixerInputs);
}
// Test mixer output with one input in the post-Stop() state.
-TEST_F(AudioRendererMixerTest, OneInputStop) {
+TEST_P(AudioRendererMixerTest, OneInputStop) {
StopTest(1);
}
// Test mixer output with many inputs in the post-Stop() state.
-TEST_F(AudioRendererMixerTest, ManyInputStop) {
+TEST_P(AudioRendererMixerTest, ManyInputStop) {
StopTest(kMixerInputs);
}
// Test mixer with many inputs in mixed post-Stop() and post-Play() states.
-TEST_F(AudioRendererMixerTest, ManyInputMixedStopPlay) {
+TEST_P(AudioRendererMixerTest, ManyInputMixedStopPlay) {
InitializeInputs(kMixerInputs);
// Start() all inputs.
@@ -366,32 +382,34 @@ TEST_F(AudioRendererMixerTest, ManyInputMixedStopPlay) {
mixer_inputs_[i - 1]->Stop();
mixer_inputs_[i]->Play();
}
- for (int i = 0; i < kMixerCycles; ++i) {
- fake_callback_->NextFillValue();
- ASSERT_TRUE(RenderAndValidateAudioData(
- fake_callback_->fill_value() * std::max(
- mixer_inputs_.size() / 2, static_cast<size_t>(1))));
- }
+ ASSERT_TRUE(RenderAndValidateAudioData(std::max(
+ mixer_inputs_.size() / 2, static_cast<size_t>(1))));
for (size_t i = 1; i < mixer_inputs_.size(); i += 2)
mixer_inputs_[i]->Stop();
}
-TEST_F(AudioRendererMixerTest, OnRenderError) {
- std::vector< scoped_refptr<AudioRendererMixerInput> > mixer_inputs;
- for (int i = 0; i < kMixerInputs; ++i) {
- scoped_refptr<AudioRendererMixerInput> mixer_input(
- new AudioRendererMixerInput(mixer_));
- mixer_input->Initialize(audio_parameters_, fake_callback_.get());
- mixer_input->SetVolume(1.0f);
- mixer_input->Start();
- mixer_inputs_.push_back(mixer_input);
+TEST_P(AudioRendererMixerTest, OnRenderError) {
+ InitializeInputs(kMixerInputs);
+ for (size_t i = 0; i < mixer_inputs_.size(); ++i) {
+ mixer_inputs_[i]->Start();
+ EXPECT_CALL(*fake_callbacks_[i], OnRenderError()).Times(1);
}
- EXPECT_CALL(*fake_callback_, OnRenderError()).Times(kMixerInputs);
- sink_->SimulateRenderError();
- for (int i = 0; i < kMixerInputs; ++i)
+ mixer_callback_->OnRenderError();
+ for (size_t i = 0; i < mixer_inputs_.size(); ++i)
mixer_inputs_[i]->Stop();
}
+INSTANTIATE_TEST_CASE_P(
+ AudioRendererMixerTest, AudioRendererMixerTest, testing::Values(
+ // No resampling.
+ std::tr1::make_tuple(44100, 44100, 0.000000477),
+
+ // Upsampling.
+ std::tr1::make_tuple(44100, 48000, 0.0329405),
+
+ // Downsampling.
+ std::tr1::make_tuple(48000, 41000, 0.0410239)));
+
} // namespace media
diff --git a/media/base/fake_audio_render_callback.cc b/media/base/fake_audio_render_callback.cc
index 3fc711b4..15986fd 100644
--- a/media/base/fake_audio_render_callback.cc
+++ b/media/base/fake_audio_render_callback.cc
@@ -11,13 +11,10 @@
namespace media {
-// Arbitrarily chosen prime value for the fake random number generator.
-static const int kFakeRandomSeed = 9440671;
-
-FakeAudioRenderCallback::FakeAudioRenderCallback(const AudioParameters& params)
+FakeAudioRenderCallback::FakeAudioRenderCallback(double step)
: half_fill_(false),
- fill_value_(1.0f),
- audio_parameters_(params) {
+ step_(step) {
+ reset();
}
FakeAudioRenderCallback::~FakeAudioRenderCallback() {}
@@ -27,18 +24,18 @@ int FakeAudioRenderCallback::Render(const std::vector<float*>& audio_data,
int audio_delay_milliseconds) {
if (half_fill_)
number_of_frames /= 2;
- for (size_t i = 0; i < audio_data.size(); ++i)
- std::fill(audio_data[i], audio_data[i] + number_of_frames, fill_value_);
- return number_of_frames;
-}
+ // Fill first channel with a sine wave.
+ for (int i = 0; i < number_of_frames; ++i)
+ audio_data[0][i] = sin(2 * M_PI * (x_ + step_ * i));
+ x_ += number_of_frames * step_;
-void FakeAudioRenderCallback::NextFillValue() {
- // Use irrationality of PI to fake random numbers; square fill_value_ to keep
- // numbers between [0, 1) so range extension to [-1, 1) by 2 * x - 1 works.
- fill_value_ = 2.0f * (static_cast<int>(
- M_PI * fill_value_ * fill_value_ * kFakeRandomSeed) % kFakeRandomSeed) /
- static_cast<float>(kFakeRandomSeed) - 1.0f;
+ // Copy first channel into the rest of the channels.
+ for (size_t i = 1; i < audio_data.size(); ++i)
+ memcpy(audio_data[i], audio_data[0],
+ number_of_frames * sizeof(*audio_data[0]));
+
+ return number_of_frames;
}
} // namespace media
diff --git a/media/base/fake_audio_render_callback.h b/media/base/fake_audio_render_callback.h
index f80c942..b1a4e44 100644
--- a/media/base/fake_audio_render_callback.h
+++ b/media/base/fake_audio_render_callback.h
@@ -7,19 +7,22 @@
#include <vector>
-#include "base/time.h"
#include "media/base/audio_renderer_sink.h"
#include "testing/gmock/include/gmock/gmock.h"
namespace media {
+// Fake RenderCallback which will fill each request with a sine wave. Sine
+// state is kept across callbacks. State can be reset to default via reset().
class FakeAudioRenderCallback : public AudioRendererSink::RenderCallback {
public:
- // Initializes |fill_value_| to a random value seeded by current time.
- explicit FakeAudioRenderCallback(const AudioParameters& params);
+ // The function used to fulfill Render() is f(x) = sin(2 * PI * x * |step|),
+ // where x = [|number_of_frames| * m, |number_of_frames| * (m + 1)] and m =
+ // the number of Render() calls fulfilled thus far.
+ explicit FakeAudioRenderCallback(double step);
virtual ~FakeAudioRenderCallback();
- // Renders |fill_value_| into the provided audio data buffer. If |half_fill_|
+ // Renders a sine wave into the provided audio data buffer. If |half_fill_|
// is set, will only fill half the buffer.
int Render(const std::vector<float*>& audio_data, int number_of_frames,
int audio_delay_milliseconds) OVERRIDE;
@@ -28,17 +31,13 @@ class FakeAudioRenderCallback : public AudioRendererSink::RenderCallback {
// Toggles only filling half the requested amount during Render().
void set_half_fill(bool half_fill) { half_fill_ = half_fill; }
- float fill_value() { return fill_value_; }
-
- // Generates a fill value between [-1, 1). NextFillValue() is deterministic
- // based on fill_value_. Which means it will generate the same sequence of
- // fill values every time unless |fill_value_| is set using set_fill_value().
- void NextFillValue();
+ // Reset the sine state to initial value.
+ void reset() { x_ = 0; }
private:
bool half_fill_;
- float fill_value_;
- AudioParameters audio_parameters_;
+ double x_;
+ double step_;
DISALLOW_COPY_AND_ASSIGN(FakeAudioRenderCallback);
};
diff --git a/media/base/mock_audio_renderer_sink.cc b/media/base/mock_audio_renderer_sink.cc
new file mode 100644
index 0000000..b21eb19
--- /dev/null
+++ b/media/base/mock_audio_renderer_sink.cc
@@ -0,0 +1,17 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/base/mock_audio_renderer_sink.h"
+
+namespace media {
+
+MockAudioRendererSink::MockAudioRendererSink() {}
+MockAudioRendererSink::~MockAudioRendererSink() {}
+
+void MockAudioRendererSink::Initialize(const AudioParameters& params,
+ RenderCallback* renderer) {
+ callback_ = renderer;
+}
+
+} // namespace media
diff --git a/media/base/mock_audio_renderer_sink.h b/media/base/mock_audio_renderer_sink.h
new file mode 100644
index 0000000..903d1fc
--- /dev/null
+++ b/media/base/mock_audio_renderer_sink.h
@@ -0,0 +1,41 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MEDIA_BASE_MOCK_AUDIO_RENDERER_SINK_H_
+#define MEDIA_BASE_MOCK_AUDIO_RENDERER_SINK_H_
+
+#include "media/audio/audio_parameters.h"
+#include "media/base/audio_renderer_sink.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace media {
+
+class MockAudioRendererSink : public AudioRendererSink {
+ public:
+ MockAudioRendererSink();
+
+ MOCK_METHOD0(Start, void());
+ MOCK_METHOD0(Stop, void());
+ MOCK_METHOD1(Pause, void(bool flush));
+ MOCK_METHOD0(Play, void());
+ MOCK_METHOD1(SetPlaybackRate, void(float rate));
+ MOCK_METHOD1(SetVolume, bool(double volume));
+ MOCK_METHOD1(GetVolume, void(double* volume));
+
+ virtual void Initialize(const AudioParameters& params,
+ RenderCallback* renderer) OVERRIDE;
+ AudioRendererSink::RenderCallback* callback() { return callback_; }
+
+ protected:
+ virtual ~MockAudioRendererSink();
+
+ private:
+ RenderCallback* callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockAudioRendererSink);
+};
+
+} // namespace media
+
+#endif // MEDIA_BASE_MOCK_AUDIO_RENDERER_SINK_H_
diff --git a/media/filters/audio_renderer_impl_unittest.cc b/media/filters/audio_renderer_impl_unittest.cc
index 1633087..909bbb0 100644
--- a/media/filters/audio_renderer_impl_unittest.cc
+++ b/media/filters/audio_renderer_impl_unittest.cc
@@ -6,6 +6,7 @@
#include "base/gtest_prod_util.h"
#include "base/stl_util.h"
#include "media/base/data_buffer.h"
+#include "media/base/mock_audio_renderer_sink.h"
#include "media/base/mock_callback.h"
#include "media/base/mock_filter_host.h"
#include "media/base/mock_filters.h"
@@ -19,26 +20,6 @@ using ::testing::Return;
using ::testing::NiceMock;
using ::testing::StrictMock;
-namespace {
-
-class MockAudioSink : public media::AudioRendererSink {
- public:
- MOCK_METHOD2(Initialize, void(const media::AudioParameters& params,
- RenderCallback* callback));
- MOCK_METHOD0(Start, void());
- MOCK_METHOD0(Stop, void());
- MOCK_METHOD1(Pause, void(bool flush));
- MOCK_METHOD0(Play, void());
- MOCK_METHOD1(SetPlaybackRate, void(float rate));
- MOCK_METHOD1(SetVolume, bool(double volume));
- MOCK_METHOD1(GetVolume, void(double* volume));
-
- protected:
- virtual ~MockAudioSink() {}
-};
-
-} // namespace
-
namespace media {
// Constants for distinguishing between muted audio and playing audio when using
@@ -50,7 +31,7 @@ class AudioRendererImplTest : public ::testing::Test {
public:
// Give the decoder some non-garbage media properties.
AudioRendererImplTest()
- : renderer_(new AudioRendererImpl(new NiceMock<MockAudioSink>())),
+ : renderer_(new AudioRendererImpl(new NiceMock<MockAudioRendererSink>())),
decoder_(new MockAudioDecoder()) {
renderer_->SetHost(&host_);
diff --git a/media/media.gyp b/media/media.gyp
index 54bca0a..d0f889b 100644
--- a/media/media.gyp
+++ b/media/media.gyp
@@ -678,8 +678,6 @@
'base/data_buffer_unittest.cc',
'base/decoder_buffer_unittest.cc',
'base/djb2_unittest.cc',
- 'base/fake_audio_render_callback.cc',
- 'base/fake_audio_render_callback.h',
'base/filter_collection_unittest.cc',
'base/multi_channel_resampler_unittest.cc',
'base/pipeline_unittest.cc',
@@ -793,6 +791,10 @@
'audio/mock_audio_manager.h',
'audio/test_audio_input_controller_factory.cc',
'audio/test_audio_input_controller_factory.h',
+ 'base/fake_audio_render_callback.cc',
+ 'base/fake_audio_render_callback.h',
+ 'base/mock_audio_renderer_sink.cc',
+ 'base/mock_audio_renderer_sink.h',
'base/mock_callback.cc',
'base/mock_callback.h',
'base/mock_data_source_host.cc',