Roll src/third_party/WebKit d9c6159:8139f33 (svn 201974:201975)
[chromium-blink-merge.git] / content / browser / media / android / browser_media_player_manager.cc
blobe52732360555fd4e32d36f6de6640f2752fd67b3
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/media/android/browser_demuxer_android.h"
11 #include "content/browser/media/android/media_resource_getter_impl.h"
12 #include "content/browser/media/android/media_session.h"
13 #include "content/browser/media/media_web_contents_observer.h"
14 #include "content/browser/renderer_host/render_view_host_impl.h"
15 #include "content/browser/web_contents/web_contents_view_android.h"
16 #include "content/common/media/media_player_messages_android.h"
17 #include "content/public/browser/android/content_view_core.h"
18 #include "content/public/browser/android/external_video_surface_container.h"
19 #include "content/public/browser/browser_context.h"
20 #include "content/public/browser/browser_thread.h"
21 #include "content/public/browser/content_browser_client.h"
22 #include "content/public/browser/render_frame_host.h"
23 #include "content/public/browser/render_process_host.h"
24 #include "content/public/browser/render_view_host.h"
25 #include "content/public/browser/storage_partition.h"
26 #include "content/public/browser/web_contents.h"
27 #include "content/public/browser/web_contents_delegate.h"
28 #include "content/public/common/content_client.h"
29 #include "content/public/common/content_switches.h"
30 #include "media/base/android/media_codec_player.h"
31 #include "media/base/android/media_player_bridge.h"
32 #include "media/base/android/media_source_player.h"
33 #include "media/base/android/media_url_interceptor.h"
34 #include "media/base/media_switches.h"
36 using media::MediaCodecPlayer;
37 using media::MediaPlayerAndroid;
38 using media::MediaPlayerBridge;
39 using media::MediaPlayerManager;
40 using media::MediaSourcePlayer;
42 namespace content {
44 // Threshold on the number of media players per renderer before we start
45 // attempting to release inactive media players.
46 const int kMediaPlayerThreshold = 1;
47 const int kInvalidMediaPlayerId = -1;
49 // Minimal duration of a media player in order to be considered as Content type.
50 const int kMinimumDurationForContentInSeconds = 5;
52 static BrowserMediaPlayerManager::Factory g_factory = NULL;
53 static media::MediaUrlInterceptor* media_url_interceptor_ = NULL;
55 // static
56 void BrowserMediaPlayerManager::RegisterFactory(Factory factory) {
57 // TODO(aberent) nullptr test is a temporary fix to simplify upstreaming Cast.
58 // Until Cast is fully upstreamed we want the downstream factory to take
59 // priority over the upstream factory. The downstream call happens first,
60 // so this will ensure that it does.
61 if (g_factory == nullptr)
62 g_factory = factory;
65 // static
66 void BrowserMediaPlayerManager::RegisterMediaUrlInterceptor(
67 media::MediaUrlInterceptor* media_url_interceptor) {
68 media_url_interceptor_ = media_url_interceptor;
71 // static
72 void BrowserMediaPlayerManager::SetSurfacePeer(
73 scoped_refptr<gfx::SurfaceTexture> surface_texture,
74 base::ProcessHandle render_process_handle,
75 int render_frame_id,
76 int player_id) {
77 DCHECK_CURRENTLY_ON(BrowserThread::UI);
78 int render_process_id = 0;
79 RenderProcessHost::iterator it = RenderProcessHost::AllHostsIterator();
80 while (!it.IsAtEnd()) {
81 if (it.GetCurrentValue()->GetHandle() == render_process_handle) {
82 render_process_id = it.GetCurrentValue()->GetID();
83 break;
85 it.Advance();
87 if (!render_process_id) {
88 DVLOG(1) << "Cannot find render process for render_process_handle "
89 << render_process_handle;
90 return;
93 RenderFrameHostImpl* frame =
94 RenderFrameHostImpl::FromID(render_process_id, render_frame_id);
95 if (!frame) {
96 DVLOG(1) << "Cannot find frame for render_frame_id " << render_frame_id;
97 return;
100 WebContentsImpl* web_contents =
101 static_cast<WebContentsImpl*>(WebContents::FromRenderFrameHost(frame));
102 BrowserMediaPlayerManager* player_manager =
103 web_contents->media_web_contents_observer()->GetMediaPlayerManager(frame);
104 if (!player_manager) {
105 DVLOG(1) << "Cannot find the media player manager for frame " << frame;
106 return;
109 media::MediaPlayerAndroid* player = player_manager->GetPlayer(player_id);
110 if (!player) {
111 DVLOG(1) << "Cannot find media player for player_id " << player_id;
112 return;
115 if (player != player_manager->GetFullscreenPlayer()) {
116 gfx::ScopedJavaSurface scoped_surface(surface_texture.get());
117 player->SetVideoSurface(scoped_surface.Pass());
121 // static
122 BrowserMediaPlayerManager* BrowserMediaPlayerManager::Create(
123 RenderFrameHost* rfh) {
124 if (g_factory)
125 return g_factory(rfh);
126 return new BrowserMediaPlayerManager(rfh);
129 ContentViewCore* BrowserMediaPlayerManager::GetContentViewCore() const {
130 return ContentViewCoreImpl::FromWebContents(web_contents());
133 MediaPlayerAndroid* BrowserMediaPlayerManager::CreateMediaPlayer(
134 const MediaPlayerHostMsg_Initialize_Params& media_player_params,
135 bool hide_url_log,
136 BrowserDemuxerAndroid* demuxer) {
137 switch (media_player_params.type) {
138 case MEDIA_PLAYER_TYPE_URL: {
139 const std::string user_agent = GetContentClient()->GetUserAgent();
140 MediaPlayerBridge* media_player_bridge = new MediaPlayerBridge(
141 media_player_params.player_id,
142 media_player_params.url,
143 media_player_params.first_party_for_cookies,
144 user_agent,
145 hide_url_log,
146 this,
147 base::Bind(&BrowserMediaPlayerManager::OnMediaResourcesRequested,
148 weak_ptr_factory_.GetWeakPtr()),
149 media_player_params.frame_url,
150 media_player_params.allow_credentials);
151 ContentViewCoreImpl* content_view_core_impl =
152 static_cast<ContentViewCoreImpl*>(ContentViewCore::FromWebContents(
153 web_contents_));
154 if (!content_view_core_impl) {
155 // May reach here due to prerendering. Don't extract the metadata
156 // since it is expensive.
157 // TODO(qinmin): extract the metadata once the user decided to load
158 // the page.
159 OnMediaMetadataChanged(
160 media_player_params.player_id, base::TimeDelta(), 0, 0, false);
161 } else if (!content_view_core_impl->ShouldBlockMediaRequest(
162 media_player_params.url)) {
163 media_player_bridge->Initialize();
165 return media_player_bridge;
168 case MEDIA_PLAYER_TYPE_MEDIA_SOURCE: {
169 if (base::CommandLine::ForCurrentProcess()->
170 HasSwitch(switches::kEnableMediaThreadForMediaPlayback)) {
171 return new MediaCodecPlayer(
172 media_player_params.player_id,
173 weak_ptr_factory_.GetWeakPtr(),
174 base::Bind(&BrowserMediaPlayerManager::OnMediaResourcesRequested,
175 weak_ptr_factory_.GetWeakPtr()),
176 demuxer->CreateDemuxer(media_player_params.demuxer_client_id),
177 media_player_params.frame_url);
178 } else {
179 return new MediaSourcePlayer(
180 media_player_params.player_id,
181 this,
182 base::Bind(&BrowserMediaPlayerManager::OnMediaResourcesRequested,
183 weak_ptr_factory_.GetWeakPtr()),
184 demuxer->CreateDemuxer(media_player_params.demuxer_client_id),
185 media_player_params.frame_url);
190 NOTREACHED();
191 return NULL;
194 BrowserMediaPlayerManager::BrowserMediaPlayerManager(
195 RenderFrameHost* render_frame_host)
196 : render_frame_host_(render_frame_host),
197 fullscreen_player_id_(kInvalidMediaPlayerId),
198 fullscreen_player_is_released_(false),
199 web_contents_(WebContents::FromRenderFrameHost(render_frame_host)),
200 weak_ptr_factory_(this) {
203 BrowserMediaPlayerManager::~BrowserMediaPlayerManager() {
204 // During the tear down process, OnDestroyPlayer() may or may not be called
205 // (e.g. the WebContents may be destroyed before the render process). So
206 // we cannot DCHECK(players_.empty()) here. Instead, all media players in
207 // |players_| will be destroyed here because |player_| is a ScopedVector.
209 for (MediaPlayerAndroid* player : players_)
210 player->DeleteOnCorrectThread();
212 MediaSession::Get(web_contents())->RemovePlayers(this);
213 players_.weak_clear();
216 void BrowserMediaPlayerManager::ExitFullscreen(bool release_media_player) {
217 if (WebContentsDelegate* delegate = web_contents_->GetDelegate())
218 delegate->ExitFullscreenModeForTab(web_contents_);
219 if (RenderWidgetHostViewAndroid* view_android =
220 static_cast<RenderWidgetHostViewAndroid*>(
221 web_contents_->GetRenderWidgetHostView())) {
222 view_android->SetOverlayVideoMode(false);
225 Send(
226 new MediaPlayerMsg_DidExitFullscreen(RoutingID(), fullscreen_player_id_));
227 video_view_.reset();
228 MediaPlayerAndroid* player = GetFullscreenPlayer();
229 fullscreen_player_id_ = kInvalidMediaPlayerId;
230 if (!player)
231 return;
233 #if defined(VIDEO_HOLE)
234 if (external_video_surface_container_)
235 external_video_surface_container_->OnFrameInfoUpdated();
236 #endif // defined(VIDEO_HOLE)
238 if (release_media_player)
239 ReleaseFullscreenPlayer(player);
240 else
241 player->SetVideoSurface(gfx::ScopedJavaSurface());
244 void BrowserMediaPlayerManager::OnTimeUpdate(
245 int player_id,
246 base::TimeDelta current_timestamp,
247 base::TimeTicks current_time_ticks) {
248 Send(new MediaPlayerMsg_MediaTimeUpdate(
249 RoutingID(), player_id, current_timestamp, current_time_ticks));
252 void BrowserMediaPlayerManager::SetVideoSurface(
253 gfx::ScopedJavaSurface surface) {
254 MediaPlayerAndroid* player = GetFullscreenPlayer();
255 if (!player)
256 return;
258 bool empty_surface = surface.IsEmpty();
259 player->SetVideoSurface(surface.Pass());
260 if (empty_surface)
261 return;
263 if (RenderWidgetHostViewAndroid* view_android =
264 static_cast<RenderWidgetHostViewAndroid*>(
265 web_contents_->GetRenderWidgetHostView())) {
266 view_android->SetOverlayVideoMode(true);
270 void BrowserMediaPlayerManager::OnMediaMetadataChanged(
271 int player_id, base::TimeDelta duration, int width, int height,
272 bool success) {
273 Send(new MediaPlayerMsg_MediaMetadataChanged(
274 RoutingID(), player_id, duration, width, height, success));
275 if (fullscreen_player_id_ == player_id)
276 video_view_->UpdateMediaMetadata();
279 void BrowserMediaPlayerManager::OnPlaybackComplete(int player_id) {
280 Send(new MediaPlayerMsg_MediaPlaybackCompleted(RoutingID(), player_id));
281 MediaSession::Get(web_contents())->RemovePlayer(this, player_id);
283 if (fullscreen_player_id_ == player_id)
284 video_view_->OnPlaybackComplete();
287 void BrowserMediaPlayerManager::OnMediaInterrupted(int player_id) {
288 // Tell WebKit that the audio should be paused, then release all resources
289 Send(new MediaPlayerMsg_MediaPlayerReleased(RoutingID(), player_id));
290 OnReleaseResources(player_id);
293 void BrowserMediaPlayerManager::OnBufferingUpdate(
294 int player_id, int percentage) {
295 Send(new MediaPlayerMsg_MediaBufferingUpdate(
296 RoutingID(), player_id, percentage));
297 if (fullscreen_player_id_ == player_id)
298 video_view_->OnBufferingUpdate(percentage);
301 void BrowserMediaPlayerManager::OnSeekRequest(
302 int player_id,
303 const base::TimeDelta& time_to_seek) {
304 Send(new MediaPlayerMsg_SeekRequest(RoutingID(), player_id, time_to_seek));
307 void BrowserMediaPlayerManager::ReleaseAllMediaPlayers() {
308 for (ScopedVector<MediaPlayerAndroid>::iterator it = players_.begin();
309 it != players_.end(); ++it) {
310 if ((*it)->player_id() == fullscreen_player_id_)
311 fullscreen_player_is_released_ = true;
312 (*it)->Release();
316 void BrowserMediaPlayerManager::OnSeekComplete(
317 int player_id,
318 const base::TimeDelta& current_time) {
319 Send(new MediaPlayerMsg_SeekCompleted(RoutingID(), player_id, current_time));
322 void BrowserMediaPlayerManager::OnError(int player_id, int error) {
323 Send(new MediaPlayerMsg_MediaError(RoutingID(), player_id, error));
324 if (fullscreen_player_id_ == player_id)
325 video_view_->OnMediaPlayerError(error);
328 void BrowserMediaPlayerManager::OnVideoSizeChanged(
329 int player_id, int width, int height) {
330 Send(new MediaPlayerMsg_MediaVideoSizeChanged(RoutingID(), player_id,
331 width, height));
332 if (fullscreen_player_id_ == player_id)
333 video_view_->OnVideoSizeChanged(width, height);
336 void BrowserMediaPlayerManager::OnWaitingForDecryptionKey(int player_id) {
337 Send(new MediaPlayerMsg_WaitingForDecryptionKey(RoutingID(), player_id));
340 media::MediaResourceGetter*
341 BrowserMediaPlayerManager::GetMediaResourceGetter() {
342 if (!media_resource_getter_.get()) {
343 RenderProcessHost* host = web_contents()->GetRenderProcessHost();
344 BrowserContext* context = host->GetBrowserContext();
345 StoragePartition* partition = host->GetStoragePartition();
346 storage::FileSystemContext* file_system_context =
347 partition ? partition->GetFileSystemContext() : NULL;
348 // Eventually this needs to be fixed to pass the correct frame rather
349 // than just using the main frame.
350 media_resource_getter_.reset(new MediaResourceGetterImpl(
351 context,
352 file_system_context,
353 host->GetID(),
354 web_contents()->GetMainFrame()->GetRoutingID()));
356 return media_resource_getter_.get();
359 media::MediaUrlInterceptor*
360 BrowserMediaPlayerManager::GetMediaUrlInterceptor() {
361 return media_url_interceptor_;
364 MediaPlayerAndroid* BrowserMediaPlayerManager::GetFullscreenPlayer() {
365 return GetPlayer(fullscreen_player_id_);
368 MediaPlayerAndroid* BrowserMediaPlayerManager::GetPlayer(int player_id) {
369 for (ScopedVector<MediaPlayerAndroid>::iterator it = players_.begin();
370 it != players_.end(); ++it) {
371 if ((*it)->player_id() == player_id)
372 return *it;
374 return NULL;
377 bool BrowserMediaPlayerManager::RequestPlay(int player_id) {
378 MediaPlayerAndroid* player = GetPlayer(player_id);
379 DCHECK(player);
381 int64 duration = player->GetDuration().InSeconds();
382 MediaSession::Type media_session_type =
383 duration == 0 || duration > kMinimumDurationForContentInSeconds
384 ? MediaSession::Type::Content : MediaSession::Type::Transient;
386 bool succeeded = MediaSession::Get(web_contents())->AddPlayer(
387 this, player_id, media_session_type);
388 if (!succeeded)
389 Send(new MediaPlayerMsg_DidMediaPlayerPause(RoutingID(), player_id));
390 return succeeded;
393 void BrowserMediaPlayerManager::OnSuspend(int player_id) {
394 MediaPlayerAndroid* player = GetPlayer(player_id);
395 DCHECK(player);
397 player->Pause(true);
398 Send(new MediaPlayerMsg_DidMediaPlayerPause(RoutingID(), player_id));
401 void BrowserMediaPlayerManager::OnResume(int player_id) {
402 MediaPlayerAndroid* player = GetPlayer(player_id);
403 DCHECK(player);
405 player->Start();
406 Send(new MediaPlayerMsg_DidMediaPlayerPlay(RoutingID(), player_id));
409 #if defined(VIDEO_HOLE)
410 void BrowserMediaPlayerManager::AttachExternalVideoSurface(int player_id,
411 jobject surface) {
412 MediaPlayerAndroid* player = GetPlayer(player_id);
413 if (player) {
414 player->SetVideoSurface(
415 gfx::ScopedJavaSurface::AcquireExternalSurface(surface));
419 void BrowserMediaPlayerManager::DetachExternalVideoSurface(int player_id) {
420 MediaPlayerAndroid* player = GetPlayer(player_id);
421 if (player)
422 player->SetVideoSurface(gfx::ScopedJavaSurface());
425 void BrowserMediaPlayerManager::OnFrameInfoUpdated() {
426 if (fullscreen_player_id_ != kInvalidMediaPlayerId)
427 return;
429 if (external_video_surface_container_)
430 external_video_surface_container_->OnFrameInfoUpdated();
433 void BrowserMediaPlayerManager::OnNotifyExternalSurface(
434 int player_id, bool is_request, const gfx::RectF& rect) {
435 if (!web_contents_)
436 return;
438 if (is_request) {
439 OnRequestExternalSurface(player_id, rect);
441 if (external_video_surface_container_) {
442 external_video_surface_container_->OnExternalVideoSurfacePositionChanged(
443 player_id, rect);
447 void BrowserMediaPlayerManager::ReleasePlayerOfExternalVideoSurfaceIfNeeded(
448 int future_player) {
449 int current_player = ExternalVideoSurfaceContainer::kInvalidPlayerId;
451 if (external_video_surface_container_)
452 current_player = external_video_surface_container_->GetCurrentPlayerId();
454 if (current_player == ExternalVideoSurfaceContainer::kInvalidPlayerId)
455 return;
457 if (current_player != future_player)
458 OnMediaInterrupted(current_player);
461 void BrowserMediaPlayerManager::OnRequestExternalSurface(
462 int player_id, const gfx::RectF& rect) {
463 if (!external_video_surface_container_) {
464 ContentBrowserClient* client = GetContentClient()->browser();
465 external_video_surface_container_.reset(
466 client->OverrideCreateExternalVideoSurfaceContainer(web_contents_));
468 // It's safe to use base::Unretained(this), because the callbacks will not
469 // be called after running ReleaseExternalVideoSurface().
470 if (external_video_surface_container_) {
471 // In case we're stealing the external surface from another player.
472 ReleasePlayerOfExternalVideoSurfaceIfNeeded(player_id);
473 external_video_surface_container_->RequestExternalVideoSurface(
474 player_id,
475 base::Bind(&BrowserMediaPlayerManager::AttachExternalVideoSurface,
476 base::Unretained(this)),
477 base::Bind(&BrowserMediaPlayerManager::DetachExternalVideoSurface,
478 base::Unretained(this)));
481 #endif // defined(VIDEO_HOLE)
483 void BrowserMediaPlayerManager::OnEnterFullscreen(int player_id) {
484 DCHECK_EQ(fullscreen_player_id_, kInvalidMediaPlayerId);
485 #if defined(VIDEO_HOLE)
486 // If this fullscreen player is started when another player
487 // uses the external surface, release that other player.
488 ReleasePlayerOfExternalVideoSurfaceIfNeeded(player_id);
489 if (external_video_surface_container_)
490 external_video_surface_container_->ReleaseExternalVideoSurface(player_id);
491 #endif // defined(VIDEO_HOLE)
492 if (video_view_.get()) {
493 fullscreen_player_id_ = player_id;
494 video_view_->OpenVideo();
495 return;
496 } else if (!ContentVideoView::GetInstance()) {
497 // In Android WebView, two ContentViewCores could both try to enter
498 // fullscreen video, we just ignore the second one.
499 video_view_.reset(new ContentVideoView(this));
500 base::android::ScopedJavaLocalRef<jobject> j_content_video_view =
501 video_view_->GetJavaObject(base::android::AttachCurrentThread());
502 if (!j_content_video_view.is_null()) {
503 fullscreen_player_id_ = player_id;
504 return;
508 // Force the second video to exit fullscreen.
509 Send(new MediaPlayerMsg_DidExitFullscreen(RoutingID(), player_id));
510 video_view_.reset();
513 void BrowserMediaPlayerManager::OnInitialize(
514 const MediaPlayerHostMsg_Initialize_Params& media_player_params) {
515 DCHECK(media_player_params.type != MEDIA_PLAYER_TYPE_MEDIA_SOURCE ||
516 media_player_params.demuxer_client_id > 0)
517 << "Media source players must have positive demuxer client IDs: "
518 << media_player_params.demuxer_client_id;
520 RemovePlayer(media_player_params.player_id);
522 RenderProcessHostImpl* host = static_cast<RenderProcessHostImpl*>(
523 web_contents()->GetRenderProcessHost());
524 MediaPlayerAndroid* player =
525 CreateMediaPlayer(media_player_params,
526 host->GetBrowserContext()->IsOffTheRecord(),
527 host->browser_demuxer_android().get());
529 if (!player)
530 return;
532 AddPlayer(player);
535 void BrowserMediaPlayerManager::OnStart(int player_id) {
536 MediaPlayerAndroid* player = GetPlayer(player_id);
537 if (!player)
538 return;
539 player->Start();
540 if (fullscreen_player_id_ == player_id && fullscreen_player_is_released_) {
541 video_view_->OpenVideo();
542 fullscreen_player_is_released_ = false;
546 void BrowserMediaPlayerManager::OnSeek(
547 int player_id,
548 const base::TimeDelta& time) {
549 MediaPlayerAndroid* player = GetPlayer(player_id);
550 if (player)
551 player->SeekTo(time);
554 void BrowserMediaPlayerManager::OnPause(
555 int player_id,
556 bool is_media_related_action) {
557 MediaPlayerAndroid* player = GetPlayer(player_id);
558 if (player)
559 player->Pause(is_media_related_action);
561 if (is_media_related_action)
562 MediaSession::Get(web_contents())->RemovePlayer(this, player_id);
565 void BrowserMediaPlayerManager::OnSetVolume(int player_id, double volume) {
566 MediaPlayerAndroid* player = GetPlayer(player_id);
567 if (player)
568 player->SetVolume(volume);
571 void BrowserMediaPlayerManager::OnSetPoster(int player_id, const GURL& url) {
572 // To be overridden by subclasses.
575 void BrowserMediaPlayerManager::OnReleaseResources(int player_id) {
576 MediaPlayerAndroid* player = GetPlayer(player_id);
577 if (player) {
578 // Videos can't play in the background, so are removed from the media
579 // session.
580 if (player->GetVideoWidth() > 0)
581 MediaSession::Get(web_contents())->RemovePlayer(this, player_id);
583 ReleasePlayer(player);
585 if (player_id == fullscreen_player_id_)
586 fullscreen_player_is_released_ = true;
589 void BrowserMediaPlayerManager::OnDestroyPlayer(int player_id) {
590 RemovePlayer(player_id);
591 if (fullscreen_player_id_ == player_id)
592 fullscreen_player_id_ = kInvalidMediaPlayerId;
595 void BrowserMediaPlayerManager::OnRequestRemotePlayback(int /* player_id */) {
596 // Does nothing if we don't have a remote player
599 void BrowserMediaPlayerManager::OnRequestRemotePlaybackControl(
600 int /* player_id */) {
601 // Does nothing if we don't have a remote player
604 void BrowserMediaPlayerManager::AddPlayer(MediaPlayerAndroid* player) {
605 DCHECK(!GetPlayer(player->player_id()));
606 players_.push_back(player);
609 void BrowserMediaPlayerManager::RemovePlayer(int player_id) {
610 for (ScopedVector<MediaPlayerAndroid>::iterator it = players_.begin();
611 it != players_.end(); ++it) {
612 if ((*it)->player_id() == player_id) {
613 ReleaseMediaResources(player_id);
614 (*it)->DeleteOnCorrectThread();
615 players_.weak_erase(it);
616 MediaSession::Get(web_contents())->RemovePlayer(this, player_id);
617 break;
622 scoped_ptr<media::MediaPlayerAndroid> BrowserMediaPlayerManager::SwapPlayer(
623 int player_id, media::MediaPlayerAndroid* player) {
624 media::MediaPlayerAndroid* previous_player = NULL;
625 for (ScopedVector<MediaPlayerAndroid>::iterator it = players_.begin();
626 it != players_.end(); ++it) {
627 if ((*it)->player_id() == player_id) {
628 previous_player = *it;
629 ReleaseMediaResources(player_id);
630 players_.weak_erase(it);
631 players_.push_back(player);
632 break;
635 return scoped_ptr<media::MediaPlayerAndroid>(previous_player);
638 int BrowserMediaPlayerManager::RoutingID() {
639 return render_frame_host_->GetRoutingID();
642 bool BrowserMediaPlayerManager::Send(IPC::Message* msg) {
643 return render_frame_host_->Send(msg);
646 void BrowserMediaPlayerManager::ReleaseFullscreenPlayer(
647 MediaPlayerAndroid* player) {
648 ReleasePlayer(player);
651 void BrowserMediaPlayerManager::OnMediaResourcesRequested(int player_id) {
652 int num_active_player = 0;
653 ScopedVector<MediaPlayerAndroid>::iterator it;
654 for (it = players_.begin(); it != players_.end(); ++it) {
655 if (!(*it)->IsPlayerReady())
656 continue;
658 // The player is already active, ignore it.
659 if ((*it)->player_id() == player_id)
660 return;
661 else
662 num_active_player++;
665 // Number of active players are less than the threshold, do nothing.
666 if (num_active_player < kMediaPlayerThreshold)
667 return;
669 for (it = players_.begin(); it != players_.end(); ++it) {
670 if ((*it)->IsPlayerReady() && !(*it)->IsPlaying() &&
671 fullscreen_player_id_ != (*it)->player_id()) {
672 ReleasePlayer(*it);
673 Send(new MediaPlayerMsg_MediaPlayerReleased(RoutingID(),
674 (*it)->player_id()));
679 void BrowserMediaPlayerManager::ReleaseMediaResources(int player_id) {
680 #if defined(VIDEO_HOLE)
681 if (external_video_surface_container_)
682 external_video_surface_container_->ReleaseExternalVideoSurface(player_id);
683 #endif // defined(VIDEO_HOLE)
686 void BrowserMediaPlayerManager::ReleasePlayer(MediaPlayerAndroid* player) {
687 player->Release();
688 ReleaseMediaResources(player->player_id());
691 } // namespace content