summaryrefslogtreecommitdiffstats
path: root/media/audio
diff options
context:
space:
mode:
authorvrk@chromium.org <vrk@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-04-06 03:17:44 +0000
committervrk@chromium.org <vrk@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-04-06 03:17:44 +0000
commite4fc09e874d7a7fc87dc1565452d32985949a3cf (patch)
tree8a8a5f596294a3db7c6aa3998b8562a4b24e60e9 /media/audio
parentf2ebbf06167ad4ff8cb23109b3652c8c4b7ff5f7 (diff)
downloadchromium_src-e4fc09e874d7a7fc87dc1565452d32985949a3cf.zip
chromium_src-e4fc09e874d7a7fc87dc1565452d32985949a3cf.tar.gz
chromium_src-e4fc09e874d7a7fc87dc1565452d32985949a3cf.tar.bz2
Merge AudioRendererImpl and AudioRendererBase; add NullAudioSink
This CL removes AudioRendererImpl and replaces it with AudioRendererBase. NullAudioRenderer is also removed and replaced with NullAudioSink. Also, a subtle bug is fixed in AudioRendererBase to allow for smooth video playback when running Chrome with the --disable-audio flag. BUG=119549,116645 TEST=media_unittests, playing video on Chrome/content_shell with and without --disable-audio flag should look identical Review URL: http://codereview.chromium.org/9826023 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@131089 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media/audio')
-rw-r--r--media/audio/audio_util.cc32
-rw-r--r--media/audio/audio_util.h4
-rw-r--r--media/audio/null_audio_sink.cc110
-rw-r--r--media/audio/null_audio_sink.h65
4 files changed, 211 insertions, 0 deletions
diff --git a/media/audio/audio_util.cc b/media/audio/audio_util.cc
index c15e845..01d71ee 100644
--- a/media/audio/audio_util.cc
+++ b/media/audio/audio_util.cc
@@ -427,6 +427,38 @@ ChannelLayout GetAudioInputHardwareChannelLayout(const std::string& device_id) {
#endif
}
+// Computes a buffer size based on the given |sample_rate|. Must be used in
+// conjunction with AUDIO_PCM_LINEAR.
+size_t GetHighLatencyOutputBufferSize(int sample_rate) {
+ // TODO(vrk/crogers): The buffer sizes that this function computes is probably
+ // overly conservative. However, reducing the buffer size to 2048-8192 bytes
+ // caused crbug.com/108396. This computation should be revisited while making
+ // sure crbug.com/108396 doesn't happen again.
+
+ // The minimum number of samples in a hardware packet.
+ // This value is selected so that we can handle down to 5khz sample rate.
+ static const size_t kMinSamplesPerHardwarePacket = 1024;
+
+ // The maximum number of samples in a hardware packet.
+ // This value is selected so that we can handle up to 192khz sample rate.
+ static const size_t kMaxSamplesPerHardwarePacket = 64 * 1024;
+
+ // This constant governs the hardware audio buffer size, this value should be
+ // chosen carefully.
+ // This value is selected so that we have 8192 samples for 48khz streams.
+ static const size_t kMillisecondsPerHardwarePacket = 170;
+
+ // Select the number of samples that can provide at least
+ // |kMillisecondsPerHardwarePacket| worth of audio data.
+ size_t samples = kMinSamplesPerHardwarePacket;
+ while (samples <= kMaxSamplesPerHardwarePacket &&
+ samples * base::Time::kMillisecondsPerSecond <
+ sample_rate * kMillisecondsPerHardwarePacket) {
+ samples *= 2;
+ }
+ return samples;
+}
+
// When transferring data in the shared memory, first word is size of data
// in bytes. Actual data starts immediately after it.
diff --git a/media/audio/audio_util.h b/media/audio/audio_util.h
index 2fccc1e..df5683f 100644
--- a/media/audio/audio_util.h
+++ b/media/audio/audio_util.h
@@ -107,6 +107,10 @@ MEDIA_EXPORT size_t GetAudioHardwareBufferSize();
MEDIA_EXPORT ChannelLayout GetAudioInputHardwareChannelLayout(
const std::string& device_id);
+// Computes a buffer size based on the given |sample_rate|. Must be used in
+// conjunction with AUDIO_PCM_LINEAR.
+MEDIA_EXPORT size_t GetHighLatencyOutputBufferSize(int sample_rate);
+
// Functions that handle data buffer passed between processes in the shared
// memory. Called on both IPC sides.
diff --git a/media/audio/null_audio_sink.cc b/media/audio/null_audio_sink.cc
new file mode 100644
index 0000000..e8cd4eb
--- /dev/null
+++ b/media/audio/null_audio_sink.cc
@@ -0,0 +1,110 @@
+// 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/audio/null_audio_sink.h"
+
+#include "base/bind.h"
+#include "base/threading/platform_thread.h"
+
+namespace media {
+
+NullAudioSink::NullAudioSink()
+ : initialized_(false),
+ playback_rate_(0.0),
+ playing_(false),
+ callback_(NULL),
+ thread_("NullAudioThread") {
+}
+
+NullAudioSink::~NullAudioSink() {
+ DCHECK(!thread_.IsRunning());
+ for (size_t i = 0; i < audio_data_.size(); ++i)
+ delete [] audio_data_[i];
+}
+
+
+void NullAudioSink::Start() {
+ if (!thread_.Start())
+ return;
+
+ thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
+ &NullAudioSink::FillBufferTask, this));
+}
+
+void NullAudioSink::Stop() {
+ SetPlaying(false);
+ thread_.Stop();
+}
+
+void NullAudioSink::Play() {
+ SetPlaying(true);
+}
+
+void NullAudioSink::Pause(bool /* flush */) {
+ SetPlaying(false);
+}
+
+void NullAudioSink::SetPlaybackRate(float rate) {
+ base::AutoLock auto_lock(lock_);
+ playback_rate_ = rate;
+}
+
+bool NullAudioSink::SetVolume(double volume) {
+ // Audio is always muted.
+ return volume == 0.0;
+}
+
+void NullAudioSink::GetVolume(double* volume) {
+ // Audio is always muted.
+ *volume = 0.0;
+}
+
+void NullAudioSink::SetPlaying(bool is_playing) {
+ base::AutoLock auto_lock(lock_);
+ playing_ = is_playing;
+}
+
+void NullAudioSink::Initialize(const AudioParameters& params,
+ RenderCallback* callback) {
+ DCHECK(!initialized_);
+ params_ = params;
+
+ audio_data_.reserve(params.channels());
+ for (int i = 0; i < params.channels(); ++i) {
+ float* channel_data = new float[params.frames_per_buffer()];
+ audio_data_.push_back(channel_data);
+ }
+
+ callback_ = callback;
+ initialized_ = true;
+}
+
+void NullAudioSink::FillBufferTask() {
+ base::AutoLock auto_lock(lock_);
+
+ base::TimeDelta delay;
+ // Only consume buffers when actually playing.
+ if (playing_) {
+ DCHECK_GT(playback_rate_, 0.0f);
+ int requested_frames = params_.frames_per_buffer();
+ int frames_received = callback_->Render(audio_data_, requested_frames, 0);
+ int frames_per_millisecond =
+ params_.sample_rate() / base::Time::kMillisecondsPerSecond;
+
+ // Calculate our sleep duration, taking playback rate into consideration.
+ delay = base::TimeDelta::FromMilliseconds(
+ frames_received / (frames_per_millisecond * playback_rate_));
+ } else {
+ // If paused, sleep for 10 milliseconds before polling again.
+ delay = base::TimeDelta::FromMilliseconds(10);
+ }
+
+ // Sleep for at least one millisecond so we don't spin the CPU.
+ MessageLoop::current()->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&NullAudioSink::FillBufferTask, this),
+ std::max(delay, base::TimeDelta::FromMilliseconds(1)));
+}
+
+} // namespace media
diff --git a/media/audio/null_audio_sink.h b/media/audio/null_audio_sink.h
new file mode 100644
index 0000000..32245eb
--- /dev/null
+++ b/media/audio/null_audio_sink.h
@@ -0,0 +1,65 @@
+// 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_FILTERS_NULL_AUDIO_RENDERER_H_
+#define MEDIA_FILTERS_NULL_AUDIO_RENDERER_H_
+
+// NullAudioSink effectively uses an extra thread to "throw away" the
+// audio data at a rate resembling normal playback speed. It's just like
+// decoding to /dev/null!
+//
+// NullAudioSink can also be used in situations where the client has no
+// audio device or we haven't written an audio implementation for a particular
+// platform yet.
+
+#include <vector>
+
+#include "base/threading/thread.h"
+#include "media/base/audio_renderer_sink.h"
+
+namespace media {
+
+class MEDIA_EXPORT NullAudioSink
+ : NON_EXPORTED_BASE(public AudioRendererSink) {
+ public:
+ NullAudioSink();
+ virtual ~NullAudioSink();
+
+ // AudioRendererSink implementation.
+ virtual void Initialize(const AudioParameters& params,
+ RenderCallback* callback) OVERRIDE;
+ virtual void Start() OVERRIDE;
+ virtual void Stop() OVERRIDE;
+ virtual void Pause(bool flush) OVERRIDE;
+ virtual void Play() OVERRIDE;
+ virtual void SetPlaybackRate(float rate) OVERRIDE;
+ virtual bool SetVolume(double volume) OVERRIDE;
+ virtual void GetVolume(double* volume) OVERRIDE;
+
+ private:
+ // Audio thread task that periodically calls FillBuffer() to consume
+ // audio data.
+ void FillBufferTask();
+
+ void SetPlaying(bool is_playing);
+
+ // A buffer passed to FillBuffer to advance playback.
+ std::vector<float*> audio_data_;
+
+ AudioParameters params_;
+ bool initialized_;
+ float playback_rate_;
+ bool playing_;
+ RenderCallback* callback_;
+
+ // Separate thread used to throw away data.
+ base::Thread thread_;
+ base::Lock lock_;
+
+ DISALLOW_COPY_AND_ASSIGN(NullAudioSink);
+};
+
+} // namespace media
+
+#endif // MEDIA_FILTERS_NULL_AUDIO_RENDERER_H_