Add ICU message format support
[chromium-blink-merge.git] / content / browser / media / android / browser_media_player_manager.cc
blobaecd2bb607250083847bedefc8a3c134270ce7eb
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 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);
398 if (!succeeded)
399 Send(new MediaPlayerMsg_DidMediaPlayerPause(RoutingID(), player_id));
400 return succeeded;
403 void BrowserMediaPlayerManager::OnSuspend(int player_id) {
404 MediaPlayerAndroid* player = GetPlayer(player_id);
405 DCHECK(player);
407 player->Pause(true);
408 Send(new MediaPlayerMsg_DidMediaPlayerPause(RoutingID(), player_id));
411 void BrowserMediaPlayerManager::OnResume(int player_id) {
412 MediaPlayerAndroid* player = GetPlayer(player_id);
413 DCHECK(player);
415 player->Start();
416 Send(new MediaPlayerMsg_DidMediaPlayerPlay(RoutingID(), player_id));
419 #if defined(VIDEO_HOLE)
420 void BrowserMediaPlayerManager::AttachExternalVideoSurface(int player_id,
421 jobject surface) {
422 MediaPlayerAndroid* player = GetPlayer(player_id);
423 if (player) {
424 player->SetVideoSurface(
425 gfx::ScopedJavaSurface::AcquireExternalSurface(surface));
429 void BrowserMediaPlayerManager::DetachExternalVideoSurface(int player_id) {
430 MediaPlayerAndroid* player = GetPlayer(player_id);
431 if (player)
432 player->SetVideoSurface(gfx::ScopedJavaSurface());
435 void BrowserMediaPlayerManager::OnFrameInfoUpdated() {
436 if (fullscreen_player_id_ != kInvalidMediaPlayerId)
437 return;
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) {
445 if (!web_contents_)
446 return;
448 if (is_request) {
449 OnRequestExternalSurface(player_id, rect);
451 if (external_video_surface_container_) {
452 external_video_surface_container_->OnExternalVideoSurfacePositionChanged(
453 player_id, rect);
457 void BrowserMediaPlayerManager::ReleasePlayerOfExternalVideoSurfaceIfNeeded(
458 int future_player) {
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)
465 return;
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(
484 player_id,
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();
505 return;
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;
514 return;
518 // Force the second video to exit fullscreen.
519 Send(new MediaPlayerMsg_DidExitFullscreen(RoutingID(), player_id));
520 video_view_.reset();
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());
539 if (!player)
540 return;
542 AddPlayer(player);
545 void BrowserMediaPlayerManager::OnStart(int player_id) {
546 MediaPlayerAndroid* player = GetPlayer(player_id);
547 if (!player)
548 return;
549 player->Start();
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(
557 int player_id,
558 const base::TimeDelta& time) {
559 MediaPlayerAndroid* player = GetPlayer(player_id);
560 if (player)
561 player->SeekTo(time);
564 void BrowserMediaPlayerManager::OnPause(
565 int player_id,
566 bool is_media_related_action) {
567 MediaPlayerAndroid* player = GetPlayer(player_id);
568 if (player)
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);
577 if (player)
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);
587 if (player) {
588 // Videos can't play in the background, so are removed from the media
589 // session.
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);
628 break;
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);
643 break;
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())
667 continue;
669 // The player is already active, ignore it.
670 if ((*it)->player_id() == player_id)
671 return;
672 else
673 num_active_player++;
676 // Number of active players are less than the threshold, do nothing.
677 if (num_active_player < kMediaPlayerThreshold)
678 return;
680 for (it = players_.begin(); it != players_.end(); ++it) {
681 if ((*it)->IsPlayerReady() && !(*it)->IsPlaying() &&
682 fullscreen_player_id_ != (*it)->player_id()) {
683 ReleasePlayer(*it);
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) {
698 player->Release();
699 ReleaseMediaResources(player->player_id());
702 } // namespace content