• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
RegisterFactory(Factory factory)47 void BrowserMediaPlayerManager::RegisterFactory(Factory factory) {
48   g_factory = factory;
49 }
50 
51 // static
RegisterMediaUrlInterceptor(media::MediaUrlInterceptor * media_url_interceptor)52 void BrowserMediaPlayerManager::RegisterMediaUrlInterceptor(
53     media::MediaUrlInterceptor* media_url_interceptor) {
54   media_url_interceptor_ = media_url_interceptor;
55 }
56 
57 // static
Create(RenderFrameHost * rfh)58 BrowserMediaPlayerManager* BrowserMediaPlayerManager::Create(
59     RenderFrameHost* rfh) {
60   if (g_factory)
61     return g_factory(rfh);
62   return new BrowserMediaPlayerManager(rfh);
63 }
64 
GetContentViewCore() const65 ContentViewCoreImpl* BrowserMediaPlayerManager::GetContentViewCore() const {
66   return ContentViewCoreImpl::FromWebContents(web_contents());
67 }
68 
CreateMediaPlayer(const MediaPlayerHostMsg_Initialize_Params & media_player_params,bool hide_url_log,MediaPlayerManager * manager,BrowserDemuxerAndroid * demuxer)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 
BrowserMediaPlayerManager(RenderFrameHost * render_frame_host)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 
~BrowserMediaPlayerManager()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 
FullscreenPlayerPlay()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 
FullscreenPlayerPause()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 
FullscreenPlayerSeek(int msec)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 
ExitFullscreen(bool release_media_player)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 
OnTimeUpdate(int player_id,base::TimeDelta current_time)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 
SetVideoSurface(gfx::ScopedJavaSurface surface)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 
OnMediaMetadataChanged(int player_id,base::TimeDelta duration,int width,int height,bool success)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 
OnPlaybackComplete(int player_id)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 
OnMediaInterrupted(int player_id)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 
OnBufferingUpdate(int player_id,int percentage)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 
OnSeekRequest(int player_id,const base::TimeDelta & time_to_seek)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 
PauseVideo()264 void BrowserMediaPlayerManager::PauseVideo() {
265   Send(new MediaPlayerMsg_PauseVideo(RoutingID()));
266 }
267 
OnSeekComplete(int player_id,const base::TimeDelta & current_time)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 
OnError(int player_id,int error)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 
OnVideoSizeChanged(int player_id,int width,int height)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*
GetMediaResourceGetter()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*
GetMediaUrlInterceptor()308 BrowserMediaPlayerManager::GetMediaUrlInterceptor() {
309   return media_url_interceptor_;
310 }
311 
GetFullscreenPlayer()312 MediaPlayerAndroid* BrowserMediaPlayerManager::GetFullscreenPlayer() {
313   return GetPlayer(fullscreen_player_id_);
314 }
315 
GetPlayer(int player_id)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 
RequestFullScreen(int player_id)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
ShouldUseVideoOverlayForEmbeddedEncryptedVideo()340 BrowserMediaPlayerManager::ShouldUseVideoOverlayForEmbeddedEncryptedVideo() {
341   RendererPreferences* prefs = web_contents_->GetMutableRendererPrefs();
342   return prefs->use_video_overlay_for_embedded_encrypted_video;
343 }
344 
AttachExternalVideoSurface(int player_id,jobject surface)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 
DetachExternalVideoSurface(int player_id)354 void BrowserMediaPlayerManager::DetachExternalVideoSurface(int player_id) {
355   MediaPlayerAndroid* player = GetPlayer(player_id);
356   if (player)
357     player->SetVideoSurface(gfx::ScopedJavaSurface());
358 }
359 
OnFrameInfoUpdated()360 void BrowserMediaPlayerManager::OnFrameInfoUpdated() {
361   if (external_video_surface_container_)
362     external_video_surface_container_->OnFrameInfoUpdated();
363 }
364 
OnNotifyExternalSurface(int player_id,bool is_request,const gfx::RectF & rect)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 
OnRequestExternalSurface(int player_id,const gfx::RectF & rect)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 
OnEnterFullscreen(int player_id)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 
OnExitFullscreen(int player_id)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 
OnInitialize(const MediaPlayerHostMsg_Initialize_Params & media_player_params)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 
OnStart(int player_id)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 
OnSeek(int player_id,const base::TimeDelta & time)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 
OnPause(int player_id,bool is_media_related_action)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 
OnSetVolume(int player_id,double volume)507 void BrowserMediaPlayerManager::OnSetVolume(int player_id, double volume) {
508   MediaPlayerAndroid* player = GetPlayer(player_id);
509   if (player)
510     player->SetVolume(volume);
511 }
512 
OnSetPoster(int player_id,const GURL & url)513 void BrowserMediaPlayerManager::OnSetPoster(int player_id, const GURL& url) {
514   // To be overridden by subclasses.
515 }
516 
OnReleaseResources(int player_id)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 
OnDestroyPlayer(int player_id)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 
AddPlayer(MediaPlayerAndroid * player)531 void BrowserMediaPlayerManager::AddPlayer(MediaPlayerAndroid* player) {
532   DCHECK(!GetPlayer(player->player_id()));
533   players_.push_back(player);
534 }
535 
RemovePlayer(int player_id)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 
SwapPlayer(int player_id,media::MediaPlayerAndroid * player)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 
RoutingID()562 int BrowserMediaPlayerManager::RoutingID() {
563   return render_frame_host_->GetRoutingID();
564 }
565 
Send(IPC::Message * msg)566 bool BrowserMediaPlayerManager::Send(IPC::Message* msg) {
567   return render_frame_host_->Send(msg);
568 }
569 
ReleaseFullscreenPlayer(MediaPlayerAndroid * player)570 void BrowserMediaPlayerManager::ReleaseFullscreenPlayer(
571     MediaPlayerAndroid* player) {
572     player->Release();
573 }
574 
OnMediaResourcesRequested(int player_id)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 
OnMediaResourcesReleased(int player_id)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