[Android] A prototype of the interactive media notification.
[chromium-blink-merge.git] / content / browser / media / android / browser_media_player_manager.cc
blob68df5743396ffa906812fff66be20f52a8493697
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;
43 namespace content {
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;
56 // static
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)
63 g_factory = factory;
66 // static
67 void BrowserMediaPlayerManager::RegisterMediaUrlInterceptor(
68 media::MediaUrlInterceptor* media_url_interceptor) {
69 media_url_interceptor_ = media_url_interceptor;
72 // static
73 void BrowserMediaPlayerManager::SetSurfacePeer(
74 scoped_refptr<gfx::SurfaceTexture> surface_texture,
75 base::ProcessHandle render_process_handle,
76 int render_frame_id,
77 int player_id) {
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();
84 break;
86 it.Advance();
88 if (!render_process_id) {
89 DVLOG(1) << "Cannot find render process for render_process_handle "
90 << render_process_handle;
91 return;
94 RenderFrameHostImpl* frame =
95 RenderFrameHostImpl::FromID(render_process_id, render_frame_id);
96 if (!frame) {
97 DVLOG(1) << "Cannot find frame for render_frame_id " << render_frame_id;
98 return;
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;
107 return;
110 media::MediaPlayerAndroid* player = player_manager->GetPlayer(player_id);
111 if (!player) {
112 DVLOG(1) << "Cannot find media player for player_id " << player_id;
113 return;
116 if (player != player_manager->GetFullscreenPlayer()) {
117 gfx::ScopedJavaSurface scoped_surface(surface_texture.get());
118 player->SetVideoSurface(scoped_surface.Pass());
122 // static
123 BrowserMediaPlayerManager* BrowserMediaPlayerManager::Create(
124 RenderFrameHost* rfh,
125 MediaPlayersObserver* audio_monitor) {
126 if (g_factory)
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,
137 bool hide_url_log,
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,
146 user_agent,
147 hide_url_log,
148 this,
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(
155 web_contents_));
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
160 // the page.
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);
180 } else {
181 return new MediaSourcePlayer(
182 media_player_params.player_id,
183 this,
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);
192 NOTREACHED();
193 return NULL;
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);
229 Send(
230 new MediaPlayerMsg_DidExitFullscreen(RoutingID(), fullscreen_player_id_));
231 video_view_.reset();
232 MediaPlayerAndroid* player = GetFullscreenPlayer();
233 fullscreen_player_id_ = kInvalidMediaPlayerId;
234 if (!player)
235 return;
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);
244 else
245 player->SetVideoSurface(gfx::ScopedJavaSurface());
248 void BrowserMediaPlayerManager::OnTimeUpdate(
249 int player_id,
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();
259 if (!player)
260 return;
262 bool empty_surface = surface.IsEmpty();
263 player->SetVideoSurface(surface.Pass());
264 if (empty_surface)
265 return;
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,
276 bool success) {
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(
306 int player_id,
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;
316 (*it)->Release();
320 void BrowserMediaPlayerManager::OnSeekComplete(
321 int player_id,
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,
335 width, height));
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(
361 context,
362 file_system_context,
363 host->GetID(),
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)
382 return *it;
384 return NULL;
387 bool BrowserMediaPlayerManager::RequestPlay(int player_id) {
388 MediaPlayerAndroid* player = GetPlayer(player_id);
389 DCHECK(player);
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);
397 if (!succeeded)
398 Send(new MediaPlayerMsg_DidMediaPlayerPause(RoutingID(), player_id));
399 return succeeded;
402 #if defined(VIDEO_HOLE)
403 void BrowserMediaPlayerManager::AttachExternalVideoSurface(int player_id,
404 jobject surface) {
405 MediaPlayerAndroid* player = GetPlayer(player_id);
406 if (player) {
407 player->SetVideoSurface(
408 gfx::ScopedJavaSurface::AcquireExternalSurface(surface));
412 void BrowserMediaPlayerManager::DetachExternalVideoSurface(int player_id) {
413 MediaPlayerAndroid* player = GetPlayer(player_id);
414 if (player)
415 player->SetVideoSurface(gfx::ScopedJavaSurface());
418 void BrowserMediaPlayerManager::OnFrameInfoUpdated() {
419 if (fullscreen_player_id_ != kInvalidMediaPlayerId)
420 return;
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);
428 DCHECK(player);
430 player->Pause(true);
431 Send(new MediaPlayerMsg_DidMediaPlayerPause(RoutingID(), player_id));
434 void BrowserMediaPlayerManager::OnResume(int player_id) {
435 MediaPlayerAndroid* player = GetPlayer(player_id);
436 DCHECK(player);
438 player->Start();
439 Send(new MediaPlayerMsg_DidMediaPlayerPlay(RoutingID(), player_id));
442 void BrowserMediaPlayerManager::OnNotifyExternalSurface(
443 int player_id, bool is_request, const gfx::RectF& rect) {
444 if (!web_contents_)
445 return;
447 if (is_request) {
448 OnRequestExternalSurface(player_id, rect);
450 if (external_video_surface_container_) {
451 external_video_surface_container_->OnExternalVideoSurfacePositionChanged(
452 player_id, rect);
456 void BrowserMediaPlayerManager::ReleasePlayerOfExternalVideoSurfaceIfNeeded(
457 int future_player) {
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)
464 return;
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(
483 player_id,
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();
504 return;
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;
513 return;
517 // Force the second video to exit fullscreen.
518 Send(new MediaPlayerMsg_DidExitFullscreen(RoutingID(), player_id));
519 video_view_.reset();
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());
538 if (!player)
539 return;
541 AddPlayer(player);
544 void BrowserMediaPlayerManager::OnStart(int player_id) {
545 MediaPlayerAndroid* player = GetPlayer(player_id);
546 if (!player)
547 return;
548 player->Start();
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(
556 int player_id,
557 const base::TimeDelta& time) {
558 MediaPlayerAndroid* player = GetPlayer(player_id);
559 if (player)
560 player->SeekTo(time);
563 void BrowserMediaPlayerManager::OnPause(
564 int player_id,
565 bool is_media_related_action) {
566 MediaPlayerAndroid* player = GetPlayer(player_id);
567 if (player)
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);
576 if (player)
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);
586 if (player)
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);
621 break;
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);
636 break;
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())
660 continue;
662 // The player is already active, ignore it.
663 if ((*it)->player_id() == player_id)
664 return;
665 else
666 num_active_player++;
669 // Number of active players are less than the threshold, do nothing.
670 if (num_active_player < kMediaPlayerThreshold)
671 return;
673 for (it = players_.begin(); it != players_.end(); ++it) {
674 if ((*it)->IsPlayerReady() && !(*it)->IsPlaying() &&
675 fullscreen_player_id_ != (*it)->player_id()) {
676 ReleasePlayer(*it);
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) {
691 player->Release();
692 ReleaseMediaResources(player->player_id());
695 } // namespace content