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 MediaSession::Type media_session_type
=
392 player
->GetDuration().InSeconds() > kMinimumDurationForContentInSeconds
393 ? MediaSession::Type::Content
: MediaSession::Type::Transient
;
395 bool succeeded
= MediaSession::Get(web_contents())->AddPlayer(
396 this, player_id
, media_session_type
);
398 Send(new MediaPlayerMsg_DidMediaPlayerPause(RoutingID(), player_id
));
402 #if defined(VIDEO_HOLE)
403 void BrowserMediaPlayerManager::AttachExternalVideoSurface(int player_id
,
405 MediaPlayerAndroid
* player
= GetPlayer(player_id
);
407 player
->SetVideoSurface(
408 gfx::ScopedJavaSurface::AcquireExternalSurface(surface
));
412 void BrowserMediaPlayerManager::DetachExternalVideoSurface(int player_id
) {
413 MediaPlayerAndroid
* player
= GetPlayer(player_id
);
415 player
->SetVideoSurface(gfx::ScopedJavaSurface());
418 void BrowserMediaPlayerManager::OnFrameInfoUpdated() {
419 if (fullscreen_player_id_
!= kInvalidMediaPlayerId
)
422 if (external_video_surface_container_
)
423 external_video_surface_container_
->OnFrameInfoUpdated();
426 void BrowserMediaPlayerManager::OnSuspend(int player_id
) {
427 MediaPlayerAndroid
* player
= GetPlayer(player_id
);
431 Send(new MediaPlayerMsg_DidMediaPlayerPause(RoutingID(), player_id
));
434 void BrowserMediaPlayerManager::OnResume(int player_id
) {
435 MediaPlayerAndroid
* player
= GetPlayer(player_id
);
439 Send(new MediaPlayerMsg_DidMediaPlayerPlay(RoutingID(), player_id
));
442 void BrowserMediaPlayerManager::OnNotifyExternalSurface(
443 int player_id
, bool is_request
, const gfx::RectF
& rect
) {
448 OnRequestExternalSurface(player_id
, rect
);
450 if (external_video_surface_container_
) {
451 external_video_surface_container_
->OnExternalVideoSurfacePositionChanged(
456 void BrowserMediaPlayerManager::ReleasePlayerOfExternalVideoSurfaceIfNeeded(
458 int current_player
= ExternalVideoSurfaceContainer::kInvalidPlayerId
;
460 if (external_video_surface_container_
)
461 current_player
= external_video_surface_container_
->GetCurrentPlayerId();
463 if (current_player
== ExternalVideoSurfaceContainer::kInvalidPlayerId
)
466 if (current_player
!= future_player
)
467 OnMediaInterrupted(current_player
);
470 void BrowserMediaPlayerManager::OnRequestExternalSurface(
471 int player_id
, const gfx::RectF
& rect
) {
472 if (!external_video_surface_container_
) {
473 ContentBrowserClient
* client
= GetContentClient()->browser();
474 external_video_surface_container_
.reset(
475 client
->OverrideCreateExternalVideoSurfaceContainer(web_contents_
));
477 // It's safe to use base::Unretained(this), because the callbacks will not
478 // be called after running ReleaseExternalVideoSurface().
479 if (external_video_surface_container_
) {
480 // In case we're stealing the external surface from another player.
481 ReleasePlayerOfExternalVideoSurfaceIfNeeded(player_id
);
482 external_video_surface_container_
->RequestExternalVideoSurface(
484 base::Bind(&BrowserMediaPlayerManager::AttachExternalVideoSurface
,
485 base::Unretained(this)),
486 base::Bind(&BrowserMediaPlayerManager::DetachExternalVideoSurface
,
487 base::Unretained(this)));
490 #endif // defined(VIDEO_HOLE)
492 void BrowserMediaPlayerManager::OnEnterFullscreen(int player_id
) {
493 DCHECK_EQ(fullscreen_player_id_
, kInvalidMediaPlayerId
);
494 #if defined(VIDEO_HOLE)
495 // If this fullscreen player is started when another player
496 // uses the external surface, release that other player.
497 ReleasePlayerOfExternalVideoSurfaceIfNeeded(player_id
);
498 if (external_video_surface_container_
)
499 external_video_surface_container_
->ReleaseExternalVideoSurface(player_id
);
500 #endif // defined(VIDEO_HOLE)
501 if (video_view_
.get()) {
502 fullscreen_player_id_
= player_id
;
503 video_view_
->OpenVideo();
505 } else if (!ContentVideoView::GetInstance()) {
506 // In Android WebView, two ContentViewCores could both try to enter
507 // fullscreen video, we just ignore the second one.
508 video_view_
.reset(new ContentVideoView(this));
509 base::android::ScopedJavaLocalRef
<jobject
> j_content_video_view
=
510 video_view_
->GetJavaObject(base::android::AttachCurrentThread());
511 if (!j_content_video_view
.is_null()) {
512 fullscreen_player_id_
= player_id
;
517 // Force the second video to exit fullscreen.
518 Send(new MediaPlayerMsg_DidExitFullscreen(RoutingID(), player_id
));
522 void BrowserMediaPlayerManager::OnInitialize(
523 const MediaPlayerHostMsg_Initialize_Params
& media_player_params
) {
524 DCHECK(media_player_params
.type
!= MEDIA_PLAYER_TYPE_MEDIA_SOURCE
||
525 media_player_params
.demuxer_client_id
> 0)
526 << "Media source players must have positive demuxer client IDs: "
527 << media_player_params
.demuxer_client_id
;
529 RemovePlayer(media_player_params
.player_id
);
531 RenderProcessHostImpl
* host
= static_cast<RenderProcessHostImpl
*>(
532 web_contents()->GetRenderProcessHost());
533 MediaPlayerAndroid
* player
=
534 CreateMediaPlayer(media_player_params
,
535 host
->GetBrowserContext()->IsOffTheRecord(),
536 host
->browser_demuxer_android().get());
544 void BrowserMediaPlayerManager::OnStart(int player_id
) {
545 MediaPlayerAndroid
* player
= GetPlayer(player_id
);
549 if (fullscreen_player_id_
== player_id
&& fullscreen_player_is_released_
) {
550 video_view_
->OpenVideo();
551 fullscreen_player_is_released_
= false;
555 void BrowserMediaPlayerManager::OnSeek(
557 const base::TimeDelta
& time
) {
558 MediaPlayerAndroid
* player
= GetPlayer(player_id
);
560 player
->SeekTo(time
);
563 void BrowserMediaPlayerManager::OnPause(
565 bool is_media_related_action
) {
566 MediaPlayerAndroid
* player
= GetPlayer(player_id
);
568 player
->Pause(is_media_related_action
);
570 if (is_media_related_action
)
571 MediaSession::Get(web_contents())->RemovePlayer(this, player_id
);
574 void BrowserMediaPlayerManager::OnSetVolume(int player_id
, double volume
) {
575 MediaPlayerAndroid
* player
= GetPlayer(player_id
);
577 player
->SetVolume(volume
);
580 void BrowserMediaPlayerManager::OnSetPoster(int player_id
, const GURL
& url
) {
581 // To be overridden by subclasses.
584 void BrowserMediaPlayerManager::OnReleaseResources(int player_id
) {
585 MediaPlayerAndroid
* player
= GetPlayer(player_id
);
587 ReleasePlayer(player
);
588 if (player_id
== fullscreen_player_id_
)
589 fullscreen_player_is_released_
= true;
592 void BrowserMediaPlayerManager::OnDestroyPlayer(int player_id
) {
593 RemovePlayer(player_id
);
594 if (fullscreen_player_id_
== player_id
)
595 fullscreen_player_id_
= kInvalidMediaPlayerId
;
598 void BrowserMediaPlayerManager::OnRequestRemotePlayback(int /* player_id */) {
599 // Does nothing if we don't have a remote player
602 void BrowserMediaPlayerManager::OnRequestRemotePlaybackControl(
603 int /* player_id */) {
604 // Does nothing if we don't have a remote player
607 void BrowserMediaPlayerManager::AddPlayer(MediaPlayerAndroid
* player
) {
608 DCHECK(!GetPlayer(player
->player_id()));
609 players_
.push_back(player
);
612 void BrowserMediaPlayerManager::RemovePlayer(int player_id
) {
613 for (ScopedVector
<MediaPlayerAndroid
>::iterator it
= players_
.begin();
614 it
!= players_
.end(); ++it
) {
615 if ((*it
)->player_id() == player_id
) {
616 ReleaseMediaResources(player_id
);
617 (*it
)->DeleteOnCorrectThread();
618 players_
.weak_erase(it
);
619 audio_monitor_
->RemovePlayer(render_frame_host_
, player_id
);
620 MediaSession::Get(web_contents())->RemovePlayer(this, player_id
);
626 scoped_ptr
<media::MediaPlayerAndroid
> BrowserMediaPlayerManager::SwapPlayer(
627 int player_id
, media::MediaPlayerAndroid
* player
) {
628 media::MediaPlayerAndroid
* previous_player
= NULL
;
629 for (ScopedVector
<MediaPlayerAndroid
>::iterator it
= players_
.begin();
630 it
!= players_
.end(); ++it
) {
631 if ((*it
)->player_id() == player_id
) {
632 previous_player
= *it
;
633 ReleaseMediaResources(player_id
);
634 players_
.weak_erase(it
);
635 players_
.push_back(player
);
639 return scoped_ptr
<media::MediaPlayerAndroid
>(previous_player
);
642 int BrowserMediaPlayerManager::RoutingID() {
643 return render_frame_host_
->GetRoutingID();
646 bool BrowserMediaPlayerManager::Send(IPC::Message
* msg
) {
647 return render_frame_host_
->Send(msg
);
650 void BrowserMediaPlayerManager::ReleaseFullscreenPlayer(
651 MediaPlayerAndroid
* player
) {
652 ReleasePlayer(player
);
655 void BrowserMediaPlayerManager::OnMediaResourcesRequested(int player_id
) {
656 int num_active_player
= 0;
657 ScopedVector
<MediaPlayerAndroid
>::iterator it
;
658 for (it
= players_
.begin(); it
!= players_
.end(); ++it
) {
659 if (!(*it
)->IsPlayerReady())
662 // The player is already active, ignore it.
663 if ((*it
)->player_id() == player_id
)
669 // Number of active players are less than the threshold, do nothing.
670 if (num_active_player
< kMediaPlayerThreshold
)
673 for (it
= players_
.begin(); it
!= players_
.end(); ++it
) {
674 if ((*it
)->IsPlayerReady() && !(*it
)->IsPlaying() &&
675 fullscreen_player_id_
!= (*it
)->player_id()) {
677 Send(new MediaPlayerMsg_MediaPlayerReleased(RoutingID(),
678 (*it
)->player_id()));
683 void BrowserMediaPlayerManager::ReleaseMediaResources(int player_id
) {
684 #if defined(VIDEO_HOLE)
685 if (external_video_surface_container_
)
686 external_video_surface_container_
->ReleaseExternalVideoSurface(player_id
);
687 #endif // defined(VIDEO_HOLE)
690 void BrowserMediaPlayerManager::ReleasePlayer(MediaPlayerAndroid
* player
) {
692 ReleaseMediaResources(player
->player_id());
695 } // namespace content