diff options
author | dalecurtis <dalecurtis@chromium.org> | 2015-08-13 14:33:19 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-08-13 21:33:58 +0000 |
commit | 6bf5bc1cde021e9b25dc3c6d342d7a96a79402f7 (patch) | |
tree | 981bb91ae4738b593d5447bc7720a8c8fceb678e | |
parent | 9b16970b9f3b8b28054d32b15099bffe55ec1722 (diff) | |
download | chromium_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}
-rw-r--r-- | media/filters/audio_renderer_algorithm.cc | 28 | ||||
-rw-r--r-- | media/filters/audio_renderer_algorithm.h | 3 | ||||
-rw-r--r-- | media/filters/audio_renderer_algorithm_unittest.cc | 2 |
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(); } } |