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 "chrome/browser/media/android/remote/remote_media_player_manager.h"
7 #include "chrome/browser/android/tab_android.h"
8 #include "chrome/common/chrome_content_client.h"
9 #include "content/common/media/media_player_messages_android.h"
10 #include "third_party/skia/include/core/SkBitmap.h"
11 #include "ui/gfx/android/java_bitmap.h"
13 using media::MediaPlayerAndroid
;
15 namespace remote_media
{
17 RemoteMediaPlayerManager::RemoteMediaPlayerManager(
18 content::RenderFrameHost
* render_frame_host
)
19 : BrowserMediaPlayerManager(render_frame_host
),
20 weak_ptr_factory_(this) {
23 RemoteMediaPlayerManager::~RemoteMediaPlayerManager() {}
25 void RemoteMediaPlayerManager::OnStart(int player_id
) {
26 // TODO(aberent) This assumes this is the first time we have started this
27 // video, rather than restarting after pause. There is a lot of logic here
28 // that is unnecessary if we are restarting after pause.
29 if (MaybeStartPlayingRemotely(player_id
))
32 ReplaceRemotePlayerWithLocal();
33 BrowserMediaPlayerManager::OnStart(player_id
);
36 void RemoteMediaPlayerManager::OnInitialize(
37 const MediaPlayerHostMsg_Initialize_Params
& media_params
) {
38 BrowserMediaPlayerManager::OnInitialize(media_params
);
40 MediaPlayerAndroid
* player
= GetPlayer(media_params
.player_id
);
42 CreateRemoteMediaPlayer(player
);
43 RemoteMediaPlayerBridge
* remote_player
= GetRemotePlayer(
44 media_params
.player_id
);
46 remote_player
->OnPlayerCreated();
50 void RemoteMediaPlayerManager::OnDestroyPlayer(int player_id
) {
51 RemoteMediaPlayerBridge
* player
= GetRemotePlayer(player_id
);
53 player
->OnPlayerDestroyed();
54 BrowserMediaPlayerManager::OnDestroyPlayer(player_id
);
57 void RemoteMediaPlayerManager::OnReleaseResources(int player_id
) {
58 // We only want to release resources of local players.
59 if (player_id
!= RemotePlayerId())
60 BrowserMediaPlayerManager::OnReleaseResources(player_id
);
63 void RemoteMediaPlayerManager::OnRequestRemotePlayback(int player_id
) {
64 RemoteMediaPlayerBridge
* player
= GetRemotePlayer(player_id
);
66 player
->RequestRemotePlayback();
69 void RemoteMediaPlayerManager::OnRequestRemotePlaybackControl(int player_id
) {
70 RemoteMediaPlayerBridge
* player
= GetRemotePlayer(player_id
);
72 player
->RequestRemotePlaybackControl();
75 int RemoteMediaPlayerManager::GetTabId() {
79 TabAndroid
* tab
= TabAndroid::FromWebContents(web_contents());
83 return tab
->GetAndroidId();
86 void RemoteMediaPlayerManager::OnSetPoster(int player_id
, const GURL
& url
) {
87 RemoteMediaPlayerBridge
* player
= GetRemotePlayer(player_id
);
89 if (player
&& url
.is_empty()) {
90 player
->SetPosterBitmap(std::vector
<SkBitmap
>());
92 // TODO(aberent) OnSetPoster is called when the attributes of the video
93 // element are parsed, which may be before OnInitialize is called. We are
94 // here relying on the image fetch taking longer than the delay until
95 // OnInitialize is called, and hence the player is created. This is not
97 content::WebContents::ImageDownloadCallback callback
= base::Bind(
98 &RemoteMediaPlayerManager::DidDownloadPoster
,
99 weak_ptr_factory_
.GetWeakPtr(), player_id
);
100 web_contents()->DownloadImage(
102 false, // is_favicon, false so that cookies will be used.
103 0, // max_bitmap_size, 0 means no limit.
104 false, // normal cache policy.
109 void RemoteMediaPlayerManager::DidDownloadPoster(
112 int http_status_code
,
113 const GURL
& image_url
,
114 const std::vector
<SkBitmap
>& bitmaps
,
115 const std::vector
<gfx::Size
>& original_bitmap_sizes
) {
116 RemoteMediaPlayerBridge
* player
= GetRemotePlayer(player_id
);
118 player
->SetPosterBitmap(bitmaps
);
121 RemoteMediaPlayerBridge
* RemoteMediaPlayerManager::CreateRemoteMediaPlayer(
122 MediaPlayerAndroid
* local_player
) {
123 RemoteMediaPlayerBridge
* player
= new RemoteMediaPlayerBridge(
128 remote_players_
.push_back(player
);
129 player
->Initialize();
133 int RemoteMediaPlayerManager::RemotePlayerId() {
134 // The remote player is created with the same id as the corresponding local
136 if (replaced_local_player_
.get())
137 return replaced_local_player_
->player_id();
142 void RemoteMediaPlayerManager::ReplaceLocalPlayerWithRemote(
143 MediaPlayerAndroid
* player
) {
147 int player_id
= player
->player_id();
148 if (player_id
== RemotePlayerId()) {
149 // The player is already remote.
153 // Before we replace the new remote player, put the old local player back
155 ReplaceRemotePlayerWithLocal();
157 // Pause the local player first before replacing it. This will allow the local
158 // player to reset its state, such as the PowerSaveBlocker.
159 // We have to pause locally as well as telling the renderer to pause, because
160 // by the time the renderer comes back to us telling us to pause we will have
163 Send(new MediaPlayerMsg_DidMediaPlayerPause(RoutingID(), player_id
));
165 // Find the remote player
166 for (auto it
= remote_players_
.begin(); it
!= remote_players_
.end(); ++it
) {
167 if ((*it
)->player_id() == player_id
) {
168 replaced_local_player_
= SwapPlayer(player_id
, *it
);
170 // Seek to the previous player's position.
171 (*it
)->SeekTo(player
->GetCurrentTime());
173 // SwapPlayers takes ownership, so we have to remove the remote player
175 remote_players_
.weak_erase(it
);
181 void RemoteMediaPlayerManager::ReplaceRemotePlayerWithLocal() {
182 int player_id
= RemotePlayerId();
186 Send(new MediaPlayerMsg_DidMediaPlayerPause(RoutingID(), player_id
));
187 Send(new MediaPlayerMsg_DisconnectedFromRemoteDevice(RoutingID(), player_id
));
189 scoped_ptr
<MediaPlayerAndroid
> remote_player
=
190 SwapPlayer(player_id
, replaced_local_player_
.release());
192 // Seek to the previous player's position.
193 GetPlayer(player_id
)->SeekTo(remote_player
->GetCurrentTime());
195 remote_player
->Release();
196 // Add the remote player back into the list
197 remote_players_
.push_back(
198 static_cast<RemoteMediaPlayerBridge
*>(remote_player
.release()));
202 bool RemoteMediaPlayerManager::MaybeStartPlayingRemotely(int player_id
) {
203 MediaPlayerAndroid
* player
= GetPlayer(player_id
);
207 RemoteMediaPlayerBridge
* remote_player
= GetRemotePlayer(player_id
);
212 if (remote_player
->IsMediaPlayableRemotely() &&
213 remote_player
->IsRemotePlaybackAvailable() &&
214 remote_player
->IsRemotePlaybackPreferredForFrame()) {
215 ReplaceLocalPlayerWithRemote(player
);
217 remote_player
->SetNativePlayer();
218 remote_player
->Start();
220 Send(new MediaPlayerMsg_DidMediaPlayerPlay(RoutingID(), player_id
));
222 Send(new MediaPlayerMsg_ConnectedToRemoteDevice(
225 remote_player
->GetCastingMessage()));
233 void RemoteMediaPlayerManager::OnRemoteDeviceSelected(int player_id
) {
235 MediaPlayerAndroid
* player
= GetPlayer(player_id
);
239 if (MaybeStartPlayingRemotely(player_id
))
244 void RemoteMediaPlayerManager::OnRemoteDeviceUnselected(int player_id
) {
245 if (player_id
== RemotePlayerId())
246 ReplaceRemotePlayerWithLocal();
249 void RemoteMediaPlayerManager::OnRemotePlaybackFinished(int player_id
) {
250 if (player_id
== RemotePlayerId())
251 ReplaceRemotePlayerWithLocal();
254 void RemoteMediaPlayerManager::OnRouteAvailabilityChanged(
255 int player_id
, bool routes_available
) {
257 new MediaPlayerMsg_RemoteRouteAvailabilityChanged(RoutingID(), player_id
,
261 void RemoteMediaPlayerManager::ReleaseFullscreenPlayer(
262 MediaPlayerAndroid
* player
) {
263 // Release the original player's resources, not the current fullscreen player
264 // (which is the remote player).
265 if (replaced_local_player_
.get())
266 replaced_local_player_
->Release();
268 BrowserMediaPlayerManager::ReleaseFullscreenPlayer(player
);
271 void RemoteMediaPlayerManager::OnPlaying(int player_id
) {
272 Send(new MediaPlayerMsg_DidMediaPlayerPlay(RoutingID(),player_id
));
275 void RemoteMediaPlayerManager::OnPaused(int player_id
) {
276 Send(new MediaPlayerMsg_DidMediaPlayerPause(RoutingID(),player_id
));
279 RemoteMediaPlayerBridge
* RemoteMediaPlayerManager::GetRemotePlayer(
281 if (player_id
== RemotePlayerId()) {
282 return static_cast<RemoteMediaPlayerBridge
*>(GetPlayer(player_id
));
284 for (RemoteMediaPlayerBridge
* player
: remote_players_
) {
285 if (player
->player_id() == player_id
) {
293 void RemoteMediaPlayerManager::OnMediaMetadataChanged(int player_id
,
294 base::TimeDelta duration
,
298 if (player_id
== RemotePlayerId() && replaced_local_player_
) {
299 Send(new MediaPlayerMsg_MediaMetadataChanged(
300 RoutingID(), player_id
, duration
,
301 replaced_local_player_
->GetVideoWidth(),
302 replaced_local_player_
->GetVideoHeight(), success
));
304 BrowserMediaPlayerManager::OnMediaMetadataChanged(player_id
, duration
,
305 width
, height
, success
);
309 } // namespace remote_media