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