| 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 76c22c19c0ff1998286c16474cceab4231b4b854..37e112096e2e547ae677a9a9fbbd9eda28013daa 100644
|
| --- a/content/browser/media/android/browser_media_player_manager.cc
|
| +++ b/content/browser/media/android/browser_media_player_manager.cc
|
| @@ -9,6 +9,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"
|
| @@ -143,16 +144,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(
|
| @@ -169,7 +173,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);
|
| @@ -177,7 +181,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);
|
| @@ -319,8 +323,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(
|
| @@ -475,6 +481,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) {
|
| @@ -533,10 +544,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));
|
| }
|
| }
|
|
|
| @@ -607,13 +622,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(
|
| @@ -623,7 +641,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;
|
| @@ -632,6 +652,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();
|
| }
|
| @@ -645,44 +711,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
|
|
|