Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1747)

Unified Diff: content/browser/media/session/media_session_impl.cc

Issue 2475473002: Implement one-shot audio focus inside MediaSession (Closed)
Patch Set: . Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/browser/media/session/media_session_impl.cc
diff --git a/content/browser/media/session/media_session_impl.cc b/content/browser/media/session/media_session_impl.cc
index 022efebc1331af527436b75cc650e019644d8266..bb6041d4bb0ec0ea1dd5ec7c3b466e660d488952 100644
--- a/content/browser/media/session/media_session_impl.cc
+++ b/content/browser/media/session/media_session_impl.cc
@@ -65,6 +65,8 @@ MediaSessionImpl* MediaSessionImpl::Get(WebContents* web_contents) {
MediaSessionImpl::~MediaSessionImpl() {
DCHECK(players_.empty());
+ DCHECK(pepper_players_.empty());
+ DCHECK(one_shot_players_.empty());
DCHECK(audio_focus_state_ == State::INACTIVE);
for (auto& observer : observers_)
observer.MediaSessionDestroyed();
@@ -101,16 +103,13 @@ void MediaSessionImpl::SetMetadata(
bool MediaSessionImpl::AddPlayer(MediaSessionPlayerObserver* observer,
int player_id,
media::MediaContentType media_content_type) {
- if (media_content_type == media::MediaContentType::Uncontrollable)
- return true;
+ if (media_content_type == media::MediaContentType::OneShot)
+ return AddOneShotPlayer(observer, player_id);
if (media_content_type == media::MediaContentType::Pepper)
return AddPepperPlayer(observer, player_id);
observer->OnSetVolumeMultiplier(player_id, GetVolumeMultiplier());
- // Determine the audio focus type required for playing the new player.
- // TODO(zqzhang): handle duckable and uncontrollable.
- // See https://crbug.com/639277.
AudioFocusManager::AudioFocusType required_audio_focus_type;
if (media_content_type == media::MediaContentType::Persistent) {
required_audio_focus_type = AudioFocusManager::AudioFocusType::Gain;
@@ -142,7 +141,7 @@ bool MediaSessionImpl::AddPlayer(MediaSessionPlayerObserver* observer,
players_.clear();
players_.insert(PlayerIdentifier(observer, player_id));
- UpdateWebContents();
+ DispatchStateChange();
return true;
}
@@ -157,6 +156,16 @@ void MediaSessionImpl::RemovePlayer(MediaSessionPlayerObserver* observer,
if (it != pepper_players_.end())
pepper_players_.erase(it);
+ it = one_shot_players_.find(PlayerIdentifier(observer, player_id));
+ if (it != one_shot_players_.end()) {
+ one_shot_players_.erase(it);
+
+ // The session may become controllable after all one-shot players are
+ // removed.
+ if (one_shot_players_.empty())
+ DispatchStateChange();
+ }
+
AbandonSystemAudioFocusIfNeeded();
}
@@ -175,6 +184,18 @@ void MediaSessionImpl::RemovePlayers(MediaSessionPlayerObserver* observer) {
++it;
}
+ for (auto it = one_shot_players_.begin(); it != one_shot_players_.end();) {
+ if (it->observer == observer)
+ one_shot_players_.erase(it++);
+ else
+ ++it;
+
+ // The session may become controllable after all one-shot players are
+ // removed.
+ if (one_shot_players_.empty())
+ DispatchStateChange();
+ }
+
AbandonSystemAudioFocusIfNeeded();
}
@@ -191,7 +212,8 @@ void MediaSessionImpl::OnPlayerPaused(MediaSessionPlayerObserver* observer,
// to this session (e.g. a silent video) is paused. MediaSessionImpl
// should ignore the paused player for this case.
if (!players_.count(PlayerIdentifier(observer, player_id)) &&
- !pepper_players_.count(PlayerIdentifier(observer, player_id))) {
+ !pepper_players_.count(PlayerIdentifier(observer, player_id)) &&
+ !one_shot_players_.count(PlayerIdentifier(observer, player_id))) {
return;
}
@@ -203,6 +225,13 @@ void MediaSessionImpl::OnPlayerPaused(MediaSessionPlayerObserver* observer,
return;
}
+ // If the player is a one-shot player, just remove it since it is not expected
+ // to resume a one-shot player via resuming MediaSession.
+ if (one_shot_players_.count(PlayerIdentifier(observer, player_id))) {
+ RemovePlayer(observer, player_id);
+ return;
+ }
+
// Otherwise, suspend the session.
DCHECK(!IsSuspended());
OnSuspendInternal(SuspendType::CONTENT, State::SUSPENDED);
@@ -294,9 +323,11 @@ bool MediaSessionImpl::IsSuspended() const {
bool MediaSessionImpl::IsControllable() const {
// Only media session having focus Gain can be controllable unless it is
- // inactive.
+ // inactive. Also, the session will be uncontrollable if it contains one-shot
+ // players.
return audio_focus_state_ != State::INACTIVE &&
- audio_focus_type_ == AudioFocusManager::AudioFocusType::Gain;
+ audio_focus_type_ == AudioFocusManager::AudioFocusType::Gain &&
+ (one_shot_players_.empty());
}
bool MediaSessionImpl::HasPepper() const {
@@ -324,6 +355,8 @@ MediaSessionUmaHelper* MediaSessionImpl::uma_helper_for_test() {
void MediaSessionImpl::RemoveAllPlayersForTest() {
players_.clear();
+ pepper_players_.clear();
+ one_shot_players_.clear();
whywhat 2016/11/03 14:32:17 nit: I feel there's more code duplication here w.r
Zhiqiang Zhang (Slow) 2016/11/04 14:10:54 Yeah, I feel this too. But as pepper_players_ is l
AbandonSystemAudioFocusIfNeeded();
}
@@ -335,6 +368,9 @@ void MediaSessionImpl::OnSuspendInternal(SuspendType suspend_type,
// UI suspend cannot use State::INACTIVE.
DCHECK(suspend_type == SuspendType::SYSTEM || new_state == State::SUSPENDED);
+ if (!one_shot_players_.empty())
+ return;
+
if (audio_focus_state_ != State::ACTIVE)
return;
@@ -376,7 +412,7 @@ void MediaSessionImpl::OnSuspendInternal(SuspendType suspend_type,
for (const auto& it : pepper_players_)
it.observer->OnSetVolumeMultiplier(it.player_id, kDuckingVolumeMultiplier);
- UpdateWebContents();
+ DispatchStateChange();
}
void MediaSessionImpl::OnResumeInternal(SuspendType suspend_type) {
@@ -391,7 +427,7 @@ void MediaSessionImpl::OnResumeInternal(SuspendType suspend_type) {
for (const auto& it : pepper_players_)
it.observer->OnSetVolumeMultiplier(it.player_id, GetVolumeMultiplier());
- UpdateWebContents();
+ DispatchStateChange();
}
MediaSessionImpl::MediaSessionImpl(WebContents* web_contents)
@@ -423,16 +459,16 @@ bool MediaSessionImpl::RequestSystemAudioFocus(
void MediaSessionImpl::AbandonSystemAudioFocusIfNeeded() {
if (audio_focus_state_ == State::INACTIVE || !players_.empty() ||
- !pepper_players_.empty()) {
+ !pepper_players_.empty() || !one_shot_players_.empty()) {
return;
}
delegate_->AbandonAudioFocus();
SetAudioFocusState(State::INACTIVE);
- UpdateWebContents();
+ DispatchStateChange();
}
-void MediaSessionImpl::UpdateWebContents() {
+void MediaSessionImpl::DispatchStateChange() {
media_session_state_listeners_.Notify(audio_focus_state_);
for (auto& observer : observers_)
observer.MediaSessionStateChanged(IsControllable(), IsSuspended());
@@ -466,6 +502,19 @@ bool MediaSessionImpl::AddPepperPlayer(MediaSessionPlayerObserver* observer,
observer->OnSetVolumeMultiplier(player_id, GetVolumeMultiplier());
+ DispatchStateChange();
+ return true;
+}
+
+bool MediaSessionImpl::AddOneShotPlayer(MediaSessionPlayerObserver* observer,
+ int player_id) {
+ // Don't check whether the request is successful or not. One-shot players
+ // should play uninterrupted.
whywhat 2016/11/03 14:32:16 that means we'd play them even if the user is in t
Zhiqiang Zhang (Slow) 2016/11/04 14:10:54 OK, let's give a chance for the players to respond
+ RequestSystemAudioFocus(AudioFocusManager::AudioFocusType::Gain);
+
+ one_shot_players_.insert(PlayerIdentifier(observer, player_id));
+
+ DispatchStateChange();
return true;
}

Powered by Google App Engine
This is Rietveld 408576698