diff options
author | vrk@chromium.org <vrk@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-04-06 03:17:44 +0000 |
---|---|---|
committer | vrk@chromium.org <vrk@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-04-06 03:17:44 +0000 |
commit | e4fc09e874d7a7fc87dc1565452d32985949a3cf (patch) | |
tree | 8a8a5f596294a3db7c6aa3998b8562a4b24e60e9 /media/audio | |
parent | f2ebbf06167ad4ff8cb23109b3652c8c4b7ff5f7 (diff) | |
download | chromium_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.cc | 32 | ||||
-rw-r--r-- | media/audio/audio_util.h | 4 | ||||
-rw-r--r-- | media/audio/null_audio_sink.cc | 110 | ||||
-rw-r--r-- | media/audio/null_audio_sink.h | 65 |
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_ |