diff options
author | dalecurtis@chromium.org <dalecurtis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-05-31 04:37:17 +0000 |
---|---|---|
committer | dalecurtis@chromium.org <dalecurtis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-05-31 04:37:17 +0000 |
commit | a1b9dfeb459092e3400fc7e23dc9c9696872be38 (patch) | |
tree | 9b57c3fa52b891ca4bafc314772caee43749be4c /content | |
parent | 675c847ddce27acfae3812dca0e5342f345e2b2a (diff) | |
download | chromium_src-a1b9dfeb459092e3400fc7e23dc9c9696872be38.zip chromium_src-a1b9dfeb459092e3400fc7e23dc9c9696872be38.tar.gz chromium_src-a1b9dfeb459092e3400fc7e23dc9c9696872be38.tar.bz2 |
Don't background processes with active audio output.
If a process is actively rendering audio, it should not be put into
the background state. "Active" is determined by having any stream
in the playing state as considered by AudioRendererHost.
When a tab has active audio, it's already being woken up ~ every
10-20ms, so I expect the power impact of this change to be negligible.
This should reduce glitching under load.
BUG=362294
TEST=Ensure Windows playback under load no longer glitches.
Review URL: https://codereview.chromium.org/298253004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@274020 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
3 files changed, 35 insertions, 2 deletions
diff --git a/content/browser/renderer_host/media/audio_renderer_host.cc b/content/browser/renderer_host/media/audio_renderer_host.cc index fd6b474..9334d94 100644 --- a/content/browser/renderer_host/media/audio_renderer_host.cc +++ b/content/browser/renderer_host/media/audio_renderer_host.cc @@ -61,6 +61,9 @@ class AudioRendererHost::AudioEntry return reader_.get(); } + bool playing() const { return playing_; } + void set_playing(bool playing) { playing_ = playing; } + private: // media::AudioOutputController::EventHandler implementation. virtual void OnCreated() OVERRIDE; @@ -85,6 +88,8 @@ class AudioRendererHost::AudioEntry // The AudioOutputController that manages the audio stream. const scoped_refptr<media::AudioOutputController> controller_; + + bool playing_; }; AudioRendererHost::AudioEntry::AudioEntry( @@ -106,7 +111,8 @@ AudioRendererHost::AudioEntry::AudioEntry( this, params, output_device_id, - reader_.get())) { + reader_.get())), + playing_(false) { DCHECK(controller_.get()); } @@ -127,7 +133,8 @@ AudioRendererHost::AudioRendererHost( mirroring_manager_(mirroring_manager), audio_log_(media_internals->CreateAudioLog( media::AudioLogFactory::AUDIO_OUTPUT_CONTROLLER)), - media_stream_manager_(media_stream_manager) { + media_stream_manager_(media_stream_manager), + num_playing_streams_(0) { DCHECK(audio_manager_); DCHECK(media_stream_manager_); } @@ -275,10 +282,18 @@ void AudioRendererHost::DoNotifyStreamStateChanged(int stream_id, entry->stream_id(), base::Bind(&media::AudioOutputController::ReadCurrentPowerAndClip, entry->controller())); + if (!entry->playing()) { + entry->set_playing(true); + base::AtomicRefCountInc(&num_playing_streams_); + } } else { media_observer->OnAudioStreamStopped(render_process_id_, entry->render_frame_id(), entry->stream_id()); + if (entry->playing()) { + entry->set_playing(false); + base::AtomicRefCountDec(&num_playing_streams_); + } } } } @@ -458,6 +473,8 @@ void AudioRendererHost::DeleteEntry(scoped_ptr<AudioEntry> entry) { media_observer->OnAudioStreamStopped(render_process_id_, entry->render_frame_id(), entry->stream_id()); + if (entry->playing()) + base::AtomicRefCountDec(&num_playing_streams_); } } @@ -483,4 +500,8 @@ AudioRendererHost::AudioEntry* AudioRendererHost::LookupById(int stream_id) { return i != audio_entries_.end() ? i->second : NULL; } +bool AudioRendererHost::HasActiveAudio() { + return !base::AtomicRefCountIsZero(&num_playing_streams_); +} + } // namespace content diff --git a/content/browser/renderer_host/media/audio_renderer_host.h b/content/browser/renderer_host/media/audio_renderer_host.h index 60556ee..38317ef 100644 --- a/content/browser/renderer_host/media/audio_renderer_host.h +++ b/content/browser/renderer_host/media/audio_renderer_host.h @@ -39,6 +39,7 @@ #include <map> +#include "base/atomic_ref_count.h" #include "base/gtest_prod_util.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" @@ -84,6 +85,10 @@ class CONTENT_EXPORT AudioRendererHost : public BrowserMessageFilter { virtual void OnDestruct() const OVERRIDE; virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; + // Returns true if any streams managed by this host are actively playing. Can + // be called from any thread. + bool HasActiveAudio(); + private: friend class AudioRendererHostTest; friend class BrowserThread; @@ -165,6 +170,9 @@ class CONTENT_EXPORT AudioRendererHost : public BrowserMessageFilter { // A map of stream IDs to audio sources. AudioEntryMap audio_entries_; + // The number of streams in the playing state. + base::AtomicRefCount num_playing_streams_; + DISALLOW_COPY_AND_ASSIGN(AudioRendererHost); }; diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index ef0fea2..7a6506e 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc @@ -1960,6 +1960,10 @@ void RenderProcessHostImpl::SetBackgrounded(bool backgrounded) { if (!child_process_launcher_.get() || child_process_launcher_->IsStarting()) return; + // Don't background processes which have active audio streams. + if (backgrounded_ && audio_renderer_host_->HasActiveAudio()) + return; + #if defined(OS_WIN) // The cbstext.dll loads as a global GetMessage hook in the browser process // and intercepts/unintercepts the kernel32 API SetPriorityClass in a |