summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--media/base/audio_renderer_mixer.cc28
-rw-r--r--media/base/audio_renderer_mixer.h4
-rw-r--r--media/base/audio_renderer_mixer_unittest.cc22
-rw-r--r--media/base/fake_audio_render_callback.cc4
-rw-r--r--media/base/fake_audio_render_callback.h5
5 files changed, 51 insertions, 12 deletions
diff --git a/media/base/audio_renderer_mixer.cc b/media/base/audio_renderer_mixer.cc
index e48b171..4df2eea 100644
--- a/media/base/audio_renderer_mixer.cc
+++ b/media/base/audio_renderer_mixer.cc
@@ -17,19 +17,23 @@ AudioRendererMixer::AudioRendererMixer(
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);
+ current_audio_delay_milliseconds_(0),
+ io_ratio_(1),
+ input_ms_per_frame_(
+ static_cast<double>(base::Time::kMillisecondsPerSecond) /
+ input_params.sample_rate()) {
+ DCHECK(input_params.IsValid());
+ DCHECK(output_params.IsValid());
+
+ // Channel mixing is handled by the browser side currently.
+ DCHECK_EQ(input_params.channels(), output_params.channels());
// Only resample if necessary since it's expensive.
if (input_params.sample_rate() != output_params.sample_rate()) {
+ io_ratio_ = input_params.sample_rate() /
+ static_cast<double>(output_params.sample_rate());
resampler_.reset(new MultiChannelResampler(
- output_params.channels(),
- input_params.sample_rate() / static_cast<double>(
- output_params.sample_rate()),
+ output_params.channels(), io_ratio_,
base::Bind(&AudioRendererMixer::ProvideInput, base::Unretained(this))));
}
@@ -60,7 +64,7 @@ void AudioRendererMixer::RemoveMixerInput(
int AudioRendererMixer::Render(AudioBus* audio_bus,
int audio_delay_milliseconds) {
- current_audio_delay_milliseconds_ = audio_delay_milliseconds;
+ current_audio_delay_milliseconds_ = audio_delay_milliseconds / io_ratio_;
if (resampler_.get())
resampler_->Resample(audio_bus, audio_bus->frames());
@@ -117,6 +121,10 @@ void AudioRendererMixer::ProvideInput(AudioBus* audio_bus) {
audio_bus->channel(i));
}
}
+
+ // Update the delay estimate.
+ current_audio_delay_milliseconds_ +=
+ audio_bus->frames() * input_ms_per_frame_;
}
void AudioRendererMixer::OnRenderError() {
diff --git a/media/base/audio_renderer_mixer.h b/media/base/audio_renderer_mixer.h
index c595c0d..7bb85af 100644
--- a/media/base/audio_renderer_mixer.h
+++ b/media/base/audio_renderer_mixer.h
@@ -61,6 +61,10 @@ class MEDIA_EXPORT AudioRendererMixer
// The audio delay in milliseconds received by the last Render() call.
int current_audio_delay_milliseconds_;
+ // Ratio of input data to output data. Used to scale audio delay information.
+ double io_ratio_;
+ double input_ms_per_frame_;
+
DISALLOW_COPY_AND_ASSIGN(AudioRendererMixer);
};
diff --git a/media/base/audio_renderer_mixer_unittest.cc b/media/base/audio_renderer_mixer_unittest.cc
index a37cd69..09fe8d4 100644
--- a/media/base/audio_renderer_mixer_unittest.cc
+++ b/media/base/audio_renderer_mixer_unittest.cc
@@ -24,7 +24,7 @@ static const int kMixerInputs = 8;
static const int kMixerCycles = 3;
// Parameters used for testing.
-static const int kBitsPerChannel = 16;
+static const int kBitsPerChannel = 32;
static const ChannelLayout kChannelLayout = CHANNEL_LAYOUT_STEREO;
static const int kHighLatencyBufferSize = 8192;
static const int kLowLatencyBufferSize = 256;
@@ -388,6 +388,26 @@ TEST_P(AudioRendererMixerTest, OnRenderError) {
mixer_inputs_[i]->Stop();
}
+// Verify that audio delay information is scaled to the input parameters.
+TEST_P(AudioRendererMixerTest, DelayTest) {
+ InitializeInputs(1);
+ static const int kAudioDelayMilliseconds = 100;
+ ASSERT_EQ(mixer_inputs_.size(), 1u);
+
+ // Start the input and issue a single render callback.
+ mixer_inputs_[0]->Start();
+ mixer_inputs_[0]->Play();
+ mixer_callback_->Render(audio_bus_.get(), kAudioDelayMilliseconds);
+
+ // The input to output ratio should only include the sample rate difference.
+ double io_ratio = input_parameters_.sample_rate() /
+ static_cast<double>(output_parameters_.sample_rate());
+
+ EXPECT_EQ(static_cast<int>(kAudioDelayMilliseconds / io_ratio),
+ fake_callbacks_[0]->last_audio_delay_milliseconds());
+ mixer_inputs_[0]->Stop();
+}
+
INSTANTIATE_TEST_CASE_P(
AudioRendererMixerTest, AudioRendererMixerTest, testing::Values(
// No resampling.
diff --git a/media/base/fake_audio_render_callback.cc b/media/base/fake_audio_render_callback.cc
index 6adf569..65b6ac9 100644
--- a/media/base/fake_audio_render_callback.cc
+++ b/media/base/fake_audio_render_callback.cc
@@ -13,7 +13,8 @@ namespace media {
FakeAudioRenderCallback::FakeAudioRenderCallback(double step)
: half_fill_(false),
- step_(step) {
+ step_(step),
+ last_audio_delay_milliseconds_(-1) {
reset();
}
@@ -21,6 +22,7 @@ FakeAudioRenderCallback::~FakeAudioRenderCallback() {}
int FakeAudioRenderCallback::Render(AudioBus* audio_bus,
int audio_delay_milliseconds) {
+ last_audio_delay_milliseconds_ = audio_delay_milliseconds;
int number_of_frames = audio_bus->frames();
if (half_fill_)
number_of_frames /= 2;
diff --git a/media/base/fake_audio_render_callback.h b/media/base/fake_audio_render_callback.h
index f6ce104..760e39d 100644
--- a/media/base/fake_audio_render_callback.h
+++ b/media/base/fake_audio_render_callback.h
@@ -31,10 +31,15 @@ class FakeAudioRenderCallback : public AudioRendererSink::RenderCallback {
// Reset the sine state to initial value.
void reset() { x_ = 0; }
+ // Returns the last |audio_delay_milliseconds| provided to Render() or -1 if
+ // no Render() call occurred.
+ int last_audio_delay_milliseconds() { return last_audio_delay_milliseconds_; }
+
private:
bool half_fill_;
double x_;
double step_;
+ int last_audio_delay_milliseconds_;
DISALLOW_COPY_AND_ASSIGN(FakeAudioRenderCallback);
};