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

Side by Side Diff: content/browser/media/android/browser_media_player_manager.cc

Issue 1372203002: Throttle media decoding after excessive Android media server crashes (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: new infobar text per UI review Created 5 years, 2 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 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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/android/browser_media_player_manager.h" 5 #include "content/browser/media/android/browser_media_player_manager.h"
6 6
7 #include "base/android/scoped_java_ref.h" 7 #include "base/android/scoped_java_ref.h"
8 #include "content/browser/android/content_view_core_impl.h" 8 #include "content/browser/android/content_view_core_impl.h"
9 #include "content/browser/media/android/browser_demuxer_android.h" 9 #include "content/browser/media/android/browser_demuxer_android.h"
10 #include "content/browser/media/android/media_resource_getter_impl.h" 10 #include "content/browser/media/android/media_resource_getter_impl.h"
11 #include "content/browser/media/android/media_session.h" 11 #include "content/browser/media/android/media_session.h"
12 #include "content/browser/media/android/media_throttler.h"
12 #include "content/browser/media/media_web_contents_observer.h" 13 #include "content/browser/media/media_web_contents_observer.h"
13 #include "content/browser/renderer_host/render_view_host_impl.h" 14 #include "content/browser/renderer_host/render_view_host_impl.h"
14 #include "content/browser/web_contents/web_contents_view_android.h" 15 #include "content/browser/web_contents/web_contents_view_android.h"
15 #include "content/common/media/media_player_messages_android.h" 16 #include "content/common/media/media_player_messages_android.h"
16 #include "content/public/browser/android/content_view_core.h" 17 #include "content/public/browser/android/content_view_core.h"
17 #include "content/public/browser/android/external_video_surface_container.h" 18 #include "content/public/browser/android/external_video_surface_container.h"
18 #include "content/public/browser/browser_context.h" 19 #include "content/public/browser/browser_context.h"
19 #include "content/public/browser/browser_thread.h" 20 #include "content/public/browser/browser_thread.h"
20 #include "content/public/browser/content_browser_client.h" 21 #include "content/public/browser/content_browser_client.h"
21 #include "content/public/browser/render_frame_host.h" 22 #include "content/public/browser/render_frame_host.h"
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
136 switch (media_player_params.type) { 137 switch (media_player_params.type) {
137 case MEDIA_PLAYER_TYPE_URL: { 138 case MEDIA_PLAYER_TYPE_URL: {
138 const std::string user_agent = GetContentClient()->GetUserAgent(); 139 const std::string user_agent = GetContentClient()->GetUserAgent();
139 MediaPlayerBridge* media_player_bridge = new MediaPlayerBridge( 140 MediaPlayerBridge* media_player_bridge = new MediaPlayerBridge(
140 media_player_params.player_id, 141 media_player_params.player_id,
141 media_player_params.url, 142 media_player_params.url,
142 media_player_params.first_party_for_cookies, 143 media_player_params.first_party_for_cookies,
143 user_agent, 144 user_agent,
144 hide_url_log, 145 hide_url_log,
145 this, 146 this,
146 base::Bind(&BrowserMediaPlayerManager::OnMediaResourcesRequested, 147 base::Bind(&BrowserMediaPlayerManager::OnDecoderResourcesReleased,
147 weak_ptr_factory_.GetWeakPtr()), 148 weak_ptr_factory_.GetWeakPtr()),
148 media_player_params.frame_url, 149 media_player_params.frame_url,
149 media_player_params.allow_credentials); 150 media_player_params.allow_credentials);
150 ContentViewCoreImpl* content_view_core_impl = 151 ContentViewCoreImpl* content_view_core_impl =
151 static_cast<ContentViewCoreImpl*>(ContentViewCore::FromWebContents( 152 static_cast<ContentViewCoreImpl*>(ContentViewCore::FromWebContents(
152 web_contents_)); 153 web_contents_));
153 if (!content_view_core_impl) { 154 if (!content_view_core_impl
154 // May reach here due to prerendering. Don't extract the metadata 155 // Initialize the player will cause MediaMetadataExtractor to decode
155 // since it is expensive. 156 // small chunks of data.
157 || !RequestDecoderResources(media_player_params.player_id, true)) {
158 // May reach here due to prerendering or throttling. Don't extract the
159 // metadata since it is expensive.
156 // TODO(qinmin): extract the metadata once the user decided to load 160 // TODO(qinmin): extract the metadata once the user decided to load
157 // the page. 161 // the page.
158 OnMediaMetadataChanged( 162 OnMediaMetadataChanged(
159 media_player_params.player_id, base::TimeDelta(), 0, 0, false); 163 media_player_params.player_id, base::TimeDelta(), 0, 0, false);
160 } else if (!content_view_core_impl->ShouldBlockMediaRequest( 164 } else if (!content_view_core_impl->ShouldBlockMediaRequest(
161 media_player_params.url)) { 165 media_player_params.url)) {
162 media_player_bridge->Initialize(); 166 media_player_bridge->Initialize();
163 } 167 }
164 return media_player_bridge; 168 return media_player_bridge;
165 } 169 }
166 170
167 case MEDIA_PLAYER_TYPE_MEDIA_SOURCE: { 171 case MEDIA_PLAYER_TYPE_MEDIA_SOURCE: {
168 if (media::UseMediaThreadForMediaPlayback()) { 172 if (media::UseMediaThreadForMediaPlayback()) {
169 return new MediaCodecPlayer( 173 return new MediaCodecPlayer(
170 media_player_params.player_id, 174 media_player_params.player_id,
171 weak_ptr_factory_.GetWeakPtr(), 175 weak_ptr_factory_.GetWeakPtr(),
172 base::Bind(&BrowserMediaPlayerManager::OnMediaResourcesRequested, 176 base::Bind(&BrowserMediaPlayerManager::OnDecoderResourcesReleased,
173 weak_ptr_factory_.GetWeakPtr()), 177 weak_ptr_factory_.GetWeakPtr()),
174 demuxer->CreateDemuxer(media_player_params.demuxer_client_id), 178 demuxer->CreateDemuxer(media_player_params.demuxer_client_id),
175 media_player_params.frame_url); 179 media_player_params.frame_url);
176 } else { 180 } else {
177 return new MediaSourcePlayer( 181 return new MediaSourcePlayer(
178 media_player_params.player_id, 182 media_player_params.player_id,
179 this, 183 this,
180 base::Bind(&BrowserMediaPlayerManager::OnMediaResourcesRequested, 184 base::Bind(&BrowserMediaPlayerManager::OnDecoderResourcesReleased,
181 weak_ptr_factory_.GetWeakPtr()), 185 weak_ptr_factory_.GetWeakPtr()),
182 demuxer->CreateDemuxer(media_player_params.demuxer_client_id), 186 demuxer->CreateDemuxer(media_player_params.demuxer_client_id),
183 media_player_params.frame_url); 187 media_player_params.frame_url);
184 } 188 }
185 } 189 }
186 } 190 }
187 191
188 NOTREACHED(); 192 NOTREACHED();
189 return NULL; 193 return NULL;
190 } 194 }
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
312 } 316 }
313 317
314 void BrowserMediaPlayerManager::OnSeekComplete( 318 void BrowserMediaPlayerManager::OnSeekComplete(
315 int player_id, 319 int player_id,
316 const base::TimeDelta& current_time) { 320 const base::TimeDelta& current_time) {
317 Send(new MediaPlayerMsg_SeekCompleted(RoutingID(), player_id, current_time)); 321 Send(new MediaPlayerMsg_SeekCompleted(RoutingID(), player_id, current_time));
318 } 322 }
319 323
320 void BrowserMediaPlayerManager::OnError(int player_id, int error) { 324 void BrowserMediaPlayerManager::OnError(int player_id, int error) {
321 Send(new MediaPlayerMsg_MediaError(RoutingID(), player_id, error)); 325 Send(new MediaPlayerMsg_MediaError(RoutingID(), player_id, error));
322 if (fullscreen_player_id_ == player_id) 326 if (fullscreen_player_id_ == player_id &&
327 error != MediaPlayerAndroid::MEDIA_ERROR_INVALID_CODE) {
323 video_view_->OnMediaPlayerError(error); 328 video_view_->OnMediaPlayerError(error);
329 }
324 } 330 }
325 331
326 void BrowserMediaPlayerManager::OnVideoSizeChanged( 332 void BrowserMediaPlayerManager::OnVideoSizeChanged(
327 int player_id, int width, int height) { 333 int player_id, int width, int height) {
328 Send(new MediaPlayerMsg_MediaVideoSizeChanged(RoutingID(), player_id, 334 Send(new MediaPlayerMsg_MediaVideoSizeChanged(RoutingID(), player_id,
329 width, height)); 335 width, height));
330 if (fullscreen_player_id_ == player_id) 336 if (fullscreen_player_id_ == player_id)
331 video_view_->OnVideoSizeChanged(width, height); 337 video_view_->OnVideoSizeChanged(width, height);
332 } 338 }
333 339
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
468 // In case we're stealing the external surface from another player. 474 // In case we're stealing the external surface from another player.
469 ReleasePlayerOfExternalVideoSurfaceIfNeeded(player_id); 475 ReleasePlayerOfExternalVideoSurfaceIfNeeded(player_id);
470 external_video_surface_container_->RequestExternalVideoSurface( 476 external_video_surface_container_->RequestExternalVideoSurface(
471 player_id, 477 player_id,
472 base::Bind(&BrowserMediaPlayerManager::AttachExternalVideoSurface, 478 base::Bind(&BrowserMediaPlayerManager::AttachExternalVideoSurface,
473 base::Unretained(this)), 479 base::Unretained(this)),
474 base::Bind(&BrowserMediaPlayerManager::DetachExternalVideoSurface, 480 base::Bind(&BrowserMediaPlayerManager::DetachExternalVideoSurface,
475 base::Unretained(this))); 481 base::Unretained(this)));
476 } 482 }
477 } 483 }
484
485 void BrowserMediaPlayerManager::ReleaseExternalSurface(int player_id) {
486 if (external_video_surface_container_)
487 external_video_surface_container_->ReleaseExternalVideoSurface(player_id);
488 }
478 #endif // defined(VIDEO_HOLE) 489 #endif // defined(VIDEO_HOLE)
479 490
480 void BrowserMediaPlayerManager::OnEnterFullscreen(int player_id) { 491 void BrowserMediaPlayerManager::OnEnterFullscreen(int player_id) {
481 DCHECK_EQ(fullscreen_player_id_, kInvalidMediaPlayerId); 492 DCHECK_EQ(fullscreen_player_id_, kInvalidMediaPlayerId);
482 #if defined(VIDEO_HOLE) 493 #if defined(VIDEO_HOLE)
483 // If this fullscreen player is started when another player 494 // If this fullscreen player is started when another player
484 // uses the external surface, release that other player. 495 // uses the external surface, release that other player.
485 ReleasePlayerOfExternalVideoSurfaceIfNeeded(player_id); 496 ReleasePlayerOfExternalVideoSurfaceIfNeeded(player_id);
486 if (external_video_surface_container_) 497 if (external_video_surface_container_)
487 external_video_surface_container_->ReleaseExternalVideoSurface(player_id); 498 external_video_surface_container_->ReleaseExternalVideoSurface(player_id);
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
526 if (!player) 537 if (!player)
527 return; 538 return;
528 539
529 AddPlayer(player); 540 AddPlayer(player);
530 } 541 }
531 542
532 void BrowserMediaPlayerManager::OnStart(int player_id) { 543 void BrowserMediaPlayerManager::OnStart(int player_id) {
533 MediaPlayerAndroid* player = GetPlayer(player_id); 544 MediaPlayerAndroid* player = GetPlayer(player_id);
534 if (!player) 545 if (!player)
535 return; 546 return;
536 player->Start(); 547
537 if (fullscreen_player_id_ == player_id && fullscreen_player_is_released_) { 548 if (RequestDecoderResources(player_id, false)) {
538 video_view_->OpenVideo(); 549 StartInternal(player_id);
539 fullscreen_player_is_released_ = false; 550 } else if (WebContentsDelegate* delegate = web_contents_->GetDelegate()){
551 delegate->RequestMediaDecodePermission(
552 web_contents_,
553 base::Bind(&BrowserMediaPlayerManager::OnPlaybackPermissionGranted,
554 weak_ptr_factory_.GetWeakPtr(), player_id));
540 } 555 }
541 } 556 }
542 557
543 void BrowserMediaPlayerManager::OnSeek( 558 void BrowserMediaPlayerManager::OnSeek(
544 int player_id, 559 int player_id,
545 const base::TimeDelta& time) { 560 const base::TimeDelta& time) {
546 MediaPlayerAndroid* player = GetPlayer(player_id); 561 MediaPlayerAndroid* player = GetPlayer(player_id);
547 if (player) 562 if (player)
548 player->SeekTo(time); 563 player->SeekTo(time);
549 } 564 }
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
600 615
601 void BrowserMediaPlayerManager::AddPlayer(MediaPlayerAndroid* player) { 616 void BrowserMediaPlayerManager::AddPlayer(MediaPlayerAndroid* player) {
602 DCHECK(!GetPlayer(player->player_id())); 617 DCHECK(!GetPlayer(player->player_id()));
603 players_.push_back(player); 618 players_.push_back(player);
604 } 619 }
605 620
606 void BrowserMediaPlayerManager::RemovePlayer(int player_id) { 621 void BrowserMediaPlayerManager::RemovePlayer(int player_id) {
607 for (ScopedVector<MediaPlayerAndroid>::iterator it = players_.begin(); 622 for (ScopedVector<MediaPlayerAndroid>::iterator it = players_.begin();
608 it != players_.end(); ++it) { 623 it != players_.end(); ++it) {
609 if ((*it)->player_id() == player_id) { 624 if ((*it)->player_id() == player_id) {
610 ReleaseMediaResources(player_id); 625 #if defined(VIDEO_HOLE)
626 ReleaseExternalSurface(player_id);
627 #endif
611 (*it)->DeleteOnCorrectThread(); 628 (*it)->DeleteOnCorrectThread();
612 players_.weak_erase(it); 629 players_.weak_erase(it);
613 MediaSession::Get(web_contents())->RemovePlayer(this, player_id); 630 MediaSession::Get(web_contents())->RemovePlayer(this, player_id);
614 break; 631 break;
615 } 632 }
616 } 633 }
634 active_players_.erase(player_id);
617 } 635 }
618 636
619 scoped_ptr<media::MediaPlayerAndroid> BrowserMediaPlayerManager::SwapPlayer( 637 scoped_ptr<media::MediaPlayerAndroid> BrowserMediaPlayerManager::SwapPlayer(
620 int player_id, media::MediaPlayerAndroid* player) { 638 int player_id, media::MediaPlayerAndroid* player) {
621 media::MediaPlayerAndroid* previous_player = NULL; 639 media::MediaPlayerAndroid* previous_player = NULL;
622 for (ScopedVector<MediaPlayerAndroid>::iterator it = players_.begin(); 640 for (ScopedVector<MediaPlayerAndroid>::iterator it = players_.begin();
623 it != players_.end(); ++it) { 641 it != players_.end(); ++it) {
624 if ((*it)->player_id() == player_id) { 642 if ((*it)->player_id() == player_id) {
625 previous_player = *it; 643 previous_player = *it;
626 ReleaseMediaResources(player_id); 644 #if defined(VIDEO_HOLE)
645 ReleaseExternalSurface(player_id);
646 #endif
627 players_.weak_erase(it); 647 players_.weak_erase(it);
628 players_.push_back(player); 648 players_.push_back(player);
629 break; 649 break;
630 } 650 }
631 } 651 }
632 return scoped_ptr<media::MediaPlayerAndroid>(previous_player); 652 return scoped_ptr<media::MediaPlayerAndroid>(previous_player);
633 } 653 }
634 654
655 bool BrowserMediaPlayerManager::RequestDecoderResources(
656 int player_id, bool temporary) {
657 if (!MediaThrottler::GetInstance()->RequestDecoderResources())
658 return false;
659
660 ActivePlayerMap::iterator it;
661 // The player is already active, ignore it. A long running player should not
662 // request temporary permissions.
663 if ((it = active_players_.find(player_id)) != active_players_.end()) {
664 DCHECK(!temporary || it->second);
665 return true;
666 }
667
668 if (!temporary) {
669 int long_running_player = 0;
670 for (it = active_players_.begin(); it != active_players_.end(); ++it) {
671 if (!it->second)
672 long_running_player++;
673 }
674
675 // Number of active players are less than the threshold, do nothing.
676 if (long_running_player < kMediaPlayerThreshold)
677 return true;
678
679 for (it = active_players_.begin(); it != active_players_.end(); ++it) {
680 if (!it->second && !GetPlayer(it->first)->IsPlaying() &&
681 fullscreen_player_id_ != it->first) {
682 ReleasePlayer(GetPlayer(it->first));
683 Send(new MediaPlayerMsg_MediaPlayerReleased(RoutingID(),
684 (it->first)));
685 }
686 }
687 }
688
689 active_players_[player_id] = temporary;
690 return true;
691 }
692
693 void BrowserMediaPlayerManager::OnDecoderResourcesReleased(int player_id) {
694 if (active_players_.find(player_id) == active_players_.end())
695 return;
696
697 active_players_.erase(player_id);
698 MediaThrottler::GetInstance()->OnDecodeRequestFinished();
699 }
700
635 int BrowserMediaPlayerManager::RoutingID() { 701 int BrowserMediaPlayerManager::RoutingID() {
636 return render_frame_host_->GetRoutingID(); 702 return render_frame_host_->GetRoutingID();
637 } 703 }
638 704
639 bool BrowserMediaPlayerManager::Send(IPC::Message* msg) { 705 bool BrowserMediaPlayerManager::Send(IPC::Message* msg) {
640 return render_frame_host_->Send(msg); 706 return render_frame_host_->Send(msg);
641 } 707 }
642 708
643 void BrowserMediaPlayerManager::ReleaseFullscreenPlayer( 709 void BrowserMediaPlayerManager::ReleaseFullscreenPlayer(
644 MediaPlayerAndroid* player) { 710 MediaPlayerAndroid* player) {
645 ReleasePlayer(player); 711 ReleasePlayer(player);
646 } 712 }
647 713
648 void BrowserMediaPlayerManager::OnMediaResourcesRequested(int player_id) {
649 int num_active_player = 0;
650 ScopedVector<MediaPlayerAndroid>::iterator it;
651 for (it = players_.begin(); it != players_.end(); ++it) {
652 if (!(*it)->IsPlayerReady())
653 continue;
654
655 // The player is already active, ignore it.
656 if ((*it)->player_id() == player_id)
657 return;
658 else
659 num_active_player++;
660 }
661
662 // Number of active players are less than the threshold, do nothing.
663 if (num_active_player < kMediaPlayerThreshold)
664 return;
665
666 for (it = players_.begin(); it != players_.end(); ++it) {
667 if ((*it)->IsPlayerReady() && !(*it)->IsPlaying() &&
668 fullscreen_player_id_ != (*it)->player_id()) {
669 ReleasePlayer(*it);
670 Send(new MediaPlayerMsg_MediaPlayerReleased(RoutingID(),
671 (*it)->player_id()));
672 }
673 }
674 }
675
676 void BrowserMediaPlayerManager::ReleaseMediaResources(int player_id) {
677 #if defined(VIDEO_HOLE)
678 if (external_video_surface_container_)
679 external_video_surface_container_->ReleaseExternalVideoSurface(player_id);
680 #endif // defined(VIDEO_HOLE)
681 }
682
683 void BrowserMediaPlayerManager::ReleasePlayer(MediaPlayerAndroid* player) { 714 void BrowserMediaPlayerManager::ReleasePlayer(MediaPlayerAndroid* player) {
684 player->Release(); 715 player->Release();
685 ReleaseMediaResources(player->player_id()); 716 #if defined(VIDEO_HOLE)
717 ReleaseExternalSurface(player->player_id());
718 #endif
719 }
720
721 void BrowserMediaPlayerManager::OnPlaybackPermissionGranted(
722 int player_id, bool granted) {
723 if (!granted)
724 return;
725
726 MediaThrottler::GetInstance()->Reset();
727 StartInternal(player_id);
728 }
729
730 void BrowserMediaPlayerManager::StartInternal(int player_id) {
731 MediaPlayerAndroid* player = GetPlayer(player_id);
732 if (!player)
733 return;
734 player->Start();
735 if (fullscreen_player_id_ == player_id && fullscreen_player_is_released_) {
736 video_view_->OpenVideo();
737 fullscreen_player_is_released_ = false;
738 }
686 } 739 }
687 740
688 } // namespace content 741 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/media/android/browser_media_player_manager.h ('k') | content/browser/media/android/media_throttler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698