diff options
author | dalecurtis@chromium.org <dalecurtis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-18 22:12:05 +0000 |
---|---|---|
committer | dalecurtis@chromium.org <dalecurtis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-18 22:12:05 +0000 |
commit | 2b392e59ab9a72858d224bad9e422fe40a696a69 (patch) | |
tree | 124296c1b0473baa88c55a66f95d22b3e4623f04 /media/audio/fake_audio_output_stream.cc | |
parent | c9b6e6a5b77de034a13c5d26b9084c40bb0e74c7 (diff) | |
download | chromium_src-2b392e59ab9a72858d224bad9e422fe40a696a69.zip chromium_src-2b392e59ab9a72858d224bad9e422fe40a696a69.tar.gz chromium_src-2b392e59ab9a72858d224bad9e422fe40a696a69.tar.bz2 |
Simulate an audio output stream when a real one isn't available.
Upgrades FakeAudioOutputStream to fake OnMoreData calls using a
PostDelayedTask approach similar to NullAudioSink.
This is necessary for playback of HTML5 videos when a real audio
device is not present. I.e. over remote desktop w/ remote audio
disabled on on some of the Buildbot machines (this should allow
us to remove --disable-audio from many of our tests).
This is a two fold change:
1. AudioOutputResampler will now request an AUDIO_FAKE device
when invalid output parameters are provided.
2. AudioManagerBase will check for AUDIO_FAKE as it always has
but will additionally check if there are any output devices
and if not return a fake stream.
2 is necessary for HTML5 audio since it doesn't use the low
latency output path.
BUG=120749
TEST=unittests. HTML5/Flash video playback over Remote Desktop
w/o Remote Audio works.
Review URL: https://chromiumcodereview.appspot.com/10987087
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@162810 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media/audio/fake_audio_output_stream.cc')
-rw-r--r-- | media/audio/fake_audio_output_stream.cc | 84 |
1 files changed, 48 insertions, 36 deletions
diff --git a/media/audio/fake_audio_output_stream.cc b/media/audio/fake_audio_output_stream.cc index f09fe5d..fe03859 100644 --- a/media/audio/fake_audio_output_stream.cc +++ b/media/audio/fake_audio_output_stream.cc @@ -4,69 +4,81 @@ #include "media/audio/fake_audio_output_stream.h" -#include "base/at_exit.h" +#include "base/bind.h" +#include "base/bind_helpers.h" #include "base/logging.h" #include "media/audio/audio_manager_base.h" namespace media { -FakeAudioOutputStream* FakeAudioOutputStream::current_fake_stream_ = NULL; - // static AudioOutputStream* FakeAudioOutputStream::MakeFakeStream( - AudioManagerBase* manager, - const AudioParameters& params) { - FakeAudioOutputStream* new_stream = new FakeAudioOutputStream(manager, - params); - DCHECK(current_fake_stream_ == NULL); - current_fake_stream_ = new_stream; - return new_stream; + AudioManagerBase* manager, const AudioParameters& params) { + return new FakeAudioOutputStream(manager, params); } -bool FakeAudioOutputStream::Open() { - return true; +FakeAudioOutputStream::FakeAudioOutputStream(AudioManagerBase* manager, + const AudioParameters& params) + : audio_manager_(manager), + callback_(NULL), + audio_bus_(AudioBus::Create(params)), + frames_per_millisecond_( + params.sample_rate() / static_cast<float>( + base::Time::kMillisecondsPerSecond)), + ALLOW_THIS_IN_INITIALIZER_LIST(weak_this_(this)) { } -// static -FakeAudioOutputStream* FakeAudioOutputStream::GetCurrentFakeStream() { - return current_fake_stream_; +FakeAudioOutputStream::~FakeAudioOutputStream() { + DCHECK(!callback_); +} + +bool FakeAudioOutputStream::Open() { + DCHECK(audio_manager_->GetMessageLoop()->BelongsToCurrentThread()); + return true; } void FakeAudioOutputStream::Start(AudioSourceCallback* callback) { + DCHECK(audio_manager_->GetMessageLoop()->BelongsToCurrentThread()); callback_ = callback; - audio_bus_->Zero(); - callback_->OnMoreData(audio_bus_.get(), AudioBuffersState(0, 0)); + audio_manager_->GetMessageLoop()->PostTask(FROM_HERE, base::Bind( + &FakeAudioOutputStream::OnMoreDataTask, weak_this_.GetWeakPtr())); } void FakeAudioOutputStream::Stop() { + DCHECK(audio_manager_->GetMessageLoop()->BelongsToCurrentThread()); callback_ = NULL; } -void FakeAudioOutputStream::SetVolume(double volume) { - volume_ = volume; +void FakeAudioOutputStream::Close() { + DCHECK(!callback_); + DCHECK(audio_manager_->GetMessageLoop()->BelongsToCurrentThread()); + weak_this_.InvalidateWeakPtrs(); + audio_manager_->ReleaseOutputStream(this); } +void FakeAudioOutputStream::SetVolume(double volume) {}; + void FakeAudioOutputStream::GetVolume(double* volume) { - *volume = volume_; -} + *volume = 0; +}; -void FakeAudioOutputStream::Close() { - closed_ = true; - audio_manager_->ReleaseOutputStream(this); -} +void FakeAudioOutputStream::OnMoreDataTask() { + DCHECK(audio_manager_->GetMessageLoop()->BelongsToCurrentThread()); -FakeAudioOutputStream::FakeAudioOutputStream(AudioManagerBase* manager, - const AudioParameters& params) - : audio_manager_(manager), - volume_(0), - callback_(NULL), - closed_(false) { - audio_bus_ = AudioBus::Create(params); -} + audio_bus_->Zero(); + int frames_received = audio_bus_->frames(); + if (callback_) { + frames_received = callback_->OnMoreData( + audio_bus_.get(), AudioBuffersState()); + } -FakeAudioOutputStream::~FakeAudioOutputStream() { - if (current_fake_stream_ == this) - current_fake_stream_ = NULL; + // Calculate our sleep duration for simulated playback. Sleep for at least + // one millisecond so we don't spin the CPU. + MessageLoop::current()->PostDelayedTask( + FROM_HERE, base::Bind( + &FakeAudioOutputStream::OnMoreDataTask, weak_this_.GetWeakPtr()), + base::TimeDelta::FromMilliseconds( + std::max(1.0f, frames_received / frames_per_millisecond_))); } } // namespace media |