summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authordalecurtis <dalecurtis@chromium.org>2015-08-13 14:33:19 -0700
committerCommit bot <commit-bot@chromium.org>2015-08-13 21:33:58 +0000
commit6bf5bc1cde021e9b25dc3c6d342d7a96a79402f7 (patch)
tree981bb91ae4738b593d5447bc7720a8c8fceb678e /media
parent9b16970b9f3b8b28054d32b15099bffe55ec1722 (diff)
downloadchromium_src-6bf5bc1cde021e9b25dc3c6d342d7a96a79402f7.zip
chromium_src-6bf5bc1cde021e9b25dc3c6d342d7a96a79402f7.tar.gz
chromium_src-6bf5bc1cde021e9b25dc3c6d342d7a96a79402f7.tar.bz2
Switch AudioRendererAlgorithm to buffer based on time.
It doesn't make sense to buffer based on a frame count when the amount of time that data represent varies with sample rate; it's the opposite of what we want. I.e., a 48kHz playback will exhaust this buffer faster than a 44.1kHz playback. Instead, switch to time based initial capacity using the sample rate provided during initialization. This provides a greater resilience against underflow when video decoding is overloading the media thread. At 48kHz we were previously buffering ~171ms and at 44.1kHz we were buffering ~186ms of audio data. I've chosen a nice round 200ms for simplicity and since it works well on an Android One device. BUG=519108 TEST=media_unittests still pass. Review URL: https://codereview.chromium.org/1278733004 Cr-Commit-Position: refs/heads/master@{#343279}
Diffstat (limited to 'media')
-rw-r--r--media/filters/audio_renderer_algorithm.cc28
-rw-r--r--media/filters/audio_renderer_algorithm.h3
-rw-r--r--media/filters/audio_renderer_algorithm_unittest.cc2
3 files changed, 19 insertions, 14 deletions
diff --git a/media/filters/audio_renderer_algorithm.cc b/media/filters/audio_renderer_algorithm.cc
index 2d2bfbf..a370124 100644
--- a/media/filters/audio_renderer_algorithm.cc
+++ b/media/filters/audio_renderer_algorithm.cc
@@ -61,20 +61,14 @@ static const int kWsolaSearchIntervalMs = 30;
// The maximum size in seconds for the |audio_buffer_|. Arbitrarily determined.
static const int kMaxCapacityInSeconds = 3;
-// The starting size in frames for |audio_buffer_|. Previous usage maintained a
-// queue of 16 AudioBuffers, each of 512 frames. This worked well, so we
-// maintain this number of frames.
-static const int kStartingBufferSizeInFrames = 16 * 512;
-
-static_assert(kStartingBufferSizeInFrames <
- (kMaxCapacityInSeconds * limits::kMinSampleRate),
- "max capacity smaller than starting buffer size");
+// The minimum size in ms for the |audio_buffer_|. Arbitrarily determined.
+static const int kStartingCapacityInMs = 200;
AudioRendererAlgorithm::AudioRendererAlgorithm()
: channels_(0),
samples_per_second_(0),
muted_partial_frame_(0),
- capacity_(kStartingBufferSizeInFrames),
+ capacity_(0),
output_time_(0.0),
search_block_center_offset_(0),
search_block_index_(0),
@@ -92,8 +86,9 @@ void AudioRendererAlgorithm::Initialize(const AudioParameters& params) {
channels_ = params.channels();
samples_per_second_ = params.sample_rate();
- num_candidate_blocks_ = (kWsolaSearchIntervalMs * samples_per_second_) / 1000;
- ola_window_size_ = kOlaWindowSizeMs * samples_per_second_ / 1000;
+ capacity_ = ConvertMillisecondsToFrames(kStartingCapacityInMs);
+ num_candidate_blocks_ = ConvertMillisecondsToFrames(kWsolaSearchIntervalMs);
+ ola_window_size_ = ConvertMillisecondsToFrames(kOlaWindowSizeMs);
// Make sure window size in an even number.
ola_window_size_ += ola_window_size_ & 1;
@@ -206,9 +201,9 @@ void AudioRendererAlgorithm::FlushBuffers() {
wsola_output_->Zero();
num_complete_frames_ = 0;
- // Reset |capacity_| so growth triggered by underflows doesn't penalize
- // seek time.
- capacity_ = kStartingBufferSizeInFrames;
+ // Reset |capacity_| so growth triggered by underflows doesn't penalize seek
+ // time.
+ capacity_ = ConvertMillisecondsToFrames(kStartingCapacityInMs);
}
void AudioRendererAlgorithm::EnqueueBuffer(
@@ -235,6 +230,11 @@ bool AudioRendererAlgorithm::CanPerformWsola() const {
search_block_index_ + search_block_size <= frames;
}
+int AudioRendererAlgorithm::ConvertMillisecondsToFrames(int ms) const {
+ return ms * (samples_per_second_ /
+ static_cast<double>(base::Time::kMillisecondsPerSecond));
+}
+
bool AudioRendererAlgorithm::RunOneWsolaIteration(double playback_rate) {
if (!CanPerformWsola())
return false;
diff --git a/media/filters/audio_renderer_algorithm.h b/media/filters/audio_renderer_algorithm.h
index 2005bfe..940e7e7 100644
--- a/media/filters/audio_renderer_algorithm.h
+++ b/media/filters/audio_renderer_algorithm.h
@@ -118,6 +118,9 @@ class MEDIA_EXPORT AudioRendererAlgorithm {
// Do we have enough data to perform one round of WSOLA?
bool CanPerformWsola() const;
+ // Converts a time in milliseconds to frames using |samples_per_second_|.
+ int ConvertMillisecondsToFrames(int ms) const;
+
// Number of channels in audio stream.
int channels_;
diff --git a/media/filters/audio_renderer_algorithm_unittest.cc b/media/filters/audio_renderer_algorithm_unittest.cc
index 003cd51..82c59675 100644
--- a/media/filters/audio_renderer_algorithm_unittest.cc
+++ b/media/filters/audio_renderer_algorithm_unittest.cc
@@ -666,6 +666,7 @@ TEST_F(AudioRendererAlgorithmTest, FillBufferOffset) {
ASSERT_EQ(kHalfSize, frames_filled);
ASSERT_TRUE(VerifyAudioData(bus.get(), 0, kHalfSize, 0));
ASSERT_FALSE(VerifyAudioData(bus.get(), kHalfSize, kHalfSize, 0));
+ FillAlgorithmQueue();
}
const float kMutedRates[] = {5.0f, 0.25f};
@@ -679,6 +680,7 @@ TEST_F(AudioRendererAlgorithmTest, FillBufferOffset) {
ASSERT_EQ(kHalfSize, frames_filled);
ASSERT_FALSE(VerifyAudioData(bus.get(), 0, kHalfSize, 0));
ASSERT_TRUE(VerifyAudioData(bus.get(), kHalfSize, kHalfSize, 0));
+ FillAlgorithmQueue();
}
}