Index: content/browser/media/android/browser_media_player_manager.cc |
diff --git a/content/browser/media/android/browser_media_player_manager.cc b/content/browser/media/android/browser_media_player_manager.cc |
index e52732360555fd4e32d36f6de6640f2752fd67b3..559ef1eea2a7084f9c4ba6e6aec889ca81c4fc98 100644 |
--- a/content/browser/media/android/browser_media_player_manager.cc |
+++ b/content/browser/media/android/browser_media_player_manager.cc |
@@ -10,6 +10,7 @@ |
#include "content/browser/media/android/browser_demuxer_android.h" |
#include "content/browser/media/android/media_resource_getter_impl.h" |
#include "content/browser/media/android/media_session.h" |
+#include "content/browser/media/android/media_throttler.h" |
#include "content/browser/media/media_web_contents_observer.h" |
#include "content/browser/renderer_host/render_view_host_impl.h" |
#include "content/browser/web_contents/web_contents_view_android.h" |
@@ -144,16 +145,19 @@ MediaPlayerAndroid* BrowserMediaPlayerManager::CreateMediaPlayer( |
user_agent, |
hide_url_log, |
this, |
- base::Bind(&BrowserMediaPlayerManager::OnMediaResourcesRequested, |
+ base::Bind(&BrowserMediaPlayerManager::OnDecoderResourcesReleased, |
weak_ptr_factory_.GetWeakPtr()), |
media_player_params.frame_url, |
media_player_params.allow_credentials); |
ContentViewCoreImpl* content_view_core_impl = |
static_cast<ContentViewCoreImpl*>(ContentViewCore::FromWebContents( |
web_contents_)); |
- if (!content_view_core_impl) { |
- // May reach here due to prerendering. Don't extract the metadata |
- // since it is expensive. |
+ if (!content_view_core_impl |
+ // Initialize the player will cause MediaMetadataExtractor to decode |
+ // small chunks of data. |
+ || !RequestDecoderResources(media_player_params.player_id, true)) { |
+ // May reach here due to prerendering or throttling. Don't extract the |
+ // metadata since it is expensive. |
// TODO(qinmin): extract the metadata once the user decided to load |
// the page. |
OnMediaMetadataChanged( |
@@ -171,7 +175,7 @@ MediaPlayerAndroid* BrowserMediaPlayerManager::CreateMediaPlayer( |
return new MediaCodecPlayer( |
media_player_params.player_id, |
weak_ptr_factory_.GetWeakPtr(), |
- base::Bind(&BrowserMediaPlayerManager::OnMediaResourcesRequested, |
+ base::Bind(&BrowserMediaPlayerManager::OnDecoderResourcesReleased, |
weak_ptr_factory_.GetWeakPtr()), |
demuxer->CreateDemuxer(media_player_params.demuxer_client_id), |
media_player_params.frame_url); |
@@ -179,7 +183,7 @@ MediaPlayerAndroid* BrowserMediaPlayerManager::CreateMediaPlayer( |
return new MediaSourcePlayer( |
media_player_params.player_id, |
this, |
- base::Bind(&BrowserMediaPlayerManager::OnMediaResourcesRequested, |
+ base::Bind(&BrowserMediaPlayerManager::OnDecoderResourcesReleased, |
weak_ptr_factory_.GetWeakPtr()), |
demuxer->CreateDemuxer(media_player_params.demuxer_client_id), |
media_player_params.frame_url); |
@@ -321,8 +325,10 @@ void BrowserMediaPlayerManager::OnSeekComplete( |
void BrowserMediaPlayerManager::OnError(int player_id, int error) { |
Send(new MediaPlayerMsg_MediaError(RoutingID(), player_id, error)); |
- if (fullscreen_player_id_ == player_id) |
+ if (fullscreen_player_id_ == player_id && |
+ error != MediaPlayerAndroid::MEDIA_ERROR_INVALID_CODE) { |
video_view_->OnMediaPlayerError(error); |
+ } |
} |
void BrowserMediaPlayerManager::OnVideoSizeChanged( |
@@ -478,6 +484,11 @@ void BrowserMediaPlayerManager::OnRequestExternalSurface( |
base::Unretained(this))); |
} |
} |
+ |
+void BrowserMediaPlayerManager::ReleaseExternalSurface(int player_id) { |
+ if (external_video_surface_container_) |
+ external_video_surface_container_->ReleaseExternalVideoSurface(player_id); |
+} |
#endif // defined(VIDEO_HOLE) |
void BrowserMediaPlayerManager::OnEnterFullscreen(int player_id) { |
@@ -536,10 +547,14 @@ void BrowserMediaPlayerManager::OnStart(int player_id) { |
MediaPlayerAndroid* player = GetPlayer(player_id); |
if (!player) |
return; |
- player->Start(); |
- if (fullscreen_player_id_ == player_id && fullscreen_player_is_released_) { |
- video_view_->OpenVideo(); |
- fullscreen_player_is_released_ = false; |
+ |
+ if (RequestDecoderResources(player_id, false)) { |
+ StartInternal(player_id); |
+ } else if (WebContentsDelegate* delegate = web_contents_->GetDelegate()){ |
+ delegate->RequestMediaDecodePermission( |
+ web_contents_, |
+ base::Bind(&BrowserMediaPlayerManager::OnPlaybackPermissionGranted, |
+ weak_ptr_factory_.GetWeakPtr(), player_id)); |
} |
} |
@@ -610,13 +625,16 @@ void BrowserMediaPlayerManager::RemovePlayer(int player_id) { |
for (ScopedVector<MediaPlayerAndroid>::iterator it = players_.begin(); |
it != players_.end(); ++it) { |
if ((*it)->player_id() == player_id) { |
- ReleaseMediaResources(player_id); |
+#if defined(VIDEO_HOLE) |
+ ReleaseExternalSurface(player_id); |
+#endif |
(*it)->DeleteOnCorrectThread(); |
players_.weak_erase(it); |
MediaSession::Get(web_contents())->RemovePlayer(this, player_id); |
break; |
} |
} |
+ active_players_.erase(player_id); |
} |
scoped_ptr<media::MediaPlayerAndroid> BrowserMediaPlayerManager::SwapPlayer( |
@@ -626,7 +644,9 @@ scoped_ptr<media::MediaPlayerAndroid> BrowserMediaPlayerManager::SwapPlayer( |
it != players_.end(); ++it) { |
if ((*it)->player_id() == player_id) { |
previous_player = *it; |
- ReleaseMediaResources(player_id); |
+#if defined(VIDEO_HOLE) |
+ ReleaseExternalSurface(player_id); |
+#endif |
players_.weak_erase(it); |
players_.push_back(player); |
break; |
@@ -635,6 +655,52 @@ scoped_ptr<media::MediaPlayerAndroid> BrowserMediaPlayerManager::SwapPlayer( |
return scoped_ptr<media::MediaPlayerAndroid>(previous_player); |
} |
+bool BrowserMediaPlayerManager::RequestDecoderResources( |
+ int player_id, bool temporary) { |
+ if (!MediaThrottler::GetInstance()->RequestDecoderResources()) |
+ return false; |
+ |
+ ActivePlayerMap::iterator it; |
+ // The player is already active, ignore it. A long running player should not |
+ // request temporary permissions. |
+ if ((it = active_players_.find(player_id)) != active_players_.end()) { |
+ DCHECK(!temporary || it->second); |
+ return true; |
+ } |
+ |
+ if (!temporary) { |
+ int long_running_player = 0; |
+ for (it = active_players_.begin(); it != active_players_.end(); ++it) { |
+ if (!it->second) |
+ long_running_player++; |
+ } |
+ |
+ // Number of active players are less than the threshold, do nothing. |
+ if (long_running_player < kMediaPlayerThreshold) |
+ return true; |
+ |
+ for (it = active_players_.begin(); it != active_players_.end(); ++it) { |
+ if (!it->second && !GetPlayer(it->first)->IsPlaying() && |
+ fullscreen_player_id_ != it->first) { |
+ ReleasePlayer(GetPlayer(it->first)); |
+ Send(new MediaPlayerMsg_MediaPlayerReleased(RoutingID(), |
+ (it->first))); |
+ } |
+ } |
+ } |
+ |
+ active_players_[player_id] = temporary; |
+ return true; |
+} |
+ |
+void BrowserMediaPlayerManager::OnDecoderResourcesReleased(int player_id) { |
+ if (active_players_.find(player_id) == active_players_.end()) |
+ return; |
+ |
+ active_players_.erase(player_id); |
+ MediaThrottler::GetInstance()->OnDecodeRequestFinished(); |
+} |
+ |
int BrowserMediaPlayerManager::RoutingID() { |
return render_frame_host_->GetRoutingID(); |
} |
@@ -648,44 +714,31 @@ void BrowserMediaPlayerManager::ReleaseFullscreenPlayer( |
ReleasePlayer(player); |
} |
-void BrowserMediaPlayerManager::OnMediaResourcesRequested(int player_id) { |
- int num_active_player = 0; |
- ScopedVector<MediaPlayerAndroid>::iterator it; |
- for (it = players_.begin(); it != players_.end(); ++it) { |
- if (!(*it)->IsPlayerReady()) |
- continue; |
- |
- // The player is already active, ignore it. |
- if ((*it)->player_id() == player_id) |
- return; |
- else |
- num_active_player++; |
- } |
+void BrowserMediaPlayerManager::ReleasePlayer(MediaPlayerAndroid* player) { |
+ player->Release(); |
+#if defined(VIDEO_HOLE) |
+ ReleaseExternalSurface(player->player_id()); |
+#endif |
+} |
- // Number of active players are less than the threshold, do nothing. |
- if (num_active_player < kMediaPlayerThreshold) |
+void BrowserMediaPlayerManager::OnPlaybackPermissionGranted( |
+ int player_id, bool granted) { |
+ if (!granted) |
return; |
- for (it = players_.begin(); it != players_.end(); ++it) { |
- if ((*it)->IsPlayerReady() && !(*it)->IsPlaying() && |
- fullscreen_player_id_ != (*it)->player_id()) { |
- ReleasePlayer(*it); |
- Send(new MediaPlayerMsg_MediaPlayerReleased(RoutingID(), |
- (*it)->player_id())); |
- } |
- } |
+ MediaThrottler::GetInstance()->Reset(); |
+ StartInternal(player_id); |
} |
-void BrowserMediaPlayerManager::ReleaseMediaResources(int player_id) { |
-#if defined(VIDEO_HOLE) |
- if (external_video_surface_container_) |
- external_video_surface_container_->ReleaseExternalVideoSurface(player_id); |
-#endif // defined(VIDEO_HOLE) |
-} |
- |
-void BrowserMediaPlayerManager::ReleasePlayer(MediaPlayerAndroid* player) { |
- player->Release(); |
- ReleaseMediaResources(player->player_id()); |
+void BrowserMediaPlayerManager::StartInternal(int player_id) { |
+ MediaPlayerAndroid* player = GetPlayer(player_id); |
+ if (!player) |
+ return; |
+ player->Start(); |
+ if (fullscreen_player_id_ == player_id && fullscreen_player_is_released_) { |
+ video_view_->OpenVideo(); |
+ fullscreen_player_is_released_ = false; |
+ } |
} |
} // namespace content |