summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authordalecurtis@chromium.org <dalecurtis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-04-17 06:06:45 +0000
committerdalecurtis@chromium.org <dalecurtis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-04-17 06:06:45 +0000
commit64e0e3b22059b006a2119a14887901f287c9f35e (patch)
tree129c9117a5d1e1abee5dc9d00c8d43ab48fb7e79 /media
parentf212ee13b64f6ced8d0948d51f7c1ac841ecc74d (diff)
downloadchromium_src-64e0e3b22059b006a2119a14887901f287c9f35e.zip
chromium_src-64e0e3b22059b006a2119a14887901f287c9f35e.tar.gz
chromium_src-64e0e3b22059b006a2119a14887901f287c9f35e.tar.bz2
Use larger buffer sizes for lower power on Linux.
HTML5 playback on Linux ALSA, Pulse, and ChromeOS will now use a buffer size of 1024+ for media playback. On my Z620 this takes pulseaudio daemon CPU usage from a solid 3-4% down to 1%. Likely there are savings in the Chrome process as well, but those are harder to measure against process noise. I suspect we'll see greater savings on Chromebooks. BUG=362261 TEST=Audio sounds the same always. CPU usage down. NOTRY=true Review URL: https://codereview.chromium.org/235723003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@264443 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media')
-rw-r--r--media/audio/cras/audio_manager_cras.cc12
-rw-r--r--media/audio/pulse/audio_manager_pulse.cc11
-rw-r--r--media/base/audio_hardware_config.cc52
-rw-r--r--media/base/audio_hardware_config.h4
-rw-r--r--media/base/audio_hardware_config_unittest.cc33
-rw-r--r--media/filters/audio_renderer_impl.cc9
6 files changed, 111 insertions, 10 deletions
diff --git a/media/audio/cras/audio_manager_cras.cc b/media/audio/cras/audio_manager_cras.cc
index ee7cc9c..53f36ab 100644
--- a/media/audio/cras/audio_manager_cras.cc
+++ b/media/audio/cras/audio_manager_cras.cc
@@ -30,6 +30,10 @@ static const int kMaxOutputStreams = 50;
// Default sample rate for input and output streams.
static const int kDefaultSampleRate = 48000;
+// Define bounds for the output buffer size.
+static const int kMinimumOutputBufferSize = 512;
+static const int kMaximumOutputBufferSize = 8192;
+
bool AudioManagerCras::HasAudioOutputDevices() {
return true;
}
@@ -103,11 +107,9 @@ AudioParameters AudioManagerCras::GetPreferredOutputStreamParameters(
const AudioParameters& input_params) {
// TODO(tommi): Support |output_device_id|.
DLOG_IF(ERROR, !output_device_id.empty()) << "Not implemented!";
- static const int kDefaultOutputBufferSize = 512;
-
ChannelLayout channel_layout = CHANNEL_LAYOUT_STEREO;
int sample_rate = kDefaultSampleRate;
- int buffer_size = kDefaultOutputBufferSize;
+ int buffer_size = kMinimumOutputBufferSize;
int bits_per_sample = 16;
int input_channels = 0;
if (input_params.IsValid()) {
@@ -115,7 +117,9 @@ AudioParameters AudioManagerCras::GetPreferredOutputStreamParameters(
bits_per_sample = input_params.bits_per_sample();
channel_layout = input_params.channel_layout();
input_channels = input_params.input_channels();
- buffer_size = input_params.frames_per_buffer();
+ buffer_size =
+ std::min(kMaximumOutputBufferSize,
+ std::max(buffer_size, input_params.frames_per_buffer()));
}
int user_buffer_size = GetUserBufferSize();
diff --git a/media/audio/pulse/audio_manager_pulse.cc b/media/audio/pulse/audio_manager_pulse.cc
index 3369fd5..238530a 100644
--- a/media/audio/pulse/audio_manager_pulse.cc
+++ b/media/audio/pulse/audio_manager_pulse.cc
@@ -35,6 +35,10 @@ using pulse::WaitForOperationCompletion;
// Maximum number of output streams that can be open simultaneously.
static const int kMaxOutputStreams = 50;
+// Define bounds for the output buffer size.
+static const int kMinimumOutputBufferSize = 512;
+static const int kMaximumOutputBufferSize = 8192;
+
static const base::FilePath::CharType kPulseLib[] =
FILE_PATH_LITERAL("libpulse.so.0");
@@ -161,10 +165,9 @@ AudioParameters AudioManagerPulse::GetPreferredOutputStreamParameters(
const AudioParameters& input_params) {
// TODO(tommi): Support |output_device_id|.
VLOG_IF(0, !output_device_id.empty()) << "Not implemented!";
- static const int kDefaultOutputBufferSize = 512;
ChannelLayout channel_layout = CHANNEL_LAYOUT_STEREO;
- int buffer_size = kDefaultOutputBufferSize;
+ int buffer_size = kMinimumOutputBufferSize;
int bits_per_sample = 16;
int input_channels = 0;
int sample_rate;
@@ -172,7 +175,9 @@ AudioParameters AudioManagerPulse::GetPreferredOutputStreamParameters(
bits_per_sample = input_params.bits_per_sample();
channel_layout = input_params.channel_layout();
input_channels = input_params.input_channels();
- buffer_size = std::min(buffer_size, input_params.frames_per_buffer());
+ buffer_size =
+ std::min(kMaximumOutputBufferSize,
+ std::max(buffer_size, input_params.frames_per_buffer()));
sample_rate = input_params.sample_rate();
} else {
sample_rate = GetNativeSampleRate();
diff --git a/media/base/audio_hardware_config.cc b/media/base/audio_hardware_config.cc
index d72fce7..959b90c 100644
--- a/media/base/audio_hardware_config.cc
+++ b/media/base/audio_hardware_config.cc
@@ -4,17 +4,40 @@
#include "media/base/audio_hardware_config.h"
+#include <algorithm>
+
+#include "base/logging.h"
+#include "build/build_config.h"
+
using base::AutoLock;
using media::AudioParameters;
namespace media {
+#if defined(OS_LINUX)
+#define HIGH_LATENCY_AUDIO_SUPPORT 1
+#endif
+
+#if defined(HIGH_LATENCY_AUDIO_SUPPORT)
+// Taken from "Bit Twiddling Hacks"
+// http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
+static uint32_t RoundUpToPowerOfTwo(uint32_t v) {
+ v--;
+ v |= v >> 1;
+ v |= v >> 2;
+ v |= v >> 4;
+ v |= v >> 8;
+ v |= v >> 16;
+ v++;
+ return v;
+}
+#endif
+
AudioHardwareConfig::AudioHardwareConfig(
const AudioParameters& input_params,
const AudioParameters& output_params)
: input_params_(input_params),
- output_params_(output_params) {
-}
+ output_params_(output_params) {}
AudioHardwareConfig::~AudioHardwareConfig() {}
@@ -77,4 +100,29 @@ void AudioHardwareConfig::UpdateOutputConfig(
output_params_ = output_params;
}
+int AudioHardwareConfig::GetHighLatencyBufferSize() const {
+ AutoLock auto_lock(config_lock_);
+#if defined(HIGH_LATENCY_AUDIO_SUPPORT)
+ // Empirically, use the nearest higher power of two buffer size corresponding
+ // to 20 ms worth of samples. For a given sample rate, this works out to:
+ //
+ // <= 3200 : 64
+ // <= 6400 : 128
+ // <= 12800 : 256
+ // <= 25600 : 512
+ // <= 51200 : 1024
+ // <= 102400 : 2048
+ // <= 204800 : 4096
+ //
+ // On Linux, the minimum hardware buffer size is 512, so the lower calculated
+ // values are unused. OSX may have a value as low as 128. Windows is device
+ // dependent but will generally be sample_rate() / 100.
+ const int high_latency_buffer_size =
+ RoundUpToPowerOfTwo(2 * output_params_.sample_rate() / 100);
+ return std::max(output_params_.frames_per_buffer(), high_latency_buffer_size);
+#else
+ return output_params_.frames_per_buffer();
+#endif
+}
+
} // namespace media
diff --git a/media/base/audio_hardware_config.h b/media/base/audio_hardware_config.h
index d1621b98..a4baaac 100644
--- a/media/base/audio_hardware_config.h
+++ b/media/base/audio_hardware_config.h
@@ -41,6 +41,10 @@ class MEDIA_EXPORT AudioHardwareConfig {
void UpdateInputConfig(const media::AudioParameters& input_params);
void UpdateOutputConfig(const media::AudioParameters& output_params);
+ // For clients which don't need low latency, a larger buffer size should be
+ // used to save power and CPU resources.
+ int GetHighLatencyBufferSize() const;
+
private:
// Cached values; access is protected by |config_lock_|.
mutable base::Lock config_lock_;
diff --git a/media/base/audio_hardware_config_unittest.cc b/media/base/audio_hardware_config_unittest.cc
index 4a742bf..357ddca 100644
--- a/media/base/audio_hardware_config_unittest.cc
+++ b/media/base/audio_hardware_config_unittest.cc
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "build/build_config.h"
#include "media/base/audio_hardware_config.h"
#include "media/audio/audio_parameters.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -87,4 +88,36 @@ TEST(AudioHardwareConfig, Setters) {
EXPECT_EQ(kNewInputChannelLayout, fake_config.GetInputChannelLayout());
}
+TEST(AudioHardwareConfig, HighLatencyBufferSizes) {
+ AudioParameters input_params(AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ kInputChannelLayout,
+ kInputSampleRate,
+ 16,
+ kOutputBufferSize);
+ AudioParameters output_params(AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ kOutputChannelLayout,
+ 3200,
+ 16,
+ 32);
+ AudioHardwareConfig fake_config(input_params, output_params);
+
+#if defined(OS_LINUX)
+ EXPECT_EQ(64, fake_config.GetHighLatencyBufferSize());
+
+ for (int i = 6400; i <= 204800; i *= 2) {
+ fake_config.UpdateOutputConfig(
+ AudioParameters(AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ kOutputChannelLayout,
+ i,
+ 16,
+ 32));
+ EXPECT_EQ(2 * (i / 100), fake_config.GetHighLatencyBufferSize());
+ }
+#else
+ // If high latency buffer sizes are not supported, the value should just pass
+ // through the output buffer size.
+ EXPECT_EQ(32, fake_config.GetHighLatencyBufferSize());
+#endif
+}
+
} // namespace content
diff --git a/media/filters/audio_renderer_impl.cc b/media/filters/audio_renderer_impl.cc
index acb43f7..bb279e9 100644
--- a/media/filters/audio_renderer_impl.cc
+++ b/media/filters/audio_renderer_impl.cc
@@ -278,7 +278,14 @@ void AudioRendererImpl::Initialize(DemuxerStream* stream,
buffer_converter_.reset();
} else {
// TODO(rileya): Support hardware config changes
- audio_parameters_ = hardware_config_->GetOutputConfig();
+ const AudioParameters& hw_params = hardware_config_->GetOutputConfig();
+ audio_parameters_.Reset(hw_params.format(),
+ hw_params.channel_layout(),
+ hw_params.channels(),
+ hw_params.input_channels(),
+ hw_params.sample_rate(),
+ hw_params.bits_per_sample(),
+ hardware_config_->GetHighLatencyBufferSize());
}
audio_buffer_stream_.Initialize(