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.
5 #include "content/browser/media/android/browser_media_player_manager.h"
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/android/media_players_observer.h"
11 #include "content/browser/media/android/browser_demuxer_android.h"
12 #include "content/browser/media/android/media_resource_getter_impl.h"
13 #include "content/browser/media/android/media_session.h"
14 #include "content/browser/media/media_web_contents_observer.h"
15 #include "content/browser/renderer_host/render_view_host_impl.h"
16 #include "content/browser/web_contents/web_contents_view_android.h"
17 #include "content/common/media/media_player_messages_android.h"
18 #include "content/public/browser/android/content_view_core.h"
19 #include "content/public/browser/android/external_video_surface_container.h"
20 #include "content/public/browser/browser_context.h"
21 #include "content/public/browser/browser_thread.h"
22 #include "content/public/browser/content_browser_client.h"
23 #include "content/public/browser/render_frame_host.h"
24 #include "content/public/browser/render_process_host.h"
25 #include "content/public/browser/render_view_host.h"
26 #include "content/public/browser/storage_partition.h"
27 #include "content/public/browser/web_contents.h"
28 #include "content/public/browser/web_contents_delegate.h"
29 #include "content/public/common/content_client.h"
30 #include "content/public/common/content_switches.h"
31 #include "media/base/android/media_codec_player.h"
32 #include "media/base/android/media_player_bridge.h"
33 #include "media/base/android/media_source_player.h"
34 #include "media/base/android/media_url_interceptor.h"
35 #include "media/base/media_switches.h"
37 using media::MediaCodecPlayer
;
38 using media::MediaPlayerAndroid
;
39 using media::MediaPlayerBridge
;
40 using media::MediaPlayerManager
;
41 using media::MediaSourcePlayer
;
45 // Threshold on the number of media players per renderer before we start
46 // attempting to release inactive media players.
47 const int kMediaPlayerThreshold
= 1;
48 const int kInvalidMediaPlayerId
= -1;
50 // Minimal duration of a media player in order to be considered as Content type.
51 const int kMinimumDurationForContentInSeconds
= 5;
53 static BrowserMediaPlayerManager::Factory g_factory
= NULL
;
54 static media::MediaUrlInterceptor
* media_url_interceptor_
= NULL
;
57 void BrowserMediaPlayerManager::RegisterFactory(Factory factory
) {
58 // TODO(aberent) nullptr test is a temporary fix to simplify upstreaming Cast.
59 // Until Cast is fully upstreamed we want the downstream factory to take
60 // priority over the upstream factory. The downstream call happens first,
61 // so this will ensure that it does.
62 if (g_factory
== nullptr)
67 void BrowserMediaPlayerManager::RegisterMediaUrlInterceptor(
68 media::MediaUrlInterceptor
* media_url_interceptor
) {
69 media_url_interceptor_
= media_url_interceptor
;
73 void BrowserMediaPlayerManager::SetSurfacePeer(
74 scoped_refptr
<gfx::SurfaceTexture
> surface_texture
,
75 base::ProcessHandle render_process_handle
,
78 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
79 int render_process_id
= 0;
80 RenderProcessHost::iterator it
= RenderProcessHost::AllHostsIterator();
81 while (!it
.IsAtEnd()) {
82 if (it
.GetCurrentValue()->GetHandle() == render_process_handle
) {
83 render_process_id
= it
.GetCurrentValue()->GetID();
88 if (!render_process_id
) {
89 DVLOG(1) << "Cannot find render process for render_process_handle "
90 << render_process_handle
;
94 RenderFrameHostImpl
* frame
=
95 RenderFrameHostImpl::FromID(render_process_id
, render_frame_id
);
97 DVLOG(1) << "Cannot find frame for render_frame_id " << render_frame_id
;
101 WebContentsImpl
* web_contents
=
102 static_cast<WebContentsImpl
*>(WebContents::FromRenderFrameHost(frame
));
103 BrowserMediaPlayerManager
* player_manager
=
104 web_contents
->media_web_contents_observer()->GetMediaPlayerManager(frame
);
105 if (!player_manager
) {
106 DVLOG(1) << "Cannot find the media player manager for frame " << frame
;
110 media::MediaPlayerAndroid
* player
= player_manager
->GetPlayer(player_id
);
112 DVLOG(1) << "Cannot find media player for player_id " << player_id
;
116 if (player
!= player_manager
->GetFullscreenPlayer()) {
117 gfx::ScopedJavaSurface
scoped_surface(surface_texture
.get());
118 player
->SetVideoSurface(scoped_surface
.Pass());
123 BrowserMediaPlayerManager
* BrowserMediaPlayerManager::Create(
124 RenderFrameHost
* rfh
,
125 MediaPlayersObserver
* audio_monitor
) {
127 return g_factory(rfh
, audio_monitor
);
128 return new BrowserMediaPlayerManager(rfh
, audio_monitor
);
131 ContentViewCore
* BrowserMediaPlayerManager::GetContentViewCore() const {
132 return ContentViewCoreImpl::FromWebContents(web_contents());
135 MediaPlayerAndroid
* BrowserMediaPlayerManager::CreateMediaPlayer(
136 const MediaPlayerHostMsg_Initialize_Params
& media_player_params
,
138 BrowserDemuxerAndroid
* demuxer
) {
139 switch (media_player_params
.type
) {
140 case MEDIA_PLAYER_TYPE_URL
: {
141 const std::string user_agent
= GetContentClient()->GetUserAgent();
142 MediaPlayerBridge
* media_player_bridge
= new MediaPlayerBridge(
143 media_player_params
.player_id
,
144 media_player_params
.url
,
145 media_player_params
.first_party_for_cookies
,
149 base::Bind(&BrowserMediaPlayerManager::OnMediaResourcesRequested
,
150 weak_ptr_factory_
.GetWeakPtr()),
151 media_player_params
.frame_url
,
152 media_player_params
.allow_credentials
);
153 ContentViewCoreImpl
* content_view_core_impl
=
154 static_cast<ContentViewCoreImpl
*>(ContentViewCore::FromWebContents(
156 if (!content_view_core_impl
) {
157 // May reach here due to prerendering. Don't extract the metadata
158 // since it is expensive.
159 // TODO(qinmin): extract the metadata once the user decided to load
161 OnMediaMetadataChanged(
162 media_player_params
.player_id
, base::TimeDelta(), 0, 0, false);
163 } else if (!content_view_core_impl
->ShouldBlockMediaRequest(
164 media_player_params
.url
)) {
165 media_player_bridge
->Initialize();
167 return media_player_bridge
;
170 case MEDIA_PLAYER_TYPE_MEDIA_SOURCE
: {
171 if (base::CommandLine::ForCurrentProcess()->
172 HasSwitch(switches::kEnableMediaThreadForMediaPlayback
)) {
173 return new MediaCodecPlayer(
174 media_player_params
.player_id
,
175 weak_ptr_factory_
.GetWeakPtr(),
176 base::Bind(&BrowserMediaPlayerManager::OnMediaResourcesRequested
,
177 weak_ptr_factory_
.GetWeakPtr()),
178 demuxer
->CreateDemuxer(media_player_params
.demuxer_client_id
),
179 media_player_params
.frame_url
);
181 return new MediaSourcePlayer(
182 media_player_params
.player_id
,
184 base::Bind(&BrowserMediaPlayerManager::OnMediaResourcesRequested
,
185 weak_ptr_factory_
.GetWeakPtr()),
186 demuxer
->CreateDemuxer(media_player_params
.demuxer_client_id
),
187 media_player_params
.frame_url
);
196 BrowserMediaPlayerManager::BrowserMediaPlayerManager(
197 RenderFrameHost
* render_frame_host
,
198 MediaPlayersObserver
* audio_monitor
)
199 : render_frame_host_(render_frame_host
),
200 audio_monitor_(audio_monitor
),
201 fullscreen_player_id_(kInvalidMediaPlayerId
),
202 fullscreen_player_is_released_(false),
203 web_contents_(WebContents::FromRenderFrameHost(render_frame_host
)),
204 weak_ptr_factory_(this) {
207 BrowserMediaPlayerManager::~BrowserMediaPlayerManager() {
208 // During the tear down process, OnDestroyPlayer() may or may not be called
209 // (e.g. the WebContents may be destroyed before the render process). So
210 // we cannot DCHECK(players_.empty()) here. Instead, all media players in
211 // |players_| will be destroyed here because |player_| is a ScopedVector.
213 for (MediaPlayerAndroid
* player
: players_
)
214 player
->DeleteOnCorrectThread();
216 MediaSession::Get(web_contents())->RemovePlayers(this);
217 players_
.weak_clear();
220 void BrowserMediaPlayerManager::ExitFullscreen(bool release_media_player
) {
221 if (WebContentsDelegate
* delegate
= web_contents_
->GetDelegate())
222 delegate
->ExitFullscreenModeForTab(web_contents_
);
223 if (RenderWidgetHostViewAndroid
* view_android
=
224 static_cast<RenderWidgetHostViewAndroid
*>(
225 web_contents_
->GetRenderWidgetHostView())) {
226 view_android
->SetOverlayVideoMode(false);
230 new MediaPlayerMsg_DidExitFullscreen(RoutingID(), fullscreen_player_id_
));
232 MediaPlayerAndroid
* player
= GetFullscreenPlayer();
233 fullscreen_player_id_
= kInvalidMediaPlayerId
;
237 #if defined(VIDEO_HOLE)
238 if (external_video_surface_container_
)
239 external_video_surface_container_
->OnFrameInfoUpdated();
240 #endif // defined(VIDEO_HOLE)
242 if (release_media_player
)
243 ReleaseFullscreenPlayer(player
);
245 player
->SetVideoSurface(gfx::ScopedJavaSurface());
248 void BrowserMediaPlayerManager::OnTimeUpdate(
250 base::TimeDelta current_timestamp
,
251 base::TimeTicks current_time_ticks
) {
252 Send(new MediaPlayerMsg_MediaTimeUpdate(
253 RoutingID(), player_id
, current_timestamp
, current_time_ticks
));
256 void BrowserMediaPlayerManager::SetVideoSurface(
257 gfx::ScopedJavaSurface surface
) {
258 MediaPlayerAndroid
* player
= GetFullscreenPlayer();
262 bool empty_surface
= surface
.IsEmpty();
263 player
->SetVideoSurface(surface
.Pass());
267 if (RenderWidgetHostViewAndroid
* view_android
=
268 static_cast<RenderWidgetHostViewAndroid
*>(
269 web_contents_
->GetRenderWidgetHostView())) {
270 view_android
->SetOverlayVideoMode(true);
274 void BrowserMediaPlayerManager::OnMediaMetadataChanged(
275 int player_id
, base::TimeDelta duration
, int width
, int height
,
277 Send(new MediaPlayerMsg_MediaMetadataChanged(
278 RoutingID(), player_id
, duration
, width
, height
, success
));
279 if (fullscreen_player_id_
== player_id
)
280 video_view_
->UpdateMediaMetadata();
283 void BrowserMediaPlayerManager::OnPlaybackComplete(int player_id
) {
284 Send(new MediaPlayerMsg_MediaPlaybackCompleted(RoutingID(), player_id
));
285 MediaSession::Get(web_contents())->RemovePlayer(this, player_id
);
287 if (fullscreen_player_id_
== player_id
)
288 video_view_
->OnPlaybackComplete();
291 void BrowserMediaPlayerManager::OnMediaInterrupted(int player_id
) {
292 // Tell WebKit that the audio should be paused, then release all resources
293 Send(new MediaPlayerMsg_MediaPlayerReleased(RoutingID(), player_id
));
294 OnReleaseResources(player_id
);
297 void BrowserMediaPlayerManager::OnBufferingUpdate(
298 int player_id
, int percentage
) {
299 Send(new MediaPlayerMsg_MediaBufferingUpdate(
300 RoutingID(), player_id
, percentage
));
301 if (fullscreen_player_id_
== player_id
)
302 video_view_
->OnBufferingUpdate(percentage
);
305 void BrowserMediaPlayerManager::OnSeekRequest(
307 const base::TimeDelta
& time_to_seek
) {
308 Send(new MediaPlayerMsg_SeekRequest(RoutingID(), player_id
, time_to_seek
));
311 void BrowserMediaPlayerManager::ReleaseAllMediaPlayers() {
312 for (ScopedVector
<MediaPlayerAndroid
>::iterator it
= players_
.begin();
313 it
!= players_
.end(); ++it
) {
314 if ((*it
)->player_id() == fullscreen_player_id_
)
315 fullscreen_player_is_released_
= true;
320 void BrowserMediaPlayerManager::OnSeekComplete(
322 const base::TimeDelta
& current_time
) {
323 Send(new MediaPlayerMsg_SeekCompleted(RoutingID(), player_id
, current_time
));
326 void BrowserMediaPlayerManager::OnError(int player_id
, int error
) {
327 Send(new MediaPlayerMsg_MediaError(RoutingID(), player_id
, error
));
328 if (fullscreen_player_id_
== player_id
)
329 video_view_
->OnMediaPlayerError(error
);
332 void BrowserMediaPlayerManager::OnVideoSizeChanged(
333 int player_id
, int width
, int height
) {
334 Send(new MediaPlayerMsg_MediaVideoSizeChanged(RoutingID(), player_id
,
336 if (fullscreen_player_id_
== player_id
)
337 video_view_
->OnVideoSizeChanged(width
, height
);
340 void BrowserMediaPlayerManager::OnAudibleStateChanged(
341 int player_id
, bool is_audible
) {
342 audio_monitor_
->OnAudibleStateChanged(
343 render_frame_host_
, player_id
, is_audible
);
346 void BrowserMediaPlayerManager::OnWaitingForDecryptionKey(int player_id
) {
347 Send(new MediaPlayerMsg_WaitingForDecryptionKey(RoutingID(), player_id
));
350 media::MediaResourceGetter
*
351 BrowserMediaPlayerManager::GetMediaResourceGetter() {
352 if (!media_resource_getter_
.get()) {
353 RenderProcessHost
* host
= web_contents()->GetRenderProcessHost();
354 BrowserContext
* context
= host
->GetBrowserContext();
355 StoragePartition
* partition
= host
->GetStoragePartition();
356 storage::FileSystemContext
* file_system_context
=
357 partition
? partition
->GetFileSystemContext() : NULL
;
358 // Eventually this needs to be fixed to pass the correct frame rather
359 // than just using the main frame.
360 media_resource_getter_
.reset(new MediaResourceGetterImpl(
364 web_contents()->GetMainFrame()->GetRoutingID()));
366 return media_resource_getter_
.get();
369 media::MediaUrlInterceptor
*
370 BrowserMediaPlayerManager::GetMediaUrlInterceptor() {
371 return media_url_interceptor_
;
374 MediaPlayerAndroid
* BrowserMediaPlayerManager::GetFullscreenPlayer() {
375 return GetPlayer(fullscreen_player_id_
);
378 MediaPlayerAndroid
* BrowserMediaPlayerManager::GetPlayer(int player_id
) {
379 for (ScopedVector
<MediaPlayerAndroid
>::iterator it
= players_
.begin();
380 it
!= players_
.end(); ++it
) {
381 if ((*it
)->player_id() == player_id
)
387 bool BrowserMediaPlayerManager::RequestPlay(int player_id
) {
388 MediaPlayerAndroid
* player
= GetPlayer(player_id
);
391 int64 duration
= player
->GetDuration().InSeconds();
392 MediaSession::Type media_session_type
=
393 duration
== 0 || duration
> kMinimumDurationForContentInSeconds
394 ? MediaSession::Type::Content
: MediaSession::Type::Transient
;
396 bool succeeded
= MediaSession::Get(web_contents())->AddPlayer(
397 this, player_id
, media_session_type
);
399 Send(new MediaPlayerMsg_DidMediaPlayerPause(RoutingID(), player_id
));
403 void BrowserMediaPlayerManager::OnSuspend(int player_id
) {
404 MediaPlayerAndroid
* player
= GetPlayer(player_id
);
408 Send(new MediaPlayerMsg_DidMediaPlayerPause(RoutingID(), player_id
));
411 void BrowserMediaPlayerManager::OnResume(int player_id
) {
412 MediaPlayerAndroid
* player
= GetPlayer(player_id
);
416 Send(new MediaPlayerMsg_DidMediaPlayerPlay(RoutingID(), player_id
));
419 #if defined(VIDEO_HOLE)
420 void BrowserMediaPlayerManager::AttachExternalVideoSurface(int player_id
,
422 MediaPlayerAndroid
* player
= GetPlayer(player_id
);
424 player
->SetVideoSurface(
425 gfx::ScopedJavaSurface::AcquireExternalSurface(surface
));
429 void BrowserMediaPlayerManager::DetachExternalVideoSurface(int player_id
) {
430 MediaPlayerAndroid
* player
= GetPlayer(player_id
);
432 player
->SetVideoSurface(gfx::ScopedJavaSurface());
435 void BrowserMediaPlayerManager::OnFrameInfoUpdated() {
436 if (fullscreen_player_id_
!= kInvalidMediaPlayerId
)
439 if (external_video_surface_container_
)
440 external_video_surface_container_
->OnFrameInfoUpdated();
443 void BrowserMediaPlayerManager::OnNotifyExternalSurface(
444 int player_id
, bool is_request
, const gfx::RectF
& rect
) {
449 OnRequestExternalSurface(player_id
, rect
);
451 if (external_video_surface_container_
) {
452 external_video_surface_container_
->OnExternalVideoSurfacePositionChanged(
457 void BrowserMediaPlayerManager::ReleasePlayerOfExternalVideoSurfaceIfNeeded(
459 int current_player
= ExternalVideoSurfaceContainer::kInvalidPlayerId
;
461 if (external_video_surface_container_
)
462 current_player
= external_video_surface_container_
->GetCurrentPlayerId();
464 if (current_player
== ExternalVideoSurfaceContainer::kInvalidPlayerId
)
467 if (current_player
!= future_player
)
468 OnMediaInterrupted(current_player
);
471 void BrowserMediaPlayerManager::OnRequestExternalSurface(
472 int player_id
, const gfx::RectF
& rect
) {
473 if (!external_video_surface_container_
) {
474 ContentBrowserClient
* client
= GetContentClient()->browser();
475 external_video_surface_container_
.reset(
476 client
->OverrideCreateExternalVideoSurfaceContainer(web_contents_
));
478 // It's safe to use base::Unretained(this), because the callbacks will not
479 // be called after running ReleaseExternalVideoSurface().
480 if (external_video_surface_container_
) {
481 // In case we're stealing the external surface from another player.
482 ReleasePlayerOfExternalVideoSurfaceIfNeeded(player_id
);
483 external_video_surface_container_
->RequestExternalVideoSurface(
485 base::Bind(&BrowserMediaPlayerManager::AttachExternalVideoSurface
,
486 base::Unretained(this)),
487 base::Bind(&BrowserMediaPlayerManager::DetachExternalVideoSurface
,
488 base::Unretained(this)));
491 #endif // defined(VIDEO_HOLE)
493 void BrowserMediaPlayerManager::OnEnterFullscreen(int player_id
) {
494 DCHECK_EQ(fullscreen_player_id_
, kInvalidMediaPlayerId
);
495 #if defined(VIDEO_HOLE)
496 // If this fullscreen player is started when another player
497 // uses the external surface, release that other player.
498 ReleasePlayerOfExternalVideoSurfaceIfNeeded(player_id
);
499 if (external_video_surface_container_
)
500 external_video_surface_container_
->ReleaseExternalVideoSurface(player_id
);
501 #endif // defined(VIDEO_HOLE)
502 if (video_view_
.get()) {
503 fullscreen_player_id_
= player_id
;
504 video_view_
->OpenVideo();
506 } else if (!ContentVideoView::GetInstance()) {
507 // In Android WebView, two ContentViewCores could both try to enter
508 // fullscreen video, we just ignore the second one.
509 video_view_
.reset(new ContentVideoView(this));
510 base::android::ScopedJavaLocalRef
<jobject
> j_content_video_view
=
511 video_view_
->GetJavaObject(base::android::AttachCurrentThread());
512 if (!j_content_video_view
.is_null()) {
513 fullscreen_player_id_
= player_id
;
518 // Force the second video to exit fullscreen.
519 Send(new MediaPlayerMsg_DidExitFullscreen(RoutingID(), player_id
));
523 void BrowserMediaPlayerManager::OnInitialize(
524 const MediaPlayerHostMsg_Initialize_Params
& media_player_params
) {
525 DCHECK(media_player_params
.type
!= MEDIA_PLAYER_TYPE_MEDIA_SOURCE
||
526 media_player_params
.demuxer_client_id
> 0)
527 << "Media source players must have positive demuxer client IDs: "
528 << media_player_params
.demuxer_client_id
;
530 RemovePlayer(media_player_params
.player_id
);
532 RenderProcessHostImpl
* host
= static_cast<RenderProcessHostImpl
*>(
533 web_contents()->GetRenderProcessHost());
534 MediaPlayerAndroid
* player
=
535 CreateMediaPlayer(media_player_params
,
536 host
->GetBrowserContext()->IsOffTheRecord(),
537 host
->browser_demuxer_android().get());
545 void BrowserMediaPlayerManager::OnStart(int player_id
) {
546 MediaPlayerAndroid
* player
= GetPlayer(player_id
);
550 if (fullscreen_player_id_
== player_id
&& fullscreen_player_is_released_
) {
551 video_view_
->OpenVideo();
552 fullscreen_player_is_released_
= false;
556 void BrowserMediaPlayerManager::OnSeek(
558 const base::TimeDelta
& time
) {
559 MediaPlayerAndroid
* player
= GetPlayer(player_id
);
561 player
->SeekTo(time
);
564 void BrowserMediaPlayerManager::OnPause(
566 bool is_media_related_action
) {
567 MediaPlayerAndroid
* player
= GetPlayer(player_id
);
569 player
->Pause(is_media_related_action
);
571 if (is_media_related_action
)
572 MediaSession::Get(web_contents())->RemovePlayer(this, player_id
);
575 void BrowserMediaPlayerManager::OnSetVolume(int player_id
, double volume
) {
576 MediaPlayerAndroid
* player
= GetPlayer(player_id
);
578 player
->SetVolume(volume
);
581 void BrowserMediaPlayerManager::OnSetPoster(int player_id
, const GURL
& url
) {
582 // To be overridden by subclasses.
585 void BrowserMediaPlayerManager::OnReleaseResources(int player_id
) {
586 MediaPlayerAndroid
* player
= GetPlayer(player_id
);
588 // Videos can't play in the background, so are removed from the media
590 if (player
->GetVideoWidth() > 0)
591 MediaSession::Get(web_contents())->RemovePlayer(this, player_id
);
593 ReleasePlayer(player
);
595 if (player_id
== fullscreen_player_id_
)
596 fullscreen_player_is_released_
= true;
599 void BrowserMediaPlayerManager::OnDestroyPlayer(int player_id
) {
600 RemovePlayer(player_id
);
601 if (fullscreen_player_id_
== player_id
)
602 fullscreen_player_id_
= kInvalidMediaPlayerId
;
605 void BrowserMediaPlayerManager::OnRequestRemotePlayback(int /* player_id */) {
606 // Does nothing if we don't have a remote player
609 void BrowserMediaPlayerManager::OnRequestRemotePlaybackControl(
610 int /* player_id */) {
611 // Does nothing if we don't have a remote player
614 void BrowserMediaPlayerManager::AddPlayer(MediaPlayerAndroid
* player
) {
615 DCHECK(!GetPlayer(player
->player_id()));
616 players_
.push_back(player
);
619 void BrowserMediaPlayerManager::RemovePlayer(int player_id
) {
620 for (ScopedVector
<MediaPlayerAndroid
>::iterator it
= players_
.begin();
621 it
!= players_
.end(); ++it
) {
622 if ((*it
)->player_id() == player_id
) {
623 ReleaseMediaResources(player_id
);
624 (*it
)->DeleteOnCorrectThread();
625 players_
.weak_erase(it
);
626 audio_monitor_
->RemovePlayer(render_frame_host_
, player_id
);
627 MediaSession::Get(web_contents())->RemovePlayer(this, player_id
);
633 scoped_ptr
<media::MediaPlayerAndroid
> BrowserMediaPlayerManager::SwapPlayer(
634 int player_id
, media::MediaPlayerAndroid
* player
) {
635 media::MediaPlayerAndroid
* previous_player
= NULL
;
636 for (ScopedVector
<MediaPlayerAndroid
>::iterator it
= players_
.begin();
637 it
!= players_
.end(); ++it
) {
638 if ((*it
)->player_id() == player_id
) {
639 previous_player
= *it
;
640 ReleaseMediaResources(player_id
);
641 players_
.weak_erase(it
);
642 players_
.push_back(player
);
646 return scoped_ptr
<media::MediaPlayerAndroid
>(previous_player
);
649 int BrowserMediaPlayerManager::RoutingID() {
650 return render_frame_host_
->GetRoutingID();
653 bool BrowserMediaPlayerManager::Send(IPC::Message
* msg
) {
654 return render_frame_host_
->Send(msg
);
657 void BrowserMediaPlayerManager::ReleaseFullscreenPlayer(
658 MediaPlayerAndroid
* player
) {
659 ReleasePlayer(player
);
662 void BrowserMediaPlayerManager::OnMediaResourcesRequested(int player_id
) {
663 int num_active_player
= 0;
664 ScopedVector
<MediaPlayerAndroid
>::iterator it
;
665 for (it
= players_
.begin(); it
!= players_
.end(); ++it
) {
666 if (!(*it
)->IsPlayerReady())
669 // The player is already active, ignore it.
670 if ((*it
)->player_id() == player_id
)
676 // Number of active players are less than the threshold, do nothing.
677 if (num_active_player
< kMediaPlayerThreshold
)
680 for (it
= players_
.begin(); it
!= players_
.end(); ++it
) {
681 if ((*it
)->IsPlayerReady() && !(*it
)->IsPlaying() &&
682 fullscreen_player_id_
!= (*it
)->player_id()) {
684 Send(new MediaPlayerMsg_MediaPlayerReleased(RoutingID(),
685 (*it
)->player_id()));
690 void BrowserMediaPlayerManager::ReleaseMediaResources(int player_id
) {
691 #if defined(VIDEO_HOLE)
692 if (external_video_surface_container_
)
693 external_video_surface_container_
->ReleaseExternalVideoSurface(player_id
);
694 #endif // defined(VIDEO_HOLE)
697 void BrowserMediaPlayerManager::ReleasePlayer(MediaPlayerAndroid
* player
) {
699 ReleaseMediaResources(player
->player_id());
702 } // namespace content