Home | History | Annotate | Download | only in android
      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
      3 // found in the LICENSE file.
      4 
      5 #include "content/browser/media/android/browser_media_player_manager.h"
      6 
      7 #include "base/android/scoped_java_ref.h"
      8 #include "base/command_line.h"
      9 #include "content/browser/android/content_view_core_impl.h"
     10 #include "content/browser/media/android/browser_demuxer_android.h"
     11 #include "content/browser/media/android/media_resource_getter_impl.h"
     12 #include "content/browser/renderer_host/render_view_host_impl.h"
     13 #include "content/browser/web_contents/web_contents_view_android.h"
     14 #include "content/common/media/media_player_messages_android.h"
     15 #include "content/public/browser/android/content_view_core.h"
     16 #include "content/public/browser/android/external_video_surface_container.h"
     17 #include "content/public/browser/browser_context.h"
     18 #include "content/public/browser/content_browser_client.h"
     19 #include "content/public/browser/render_frame_host.h"
     20 #include "content/public/browser/render_process_host.h"
     21 #include "content/public/browser/render_view_host.h"
     22 #include "content/public/browser/storage_partition.h"
     23 #include "content/public/browser/web_contents.h"
     24 #include "content/public/browser/web_contents_delegate.h"
     25 #include "content/public/common/content_client.h"
     26 #include "content/public/common/content_switches.h"
     27 #include "media/base/android/media_player_bridge.h"
     28 #include "media/base/android/media_source_player.h"
     29 #include "media/base/android/media_url_interceptor.h"
     30 #include "media/base/media_switches.h"
     31 
     32 using media::MediaPlayerAndroid;
     33 using media::MediaPlayerBridge;
     34 using media::MediaPlayerManager;
     35 using media::MediaSourcePlayer;
     36 
     37 namespace content {
     38 
     39 // Threshold on the number of media players per renderer before we start
     40 // attempting to release inactive media players.
     41 const int kMediaPlayerThreshold = 1;
     42 
     43 static BrowserMediaPlayerManager::Factory g_factory = NULL;
     44 static media::MediaUrlInterceptor* media_url_interceptor_ = NULL;
     45 
     46 // static
     47 void BrowserMediaPlayerManager::RegisterFactory(Factory factory) {
     48   g_factory = factory;
     49 }
     50 
     51 // static
     52 void BrowserMediaPlayerManager::RegisterMediaUrlInterceptor(
     53     media::MediaUrlInterceptor* media_url_interceptor) {
     54   media_url_interceptor_ = media_url_interceptor;
     55 }
     56 
     57 // static
     58 BrowserMediaPlayerManager* BrowserMediaPlayerManager::Create(
     59     RenderFrameHost* rfh) {
     60   if (g_factory)
     61     return g_factory(rfh);
     62   return new BrowserMediaPlayerManager(rfh);
     63 }
     64 
     65 ContentViewCoreImpl* BrowserMediaPlayerManager::GetContentViewCore() const {
     66   return ContentViewCoreImpl::FromWebContents(web_contents());
     67 }
     68 
     69 MediaPlayerAndroid* BrowserMediaPlayerManager::CreateMediaPlayer(
     70     const MediaPlayerHostMsg_Initialize_Params& media_player_params,
     71     bool hide_url_log,
     72     MediaPlayerManager* manager,
     73     BrowserDemuxerAndroid* demuxer) {
     74   switch (media_player_params.type) {
     75     case MEDIA_PLAYER_TYPE_URL: {
     76       const std::string user_agent = GetContentClient()->GetUserAgent();
     77       MediaPlayerBridge* media_player_bridge = new MediaPlayerBridge(
     78           media_player_params.player_id,
     79           media_player_params.url,
     80           media_player_params.first_party_for_cookies,
     81           user_agent,
     82           hide_url_log,
     83           manager,
     84           base::Bind(&BrowserMediaPlayerManager::OnMediaResourcesRequested,
     85                      weak_ptr_factory_.GetWeakPtr()),
     86           base::Bind(&BrowserMediaPlayerManager::OnMediaResourcesReleased,
     87                      weak_ptr_factory_.GetWeakPtr()),
     88           media_player_params.frame_url,
     89           media_player_params.allow_credentials);
     90       BrowserMediaPlayerManager* browser_media_player_manager =
     91           static_cast<BrowserMediaPlayerManager*>(manager);
     92       ContentViewCoreImpl* content_view_core_impl =
     93           static_cast<ContentViewCoreImpl*>(ContentViewCore::FromWebContents(
     94               browser_media_player_manager->web_contents_));
     95       if (!content_view_core_impl) {
     96         // May reach here due to prerendering. Don't extract the metadata
     97         // since it is expensive.
     98         // TODO(qinmin): extract the metadata once the user decided to load
     99         // the page.
    100         browser_media_player_manager->OnMediaMetadataChanged(
    101             media_player_params.player_id, base::TimeDelta(), 0, 0, false);
    102       } else if (!content_view_core_impl->ShouldBlockMediaRequest(
    103             media_player_params.url)) {
    104         media_player_bridge->Initialize();
    105       }
    106       return media_player_bridge;
    107     }
    108 
    109     case MEDIA_PLAYER_TYPE_MEDIA_SOURCE: {
    110       return new MediaSourcePlayer(
    111           media_player_params.player_id,
    112           manager,
    113           base::Bind(&BrowserMediaPlayerManager::OnMediaResourcesRequested,
    114                      weak_ptr_factory_.GetWeakPtr()),
    115           base::Bind(&BrowserMediaPlayerManager::OnMediaResourcesReleased,
    116                      weak_ptr_factory_.GetWeakPtr()),
    117           demuxer->CreateDemuxer(media_player_params.demuxer_client_id),
    118           media_player_params.frame_url);
    119     }
    120   }
    121 
    122   NOTREACHED();
    123   return NULL;
    124 }
    125 
    126 BrowserMediaPlayerManager::BrowserMediaPlayerManager(
    127     RenderFrameHost* render_frame_host)
    128     : render_frame_host_(render_frame_host),
    129       fullscreen_player_id_(-1),
    130       fullscreen_player_is_released_(false),
    131       web_contents_(WebContents::FromRenderFrameHost(render_frame_host)),
    132       weak_ptr_factory_(this) {
    133 }
    134 
    135 BrowserMediaPlayerManager::~BrowserMediaPlayerManager() {
    136   // During the tear down process, OnDestroyPlayer() may or may not be called
    137   // (e.g. the WebContents may be destroyed before the render process). So
    138   // we cannot DCHECK(players_.empty()) here. Instead, all media players in
    139   // |players_| will be destroyed here because |player_| is a ScopedVector.
    140 }
    141 
    142 void BrowserMediaPlayerManager::FullscreenPlayerPlay() {
    143   MediaPlayerAndroid* player = GetFullscreenPlayer();
    144   if (player) {
    145     if (fullscreen_player_is_released_) {
    146       video_view_->OpenVideo();
    147       fullscreen_player_is_released_ = false;
    148     }
    149     player->Start();
    150     Send(new MediaPlayerMsg_DidMediaPlayerPlay(RoutingID(),
    151                                                fullscreen_player_id_));
    152   }
    153 }
    154 
    155 void BrowserMediaPlayerManager::FullscreenPlayerPause() {
    156   MediaPlayerAndroid* player = GetFullscreenPlayer();
    157   if (player) {
    158     player->Pause(true);
    159     Send(new MediaPlayerMsg_DidMediaPlayerPause(RoutingID(),
    160                                                 fullscreen_player_id_));
    161   }
    162 }
    163 
    164 void BrowserMediaPlayerManager::FullscreenPlayerSeek(int msec) {
    165   MediaPlayerAndroid* player = GetFullscreenPlayer();
    166   if (player) {
    167     // TODO(kbalazs): if |fullscreen_player_is_released_| is true
    168     // at this point, player->GetCurrentTime() will be wrong until
    169     // FullscreenPlayerPlay (http://crbug.com/322798).
    170     OnSeekRequest(fullscreen_player_id_,
    171                   base::TimeDelta::FromMilliseconds(msec));
    172   }
    173 }
    174 
    175 void BrowserMediaPlayerManager::ExitFullscreen(bool release_media_player) {
    176   if (WebContentsDelegate* delegate = web_contents_->GetDelegate())
    177     delegate->ToggleFullscreenModeForTab(web_contents_, false);
    178   if (!CommandLine::ForCurrentProcess()->HasSwitch(
    179       switches::kDisableOverlayFullscreenVideoSubtitle)) {
    180     if (RenderWidgetHostViewAndroid* view_android =
    181         static_cast<RenderWidgetHostViewAndroid*>(
    182             web_contents_->GetRenderWidgetHostView())) {
    183       view_android->SetOverlayVideoMode(false);
    184     }
    185   }
    186 
    187   Send(
    188       new MediaPlayerMsg_DidExitFullscreen(RoutingID(), fullscreen_player_id_));
    189   video_view_.reset();
    190   MediaPlayerAndroid* player = GetFullscreenPlayer();
    191   fullscreen_player_id_ = -1;
    192   if (!player)
    193     return;
    194   if (release_media_player)
    195     ReleaseFullscreenPlayer(player);
    196   else
    197     player->SetVideoSurface(gfx::ScopedJavaSurface());
    198 }
    199 
    200 void BrowserMediaPlayerManager::OnTimeUpdate(int player_id,
    201                                              base::TimeDelta current_time) {
    202   Send(
    203       new MediaPlayerMsg_MediaTimeUpdate(RoutingID(), player_id, current_time));
    204 }
    205 
    206 void BrowserMediaPlayerManager::SetVideoSurface(
    207     gfx::ScopedJavaSurface surface) {
    208   MediaPlayerAndroid* player = GetFullscreenPlayer();
    209   if (!player)
    210     return;
    211 
    212   bool empty_surface = surface.IsEmpty();
    213   player->SetVideoSurface(surface.Pass());
    214   if (empty_surface)
    215     return;
    216 
    217   Send(new MediaPlayerMsg_DidEnterFullscreen(RoutingID(), player->player_id()));
    218   if (CommandLine::ForCurrentProcess()->HasSwitch(
    219       switches::kDisableOverlayFullscreenVideoSubtitle)) {
    220     return;
    221   }
    222   if (RenderWidgetHostViewAndroid* view_android =
    223       static_cast<RenderWidgetHostViewAndroid*>(
    224           web_contents_->GetRenderWidgetHostView())) {
    225     view_android->SetOverlayVideoMode(true);
    226   }
    227 }
    228 
    229 void BrowserMediaPlayerManager::OnMediaMetadataChanged(
    230     int player_id, base::TimeDelta duration, int width, int height,
    231     bool success) {
    232   Send(new MediaPlayerMsg_MediaMetadataChanged(
    233       RoutingID(), player_id, duration, width, height, success));
    234   if (fullscreen_player_id_ == player_id)
    235     video_view_->UpdateMediaMetadata();
    236 }
    237 
    238 void BrowserMediaPlayerManager::OnPlaybackComplete(int player_id) {
    239   Send(new MediaPlayerMsg_MediaPlaybackCompleted(RoutingID(), player_id));
    240   if (fullscreen_player_id_ == player_id)
    241     video_view_->OnPlaybackComplete();
    242 }
    243 
    244 void BrowserMediaPlayerManager::OnMediaInterrupted(int player_id) {
    245   // Tell WebKit that the audio should be paused, then release all resources
    246   Send(new MediaPlayerMsg_MediaPlayerReleased(RoutingID(), player_id));
    247   OnReleaseResources(player_id);
    248 }
    249 
    250 void BrowserMediaPlayerManager::OnBufferingUpdate(
    251     int player_id, int percentage) {
    252   Send(new MediaPlayerMsg_MediaBufferingUpdate(
    253       RoutingID(), player_id, percentage));
    254   if (fullscreen_player_id_ == player_id)
    255     video_view_->OnBufferingUpdate(percentage);
    256 }
    257 
    258 void BrowserMediaPlayerManager::OnSeekRequest(
    259     int player_id,
    260     const base::TimeDelta& time_to_seek) {
    261   Send(new MediaPlayerMsg_SeekRequest(RoutingID(), player_id, time_to_seek));
    262 }
    263 
    264 void BrowserMediaPlayerManager::PauseVideo() {
    265   Send(new MediaPlayerMsg_PauseVideo(RoutingID()));
    266 }
    267 
    268 void BrowserMediaPlayerManager::OnSeekComplete(
    269     int player_id,
    270     const base::TimeDelta& current_time) {
    271   Send(new MediaPlayerMsg_SeekCompleted(RoutingID(), player_id, current_time));
    272 }
    273 
    274 void BrowserMediaPlayerManager::OnError(int player_id, int error) {
    275   Send(new MediaPlayerMsg_MediaError(RoutingID(), player_id, error));
    276   if (fullscreen_player_id_ == player_id)
    277     video_view_->OnMediaPlayerError(error);
    278 }
    279 
    280 void BrowserMediaPlayerManager::OnVideoSizeChanged(
    281     int player_id, int width, int height) {
    282   Send(new MediaPlayerMsg_MediaVideoSizeChanged(RoutingID(), player_id,
    283       width, height));
    284   if (fullscreen_player_id_ == player_id)
    285     video_view_->OnVideoSizeChanged(width, height);
    286 }
    287 
    288 media::MediaResourceGetter*
    289 BrowserMediaPlayerManager::GetMediaResourceGetter() {
    290   if (!media_resource_getter_.get()) {
    291     RenderProcessHost* host = web_contents()->GetRenderProcessHost();
    292     BrowserContext* context = host->GetBrowserContext();
    293     StoragePartition* partition = host->GetStoragePartition();
    294     fileapi::FileSystemContext* file_system_context =
    295         partition ? partition->GetFileSystemContext() : NULL;
    296     // Eventually this needs to be fixed to pass the correct frame rather
    297     // than just using the main frame.
    298     media_resource_getter_.reset(new MediaResourceGetterImpl(
    299         context,
    300         file_system_context,
    301         host->GetID(),
    302         web_contents()->GetMainFrame()->GetRoutingID()));
    303   }
    304   return media_resource_getter_.get();
    305 }
    306 
    307 media::MediaUrlInterceptor*
    308 BrowserMediaPlayerManager::GetMediaUrlInterceptor() {
    309   return media_url_interceptor_;
    310 }
    311 
    312 MediaPlayerAndroid* BrowserMediaPlayerManager::GetFullscreenPlayer() {
    313   return GetPlayer(fullscreen_player_id_);
    314 }
    315 
    316 MediaPlayerAndroid* BrowserMediaPlayerManager::GetPlayer(int player_id) {
    317   for (ScopedVector<MediaPlayerAndroid>::iterator it = players_.begin();
    318       it != players_.end(); ++it) {
    319     if ((*it)->player_id() == player_id)
    320       return *it;
    321   }
    322   return NULL;
    323 }
    324 
    325 void BrowserMediaPlayerManager::RequestFullScreen(int player_id) {
    326   if (fullscreen_player_id_ == player_id)
    327     return;
    328 
    329   if (fullscreen_player_id_ != -1) {
    330     // TODO(qinmin): Determine the correct error code we should report to WMPA.
    331     OnError(player_id, MediaPlayerAndroid::MEDIA_ERROR_DECODE);
    332     return;
    333   }
    334 
    335   Send(new MediaPlayerMsg_RequestFullscreen(RoutingID(), player_id));
    336 }
    337 
    338 #if defined(VIDEO_HOLE)
    339 bool
    340 BrowserMediaPlayerManager::ShouldUseVideoOverlayForEmbeddedEncryptedVideo() {
    341   RendererPreferences* prefs = web_contents_->GetMutableRendererPrefs();
    342   return prefs->use_video_overlay_for_embedded_encrypted_video;
    343 }
    344 
    345 void BrowserMediaPlayerManager::AttachExternalVideoSurface(int player_id,
    346                                                            jobject surface) {
    347   MediaPlayerAndroid* player = GetPlayer(player_id);
    348   if (player) {
    349     player->SetVideoSurface(
    350         gfx::ScopedJavaSurface::AcquireExternalSurface(surface));
    351   }
    352 }
    353 
    354 void BrowserMediaPlayerManager::DetachExternalVideoSurface(int player_id) {
    355   MediaPlayerAndroid* player = GetPlayer(player_id);
    356   if (player)
    357     player->SetVideoSurface(gfx::ScopedJavaSurface());
    358 }
    359 
    360 void BrowserMediaPlayerManager::OnFrameInfoUpdated() {
    361   if (external_video_surface_container_)
    362     external_video_surface_container_->OnFrameInfoUpdated();
    363 }
    364 
    365 void BrowserMediaPlayerManager::OnNotifyExternalSurface(
    366     int player_id, bool is_request, const gfx::RectF& rect) {
    367   if (!web_contents_)
    368     return;
    369 
    370   if (is_request) {
    371     OnRequestExternalSurface(player_id, rect);
    372   }
    373   if (external_video_surface_container_) {
    374     external_video_surface_container_->OnExternalVideoSurfacePositionChanged(
    375         player_id, rect);
    376   }
    377 }
    378 
    379 void BrowserMediaPlayerManager::OnRequestExternalSurface(
    380     int player_id, const gfx::RectF& rect) {
    381   if (!external_video_surface_container_) {
    382     ContentBrowserClient* client = GetContentClient()->browser();
    383     external_video_surface_container_.reset(
    384         client->OverrideCreateExternalVideoSurfaceContainer(web_contents_));
    385   }
    386   // It's safe to use base::Unretained(this), because the callbacks will not
    387   // be called after running ReleaseExternalVideoSurface().
    388   if (external_video_surface_container_) {
    389     external_video_surface_container_->RequestExternalVideoSurface(
    390         player_id,
    391         base::Bind(&BrowserMediaPlayerManager::AttachExternalVideoSurface,
    392                    base::Unretained(this)),
    393         base::Bind(&BrowserMediaPlayerManager::DetachExternalVideoSurface,
    394                    base::Unretained(this)));
    395   }
    396 }
    397 #endif  // defined(VIDEO_HOLE)
    398 
    399 void BrowserMediaPlayerManager::OnEnterFullscreen(int player_id) {
    400   DCHECK_EQ(fullscreen_player_id_, -1);
    401 #if defined(VIDEO_HOLE)
    402   if (external_video_surface_container_)
    403     external_video_surface_container_->ReleaseExternalVideoSurface(player_id);
    404 #endif  // defined(VIDEO_HOLE)
    405   if (video_view_.get()) {
    406     fullscreen_player_id_ = player_id;
    407     video_view_->OpenVideo();
    408     return;
    409   } else if (!ContentVideoView::GetInstance()) {
    410     if (!GetPlayer(player_id)) {
    411       // If a player doesn't exist, it must be waiting for CORS check.
    412       // As a result, just request the tab to enter fullscreen mode without
    413       // creating the surface view. This is only needed for M37.
    414       Send(new MediaPlayerMsg_DidEnterFullscreen(RoutingID(), player_id));
    415       if (CommandLine::ForCurrentProcess()->HasSwitch(
    416           switches::kDisableOverlayFullscreenVideoSubtitle)) {
    417         return;
    418       }
    419       if (RenderWidgetHostViewAndroid* view_android =
    420           static_cast<RenderWidgetHostViewAndroid*>(
    421               web_contents_->GetRenderWidgetHostView())) {
    422         view_android->SetOverlayVideoMode(true);
    423       }
    424       if (WebContentsDelegate* delegate = web_contents_->GetDelegate())
    425           delegate->ToggleFullscreenModeForTab(web_contents_, true);
    426     }
    427 
    428     // In Android WebView, two ContentViewCores could both try to enter
    429     // fullscreen video, we just ignore the second one.
    430     video_view_.reset(new ContentVideoView(this));
    431     base::android::ScopedJavaLocalRef<jobject> j_content_video_view =
    432         video_view_->GetJavaObject(base::android::AttachCurrentThread());
    433     if (!j_content_video_view.is_null()) {
    434       fullscreen_player_id_ = player_id;
    435       return;
    436     }
    437   }
    438 
    439   // Force the second video to exit fullscreen.
    440   // TODO(qinmin): There is no need to send DidEnterFullscreen message.
    441   // However, if we don't send the message, page layers will not be
    442   // correctly restored. http:crbug.com/367346.
    443   Send(new MediaPlayerMsg_DidEnterFullscreen(RoutingID(), player_id));
    444   Send(new MediaPlayerMsg_DidExitFullscreen(RoutingID(), player_id));
    445   video_view_.reset();
    446 }
    447 
    448 void BrowserMediaPlayerManager::OnExitFullscreen(int player_id) {
    449   if (fullscreen_player_id_ == player_id) {
    450     MediaPlayerAndroid* player = GetPlayer(player_id);
    451     if (player)
    452       player->SetVideoSurface(gfx::ScopedJavaSurface());
    453     video_view_->OnExitFullscreen();
    454   }
    455 }
    456 
    457 void BrowserMediaPlayerManager::OnInitialize(
    458     const MediaPlayerHostMsg_Initialize_Params& media_player_params) {
    459   DCHECK(media_player_params.type != MEDIA_PLAYER_TYPE_MEDIA_SOURCE ||
    460       media_player_params.demuxer_client_id > 0)
    461       << "Media source players must have positive demuxer client IDs: "
    462       << media_player_params.demuxer_client_id;
    463 
    464   RemovePlayer(media_player_params.player_id);
    465 
    466   RenderProcessHostImpl* host = static_cast<RenderProcessHostImpl*>(
    467       web_contents()->GetRenderProcessHost());
    468   MediaPlayerAndroid* player = CreateMediaPlayer(
    469       media_player_params,
    470 
    471       host->GetBrowserContext()->IsOffTheRecord(), this,
    472       host->browser_demuxer_android());
    473 
    474   if (!player)
    475     return;
    476 
    477   AddPlayer(player);
    478 }
    479 
    480 void BrowserMediaPlayerManager::OnStart(int player_id) {
    481   MediaPlayerAndroid* player = GetPlayer(player_id);
    482   if (!player)
    483     return;
    484   player->Start();
    485   if (fullscreen_player_id_ == player_id && fullscreen_player_is_released_) {
    486     video_view_->OpenVideo();
    487     fullscreen_player_is_released_ = false;
    488   }
    489 }
    490 
    491 void BrowserMediaPlayerManager::OnSeek(
    492     int player_id,
    493     const base::TimeDelta& time) {
    494   MediaPlayerAndroid* player = GetPlayer(player_id);
    495   if (player)
    496     player->SeekTo(time);
    497 }
    498 
    499 void BrowserMediaPlayerManager::OnPause(
    500     int player_id,
    501     bool is_media_related_action) {
    502   MediaPlayerAndroid* player = GetPlayer(player_id);
    503   if (player)
    504     player->Pause(is_media_related_action);
    505 }
    506 
    507 void BrowserMediaPlayerManager::OnSetVolume(int player_id, double volume) {
    508   MediaPlayerAndroid* player = GetPlayer(player_id);
    509   if (player)
    510     player->SetVolume(volume);
    511 }
    512 
    513 void BrowserMediaPlayerManager::OnSetPoster(int player_id, const GURL& url) {
    514   // To be overridden by subclasses.
    515 }
    516 
    517 void BrowserMediaPlayerManager::OnReleaseResources(int player_id) {
    518   MediaPlayerAndroid* player = GetPlayer(player_id);
    519   if (player)
    520     player->Release();
    521   if (player_id == fullscreen_player_id_)
    522     fullscreen_player_is_released_ = true;
    523 }
    524 
    525 void BrowserMediaPlayerManager::OnDestroyPlayer(int player_id) {
    526   RemovePlayer(player_id);
    527   if (fullscreen_player_id_ == player_id)
    528     fullscreen_player_id_ = -1;
    529 }
    530 
    531 void BrowserMediaPlayerManager::AddPlayer(MediaPlayerAndroid* player) {
    532   DCHECK(!GetPlayer(player->player_id()));
    533   players_.push_back(player);
    534 }
    535 
    536 void BrowserMediaPlayerManager::RemovePlayer(int player_id) {
    537   for (ScopedVector<MediaPlayerAndroid>::iterator it = players_.begin();
    538       it != players_.end(); ++it) {
    539     MediaPlayerAndroid* player = *it;
    540     if (player->player_id() == player_id) {
    541       players_.erase(it);
    542       break;
    543     }
    544   }
    545 }
    546 
    547 scoped_ptr<media::MediaPlayerAndroid> BrowserMediaPlayerManager::SwapPlayer(
    548       int player_id, media::MediaPlayerAndroid* player) {
    549   media::MediaPlayerAndroid* previous_player = NULL;
    550   for (ScopedVector<MediaPlayerAndroid>::iterator it = players_.begin();
    551       it != players_.end(); ++it) {
    552     if ((*it)->player_id() == player_id) {
    553       previous_player = *it;
    554       players_.weak_erase(it);
    555       players_.push_back(player);
    556       break;
    557     }
    558   }
    559   return scoped_ptr<media::MediaPlayerAndroid>(previous_player);
    560 }
    561 
    562 int BrowserMediaPlayerManager::RoutingID() {
    563   return render_frame_host_->GetRoutingID();
    564 }
    565 
    566 bool BrowserMediaPlayerManager::Send(IPC::Message* msg) {
    567   return render_frame_host_->Send(msg);
    568 }
    569 
    570 void BrowserMediaPlayerManager::ReleaseFullscreenPlayer(
    571     MediaPlayerAndroid* player) {
    572     player->Release();
    573 }
    574 
    575 void BrowserMediaPlayerManager::OnMediaResourcesRequested(int player_id) {
    576   int num_active_player = 0;
    577   ScopedVector<MediaPlayerAndroid>::iterator it;
    578   for (it = players_.begin(); it != players_.end(); ++it) {
    579     if (!(*it)->IsPlayerReady())
    580       continue;
    581 
    582     // The player is already active, ignore it.
    583     if ((*it)->player_id() == player_id)
    584       return;
    585     else
    586       num_active_player++;
    587   }
    588 
    589   // Number of active players are less than the threshold, do nothing.
    590   if (num_active_player < kMediaPlayerThreshold)
    591     return;
    592 
    593   for (it = players_.begin(); it != players_.end(); ++it) {
    594     if ((*it)->IsPlayerReady() && !(*it)->IsPlaying() &&
    595         fullscreen_player_id_ != (*it)->player_id()) {
    596       (*it)->Release();
    597       Send(new MediaPlayerMsg_MediaPlayerReleased(RoutingID(),
    598                                                   (*it)->player_id()));
    599     }
    600   }
    601 }
    602 
    603 void BrowserMediaPlayerManager::OnMediaResourcesReleased(int player_id) {
    604 #if defined(VIDEO_HOLE)
    605   MediaPlayerAndroid* player = GetPlayer(player_id);
    606   if (player && player->IsSurfaceInUse())
    607     return;
    608   if (external_video_surface_container_)
    609     external_video_surface_container_->ReleaseExternalVideoSurface(player_id);
    610 #endif  // defined(VIDEO_HOLE)
    611 }
    612 
    613 }  // namespace content
    614