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

Side by Side Diff: content/browser/media/session/media_session.cc

Issue 2274873003: Letting Flash join MediaSession (stack implementaion) (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@media_session_type
Patch Set: fixed unduck bug Created 4 years, 3 months 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 unified diff | Download patch
OLDNEW
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698