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

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

Powered by Google App Engine
This is Rietveld 408576698