diff options
author | dalecurtis@chromium.org <dalecurtis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-03-15 04:34:16 +0000 |
---|---|---|
committer | dalecurtis@chromium.org <dalecurtis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-03-15 04:34:16 +0000 |
commit | 8754d953bfca98c6dcc0d716dd8408afe5199248 (patch) | |
tree | a397bfaf171848d4b4020d09318c2e49a7b0d2a8 /media/audio/null_audio_sink.cc | |
parent | b8ad39b6f840b7cb91a6d86f101ed1671a7e009f (diff) | |
download | chromium_src-8754d953bfca98c6dcc0d716dd8408afe5199248.zip chromium_src-8754d953bfca98c6dcc0d716dd8408afe5199248.tar.gz chromium_src-8754d953bfca98c6dcc0d716dd8408afe5199248.tar.bz2 |
Refactor FakeAudioOutputStream, NullAudioSink into FakeAudioConsumer.
We have two fake audio consumers: FakeAudioOutputStream on the browser
side and NullAudioSink on the renderer side. At present we can't remove
NullAudioSink since its used for PipelineIntegrationTests.
This change collapses the common functionality between both consumers
and as an added bonus replaces NullAudioSink's private thread in favor
of sharing the MediaThread.
BUG=none
TEST=unit tests, remote desktop session w/o audio, --disable-audio.
Review URL: https://chromiumcodereview.appspot.com/12334061
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@188251 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media/audio/null_audio_sink.cc')
-rw-r--r-- | media/audio/null_audio_sink.cc | 129 |
1 files changed, 52 insertions, 77 deletions
diff --git a/media/audio/null_audio_sink.cc b/media/audio/null_audio_sink.cc index c93ceb1..37d3ce0 100644 --- a/media/audio/null_audio_sink.cc +++ b/media/audio/null_audio_sink.cc @@ -5,30 +5,34 @@ #include "media/audio/null_audio_sink.h" #include "base/bind.h" +#include "base/message_loop_proxy.h" #include "base/stringprintf.h" #include "base/sys_byteorder.h" -#include "base/threading/platform_thread.h" +#include "media/audio/fake_audio_consumer.h" namespace media { -NullAudioSink::NullAudioSink() +NullAudioSink::NullAudioSink( + const scoped_refptr<base::MessageLoopProxy>& message_loop) : initialized_(false), - playing_(false), callback_(NULL), - thread_("NullAudioThread"), - hash_audio_for_testing_(false) { + hash_audio_for_testing_(false), + channels_(0), + message_loop_(message_loop) { } +NullAudioSink::~NullAudioSink() {} + void NullAudioSink::Initialize(const AudioParameters& params, RenderCallback* callback) { DCHECK(!initialized_); - params_ = params; - audio_bus_ = AudioBus::Create(params_); + fake_consumer_.reset(new FakeAudioConsumer(message_loop_, params)); if (hash_audio_for_testing_) { - md5_channel_contexts_.reset(new base::MD5Context[params_.channels()]); - for (int i = 0; i < params_.channels(); i++) + channels_ = params.channels(); + md5_channel_contexts_.reset(new base::MD5Context[params.channels()]); + for (int i = 0; i < params.channels(); i++) base::MD5Init(&md5_channel_contexts_[i]); } @@ -37,24 +41,27 @@ void NullAudioSink::Initialize(const AudioParameters& params, } void NullAudioSink::Start() { - if (!thread_.Start()) - return; - - thread_.message_loop()->PostTask(FROM_HERE, base::Bind( - &NullAudioSink::FillBufferTask, this)); + DCHECK(message_loop_->BelongsToCurrentThread()); } void NullAudioSink::Stop() { - SetPlaying(false); - thread_.Stop(); + DCHECK(message_loop_->BelongsToCurrentThread()); + + // Stop may be called at any time, so we have to check before stopping. + if (fake_consumer_) + fake_consumer_->Stop(); } void NullAudioSink::Play() { - SetPlaying(true); + DCHECK(message_loop_->BelongsToCurrentThread()); + DCHECK(initialized_); + fake_consumer_->Start(base::Bind( + &NullAudioSink::CallRender, base::Unretained(this))); } void NullAudioSink::Pause(bool /* flush */) { - SetPlaying(false); + DCHECK(message_loop_->BelongsToCurrentThread()); + fake_consumer_->Stop(); } bool NullAudioSink::SetVolume(double volume) { @@ -62,54 +69,24 @@ bool NullAudioSink::SetVolume(double volume) { return volume == 0.0; } -void NullAudioSink::SetPlaying(bool is_playing) { - base::AutoLock auto_lock(lock_); - playing_ = is_playing; -} +void NullAudioSink::CallRender(AudioBus* audio_bus) { + DCHECK(message_loop_->BelongsToCurrentThread()); -NullAudioSink::~NullAudioSink() { - DCHECK(!thread_.IsRunning()); -} + int frames_received = callback_->Render(audio_bus, 0); + if (!hash_audio_for_testing_ || frames_received <= 0) + return; -void NullAudioSink::FillBufferTask() { - base::AutoLock auto_lock(lock_); - - base::TimeDelta delay; - // Only consume buffers when actually playing. - if (playing_) { - int frames_received = callback_->Render(audio_bus_.get(), 0); - int frames_per_millisecond = - params_.sample_rate() / base::Time::kMillisecondsPerSecond; - - if (hash_audio_for_testing_ && frames_received > 0) { - DCHECK_EQ(sizeof(float), sizeof(uint32)); - int channels = audio_bus_->channels(); - for (int channel_idx = 0; channel_idx < channels; ++channel_idx) { - float* channel = audio_bus_->channel(channel_idx); - for (int frame_idx = 0; frame_idx < frames_received; frame_idx++) { - // Convert float to uint32 w/o conversion loss. - uint32 frame = base::ByteSwapToLE32( - bit_cast<uint32>(channel[frame_idx])); - base::MD5Update( - &md5_channel_contexts_[channel_idx], base::StringPiece( - reinterpret_cast<char*>(&frame), sizeof(frame))); - } - } + DCHECK_EQ(sizeof(float), sizeof(uint32)); + int channels = audio_bus->channels(); + for (int channel_idx = 0; channel_idx < channels; ++channel_idx) { + float* channel = audio_bus->channel(channel_idx); + for (int frame_idx = 0; frame_idx < frames_received; frame_idx++) { + // Convert float to uint32 w/o conversion loss. + uint32 frame = base::ByteSwapToLE32(bit_cast<uint32>(channel[frame_idx])); + base::MD5Update(&md5_channel_contexts_[channel_idx], base::StringPiece( + reinterpret_cast<char*>(&frame), sizeof(frame))); } - - // Calculate our sleep duration. - delay = base::TimeDelta::FromMilliseconds( - frames_received / frames_per_millisecond); - } 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))); } void NullAudioSink::StartAudioHashForTesting() { @@ -120,24 +97,22 @@ void NullAudioSink::StartAudioHashForTesting() { std::string NullAudioSink::GetAudioHashForTesting() { DCHECK(hash_audio_for_testing_); - // If initialize failed or was never called, ensure we return an empty hash. - int channels = 1; - if (!initialized_) { - md5_channel_contexts_.reset(new base::MD5Context[1]); - base::MD5Init(&md5_channel_contexts_[0]); - } else { - channels = audio_bus_->channels(); - } - - // Hash all channels into the first channel. base::MD5Digest digest; - for (int i = 1; i < channels; i++) { - base::MD5Final(&digest, &md5_channel_contexts_[i]); - base::MD5Update(&md5_channel_contexts_[0], base::StringPiece( - reinterpret_cast<char*>(&digest), sizeof(base::MD5Digest))); + if (channels_ == 0) { + // If initialize failed or was never called, ensure we return an empty hash. + base::MD5Context context; + base::MD5Init(&context); + base::MD5Final(&digest, &context); + } else { + // Hash all channels into the first channel. + for (int i = 1; i < channels_; i++) { + base::MD5Final(&digest, &md5_channel_contexts_[i]); + base::MD5Update(&md5_channel_contexts_[0], base::StringPiece( + reinterpret_cast<char*>(&digest), sizeof(base::MD5Digest))); + } + base::MD5Final(&digest, &md5_channel_contexts_[0]); } - base::MD5Final(&digest, &md5_channel_contexts_[0]); return base::MD5DigestToBase16(digest); } |