forked from chromium/chromium
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Replumb audible playback detection to use a poll-based approach.
The previous approach involved hopping across three threads for every data update, and was riddled with a number of other warts. This change contains a rewrite of AudioStreamIndicator (now called AudioStreamMonitor) to: 1) use an efficient polling-based approach for audible tab detection; 2) resolve bug 339133 by using simple debouncing logic; 3) solve the problem of massively redundantly notifying the tab UI when no state changes occur. Also, this functionality now has unit tests where it did not before. Other changes: 1. Adding miu@ to OWNERS for tab media indicator-related code. 2. While making interface changes in MediaObserver, I did a little work to help migrate from render view IDs to render frame IDs. BUG=339133 TEST=New AudioStreamMonitorTest's in unit_tests. Also, manually confirmed behavior fixes using repro steps in bug 339133. Review URL: https://codereview.chromium.org/135013008 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@256346 0039d316-1c4b-4281-b951-d872f2087c98
- Loading branch information
miu@chromium.org
committed
Mar 11, 2014
1 parent
fb35788
commit aed46f1
Showing
22 changed files
with
704 additions
and
352 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
// Copyright 2014 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 "chrome/browser/media/audio_stream_monitor.h" | ||
|
||
#include "base/bind.h" | ||
#include "base/bind_helpers.h" | ||
#include "content/public/browser/invalidate_type.h" | ||
#include "content/public/browser/web_contents.h" | ||
|
||
DEFINE_WEB_CONTENTS_USER_DATA_KEY(AudioStreamMonitor); | ||
|
||
AudioStreamMonitor::AudioStreamMonitor(content::WebContents* contents) | ||
: web_contents_(contents), | ||
clock_(&default_tick_clock_), | ||
was_recently_audible_(false) { | ||
DCHECK(web_contents_); | ||
} | ||
|
||
AudioStreamMonitor::~AudioStreamMonitor() {} | ||
|
||
bool AudioStreamMonitor::WasRecentlyAudible() const { | ||
DCHECK(thread_checker_.CalledOnValidThread()); | ||
return was_recently_audible_; | ||
} | ||
|
||
void AudioStreamMonitor::StartMonitoringStream( | ||
int stream_id, | ||
const ReadPowerAndClipCallback& read_power_callback) { | ||
DCHECK(thread_checker_.CalledOnValidThread()); | ||
DCHECK(!read_power_callback.is_null()); | ||
poll_callbacks_[stream_id] = read_power_callback; | ||
if (!poll_timer_.IsRunning()) { | ||
poll_timer_.Start( | ||
FROM_HERE, | ||
base::TimeDelta::FromSeconds(1) / kPowerMeasurementsPerSecond, | ||
base::Bind(&AudioStreamMonitor::Poll, base::Unretained(this))); | ||
} | ||
} | ||
|
||
void AudioStreamMonitor::StopMonitoringStream(int stream_id) { | ||
DCHECK(thread_checker_.CalledOnValidThread()); | ||
poll_callbacks_.erase(stream_id); | ||
if (poll_callbacks_.empty()) | ||
poll_timer_.Stop(); | ||
} | ||
|
||
void AudioStreamMonitor::Poll() { | ||
for (StreamPollCallbackMap::const_iterator it = poll_callbacks_.begin(); | ||
it != poll_callbacks_.end(); | ||
++it) { | ||
// TODO(miu): A new UI for delivering specific power level and clipping | ||
// information is still in the works. For now, we throw away all | ||
// information except for "is it audible?" | ||
const float power_dbfs = it->second.Run().first; | ||
const float kSilenceThresholdDBFS = -72.24719896f; | ||
if (power_dbfs >= kSilenceThresholdDBFS) { | ||
last_blurt_time_ = clock_->NowTicks(); | ||
MaybeToggle(); | ||
break; // No need to poll remaining streams. | ||
} | ||
} | ||
} | ||
|
||
void AudioStreamMonitor::MaybeToggle() { | ||
const bool indicator_was_on = was_recently_audible_; | ||
const base::TimeTicks off_time = | ||
last_blurt_time_ + base::TimeDelta::FromMilliseconds(kHoldOnMilliseconds); | ||
const base::TimeTicks now = clock_->NowTicks(); | ||
const bool should_indicator_be_on = now < off_time; | ||
|
||
if (should_indicator_be_on != indicator_was_on) { | ||
was_recently_audible_ = should_indicator_be_on; | ||
web_contents_->NotifyNavigationStateChanged(content::INVALIDATE_TYPE_TAB); | ||
} | ||
|
||
if (!should_indicator_be_on) { | ||
off_timer_.Stop(); | ||
} else if (!off_timer_.IsRunning()) { | ||
off_timer_.Start( | ||
FROM_HERE, | ||
off_time - now, | ||
base::Bind(&AudioStreamMonitor::MaybeToggle, base::Unretained(this))); | ||
} | ||
} |
Oops, something went wrong.