Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/media/session/media_session.h" | 5 #include "content/browser/media/session/media_session.h" |
| 6 | 6 |
| 7 #include "content/browser/media/session/media_session_delegate.h" | 7 #include "content/browser/media/session/media_session_delegate.h" |
| 8 #include "content/browser/media/session/media_session_observer.h" | 8 #include "content/browser/media/session/media_session_observer.h" |
| 9 #include "content/browser/web_contents/web_contents_impl.h" | 9 #include "content/browser/web_contents/web_contents_impl.h" |
| 10 #include "content/public/browser/web_contents.h" | 10 #include "content/public/browser/web_contents.h" |
| 11 #include "content/public/browser/web_contents_delegate.h" | 11 #include "content/public/browser/web_contents_delegate.h" |
| 12 #include "media/base/media_content_type.h" | 12 #include "media/base/media_content_type.h" |
| 13 | 13 |
| 14 namespace content { | 14 namespace content { |
| 15 | 15 |
| 16 namespace { | 16 namespace { |
| 17 | 17 |
| 18 const double kDefaultVolumeMultiplier = 1.0; | 18 const double kDefaultVolumeMultiplier = 1.0; |
| 19 const double kDuckingVolumeMultiplier = 0.2; | |
| 19 | 20 |
| 20 } // anonymous namespace | 21 } // anonymous namespace |
| 21 | 22 |
| 22 using MediaSessionSuspendedSource = | 23 using MediaSessionSuspendedSource = |
| 23 MediaSessionUmaHelper::MediaSessionSuspendedSource; | 24 MediaSessionUmaHelper::MediaSessionSuspendedSource; |
| 24 | 25 |
| 25 DEFINE_WEB_CONTENTS_USER_DATA_KEY(MediaSession); | 26 DEFINE_WEB_CONTENTS_USER_DATA_KEY(MediaSession); |
| 26 | 27 |
| 27 MediaSession::PlayerIdentifier::PlayerIdentifier(MediaSessionObserver* observer, | 28 MediaSession::PlayerIdentifier::PlayerIdentifier(MediaSessionObserver* observer, |
| 28 int player_id) | 29 int player_id) |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 63 metadata_ = metadata; | 64 metadata_ = metadata; |
| 64 // TODO(zqzhang): On Android, the metadata is sent though JNI everytime the | 65 // TODO(zqzhang): On Android, the metadata is sent though JNI everytime the |
| 65 // media session play/pause state changes. Need to find a way to seprate the | 66 // media session play/pause state changes. Need to find a way to seprate the |
| 66 // state change and Metadata update. See https://crbug.com/621855. | 67 // state change and Metadata update. See https://crbug.com/621855. |
| 67 static_cast<WebContentsImpl*>(web_contents())->OnMediaSessionStateChanged(); | 68 static_cast<WebContentsImpl*>(web_contents())->OnMediaSessionStateChanged(); |
| 68 } | 69 } |
| 69 | 70 |
| 70 bool MediaSession::AddPlayer(MediaSessionObserver* observer, | 71 bool MediaSession::AddPlayer(MediaSessionObserver* observer, |
| 71 int player_id, | 72 int player_id, |
| 72 media::MediaContentType media_content_type) { | 73 media::MediaContentType media_content_type) { |
| 73 observer->OnSetVolumeMultiplier(player_id, volume_multiplier_); | 74 if (media_content_type == media::MediaContentType::Pepper) |
| 75 return AddPepperPlayer(observer, player_id); | |
| 76 | |
| 77 observer->OnSetVolumeMultiplier(player_id, GetVolumeMultiplier()); | |
|
whywhat
2016/08/30 21:09:37
seems like this change should be rebased on top of
| |
| 74 | 78 |
| 75 // Determine the audio focus type required for playing the new player. | 79 // Determine the audio focus type required for playing the new player. |
| 76 // TODO(zqzhang): handle duckable and uncontrollable. | 80 // TODO(zqzhang): handle duckable and uncontrollable. |
| 77 // See https://crbug.com/639277. | 81 // See https://crbug.com/639277. |
| 78 AudioFocusManager::AudioFocusType required_audio_focus_type; | 82 AudioFocusManager::AudioFocusType required_audio_focus_type; |
| 79 if (media_content_type == media::MediaContentType::Persistent) { | 83 if (media_content_type == media::MediaContentType::Persistent) { |
| 80 required_audio_focus_type = AudioFocusManager::AudioFocusType::Gain; | 84 required_audio_focus_type = AudioFocusManager::AudioFocusType::Gain; |
| 81 } else { | 85 } else { |
| 82 required_audio_focus_type = | 86 required_audio_focus_type = |
| 83 AudioFocusManager::AudioFocusType::GainTransientMayDuck; | 87 AudioFocusManager::AudioFocusType::GainTransientMayDuck; |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 114 | 118 |
| 115 return true; | 119 return true; |
| 116 } | 120 } |
| 117 | 121 |
| 118 void MediaSession::RemovePlayer(MediaSessionObserver* observer, | 122 void MediaSession::RemovePlayer(MediaSessionObserver* observer, |
| 119 int player_id) { | 123 int player_id) { |
| 120 auto it = players_.find(PlayerIdentifier(observer, player_id)); | 124 auto it = players_.find(PlayerIdentifier(observer, player_id)); |
| 121 if (it != players_.end()) | 125 if (it != players_.end()) |
| 122 players_.erase(it); | 126 players_.erase(it); |
| 123 | 127 |
| 128 it = pepper_players_.find(PlayerIdentifier(observer, player_id)); | |
| 129 if (it != pepper_players_.end()) | |
| 130 pepper_players_.erase(it); | |
| 131 | |
| 124 AbandonSystemAudioFocusIfNeeded(); | 132 AbandonSystemAudioFocusIfNeeded(); |
| 125 } | 133 } |
| 126 | 134 |
| 127 void MediaSession::RemovePlayers(MediaSessionObserver* observer) { | 135 void MediaSession::RemovePlayers(MediaSessionObserver* observer) { |
| 128 for (auto it = players_.begin(); it != players_.end();) { | 136 for (auto it = players_.begin(); it != players_.end();) { |
| 129 if (it->observer == observer) | 137 if (it->observer == observer) |
| 130 players_.erase(it++); | 138 players_.erase(it++); |
| 131 else | 139 else |
| 132 ++it; | 140 ++it; |
| 133 } | 141 } |
| 134 | 142 |
| 143 for (auto it = pepper_players_.begin(); it != pepper_players_.end();) { | |
|
whywhat
2016/08/30 21:09:37
nit: extract a helper function or a predicate and
| |
| 144 if (it->observer == observer) | |
| 145 pepper_players_.erase(it++); | |
| 146 else | |
| 147 ++it; | |
| 148 } | |
| 149 | |
| 135 AbandonSystemAudioFocusIfNeeded(); | 150 AbandonSystemAudioFocusIfNeeded(); |
| 136 } | 151 } |
| 137 | 152 |
| 138 void MediaSession::RecordSessionDuck() { | 153 void MediaSession::RecordSessionDuck() { |
| 139 uma_helper_.RecordSessionSuspended( | 154 uma_helper_.RecordSessionSuspended( |
| 140 MediaSessionSuspendedSource::SystemTransientDuck); | 155 MediaSessionSuspendedSource::SystemTransientDuck); |
| 141 } | 156 } |
| 142 | 157 |
| 143 void MediaSession::OnPlayerPaused(MediaSessionObserver* observer, | 158 void MediaSession::OnPlayerPaused(MediaSessionObserver* observer, |
| 144 int player_id) { | 159 int player_id) { |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 196 if (suspend_type == SuspendType::SYSTEM) { | 211 if (suspend_type == SuspendType::SYSTEM) { |
| 197 OnSuspendInternal(suspend_type, State::INACTIVE); | 212 OnSuspendInternal(suspend_type, State::INACTIVE); |
| 198 return; | 213 return; |
| 199 } | 214 } |
| 200 | 215 |
| 201 if (audio_focus_state_ != State::SUSPENDED) | 216 if (audio_focus_state_ != State::SUSPENDED) |
| 202 OnSuspendInternal(suspend_type, State::SUSPENDED); | 217 OnSuspendInternal(suspend_type, State::SUSPENDED); |
| 203 | 218 |
| 204 DCHECK(audio_focus_state_ == State::SUSPENDED); | 219 DCHECK(audio_focus_state_ == State::SUSPENDED); |
| 205 players_.clear(); | 220 players_.clear(); |
| 221 | |
| 222 for (const auto& it : pepper_players_) | |
| 223 it.observer->OnSetVolumeMultiplier( | |
|
whywhat
2016/08/30 21:09:37
nit: not a one-liner, use {}
| |
| 224 it.player_id, GetPepperVolumeMultiplier()); | |
| 225 | |
| 206 AbandonSystemAudioFocusIfNeeded(); | 226 AbandonSystemAudioFocusIfNeeded(); |
| 207 } | 227 } |
| 208 | 228 |
| 209 void MediaSession::SetVolumeMultiplier(double volume_multiplier) { | 229 void MediaSession::Duck() { |
| 210 volume_multiplier_ = volume_multiplier; | 230 if (is_ducking_) |
| 231 return; | |
| 232 | |
| 233 is_ducking_ = true; | |
| 211 for (const auto& it : players_) | 234 for (const auto& it : players_) |
| 212 it.observer->OnSetVolumeMultiplier(it.player_id, volume_multiplier_); | 235 it.observer->OnSetVolumeMultiplier(it.player_id, GetVolumeMultiplier()); |
| 236 for (const auto& it : pepper_players_) | |
| 237 it.observer->OnSetVolumeMultiplier( | |
| 238 it.player_id, GetPepperVolumeMultiplier()); | |
| 239 } | |
| 240 | |
| 241 void MediaSession::Unduck() { | |
| 242 if (!is_ducking_) | |
| 243 return; | |
| 244 | |
| 245 is_ducking_ = false; | |
| 246 for (const auto& it : players_) | |
| 247 it.observer->OnSetVolumeMultiplier(it.player_id, GetVolumeMultiplier()); | |
| 248 for (const auto& it : pepper_players_) { | |
| 249 it.observer->OnSetVolumeMultiplier( | |
| 250 it.player_id, GetPepperVolumeMultiplier()); | |
| 251 } | |
| 213 } | 252 } |
| 214 | 253 |
| 215 bool MediaSession::IsActive() const { | 254 bool MediaSession::IsActive() const { |
| 216 return audio_focus_state_ == State::ACTIVE; | 255 return audio_focus_state_ == State::ACTIVE; |
| 217 } | 256 } |
| 218 | 257 |
| 219 bool MediaSession::IsReallySuspended() const { | 258 bool MediaSession::IsReallySuspended() const { |
| 220 return audio_focus_state_ == State::SUSPENDED; | 259 return audio_focus_state_ == State::SUSPENDED; |
| 221 } | 260 } |
| 222 | 261 |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 298 suspend_type_ = suspend_type; | 337 suspend_type_ = suspend_type; |
| 299 | 338 |
| 300 if (suspend_type != SuspendType::CONTENT) { | 339 if (suspend_type != SuspendType::CONTENT) { |
| 301 // SuspendType::CONTENT happens when the suspend action came from | 340 // SuspendType::CONTENT happens when the suspend action came from |
| 302 // the page in which case the player is already paused. | 341 // the page in which case the player is already paused. |
| 303 // Otherwise, the players need to be paused. | 342 // Otherwise, the players need to be paused. |
| 304 for (const auto& it : players_) | 343 for (const auto& it : players_) |
| 305 it.observer->OnSuspend(it.player_id); | 344 it.observer->OnSuspend(it.player_id); |
| 306 } | 345 } |
| 307 | 346 |
| 347 for (const auto& it : pepper_players_) | |
| 348 it.observer->OnSetVolumeMultiplier(it.player_id, kDuckingVolumeMultiplier); | |
| 349 | |
| 308 UpdateWebContents(); | 350 UpdateWebContents(); |
| 309 } | 351 } |
| 310 | 352 |
| 311 void MediaSession::OnResumeInternal(SuspendType suspend_type) { | 353 void MediaSession::OnResumeInternal(SuspendType suspend_type) { |
| 312 if (suspend_type == SuspendType::SYSTEM && suspend_type_ != suspend_type) | 354 if (suspend_type == SuspendType::SYSTEM && suspend_type_ != suspend_type) |
| 313 return; | 355 return; |
| 314 | 356 |
| 315 SetAudioFocusState(State::ACTIVE); | 357 SetAudioFocusState(State::ACTIVE); |
| 316 | 358 |
| 317 for (const auto& it : players_) | 359 for (const auto& it : players_) |
| 318 it.observer->OnResume(it.player_id); | 360 it.observer->OnResume(it.player_id); |
| 319 | 361 |
| 362 for (const auto& it : pepper_players_) | |
|
whywhat
2016/08/30 21:09:37
it seems like with a couple of exceptions we handl
| |
| 363 it.observer->OnSetVolumeMultiplier( | |
| 364 it.player_id, GetPepperVolumeMultiplier()); | |
| 365 | |
| 320 UpdateWebContents(); | 366 UpdateWebContents(); |
| 321 } | 367 } |
| 322 | 368 |
| 323 MediaSession::MediaSession(WebContents* web_contents) | 369 MediaSession::MediaSession(WebContents* web_contents) |
| 324 : WebContentsObserver(web_contents), | 370 : WebContentsObserver(web_contents), |
| 325 audio_focus_state_(State::INACTIVE), | 371 audio_focus_state_(State::INACTIVE), |
| 326 audio_focus_type_( | 372 audio_focus_type_( |
| 327 AudioFocusManager::AudioFocusType::GainTransientMayDuck), | 373 AudioFocusManager::AudioFocusType::GainTransientMayDuck), |
| 328 volume_multiplier_(kDefaultVolumeMultiplier) {} | 374 is_ducking_(false), |
| 375 is_on_top_(false) {} | |
| 329 | 376 |
| 330 void MediaSession::Initialize() { | 377 void MediaSession::Initialize() { |
| 331 delegate_ = MediaSessionDelegate::Create(this); | 378 delegate_ = MediaSessionDelegate::Create(this); |
| 332 } | 379 } |
| 333 | 380 |
| 334 bool MediaSession::RequestSystemAudioFocus( | 381 bool MediaSession::RequestSystemAudioFocus( |
| 335 AudioFocusManager::AudioFocusType audio_focus_type) { | 382 AudioFocusManager::AudioFocusType audio_focus_type) { |
| 336 bool result = delegate_->RequestAudioFocus(audio_focus_type); | 383 bool result = delegate_->RequestAudioFocus(audio_focus_type); |
| 337 uma_helper_.RecordRequestAudioFocusResult(result); | 384 uma_helper_.RecordRequestAudioFocusResult(result); |
| 338 return result; | 385 return result; |
| 339 } | 386 } |
| 340 | 387 |
| 341 void MediaSession::AbandonSystemAudioFocusIfNeeded() { | 388 void MediaSession::AbandonSystemAudioFocusIfNeeded() { |
| 342 if (audio_focus_state_ == State::INACTIVE || !players_.empty()) | 389 if (audio_focus_state_ == State::INACTIVE || !players_.empty() || |
| 390 !pepper_players_.empty()) | |
| 343 return; | 391 return; |
| 344 | 392 |
| 345 delegate_->AbandonAudioFocus(); | 393 delegate_->AbandonAudioFocus(); |
| 346 | 394 |
| 347 SetAudioFocusState(State::INACTIVE); | 395 SetAudioFocusState(State::INACTIVE); |
| 348 UpdateWebContents(); | 396 UpdateWebContents(); |
| 349 } | 397 } |
| 350 | 398 |
| 351 void MediaSession::UpdateWebContents() { | 399 void MediaSession::UpdateWebContents() { |
| 352 media_session_state_listeners_.Notify(audio_focus_state_); | 400 media_session_state_listeners_.Notify(audio_focus_state_); |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 364 break; | 412 break; |
| 365 case State::SUSPENDED: | 413 case State::SUSPENDED: |
| 366 uma_helper_.OnSessionSuspended(); | 414 uma_helper_.OnSessionSuspended(); |
| 367 break; | 415 break; |
| 368 case State::INACTIVE: | 416 case State::INACTIVE: |
| 369 uma_helper_.OnSessionInactive(); | 417 uma_helper_.OnSessionInactive(); |
| 370 break; | 418 break; |
| 371 } | 419 } |
| 372 } | 420 } |
| 373 | 421 |
| 422 double MediaSession::GetVolumeMultiplier() const { | |
| 423 return is_ducking_ ? kDuckingVolumeMultiplier : kDefaultVolumeMultiplier; | |
| 424 } | |
| 425 | |
| 426 double MediaSession::GetPepperVolumeMultiplier() const { | |
| 427 if (is_on_top_) | |
| 428 return kDefaultVolumeMultiplier; | |
| 429 if (!IsActive() || is_ducking_) | |
|
whywhat
2016/08/30 21:09:37
nit: is this equivalent to
if (!is_on_top_ && (!I
| |
| 430 return kDuckingVolumeMultiplier; | |
| 431 return kDefaultVolumeMultiplier; | |
| 432 } | |
| 433 | |
| 434 bool MediaSession::AddPepperPlayer(MediaSessionObserver* observer, | |
| 435 int player_id) { | |
| 436 AudioFocusManager::AudioFocusType focus_type = | |
| 437 AudioFocusManager::AudioFocusType::Gain; | |
| 438 State audio_focus_state = | |
| 439 RequestSystemAudioFocus(focus_type) ? State::ACTIVE : State::INACTIVE; | |
| 440 SetAudioFocusState(audio_focus_state); | |
| 441 audio_focus_type_ = focus_type; | |
| 442 pepper_players_.insert(PlayerIdentifier(observer, player_id)); | |
| 443 | |
| 444 observer->OnSetVolumeMultiplier(player_id, GetPepperVolumeMultiplier()); | |
| 445 | |
| 446 return true; | |
| 447 } | |
| 448 | |
| 449 void MediaSession::SetOnTop(bool is_on_top) { | |
|
whywhat
2016/08/30 21:09:37
isn't it equivalent to got audio focus / active ju
Zhiqiang Zhang (Slow)
2016/08/31 14:37:34
Yeah, I agree that SetOnTop() sounds like a dirty
whywhat
2016/08/31 18:37:09
It sounds as a dirty hack because it exposes the f
| |
| 450 if (is_on_top_ == is_on_top) | |
| 451 return; | |
| 452 | |
| 453 is_on_top_ = is_on_top; | |
| 454 for (const auto& it : pepper_players_) { | |
| 455 it.observer->OnSetVolumeMultiplier( | |
| 456 it.player_id, GetPepperVolumeMultiplier()); | |
| 457 } | |
| 458 } | |
| 459 | |
| 374 } // namespace content | 460 } // namespace content |
| OLD | NEW |