OLD | NEW |
(Empty) | |
| 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. |
| 4 |
| 5 #include "chrome/browser/media/android/remote/remote_media_player_manager.h" |
| 6 |
| 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" |
| 12 |
| 13 using media::MediaPlayerAndroid; |
| 14 |
| 15 namespace remote_media { |
| 16 |
| 17 RemoteMediaPlayerManager::RemoteMediaPlayerManager( |
| 18 content::RenderFrameHost* render_frame_host, |
| 19 content::MediaPlayersObserver* audio_monitor) |
| 20 : BrowserMediaPlayerManager(render_frame_host, audio_monitor), |
| 21 weak_ptr_factory_(this) { |
| 22 } |
| 23 |
| 24 RemoteMediaPlayerManager::~RemoteMediaPlayerManager() {} |
| 25 |
| 26 void RemoteMediaPlayerManager::OnStart(int player_id) { |
| 27 // TODO(aberent) This assumes this is the first time we have started this |
| 28 // video, rather than restarting after pause. There is a lot of logic here |
| 29 // that is unnecessary if we are restarting after pause. |
| 30 if (MaybeStartPlayingRemotely(player_id)) |
| 31 return; |
| 32 |
| 33 ReplaceRemotePlayerWithLocal(); |
| 34 BrowserMediaPlayerManager::OnStart(player_id); |
| 35 } |
| 36 |
| 37 void RemoteMediaPlayerManager::OnInitialize( |
| 38 const MediaPlayerHostMsg_Initialize_Params& media_params) { |
| 39 BrowserMediaPlayerManager::OnInitialize(media_params); |
| 40 |
| 41 MediaPlayerAndroid* player = GetPlayer(media_params.player_id); |
| 42 if (player) { |
| 43 CreateRemoteMediaPlayer(player); |
| 44 RemoteMediaPlayerBridge* remote_player = GetRemotePlayer( |
| 45 media_params.player_id); |
| 46 if (remote_player) |
| 47 remote_player->OnPlayerCreated(); |
| 48 } |
| 49 } |
| 50 |
| 51 void RemoteMediaPlayerManager::OnDestroyPlayer(int player_id) { |
| 52 RemoteMediaPlayerBridge* player = GetRemotePlayer(player_id); |
| 53 if (player) |
| 54 player->OnPlayerDestroyed(); |
| 55 BrowserMediaPlayerManager::OnDestroyPlayer(player_id); |
| 56 } |
| 57 |
| 58 void RemoteMediaPlayerManager::OnReleaseResources(int player_id) { |
| 59 // We only want to release resources of local players. |
| 60 if (player_id != RemotePlayerId()) |
| 61 BrowserMediaPlayerManager::OnReleaseResources(player_id); |
| 62 } |
| 63 |
| 64 void RemoteMediaPlayerManager::OnRequestRemotePlayback(int player_id) { |
| 65 RemoteMediaPlayerBridge* player = GetRemotePlayer(player_id); |
| 66 if (player) |
| 67 player->RequestRemotePlayback(); |
| 68 } |
| 69 |
| 70 void RemoteMediaPlayerManager::OnRequestRemotePlaybackControl(int player_id) { |
| 71 RemoteMediaPlayerBridge* player = GetRemotePlayer(player_id); |
| 72 if (player) |
| 73 player->RequestRemotePlaybackControl(); |
| 74 } |
| 75 |
| 76 int RemoteMediaPlayerManager::GetTabId() { |
| 77 if (!web_contents()) |
| 78 return -1; |
| 79 |
| 80 TabAndroid* tab = TabAndroid::FromWebContents(web_contents()); |
| 81 if (!tab) |
| 82 return -1; |
| 83 |
| 84 return tab->GetAndroidId(); |
| 85 } |
| 86 |
| 87 void RemoteMediaPlayerManager::OnSetPoster(int player_id, const GURL& url) { |
| 88 RemoteMediaPlayerBridge* player = GetRemotePlayer(player_id); |
| 89 |
| 90 if (player && url.is_empty()) { |
| 91 player->SetPosterBitmap(std::vector<SkBitmap>()); |
| 92 } else { |
| 93 // TODO(aberent) OnSetPoster is called when the attributes of the video |
| 94 // element are parsed, which may be before OnInitialize is called. We are |
| 95 // here relying on the image fetch taking longer than the delay until |
| 96 // OnInitialize is called, and hence the player is created. This is not |
| 97 // guaranteed. |
| 98 content::WebContents::ImageDownloadCallback callback = base::Bind( |
| 99 &RemoteMediaPlayerManager::DidDownloadPoster, |
| 100 weak_ptr_factory_.GetWeakPtr(), player_id); |
| 101 web_contents()->DownloadImage( |
| 102 url, |
| 103 false, // is_favicon, false so that cookies will be used. |
| 104 0, // max_bitmap_size, 0 means no limit. |
| 105 false, // normal cache policy. |
| 106 callback); |
| 107 } |
| 108 } |
| 109 |
| 110 void RemoteMediaPlayerManager::DidDownloadPoster( |
| 111 int player_id, |
| 112 int id, |
| 113 int http_status_code, |
| 114 const GURL& image_url, |
| 115 const std::vector<SkBitmap>& bitmaps, |
| 116 const std::vector<gfx::Size>& original_bitmap_sizes) { |
| 117 RemoteMediaPlayerBridge* player = GetRemotePlayer(player_id); |
| 118 if (player) |
| 119 player->SetPosterBitmap(bitmaps); |
| 120 } |
| 121 |
| 122 RemoteMediaPlayerBridge* RemoteMediaPlayerManager::CreateRemoteMediaPlayer( |
| 123 MediaPlayerAndroid* local_player) { |
| 124 RemoteMediaPlayerBridge* player = new RemoteMediaPlayerBridge( |
| 125 local_player, |
| 126 GetUserAgent(), |
| 127 false, |
| 128 this); |
| 129 remote_players_.push_back(player); |
| 130 player->Initialize(); |
| 131 return player; |
| 132 } |
| 133 |
| 134 int RemoteMediaPlayerManager::RemotePlayerId() { |
| 135 // The remote player is created with the same id as the corresponding local |
| 136 // player. |
| 137 if (replaced_local_player_.get()) |
| 138 return replaced_local_player_->player_id(); |
| 139 else |
| 140 return -1; |
| 141 } |
| 142 |
| 143 void RemoteMediaPlayerManager::ReplaceLocalPlayerWithRemote( |
| 144 MediaPlayerAndroid* player) { |
| 145 if (!player) |
| 146 return; |
| 147 |
| 148 int player_id = player->player_id(); |
| 149 if (player_id == RemotePlayerId()) { |
| 150 // The player is already remote. |
| 151 return; |
| 152 } |
| 153 |
| 154 // Before we replace the new remote player, put the old local player back |
| 155 // in its place. |
| 156 ReplaceRemotePlayerWithLocal(); |
| 157 |
| 158 // Pause the local player first before replacing it. This will allow the local |
| 159 // player to reset its state, such as the PowerSaveBlocker. |
| 160 // We have to pause locally as well as telling the renderer to pause, because |
| 161 // by the time the renderer comes back to us telling us to pause we will have |
| 162 // switched players. |
| 163 player->Pause(true); |
| 164 Send(new MediaPlayerMsg_DidMediaPlayerPause(RoutingID(), player_id)); |
| 165 |
| 166 // Find the remote player |
| 167 for (auto it = remote_players_.begin(); it != remote_players_.end(); ++it) { |
| 168 if ((*it)->player_id() == player_id) { |
| 169 replaced_local_player_ = SwapPlayer(player_id, *it); |
| 170 |
| 171 // Seek to the previous player's position. |
| 172 (*it)->SeekTo(player->GetCurrentTime()); |
| 173 |
| 174 // SwapPlayers takes ownership, so we have to remove the remote player |
| 175 // from the vector. |
| 176 remote_players_.weak_erase(it); |
| 177 break; |
| 178 } |
| 179 } |
| 180 } |
| 181 |
| 182 void RemoteMediaPlayerManager::ReplaceRemotePlayerWithLocal() { |
| 183 int player_id = RemotePlayerId(); |
| 184 if (player_id == -1) |
| 185 return; |
| 186 |
| 187 Send(new MediaPlayerMsg_DidMediaPlayerPause(RoutingID(), player_id)); |
| 188 Send(new MediaPlayerMsg_DisconnectedFromRemoteDevice(RoutingID(), player_id)); |
| 189 |
| 190 scoped_ptr<MediaPlayerAndroid> remote_player = |
| 191 SwapPlayer(player_id, replaced_local_player_.release()); |
| 192 if (remote_player) { |
| 193 // Seek to the previous player's position. |
| 194 GetPlayer(player_id)->SeekTo(remote_player->GetCurrentTime()); |
| 195 |
| 196 remote_player->Release(); |
| 197 // Add the remote player back into the list |
| 198 remote_players_.push_back( |
| 199 static_cast<RemoteMediaPlayerBridge *>(remote_player.release())); |
| 200 } |
| 201 } |
| 202 |
| 203 bool RemoteMediaPlayerManager::MaybeStartPlayingRemotely(int player_id) { |
| 204 MediaPlayerAndroid* player = GetPlayer(player_id); |
| 205 if (!player) |
| 206 return false; |
| 207 |
| 208 RemoteMediaPlayerBridge* remote_player = GetRemotePlayer(player_id); |
| 209 |
| 210 if (!remote_player) |
| 211 return false; |
| 212 |
| 213 if (remote_player->IsMediaPlayableRemotely() && |
| 214 remote_player->IsRemotePlaybackAvailable() && |
| 215 remote_player->IsRemotePlaybackPreferredForFrame()) { |
| 216 ReplaceLocalPlayerWithRemote(player); |
| 217 |
| 218 remote_player->SetNativePlayer(); |
| 219 remote_player->Start(); |
| 220 |
| 221 Send(new MediaPlayerMsg_DidMediaPlayerPlay(RoutingID(), player_id)); |
| 222 |
| 223 Send(new MediaPlayerMsg_ConnectedToRemoteDevice( |
| 224 RoutingID(), |
| 225 player_id, |
| 226 remote_player->GetCastingMessage())); |
| 227 |
| 228 return true; |
| 229 } |
| 230 |
| 231 return false; |
| 232 } |
| 233 |
| 234 void RemoteMediaPlayerManager::OnRemoteDeviceSelected(int player_id) { |
| 235 |
| 236 MediaPlayerAndroid* player = GetPlayer(player_id); |
| 237 if (!player) |
| 238 return; |
| 239 |
| 240 if (MaybeStartPlayingRemotely(player_id)) |
| 241 return; |
| 242 OnStart(player_id); |
| 243 } |
| 244 |
| 245 void RemoteMediaPlayerManager::OnRemoteDeviceUnselected(int player_id) { |
| 246 if (player_id == RemotePlayerId()) |
| 247 ReplaceRemotePlayerWithLocal(); |
| 248 } |
| 249 |
| 250 void RemoteMediaPlayerManager::OnRemotePlaybackFinished(int player_id) { |
| 251 if (player_id == RemotePlayerId()) |
| 252 ReplaceRemotePlayerWithLocal(); |
| 253 } |
| 254 |
| 255 void RemoteMediaPlayerManager::OnRouteAvailabilityChanged( |
| 256 int player_id, bool routes_available) { |
| 257 Send( |
| 258 new MediaPlayerMsg_RemoteRouteAvailabilityChanged(RoutingID(), player_id, |
| 259 routes_available)); |
| 260 } |
| 261 |
| 262 void RemoteMediaPlayerManager::ReleaseFullscreenPlayer( |
| 263 MediaPlayerAndroid* player) { |
| 264 // Release the original player's resources, not the current fullscreen player |
| 265 // (which is the remote player). |
| 266 if (replaced_local_player_.get()) |
| 267 replaced_local_player_->Release(); |
| 268 else |
| 269 BrowserMediaPlayerManager::ReleaseFullscreenPlayer(player); |
| 270 } |
| 271 |
| 272 void RemoteMediaPlayerManager::OnPlaying(int player_id) { |
| 273 Send(new MediaPlayerMsg_DidMediaPlayerPlay(RoutingID(),player_id)); |
| 274 } |
| 275 |
| 276 void RemoteMediaPlayerManager::OnPaused(int player_id) { |
| 277 Send(new MediaPlayerMsg_DidMediaPlayerPause(RoutingID(),player_id)); |
| 278 } |
| 279 |
| 280 RemoteMediaPlayerBridge* RemoteMediaPlayerManager::GetRemotePlayer( |
| 281 int player_id) { |
| 282 if (player_id == RemotePlayerId()) { |
| 283 return static_cast<RemoteMediaPlayerBridge*>(GetPlayer(player_id)); |
| 284 } else { |
| 285 for (RemoteMediaPlayerBridge* player : remote_players_) { |
| 286 if (player->player_id() == player_id) { |
| 287 return player; |
| 288 } |
| 289 } |
| 290 return nullptr; |
| 291 } |
| 292 } |
| 293 |
| 294 void RemoteMediaPlayerManager::OnMediaMetadataChanged(int player_id, |
| 295 base::TimeDelta duration, |
| 296 int width, |
| 297 int height, |
| 298 bool success) { |
| 299 if (player_id == RemotePlayerId() && replaced_local_player_) { |
| 300 Send(new MediaPlayerMsg_MediaMetadataChanged( |
| 301 RoutingID(), player_id, duration, |
| 302 replaced_local_player_->GetVideoWidth(), |
| 303 replaced_local_player_->GetVideoHeight(), success)); |
| 304 } else { |
| 305 BrowserMediaPlayerManager::OnMediaMetadataChanged(player_id, duration, |
| 306 width, height, success); |
| 307 } |
| 308 } |
| 309 |
| 310 } // namespace remote_media |
OLD | NEW |